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

Reply via email to