The DMA (fast-load) 3D LUT and the legacy inline 3D LUT map to the same MCM 3D LUT HW block, so rather than adding a second 3D LUT op to the existing pipeline, advertise a second color pipeline that is identical to the default one except the inline DRM_COLOROP_3D_LUT is replaced by a DRM_COLOROP_3D_LUT_DMA.
amdgpu_dm_build_default_pipeline() gains a dma_3d_lut argument that selects the 3D LUT variant; amdgpu_dm_initialize_dma_3dlut_pipeline() builds the DMA variant, and dm_plane_init_colorops() advertises it as a second pipeline when mcm_3d_lut_caps.dma_3d_lut is set. The advertised format is a 17^3 XBGR16161616 LINEAR cube with the DCN-derived 256-byte pitch. Keep it behind an experimental KConfig for now. Signed-off-by: Harry Wentland <[email protected]> --- drivers/gpu/drm/amd/display/Kconfig | 13 ++++++ .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 43 ++++++++++++++++--- .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h | 4 +- .../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 17 ++++++++ .../amdgpu_dm/tests/amdgpu_dm_colorop_test.c | 4 +- 5 files changed, 71 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index a319680c329b..e62efe422aeb 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -65,6 +65,19 @@ config DRM_AMD_SECURE_DISPLAY This option enables the calculation of crc of specific region via debugfs. Cooperate with specific DMCU FW. +config DRM_AMD_DC_3DLUT_DMA + bool "Expose the DMA 3D LUT color pipeline (EXPERIMENTAL)" + depends on DRM_AMD_DC + default n + help + Advertise a color pipeline with a DRM_COLOROP_3D_LUT_DMA colorop + when the display hardware supports fast-loading the 3D LUT from a + framebuffer. + + This is experimental. + + If unsure, say N. + config DRM_AMD_DC_KUNIT_TEST tristate "KUnit tests for the AMD DC display driver" if !KUNIT_ALL_TESTS depends on DRM_AMD_DC && KUNIT && DEBUG_FS diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c index 47d90b67120e..9d7720a9bd2e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c @@ -28,6 +28,7 @@ #include <drm/drm_plane.h> #include <drm/drm_property.h> #include <drm/drm_colorop.h> +#include <drm/drm_fourcc.h> #include "amdgpu.h" #include "amdgpu_dm_colorop.h" @@ -67,6 +68,17 @@ const u64 amdgpu_dm_supported_fm = #define LUT3D_SIZE 17 +static const struct drm_mode_3dlut_mode amdgpu_dm_3dlut_dma_modes[] = { + { + .lut_size = LUT3D_SIZE, + .format = DRM_FORMAT_XBGR16161616, + .modifier = DRM_FORMAT_MOD_LINEAR, + .pitch = 256, + .traversal_order = DRM_COLOROP_LUT3D_TRAVERSAL_RGB, + .interpolation = DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, + }, +}; + static const struct drm_colorop_funcs dm_colorop_funcs = { .destroy = drm_colorop_destroy, }; @@ -115,7 +127,8 @@ EXPORT_IF_KUNIT(amdgpu_dm_colorop_kunit_set_ops); STATIC_IFN_KUNIT int amdgpu_dm_build_default_pipeline(struct drm_device *dev, struct drm_plane *plane, - bool hw_3d_lut, struct drm_prop_enum_list *list) + bool hw_3d_lut, bool dma_3d_lut, + struct drm_prop_enum_list *list) { struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS]; int ret; @@ -225,17 +238,23 @@ amdgpu_dm_build_default_pipeline(struct drm_device *dev, struct drm_plane *plane i++; - /* 3D LUT */ + /* 3D LUT - host loading, or DMA (fast-loading) */ ops[i] = colorop_kzalloc_obj(); if (!ops[i]) { ret = -ENOMEM; goto cleanup; } - ret = colorop_3dlut_init(dev, ops[i], plane, &dm_colorop_funcs, - LUT3D_SIZE, - DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, - DRM_COLOROP_FLAG_ALLOW_BYPASS); + if (dma_3d_lut) + ret = drm_plane_colorop_3dlut_dma_init(dev, ops[i], plane, + &dm_colorop_funcs, amdgpu_dm_3dlut_dma_modes, + ARRAY_SIZE(amdgpu_dm_3dlut_dma_modes), + DRM_COLOROP_FLAG_ALLOW_BYPASS); + else + ret = colorop_3dlut_init(dev, ops[i], plane, + &dm_colorop_funcs, LUT3D_SIZE, + DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, + DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) goto cleanup; @@ -298,6 +317,16 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr bool hw_3d_lut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend; - return amdgpu_dm_build_default_pipeline(dev, plane, hw_3d_lut, list); + return amdgpu_dm_build_default_pipeline(dev, plane, hw_3d_lut, false, list); } EXPORT_IF_KUNIT(amdgpu_dm_initialize_default_pipeline); + +int amdgpu_dm_initialize_dma_3dlut_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list) +{ + struct drm_device *dev = plane->dev; + struct amdgpu_device *adev = drm_to_adev(dev); + bool hw_3d_lut = adev->dm.dc->caps.color.dpp.hw_3d_lut || + adev->dm.dc->caps.color.mpc.preblend; + + return amdgpu_dm_build_default_pipeline(dev, plane, hw_3d_lut, true, list); +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h index edf7df7c19e9..510c367f8ca5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h @@ -33,6 +33,7 @@ extern const u64 amdgpu_dm_supported_blnd_tfs; extern const u64 amdgpu_dm_supported_fm; int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list); +int amdgpu_dm_initialize_dma_3dlut_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list); #if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST) #include <drm/drm_colorop.h> @@ -63,7 +64,8 @@ struct amdgpu_dm_colorop_kunit_ops { }; int amdgpu_dm_build_default_pipeline(struct drm_device *dev, struct drm_plane *plane, - bool hw_3d_lut, struct drm_prop_enum_list *list); + bool hw_3d_lut, bool dma_3d_lut, + struct drm_prop_enum_list *list); void amdgpu_dm_colorop_kunit_set_ops(const struct amdgpu_dm_colorop_kunit_ops *ops); #endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 91398230d408..21fe005fe583 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -2172,6 +2172,23 @@ dm_plane_init_colorops(struct drm_plane *plane) /* initialize pipeline */ if (dc->ctx->dce_version >= DCN_VERSION_3_0) { + /* + * Advertise the DMA (fast-load) 3D LUT pipeline first + * so that userspace which understands it prefers it + * over the host-loading 3D LUT pipeline. + */ + if (IS_ENABLED(CONFIG_DRM_AMD_DC_3DLUT_DMA) && + dc->caps.color.mpc.mcm_3d_lut_caps.dma_3d_lut && + (dc->caps.color.dpp.hw_3d_lut || dc->caps.color.mpc.preblend)) { + ret = amdgpu_dm_initialize_dma_3dlut_pipeline(plane, &pipelines[len]); + if (ret) { + drm_err(plane->dev, "Failed to create DMA 3D LUT pipeline for plane %d: %d\n", + plane->base.id, ret); + goto out; + } + len++; + } + ret = amdgpu_dm_initialize_default_pipeline(plane, &pipelines[len]); if (ret) { drm_err(plane->dev, "Failed to create color pipeline for plane %d: %pe\n", diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_colorop_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_colorop_test.c index 90cc5592ef5d..49d1d252a67d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_colorop_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_colorop_test.c @@ -208,7 +208,7 @@ static void dm_test_initialize_default_pipeline(struct kunit *test) plane = dm_colorop_alloc_plane(test, &drm); - ret = amdgpu_dm_build_default_pipeline(drm, plane, true, &list); + ret = amdgpu_dm_build_default_pipeline(drm, plane, true, false, &list); KUNIT_ASSERT_EQ(test, ret, 0); kfree(list.name); @@ -430,7 +430,7 @@ static int dm_colorop_build_with_fault(struct kunit *test, struct drm_device **d amdgpu_dm_colorop_kunit_set_ops(&dm_colorop_test_ops); KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_colorop_test_reset_ops, NULL), 0); - ret = amdgpu_dm_build_default_pipeline(*drm, plane, true, &list); + ret = amdgpu_dm_build_default_pipeline(*drm, plane, true, false, &list); kfree(list.name); return ret; -- 2.56.0
