[PATCH 07/49] drm/amd/display: Add 22, 24, and 26 degamma

sunpeng.li at amd.com sunpeng.li at amd.com
Fri Aug 9 21:37:00 UTC 2019


From: Vitaly Prosyak <vitaly.prosyak at amd.com>

[Why & How]
Support degamma ROM and RAM based on hardware capabilities.
Some refactoring into color module

Signed-off-by: Vitaly Prosyak <vitaly.prosyak at amd.com>
Reviewed-by: Gary Kattan <Gary.Kattan at amd.com>
Reviewed-by: Nevenko Stupar <Nevenko.Stupar at amd.com>
Acked-by: Leo Li <sunpeng.li at amd.com>
Acked-by: Vitaly Prosyak <Vitaly.Prosyak at amd.com>
---
 drivers/gpu/drm/amd/display/dc/dc.h           |   5 +-
 .../amd/display/modules/color/color_gamma.c   | 116 +++++++++++-------
 2 files changed, 75 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index c585e16bc9f1..e3d7710b5c54 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -614,9 +614,12 @@ enum dc_transfer_func_predefined {
 	TRANSFER_FUNCTION_UNITY,
 	TRANSFER_FUNCTION_HLG,
 	TRANSFER_FUNCTION_HLG12,
-	TRANSFER_FUNCTION_GAMMA22
+	TRANSFER_FUNCTION_GAMMA22,
+	TRANSFER_FUNCTION_GAMMA24,
+	TRANSFER_FUNCTION_GAMMA26
 };
 
