drm/amd/display: Fix OGAM LUT calculation precision
authorFelipe <Felipe.Clark@amd.com>
Mon, 30 Nov 2020 22:38:02 +0000 (17:38 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 15 Dec 2020 16:34:35 +0000 (11:34 -0500)
[Why]
The OGAM LUT precision was accumulating too much error
in the higher end.

[How]
Instead of calculating all points of the LUT in relation
to the previous ones, perform a full calculation in one
of the intermediate segments to stop error propagation.

Signed-off-by: Felipe Clark <Felipe.Clark@amd.com>
Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/modules/color/color_gamma.c

index eced40a..5c67e12 100644 (file)
 #include "opp.h"
 #include "color_gamma.h"
 
+/* When calculating LUT values the first region and at least one subsequent
+ * region are calculated with full precision. These defines are a demarcation
+ * of where the second region starts and ends.
+ * These are hardcoded values to avoid recalculating them in loops.
+ */
+#define PRECISE_LUT_REGION_START 224
+#define PRECISE_LUT_REGION_END 239
+
 static struct hw_x_point coordinates_x[MAX_HW_POINTS + 2];
 
 // these are helpers for calculations to reduce stack usage
@@ -346,7 +354,13 @@ static struct fixed31_32 translate_from_linear_space(
                                        dc_fixpt_recip(args->gamma));
                }
                scratch_1 = dc_fixpt_add(one, args->a3);
-               if (cal_buffer->buffer_index < 16)
+               /* In the first region (first 16 points) and in the
+                * region delimited by START/END we calculate with
+                * full precision to avoid error accumulation. 
+                */
+               if ((cal_buffer->buffer_index >= PRECISE_LUT_REGION_START &&
+                       cal_buffer->buffer_index <= PRECISE_LUT_REGION_END) ||
+                       (cal_buffer->buffer_index < 16))
                        scratch_2 = dc_fixpt_pow(args->arg,
                                        dc_fixpt_recip(args->gamma));
                else
@@ -397,9 +411,7 @@ static struct fixed31_32 translate_from_linear_space_long(
                                        dc_fixpt_recip(args->gamma))),
                                        args->a2);
        else
-               return dc_fixpt_mul(
-                       args->arg,
-                       args->a1);
+               return dc_fixpt_mul(args->arg, args->a1);
 }
 
 static struct fixed31_32 calculate_gamma22(struct fixed31_32 arg, bool use_eetf, struct calculate_buffer *cal_buffer)
@@ -717,7 +729,6 @@ static struct fixed31_32 calculate_mapped_value(
                BREAK_TO_DEBUGGER();
                result = dc_fixpt_zero;
        } else {
-               BREAK_TO_DEBUGGER();
                result = dc_fixpt_one;
        }
 
@@ -976,6 +987,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma,
                cal_buffer->buffer_index = 0; // see var definition for more info
        rgb += 32; // first 32 points have problems with fixed point, too small
        coord_x += 32;
+
        for (i = 32; i <= hw_points_num; i++) {
                if (!is_clipped) {
                        if (use_eetf) {