Commit 1ee299b9 authored by Vitaly Prosyak's avatar Vitaly Prosyak Committed by Alex Deucher

drm/amd/display: Add 22, 24, and 26 degamma

[Why & How]
Support degamma ROM and RAM based on hardware capabilities.
Some refactoring into color module
Signed-off-by: default avatarVitaly Prosyak <vitaly.prosyak@amd.com>
Reviewed-by: default avatarGary Kattan <Gary.Kattan@amd.com>
Reviewed-by: default avatarNevenko Stupar <Nevenko.Stupar@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Acked-by: default avatarVitaly Prosyak <Vitaly.Prosyak@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a463b263
...@@ -614,9 +614,12 @@ enum dc_transfer_func_predefined { ...@@ -614,9 +614,12 @@ enum dc_transfer_func_predefined {
TRANSFER_FUNCTION_UNITY, TRANSFER_FUNCTION_UNITY,
TRANSFER_FUNCTION_HLG, TRANSFER_FUNCTION_HLG,
TRANSFER_FUNCTION_HLG12, TRANSFER_FUNCTION_HLG12,
TRANSFER_FUNCTION_GAMMA22 TRANSFER_FUNCTION_GAMMA22,
TRANSFER_FUNCTION_GAMMA24,
TRANSFER_FUNCTION_GAMMA26
}; };
struct dc_transfer_func { struct dc_transfer_func {
struct kref refcount; struct kref refcount;
enum dc_transfer_func_type type; enum dc_transfer_func_type type;
......
...@@ -60,12 +60,12 @@ static struct translate_from_linear_space_args scratch_gamma_args; ...@@ -60,12 +60,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 pow_buffer[NUM_PTS_IN_REGION];
static struct fixed31_32 gamma_of_2; // 2^gamma static struct fixed31_32 gamma_of_2; // 2^gamma
int pow_buffer_ptr = -1; int pow_buffer_ptr = -1;
/*sRGB 709 2.2 2.4 P3*/
static const int32_t gamma_numerator01[] = { 31308, 180000, 0}; static const int32_t gamma_numerator01[] = { 31308, 180000, 0, 0, 0};
static const int32_t gamma_numerator02[] = { 12920, 4500, 0}; static const int32_t gamma_numerator02[] = { 12920, 4500, 0, 0, 0};
static const int32_t gamma_numerator03[] = { 55, 99, 0}; static const int32_t gamma_numerator03[] = { 55, 99, 0, 0, 0};
static const int32_t gamma_numerator04[] = { 55, 99, 0}; static const int32_t gamma_numerator04[] = { 55, 99, 0, 0, 0};
static const int32_t gamma_numerator05[] = { 2400, 2200, 2200}; static const int32_t gamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600};
static bool pq_initialized; /* = false; */ static bool pq_initialized; /* = false; */
static bool de_pq_initialized; /* = false; */ static bool de_pq_initialized; /* = false; */
...@@ -270,23 +270,28 @@ struct dividers { ...@@ -270,23 +270,28 @@ struct dividers {
struct fixed31_32 divider3; 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 i = 0;
uint32_t index = 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; index = 1;
else if (type == gamma_type_index_2_2_flat) else if (type == TRANSFER_FUNCTION_GAMMA22)
index = 2; index = 2;
else if (type == TRANSFER_FUNCTION_GAMMA24)
index = 3;
else if (type == TRANSFER_FUNCTION_GAMMA26)
index = 4;
else {
ret = false;
goto release;
}
do { do {
coefficients->a0[i] = dc_fixpt_from_fraction( coefficients->a0[i] = dc_fixpt_from_fraction(
...@@ -302,6 +307,8 @@ static void build_coefficients(struct gamma_coefficients *coefficients, enum gam ...@@ -302,6 +307,8 @@ static void build_coefficients(struct gamma_coefficients *coefficients, enum gam
++i; ++i;
} while (i != ARRAY_SIZE(coefficients->a0)); } while (i != ARRAY_SIZE(coefficients->a0));
release:
return ret;
} }
static struct fixed31_32 translate_from_linear_space( static struct fixed31_32 translate_from_linear_space(
...@@ -738,11 +745,12 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq, ...@@ -738,11 +745,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, 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; uint32_t i;
bool ret = false;
struct gamma_coefficients *coeff; struct gamma_coefficients *coeff;
struct pwl_float_data_ex *rgb = rgb_regamma; struct pwl_float_data_ex *rgb = rgb_regamma;
...@@ -750,9 +758,10 @@ static void build_regamma(struct pwl_float_data_ex *rgb_regamma, ...@@ -750,9 +758,10 @@ static void build_regamma(struct pwl_float_data_ex *rgb_regamma,
coeff = kvzalloc(sizeof(*coeff), GFP_KERNEL); coeff = kvzalloc(sizeof(*coeff), GFP_KERNEL);
if (!coeff) 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)); memset(pow_buffer, 0, NUM_PTS_IN_REGION * sizeof(struct fixed31_32));
pow_buffer_ptr = 0; // see variable definition for more info pow_buffer_ptr = 0; // see variable definition for more info
...@@ -768,8 +777,10 @@ static void build_regamma(struct pwl_float_data_ex *rgb_regamma, ...@@ -768,8 +777,10 @@ static void build_regamma(struct pwl_float_data_ex *rgb_regamma,
++i; ++i;
} }
pow_buffer_ptr = -1; // reset back to no optimize pow_buffer_ptr = -1; // reset back to no optimize
ret = true;
release:
kfree(coeff); kfree(coeff);
return ret;
} }
static void hermite_spline_eetf(struct fixed31_32 input_x, static void hermite_spline_eetf(struct fixed31_32 input_x,
...@@ -944,15 +955,18 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, ...@@ -944,15 +955,18 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma,
return true; 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, 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; uint32_t i;
struct gamma_coefficients coeff; struct gamma_coefficients coeff;
uint32_t begin_index, end_index; uint32_t begin_index, end_index;
bool ret = false;
if (!build_coefficients(&coeff, type))
goto release;
build_coefficients(&coeff, type);
i = 0; i = 0;
/* X points is 2^-25 to 2^7 /* X points is 2^-25 to 2^7
...@@ -981,6 +995,9 @@ static void build_degamma(struct pwl_float_data_ex *curve, ...@@ -981,6 +995,9 @@ static void build_degamma(struct pwl_float_data_ex *curve,
curve[i].b = dc_fixpt_one; curve[i].b = dc_fixpt_one;
i++; i++;
} }
ret = true;
release:
return ret;
} }
static void build_hlg_degamma(struct pwl_float_data_ex *degamma, static void build_hlg_degamma(struct pwl_float_data_ex *degamma,
...@@ -1675,6 +1692,12 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, ...@@ -1675,6 +1692,12 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x, coordinates_x,
fs_params); fs_params);
} else if (tf == TRANSFER_FUNCTION_HLG) {
build_freesync_hdr(rgb_regamma,
MAX_HW_POINTS,
coordinates_x,
fs_params);
} else { } else {
tf_pts->end_exponent = 0; tf_pts->end_exponent = 0;
tf_pts->x_point_at_y1_red = 1; tf_pts->x_point_at_y1_red = 1;
...@@ -1683,9 +1706,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, ...@@ -1683,9 +1706,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
build_regamma(rgb_regamma, build_regamma(rgb_regamma,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x, tf == TRANSFER_FUNCTION_SRGB ? gamma_type_index_2_4 : coordinates_x, tf);
tf == TRANSFER_FUNCTION_GAMMA22 ?
gamma_type_index_2_2_flat : gamma_type_index_2_2);
} }
map_regamma_hw_to_x_user(ramp, coeff, rgb_user, map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
coordinates_x, axis_x, rgb_regamma, coordinates_x, axis_x, rgb_regamma,
...@@ -1886,13 +1907,19 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, ...@@ -1886,13 +1907,19 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x); coordinates_x);
else if (tf == TRANSFER_FUNCTION_SRGB || 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, build_degamma(curve,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x, coordinates_x,
tf == TRANSFER_FUNCTION_SRGB ? tf);
gamma_type_index_2_4 : tf == TRANSFER_FUNCTION_GAMMA22 ? else if (tf == TRANSFER_FUNCTION_HLG)
gamma_type_index_2_2_flat : gamma_type_index_2_2); build_hlg_degamma(curve,
MAX_HW_POINTS,
coordinates_x,
true);
else if (tf == TRANSFER_FUNCTION_LINEAR) { else if (tf == TRANSFER_FUNCTION_LINEAR) {
// just copy coordinates_x into curve // just copy coordinates_x into curve
i = 0; i = 0;
...@@ -1979,7 +2006,10 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, ...@@ -1979,7 +2006,10 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
kvfree(rgb_regamma); kvfree(rgb_regamma);
} else if (trans == TRANSFER_FUNCTION_SRGB || } 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, rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_regamma), sizeof(*rgb_regamma),
GFP_KERNEL); GFP_KERNEL);
...@@ -1993,9 +2023,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, ...@@ -1993,9 +2023,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
build_regamma(rgb_regamma, build_regamma(rgb_regamma,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x, coordinates_x,
trans == TRANSFER_FUNCTION_SRGB ? trans);
gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ?
gamma_type_index_2_2_flat : gamma_type_index_2_2);
for (i = 0; i <= MAX_HW_POINTS ; i++) { for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_regamma[i].r; points->red[i] = rgb_regamma[i].r;
points->green[i] = rgb_regamma[i].g; points->green[i] = rgb_regamma[i].g;
...@@ -2004,8 +2032,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, ...@@ -2004,8 +2032,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
ret = true; ret = true;
kvfree(rgb_regamma); kvfree(rgb_regamma);
} else if (trans == TRANSFER_FUNCTION_HLG || } else if (trans == TRANSFER_FUNCTION_HLG) {
trans == TRANSFER_FUNCTION_HLG12) {
rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_regamma), sizeof(*rgb_regamma),
GFP_KERNEL); GFP_KERNEL);
...@@ -2015,7 +2042,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, ...@@ -2015,7 +2042,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
build_hlg_regamma(rgb_regamma, build_hlg_regamma(rgb_regamma,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x, coordinates_x,
trans == TRANSFER_FUNCTION_HLG12 ? true:false); true);
for (i = 0; i <= MAX_HW_POINTS ; i++) { for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_regamma[i].r; points->red[i] = rgb_regamma[i].r;
points->green[i] = rgb_regamma[i].g; points->green[i] = rgb_regamma[i].g;
...@@ -2065,8 +2092,10 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, ...@@ -2065,8 +2092,10 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
kvfree(rgb_degamma); kvfree(rgb_degamma);
} else if (trans == TRANSFER_FUNCTION_SRGB || } else if (trans == TRANSFER_FUNCTION_SRGB ||
trans == TRANSFER_FUNCTION_BT709 || trans == TRANSFER_FUNCTION_BT709 ||
trans == TRANSFER_FUNCTION_GAMMA22) { trans == TRANSFER_FUNCTION_GAMMA22 ||
trans == TRANSFER_FUNCTION_GAMMA24 ||
trans == TRANSFER_FUNCTION_GAMMA26) {
rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_degamma), sizeof(*rgb_degamma),
GFP_KERNEL); GFP_KERNEL);
...@@ -2076,9 +2105,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, ...@@ -2076,9 +2105,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
build_degamma(rgb_degamma, build_degamma(rgb_degamma,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x, coordinates_x,
trans == TRANSFER_FUNCTION_SRGB ? trans);
gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ?
gamma_type_index_2_2_flat : gamma_type_index_2_2);
for (i = 0; i <= MAX_HW_POINTS ; i++) { for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_degamma[i].r; points->red[i] = rgb_degamma[i].r;
points->green[i] = rgb_degamma[i].g; points->green[i] = rgb_degamma[i].g;
...@@ -2087,8 +2114,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, ...@@ -2087,8 +2114,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
ret = true; ret = true;
kvfree(rgb_degamma); kvfree(rgb_degamma);
} else if (trans == TRANSFER_FUNCTION_HLG || } else if (trans == TRANSFER_FUNCTION_HLG) {
trans == TRANSFER_FUNCTION_HLG12) {
rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_degamma), sizeof(*rgb_degamma),
GFP_KERNEL); GFP_KERNEL);
...@@ -2098,7 +2124,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, ...@@ -2098,7 +2124,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
build_hlg_degamma(rgb_degamma, build_hlg_degamma(rgb_degamma,
MAX_HW_POINTS, MAX_HW_POINTS,
coordinates_x, coordinates_x,
trans == TRANSFER_FUNCTION_HLG12 ? true:false); true);
for (i = 0; i <= MAX_HW_POINTS ; i++) { for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_degamma[i].r; points->red[i] = rgb_degamma[i].r;
points->green[i] = rgb_degamma[i].g; points->green[i] = rgb_degamma[i].g;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment