diff options
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c | 116 |
3 files changed, 122 insertions, 3 deletions
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 bb9fd97786da..ae2837a5eb5d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3374,9 +3374,9 @@ STATIC_IFN_KUNIT int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_commit * } EXPORT_IF_KUNIT(dm_update_mst_vcpi_slots_for_dsc); -static void manage_dm_interrupts(struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - struct dm_crtc_state *acrtc_state) +STATIC_IFN_KUNIT void manage_dm_interrupts(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + struct dm_crtc_state *acrtc_state) { /* * We cannot be sure that the frontend index maps to the same * backend index - some even map to more than one. @@ -3455,6 +3455,7 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, drm_crtc_vblank_off(&acrtc->base); } } +EXPORT_IF_KUNIT(manage_dm_interrupts); STATIC_IFN_KUNIT void dm_update_pflip_irq_state(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) 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 089741ba0619..ad72dc182e93 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -1264,6 +1264,8 @@ int fill_dc_plane_info_and_addr(struct amdgpu_device *adev, struct dc_plane_address *address, bool tmz_surface); int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_commit *state, struct dc_state *dc_state, struct dsc_mst_fairness_vars *vars); +void manage_dm_interrupts(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, + struct dm_crtc_state *acrtc_state); int load_dmcu_fw(struct amdgpu_device *adev); int dm_sw_init(struct amdgpu_ip_block *ip_block); int dm_late_init(struct amdgpu_ip_block *ip_block); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c index a67774e6db36..4daa187fbd0a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c @@ -3803,6 +3803,117 @@ static void dm_test_plane_info_layer_and_blending(struct kunit *test) KUNIT_EXPECT_EQ(test, ctx->plane_info.global_alpha_value, 0x7f); } +/* Tests for manage_dm_interrupts() */ + +struct dm_test_irq_mgmt_ctx { + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc; + struct dm_crtc_state *acrtc_state; +}; + +/* + * A CRTC with a single initialised vblank and a 1080p60 stream timing, which + * is what the vblank off-delay estimate is derived from. + */ +static struct dm_test_irq_mgmt_ctx *dm_test_irq_mgmt_ctx_alloc(struct kunit *test) +{ + struct dm_test_irq_mgmt_ctx *ctx; + struct dc_crtc_timing *timing; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx); + + ctx->adev = dm_kunit_alloc_adev(test); + KUNIT_ASSERT_EQ(test, drm_vblank_init(&ctx->adev->ddev, 1), 0); + + ctx->acrtc = kunit_kzalloc(test, sizeof(*ctx->acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->acrtc); + ctx->acrtc_state = kunit_kzalloc(test, sizeof(*ctx->acrtc_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->acrtc_state); + + ctx->adev->mode_info.num_crtc = 1; + ctx->acrtc->base.dev = &ctx->adev->ddev; + ctx->acrtc->crtc_id = 0; + + ctx->acrtc_state->stream = dm_kunit_alloc_stream(test, NULL); + timing = &ctx->acrtc_state->stream->timing; + timing->h_total = 2200; + timing->v_total = 1125; + timing->pix_clk_100hz = 1485000; + + return ctx; +} + +/** + * dm_test_manage_interrupts_offdelay - Test the off delay is derived from timing + * @test: The KUnit test context + * + * DCN3.0 also takes the extra vupdate reference. The IRQ subsystem is not + * installed, so amdgpu_irq_get() only reports the missing source. + */ +static void dm_test_manage_interrupts_offdelay(struct kunit *test) +{ + struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test); + + /* Pre-DCN3.5 keeps the two frame off delay. */ + ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 0, 0); + + manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state); + + KUNIT_EXPECT_EQ(test, ctx->adev->ddev.vblank[0].config.offdelay_ms, 34); + KUNIT_EXPECT_FALSE(test, ctx->adev->ddev.vblank[0].config.disable_immediate); +} + +/** + * dm_test_manage_interrupts_offdelay_fallback - Test a zero delay falls back to 30ms + * @test: The KUnit test context + */ +static void dm_test_manage_interrupts_offdelay_fallback(struct kunit *test) +{ + struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test); + + ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 1, 2); + /* A zero line count makes the computed delay round down to zero. */ + ctx->acrtc_state->stream->timing.v_total = 0; + + manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state); + + KUNIT_EXPECT_EQ(test, ctx->adev->ddev.vblank[0].config.offdelay_ms, 30); +} + +/** + * dm_test_manage_interrupts_apu_instant_off - Test DCN3.5 APUs use instant off + * @test: The KUnit test context + */ +static void dm_test_manage_interrupts_apu_instant_off(struct kunit *test) +{ + struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test); + + ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 5, 0); + ctx->adev->flags |= AMD_IS_APU; + + manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state); + + KUNIT_EXPECT_EQ(test, ctx->adev->ddev.vblank[0].config.offdelay_ms, 1); + KUNIT_EXPECT_TRUE(test, ctx->adev->ddev.vblank[0].config.disable_immediate); +} + +/** + * dm_test_manage_interrupts_disable - Test a NULL CRTC state turns vblank off + * @test: The KUnit test context + */ +static void dm_test_manage_interrupts_disable(struct kunit *test) +{ + struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test); + + ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 0, 0); + manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state); + + manage_dm_interrupts(ctx->adev, ctx->acrtc, NULL); + + KUNIT_EXPECT_FALSE(test, ctx->adev->ddev.vblank[0].enabled); +} + /* Tests for dm_early_init() */ #define DM_TEST_ATOM_BIOS_SIZE 512 @@ -4725,6 +4836,11 @@ static struct kunit_case amdgpu_dm_tests[] = { KUNIT_CASE(dm_test_plane_info_bad_color_encoding), KUNIT_CASE(dm_test_plane_info_rotations), KUNIT_CASE(dm_test_plane_info_layer_and_blending), + /* manage_dm_interrupts */ + KUNIT_CASE(dm_test_manage_interrupts_offdelay), + KUNIT_CASE(dm_test_manage_interrupts_offdelay_fallback), + KUNIT_CASE(dm_test_manage_interrupts_apu_instant_off), + KUNIT_CASE(dm_test_manage_interrupts_disable), /* dm_early_init */ KUNIT_CASE(dm_test_early_init_no_object_header), KUNIT_CASE(dm_test_early_init_legacy_asics), |
