summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrunoslav Kovac2019-01-17 23:56:51 +0100
committerAlex Deucher2019-02-06 03:16:23 +0100
commit8f0159122714d38f89140993eb0a070f8eeb2e9d (patch)
treeb1e2637f4754d95680f5c2c87592d6c115378b34
parentdrm/amd/display: Check that vrefresh is in freesync range (diff)
downloadkernel-qcow2-linux-8f0159122714d38f89140993eb0a070f8eeb2e9d.tar.gz
kernel-qcow2-linux-8f0159122714d38f89140993eb0a070f8eeb2e9d.tar.xz
kernel-qcow2-linux-8f0159122714d38f89140993eb0a070f8eeb2e9d.zip
drm/amd/display: DGAM enabled for HDR
[Why] On HW that doesn't have input LUT, we may combine degamma with OS ramp Problem here is that it assumes DGAM is inverse of PQ or SRGB. It doesn't handle linear case, it would default to sRGB and always enable DGAM.. [How] Add handling for linear case. Also check for null ramp and instead of blowing up, assume it's identity. Signed-off-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c89
1 files changed, 52 insertions, 37 deletions
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 eefb85928298..0fbc8fbc3541 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -1765,68 +1765,85 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
{
struct dc_transfer_func_distributed_points *tf_pts = &input_tf->tf_pts;
struct dividers dividers;
-
struct pwl_float_data *rgb_user = NULL;
struct pwl_float_data_ex *curve = NULL;
struct gamma_pixel *axis_x = NULL;
struct pixel_gamma_point *coeff = NULL;
enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB;
+ uint32_t i;
bool ret = false;
if (input_tf->type == TF_TYPE_BYPASS)
return false;
- /* we can use hardcoded curve for plain SRGB TF */
+ /* we can use hardcoded curve for plain SRGB TF
+ * If linear, it's bypass if on user ramp
+ */
if (input_tf->type == TF_TYPE_PREDEFINED &&
- input_tf->tf == TRANSFER_FUNCTION_SRGB &&
- !mapUserRamp)
+ (input_tf->tf == TRANSFER_FUNCTION_SRGB ||
+ input_tf->tf == TRANSFER_FUNCTION_LINEAR) &&
+ !mapUserRamp)
return true;
input_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
- rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS,
- sizeof(*rgb_user),
- GFP_KERNEL);
- if (!rgb_user)
- goto rgb_user_alloc_fail;
+ if (mapUserRamp && ramp && ramp->type == GAMMA_RGB_256) {
+ rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS,
+ sizeof(*rgb_user),
+ GFP_KERNEL);
+ if (!rgb_user)
+ goto rgb_user_alloc_fail;
+
+ axis_x = kvcalloc(ramp->num_entries + _EXTRA_POINTS, sizeof(*axis_x),
+ GFP_KERNEL);
+ if (!axis_x)
+ goto axis_x_alloc_fail;
+
+ dividers.divider1 = dc_fixpt_from_fraction(3, 2);
+ dividers.divider2 = dc_fixpt_from_int(2);
+ dividers.divider3 = dc_fixpt_from_fraction(5, 2);
+
+ build_evenly_distributed_points(
+ axis_x,
+ ramp->num_entries,
+ dividers);
+
+ scale_gamma(rgb_user, ramp, dividers);
+ }
+
curve = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*curve),
- GFP_KERNEL);
+ GFP_KERNEL);
if (!curve)
goto curve_alloc_fail;
- axis_x = kvcalloc(ramp->num_entries + _EXTRA_POINTS, sizeof(*axis_x),
- GFP_KERNEL);
- if (!axis_x)
- goto axis_x_alloc_fail;
+
coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff),
- GFP_KERNEL);
+ GFP_KERNEL);
if (!coeff)
goto coeff_alloc_fail;
- dividers.divider1 = dc_fixpt_from_fraction(3, 2);
- dividers.divider2 = dc_fixpt_from_int(2);
- dividers.divider3 = dc_fixpt_from_fraction(5, 2);
-
tf = input_tf->tf;
- build_evenly_distributed_points(
- axis_x,
- ramp->num_entries,
- dividers);
-
- if (ramp->type == GAMMA_RGB_256 && mapUserRamp)
- scale_gamma(rgb_user, ramp, dividers);
- else if (ramp->type == GAMMA_RGB_FLOAT_1024)
- scale_gamma_dx(rgb_user, ramp, dividers);
-
if (tf == TRANSFER_FUNCTION_PQ)
build_de_pq(curve,
MAX_HW_POINTS,
coordinates_x);
- else
+ else if (tf == TRANSFER_FUNCTION_SRGB ||
+ tf == TRANSFER_FUNCTION_BT709)
build_degamma(curve,
MAX_HW_POINTS,
coordinates_x,
- tf == TRANSFER_FUNCTION_SRGB ? true:false);
+ tf == TRANSFER_FUNCTION_SRGB ? true : false);
+ else if (tf == TRANSFER_FUNCTION_LINEAR) {
+ // just copy coordinates_x into curve
+ i = 0;
+ while (i != MAX_HW_POINTS + 1) {
+ curve[i].r = coordinates_x[i].x;
+ curve[i].g = curve[i].r;
+ curve[i].b = curve[i].r;
+ i++;
+ }
+ } else
+ goto invalid_tf_fail;
tf_pts->end_exponent = 0;
tf_pts->x_point_at_y1_red = 1;
@@ -1836,23 +1853,21 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
coordinates_x, axis_x, curve,
MAX_HW_POINTS, tf_pts,
- mapUserRamp && ramp->type != GAMMA_CUSTOM);
- if (ramp->type == GAMMA_CUSTOM)
- apply_lut_1d(ramp, MAX_HW_POINTS, tf_pts);
+ mapUserRamp && ramp && ramp->type == GAMMA_RGB_256);
ret = true;
+invalid_tf_fail:
kvfree(coeff);
coeff_alloc_fail:
- kvfree(axis_x);
-axis_x_alloc_fail:
kvfree(curve);
curve_alloc_fail:
+ kvfree(axis_x);
+axis_x_alloc_fail:
kvfree(rgb_user);
rgb_user_alloc_fail:
return ret;
-
}