Translate an enabled DRM_COLOROP_3D_LUT_DMA colorop into the DC fast-load
3D LUT config. __set_dm_plane_colorop_3dlut() now handles both the inline
3D LUT (DATA blob -> lut3d_func) and the DMA variant, which fills
dc_plane_state->cm.lut3d_dma from the pinned framebuffer's GPU address
(LINEAR_RGB swizzle, RGBA16161616 UNORM 12MSB, 17^3, neutral bias/scale)
and sets lut3d_dma_enable. Both 3D LUT variants map to the same MCM HW
block, so the rest of the per-colorop walk is shared; only this step
branches on the colorop type.

Signed-off-by: Harry Wentland <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 68 ++++++++++++++-----
 1 file changed, 51 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index ebb05a20aa0c..8936b30e9eae 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1868,25 +1868,60 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state 
*plane_state,
        bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || 
adev->dm.dc->caps.color.mpc.preblend;
        const struct drm_device *dev = colorop->dev;
        const struct drm_color_lut32 *lut3d;
+       struct amdgpu_framebuffer *afb;
        uint32_t lut3d_size;
+       uint64_t addr;
        int i = 0, ret = 0;
 
-       /* 3D LUT */
+       /* 3D LUT - inline or DMA (fast-load); both map to the same HW block */
        old_colorop = colorop;
        for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
                if (new_colorop_state->colorop == old_colorop &&
-                   new_colorop_state->colorop->type == DRM_COLOROP_3D_LUT) {
+                   (new_colorop_state->colorop->type == DRM_COLOROP_3D_LUT ||
+                    new_colorop_state->colorop->type == 
DRM_COLOROP_3D_LUT_DMA)) {
                        colorop_state = new_colorop_state;
                        break;
                }
        }
 
-       if (colorop_state && !colorop_state->bypass && colorop->type == 
DRM_COLOROP_3D_LUT) {
-               if (!has_3dlut) {
-                       drm_dbg(dev, "3D LUT is not supported by hardware\n");
+       if (!colorop_state || colorop_state->bypass) {
+               dc_plane_state->cm.flags.bits.lut3d_enable = 0;
+               dc_plane_state->cm.flags.bits.lut3d_dma_enable = 0;
+               return 0;
+       }
+
+       if (!has_3dlut) {
+               drm_dbg(dev, "3D LUT is not supported by hardware\n");
+               return -EINVAL;
+       }
+
+       if (colorop->type == DRM_COLOROP_3D_LUT_DMA) {
+               if (!colorop_state->fb) {
+                       drm_dbg(dev, "DMA 3D LUT colorop %d has no 
framebuffer\n",
+                               colorop->base.id);
                        return -EINVAL;
                }
 
+               drm_dbg(dev, "DMA 3D LUT colorop with ID: %d\n", 
colorop->base.id);
+
+               /* Not pinned yet for a new FB; the plane's prepare_fb fixes up 
addr */
+               afb = to_amdgpu_framebuffer(colorop_state->fb);
+               addr = afb->address + colorop_state->fb->offsets[0];
+
+               memset(&dc_plane_state->cm.lut3d_dma, 0, 
sizeof(dc_plane_state->cm.lut3d_dma));
+               dc_plane_state->cm.lut3d_dma.addr.type = PLN_ADDR_TYPE_GRAPHICS;
+               dc_plane_state->cm.lut3d_dma.addr.grph.addr.low_part = 
lower_32_bits(addr);
+               dc_plane_state->cm.lut3d_dma.addr.grph.addr.high_part = 
upper_32_bits(addr);
+               dc_plane_state->cm.lut3d_dma.swizzle = 
CM_LUT_3D_SWIZZLE_LINEAR_RGB;
+               dc_plane_state->cm.lut3d_dma.format = 
CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB;
+               dc_plane_state->cm.lut3d_dma.size = CM_LUT_SIZE_171717;
+               /* neutral bias/scale for UNORM input */
+               dc_plane_state->cm.lut3d_dma.bias = 0;
+               dc_plane_state->cm.lut3d_dma.scale = 0x3C00; /* 1.0 in FP1.5.10 
*/
+               dc_plane_state->cm.flags.bits.lut3d_dma_enable = 1;
+               /* lut3d_enable gates the fast-load trigger and MCM 3D LUT 
enable */
+               dc_plane_state->cm.flags.bits.lut3d_enable = 1;
+       } else {
                drm_dbg(dev, "3D LUT colorop with ID: %d\n", colorop->base.id);
                lut3d = __extract_blob_lut32(colorop_state->data, &lut3d_size);
                lut3d_size = lut3d != NULL ? lut3d_size : 0;
@@ -1898,19 +1933,18 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state 
*plane_state,
                }
 
                dc_plane_state->cm.flags.bits.lut3d_enable = 1;
+               dc_plane_state->cm.flags.bits.lut3d_dma_enable = 0;
+       }
 
-               /* 3D LUT requires shaper. If shaper colorop is bypassed, 
enable shaper curve
-                * with TRANSFER_FUNCTION_LINEAR
-                */
-               if (tf->type == TF_TYPE_BYPASS) {
-                       tf->type = TF_TYPE_DISTRIBUTED_POINTS;
-                       tf->tf = TRANSFER_FUNCTION_LINEAR;
-                       tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
-                       ret = __set_output_tf_32(tf, NULL, 0, false);
-                       dc_plane_state->cm.flags.bits.shaper_enable = 1;
-               }
-       } else {
-               dc_plane_state->cm.flags.bits.lut3d_enable = 0;
+       /* 3D LUT requires shaper. If shaper colorop is bypassed, enable shaper 
curve
+        * with TRANSFER_FUNCTION_LINEAR
+        */
+       if (tf->type == TF_TYPE_BYPASS) {
+               tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+               tf->tf = TRANSFER_FUNCTION_LINEAR;
+               tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+               ret = __set_output_tf_32(tf, NULL, 0, false);
+               dc_plane_state->cm.flags.bits.shaper_enable = 1;
        }
 
        return ret;
-- 
2.56.0

Reply via email to