Commit 90f33674 authored by Martin Leung's avatar Martin Leung Committed by Alex Deucher
Browse files

drm/amd/display: Prepare for new interfaces



[WHY]:
Lut pipeline will be hooked up differently in some asics
need to add new interfaces and missing registers.

[HOW]:
Add missing registers and hook up programming from DPP for pre-blend
lut.

Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarMartin Leung <Martin.Leung@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 85f4bc0c
Loading
Loading
Loading
Loading
+105 −1
Original line number Diff line number Diff line
@@ -283,6 +283,7 @@
	uint32_t MPC_OUT_CSC_COEF_FORMAT

#define MPC_REG_VARIABLE_LIST_DCN32 \
	uint32_t MPCC_MOVABLE_CM_LOCATION_CONTROL[MAX_MPCC]; \
	uint32_t MPCC_MCM_SHAPER_CONTROL[MAX_MPCC]; \
	uint32_t MPCC_MCM_SHAPER_OFFSET_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_SHAPER_OFFSET_G[MAX_MPCC]; \
@@ -347,6 +348,80 @@
	uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_CONTROL[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_LUT_INDEX[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_LUT_DATA[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_LUT_CONTROL[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_CNTL_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_CNTL_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_CNTL_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL1_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL2_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL1_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL2_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL1_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL2_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_OFFSET_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_OFFSET_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_OFFSET_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_0_1[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_2_3[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_4_5[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_6_7[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_8_9[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_10_11[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_12_13[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_14_15[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_16_17[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_18_19[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_20_21[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_22_23[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_24_25[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_26_27[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_28_29[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_30_31[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMA_REGION_32_33[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_CNTL_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_CNTL_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_CNTL_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL1_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL2_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL1_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL2_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL1_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL2_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_OFFSET_B[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_OFFSET_G[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_OFFSET_R[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_0_1[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_2_3[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_4_5[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_6_7[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_8_9[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_10_11[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_12_13[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_14_15[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_16_17[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_18_19[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_20_21[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_22_23[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_24_25[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_26_27[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_28_29[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_30_31[MAX_MPCC]; \
	uint32_t MPCC_MCM_1DLUT_RAMB_REGION_32_33[MAX_MPCC]; \
	uint32_t MPCC_MCM_MEM_PWR_CTRL[MAX_MPCC]

#define MPC_COMMON_MASK_SH_LIST_DCN3_0(mask_sh) \
@@ -648,6 +723,8 @@
	type MPC_RMU_SHAPER_MODE_CURRENT

#define MPC_REG_FIELD_LIST_DCN32(type) \
	type MPCC_MOVABLE_CM_LOCATION_CNTL;\
	type MPCC_MOVABLE_CM_LOCATION_CNTL_CURRENT;\
	type MPCC_MCM_SHAPER_MEM_PWR_FORCE;\
	type MPCC_MCM_SHAPER_MEM_PWR_DIS;\
	type MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE;\
@@ -692,7 +769,34 @@
	type MPCC_MCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\
	type MPCC_MCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\
	type MPCC_MCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET;\
	type MPCC_MCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS
	type MPCC_MCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS; \
	type MPCC_MCM_1DLUT_MODE;\
	type MPCC_MCM_1DLUT_SELECT;\
	type MPCC_MCM_1DLUT_PWL_DISABLE;\
	type MPCC_MCM_1DLUT_MODE_CURRENT;\
	type MPCC_MCM_1DLUT_SELECT_CURRENT;\
	type MPCC_MCM_1DLUT_LUT_INDEX;\
	type MPCC_MCM_1DLUT_LUT_DATA;\
	type MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK;\
	type MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL;\
	type MPCC_MCM_1DLUT_LUT_READ_DBG;\
	type MPCC_MCM_1DLUT_LUT_HOST_SEL;\
	type MPCC_MCM_1DLUT_LUT_CONFIG_MODE;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SEGMENT_B;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SLOPE_B;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_BASE_B;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_BASE_B;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_B;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_SLOPE_B;\
	type MPCC_MCM_1DLUT_RAMA_OFFSET_B;\
	type MPCC_MCM_1DLUT_RAMA_OFFSET_G;\
	type MPCC_MCM_1DLUT_RAMA_OFFSET_R;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION0_LUT_OFFSET;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION0_NUM_SEGMENTS;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION1_LUT_OFFSET;\
	type MPCC_MCM_1DLUT_RAMA_EXP_REGION1_NUM_SEGMENTS


#define MPC_COMMON_MASK_SH_LIST_DCN303(mask_sh) \
	MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh),\
+91 −0
Original line number Diff line number Diff line
@@ -502,6 +502,97 @@ static bool dcn32_set_mpc_shaper_3dlut(

	return result;
}

bool dcn32_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 mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
	bool result = true;
	struct pwl_params *lut_params = NULL;

	// 1D LUT
	if (plane_state->blend_tf) {
		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) {
			cm_helper_translate_curve_to_hw_format(
					plane_state->blend_tf,
					&dpp_base->regamma_params, false);
			lut_params = &dpp_base->regamma_params;
		}
	}
	result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);

	// Shaper
	if (plane_state->in_shaper_func) {
		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
			ASSERT(false);
			cm_helper_translate_curve_to_hw_format(
					plane_state->in_shaper_func,
					&dpp_base->shaper_params, true);
			lut_params = &dpp_base->shaper_params;
		}
	}

	result = mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);

	// 3D
	if (plane_state->lut3d_func && 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;
}

bool dcn32_set_input_transfer_func(struct dc *dc,
				struct pipe_ctx *pipe_ctx,
				const struct dc_plane_state *plane_state)
{
	struct dce_hwseq *hws = dc->hwseq;
	struct mpc *mpc = dc->res_pool->mpc;
	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;

	enum dc_transfer_func_predefined tf;
	bool result = true;
	struct pwl_params *params = NULL;

	if (mpc == NULL || plane_state == NULL)
		return false;

	tf = TRANSFER_FUNCTION_UNITY;

	if (plane_state->in_transfer_func &&
		plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED)
		tf = plane_state->in_transfer_func->tf;

	dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);

	if (plane_state->in_transfer_func) {
		if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL)
			params = &plane_state->in_transfer_func->pwl;
		else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS &&
			cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func,
					&dpp_base->degamma_params, false))
			params = &dpp_base->degamma_params;
	}

	result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);

	if (result &&
			pipe_ctx->stream_res.opp &&
			pipe_ctx->stream_res.opp->ctx &&
			hws->funcs.set_mcm_luts)
		result = hws->funcs.set_mcm_luts(pipe_ctx, plane_state);

	return result;
}

bool dcn32_set_output_transfer_func(struct dc *dc,
				struct pipe_ctx *pipe_ctx,
				const struct dc_stream_state *stream)
+7 −0
Original line number Diff line number Diff line
@@ -47,6 +47,13 @@ void dcn32_cab_for_ss_control(struct dc *dc, bool enable);

void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context);

bool dcn32_set_mcm_luts(struct pipe_ctx *pipe_ctx,
				const struct dc_plane_state *plane_state);

bool dcn32_set_input_transfer_func(struct dc *dc,
				struct pipe_ctx *pipe_ctx,
				const struct dc_plane_state *plane_state);

bool dcn32_set_output_transfer_func(struct dc *dc,
				struct pipe_ctx *pipe_ctx,
				const struct dc_stream_state *stream);
+2 −3
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
	.update_plane_addr = dcn20_update_plane_addr,
	.plane_atomic_disconnect = dcn10_plane_atomic_disconnect,
	.update_mpcc = dcn20_update_mpcc,
	.set_input_transfer_func = dcn30_set_input_transfer_func,
	.set_input_transfer_func = dcn32_set_input_transfer_func,
	.set_output_transfer_func = dcn32_set_output_transfer_func,
	.power_down = dce110_power_down,
	.enable_display_power_gating = dcn10_dummy_display_power_gating,
@@ -137,8 +137,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
	.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
	.wait_for_blank_complete = dcn20_wait_for_blank_complete,
	.dccg_init = dcn20_dccg_init,
	.set_blend_lut = dcn30_set_blend_lut,
	.set_shaper_3dlut = dcn20_set_shaper_3dlut,
	.set_mcm_luts = dcn32_set_mcm_luts,
	.program_mall_pipe_config = dcn32_program_mall_pipe_config,
	.subvp_update_force_pstate = dcn32_subvp_update_force_pstate,
	.update_mall_sel = dcn32_update_mall_sel,
+235 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@
#include "reg_helper.h"
#include "dcn30/dcn30_mpc.h"
#include "dcn30/dcn30_cm_common.h"
#include "dcn30/dcn30_mpc.h"
#include "dcn32_mpc.h"
#include "basics/conversion.h"
#include "dcn10/dcn10_cm_common.h"
#include "dc.h"
@@ -64,6 +64,235 @@ static void mpc32_mpc_init(struct mpc *mpc)
	}
}

static void mpc32_power_on_blnd_lut(
	struct mpc *mpc,
	uint32_t mpcc_id,
	bool power_on)
{
	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);

	if (mpc->ctx->dc->debug.enable_mem_low_power.bits.cm) {
		if (power_on) {
			REG_UPDATE(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_FORCE, 0);
			REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_STATE, 0, 1, 5);
		} else {
			ASSERT(false);
			/* TODO: change to mpc
			 *  dpp_base->ctx->dc->optimized_required = true;
			 *  dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true;
			 */
		}
	} else {
		REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0,
				MPCC_MCM_1DLUT_MEM_PWR_FORCE, power_on == true ? 0 : 1);
	}
}

static enum dc_lut_mode mpc32_get_post1dlut_current(struct mpc *mpc, uint32_t mpcc_id)
{
	enum dc_lut_mode mode;
	uint32_t mode_current = 0;
	uint32_t in_use = 0;

	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);

	REG_GET(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
			MPCC_MCM_1DLUT_MODE_CURRENT, &mode_current);
	REG_GET(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
			MPCC_MCM_1DLUT_SELECT_CURRENT, &in_use);

	switch (mode_current) {
	case 0:
	case 1:
		mode = LUT_BYPASS;
		break;

	case 2:
		if (in_use == 0)
			mode = LUT_RAM_A;
		else
			mode = LUT_RAM_B;
		break;
	default:
		mode = LUT_BYPASS;
		break;
	}
	return mode;
}

static void mpc32_configure_post1dlut(
		struct mpc *mpc,
		uint32_t mpcc_id,
		bool is_ram_a)
{
	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);

	//TODO: this
	REG_UPDATE_2(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id],
			MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 7,
			MPCC_MCM_1DLUT_LUT_HOST_SEL, is_ram_a == true ? 0 : 1);

	REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0);
}

static void mpc32_post1dlut_get_reg_field(
		struct dcn30_mpc *mpc,
		struct dcn3_xfer_func_reg *reg)
{
	reg->shifts.exp_region0_lut_offset = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION0_LUT_OFFSET;
	reg->masks.exp_region0_lut_offset = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION0_LUT_OFFSET;
	reg->shifts.exp_region0_num_segments = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION0_NUM_SEGMENTS;
	reg->masks.exp_region0_num_segments = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION0_NUM_SEGMENTS;
	reg->shifts.exp_region1_lut_offset = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION1_LUT_OFFSET;
	reg->masks.exp_region1_lut_offset = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION1_LUT_OFFSET;
	reg->shifts.exp_region1_num_segments = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION1_NUM_SEGMENTS;
	reg->masks.exp_region1_num_segments = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION1_NUM_SEGMENTS;

	reg->shifts.field_region_end = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_B;
	reg->masks.field_region_end = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_B;
	reg->shifts.field_region_end_slope = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_SLOPE_B;
	reg->masks.field_region_end_slope = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_SLOPE_B;
	reg->shifts.field_region_end_base = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_BASE_B;
	reg->masks.field_region_end_base = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_BASE_B;
	reg->shifts.field_region_linear_slope = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SLOPE_B;
	reg->masks.field_region_linear_slope = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SLOPE_B;
	reg->shifts.exp_region_start = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B;
	reg->masks.exp_region_start = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B;
	reg->shifts.exp_resion_start_segment = mpc->mpc_shift->MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SEGMENT_B;
	reg->masks.exp_resion_start_segment = mpc->mpc_mask->MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SEGMENT_B;
}

/*program blnd lut RAM A*/
static void mpc32_program_post1dluta_settings(
		struct mpc *mpc,
		uint32_t mpcc_id,
		const struct pwl_params *params)
{
	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
	struct dcn3_xfer_func_reg gam_regs;

	mpc32_post1dlut_get_reg_field(mpc30, &gam_regs);

	gam_regs.start_cntl_b = REG(MPCC_MCM_1DLUT_RAMA_START_CNTL_B[mpcc_id]);
	gam_regs.start_cntl_g = REG(MPCC_MCM_1DLUT_RAMA_START_CNTL_G[mpcc_id]);
	gam_regs.start_cntl_r = REG(MPCC_MCM_1DLUT_RAMA_START_CNTL_R[mpcc_id]);
	gam_regs.start_slope_cntl_b = REG(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B[mpcc_id]);
	gam_regs.start_slope_cntl_g = REG(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_G[mpcc_id]);
	gam_regs.start_slope_cntl_r = REG(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_R[mpcc_id]);
	gam_regs.start_end_cntl1_b = REG(MPCC_MCM_1DLUT_RAMA_END_CNTL1_B[mpcc_id]);
	gam_regs.start_end_cntl2_b = REG(MPCC_MCM_1DLUT_RAMA_END_CNTL2_B[mpcc_id]);
	gam_regs.start_end_cntl1_g = REG(MPCC_MCM_1DLUT_RAMA_END_CNTL1_G[mpcc_id]);
	gam_regs.start_end_cntl2_g = REG(MPCC_MCM_1DLUT_RAMA_END_CNTL2_G[mpcc_id]);
	gam_regs.start_end_cntl1_r = REG(MPCC_MCM_1DLUT_RAMA_END_CNTL1_R[mpcc_id]);
	gam_regs.start_end_cntl2_r = REG(MPCC_MCM_1DLUT_RAMA_END_CNTL2_R[mpcc_id]);
	gam_regs.region_start = REG(MPCC_MCM_1DLUT_RAMA_REGION_0_1[mpcc_id]);
	gam_regs.region_end = REG(MPCC_MCM_1DLUT_RAMA_REGION_32_33[mpcc_id]);

	cm_helper_program_gamcor_xfer_func(mpc->ctx, params, &gam_regs);
}

/*program blnd lut RAM B*/
static void mpc32_program_post1dlutb_settings(
		struct mpc *mpc,
		uint32_t mpcc_id,
		const struct pwl_params *params)
{
	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
	struct dcn3_xfer_func_reg gam_regs;

	mpc32_post1dlut_get_reg_field(mpc30, &gam_regs);

	gam_regs.start_cntl_b = REG(MPCC_MCM_1DLUT_RAMB_START_CNTL_B[mpcc_id]);
	gam_regs.start_cntl_g = REG(MPCC_MCM_1DLUT_RAMB_START_CNTL_G[mpcc_id]);
	gam_regs.start_cntl_r = REG(MPCC_MCM_1DLUT_RAMB_START_CNTL_R[mpcc_id]);
	gam_regs.start_slope_cntl_b = REG(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_B[mpcc_id]);
	gam_regs.start_slope_cntl_g = REG(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_G[mpcc_id]);
	gam_regs.start_slope_cntl_r = REG(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_R[mpcc_id]);
	gam_regs.start_end_cntl1_b = REG(MPCC_MCM_1DLUT_RAMB_END_CNTL1_B[mpcc_id]);
	gam_regs.start_end_cntl2_b = REG(MPCC_MCM_1DLUT_RAMB_END_CNTL2_B[mpcc_id]);
	gam_regs.start_end_cntl1_g = REG(MPCC_MCM_1DLUT_RAMB_END_CNTL1_G[mpcc_id]);
	gam_regs.start_end_cntl2_g = REG(MPCC_MCM_1DLUT_RAMB_END_CNTL2_G[mpcc_id]);
	gam_regs.start_end_cntl1_r = REG(MPCC_MCM_1DLUT_RAMB_END_CNTL1_R[mpcc_id]);
	gam_regs.start_end_cntl2_r = REG(MPCC_MCM_1DLUT_RAMB_END_CNTL2_R[mpcc_id]);
	gam_regs.region_start = REG(MPCC_MCM_1DLUT_RAMB_REGION_0_1[mpcc_id]);
	gam_regs.region_end = REG(MPCC_MCM_1DLUT_RAMB_REGION_32_33[mpcc_id]);

	cm_helper_program_gamcor_xfer_func(mpc->ctx, params, &gam_regs);
}

static void mpc32_program_post1dlut_pwl(
		struct mpc *mpc,
		uint32_t mpcc_id,
		const struct pwl_result_data *rgb,
		uint32_t num)
{
	uint32_t i;
	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
	uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
	uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
	uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;

	if (is_rgb_equal(rgb, num)) {
		for (i = 0 ; i < num; i++)
			REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg);
		REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red);
	} else {
		REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 4);
		for (i = 0 ; i < num; i++)
			REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg);
		REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red);

		REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 2);
		for (i = 0 ; i < num; i++)
			REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].green_reg);
		REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_green);

		REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 1);
		for (i = 0 ; i < num; i++)
			REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].blue_reg);
		REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_blue);
	}
}

static bool mpc32_program_post1dlut(
		struct mpc *mpc,
		const struct pwl_params *params,
		uint32_t mpcc_id)
{
	enum dc_lut_mode current_mode;
	enum dc_lut_mode next_mode;
	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);

	if (params == NULL) {
		REG_SET(MPCC_MCM_1DLUT_CONTROL[mpcc_id], 0, MPCC_MCM_1DLUT_MODE, 0);
		if (mpc->ctx->dc->debug.enable_mem_low_power.bits.cm)
			mpc32_power_on_blnd_lut(mpc, mpcc_id, false);
		return false;
	}

	current_mode = mpc32_get_post1dlut_current(mpc, mpcc_id);
	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_B)
		next_mode = LUT_RAM_A;
	else
		next_mode = LUT_RAM_B;

	mpc32_power_on_blnd_lut(mpc, mpcc_id, true);
	mpc32_configure_post1dlut(mpc, mpcc_id, next_mode == LUT_RAM_A);

	if (next_mode == LUT_RAM_A)
		mpc32_program_post1dluta_settings(mpc, mpcc_id, params);
	else
		mpc32_program_post1dlutb_settings(mpc, mpcc_id, params);

	mpc32_program_post1dlut_pwl(
			mpc, mpcc_id, params->rgb_resulted, params->hw_points_num);

	REG_UPDATE_2(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
			MPCC_MCM_1DLUT_MODE, 2,
			MPCC_MCM_1DLUT_SELECT, next_mode == LUT_RAM_A ? 0 : 1);

	return true;
}

static enum dc_lut_mode mpc32_get_shaper_current(struct mpc *mpc, uint32_t mpcc_id)
{
@@ -651,6 +880,10 @@ static void mpc32_set_3dlut_mode(
	uint32_t lut_mode;
	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);

	// set default 3DLUT to pre-blend
	// TODO: implement movable CM location
	REG_UPDATE(MPCC_MOVABLE_CM_LOCATION_CONTROL[mpcc_id], MPCC_MOVABLE_CM_LOCATION_CNTL, 0);

	if (mode == LUT_BYPASS)
		lut_mode = 0;
	else if (mode == LUT_RAM_A)
@@ -775,6 +1008,7 @@ const struct mpc_funcs dcn32_mpc_funcs = {
	.set_gamut_remap = mpc3_set_gamut_remap,
	.program_shaper = mpc32_program_shaper,
	.program_3dlut = mpc32_program_3dlut,
	.program_1dlut = mpc32_program_post1dlut,
	.acquire_rmu = NULL,
	.release_rmu = NULL,
	.power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut,
Loading