From: Greg Kroah-Hartman Date: Tue, 21 Jul 2026 13:15:27 +0000 (+0200) Subject: 7.1-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c508d1e72f928f843d0126fad72a572f16344e5;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches added patches: drm-amd-display-fix-color-manager-3dlut-shaper-blend.patch --- 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 index 0000000000..5d17c86dc5 --- /dev/null +++ b/queue-7.1/drm-amd-display-fix-color-manager-3dlut-shaper-blend.patch @@ -0,0 +1,2884 @@ +From 12f58a6caad3be54d7788b338b3f57d7c17bbef7 Mon Sep 17 00:00:00 2001 +From: Dillon Varone +Date: Thu, 19 Mar 2026 11:57:08 -0400 +Subject: drm/amd/display: Fix Color Manager (3DLUT, Shaper, Blend) + +From: Dillon Varone + +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 +Signed-off-by: Dillon Varone +Signed-off-by: James Lin +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman +--- + 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 = { diff --git a/queue-7.1/series b/queue-7.1/series index 5952a84f17..a3b3cc50ec 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -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