+
 struct dc_transfer_func {
 	struct kref refcount;
 	enum dc_transfer_func_type type;
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
index 294fe4f0cb67..8b2ee606dbc2 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -57,12 +57,12 @@ static struct translate_from_linear_space_args scratch_gamma_args;
 static struct fixed31_32 pow_buffer[NUM_PTS_IN_REGION];
 static struct fixed31_32 gamma_of_2; // 2^gamma
 int pow_buffer_ptr = -1;
-
-static const int32_t gamma_numerator01[] = { 31308,	180000,	0};
-static const int32_t gamma_numerator02[] = { 12920,	4500,	0};
-static const int32_t gamma_numerator03[] = { 55,	99,	0};
-static const int32_t gamma_numerator04[] = { 55,	99,	0};
-static const int32_t gamma_numerator05[] = { 2400,	2200, 2200};
+										/*sRGB	 709 2.2 2.4 P3*/
+static const int32_t gamma_numerator01[] = { 31308,	180000,	0,	0,	0};
+static const int32_t gamma_numerator02[] = { 12920,	4500,	0,	0,	0};
+static const int32_t gamma_numerator03[] = { 55,	99,		0,	0,	0};
+static const int32_t gamma_numerator04[] = { 55,	99,		0,	0,	0};
+static const int32_t gamma_numerator05[] = { 2400,	2200,	2200, 2400, 2600};
 
 static bool pq_initialized; /* = false; */
 static bool de_pq_initialized; /* = false; */
@@ -267,23 +267,28 @@ struct dividers {
 	struct fixed31_32 divider3;
 };
 
-enum gamma_type_index {
-	gamma_type_index_2_4,
-	gamma_type_index_2_2,
-	gamma_type_index_2_2_flat
-};
 
-static void build_coefficients(struct gamma_coefficients *coefficients, enum gamma_type_index type)
+static bool build_coefficients(struct gamma_coefficients *coefficients, enum dc_transfer_func_predefined type)
 {
 
-
 	uint32_t i = 0;
 	uint32_t index = 0;
+	bool ret = true;
 
-	if (type == gamma_type_index_2_2)
+	if (type == TRANSFER_FUNCTION_SRGB)
+		index = 0;
+	else if (type == TRANSFER_FUNCTION_BT709)
 		index = 1;
-	else if (type == gamma_type_index_2_2_flat)
+	else if (type == TRANSFER_FUNCTION_GAMMA22)
 		index = 2;
+	else if (type == TRANSFER_FUNCTION_GAMMA24)
+		index = 3;
+	else if (type == TRANSFER_FUNCTION_GAMMA26)
+		index = 4;
+	else {
+		ret = false;
+		goto release;
+	}
 
 	do {
 		coefficients->a0[i] = dc_fixpt_from_fraction(
@@ -299,6 +304,8 @@ static void build_coefficients(struct gamma_coefficients *coefficients, enum gam
 
 		++i;
 	} while (i != ARRAY_SIZE(coefficients->a0));
+release:
+	return ret;
 }
 
 static struct fixed31_32 translate_from_linear_space(
@@ -735,11 +742,12 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq,
 	}
 }
 
-static void build_regamma(struct pwl_float_data_ex *rgb_regamma,
+static bool build_regamma(struct pwl_float_data_ex *rgb_regamma,
 		uint32_t hw_points_num,
-		const struct hw_x_point *coordinate_x, enum gamma_type_index type)
+		const struct hw_x_point *coordinate_x, enum dc_transfer_func_predefined type)
 {
 	uint32_t i;
+	bool ret = false;
 
 	struct gamma_coefficients *coeff;
 	struct pwl_float_data_ex *rgb = rgb_regamma;
@@ -747,9 +755,10 @@ static void build_regamma(struct pwl_float_data_ex *rgb_regamma,
 
 	coeff = kvzalloc(sizeof(*coeff), GFP_KERNEL);
 	if (!coeff)
-		return;
+		goto release;
 
-	build_coefficients(coeff, type);
+	if (!build_coefficients(coeff, type))
+		goto release;
 
 	memset(pow_buffer, 0, NUM_PTS_IN_REGION * sizeof(struct fixed31_32));
 	pow_buffer_ptr = 0; // see variable definition for more info
@@ -765,8 +774,10 @@ static void build_regamma(struct pwl_float_data_ex *rgb_regamma,
 		++i;
 	}
 	pow_buffer_ptr = -1; // reset back to no optimize
-
+	ret = true;
+release:
 	kfree(coeff);
+	return ret;
 }
 
 static void hermite_spline_eetf(struct fixed31_32 input_x,
@@ -941,15 +952,18 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma,
 	return true;
 }
 
-static void build_degamma(struct pwl_float_data_ex *curve,
+static bool build_degamma(struct pwl_float_data_ex *curve,
 		uint32_t hw_points_num,
-		const struct hw_x_point *coordinate_x, enum gamma_type_index type)
+		const struct hw_x_point *coordinate_x, enum dc_transfer_func_predefined type)
 {
 	uint32_t i;
 	struct gamma_coefficients coeff;
 	uint32_t begin_index, end_index;
+	bool ret = false;
+
+	if (!build_coefficients(&coeff, type))
+		goto release;
 
-	build_coefficients(&coeff, type);
 	i = 0;
 
 	/* X points is 2^-25 to 2^7
@@ -978,6 +992,9 @@ static void build_degamma(struct pwl_float_data_ex *curve,
 		curve[i].b = dc_fixpt_one;
 		i++;
 	}
+	ret = true;
+release:
+	return ret;
 }
 
 static void build_hlg_degamma(struct pwl_float_data_ex *degamma,
@@ -1672,6 +1689,12 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
 				MAX_HW_POINTS,
 				coordinates_x,
 				fs_params);
+	} else if (tf == TRANSFER_FUNCTION_HLG) {
+		build_freesync_hdr(rgb_regamma,
+				MAX_HW_POINTS,
+				coordinates_x,
+				fs_params);
+
 	} else {
 		tf_pts->end_exponent = 0;
 		tf_pts->x_point_at_y1_red = 1;
@@ -1680,9 +1703,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
 
 		build_regamma(rgb_regamma,
 				MAX_HW_POINTS,
-				coordinates_x, tf == TRANSFER_FUNCTION_SRGB ? gamma_type_index_2_4 :
-					tf == TRANSFER_FUNCTION_GAMMA22 ?
-					gamma_type_index_2_2_flat : gamma_type_index_2_2);
+				coordinates_x, tf);
 	}
 	map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
 			coordinates_x, axis_x, rgb_regamma,
@@ -1883,13 +1904,19 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
 				MAX_HW_POINTS,
 				coordinates_x);
 	else if (tf == TRANSFER_FUNCTION_SRGB ||
-			tf == TRANSFER_FUNCTION_BT709)
+		tf == TRANSFER_FUNCTION_BT709 ||
+		tf == TRANSFER_FUNCTION_GAMMA22 ||
+		tf == TRANSFER_FUNCTION_GAMMA24 ||
+		tf == TRANSFER_FUNCTION_GAMMA26)
 		build_degamma(curve,
 				MAX_HW_POINTS,
 				coordinates_x,
-				tf == TRANSFER_FUNCTION_SRGB ?
-				gamma_type_index_2_4 : tf == TRANSFER_FUNCTION_GAMMA22 ?
-				gamma_type_index_2_2_flat : gamma_type_index_2_2);
+				tf);
+	else if (tf == TRANSFER_FUNCTION_HLG)
+		build_hlg_degamma(curve,
+				MAX_HW_POINTS,
+				coordinates_x,
+				true);
 	else if (tf == TRANSFER_FUNCTION_LINEAR) {
 		// just copy coordinates_x into curve
 		i = 0;
@@ -1976,7 +2003,10 @@ bool  mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
 
 		kvfree(rgb_regamma);
 	} else if (trans == TRANSFER_FUNCTION_SRGB ||
-			  trans == TRANSFER_FUNCTION_BT709) {
+		trans == TRANSFER_FUNCTION_BT709 ||
+		trans == TRANSFER_FUNCTION_GAMMA22 ||
+		trans == TRANSFER_FUNCTION_GAMMA24 ||
+		trans == TRANSFER_FUNCTION_GAMMA26) {
 		rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
 				       sizeof(*rgb_regamma),
 				       GFP_KERNEL);
@@ -1990,9 +2020,7 @@ bool  mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
 		build_regamma(rgb_regamma,
 				MAX_HW_POINTS,
 				coordinates_x,
-				trans == TRANSFER_FUNCTION_SRGB ?
-				gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ?
-				gamma_type_index_2_2_flat : gamma_type_index_2_2);
+				trans);
 		for (i = 0; i <= MAX_HW_POINTS ; i++) {
 			points->red[i]    = rgb_regamma[i].r;
 			points->green[i]  = rgb_regamma[i].g;
@@ -2001,8 +2029,7 @@ bool  mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
 		ret = true;
 
 		kvfree(rgb_regamma);
-	} else if (trans == TRANSFER_FUNCTION_HLG ||
-		trans == TRANSFER_FUNCTION_HLG12) {
+	} else if (trans == TRANSFER_FUNCTION_HLG) {
 		rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
 				       sizeof(*rgb_regamma),
 				       GFP_KERNEL);
@@ -2012,7 +2039,7 @@ bool  mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
 		build_hlg_regamma(rgb_regamma,
 				MAX_HW_POINTS,
 				coordinates_x,
-				trans == TRANSFER_FUNCTION_HLG12 ? true:false);
+				true);
 		for (i = 0; i <= MAX_HW_POINTS ; i++) {
 			points->red[i]    = rgb_regamma[i].r;
 			points->green[i]  = rgb_regamma[i].g;
@@ -2062,8 +2089,10 @@ bool  mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
 
 		kvfree(rgb_degamma);
 	} else if (trans == TRANSFER_FUNCTION_SRGB ||
-			  trans == TRANSFER_FUNCTION_BT709 ||
-			  trans == TRANSFER_FUNCTION_GAMMA22) {
+		trans == TRANSFER_FUNCTION_BT709 ||
+		trans == TRANSFER_FUNCTION_GAMMA22 ||
+		trans == TRANSFER_FUNCTION_GAMMA24 ||
+		trans == TRANSFER_FUNCTION_GAMMA26) {
 		rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
 				       sizeof(*rgb_degamma),
 				       GFP_KERNEL);
@@ -2073,9 +2102,7 @@ bool  mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
 		build_degamma(rgb_degamma,
 				MAX_HW_POINTS,
 				coordinates_x,
-				trans == TRANSFER_FUNCTION_SRGB ?
-				gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ?
-				gamma_type_index_2_2_flat : gamma_type_index_2_2);
+				trans);
 		for (i = 0; i <= MAX_HW_POINTS ; i++) {
 			points->red[i]    = rgb_degamma[i].r;
 			points->green[i]  = rgb_degamma[i].g;
@@ -2084,8 +2111,7 @@ bool  mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
 		ret = true;
 
 		kvfree(rgb_degamma);
-	} else if (trans == TRANSFER_FUNCTION_HLG ||
-		trans == TRANSFER_FUNCTION_HLG12) {
+	} else if (trans == TRANSFER_FUNCTION_HLG) {
 		rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
 				       sizeof(*rgb_degamma),
 				       GFP_KERNEL);
@@ -2095,7 +2121,7 @@ bool  mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
 		build_hlg_degamma(rgb_degamma,
 				MAX_HW_POINTS,
 				coordinates_x,
-				trans == TRANSFER_FUNCTION_HLG12 ? true:false);
+				true);
 		for (i = 0; i <= MAX_HW_POINTS ; i++) {
 			points->red[i]    = rgb_degamma[i].r;
 			points->green[i]  = rgb_degamma[i].g;
-- 
2.22.0



More information about the amd-gfx mailing list