Takashi Iwai 8bd7a3
From d5e688b6be272d6b3999d2463e39a77dc52bc411 Mon Sep 17 00:00:00 2001
Takashi Iwai 8bd7a3
From: Roy Chan <roy.chan@amd.com>
Takashi Iwai 8bd7a3
Date: Mon, 19 Jul 2021 19:00:22 -0400
Takashi Iwai 8bd7a3
Subject: [PATCH] drm/amd/display: fix incorrect CM/TF programming sequence in dwb
Takashi Iwai 8bd7a3
Git-commit: 781e1e23131cce56fb557e6ec2260480a6bd08cc
Takashi Iwai 8bd7a3
Patch-mainline: v5.15-rc1
Takashi Iwai 8bd7a3
References: stable-5.14.6
Takashi Iwai 8bd7a3
Takashi Iwai 8bd7a3
[ Upstream commit 781e1e23131cce56fb557e6ec2260480a6bd08cc ]
Takashi Iwai 8bd7a3
Takashi Iwai 8bd7a3
[How]
Takashi Iwai 8bd7a3
the programming sequeune was for old asic.
Takashi Iwai 8bd7a3
the correct programming sequeunce should be similar to the one
Takashi Iwai 8bd7a3
used in mpc. the fix is copied from the mpc programming sequeunce.
Takashi Iwai 8bd7a3
Takashi Iwai 8bd7a3
Reviewed-by: Anthony Koo <Anthony.Koo@amd.com>
Takashi Iwai 8bd7a3
Acked-by: Anson Jacob <Anson.Jacob@amd.com>
Takashi Iwai 8bd7a3
Signed-off-by: Roy Chan <roy.chan@amd.com>
Takashi Iwai 8bd7a3
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Takashi Iwai 8bd7a3
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Takashi Iwai 8bd7a3
Signed-off-by: Sasha Levin <sashal@kernel.org>
Takashi Iwai 8bd7a3
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 8bd7a3
Takashi Iwai 8bd7a3
---
Takashi Iwai 8bd7a3
 .../drm/amd/display/dc/dcn30/dcn30_dwb_cm.c   | 90 +++++++++++++------
Takashi Iwai 8bd7a3
 1 file changed, 64 insertions(+), 26 deletions(-)
Takashi Iwai 8bd7a3
Takashi Iwai 8bd7a3
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
Takashi Iwai 8bd7a3
index 3fe9e41e4dbd..6a3d3a0ec0a3 100644
Takashi Iwai 8bd7a3
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
Takashi Iwai 8bd7a3
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
Takashi Iwai 8bd7a3
@@ -49,6 +49,11 @@
Takashi Iwai 8bd7a3
 static void dwb3_get_reg_field_ogam(struct dcn30_dwbc *dwbc30,
Takashi Iwai 8bd7a3
 	struct dcn3_xfer_func_reg *reg)
