]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jul 2026 13:15:27 +0000 (15:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jul 2026 13:15:27 +0000 (15:15 +0200)
added patches:
drm-amd-display-fix-color-manager-3dlut-shaper-blend.patch

queue-7.1/drm-amd-display-fix-color-manager-3dlut-shaper-blend.patch [new file with mode: 0644]
queue-7.1/series

diff --git a/queue-7.1/drm-amd-display-fix-color-manager-3dlut-shaper-blend.patch b/queue-7.1/drm-amd-display-fix-color-manager-3dlut-shaper-blend.patch
new file mode 100644 (file)
index 0000000..5d17c86
--- /dev/null
@@ -0,0 +1,2884 @@
+From 12f58a6caad3be54d7788b338b3f57d7c17bbef7 Mon Sep 17 00:00:00 2001
+From: Dillon Varone <Dillon.Varone@amd.com>
+Date: Thu, 19 Mar 2026 11:57:08 -0400
+Subject: drm/amd/display: Fix Color Manager (3DLUT, Shaper, Blend)
+
+From: Dillon Varone <Dillon.Varone@amd.com>
+
+commit 12f58a6caad3be54d7788b338b3f57d7c17bbef7 upstream.
+
+[WHY & HOW]
+The original refactor and fixes are causing regressions.
+Revert them for now until they can be resolved
+
+Fixes: e56e3cff2a1b ("drm/amd/display: Sync dcn42 with DC 3.2.373")
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Dillon Varone <Dillon.Varone@amd.com>
+Signed-off-by: James Lin <pinglei.lin@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c                       |   81 +
+ drivers/gpu/drm/amd/display/dc/core/dc_stream.c                |    2 
+ drivers/gpu/drm/amd/display/dc/dc.h                            |   58 -
+ drivers/gpu/drm/amd/display/dc/dc_types.h                      |   24 
+ drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c       |  201 +---
+ drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h       |   23 
+ drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c         |   78 -
+ drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h         |   10 
+ drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c      |  389 +++++--
+ drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c        |  499 +++++++++-
+ drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h        |    9 
+ drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h                   |   35 
+ drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h                    |   79 -
+ drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c         |  177 +--
+ drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h         |   25 
+ drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c           |  388 +++++++
+ drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h           |   49 
+ drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c |    1 
+ 18 files changed, 1439 insertions(+), 689 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -2956,27 +2956,16 @@ static struct surface_update_descriptor
+               elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
+       }
+-      if (u->cm || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
++      if (u->blend_tf || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
+               update_flags->bits.gamma_change = 1;
+               elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
+       }
+-      if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) {
++      if (u->lut3d_func || u->func_shaper) {
+               update_flags->bits.lut_3d = 1;
+               elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
+       }
+-      if (u->cm && u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable &&
+-                      u->cm->flags.bits.lut3d_enable && u->surface->cm.flags.bits.lut3d_enable) {
+-              /* Toggling 3DLUT loading between DMA and Host is illegal */
+-              BREAK_TO_DEBUGGER();
+-      }
+-
+-      if (u->cm && u->cm->flags.bits.lut3d_enable && !u->cm->flags.bits.lut3d_dma_enable) {
+-              /* Host loading 3DLUT requires full update but only stream lock  */
+-              elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_STREAM);
+-      }
+-
+       if (u->hdr_mult.value)
+               if (u->hdr_mult.value != u->surface->hdr_mult.value) {
+                       // TODO: Should be fast?
+@@ -2995,6 +2984,20 @@ static struct surface_update_descriptor
+               update_flags->bits.cm_hist_change = 1;
+               elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
+       }
++      if (u->cm2_params) {
++              if (u->cm2_params->component_settings.shaper_3dlut_setting != u->surface->mcm_shaper_3dlut_setting
++                              || u->cm2_params->component_settings.lut1d_enable != u->surface->mcm_lut1d_enable
++                              || u->cm2_params->cm2_luts.lut3d_data.lut3d_src != u->surface->mcm_luts.lut3d_data.lut3d_src) {
++                      update_flags->bits.mcm_transfer_function_enable_change = 1;
++                      elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
++              }
++      }
++
++      if (update_flags->bits.lut_3d &&
++                      u->surface->mcm_luts.lut3d_data.lut3d_src != DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
++              elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
++      }
++
+       if (check_config->enable_legacy_fast_update &&
+                       (update_flags->bits.gamma_change ||
+                       update_flags->bits.gamut_remap_change ||
+@@ -3250,12 +3253,24 @@ static void copy_surface_update_to_plane
+                       sizeof(struct dc_transfer_func_distributed_points));
+       }
+-      /* Shaper, 3DLUT, 1DLUT */
+-      if (srf_update->cm) {
+-              memcpy(&surface->cm, srf_update->cm,
+-                              sizeof(surface->cm));
++      if (srf_update->cm2_params) {
++              surface->mcm_shaper_3dlut_setting = srf_update->cm2_params->component_settings.shaper_3dlut_setting;
++              surface->mcm_lut1d_enable = srf_update->cm2_params->component_settings.lut1d_enable;
++              surface->mcm_luts = srf_update->cm2_params->cm2_luts;
++      }
++
++      if (srf_update->func_shaper) {
++              memcpy(&surface->in_shaper_func, srf_update->func_shaper,
++              sizeof(surface->in_shaper_func));
++
++              if (surface->mcm_shaper_3dlut_setting >= DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER)
++                      surface->mcm_luts.shaper = &surface->in_shaper_func;
+       }
++      if (srf_update->lut3d_func)
++              memcpy(&surface->lut3d_func, srf_update->lut3d_func,
++              sizeof(surface->lut3d_func));
++
+       if (srf_update->hdr_mult.value)
+               surface->hdr_mult =
+                               srf_update->hdr_mult;
+@@ -3264,6 +3279,17 @@ static void copy_surface_update_to_plane
+               surface->sdr_white_level_nits =
+                               srf_update->sdr_white_level_nits;
++      if (srf_update->blend_tf) {
++              memcpy(&surface->blend_tf, srf_update->blend_tf,
++              sizeof(surface->blend_tf));
++
++              if (surface->mcm_lut1d_enable)
++                      surface->mcm_luts.lut1d_func = &surface->blend_tf;
++      }
++
++      if (srf_update->cm2_params || srf_update->blend_tf)
++              surface->lut_bank_a = !surface->lut_bank_a;
++
+       if (srf_update->input_csc_color_matrix)
+               surface->input_csc_color_matrix =
+                       *srf_update->input_csc_color_matrix;
+@@ -4550,9 +4576,11 @@ static void commit_planes_for_stream(str
+                               if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
+                                       continue;
+-                              if (srf_updates[i].cm &&
+-                                              srf_updates[i].cm->flags.bits.lut3d_enable &&
+-                                              srf_updates[i].cm->flags.bits.lut3d_dma_enable &&
++                              if (srf_updates[i].cm2_params &&
++                                              srf_updates[i].cm2_params->cm2_luts.lut3d_data.lut3d_src ==
++                                                              DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM &&
++                                              srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting ==
++                                                              DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT &&
+                                               dc->hwss.trigger_3dlut_dma_load)
+                                       dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx);
+@@ -5209,12 +5237,6 @@ static bool full_update_required(
+               const struct dc_stream_update *stream_update,
+               const struct dc_stream_state *stream)
+ {
+-      const union dc_plane_cm_flags blend_only_flags = {
+-              .bits = {
+-                      .blend_enable = 1,
+-              }
+-      };
+-
+       if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream))
+               return true;
+@@ -5229,10 +5251,7 @@ static bool full_update_required(
+                               srf_updates[i].in_transfer_func ||
+                               srf_updates[i].surface->force_full_update ||
+                               (srf_updates[i].flip_addr &&
+-                              srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) ||
+-                              (srf_updates[i].cm &&
+-                              ((srf_updates[i].cm->flags.all != blend_only_flags.all && srf_updates[i].cm->flags.all != 0) ||
+-                              (srf_updates[i].surface->cm.flags.all != blend_only_flags.all && srf_updates[i].surface->cm.flags.all != 0)))))
++                              srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface)))
+                       return true;
+       }
+@@ -6966,7 +6985,7 @@ bool dc_capture_register_software_state(
+                       struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+                       /* MPCC blending tree and mode control - capture actual blend configuration */
+-                      state->mpc.mpcc_mode[i] = (plane_state->cm.blend_func.type != TF_TYPE_BYPASS) ? 1 : 0;
++                      state->mpc.mpcc_mode[i] = (plane_state->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0;
+                       state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0;
+                       state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0;
+                       state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+@@ -996,6 +996,7 @@ void dc_stream_release_3dlut_for_stream(
+       if (rmcm_3dlut) {
+               rmcm_3dlut->isInUse = false;
+               rmcm_3dlut->stream  = NULL;
++              rmcm_3dlut->protection_bits = 0;
+       }
+ }
+@@ -1007,6 +1008,7 @@ void dc_stream_init_rmcm_3dlut(struct dc
+       for (int i = 0; i < num_rmcm; i++) {
+               dc->res_pool->rmcm_3dlut[i].isInUse = false;
+               dc->res_pool->rmcm_3dlut[i].stream = NULL;
++              dc->res_pool->rmcm_3dlut[i].protection_bits = 0;
+       }
+ }
+--- a/drivers/gpu/drm/amd/display/dc/dc.h
++++ b/drivers/gpu/drm/amd/display/dc/dc.h
+@@ -1407,50 +1407,15 @@ struct lut_mem_mapping {
+ struct dc_rmcm_3dlut {
+       bool isInUse;
+       const struct dc_stream_state *stream;
++      uint8_t protection_bits;
+ };
+ struct dc_3dlut {
+       struct kref refcount;
+       struct tetrahedral_params lut_3d;
++      struct fixed31_32 hdr_multiplier;
+       union dc_3dlut_state state;
+ };
+-
+-/* 3DLUT DMA (Fast Load) params */
+-struct dc_3dlut_dma {
+-      struct dc_plane_address addr;
+-      enum dc_cm_lut_swizzle swizzle;
+-      enum dc_cm_lut_pixel_format format;
+-      uint16_t bias; /* FP1.5.10 */
+-      uint16_t scale; /* FP1.5.10 */
+-      enum dc_cm_lut_size size;
+-};
+-
+-/* color manager */
+-union dc_plane_cm_flags {
+-      unsigned int all;
+-      struct {
+-              unsigned int shaper_enable    : 1;
+-              unsigned int lut3d_enable     : 1;
+-              unsigned int blend_enable     : 1;
+-              /* whether legacy (lut3d_func) or DMA is valid */
+-              unsigned int lut3d_dma_enable : 1;
+-              /* RMCM lut to be used instead of MCM */
+-              unsigned int rmcm_enable         : 1;
+-              unsigned int reserved: 27;
+-      } bits;
+-};
+-
+-struct dc_plane_cm {
+-      struct kref refcount;
+-      struct dc_transfer_func shaper_func;
+-      union {
+-              struct dc_3dlut lut3d_func;
+-              struct dc_3dlut_dma lut3d_dma;
+-      };
+-      struct dc_transfer_func blend_func;
+-      union dc_plane_cm_flags flags;
+-};
+-
+ /*
+  * This structure is filled in by dc_surface_get_status and contains
+  * the last requested address and the currently active address so the called
+@@ -1528,18 +1493,14 @@ struct dc_plane_state {
+       struct fixed31_32 hdr_mult;
+       struct colorspace_transform gamut_remap_matrix;
++      // TODO: No longer used, remove
++      struct dc_hdr_static_metadata hdr_static_ctx;
++
+       enum dc_color_space color_space;
+-      bool lut_bank_a;
+-      struct dc_hdr_static_metadata hdr_static_ctx;
+       struct dc_3dlut lut3d_func;
+       struct dc_transfer_func in_shaper_func;
+       struct dc_transfer_func blend_tf;
+-      enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting;
+-      bool mcm_lut1d_enable;
+-      struct dc_cm2_func_luts mcm_luts;
+-      enum mpcc_movable_cm_location mcm_location;
+-      struct dc_plane_cm cm;
+       struct dc_transfer_func *gamcor_tf;
+       enum surface_pixel_format format;
+@@ -1576,6 +1537,11 @@ struct dc_plane_state {
+       bool is_statically_allocated;
+       enum chroma_cositing cositing;
++      enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting;
++      bool mcm_lut1d_enable;
++      struct dc_cm2_func_luts mcm_luts;
++      bool lut_bank_a;
++      enum mpcc_movable_cm_location mcm_location;
+       struct dc_csc_transform cursor_csc_color_matrix;
+       bool adaptive_sharpness_en;
+       int adaptive_sharpness_policy;
+@@ -1968,10 +1934,6 @@ struct dc_3dlut *dc_create_3dlut_func(vo
+ void dc_3dlut_func_release(struct dc_3dlut *lut);
+ void dc_3dlut_func_retain(struct dc_3dlut *lut);
+-struct dc_plane_cm *dc_plane_cm_create(void);
+-void dc_plane_cm_release(struct dc_plane_cm *cm);
+-void dc_plane_cm_retain(struct dc_plane_cm *cm);
+-
+ void dc_post_update_surfaces_to_stream(
+               struct dc *dc);
+--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
+@@ -1493,28 +1493,4 @@ struct dc_validation_dpia_set {
+       uint32_t required_bw;
+ };
+-enum dc_cm_lut_swizzle {
+-      CM_LUT_3D_SWIZZLE_LINEAR_RGB,
+-      CM_LUT_3D_SWIZZLE_LINEAR_BGR,
+-      CM_LUT_1D_PACKED_LINEAR
+-};
+-
+-enum dc_cm_lut_pixel_format {
+-      CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB,
+-      CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB,
+-      CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB,
+-      CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB,
+-      CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10,
+-      CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10
+-};
+-
+-enum dc_cm_lut_size {
+-      CM_LUT_SIZE_NONE,
+-      CM_LUT_SIZE_999,
+-      CM_LUT_SIZE_171717,
+-      CM_LUT_SIZE_333333,
+-      CM_LUT_SIZE_454545,
+-      CM_LUT_SIZE_656565,
+-};
+-
+ #endif /* DC_TYPES_H_ */
+--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
++++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
+@@ -41,12 +41,12 @@
+       hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name
+ void hubp401_program_3dlut_fl_addr(struct hubp *hubp,
+-      const struct dc_plane_address *address)
++      const struct dc_plane_address address)
+ {
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-      REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, address->lut3d.addr.high_part);
+-      REG_WRITE(HUBP_3DLUT_ADDRESS_LOW, address->lut3d.addr.low_part);
++      REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, address.lut3d.addr.high_part);
++      REG_WRITE(HUBP_3DLUT_ADDRESS_LOW, address.lut3d.addr.low_part);
+ }
+ void hubp401_program_3dlut_fl_dlg_param(struct hubp *hubp, int refcyc_per_3dlut_group)
+@@ -72,46 +72,33 @@ int hubp401_get_3dlut_fl_done(struct hub
+       return ret;
+ }
+-static void hubp401_get_3dlut_fl_xbar_map(
+-              const enum dc_cm_lut_pixel_format format,
+-              enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_y_g,
+-              enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cb_b,
+-              enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cr_r)
+-{
+-      switch (format) {
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB:
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB:
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10:
+-              /* BGRA */
+-              *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+-              *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+-              *bit_slice_cb_b =  hubp_3dlut_fl_crossbar_bit_slice_0_15;
+-              break;
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
+-      default:
+-              /* RGBA */
+-              *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
+-              *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+-              *bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+-              break;
+-      }
++void hubp401_program_3dlut_fl_addressing_mode(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode)
++{
++      struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
++
++      REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_ADDRESSING_MODE, addr_mode);
+ }
+-void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp,
+-              const enum dc_cm_lut_pixel_format format)
++void hubp401_program_3dlut_fl_width(struct hubp *hubp, enum hubp_3dlut_fl_width width)
+ {
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g = 0;
+-      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b = 0;
+-      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r = 0;
++      REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, width);
++}
+-      hubp401_get_3dlut_fl_xbar_map(format,
+-                      &bit_slice_y_g,
+-                      &bit_slice_cb_b,
+-                      &bit_slice_cr_r);
++void hubp401_program_3dlut_fl_tmz_protected(struct hubp *hubp, uint8_t protection_bits)
++{
++      struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
++
++      REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, protection_bits);
++}
++
++void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp,
++                      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g,
++                      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b,
++                      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r)
++{
++      struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+       REG_UPDATE_3(HUBP_3DLUT_CONTROL,
+                       HUBP_3DLUT_CROSSBAR_SELECT_Y_G, bit_slice_y_g,
+@@ -119,122 +106,62 @@ void hubp401_program_3dlut_fl_crossbar(s
+                       HUBP_3DLUT_CROSSBAR_SELECT_CR_R, bit_slice_cr_r);
+ }
+-static enum hubp_3dlut_fl_width hubp401_get_3dlut_fl_width(
+-              const enum dc_cm_lut_size size,
+-              const enum dc_cm_lut_swizzle swizzle)
+-{
+-      enum hubp_3dlut_fl_width width = 0;
+-
+-      switch (size) {
+-      case CM_LUT_SIZE_333333:
+-              ASSERT(swizzle != CM_LUT_1D_PACKED_LINEAR);
+-              width = hubp_3dlut_fl_width_33;
+-              break;
+-      case CM_LUT_SIZE_171717:
+-              if (swizzle != CM_LUT_1D_PACKED_LINEAR) {
+-                      width = hubp_3dlut_fl_width_17;
+-              } else {
+-                      width = hubp_3dlut_fl_width_17_transformed;
+-              }
+-              break;
+-      default:
+-              width = 0;
+-              break;
+-      }
+-
+-      return width;
+-}
+-
+-static enum hubp_3dlut_fl_format hubp401_get_3dlut_fl_format(
+-              const enum dc_cm_lut_pixel_format dc_format)
++void hubp401_update_3dlut_fl_bias_scale(struct hubp *hubp, uint16_t bias, uint16_t scale)
+ {
+-      enum hubp_3dlut_fl_format hubp_format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
+-
+-      switch (dc_format) {
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB:
+-              hubp_format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
+-              break;
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB:
+-              hubp_format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
+-              break;
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10:
+-              hubp_format = hubp_3dlut_fl_format_float_fp1_5_10;
+-              break;
+-      default:
+-              BREAK_TO_DEBUGGER();
+-              break;
+-      }
++      struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-      return hubp_format;
++      REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, bias, HUBP0_3DLUT_FL_SCALE, scale);
+ }
+-static enum hubp_3dlut_fl_addressing_mode hubp401_get_3dlut_fl_addr_mode(
+-              const enum dc_cm_lut_swizzle swizzle)
++void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mode)
+ {
+-      enum hubp_3dlut_fl_addressing_mode addr_mode;
+-
+-      switch (swizzle) {
+-      case CM_LUT_1D_PACKED_LINEAR:
+-              addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
+-              break;
+-      case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
+-      case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
+-      default:
+-              addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+-              break;
+-      }
++      struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-      return addr_mode;
++      REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mode);
+ }
+-static enum hubp_3dlut_fl_mode hubp401_get_3dlut_fl_mode(
+-              const enum dc_cm_lut_swizzle swizzle)
++void hubp401_program_3dlut_fl_format(struct hubp *hubp, enum hubp_3dlut_fl_format format)
+ {
+-      enum hubp_3dlut_fl_mode mode;
+-
+-      switch (swizzle) {
+-      case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
+-              mode = hubp_3dlut_fl_mode_native_1;
+-              break;
+-      case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
+-              mode = hubp_3dlut_fl_mode_native_2;
+-              break;
+-      case CM_LUT_1D_PACKED_LINEAR:
+-              mode = hubp_3dlut_fl_mode_transform;
+-              break;
+-      default:
+-              mode = hubp_3dlut_fl_mode_disable;
+-              break;
+-      }
++      struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-      return mode;
++      REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, format);
+ }
+-void hubp401_program_3dlut_fl_config(struct hubp *hubp,
+-              const struct dc_3dlut_dma *config)
++void hubp401_program_3dlut_fl_config(
++      struct hubp *hubp,
++      struct hubp_fl_3dlut_config *cfg)
+ {
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-      enum hubp_3dlut_fl_width width = hubp401_get_3dlut_fl_width(config->size, config->swizzle);
+-      enum hubp_3dlut_fl_format format = hubp401_get_3dlut_fl_format(config->format);
+-      enum hubp_3dlut_fl_addressing_mode addr_mode = hubp401_get_3dlut_fl_addr_mode(config->swizzle);
+-      enum hubp_3dlut_fl_mode mode = hubp401_get_3dlut_fl_mode(config->swizzle);
++      uint32_t mpc_width = {(cfg->width == 17) ? 0 : 1};
++      uint32_t width = {cfg->width};
++
++      if (cfg->layout == DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR)
++              width = (cfg->width == 17) ? 4916 : 35940;
+       REG_UPDATE_2(_3DLUT_FL_CONFIG,
+-                      HUBP0_3DLUT_FL_MODE, mode,
+-                      HUBP0_3DLUT_FL_FORMAT, format);
++              HUBP0_3DLUT_FL_MODE, cfg->mode,
++              HUBP0_3DLUT_FL_FORMAT, cfg->format);
+       REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE,
+-                      HUBP0_3DLUT_FL_BIAS, config->bias,
+-                      HUBP0_3DLUT_FL_SCALE, config->scale);
++              HUBP0_3DLUT_FL_BIAS, cfg->bias,
++              HUBP0_3DLUT_FL_SCALE, cfg->scale);
+-      REG_UPDATE_3(HUBP_3DLUT_CONTROL,
+-                      HUBP_3DLUT_WIDTH, width,
+-                      HUBP_3DLUT_ADDRESSING_MODE, addr_mode,
+-                      HUBP_3DLUT_TMZ, config->addr.tmz_surface);
++      REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH,
++              HUBP_3DLUT_ADDRESS_HIGH, cfg->address.lut3d.addr.high_part);
++      REG_UPDATE(HUBP_3DLUT_ADDRESS_LOW,
++              HUBP_3DLUT_ADDRESS_LOW, cfg->address.lut3d.addr.low_part);
++
++      //cross bar
++      REG_UPDATE_8(HUBP_3DLUT_CONTROL,
++              HUBP_3DLUT_MPC_WIDTH, mpc_width,
++              HUBP_3DLUT_WIDTH, width,
++              HUBP_3DLUT_CROSSBAR_SELECT_CR_R, cfg->crossbar_bit_slice_cr_r,
++              HUBP_3DLUT_CROSSBAR_SELECT_Y_G, cfg->crossbar_bit_slice_y_g,
++              HUBP_3DLUT_CROSSBAR_SELECT_CB_B, cfg->crossbar_bit_slice_cb_b,
++              HUBP_3DLUT_ADDRESSING_MODE, cfg->addr_mode,
++              HUBP_3DLUT_TMZ, cfg->protection_bits,
++              HUBP_3DLUT_ENABLE, cfg->enabled ? 1 : 0);
+ }
+ void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor)
+@@ -1135,13 +1062,19 @@ static struct hubp_funcs dcn401_hubp_fun
+       .hubp_update_mall_sel = hubp401_update_mall_sel,
+       .hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering,
+       .hubp_program_mcache_id_and_split_coordinate = hubp401_program_mcache_id_and_split_coordinate,
++      .hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale,
++      .hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode,
++      .hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format,
+       .hubp_program_3dlut_fl_addr = hubp401_program_3dlut_fl_addr,
+-      .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config,
+       .hubp_program_3dlut_fl_dlg_param = hubp401_program_3dlut_fl_dlg_param,
+       .hubp_enable_3dlut_fl = hubp401_enable_3dlut_fl,
++      .hubp_program_3dlut_fl_addressing_mode = hubp401_program_3dlut_fl_addressing_mode,
++      .hubp_program_3dlut_fl_width = hubp401_program_3dlut_fl_width,
++      .hubp_program_3dlut_fl_tmz_protected = hubp401_program_3dlut_fl_tmz_protected,
+       .hubp_program_3dlut_fl_crossbar = hubp401_program_3dlut_fl_crossbar,
+       .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done,
+       .hubp_clear_tiling = hubp401_clear_tiling,
++      .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config,
+       .hubp_read_reg_state = hubp3_read_reg_state
+ };
+--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
++++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
+@@ -328,17 +328,32 @@ int hubp401_get_3dlut_fl_done(struct hub
+ void hubp401_set_unbounded_requesting(struct hubp *hubp, bool enable);
++void hubp401_update_3dlut_fl_bias_scale(struct hubp *hubp, uint16_t bias, uint16_t scale);
++
+ void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp,
+-              const enum dc_cm_lut_pixel_format format);
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g,
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b,
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r);
++
++void hubp401_program_3dlut_fl_tmz_protected(struct hubp *hubp, uint8_t protection_bits);
++
++void hubp401_program_3dlut_fl_width(struct hubp *hubp, enum hubp_3dlut_fl_width width);
++
++void hubp401_program_3dlut_fl_addressing_mode(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode);
+ void hubp401_enable_3dlut_fl(struct hubp *hubp, bool enable);
+ void hubp401_program_3dlut_fl_dlg_param(struct hubp *hubp, int refcyc_per_3dlut_group);
+-void hubp401_program_3dlut_fl_addr(struct hubp *hubp, const struct dc_plane_address *address);
++void hubp401_program_3dlut_fl_addr(struct hubp *hubp, const struct dc_plane_address address);
++
++void hubp401_program_3dlut_fl_format(struct hubp *hubp, enum hubp_3dlut_fl_format format);
++
++void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mode);
+-void hubp401_program_3dlut_fl_config(struct hubp *hubp,
+-              const struct dc_3dlut_dma *config);
++void hubp401_program_3dlut_fl_config(
++      struct hubp *hubp,
++      struct hubp_fl_3dlut_config *cfg);
+ void hubp401_clear_tiling(struct hubp *hubp);
+--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
++++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
+@@ -311,84 +311,19 @@ static void hubp42_program_surface_confi
+       hubp42_program_pixel_format(hubp, format);
+ }
+-static void hubp42_get_3dlut_fl_xbar_map(
+-              const enum dc_cm_lut_pixel_format format,
+-              enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_y_g,
+-              enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cb_b,
+-              enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cr_r)
+-{
+-      switch (format) {
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB:
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB:
+-      case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10:
+-              /* BGRA */
+-              *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+-              *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+-              *bit_slice_cb_b =  hubp_3dlut_fl_crossbar_bit_slice_0_15;
+-              break;
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
+-      case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
+-      default:
+-              /* RGBA */
+-              *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
+-              *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+-              *bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+-              break;
+-      }
+-}
+-
+ void hubp42_program_3dlut_fl_crossbar(struct hubp *hubp,
+-              const enum dc_cm_lut_pixel_format format)
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r,
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g,
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b)
+ {
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g = 0;
+-      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b = 0;
+-      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r = 0;
+-
+-      hubp42_get_3dlut_fl_xbar_map(format,
+-                      &bit_slice_g,
+-                      &bit_slice_b,
+-                      &bit_slice_r);
+-
+       REG_UPDATE_3(HUBP_3DLUT_CONTROL,
+               HUBP_3DLUT_CROSSBAR_SEL_R, bit_slice_r,
+               HUBP_3DLUT_CROSSBAR_SEL_G, bit_slice_g,
+               HUBP_3DLUT_CROSSBAR_SEL_B, bit_slice_b);
+ }
+-static uint32_t hubp42_get_3dlut_fl_mpc_width(
+-              const enum dc_cm_lut_size size)
+-{
+-      uint32_t width = 0;
+-
+-      switch (size) {
+-      case CM_LUT_SIZE_333333:
+-              width = 1;
+-              break;
+-      case CM_LUT_SIZE_171717:
+-      default:
+-              width = 0;
+-              break;
+-      }
+-
+-      return width;
+-}
+-
+-void hubp42_program_3dlut_fl_config(struct hubp *hubp,
+-              const struct dc_3dlut_dma *config)
+-{
+-      struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+-
+-      uint32_t mpc_width = hubp42_get_3dlut_fl_mpc_width(config->size);
+-
+-      REG_UPDATE(HUBP_3DLUT_CONTROL,
+-                      HUBP_3DLUT_MPC_WIDTH, mpc_width);
+-
+-      hubp401_program_3dlut_fl_config(hubp, config);
+-}
+-
+ static bool hubp42_program_surface_flip_and_addr(
+       struct hubp *hubp,
+       const struct dc_plane_address *address,
+@@ -670,10 +605,15 @@ struct hubp_funcs dcn42_hubp_funcs = {
+       .hubp_set_flip_int = hubp1_set_flip_int,
+       .hubp_in_blank = hubp1_in_blank,
+       .program_extended_blank = hubp31_program_extended_blank_value,
++      .hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale,
++      .hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode,
++      .hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format,
+       .hubp_program_3dlut_fl_addr = hubp401_program_3dlut_fl_addr,
+-      .hubp_program_3dlut_fl_config = hubp42_program_3dlut_fl_config,
+       .hubp_program_3dlut_fl_dlg_param = hubp401_program_3dlut_fl_dlg_param,
+       .hubp_enable_3dlut_fl = hubp401_enable_3dlut_fl,
++      .hubp_program_3dlut_fl_addressing_mode = hubp401_program_3dlut_fl_addressing_mode,
++      .hubp_program_3dlut_fl_width = hubp401_program_3dlut_fl_width,
++      .hubp_program_3dlut_fl_tmz_protected = hubp401_program_3dlut_fl_tmz_protected,
+       .hubp_program_3dlut_fl_crossbar = hubp42_program_3dlut_fl_crossbar,
+       .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done,
+       .hubp_clear_tiling = hubp3_clear_tiling,
+--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
++++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
+@@ -58,11 +58,11 @@ bool hubp42_construct(
+       const struct dcn_hubp2_shift *hubp_shift,
+       const struct dcn_hubp2_mask *hubp_mask);
+-void hubp42_program_3dlut_fl_crossbar(struct hubp *hubp,
+-              const enum dc_cm_lut_pixel_format format);
+-
+-void hubp42_program_3dlut_fl_config(struct hubp *hubp,
+-              const struct dc_3dlut_dma *config);
++void hubp42_program_3dlut_fl_crossbar(
++      struct hubp *hubp,
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r,
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g,
++      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b);
+ void hubp42_read_state(struct hubp *hubp);
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+@@ -95,6 +95,10 @@ void dcn401_program_gamut_remap(struct p
+       unsigned int mpcc_id = pipe_ctx->plane_res.mpcc_inst;
+       struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
++      //For now assert if location is not pre-blend
++      if (pipe_ctx->plane_state)
++              ASSERT(pipe_ctx->plane_state->mcm_location == MPCC_MOVABLE_CM_LOCATION_BEFORE);
++
+       // program MPCC_MCM_FIRST_GAMUT_REMAP
+       memset(&mpc_adjust, 0, sizeof(mpc_adjust));
+       mpc_adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
+@@ -374,180 +378,300 @@ void dcn401_init_hw(struct dc *dc)
+       }
+ }
+-void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx)
++static void dcn401_get_mcm_lut_xable_from_pipe_ctx(struct dc *dc, struct pipe_ctx *pipe_ctx,
++              enum MCM_LUT_XABLE *shaper_xable,
++              enum MCM_LUT_XABLE *lut3d_xable,
++              enum MCM_LUT_XABLE *lut1d_xable)
+ {
+-      (void)dc;
+-      struct hubp *hubp = pipe_ctx->plane_res.hubp;
++      enum dc_cm2_shaper_3dlut_setting shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL;
++      bool lut1d_enable = false;
++      struct mpc *mpc = dc->res_pool->mpc;
++      int mpcc_id = pipe_ctx->plane_res.hubp->inst;
+-      if (hubp->funcs->hubp_enable_3dlut_fl) {
+-              hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
++      if (!pipe_ctx->plane_state)
++              return;
++      shaper_3dlut_setting = pipe_ctx->plane_state->mcm_shaper_3dlut_setting;
++      lut1d_enable = pipe_ctx->plane_state->mcm_lut1d_enable;
++      mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
++      pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
++
++      *lut1d_xable = lut1d_enable ? MCM_LUT_ENABLE : MCM_LUT_DISABLE;
++
++      switch (shaper_3dlut_setting) {
++      case DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL:
++              *lut3d_xable = *shaper_xable = MCM_LUT_DISABLE;
++              break;
++      case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER:
++              *lut3d_xable = MCM_LUT_DISABLE;
++              *shaper_xable = MCM_LUT_ENABLE;
++              break;
++      case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT:
++              *lut3d_xable = *shaper_xable = MCM_LUT_ENABLE;
++              break;
+       }
+ }
+-bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
+-                              const struct dc_plane_state *plane_state)
++void dcn401_populate_mcm_luts(struct dc *dc,
++              struct pipe_ctx *pipe_ctx,
++              struct dc_cm2_func_luts mcm_luts,
++              bool lut_bank_a)
+ {
+-      struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc;
+       struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
+       struct hubp *hubp = pipe_ctx->plane_res.hubp;
+-      const struct dc_plane_cm *cm = &plane_state->cm;
+       int mpcc_id = hubp->inst;
+       struct mpc *mpc = dc->res_pool->mpc;
+       union mcm_lut_params m_lut_params;
+-      struct dc_3dlut_dma lut3d_dma;
+-      bool lut_enable;
+-      bool lut_bank_a;
++      enum dc_cm2_transfer_func_source lut3d_src = mcm_luts.lut3d_data.lut3d_src;
++      enum hubp_3dlut_fl_format format = 0;
++      enum hubp_3dlut_fl_mode mode;
++      enum hubp_3dlut_fl_width width = 0;
++      enum hubp_3dlut_fl_addressing_mode addr_mode;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0;
++      enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE;
++      enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE;
++      enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE;
+       bool rval;
+-      bool result = true;
+-      /* decide LUT bank based on current in use */
+-      mpc->funcs->get_lut_mode(mpc, MCM_LUT_1DLUT, mpcc_id, &lut_enable, &lut_bank_a);
+-      if (!lut_enable) {
+-              mpc->funcs->get_lut_mode(mpc, MCM_LUT_SHAPER, mpcc_id, &lut_enable, &lut_bank_a);
+-      }
+-      if (!lut_enable) {
+-              mpc->funcs->get_lut_mode(mpc, MCM_LUT_3DLUT, mpcc_id, &lut_enable, &lut_bank_a);
+-      }
+-
+-      /* switch to the next bank */
+-      if (lut_enable) {
+-              lut_bank_a = !lut_bank_a;
+-      }
+-
+-      /* MCM location fixed to pre-blend */
+-      mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
++      dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
+       /* 1D LUT */
+-      lut_enable = cm->flags.bits.blend_enable;
+-      memset(&m_lut_params, 0, sizeof(m_lut_params));
+-      if (lut_enable) {
+-              if (cm->blend_func.type == TF_TYPE_HWPWL)
+-                      m_lut_params.pwl = &cm->blend_func.pwl;
+-              else if (cm->blend_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
+-                      rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+-                                      &cm->blend_func,
+-                                      &dpp_base->regamma_params,
+-                                      false);
++      if (mcm_luts.lut1d_func) {
++              memset(&m_lut_params, 0, sizeof(m_lut_params));
++              if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL)
++                      m_lut_params.pwl = &mcm_luts.lut1d_func->pwl;
++              else if (mcm_luts.lut1d_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
++                      rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
++                                      mcm_luts.lut1d_func,
++                                      &dpp_base->regamma_params, false);
+                       m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
+               }
+-
+-              if (!m_lut_params.pwl) {
+-                      lut_enable = false;
++              if (m_lut_params.pwl) {
++                      if (mpc->funcs->populate_lut)
++                              mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, m_lut_params, lut_bank_a, mpcc_id);
+               }
+-      } else {
+-              lut_enable = false;
++              if (mpc->funcs->program_lut_mode)
++                      mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut1d_xable && m_lut_params.pwl, lut_bank_a, mpcc_id);
+       }
+-      if (mpc->funcs->program_lut_mode)
+-              mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut_enable, lut_bank_a, CM_LUT_SIZE_NONE, mpcc_id);
+-      if (lut_enable && mpc->funcs->populate_lut)
+-              mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, &m_lut_params, lut_bank_a, mpcc_id);
+-
+       /* Shaper */
+-      lut_enable = cm->flags.bits.shaper_enable;
+-      if (lut_enable) {
++      if (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) {
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+-              if (cm->shaper_func.type == TF_TYPE_HWPWL)
+-                      m_lut_params.pwl = &cm->shaper_func.pwl;
+-              else if (cm->shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
++              if (mcm_luts.shaper->type == TF_TYPE_HWPWL)
++                      m_lut_params.pwl = &mcm_luts.shaper->pwl;
++              else if (mcm_luts.shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
+                       ASSERT(false);
+-                      rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+-                                      &cm->shaper_func,
+-                                      &dpp_base->shaper_params,
+-                                      true);
+-                      m_lut_params.pwl = rval ? &dpp_base->shaper_params : NULL;
++                      rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
++                                      mcm_luts.shaper,
++                                      &dpp_base->regamma_params, true);
++                      m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
+               }
+-              if (!m_lut_params.pwl) {
+-                      lut_enable = false;
++              if (m_lut_params.pwl) {
++                      if (mpc->funcs->mcm.populate_lut)
++                              mpc->funcs->mcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id);
++                      if (mpc->funcs->program_lut_mode)
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_ENABLE, lut_bank_a, mpcc_id);
+               }
+-      } else {
+-              lut_enable = false;
+       }
+-      if (mpc->funcs->program_lut_mode)
+-              mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, lut_enable, lut_bank_a, CM_LUT_SIZE_NONE, mpcc_id);
+-      if (lut_enable && mpc->funcs->populate_lut)
+-              mpc->funcs->populate_lut(mpc, MCM_LUT_SHAPER, &m_lut_params, lut_bank_a, mpcc_id);
++      /* 3DLUT */
++      switch (lut3d_src) {
++      case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
++              memset(&m_lut_params, 0, sizeof(m_lut_params));
++              if (hubp->funcs->hubp_enable_3dlut_fl)
++                      hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
+-      /* NOTE: Toggling from DMA->Host is not supported atomically as hardware
+-       * blocks writes until 3DLUT FL mode is cleared from HUBP on VUpdate.
+-       * Expectation is either option is used consistently.
+-       */
++              if (mcm_luts.lut3d_data.lut3d_func && mcm_luts.lut3d_data.lut3d_func->state.bits.initialized) {
++                      m_lut_params.lut3d = &mcm_luts.lut3d_data.lut3d_func->lut_3d;
++                      if (mpc->funcs->populate_lut)
++                              mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, m_lut_params, lut_bank_a, mpcc_id);
++                      if (mpc->funcs->program_lut_mode)
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a,
++                                              mpcc_id);
++              }
++              break;
++      case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM:
++              switch (mcm_luts.lut3d_data.gpu_mem_params.size) {
++#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
++              case DC_CM2_GPU_MEM_SIZE_333333:
++                      if (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33)
++                              width = hubp_3dlut_fl_width_33;
++                      break;
++#endif
++              case DC_CM2_GPU_MEM_SIZE_171717:
++                      width = hubp_3dlut_fl_width_17;
++                      break;
++              case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
++                      width = hubp_3dlut_fl_width_transformed;
++                      break;
++              default:
++                      //TODO: handle default case
++                      break;
++              }
+-      /* 3DLUT */
+-      lut_enable = cm->flags.bits.lut3d_enable;
+-      if (lut_enable && cm->flags.bits.lut3d_dma_enable) {
+-              /* Fast (DMA) Load Mode */
+-              /* MPC */
+-              if (mpc->funcs->program_lut_mode)
+-                      mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut_enable, lut_bank_a, cm->lut3d_dma.size, mpcc_id);
++              //check for support
++              if (mpc->funcs->mcm.is_config_supported &&
++                      !mpc->funcs->mcm.is_config_supported(width))
++                      break;
+-              /* only supports 12 bit */
+               if (mpc->funcs->program_lut_read_write_control)
+-                      mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, 12, mpcc_id);
++                      mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id);
++              if (mpc->funcs->program_lut_mode)
++                      mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id);
+-              if (mpc->funcs->update_3dlut_fast_load_select)
+-                      mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst);
++              if (hubp->funcs->hubp_program_3dlut_fl_addr)
++                      hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr);
+-              /* HUBP */
+-              if (hubp->funcs->hubp_program_3dlut_fl_config)
+-                      hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma);
++              if (mpc->funcs->mcm.program_bit_depth)
++                      mpc->funcs->mcm.program_bit_depth(mpc, mcm_luts.lut3d_data.gpu_mem_params.bit_depth, mpcc_id);
++
++              switch (mcm_luts.lut3d_data.gpu_mem_params.layout) {
++              case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
++                      mode = hubp_3dlut_fl_mode_native_1;
++                      addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++                      break;
++              case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
++                      mode = hubp_3dlut_fl_mode_native_2;
++                      addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++                      break;
++              case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
++                      mode = hubp_3dlut_fl_mode_transform;
++                      addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
++                      break;
++              default:
++                      mode = hubp_3dlut_fl_mode_disable;
++                      addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++                      break;
++              }
++              if (hubp->funcs->hubp_program_3dlut_fl_mode)
++                      hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode);
++
++              if (hubp->funcs->hubp_program_3dlut_fl_addressing_mode)
++                      hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode);
++
++              switch (mcm_luts.lut3d_data.gpu_mem_params.format_params.format) {
++              case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB:
++                      format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
++                      break;
++              case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB:
++                      format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
++                      break;
++              case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10:
++                      format = hubp_3dlut_fl_format_float_fp1_5_10;
++                      break;
++              }
++              if (hubp->funcs->hubp_program_3dlut_fl_format)
++                      hubp->funcs->hubp_program_3dlut_fl_format(hubp, format);
++              if (hubp->funcs->hubp_update_3dlut_fl_bias_scale &&
++                              mpc->funcs->mcm.program_bias_scale) {
++                      mpc->funcs->mcm.program_bias_scale(mpc,
++                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
++                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale,
++                              mpcc_id);
++                      hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp,
++                                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
++                                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale);
++              }
++
++              //navi 4x has a bug and r and blue are swapped and need to be worked around here in
++              //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x
++              switch (mcm_luts.lut3d_data.gpu_mem_params.component_order) {
++              case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA:
++              default:
++                      crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
++                      crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
++                      crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
++                      break;
++              }
+               if (hubp->funcs->hubp_program_3dlut_fl_crossbar)
+-                      hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, cm->lut3d_dma.format);
++                      hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp,
++                                      crossbar_bit_slice_cr_r,
++                                      crossbar_bit_slice_y_g,
++                                      crossbar_bit_slice_cb_b);
+-              if (hubp->funcs->hubp_program_3dlut_fl_addr)
+-                      hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr);
++              if (mpc->funcs->mcm.program_lut_read_write_control)
++                      mpc->funcs->mcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, true, mpcc_id);
++
++              if (mpc->funcs->mcm.program_3dlut_size)
++                      mpc->funcs->mcm.program_3dlut_size(mpc, width, mpcc_id);
+-              if (hubp->funcs->hubp_enable_3dlut_fl) {
++              if (mpc->funcs->update_3dlut_fast_load_select)
++                      mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst);
++
++              if (hubp->funcs->hubp_enable_3dlut_fl)
+                       hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
+-              } else {
+-                      /* GPU memory only supports fast load path */
+-                      BREAK_TO_DEBUGGER();
+-                      lut_enable = false;
+-                      result = false;
++              else {
++                      if (mpc->funcs->program_lut_mode) {
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
++                      }
+               }
+-      } else {
+-              /* Legacy (Host) Load Mode */
+-              memset(&m_lut_params, 0, sizeof(m_lut_params));
++              break;
+-              if (cm->flags.bits.lut3d_enable && cm->lut3d_func.state.bits.initialized) {
+-                      m_lut_params.lut3d = &cm->lut3d_func.lut_3d;
+-              } else {
+-                      lut_enable = false;
+-              }
++      }
++}
+-              /* MPC */
+-              if (mpc->funcs->program_lut_mode)
+-                      mpc->funcs->program_lut_mode(mpc,
+-                                      MCM_LUT_3DLUT,
+-                                      lut_enable,
+-                                      lut_bank_a,
+-                                      cm->lut3d_func.lut_3d.use_tetrahedral_9 ? CM_LUT_SIZE_999 : CM_LUT_SIZE_171717,
+-                                      mpcc_id);
+-
+-              if (lut_enable) {
+-                      if (mpc->funcs->program_lut_read_write_control)
+-                              mpc->funcs->program_lut_read_write_control(mpc,
+-                                              MCM_LUT_3DLUT,
+-                                              lut_bank_a,
+-                                              cm->lut3d_func.lut_3d.use_12bits ? 12 : 10,
+-                                              mpcc_id);
++void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx)
++{
++      (void)dc;
++      struct hubp *hubp = pipe_ctx->plane_res.hubp;
+-                      if (mpc->funcs->update_3dlut_fast_load_select)
+-                              mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, 0xf);
++      if (hubp->funcs->hubp_enable_3dlut_fl) {
++              hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
++      }
++}
+-                      if (mpc->funcs->populate_lut)
+-                              mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, &m_lut_params, lut_bank_a, mpcc_id);
+-              }
++bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
++                              const struct dc_plane_state *plane_state)
++{
++      struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
++      int mpcc_id = pipe_ctx->plane_res.hubp->inst;
++      struct dc *dc = pipe_ctx->stream_res.opp->ctx->dc;
++      struct mpc *mpc = dc->res_pool->mpc;
++      bool result;
++      const struct pwl_params *lut_params = NULL;
++      bool rval;
+-              /* HUBP */
+-              memset(&lut3d_dma, 0, sizeof(lut3d_dma));
+-              if (hubp->funcs->hubp_program_3dlut_fl_config)
+-                      hubp->funcs->hubp_program_3dlut_fl_config(hubp, &lut3d_dma);
++      if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
++              dcn401_populate_mcm_luts(dc, pipe_ctx, plane_state->mcm_luts, plane_state->lut_bank_a);
++              return true;
++      }
+-              if (hubp->funcs->hubp_enable_3dlut_fl)
+-                      hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
++      mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
++      pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
++      // 1D LUT
++      if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
++              lut_params = &plane_state->blend_tf.pwl;
++      else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
++              rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
++                                                             &plane_state->blend_tf,
++                                                             &dpp_base->regamma_params, false);
++              lut_params = rval ? &dpp_base->regamma_params : NULL;
++      }
++      result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
++      lut_params = NULL;
++
++      // Shaper
++      if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL)
++              lut_params = &plane_state->in_shaper_func.pwl;
++      else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
++              // TODO: dpp_base replace
++              rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
++                                                             &plane_state->in_shaper_func,
++                                                             &dpp_base->shaper_params, true);
++              lut_params = rval ? &dpp_base->shaper_params : NULL;
++      }
++      result &= mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
++
++      // 3D
++      if (mpc->funcs->program_3dlut) {
++              if (plane_state->lut3d_func.state.bits.initialized == 1)
++                      result &= mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func.lut_3d, mpcc_id);
++              else
++                      result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id);
+       }
+       return result;
+@@ -1824,9 +1948,10 @@ void dcn401_perform_3dlut_wa_unlock(stru
+       for (odm_pipe = pipe_ctx; odm_pipe != NULL; odm_pipe = odm_pipe->next_odm_pipe) {
+               for (mpc_pipe = odm_pipe; mpc_pipe != NULL; mpc_pipe = mpc_pipe->bottom_pipe) {
+-                      if (mpc_pipe->plane_state &&
+-                                      mpc_pipe->plane_state->cm.flags.bits.lut3d_enable &&
+-                                      mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable) {
++                      if (mpc_pipe->plane_state && mpc_pipe->plane_state->mcm_luts.lut3d_data.lut3d_src
++                                              == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM
++                                      && mpc_pipe->plane_state->mcm_shaper_3dlut_setting
++                                              == DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT) {
+                               wa_pipes[wa_pipe_ct++] = mpc_pipe;
+                       }
+               }
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
+@@ -394,6 +394,68 @@ void dcn42_program_cm_hist(
+                       plane_state->cm_hist_control, plane_state->color_space);
+ }
++static void dc_get_lut_xbar(
++      enum dc_cm2_gpu_mem_pixel_component_order order,
++      enum hubp_3dlut_fl_crossbar_bit_slice *cr_r,
++      enum hubp_3dlut_fl_crossbar_bit_slice *y_g,
++      enum hubp_3dlut_fl_crossbar_bit_slice *cb_b)
++{
++      switch (order) {
++      case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA:
++              *cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
++              *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
++              *cb_b =  hubp_3dlut_fl_crossbar_bit_slice_0_15;
++              break;
++      case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA:
++              *cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
++              *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
++              *cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
++              break;
++      }
++}
++
++static void dc_get_lut_mode(
++      enum dc_cm2_gpu_mem_layout layout,
++      enum hubp_3dlut_fl_mode *mode,
++      enum hubp_3dlut_fl_addressing_mode *addr_mode)
++{
++      switch (layout) {
++      case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
++              *mode = hubp_3dlut_fl_mode_native_1;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++              break;
++      case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
++              *mode = hubp_3dlut_fl_mode_native_2;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++              break;
++      case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
++              *mode = hubp_3dlut_fl_mode_transform;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
++              break;
++      default:
++              *mode = hubp_3dlut_fl_mode_disable;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++              break;
++      }
++}
++
++static void dc_get_lut_format(
++      enum dc_cm2_gpu_mem_format dc_format,
++      enum hubp_3dlut_fl_format *format)
++{
++      switch (dc_format) {
++      case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB:
++              *format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
++              break;
++      case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB:
++              *format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
++              break;
++      case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10:
++              *format = hubp_3dlut_fl_format_float_fp1_5_10;
++              break;
++      }
++}
++
+ static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc)
+ {
+       if (mpc->funcs->rmcm.power_on_shaper_3dlut &&
+@@ -404,17 +466,119 @@ static bool dc_is_rmcm_3dlut_supported(s
+       return false;
+ }
++static bool is_rmcm_3dlut_fl_supported(struct dc *dc, enum dc_cm2_gpu_mem_size size)
++{
++      if (!dc->caps.color.mpc.rmcm_3d_lut_caps.dma_3d_lut)
++              return false;
++      if (size == DC_CM2_GPU_MEM_SIZE_171717)
++              return (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_17);
++      else if (size == DC_CM2_GPU_MEM_SIZE_333333)
++              return (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33);
++      return false;
++}
++
++static void dcn42_set_mcm_location_post_blend(struct dc *dc, struct pipe_ctx *pipe_ctx, bool bPostBlend)
++{
++      struct mpc *mpc = dc->res_pool->mpc;
++      int mpcc_id = pipe_ctx->plane_res.hubp->inst;
++
++      if (!pipe_ctx->plane_state)
++              return;
++
++      mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
++      pipe_ctx->plane_state->mcm_location = (bPostBlend) ?
++                                                                                      MPCC_MOVABLE_CM_LOCATION_AFTER :
++                                                                                      MPCC_MOVABLE_CM_LOCATION_BEFORE;
++}
++
++static void dcn42_get_mcm_lut_xable_from_pipe_ctx(struct dc *dc, struct pipe_ctx *pipe_ctx,
++              enum MCM_LUT_XABLE *shaper_xable,
++              enum MCM_LUT_XABLE *lut3d_xable,
++              enum MCM_LUT_XABLE *lut1d_xable)
++{
++      enum dc_cm2_shaper_3dlut_setting shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL;
++      bool lut1d_enable = false;
++      struct mpc *mpc = dc->res_pool->mpc;
++      int mpcc_id = pipe_ctx->plane_res.hubp->inst;
++
++      if (!pipe_ctx->plane_state)
++              return;
++      shaper_3dlut_setting = pipe_ctx->plane_state->mcm_shaper_3dlut_setting;
++      lut1d_enable = pipe_ctx->plane_state->mcm_lut1d_enable;
++      mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
++      pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
++
++      *lut1d_xable = lut1d_enable ? MCM_LUT_ENABLE : MCM_LUT_DISABLE;
++
++      switch (shaper_3dlut_setting) {
++      case DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL:
++              *lut3d_xable = *shaper_xable = MCM_LUT_DISABLE;
++              break;
++      case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER:
++              *lut3d_xable = MCM_LUT_DISABLE;
++              *shaper_xable = MCM_LUT_ENABLE;
++              break;
++      case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT:
++              *lut3d_xable = *shaper_xable = MCM_LUT_ENABLE;
++              break;
++      }
++}
++
++static void fl_get_lut_mode(
++      enum dc_cm2_gpu_mem_layout layout,
++      enum dc_cm2_gpu_mem_size   size,
++      enum hubp_3dlut_fl_mode *mode,
++      enum hubp_3dlut_fl_addressing_mode *addr_mode,
++      enum hubp_3dlut_fl_width *width)
++{
++      *width = hubp_3dlut_fl_width_17;
++
++      if (size == DC_CM2_GPU_MEM_SIZE_333333)
++              *width = hubp_3dlut_fl_width_33;
++
++      switch (layout) {
++      case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
++              *mode = hubp_3dlut_fl_mode_native_1;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++              break;
++      case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
++              *mode = hubp_3dlut_fl_mode_native_2;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++              break;
++      case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
++              *mode = hubp_3dlut_fl_mode_transform;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
++              break;
++      default:
++              *mode = hubp_3dlut_fl_mode_disable;
++              *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
++              break;
++      }
++}
++
+ bool dcn42_program_rmcm_luts(
+       struct hubp *hubp,
+       struct pipe_ctx *pipe_ctx,
+-      const struct dc_plane_cm *cm,
++      enum dc_cm2_transfer_func_source lut3d_src,
++      struct dc_cm2_func_luts *mcm_luts,
+       struct mpc *mpc,
++      bool lut_bank_a,
+       int mpcc_id)
+ {
+       struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
+       union mcm_lut_params m_lut_params = {0};
++      enum MCM_LUT_XABLE shaper_xable, lut3d_xable = MCM_LUT_DISABLE, lut1d_xable;
++              enum hubp_3dlut_fl_mode mode;
++      enum hubp_3dlut_fl_addressing_mode addr_mode;
++      enum hubp_3dlut_fl_format format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
++      enum hubp_3dlut_fl_width width = hubp_3dlut_fl_width_17;
++
+       struct dc *dc = hubp->ctx->dc;
++      struct hubp_fl_3dlut_config fl_config;
+       struct mpc_fl_3dlut_config mpc_fl_config;
+       struct dc_stream_state *stream = pipe_ctx->stream;
+@@ -422,23 +586,25 @@ bool dcn42_program_rmcm_luts(
+       // true->false when it can be allocated at DI time
+       struct dc_rmcm_3dlut *rmcm_3dlut = dc_stream_get_3dlut_for_stream(dc, stream, false);
+-      bool lut_bank_a = true; // TODO get from HW
+-
+       //check to see current pipe is part of a stream with allocated rmcm 3dlut
+       if (!rmcm_3dlut)
+               return false;
++      rmcm_3dlut->protection_bits = mcm_luts->lut3d_data.rmcm_tmz;
++
++      dcn42_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
++
+       /* Shaper */
+-      if (cm->flags.bits.shaper_enable) {
++      if (mcm_luts->shaper) {
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+-              if (cm->shaper_func.type == TF_TYPE_HWPWL) {
+-                      m_lut_params.pwl = &cm->shaper_func.pwl;
+-              } else if (cm->shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
++              if (mcm_luts->shaper->type == TF_TYPE_HWPWL) {
++                      m_lut_params.pwl = &mcm_luts->shaper->pwl;
++              } else if (mcm_luts->shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
+                       ASSERT(false);
+                       cm_helper_translate_curve_to_hw_format(
+                                       dc->ctx,
+-                                      &cm->shaper_func,
++                                      mcm_luts->shaper,
+                                       &dpp_base->shaper_params, true);
+                       m_lut_params.pwl = &dpp_base->shaper_params;
+               }
+@@ -454,21 +620,58 @@ bool dcn42_program_rmcm_luts(
+       }
+       /* 3DLUT */
+-      if (!cm->flags.bits.lut3d_dma_enable) {
++      switch (lut3d_src) {
++      case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+               // Don't know what to do in this case.
+-      } else {
+-              if (!dc_is_rmcm_3dlut_supported(hubp, mpc))
++              //case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
++              break;
++      case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM:
++              fl_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout,
++                              mcm_luts->lut3d_data.gpu_mem_params.size,
++                              &mode,
++                              &addr_mode,
++                              &width);
++
++              if (!dc_is_rmcm_3dlut_supported(hubp, mpc) ||
++                      !mpc->funcs->rmcm.is_config_supported(
++                              (width == hubp_3dlut_fl_width_17 ||
++                               width == hubp_3dlut_fl_width_transformed) ? 17 : 33))
+                       return false;
++              // setting native or transformed mode,
++              dc_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout, &mode, &addr_mode);
++
+               //seems to be only for the MCM
+-              mpc_fl_config.enabled                   = cm->flags.bits.lut3d_enable;
+-              mpc_fl_config.size                  = cm->lut3d_dma.size;
++              dc_get_lut_format(mcm_luts->lut3d_data.gpu_mem_params.format_params.format, &format);
++
++              dc_get_lut_xbar(
++                      mcm_luts->lut3d_data.gpu_mem_params.component_order,
++                      &crossbar_bit_slice_cr_r,
++                      &crossbar_bit_slice_y_g,
++                      &crossbar_bit_slice_cb_b);
++
++              fl_config.mode                                  = mode;
++              fl_config.enabled                               = lut3d_xable != MCM_LUT_DISABLE;
++              fl_config.address                               = mcm_luts->lut3d_data.gpu_mem_params.addr;
++              fl_config.format                                = format;
++              fl_config.crossbar_bit_slice_y_g  = crossbar_bit_slice_y_g;
++              fl_config.crossbar_bit_slice_cb_b = crossbar_bit_slice_cb_b;
++              fl_config.crossbar_bit_slice_cr_r = crossbar_bit_slice_cr_r;
++              fl_config.width                             = width;
++              fl_config.protection_bits               = rmcm_3dlut->protection_bits;
++              fl_config.addr_mode                         = addr_mode;
++              fl_config.layout                = mcm_luts->lut3d_data.gpu_mem_params.layout;
++              fl_config.bias  = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias;
++              fl_config.scale = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale;
++
++              mpc_fl_config.enabled                   = fl_config.enabled;
++              mpc_fl_config.width                 = width;
+               mpc_fl_config.select_lut_bank_a = lut_bank_a;
+-              mpc_fl_config.bit_depth             = 0;
++              mpc_fl_config.bit_depth             = mcm_luts->lut3d_data.gpu_mem_params.bit_depth;
+               mpc_fl_config.hubp_index                = hubp->inst;
+-              mpc_fl_config.bias      = cm->lut3d_dma.bias;
+-              mpc_fl_config.scale     = cm->lut3d_dma.scale;
++              mpc_fl_config.bias      = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias;
++              mpc_fl_config.scale     = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale;
+               //1. power down the block
+               mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, false);
+@@ -476,44 +679,268 @@ bool dcn42_program_rmcm_luts(
+               //2. program RMCM - 3dlut reg programming
+               mpc->funcs->rmcm.fl_3dlut_configure(mpc, &mpc_fl_config, mpcc_id);
+-              /* HUBP */
+-              if (hubp->funcs->hubp_program_3dlut_fl_config)
+-                      hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma);
+-
+-              if (hubp->funcs->hubp_program_3dlut_fl_addr)
+-                      hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr);
++              hubp->funcs->hubp_program_3dlut_fl_config(hubp, &fl_config);
+               //3. power on the block
+               mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, true);
++
++              break;
++      default:
++              return false;
+       }
+       return true;
+ }
+-bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx,
+-                              const struct dc_plane_state *plane_state)
++void dcn42_populate_mcm_luts(struct dc *dc,
++              struct pipe_ctx *pipe_ctx,
++              struct dc_cm2_func_luts mcm_luts,
++              bool lut_bank_a)
+ {
+-      struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc;
++      struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
+       struct hubp *hubp = pipe_ctx->plane_res.hubp;
+-      const struct dc_plane_cm *cm = &plane_state->cm;
+-      struct mpc *mpc = dc->res_pool->mpc;
+       int mpcc_id = hubp->inst;
+-      bool result;
+-
+-      /* MCM */
+-      result = dcn401_set_mcm_luts(pipe_ctx, plane_state);
+-
+-      /* RMCM */
+-      if (cm->flags.bits.rmcm_enable && cm->flags.bits.lut3d_dma_enable) {
+-              /* TODO - move RMCM to its own block */
++      struct mpc *mpc = dc->res_pool->mpc;
++      union mcm_lut_params m_lut_params;
++      enum dc_cm2_transfer_func_source lut3d_src = mcm_luts.lut3d_data.lut3d_src;
++      enum hubp_3dlut_fl_format format = 0;
++      enum hubp_3dlut_fl_mode mode;
++      enum hubp_3dlut_fl_width width = 0;
++      enum hubp_3dlut_fl_addressing_mode addr_mode;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0;
++      enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE;
++      enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE;
++      enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE;
++      bool rval;
++
++      dcn42_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
++
++      //MCM - setting its location (Before/After) blender
++      //set to post blend (true)
++      dcn42_set_mcm_location_post_blend(
++              dc,
++              pipe_ctx,
++              mcm_luts.lut3d_data.mpc_mcm_post_blend);
++
++      //RMCM - 3dLUT+Shaper
++      if (mcm_luts.lut3d_data.rmcm_3dlut_enable &&
++              is_rmcm_3dlut_fl_supported(dc, mcm_luts.lut3d_data.gpu_mem_params.size)) {
+               dcn42_program_rmcm_luts(
+                       hubp,
+                       pipe_ctx,
+-                      cm,
++                      lut3d_src,
++                      &mcm_luts,
+                       mpc,
++                      lut_bank_a,
+                       mpcc_id);
+       }
++      /* 1D LUT */
++      if (mcm_luts.lut1d_func) {
++              memset(&m_lut_params, 0, sizeof(m_lut_params));
++              if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL)
++                      m_lut_params.pwl = &mcm_luts.lut1d_func->pwl;
++              else if (mcm_luts.lut1d_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
++                      rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
++                                      mcm_luts.lut1d_func,
++                                      &dpp_base->regamma_params, false);
++                      m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
++              }
++              if (m_lut_params.pwl) {
++                      if (mpc->funcs->populate_lut)
++                              mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, m_lut_params, lut_bank_a, mpcc_id);
++              }
++              if (mpc->funcs->program_lut_mode)
++                      mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut1d_xable && m_lut_params.pwl, lut_bank_a, mpcc_id);
++      }
++
++      /* Shaper */
++      if (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) {
++              memset(&m_lut_params, 0, sizeof(m_lut_params));
++              if (mcm_luts.shaper->type == TF_TYPE_HWPWL)
++                      m_lut_params.pwl = &mcm_luts.shaper->pwl;
++              else if (mcm_luts.shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
++                      ASSERT(false);
++                      rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
++                                      mcm_luts.shaper,
++                                      &dpp_base->regamma_params, true);
++                      m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
++              }
++              if (m_lut_params.pwl) {
++                      if (mpc->funcs->mcm.populate_lut)
++                              mpc->funcs->mcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id);
++                      if (mpc->funcs->program_lut_mode)
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_ENABLE, lut_bank_a, mpcc_id);
++              }
++      }
++
++      /* 3DLUT */
++      switch (lut3d_src) {
++      case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
++              memset(&m_lut_params, 0, sizeof(m_lut_params));
++              if (hubp->funcs->hubp_enable_3dlut_fl)
++                      hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
++
++              if (mcm_luts.lut3d_data.lut3d_func && mcm_luts.lut3d_data.lut3d_func->state.bits.initialized) {
++                      m_lut_params.lut3d = &mcm_luts.lut3d_data.lut3d_func->lut_3d;
++                      if (mpc->funcs->populate_lut)
++                              mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, m_lut_params, lut_bank_a, mpcc_id);
++                      if (mpc->funcs->program_lut_mode)
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a,
++                                              mpcc_id);
++              }
++              break;
++      case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM:
++              switch (mcm_luts.lut3d_data.gpu_mem_params.size) {
++              case DC_CM2_GPU_MEM_SIZE_333333:
++                      width = hubp_3dlut_fl_width_33;
++                      break;
++              case DC_CM2_GPU_MEM_SIZE_171717:
++                      width = hubp_3dlut_fl_width_17;
++                      break;
++              case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
++                      width = hubp_3dlut_fl_width_transformed;
++                      break;
++              default:
++                      //TODO: Handle default case
++                      break;
++              }
++
++              //check for support
++              if (mpc->funcs->mcm.is_config_supported &&
++                      !mpc->funcs->mcm.is_config_supported(width))
++                      break;
++
++              if (mpc->funcs->program_lut_read_write_control)
++                      mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id);
++              if (mpc->funcs->program_lut_mode)
++                      mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id);
++
++              if (hubp->funcs->hubp_program_3dlut_fl_addr)
++                      hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr);
++
++              if (mpc->funcs->mcm.program_bit_depth)
++                      mpc->funcs->mcm.program_bit_depth(mpc, mcm_luts.lut3d_data.gpu_mem_params.bit_depth, mpcc_id);
++
++              dc_get_lut_mode(mcm_luts.lut3d_data.gpu_mem_params.layout, &mode, &addr_mode);
++              if (hubp->funcs->hubp_program_3dlut_fl_mode)
++                      hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode);
++
++              if (hubp->funcs->hubp_program_3dlut_fl_addressing_mode)
++                      hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode);
++
++              switch (mcm_luts.lut3d_data.gpu_mem_params.format_params.format) {
++              case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB:
++                      format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
++                      break;
++              case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB:
++                      format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
++                      break;
++              case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10:
++                      format = hubp_3dlut_fl_format_float_fp1_5_10;
++                      break;
++              }
++              if (hubp->funcs->hubp_program_3dlut_fl_format)
++                      hubp->funcs->hubp_program_3dlut_fl_format(hubp, format);
++              if (hubp->funcs->hubp_update_3dlut_fl_bias_scale &&
++                              mpc->funcs->mcm.program_bias_scale) {
++                      mpc->funcs->mcm.program_bias_scale(mpc,
++                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
++                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale,
++                              mpcc_id);
++                      hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp,
++                                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
++                                              mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale);
++              }
++
++              //navi 4x has a bug and r and blue are swapped and need to be worked around here in
++              //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x
++              dc_get_lut_xbar(
++                      mcm_luts.lut3d_data.gpu_mem_params.component_order,
++                      &crossbar_bit_slice_cr_r,
++                      &crossbar_bit_slice_y_g,
++                      &crossbar_bit_slice_cb_b);
++
++              if (hubp->funcs->hubp_program_3dlut_fl_crossbar)
++                      hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp,
++                                      crossbar_bit_slice_cr_r,
++                                      crossbar_bit_slice_y_g,
++                                      crossbar_bit_slice_cb_b);
++
++              if (mpc->funcs->mcm.program_lut_read_write_control)
++                      mpc->funcs->mcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, true, mpcc_id);
++
++              if (mpc->funcs->mcm.program_3dlut_size)
++                      mpc->funcs->mcm.program_3dlut_size(mpc, width, mpcc_id);
++
++              if (mpc->funcs->update_3dlut_fast_load_select)
++                      mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst);
++
++              if (hubp->funcs->hubp_enable_3dlut_fl)
++                      hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
++              else {
++                      if (mpc->funcs->program_lut_mode) {
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
++                              mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
++                      }
++              }
++              break;
++      }
++}
++
++bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx,
++                              const struct dc_plane_state *plane_state)
++{
++      struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
++      int mpcc_id = pipe_ctx->plane_res.hubp->inst;
++      struct dc *dc = pipe_ctx->stream_res.opp->ctx->dc;
++      struct mpc *mpc = dc->res_pool->mpc;
++      bool result;
++      const struct pwl_params *lut_params = NULL;
++      bool rval;
++
++      if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
++              dcn42_populate_mcm_luts(dc, pipe_ctx, plane_state->mcm_luts, plane_state->lut_bank_a);
++              return true;
++      }
++
++      mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
++      pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
++      // 1D LUT
++      if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
++              lut_params = &plane_state->blend_tf.pwl;
++      else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
++              rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
++                              &plane_state->blend_tf,
++                              &dpp_base->regamma_params, false);
++              lut_params = rval ? &dpp_base->regamma_params : NULL;
++      }
++      result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
++      lut_params = NULL;
++
++      // Shaper
++      if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL)
++              lut_params = &plane_state->in_shaper_func.pwl;
++      else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
++              // TODO: dpp_base replace
++              rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
++                              &plane_state->in_shaper_func,
++                              &dpp_base->shaper_params, true);
++              lut_params = rval ? &dpp_base->shaper_params : NULL;
++      }
++      result &= mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
++
++      // 3D
++      if (mpc->funcs->program_3dlut) {
++              if (plane_state->lut3d_func.state.bits.initialized == 1)
++                      result &= mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func.lut_3d, mpcc_id);
++              else
++                      result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id);
++      }
++
+       return result;
+ }
+ void dcn42_hardware_release(struct dc *dc)
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
+@@ -18,11 +18,18 @@ void dcn42_program_cm_hist(
+ bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx,
+       const struct dc_plane_state *plane_state);
++void dcn42_populate_mcm_luts(struct dc *dc,
++              struct pipe_ctx *pipe_ctx,
++              struct dc_cm2_func_luts mcm_luts,
++              bool lut_bank_a);
++
+ bool dcn42_program_rmcm_luts(
+       struct hubp *hubp,
+       struct pipe_ctx *pipe_ctx,
+-      const struct dc_plane_cm *cm,
++      enum dc_cm2_transfer_func_source lut3d_src,
++      struct dc_cm2_func_luts *mcm_luts,
+       struct mpc *mpc,
++      bool lut_bank_a,
+       int mpcc_id);
+ void dcn42_hardware_release(struct dc *dc);
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
+@@ -89,7 +89,7 @@ enum hubp_3dlut_fl_addressing_mode {
+ enum hubp_3dlut_fl_width {
+       hubp_3dlut_fl_width_17 = 17,
+       hubp_3dlut_fl_width_33 = 33,
+-      hubp_3dlut_fl_width_17_transformed    = 4916, //mpc default
++      hubp_3dlut_fl_width_transformed    = 4916, //mpc default
+ };
+ enum hubp_3dlut_fl_crossbar_bit_slice {
+@@ -99,6 +99,22 @@ enum hubp_3dlut_fl_crossbar_bit_slice {
+       hubp_3dlut_fl_crossbar_bit_slice_48_63 = 3
+ };
++struct hubp_fl_3dlut_config {
++      bool enabled;
++      enum hubp_3dlut_fl_width width;
++      enum hubp_3dlut_fl_mode mode;
++      enum hubp_3dlut_fl_format format;
++      uint16_t bias;
++      uint16_t scale;
++      struct dc_plane_address address;
++      enum hubp_3dlut_fl_addressing_mode addr_mode;
++      enum dc_cm2_gpu_mem_layout layout;
++      uint8_t protection_bits;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b;
++      enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r;
++};
++
+ struct hubp {
+       const struct hubp_funcs *funcs;
+       struct dc_context *ctx;
+@@ -273,15 +289,24 @@ struct hubp_funcs {
+       void (*hubp_wait_pipe_read_start)(struct hubp *hubp);
+       void (*hubp_program_mcache_id_and_split_coordinate)(struct hubp *hubp, struct dml2_hubp_pipe_mcache_regs *mcache_regs);
++      void (*hubp_update_3dlut_fl_bias_scale)(struct hubp *hubp, uint16_t bias, uint16_t scale);
++      void (*hubp_program_3dlut_fl_mode)(struct hubp *hubp,
++                      enum hubp_3dlut_fl_mode mode);
++      void (*hubp_program_3dlut_fl_format)(struct hubp *hubp,
++                      enum hubp_3dlut_fl_format format);
+       void (*hubp_program_3dlut_fl_addr)(struct hubp *hubp,
+-              const struct dc_plane_address *address);
+-      void (*hubp_program_3dlut_fl_config)(struct hubp *hubp,
+-              const struct dc_3dlut_dma *config);
++              const struct dc_plane_address address);
+       void (*hubp_program_3dlut_fl_dlg_param)(struct hubp *hubp, int refcyc_per_3dlut_group);
+       void (*hubp_enable_3dlut_fl)(struct hubp *hubp, bool enable);
++      void (*hubp_program_3dlut_fl_addressing_mode)(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode);
++      void (*hubp_program_3dlut_fl_width)(struct hubp *hubp, enum hubp_3dlut_fl_width width);
++      void (*hubp_program_3dlut_fl_tmz_protected)(struct hubp *hubp, uint8_t protection_bits);
+       void (*hubp_program_3dlut_fl_crossbar)(struct hubp *hubp,
+-                      enum dc_cm_lut_pixel_format format);
++                      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g,
++                      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b,
++                      enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r);
+       int (*hubp_get_3dlut_fl_done)(struct hubp *hubp);
++      void (*hubp_program_3dlut_fl_config)(struct hubp *hubp, struct hubp_fl_3dlut_config *cfg);
+       void (*hubp_clear_tiling)(struct hubp *hubp);
+       uint32_t (*hubp_get_current_read_line)(struct hubp *hubp);
+       uint32_t (*hubp_get_det_config_error)(struct hubp *hubp);
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
+@@ -54,7 +54,6 @@
+ #include "dc_hw_types.h"
+ #include "hw_shared.h"
+ #include "transform.h"
+-#include "dc_types.h"
+ #define MAX_MPCC 6
+ #define MAX_OPP 6
+@@ -102,6 +101,13 @@ enum mpcc_movable_cm_location {
+       MPCC_MOVABLE_CM_LOCATION_AFTER,
+ };
++enum MCM_LUT_XABLE {
++      MCM_LUT_DISABLE,
++      MCM_LUT_DISABLED = MCM_LUT_DISABLE,
++      MCM_LUT_ENABLE,
++      MCM_LUT_ENABLED = MCM_LUT_ENABLE,
++};
++
+ enum MCM_LUT_ID {
+       MCM_LUT_3DLUT,
+       MCM_LUT_1DLUT,
+@@ -110,7 +116,7 @@ enum MCM_LUT_ID {
+ struct mpc_fl_3dlut_config {
+       bool enabled;
+-      enum dc_cm_lut_size size;
++      uint16_t width;
+       bool select_lut_bank_a;
+       uint16_t bit_depth;
+       int hubp_index;
+@@ -1069,11 +1075,8 @@ struct mpc_funcs {
+       *
+       * void
+       */
+-      void (*populate_lut)(struct mpc *mpc,
+-                      const enum MCM_LUT_ID id,
+-                      const union mcm_lut_params *params,
+-                      const bool lut_bank_a,
+-                      const int mpcc_id);
++      void (*populate_lut)(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params,
++                      bool lut_bank_a, int mpcc_id);
+       /**
+       * @program_lut_read_write_control:
+@@ -1084,18 +1087,13 @@ struct mpc_funcs {
+       * - [in/out] mpc - MPC context.
+       * - [in] id
+       * - [in] lut_bank_a
+-      * - [in] bit_depth
+       * - [in] mpcc_id
+       *
+       * Return:
+       *
+       * void
+       */
+-      void (*program_lut_read_write_control)(struct mpc *mpc,
+-              const enum MCM_LUT_ID id,
+-              const bool lut_bank_a,
+-              const unsigned int bit_depth,
+-              const int mpcc_id);
++      void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id);
+       /**
+       * @program_lut_mode:
+@@ -1105,44 +1103,33 @@ struct mpc_funcs {
+       * Parameters:
+       * - [in/out] mpc - MPC context.
+       * - [in] id
+-      * - [in] enable
++      * - [in] xable
+       * - [in] lut_bank_a
+-      * - [in] size
+       * - [in] mpcc_id
+       *
+       * Return:
+       *
+       * void
+       */
+-      void (*program_lut_mode)(struct mpc *mpc,
+-                      const enum MCM_LUT_ID id,
+-                      const bool enable,
+-                      const bool lut_bank_a,
+-                      const enum dc_cm_lut_size size,
+-                      const int mpcc_id);
+-
++      void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_ID id, const enum MCM_LUT_XABLE xable,
++                      bool lut_bank_a, int mpcc_id);
+       /**
+-      * @get_lut_mode:
+-      *
+-      * Obtains enablement and ram bank status.
+-      *
+-      * Parameters:
+-      * - [in/out] mpc - MPC context.
+-      * - [in] id
+-      * - [in] mpcc_id
+-      * - [out] enable
+-      * - [out] lut_bank_a
+-      *
+-      * Return:
+-      *
+-      * void
+-      */
+-      void (*get_lut_mode)(struct mpc *mpc,
+-                      const enum MCM_LUT_ID id,
+-                      const int mpcc_id,
+-                      bool *enable,
+-                      bool *lut_bank_a);
++       * @mcm:
++       *
++       * MPC MCM new HW sequential programming functions
++       */
++      struct {
++              void (*program_3dlut_size)(struct mpc *mpc, uint32_t width, int mpcc_id);
++              void (*program_bias_scale)(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id);
++              void (*program_bit_depth)(struct mpc *mpc, uint16_t bit_depth, int mpcc_id);
++              bool (*is_config_supported)(uint32_t width);
++              void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id,
++                      bool lut_bank_a, bool enabled, int mpcc_id);
++
++              void (*populate_lut)(struct mpc *mpc, const union mcm_lut_params params,
++                      bool lut_bank_a, int mpcc_id);
++      } mcm;
+       /**
+        * @rmcm:
+@@ -1155,11 +1142,9 @@ struct mpc_funcs {
+               void (*update_3dlut_fast_load_select)(struct mpc *mpc, int mpcc_id, int hubp_idx);
+               void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id,
+                       bool lut_bank_a, bool enabled, int mpcc_id);
+-              void (*program_lut_mode)(struct mpc *mpc,
+-                      bool enable,
+-                      bool lut_bank_a,
+-                      int mpcc_id);
+-              void (*program_3dlut_size)(struct mpc *mpc, const enum dc_cm_lut_size size, int mpcc_id);
++              void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_XABLE xable,
++                      bool lut_bank_a, int mpcc_id);
++              void (*program_3dlut_size)(struct mpc *mpc, uint32_t width, int mpcc_id);
+               void (*program_bias_scale)(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id);
+               void (*program_bit_depth)(struct mpc *mpc, uint16_t bit_depth, int mpcc_id);
+               bool (*is_config_supported)(uint32_t width);
+--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
++++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
+@@ -73,15 +73,56 @@ void mpc401_set_movable_cm_location(stru
+       }
+ }
+-void mpc401_populate_lut(struct mpc *mpc,
+-              const enum MCM_LUT_ID id,
+-              const union mcm_lut_params *params,
+-              const bool lut_bank_a,
+-              const int mpcc_id)
++static enum dc_lut_mode get3dlut_config(
++                      struct mpc *mpc,
++                      bool *is_17x17x17,
++                      bool *is_12bits_color_channel,
++                      int mpcc_id)
++{
++      uint32_t i_mode, i_enable_10bits, lut_size;
++      enum dc_lut_mode mode;
++      struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
++
++      REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id],
++                      MPCC_MCM_3DLUT_MODE_CURRENT,  &i_mode);
++
++      REG_GET(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
++                      MPCC_MCM_3DLUT_30BIT_EN, &i_enable_10bits);
++
++      switch (i_mode) {
++      case 0:
++              mode = LUT_BYPASS;
++              break;
++      case 1:
++              mode = LUT_RAM_A;
++              break;
++      case 2:
++              mode = LUT_RAM_B;
++              break;
++      default:
++              mode = LUT_BYPASS;
++              break;
++      }
++      if (i_enable_10bits > 0)
++              *is_12bits_color_channel = false;
++      else
++              *is_12bits_color_channel = true;
++
++      REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &lut_size);
++
++      if (lut_size == 0)
++              *is_17x17x17 = true;
++      else
++              *is_17x17x17 = false;
++
++      return mode;
++}
++
++void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params, bool lut_bank_a, int mpcc_id)
+ {
+       const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B;
+-      const struct pwl_params *lut1d = params->pwl;
+-      const struct pwl_params *lut_shaper = params->pwl;
++      const struct pwl_params *lut1d = params.pwl;
++      const struct pwl_params *lut_shaper = params.pwl;
+       bool is_17x17x17;
+       bool is_12bits_color_channel;
+       const struct dc_rgb *lut0;
+@@ -90,7 +131,7 @@ void mpc401_populate_lut(struct mpc *mpc
+       const struct dc_rgb *lut3;
+       int lut_size0;
+       int lut_size;
+-      const struct tetrahedral_params *lut3d = params->lut3d;
++      const struct tetrahedral_params *lut3d = params.lut3d;
+       switch (id) {
+       case MCM_LUT_1DLUT:
+@@ -133,6 +174,8 @@ void mpc401_populate_lut(struct mpc *mpc
+               mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true);
++              get3dlut_config(mpc, &is_17x17x17, &is_12bits_color_channel, mpcc_id);
++
+               is_17x17x17 = !lut3d->use_tetrahedral_9;
+               is_12bits_color_channel = lut3d->use_12bits;
+               if (is_17x17x17) {
+@@ -155,6 +198,8 @@ void mpc401_populate_lut(struct mpc *mpc
+                                       sizeof(lut3d->tetrahedral_9.lut1[0]);
+                       }
++              mpc32_select_3dlut_ram(mpc, next_mode,
++                                      is_12bits_color_channel, mpcc_id);
+               mpc32_select_3dlut_ram_mask(mpc, 0x1, mpcc_id);
+               if (is_12bits_color_channel)
+                       mpc32_set3dlut_ram12(mpc, lut0, lut_size0, mpcc_id);
+@@ -187,69 +232,46 @@ void mpc401_populate_lut(struct mpc *mpc
+ }
+-static uint32_t mpc401_cm_lut_size_to_3dlut_size(const enum dc_cm_lut_size cm_size)
+-{
+-      uint32_t size = 0;
+-
+-      switch (cm_size) {
+-      case CM_LUT_SIZE_999:
+-              size = 1;
+-              break;
+-      case CM_LUT_SIZE_171717:
+-              size = 0;
+-              break;
+-      default:
+-              /* invalid LUT size */
+-              ASSERT(false);
+-              size = 0;
+-              break;
+-      }
+-
+-      return size;
+-}
+-
+ void mpc401_program_lut_mode(
+               struct mpc *mpc,
+               const enum MCM_LUT_ID id,
+-              const bool enable,
+-              const bool lut_bank_a,
+-              const enum dc_cm_lut_size size,
+-              const int mpcc_id)
++              const enum MCM_LUT_XABLE xable,
++              bool lut_bank_a,
++              int mpcc_id)
+ {
+-      uint32_t lut_size;
+       struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
+       switch (id) {
+       case MCM_LUT_3DLUT:
+-              if (enable) {
+-                      lut_size = mpc401_cm_lut_size_to_3dlut_size(size);
+-                      REG_UPDATE_2(MPCC_MCM_3DLUT_MODE[mpcc_id],
+-                                      MPCC_MCM_3DLUT_MODE, lut_bank_a ? 1 : 2,
+-                                      MPCC_MCM_3DLUT_SIZE, lut_size);
+-              } else {
+-                      if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+-                              mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false);
++              switch (xable) {
++              case MCM_LUT_DISABLE:
+                       REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, 0);
++                      break;
++              case MCM_LUT_ENABLE:
++                      REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, lut_bank_a ? 1 : 2);
++                      break;
+               }
+               break;
+       case MCM_LUT_SHAPER:
+-              if (enable) {
+-                      REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
+-              } else {
+-                      if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+-                              mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false);
++              switch (xable) {
++              case MCM_LUT_DISABLE:
+                       REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, 0);
++                      break;
++              case MCM_LUT_ENABLE:
++                      REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
++                      break;
+               }
+               break;
+       case MCM_LUT_1DLUT:
+-              if (enable) {
+-                      REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+-                                      MPCC_MCM_1DLUT_MODE, 2);
+-              } else {
+-                      if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+-                              mpc32_power_on_blnd_lut(mpc, mpcc_id, false);
++              switch (xable) {
++              case MCM_LUT_DISABLE:
+                       REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+                                       MPCC_MCM_1DLUT_MODE, 0);
++                      break;
++              case MCM_LUT_ENABLE:
++                      REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
++                                      MPCC_MCM_1DLUT_MODE, 2);
++                      break;
+               }
+               REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+                               MPCC_MCM_1DLUT_SELECT, lut_bank_a ? 0 : 1);
+@@ -257,20 +279,14 @@ void mpc401_program_lut_mode(
+       }
+ }
+-void mpc401_program_lut_read_write_control(struct mpc *mpc,
+-              const enum MCM_LUT_ID id,
+-              const bool lut_bank_a,
+-              const unsigned int bit_depth,
+-              const int mpcc_id)
++void mpc401_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id)
+ {
+       struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
+       switch (id) {
+       case MCM_LUT_3DLUT:
+               mpc32_select_3dlut_ram_mask(mpc, 0xf, mpcc_id);
+-              REG_UPDATE_2(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+-                              MPCC_MCM_3DLUT_30BIT_EN, (bit_depth == 10) ? 1 : 0,
+-                              MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1);
++              REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1);
+               break;
+       case MCM_LUT_SHAPER:
+               mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id);
+@@ -562,44 +578,6 @@ void mpc401_get_gamut_remap(struct mpc *
+               arr_reg_val, ARRAY_SIZE(arr_reg_val));
+ }
+-void mpc401_get_lut_mode(struct mpc *mpc,
+-              const enum MCM_LUT_ID id,
+-              const int mpcc_id,
+-              bool *enable,
+-              bool *lut_bank_a)
+-{
+-      struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
+-
+-      uint32_t lut_mode = 0;
+-      uint32_t lut_select = 0;
+-
+-      *enable = false;
+-      *lut_bank_a = true;
+-
+-      switch (id) {
+-      case MCM_LUT_SHAPER:
+-              REG_GET(MPCC_MCM_SHAPER_CONTROL[mpcc_id],
+-                              MPCC_MCM_SHAPER_MODE_CURRENT, &lut_mode);
+-              *enable = lut_mode != 0;
+-              *lut_bank_a = lut_mode != 2;
+-              break;
+-      case MCM_LUT_1DLUT:
+-              REG_GET_2(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+-                              MPCC_MCM_1DLUT_MODE_CURRENT, &lut_mode,
+-                              MPCC_MCM_1DLUT_SELECT_CURRENT, &lut_select);
+-              *enable = lut_mode != 0;
+-              *lut_bank_a = lut_mode == 0 || lut_select == 0;
+-              break;
+-      case MCM_LUT_3DLUT:
+-      default:
+-              REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id],
+-                              MPCC_MCM_3DLUT_MODE_CURRENT, &lut_mode);
+-              *enable = lut_mode != 0;
+-              *lut_bank_a = lut_mode != 2;
+-              break;
+-      }
+-}
+-
+ static const struct mpc_funcs dcn401_mpc_funcs = {
+       .read_mpcc_state = mpc1_read_mpcc_state,
+       .insert_plane = mpc1_insert_plane,
+@@ -638,7 +616,6 @@ static const struct mpc_funcs dcn401_mpc
+       .populate_lut = mpc401_populate_lut,
+       .program_lut_read_write_control = mpc401_program_lut_read_write_control,
+       .program_lut_mode = mpc401_program_lut_mode,
+-      .get_lut_mode = mpc401_get_lut_mode,
+ };
+--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h
++++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h
+@@ -206,32 +206,21 @@ void dcn401_mpc_construct(struct dcn401_
+       int num_rmu);
+ void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_location location, int mpcc_id);
+-void mpc401_populate_lut(struct mpc *mpc,
+-              const enum MCM_LUT_ID id,
+-              const union mcm_lut_params *params,
+-              bool lut_bank_a,
+-              int mpcc_id);
++void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params,
++              bool lut_bank_a, int mpcc_id);
+ void mpc401_program_lut_mode(
+               struct mpc *mpc,
+               const enum MCM_LUT_ID id,
+-              const bool enable,
+-              const bool lut_bank_a,
+-              const enum dc_cm_lut_size size,
+-              const int mpcc_id);
+-
+-void mpc401_get_lut_mode(struct mpc *mpc,
+-              const enum MCM_LUT_ID id,
+-              const int mpcc_id,
+-              bool *enable,
+-              bool *lut_bank_a);
++              const enum MCM_LUT_XABLE xable,
++              bool lut_bank_a,
++              int mpcc_id);
+ void mpc401_program_lut_read_write_control(
+               struct mpc *mpc,
+               const enum MCM_LUT_ID id,
+-              const bool lut_bank_a,
+-              const unsigned int bit_depth,
+-              const int mpcc_id);
++              bool lut_bank_a,
++              int mpcc_id);
+ void mpc401_set_gamut_remap(
+       struct mpc *mpc,
+--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c
++++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c
+@@ -63,6 +63,154 @@ void mpc42_update_blending(
+       mpcc->blnd_cfg = *blnd_cfg;
+ }
++/* Shaper functions */
++void mpc42_power_on_shaper_3dlut(
++      struct mpc *mpc,
++      uint32_t mpcc_id,
++      bool power_on)
++{
++      uint32_t power_status_shaper = 2;
++      uint32_t power_status_3dlut  = 2;
++      struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++      int max_retries = 10;
++
++      REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0,
++              MPCC_MCM_3DLUT_MEM_PWR_DIS, power_on == true ? 1:0);
++      REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0,
++              MPCC_MCM_SHAPER_MEM_PWR_DIS, power_on == true ? 1:0);
++      /* wait for memory to fully power up */
++      if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
++              REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
++              REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
++      }
++
++      /*read status is not mandatory, it is just for debugging*/
++      REG_GET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_SHAPER_MEM_PWR_STATE, &power_status_shaper);
++      REG_GET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
++
++      if (power_status_shaper != 0 && power_on == true)
++              BREAK_TO_DEBUGGER();
++
++      if (power_status_3dlut != 0 && power_on == true)
++              BREAK_TO_DEBUGGER();
++}
++
++void mpc42_configure_shaper_lut(
++      struct mpc *mpc,
++      bool is_ram_a,
++      uint32_t mpcc_id)
++{
++      struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++
++      REG_UPDATE(MPCC_MCM_SHAPER_SCALE_G_B[mpcc_id],
++              MPCC_MCM_SHAPER_SCALE_B, 0x7000);
++      REG_UPDATE(MPCC_MCM_SHAPER_SCALE_G_B[mpcc_id],
++              MPCC_MCM_SHAPER_SCALE_G, 0x7000);
++      REG_UPDATE(MPCC_MCM_SHAPER_SCALE_R[mpcc_id],
++              MPCC_MCM_SHAPER_SCALE_R, 0x7000);
++      REG_UPDATE(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
++                      MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, 7);
++      REG_UPDATE(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
++                      MPCC_MCM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
++      REG_SET(MPCC_MCM_SHAPER_LUT_INDEX[mpcc_id], 0, MPCC_MCM_SHAPER_LUT_INDEX, 0);
++}
++
++
++void mpc42_program_3dlut_size(struct mpc *mpc, uint32_t width, int mpcc_id)
++{
++      struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++      uint32_t size = 0xff;
++
++      REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &size);
++
++      REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE,
++              (width == 33) ? 2 :
++              (width == 17) ? 0 : 2);
++
++      REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &size);
++}
++
++void mpc42_program_3dlut_fl_bias_scale(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id)
++{
++      struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++
++      REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_R[mpcc_id],
++              MPCC_MCM_3DLUT_OUT_OFFSET_R, bias,
++              MPCC_MCM_3DLUT_OUT_SCALE_R, scale);
++
++      REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_G[mpcc_id],
++              MPCC_MCM_3DLUT_OUT_OFFSET_G, bias,
++              MPCC_MCM_3DLUT_OUT_SCALE_G, scale);
++
++      REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_B[mpcc_id],
++              MPCC_MCM_3DLUT_OUT_OFFSET_B, bias,
++              MPCC_MCM_3DLUT_OUT_SCALE_B, scale);
++}
++
++void mpc42_program_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_id)
++{
++      struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++
++      REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_WRITE_EN_MASK, 0xF);
++
++      //program bit_depth
++      REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
++              MPCC_MCM_3DLUT_30BIT_EN,
++              (bit_depth == 10) ? 1 : 0);
++}
++
++bool mpc42_is_config_supported(uint32_t width)
++{
++      if (width == 17)
++              return true;
++
++      return false;
++}
++
++void mpc42_populate_lut(struct mpc *mpc, const union mcm_lut_params params,
++      bool lut_bank_a, int mpcc_id)
++{
++      const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B;
++      const struct pwl_params *lut_shaper = params.pwl;
++
++      if (lut_shaper == NULL)
++              return;
++      if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
++              mpc42_power_on_shaper_3dlut(mpc, mpcc_id, true);
++
++      mpc42_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, mpcc_id);
++
++      if (next_mode == LUT_RAM_A)
++              mpc32_program_shaper_luta_settings(mpc, lut_shaper, mpcc_id);
++      else
++              mpc32_program_shaper_lutb_settings(mpc, lut_shaper, mpcc_id);
++
++      mpc32_program_shaper_lut(
++                      mpc, lut_shaper->rgb_resulted, lut_shaper->hw_points_num, mpcc_id);
++
++      mpc42_power_on_shaper_3dlut(mpc, mpcc_id, false);
++}
++
++void mpc42_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id,
++      bool lut_bank_a, bool enabled, int mpcc_id)
++{
++      struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++
++      switch (id) {
++      case MCM_LUT_3DLUT:
++              REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE,
++                      (!enabled) ? 0 :
++                      (lut_bank_a) ? 1 : 2);
++              REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1);
++              break;
++      case MCM_LUT_SHAPER:
++              mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id);
++              break;
++      default:
++              break;
++      }
++}
++
+ /* RMCM Shaper functions */
+ void mpc42_power_on_rmcm_shaper_3dlut(
+       struct mpc *mpc,
+@@ -526,47 +674,32 @@ void mpc42_program_rmcm_lut_read_write_c
+       }
+ }
+-void mpc42_program_lut_mode(struct mpc *mpc,
+-      bool enable,
+-      bool lut_bank_a,
+-      int mpcc_id)
++void mpc42_program_lut_mode(struct mpc *mpc, const enum MCM_LUT_XABLE xable,
++      bool lut_bank_a, int mpcc_id)
+ {
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+-      if (enable) {
+-              REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
+-      } else {
++      switch (xable) {
++      case MCM_LUT_DISABLE:
+               REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, 0);
+-      }
+-}
+-
+-static uint32_t mpc42_get_rmcm_3dlut_width(
+-              const enum dc_cm_lut_size size)
+-{
+-      uint32_t width = 0;
+-
+-      switch (size) {
+-      case CM_LUT_SIZE_333333:
+-              width = 2;
+               break;
+-      case CM_LUT_SIZE_171717:
+-      default:
+-              width = 0;
++      case MCM_LUT_ENABLE:
++              REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
+               break;
+       }
+-
+-      return width;
+ }
+-void mpc42_program_rmcm_3dlut_size(struct mpc *mpc,
+-              const enum dc_cm_lut_size size,
+-              int mpcc_id)
++void mpc42_program_rmcm_3dlut_size(struct mpc *mpc, uint32_t width, int mpcc_id)
+ {
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+-      uint32_t width = mpc42_get_rmcm_3dlut_width(size);
++      uint32_t size = 0xff;
++
++      REG_GET(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE, &size);
+-      REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id],
+-                      MPC_RMCM_3DLUT_SIZE, width);
++      REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE,
++              (width == 33) ? 2 : 0);
++
++      REG_GET(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE, &size);
+ }
+ void mpc42_program_rmcm_3dlut_fast_load_bias_scale(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id)
+@@ -598,6 +731,14 @@ void mpc42_program_rmcm_bit_depth(struct
+               (bit_depth == 10) ? 1 : 0);
+ }
++bool mpc42_is_rmcm_config_supported(uint32_t width)
++{
++      if (width == 17 || width == 33)
++              return true;
++
++      return false;
++}
++
+ void mpc42_set_fl_config(
+       struct mpc *mpc,
+       struct mpc_fl_3dlut_config *cfg,
+@@ -605,7 +746,6 @@ void mpc42_set_fl_config(
+ {
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+-      uint32_t width = mpc42_get_rmcm_3dlut_width(cfg->size);
+       /*
+       From: Jie Zhou
+@@ -646,7 +786,7 @@ void mpc42_set_fl_config(
+       //width
+       REG_UPDATE_2(MPC_RMCM_3DLUT_MODE[mpcc_id],
+-              MPC_RMCM_3DLUT_SIZE, width,
++              MPC_RMCM_3DLUT_SIZE, (cfg->width == 33) ? 2 : 0,
+               MPC_RMCM_3DLUT_MODE, (!cfg->enabled) ? 0 : (cfg->select_lut_bank_a) ? 1 : 2);
+       //connect to hubp
+@@ -659,6 +799,182 @@ void mpc42_set_fl_config(
+       REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, cfg->enabled ? 0 : 0xF);
+ }
++//static void rmcm_program_gamut_remap(
++//    struct mpc *mpc,
++//    unsigned int mpcc_id,
++//    const uint16_t *regval,
++//    enum mpcc_gamut_remap_id gamut_remap_block_id,
++//    enum mpcc_gamut_remap_mode_select mode_select)
++//{
++//    struct color_matrices_reg gamut_regs;
++//    struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++//
++//    if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP ||
++//            gamut_remap_block_id == MPCC_MCM_FIRST_GAMUT_REMAP ||
++//            gamut_remap_block_id == MPCC_MCM_SECOND_GAMUT_REMAP) {
++//            mpc_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
++//            return;
++//    }
++//    if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP) {
++//
++//            if (regval == NULL || mode_select == MPCC_GAMUT_REMAP_MODE_SELECT_0) {
++//                    REG_SET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], 0,
++//                            MPC_RMCM_GAMUT_REMAP_MODE, mode_select);
++//                    return;
++//            }
++//
++//            gamut_regs.shifts.csc_c11 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C11_A;
++//            gamut_regs.masks.csc_c11 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C11_A;
++//            gamut_regs.shifts.csc_c12 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C12_A;
++//            gamut_regs.masks.csc_c12 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C12_A;
++//
++//            switch (mode_select) {
++//            case MPCC_GAMUT_REMAP_MODE_SELECT_1:
++//                    gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_A[mpcc_id]);
++//                    gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_A[mpcc_id]);
++//                    break;
++//            case MPCC_GAMUT_REMAP_MODE_SELECT_2:
++//                    gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_B[mpcc_id]);
++//                    gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_B[mpcc_id]);
++//                    break;
++//            default:
++//                    break;
++//            }
++//
++//            cm_helper_program_color_matrices(
++//                    mpc->ctx,
++//                    regval,
++//                    &gamut_regs);
++//
++//            //select coefficient set to use, set A (MODE_1) or set B (MODE_2)
++//            REG_SET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], 0, MPC_RMCM_GAMUT_REMAP_MODE, mode_select);
++//    }
++//}
++
++//static bool is_mpc_legacy_gamut_id(enum mpcc_gamut_remap_id gamut_remap_block_id)
++//{
++//    if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP ||
++//            gamut_remap_block_id == MPCC_MCM_FIRST_GAMUT_REMAP ||
++//            gamut_remap_block_id == MPCC_MCM_SECOND_GAMUT_REMAP) {
++//            return true;
++//    }
++//    return false;
++//}
++//static void program_gamut_remap(
++//    struct mpc *mpc,
++//    unsigned int mpcc_id,
++//    const uint16_t *regval,
++//    enum mpcc_gamut_remap_id gamut_remap_block_id,
++//    enum mpcc_gamut_remap_mode_select mode_select)
++//{
++//    if (is_mpc_legacy_gamut_id(gamut_remap_block_id))
++//            mpc_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
++//    else
++//            rmcm_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
++//}
++
++//void mpc42_set_gamut_remap(
++//    struct mpc *mpc,
++//    int mpcc_id,
++//    const struct mpc_grph_gamut_adjustment *adjust)
++//{
++//    struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++//    unsigned int i = 0;
++//    uint32_t mode_select = 0;
++//
++//    if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) {
++//            /* Bypass / Disable if type is bypass or hw */
++//            program_gamut_remap(mpc, mpcc_id, NULL,
++//                    adjust->mpcc_gamut_remap_block_id, MPCC_GAMUT_REMAP_MODE_SELECT_0);
++//    } else {
++//            struct fixed31_32 arr_matrix[12];
++//            uint16_t arr_reg_val[12];
++//
++//            for (i = 0; i < 12; i++)
++//                    arr_matrix[i] = adjust->temperature_matrix[i];
++//
++//            convert_float_matrix(arr_reg_val, arr_matrix, 12);
++//
++//            if (is_mpc_legacy_gamut_id(adjust->mpcc_gamut_remap_block_id))
++//                    REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id],
++//                            MPCC_GAMUT_REMAP_MODE_CURRENT, &mode_select);
++//            else
++//                    REG_GET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id],
++//                            MPC_RMCM_GAMUT_REMAP_MODE_CURRENT, &mode_select);
++//
++//            //If current set in use not set A (MODE_1), then use set A, otherwise use set B
++//            if (mode_select != MPCC_GAMUT_REMAP_MODE_SELECT_1)
++//                    mode_select = MPCC_GAMUT_REMAP_MODE_SELECT_1;
++//            else
++//                    mode_select = MPCC_GAMUT_REMAP_MODE_SELECT_2;
++//
++//            program_gamut_remap(mpc, mpcc_id, arr_reg_val,
++//                    adjust->mpcc_gamut_remap_block_id, mode_select);
++//    }
++//}
++
++//static void read_gamut_remap(struct mpc *mpc,
++//    int mpcc_id,
++//    uint16_t *regval,
++//    enum mpcc_gamut_remap_id gamut_remap_block_id,
++//    uint32_t *mode_select)
++//{
++//    struct color_matrices_reg gamut_regs = {0};
++//    struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
++//
++//    if (is_mpc_legacy_gamut_id(gamut_remap_block_id)) {
++//            mpc_read_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
++//    }
++//    if (gamut_remap_block_id == MPCC_RMCM_GAMUT_REMAP) {
++//            //current coefficient set in use
++//            REG_GET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], MPC_RMCM_GAMUT_REMAP_MODE, mode_select);
++//
++//            gamut_regs.shifts.csc_c11 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C11_A;
++//            gamut_regs.masks.csc_c11 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C11_A;
++//            gamut_regs.shifts.csc_c12 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C12_A;
++//            gamut_regs.masks.csc_c12 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C12_A;
++//
++//            switch (*mode_select) {
++//            case MPCC_GAMUT_REMAP_MODE_SELECT_1:
++//                    gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_A[mpcc_id]);
++//                    gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_A[mpcc_id]);
++//                    break;
++//            case MPCC_GAMUT_REMAP_MODE_SELECT_2:
++//                    gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_B[mpcc_id]);
++//                    gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_B[mpcc_id]);
++//                    break;
++//            default:
++//                    break;
++//            }
++//    }
++//
++//    if (*mode_select != MPCC_GAMUT_REMAP_MODE_SELECT_0) {
++//            cm_helper_read_color_matrices(
++//                    mpc42->base.ctx,
++//                    regval,
++//                    &gamut_regs);
++//    }
++//}
++
++//void mpc42_get_gamut_remap(struct mpc *mpc,
++//    int mpcc_id,
++//    struct mpc_grph_gamut_adjustment *adjust)
++//{
++//    uint16_t arr_reg_val[12] = {0};
++//    uint32_t mode_select;
++//
++//    read_gamut_remap(mpc, mpcc_id, arr_reg_val, adjust->mpcc_gamut_remap_block_id, &mode_select);
++//
++//    if (mode_select == MPCC_GAMUT_REMAP_MODE_SELECT_0) {
++//            adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
++//            return;
++//    }
++//
++//    adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
++//    convert_hw_matrix(adjust->temperature_matrix,
++//            arr_reg_val, ARRAY_SIZE(arr_reg_val));
++//}
++
+ void mpc42_read_mpcc_state(
+               struct mpc *mpc,
+               int mpcc_inst,
+@@ -755,7 +1071,14 @@ static const struct mpc_funcs dcn42_mpc_
+       .populate_lut = mpc401_populate_lut,
+       .program_lut_read_write_control = mpc401_program_lut_read_write_control,
+       .program_lut_mode = mpc401_program_lut_mode,
+-      .get_lut_mode = mpc401_get_lut_mode,
++      .mcm = {
++              .program_lut_read_write_control = mpc42_program_lut_read_write_control,
++              .program_3dlut_size = mpc42_program_3dlut_size,
++              .program_bias_scale = mpc42_program_3dlut_fl_bias_scale,
++              .program_bit_depth = mpc42_program_bit_depth,
++              .is_config_supported = mpc42_is_config_supported,
++              .populate_lut = mpc42_populate_lut,
++      },
+       .rmcm = {
+               .enable_3dlut_fl = mpc42_enable_3dlut_fl,
+               .update_3dlut_fast_load_select = mpc42_update_3dlut_fast_load_select,
+@@ -764,6 +1087,7 @@ static const struct mpc_funcs dcn42_mpc_
+               .program_3dlut_size = mpc42_program_rmcm_3dlut_size,
+               .program_bias_scale = mpc42_program_rmcm_3dlut_fast_load_bias_scale,
+               .program_bit_depth = mpc42_program_rmcm_bit_depth,
++              .is_config_supported = mpc42_is_rmcm_config_supported,
+               .power_on_shaper_3dlut = mpc42_power_on_rmcm_shaper_3dlut,
+               .populate_lut = mpc42_populate_rmcm_lut,
+               .fl_3dlut_configure = mpc42_set_fl_config,
+--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h
++++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h
+@@ -884,6 +884,49 @@ void dcn42_mpc_construct(struct dcn42_mp
+ void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst);
++void mpc42_program_shaper_lutb_settings(
++      struct mpc *mpc,
++      const struct pwl_params *params,
++      uint32_t mpcc_id);
++void mpc42_program_shaper_luta_settings(
++              struct mpc *mpc,
++              const struct pwl_params *params,
++              uint32_t mpcc_id);
++void mpc42_configure_shaper_lut(
++              struct mpc *mpc,
++              bool is_ram_a,
++              uint32_t mpcc_id);
++void mpc42_power_on_shaper_3dlut(
++              struct mpc *mpc,
++              uint32_t mpcc_id,
++              bool power_on);
++void mpc42_program_3dlut_size(
++              struct mpc *mpc,
++              uint32_t width,
++              int mpcc_id);
++void mpc42_program_3dlut_fl_bias_scale(
++              struct mpc *mpc,
++              uint16_t bias,
++              uint16_t scale,
++              int mpcc_id);
++void mpc42_program_bit_depth(
++              struct mpc *mpc,
++              uint16_t bit_depth,
++              int mpcc_id);
++void mpc42_populate_lut(
++              struct mpc *mpc,
++              const union mcm_lut_params params,
++              bool lut_bank_a,
++              int mpcc_id);
++void mpc42_program_lut_read_write_control(
++              struct mpc *mpc,
++              const enum MCM_LUT_ID id,
++              bool lut_bank_a,
++              bool enabled,
++              int mpcc_id);
++
++bool mpc42_is_config_supported(uint32_t width);
++
+ /* RMCM */
+ void mpc42_program_rmcm_shaper_lut(
+               struct mpc *mpc,
+@@ -927,12 +970,12 @@ void mpc42_program_rmcm_lut_read_write_c
+               int mpcc_id);
+ void mpc42_program_lut_mode(
+               struct mpc *mpc,
+-              bool enable,
++              const enum MCM_LUT_XABLE xable,
+               bool lut_bank_a,
+               int mpcc_id);
+ void mpc42_program_rmcm_3dlut_size(
+               struct mpc *mpc,
+-              const enum dc_cm_lut_size size,
++              uint32_t width,
+               int mpcc_id);
+ void mpc42_program_rmcm_3dlut_fast_load_bias_scale(
+               struct mpc *mpc,
+@@ -944,6 +987,8 @@ void mpc42_program_rmcm_bit_depth(
+               uint16_t bit_depth,
+               int mpcc_id);
++bool mpc42_is_rmcm_config_supported(uint32_t width);
++
+ void mpc42_set_fl_config(
+       struct mpc *mpc,
+       struct mpc_fl_3dlut_config *cfg,
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
+@@ -666,7 +666,6 @@ static const struct resource_caps res_ca
+       .num_vmid = 16,
+       .num_mpc_3dlut = 2,
+       .num_dsc = 4,
+-      .num_rmcm = 2,
+ };
+ static const struct dc_plane_cap plane_cap = {
index 5952a84f17577bd03bab653f001e348b2529b173..a3b3cc50ec7f28ce99cb5734b34f837208a38a84 100644 (file)
@@ -2072,3 +2072,4 @@ exfat-add-balloc-parameter-to-exfat_map_cluster-for-iomap-support.patch
 exfat-add-data_start_bytes-and-exfat_cluster_to_phys_bytes-helper.patch
 exfat-fix-implicit-declaration-of-brelse.patch
 iomap-consolidate-bio-submission.patch
+drm-amd-display-fix-color-manager-3dlut-shaper-blend.patch