drm/amd/display: Correct algorithm for reversed gamma
[Why] DCN30 needs to correctly program reversed gamma curve, which DCN20 already has. Also needs to fix a bug that 252-255 values are clipped. [How] Apply two fixes into DCN30. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1513 Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Calvin Hou <Calvin.Hou@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com> Acked-by: Solomon Chiu <solomon.chiu@amd.com> Acked-by: Vladimir Stempen <Vladimir.Stempen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
73076790e2
commit
34fa493a56
|
@ -113,6 +113,7 @@ bool cm3_helper_translate_curve_to_hw_format(
|
|||
struct pwl_result_data *rgb_resulted;
|
||||
struct pwl_result_data *rgb;
|
||||
struct pwl_result_data *rgb_plus_1;
|
||||
struct pwl_result_data *rgb_minus_1;
|
||||
struct fixed31_32 end_value;
|
||||
|
||||
int32_t region_start, region_end;
|
||||
|
@ -140,7 +141,7 @@ bool cm3_helper_translate_curve_to_hw_format(
|
|||
region_start = -MAX_LOW_POINT;
|
||||
region_end = NUMBER_REGIONS - MAX_LOW_POINT;
|
||||
} else {
|
||||
/* 10 segments
|
||||
/* 11 segments
|
||||
* segment is from 2^-10 to 2^0
|
||||
* There are less than 256 points, for optimization
|
||||
*/
|
||||
|
@ -154,9 +155,10 @@ bool cm3_helper_translate_curve_to_hw_format(
|
|||
seg_distr[7] = 4;
|
||||
seg_distr[8] = 4;
|
||||
seg_distr[9] = 4;
|
||||
seg_distr[10] = 1;
|
||||
|
||||
region_start = -10;
|
||||
region_end = 0;
|
||||
region_end = 1;
|
||||
}
|
||||
|
||||
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
|
||||
|
@ -189,6 +191,10 @@ bool cm3_helper_translate_curve_to_hw_format(
|
|||
rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
|
||||
rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
|
||||
|
||||
rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
|
||||
rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
|
||||
rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
|
||||
|
||||
// All 3 color channels have same x
|
||||
corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
|
||||
dc_fixpt_from_int(region_start));
|
||||
|
@ -259,15 +265,18 @@ bool cm3_helper_translate_curve_to_hw_format(
|
|||
|
||||
rgb = rgb_resulted;
|
||||
rgb_plus_1 = rgb_resulted + 1;
|
||||
rgb_minus_1 = rgb;
|
||||
|
||||
i = 1;
|
||||
while (i != hw_points + 1) {
|
||||
if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
|
||||
rgb_plus_1->red = rgb->red;
|
||||
if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
|
||||
rgb_plus_1->green = rgb->green;
|
||||
if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
|
||||
rgb_plus_1->blue = rgb->blue;
|
||||
if (i >= hw_points - 1) {
|
||||
if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
|
||||
rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red);
|
||||
if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
|
||||
rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green);
|
||||
if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
|
||||
rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue);
|
||||
}
|
||||
|
||||
rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
|
||||
rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
|
||||
|
@ -283,6 +292,7 @@ bool cm3_helper_translate_curve_to_hw_format(
|
|||
}
|
||||
|
||||
++rgb_plus_1;
|
||||
rgb_minus_1 = rgb;
|
||||
++rgb;
|
||||
++i;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue