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