Takashi Iwai 8bd7a3
 {
Takashi Iwai 8bd7a3
+	reg->shifts.field_region_start_base = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_BASE_B;
Takashi Iwai 8bd7a3
+	reg->masks.field_region_start_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_BASE_B;
Takashi Iwai 8bd7a3
+	reg->shifts.field_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_OFFSET_B;
Takashi Iwai 8bd7a3
+	reg->masks.field_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_OFFSET_B;
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
 	reg->shifts.exp_region0_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
Takashi Iwai 8bd7a3
 	reg->masks.exp_region0_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
Takashi Iwai 8bd7a3
 	reg->shifts.exp_region0_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
Takashi Iwai 8bd7a3
@@ -66,8 +71,6 @@ static void dwb3_get_reg_field_ogam(struct dcn30_dwbc *dwbc30,
Takashi Iwai 8bd7a3
 	reg->masks.field_region_end_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B;
Takashi Iwai 8bd7a3
 	reg->shifts.field_region_linear_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
Takashi Iwai 8bd7a3
 	reg->masks.field_region_linear_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
Takashi Iwai 8bd7a3
-	reg->masks.field_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_OFFSET_B;
Takashi Iwai 8bd7a3
-	reg->shifts.field_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_OFFSET_B;
Takashi Iwai 8bd7a3
 	reg->shifts.exp_region_start = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_B;
Takashi Iwai 8bd7a3
 	reg->masks.exp_region_start = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_B;
Takashi Iwai 8bd7a3
 	reg->shifts.exp_resion_start_segment = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
Takashi Iwai 8bd7a3
@@ -147,18 +150,19 @@ static enum dc_lut_mode dwb3_get_ogam_current(
Takashi Iwai 8bd7a3
 	uint32_t state_mode;
Takashi Iwai 8bd7a3
 	uint32_t ram_select;
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
-	REG_GET(DWB_OGAM_CONTROL,
Takashi Iwai 8bd7a3
-		DWB_OGAM_MODE, &state_mode);
Takashi Iwai 8bd7a3
-	REG_GET(DWB_OGAM_CONTROL,
Takashi Iwai 8bd7a3
-		DWB_OGAM_SELECT, &ram_select);
Takashi Iwai 8bd7a3
+	REG_GET_2(DWB_OGAM_CONTROL,
Takashi Iwai 8bd7a3
+		DWB_OGAM_MODE_CURRENT, &state_mode,
Takashi Iwai 8bd7a3
+		DWB_OGAM_SELECT_CURRENT, &ram_select);
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
 	if (state_mode == 0) {
Takashi Iwai 8bd7a3
 		mode = LUT_BYPASS;
Takashi Iwai 8bd7a3
 	} else if (state_mode == 2) {
Takashi Iwai 8bd7a3
 		if (ram_select == 0)
Takashi Iwai 8bd7a3
 			mode = LUT_RAM_A;
Takashi Iwai 8bd7a3
-		else
Takashi Iwai 8bd7a3
+		else if (ram_select == 1)
Takashi Iwai 8bd7a3
 			mode = LUT_RAM_B;
Takashi Iwai 8bd7a3
+		else
Takashi Iwai 8bd7a3
+			mode = LUT_BYPASS;
Takashi Iwai 8bd7a3
 	} else {
Takashi Iwai 8bd7a3
 		// Reserved value
Takashi Iwai 8bd7a3
 		mode = LUT_BYPASS;
Takashi Iwai 8bd7a3
@@ -172,10 +176,10 @@ static void dwb3_configure_ogam_lut(
Takashi Iwai 8bd7a3
 	struct dcn30_dwbc *dwbc30,
Takashi Iwai 8bd7a3
 	bool is_ram_a)
Takashi Iwai 8bd7a3
 {
Takashi Iwai 8bd7a3
-	REG_UPDATE(DWB_OGAM_LUT_CONTROL,
Takashi Iwai 8bd7a3
-		DWB_OGAM_LUT_READ_COLOR_SEL, 7);
Takashi Iwai 8bd7a3
-	REG_UPDATE(DWB_OGAM_CONTROL,
Takashi Iwai 8bd7a3
-		DWB_OGAM_SELECT, is_ram_a == true ? 0 : 1);
Takashi Iwai 8bd7a3
+	REG_UPDATE_2(DWB_OGAM_LUT_CONTROL,
Takashi Iwai 8bd7a3
+		DWB_OGAM_LUT_WRITE_COLOR_MASK, 7,
Takashi Iwai 8bd7a3
+		DWB_OGAM_LUT_HOST_SEL, (is_ram_a == true) ? 0 : 1);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
 	REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0);
Takashi Iwai 8bd7a3
 }
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
@@ -185,17 +189,45 @@ static void dwb3_program_ogam_pwl(struct dcn30_dwbc *dwbc30,
Takashi Iwai 8bd7a3
 {
Takashi Iwai 8bd7a3
 	uint32_t i;
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
-    // triple base implementation
Takashi Iwai 8bd7a3
-	for (i = 0; i < num/2; i++) {
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].red_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].green_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+0].blue_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].red_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].green_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+1].blue_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].red_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].green_reg);
Takashi Iwai 8bd7a3
-		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[2*i+2].blue_reg);
Takashi Iwai 8bd7a3
+	uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
Takashi Iwai 8bd7a3
+	uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
Takashi Iwai 8bd7a3
+	uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+	if (is_rgb_equal(rgb,  num)) {
Takashi Iwai 8bd7a3
+		for (i = 0 ; i < num; i++)
Takashi Iwai 8bd7a3
+			REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].red_reg);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_red);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+	} else {
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_UPDATE(DWB_OGAM_LUT_CONTROL,
Takashi Iwai 8bd7a3
+				DWB_OGAM_LUT_WRITE_COLOR_MASK, 4);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		for (i = 0 ; i < num; i++)
Takashi Iwai 8bd7a3
+			REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].red_reg);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_red);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_UPDATE(DWB_OGAM_LUT_CONTROL,
Takashi Iwai 8bd7a3
+				DWB_OGAM_LUT_WRITE_COLOR_MASK, 2);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		for (i = 0 ; i < num; i++)
Takashi Iwai 8bd7a3
+			REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].green_reg);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_green);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_UPDATE(DWB_OGAM_LUT_CONTROL,
Takashi Iwai 8bd7a3
+				DWB_OGAM_LUT_WRITE_COLOR_MASK, 1);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		for (i = 0 ; i < num; i++)
Takashi Iwai 8bd7a3
+			REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].blue_reg);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+		REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_blue);
Takashi Iwai 8bd7a3
 	}
