Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.

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>

authored by

Calvin Hou and committed by
Alex Deucher
ef08f9c2 8c2f14c3

+18 -8
+18 -8
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
··· 113 113 struct pwl_result_data *rgb_resulted; 114 114 struct pwl_result_data *rgb; 115 115 struct pwl_result_data *rgb_plus_1; 116 + struct pwl_result_data *rgb_minus_1; 116 117 struct fixed31_32 end_value; 117 118 118 119 int32_t region_start, region_end; ··· 141 140 region_start = -MAX_LOW_POINT; 142 141 region_end = NUMBER_REGIONS - MAX_LOW_POINT; 143 142 } else { 144 - /* 10 segments 143 + /* 11 segments 145 144 * segment is from 2^-10 to 2^0 146 145 * There are less than 256 points, for optimization 147 146 */ ··· 155 154 seg_distr[7] = 4; 156 155 seg_distr[8] = 4; 157 156 seg_distr[9] = 4; 157 + seg_distr[10] = 1; 158 158 159 159 region_start = -10; 160 - region_end = 0; 160 + region_end = 1; 161 161 } 162 162 163 163 for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) ··· 190 188 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; 191 189 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; 192 190 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; 191 + 192 + rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red; 193 + rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green; 194 + rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue; 193 195 194 196 // All 3 color channels have same x 195 197 corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), ··· 265 259 266 260 rgb = rgb_resulted; 267 261 rgb_plus_1 = rgb_resulted + 1; 262 + rgb_minus_1 = rgb; 268 263 269 264 i = 1; 270 265 while (i != hw_points + 1) { 271 - if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 272 - rgb_plus_1->red = rgb->red; 273 - if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 274 - rgb_plus_1->green = rgb->green; 275 - if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 276 - rgb_plus_1->blue = rgb->blue; 266 + if (i >= hw_points - 1) { 267 + if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 268 + rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red); 269 + if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 270 + rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green); 271 + if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 272 + rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue); 273 + } 277 274 278 275 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); 279 276 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); ··· 292 283 } 293 284 294 285 ++rgb_plus_1; 286 + rgb_minus_1 = rgb; 295 287 ++rgb; 296 288 ++i; 297 289 }