diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0073-drm-amd-display-Implement-PQ-curve-based-on-output-t.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0073-drm-amd-display-Implement-PQ-curve-based-on-output-t.patch | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0073-drm-amd-display-Implement-PQ-curve-based-on-output-t.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0073-drm-amd-display-Implement-PQ-curve-based-on-output-t.patch new file mode 100644 index 00000000..16e970c8 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0073-drm-amd-display-Implement-PQ-curve-based-on-output-t.patch @@ -0,0 +1,177 @@ +From 9d8fdc3b5509a38b2434adcef7ec918932d3c728 Mon Sep 17 00:00:00 2001 +From: Anthony Koo <Anthony.Koo@amd.com> +Date: Fri, 16 Dec 2016 12:12:03 -0500 +Subject: [PATCH 0073/4131] drm/amd/display: Implement PQ curve based on output + transfer function + +Refactor part 5 - Regamma programming should be dependent on Output +transfer function type + +Program sRGB gamma or PQ transfer function based on output transfer +function. + +Signed-off-by: Anthony Koo <anthony.koo@amd.com> +Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> +Acked-by: Harry Wentland <Harry.Wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 93 ++++++++++++++++++++-- + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 3 +- + drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h | 3 +- + 3 files changed, 92 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +index 854796a..973be8f 100644 +--- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c ++++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +@@ -791,6 +791,82 @@ static inline struct fixed31_32 calculate_oem_mapped_value( + max_index); + } + ++static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) ++{ ++ /* consts for PQ gamma formula. */ ++ const struct fixed31_32 m1 = ++ dal_fixed31_32_from_fraction(159301758, 1000000000); ++ const struct fixed31_32 m2 = ++ dal_fixed31_32_from_fraction(7884375, 100000); ++ const struct fixed31_32 c1 = ++ dal_fixed31_32_from_fraction(8359375, 10000000); ++ const struct fixed31_32 c2 = ++ dal_fixed31_32_from_fraction(188515625, 10000000); ++ const struct fixed31_32 c3 = ++ dal_fixed31_32_from_fraction(186875, 10000); ++ ++ struct fixed31_32 l_pow_m1; ++ struct fixed31_32 base; ++ ++ if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero)) ++ in_x = dal_fixed31_32_zero; ++ ++ l_pow_m1 = dal_fixed31_32_pow(in_x, m1); ++ base = dal_fixed31_32_div( ++ dal_fixed31_32_add(c1, ++ (dal_fixed31_32_mul(c2, l_pow_m1))), ++ dal_fixed31_32_add(dal_fixed31_32_one, ++ (dal_fixed31_32_mul(c3, l_pow_m1)))); ++ *out_y = dal_fixed31_32_pow(base, m2); ++} ++ ++static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, ++ struct pwl_float_data *rgb_oem, ++ struct pixel_gamma_point *coeff128_oem, ++ const struct core_gamma *ramp, ++ const struct core_surface *surface, ++ uint32_t hw_points_num, ++ const struct hw_x_point *coordinate_x, ++ const struct gamma_pixel *axis_x, ++ struct dividers dividers) ++{ ++ uint32_t i; ++ ++ struct pwl_float_data_ex *rgb = rgb_regamma; ++ const struct hw_x_point *coord_x = coordinate_x; ++ struct fixed31_32 x; ++ struct fixed31_32 output; ++ struct fixed31_32 scaling_factor = ++ dal_fixed31_32_from_fraction(8, 1000); ++ ++ /* use coord_x to retrieve coordinates chosen base on given user curve ++ * the x values are exponentially distributed and currently it is hard ++ * coded, the user curve shape is ignored. Need to recalculate coord_x ++ * based on input curve, translation from 256/1025 to 128 PWL points. ++ */ ++ for (i = 0; i <= hw_points_num; i++) { ++ /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125. ++ * FP 1.0 = 80nits ++ */ ++ x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor); ++ ++ compute_pq(x, &output); ++ ++ /* should really not happen? */ ++ if (dal_fixed31_32_lt(output, dal_fixed31_32_zero)) ++ output = dal_fixed31_32_zero; ++ else if (dal_fixed31_32_lt(dal_fixed31_32_one, output)) ++ output = dal_fixed31_32_one; ++ ++ rgb->r = output; ++ rgb->g = output; ++ rgb->b = output; ++ ++ ++coord_x; ++ ++rgb; ++ } ++} ++ + static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, + struct pwl_float_data *rgb_oem, + struct pixel_gamma_point *coeff128_oem, +@@ -1286,7 +1362,8 @@ static bool convert_to_custom_float( + + bool calculate_regamma_params(struct pwl_params *params, + const struct core_gamma *ramp, +- const struct core_surface *surface) ++ const struct core_surface *surface, ++ const struct core_stream *stream) + { + struct gamma_curve *arr_curve_points = params->arr_curve_points; + struct curve_points *arr_points = params->arr_points; +@@ -1301,7 +1378,6 @@ bool calculate_regamma_params(struct pwl_params *params, + struct pixel_gamma_point *coeff128_oem = NULL; + struct pixel_gamma_point *coeff128 = NULL; + +- + bool ret = false; + + coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); +@@ -1341,9 +1417,16 @@ bool calculate_regamma_params(struct pwl_params *params, + setup_distribution_points(arr_curve_points, arr_points, + ¶ms->hw_points_num, coordinates_x); + +- build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, +- ramp, surface, params->hw_points_num, +- coordinates_x, axix_x_256, dividers); ++ if (stream->public.out_transfer_func && ++ stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { ++ build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem, ++ ramp, surface, params->hw_points_num, ++ coordinates_x, axix_x_256, dividers); ++ } else { ++ build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, ++ ramp, surface, params->hw_points_num, ++ coordinates_x, axix_x_256, dividers); ++ } + + map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, + coordinates_x, axix_x_256, &ramp->public, rgb_regamma, +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +index 72017d5..2f79075 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +@@ -303,7 +303,8 @@ static bool dce110_set_output_transfer_func( + + opp->funcs->opp_power_on_regamma_lut(opp, true); + +- if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { ++ if (ramp && calculate_regamma_params( ++ regamma_params, ramp, surface, stream)) { + opp->funcs->opp_program_regamma_pwl(opp, regamma_params); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + } else { +diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h +index e2c63fd..0712268 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h +@@ -14,6 +14,7 @@ + + bool calculate_regamma_params(struct pwl_params *params, + const struct core_gamma *ramp, +- const struct core_surface *surface); ++ const struct core_surface *surface, ++ const struct core_stream *stream); + + #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */ +-- +2.7.4 + |