Takashi Iwai 8bd7a3
 }
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
@@ -211,6 +243,8 @@ static bool dwb3_program_ogam_lut(
Takashi Iwai 8bd7a3
 		return false;
Takashi Iwai 8bd7a3
 	}
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
+	REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
 	current_mode = dwb3_get_ogam_current(dwbc30);
Takashi Iwai 8bd7a3
 	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
Takashi Iwai 8bd7a3
 		next_mode = LUT_RAM_B;
Takashi Iwai 8bd7a3
@@ -227,8 +261,7 @@ static bool dwb3_program_ogam_lut(
Takashi Iwai 8bd7a3
 	dwb3_program_ogam_pwl(
Takashi Iwai 8bd7a3
 		dwbc30, params->rgb_resulted, params->hw_points_num);
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
-	REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2);
Takashi Iwai 8bd7a3
-	REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1);
Takashi Iwai 8bd7a3
+	REG_UPDATE(DWB_OGAM_CONTROL, DWB_OGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1);
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
 	return true;
Takashi Iwai 8bd7a3
 }
Takashi Iwai 8bd7a3
@@ -271,14 +304,19 @@ static void dwb3_program_gamut_remap(
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
 	struct color_matrices_reg gam_regs;
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
-	REG_UPDATE(DWB_GAMUT_REMAP_COEF_FORMAT, DWB_GAMUT_REMAP_COEF_FORMAT, coef_format);
Takashi Iwai 8bd7a3
-
Takashi Iwai 8bd7a3
 	if (regval == NULL || select == CM_GAMUT_REMAP_MODE_BYPASS) {
Takashi Iwai 8bd7a3
 		REG_SET(DWB_GAMUT_REMAP_MODE, 0,
Takashi Iwai 8bd7a3
 				DWB_GAMUT_REMAP_MODE, 0);
Takashi Iwai 8bd7a3
 		return;
Takashi Iwai 8bd7a3
 	}
Takashi Iwai 8bd7a3
 
Takashi Iwai 8bd7a3
+	REG_UPDATE(DWB_GAMUT_REMAP_COEF_FORMAT, DWB_GAMUT_REMAP_COEF_FORMAT, coef_format);
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
+	gam_regs.shifts.csc_c11 = dwbc30->dwbc_shift->DWB_GAMUT_REMAPA_C11;
Takashi Iwai 8bd7a3
+	gam_regs.masks.csc_c11  = dwbc30->dwbc_mask->DWB_GAMUT_REMAPA_C11;
Takashi Iwai 8bd7a3
+	gam_regs.shifts.csc_c12 = dwbc30->dwbc_shift->DWB_GAMUT_REMAPA_C12;
Takashi Iwai 8bd7a3
+	gam_regs.masks.csc_c12 = dwbc30->dwbc_mask->DWB_GAMUT_REMAPA_C12;
Takashi Iwai 8bd7a3
+
Takashi Iwai 8bd7a3
 	switch (select) {
Takashi Iwai 8bd7a3
 	case CM_GAMUT_REMAP_MODE_RAMA_COEFF:
Takashi Iwai 8bd7a3
 		gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPA_C11_C12);
Takashi Iwai 8bd7a3
-- 
Takashi Iwai 8bd7a3
2.26.2
Takashi Iwai 8bd7a3