diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
9 files changed, 303 insertions, 119 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/color/Makefile b/drivers/gpu/drm/amd/display/modules/color/Makefile index 65c33a76951a..e66c19a840c2 100644 --- a/drivers/gpu/drm/amd/display/modules/color/Makefile +++ b/drivers/gpu/drm/amd/display/modules/color/Makefile @@ -23,7 +23,7 @@ # Makefile for the color sub-module of DAL. # -MOD_COLOR = color_gamma.o +MOD_COLOR = color_gamma.o color_table.o AMD_DAL_MOD_COLOR = $(addprefix $(AMDDALPATH)/modules/color/,$(MOD_COLOR)) #$(info ************ DAL COLOR MODULE MAKEFILE ************) 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 bcfe34ef8c28..b8695660b480 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -30,20 +30,10 @@ #include "opp.h" #include "color_gamma.h" -#define NUM_PTS_IN_REGION 16 -#define NUM_REGIONS 32 -#define MAX_HW_POINTS (NUM_PTS_IN_REGION*NUM_REGIONS) - static struct hw_x_point coordinates_x[MAX_HW_POINTS + 2]; -static struct fixed31_32 pq_table[MAX_HW_POINTS + 2]; -static struct fixed31_32 de_pq_table[MAX_HW_POINTS + 2]; - // these are helpers for calculations to reduce stack usage // do not depend on these being preserved across calls -static struct fixed31_32 scratch_1; -static struct fixed31_32 scratch_2; -static struct translate_from_linear_space_args scratch_gamma_args; /* Helper to optimize gamma calculation, only use in translate_from_linear, in * particular the dc_fixpt_pow function which is very expensive @@ -56,9 +46,6 @@ static struct translate_from_linear_space_args scratch_gamma_args; * just multiply with 2^gamma which can be computed once, and save the result so we * recursively compute all the values. */ -static struct fixed31_32 pow_buffer[NUM_PTS_IN_REGION]; -static struct fixed31_32 gamma_of_2; // 2^gamma -int pow_buffer_ptr = -1; /*sRGB 709 2.2 2.4 P3*/ static const int32_t gamma_numerator01[] = { 31308, 180000, 0, 0, 0}; static const int32_t gamma_numerator02[] = { 12920, 4500, 0, 0, 0}; @@ -66,9 +53,6 @@ static const int32_t gamma_numerator03[] = { 55, 99, 0, 0, 0}; static const int32_t gamma_numerator04[] = { 55, 99, 0, 0, 0}; static const int32_t gamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600}; -static bool pq_initialized; /* = false; */ -static bool de_pq_initialized; /* = false; */ - /* one-time setup of X points */ void setup_x_points_distribution(void) { @@ -250,6 +234,8 @@ void precompute_pq(void) struct fixed31_32 scaling_factor = dc_fixpt_from_fraction(80, 10000); + struct fixed31_32 *pq_table = mod_color_get_table(type_pq_table); + /* pow function has problems with arguments too small */ for (i = 0; i < 32; i++) pq_table[i] = dc_fixpt_zero; @@ -269,7 +255,7 @@ void precompute_de_pq(void) uint32_t begin_index, end_index; struct fixed31_32 scaling_factor = dc_fixpt_from_int(125); - + struct fixed31_32 *de_pq_table = mod_color_get_table(type_de_pq_table); /* X points is 2^-25 to 2^7 * De-gamma X is 2^-12 to 2^0 – we are skipping first -12-(-25) = 13 regions */ @@ -339,6 +325,9 @@ static struct fixed31_32 translate_from_linear_space( { const struct fixed31_32 one = dc_fixpt_from_int(1); + struct fixed31_32 scratch_1, scratch_2; + struct calculate_buffer *cal_buffer = args->cal_buffer; + if (dc_fixpt_le(one, args->arg)) return one; @@ -352,21 +341,21 @@ static struct fixed31_32 translate_from_linear_space( return scratch_1; } else if (dc_fixpt_le(args->a0, args->arg)) { - if (pow_buffer_ptr == 0) { - gamma_of_2 = dc_fixpt_pow(dc_fixpt_from_int(2), + if (cal_buffer->buffer_index == 0) { + cal_buffer->gamma_of_2 = dc_fixpt_pow(dc_fixpt_from_int(2), dc_fixpt_recip(args->gamma)); } scratch_1 = dc_fixpt_add(one, args->a3); - if (pow_buffer_ptr < 16) + if (cal_buffer->buffer_index < 16) scratch_2 = dc_fixpt_pow(args->arg, dc_fixpt_recip(args->gamma)); else - scratch_2 = dc_fixpt_mul(gamma_of_2, - pow_buffer[pow_buffer_ptr%16]); + scratch_2 = dc_fixpt_mul(cal_buffer->gamma_of_2, + cal_buffer->buffer[cal_buffer->buffer_index%16]); - if (pow_buffer_ptr != -1) { - pow_buffer[pow_buffer_ptr%16] = scratch_2; - pow_buffer_ptr++; + if (cal_buffer->buffer_index != -1) { + cal_buffer->buffer[cal_buffer->buffer_index%16] = scratch_2; + cal_buffer->buffer_index++; } scratch_1 = dc_fixpt_mul(scratch_1, scratch_2); @@ -413,15 +402,17 @@ static struct fixed31_32 translate_from_linear_space_long( args->a1); } -static struct fixed31_32 calculate_gamma22(struct fixed31_32 arg, bool use_eetf) +static struct fixed31_32 calculate_gamma22(struct fixed31_32 arg, bool use_eetf, struct calculate_buffer *cal_buffer) { struct fixed31_32 gamma = dc_fixpt_from_fraction(22, 10); + struct translate_from_linear_space_args scratch_gamma_args; scratch_gamma_args.arg = arg; scratch_gamma_args.a0 = dc_fixpt_zero; scratch_gamma_args.a1 = dc_fixpt_zero; scratch_gamma_args.a2 = dc_fixpt_zero; scratch_gamma_args.a3 = dc_fixpt_zero; + scratch_gamma_args.cal_buffer = cal_buffer; scratch_gamma_args.gamma = gamma; if (use_eetf) @@ -467,14 +458,18 @@ static struct fixed31_32 translate_to_linear_space( static struct fixed31_32 translate_from_linear_space_ex( struct fixed31_32 arg, struct gamma_coefficients *coeff, - uint32_t color_index) + uint32_t color_index, + struct calculate_buffer *cal_buffer) { + struct translate_from_linear_space_args scratch_gamma_args; + scratch_gamma_args.arg = arg; scratch_gamma_args.a0 = coeff->a0[color_index]; scratch_gamma_args.a1 = coeff->a1[color_index]; scratch_gamma_args.a2 = coeff->a2[color_index]; scratch_gamma_args.a3 = coeff->a3[color_index]; scratch_gamma_args.gamma = coeff->user_gamma[color_index]; + scratch_gamma_args.cal_buffer = cal_buffer; return translate_from_linear_space(&scratch_gamma_args); } @@ -742,10 +737,11 @@ static void build_pq(struct pwl_float_data_ex *rgb_regamma, struct fixed31_32 output; struct fixed31_32 scaling_factor = dc_fixpt_from_fraction(sdr_white_level, 10000); + struct fixed31_32 *pq_table = mod_color_get_table(type_pq_table); - if (!pq_initialized && sdr_white_level == 80) { + if (!mod_color_is_table_init(type_pq_table) && sdr_white_level == 80) { precompute_pq(); - pq_initialized = true; + mod_color_set_table_init_state(type_pq_table, true); } /* TODO: start index is from segment 2^-24, skipping first segment @@ -787,12 +783,12 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq, { uint32_t i; struct fixed31_32 output; - + struct fixed31_32 *de_pq_table = mod_color_get_table(type_de_pq_table); struct fixed31_32 scaling_factor = dc_fixpt_from_int(125); - if (!de_pq_initialized) { + if (!mod_color_is_table_init(type_de_pq_table)) { precompute_de_pq(); - de_pq_initialized = true; + mod_color_set_table_init_state(type_de_pq_table, true); } @@ -811,7 +807,9 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq, static bool build_regamma(struct pwl_float_data_ex *rgb_regamma, uint32_t hw_points_num, - const struct hw_x_point *coordinate_x, enum dc_transfer_func_predefined type) + const struct hw_x_point *coordinate_x, + enum dc_transfer_func_predefined type, + struct calculate_buffer *cal_buffer) { uint32_t i; bool ret = false; @@ -827,20 +825,21 @@ static bool build_regamma(struct pwl_float_data_ex *rgb_regamma, if (!build_coefficients(coeff, type)) goto release; - memset(pow_buffer, 0, NUM_PTS_IN_REGION * sizeof(struct fixed31_32)); - pow_buffer_ptr = 0; // see variable definition for more info + memset(cal_buffer->buffer, 0, NUM_PTS_IN_REGION * sizeof(struct fixed31_32)); + cal_buffer->buffer_index = 0; // see variable definition for more info + i = 0; while (i <= hw_points_num) { /*TODO use y vs r,g,b*/ rgb->r = translate_from_linear_space_ex( - coord_x->x, coeff, 0); + coord_x->x, coeff, 0, cal_buffer); rgb->g = rgb->r; rgb->b = rgb->r; ++coord_x; ++rgb; ++i; } - pow_buffer_ptr = -1; // reset back to no optimize + cal_buffer->buffer_index = -1; ret = true; release: kvfree(coeff); @@ -932,7 +931,8 @@ static void hermite_spline_eetf(struct fixed31_32 input_x, static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, uint32_t hw_points_num, const struct hw_x_point *coordinate_x, - const struct freesync_hdr_tf_params *fs_params) + const struct freesync_hdr_tf_params *fs_params, + struct calculate_buffer *cal_buffer) { uint32_t i; struct pwl_float_data_ex *rgb = rgb_regamma; @@ -969,7 +969,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, max_content = max_display; if (!use_eetf) - pow_buffer_ptr = 0; // see var definition for more info + 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++) { @@ -988,7 +988,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, if (dc_fixpt_lt(scaledX, dc_fixpt_zero)) output = dc_fixpt_zero; else - output = calculate_gamma22(scaledX, use_eetf); + output = calculate_gamma22(scaledX, use_eetf, cal_buffer); rgb->r = output; rgb->g = output; @@ -1008,7 +1008,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, ++coord_x; ++rgb; } - pow_buffer_ptr = -1; + cal_buffer->buffer_index = -1; return true; } @@ -1606,7 +1606,7 @@ static void build_new_custom_resulted_curve( } static void apply_degamma_for_user_regamma(struct pwl_float_data_ex *rgb_regamma, - uint32_t hw_points_num) + uint32_t hw_points_num, struct calculate_buffer *cal_buffer) { uint32_t i; @@ -1619,7 +1619,7 @@ static void apply_degamma_for_user_regamma(struct pwl_float_data_ex *rgb_regamma i = 0; while (i != hw_points_num + 1) { rgb->r = translate_from_linear_space_ex( - coord_x->x, &coeff, 0); + coord_x->x, &coeff, 0, cal_buffer); rgb->g = rgb->r; rgb->b = rgb->r; ++coord_x; @@ -1674,7 +1674,8 @@ static bool map_regamma_hw_to_x_user( #define _EXTRA_POINTS 3 bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf, - const struct regamma_lut *regamma) + const struct regamma_lut *regamma, + struct calculate_buffer *cal_buffer) { struct gamma_coefficients coeff; const struct hw_x_point *coord_x = coordinates_x; @@ -1706,11 +1707,11 @@ bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf, } while (i != MAX_HW_POINTS + 1) { output_tf->tf_pts.red[i] = translate_from_linear_space_ex( - coord_x->x, &coeff, 0); + coord_x->x, &coeff, 0, cal_buffer); output_tf->tf_pts.green[i] = translate_from_linear_space_ex( - coord_x->x, &coeff, 1); + coord_x->x, &coeff, 1, cal_buffer); output_tf->tf_pts.blue[i] = translate_from_linear_space_ex( - coord_x->x, &coeff, 2); + coord_x->x, &coeff, 2, cal_buffer); ++coord_x; ++i; } @@ -1723,7 +1724,8 @@ bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf, } bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf, - const struct regamma_lut *regamma) + const struct regamma_lut *regamma, + struct calculate_buffer *cal_buffer) { struct dc_transfer_func_distributed_points *tf_pts = &output_tf->tf_pts; struct dividers dividers; @@ -1756,7 +1758,7 @@ bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf, scale_user_regamma_ramp(rgb_user, ®amma->ramp, dividers); if (regamma->flags.bits.applyDegamma == 1) { - apply_degamma_for_user_regamma(rgb_regamma, MAX_HW_POINTS); + apply_degamma_for_user_regamma(rgb_regamma, MAX_HW_POINTS, cal_buffer); copy_rgb_regamma_to_coordinates_x(coordinates_x, MAX_HW_POINTS, rgb_regamma); } @@ -1943,7 +1945,8 @@ static bool calculate_curve(enum dc_transfer_func_predefined trans, struct dc_transfer_func_distributed_points *points, struct pwl_float_data_ex *rgb_regamma, const struct freesync_hdr_tf_params *fs_params, - uint32_t sdr_ref_white_level) + uint32_t sdr_ref_white_level, + struct calculate_buffer *cal_buffer) { uint32_t i; bool ret = false; @@ -1979,7 +1982,8 @@ static bool calculate_curve(enum dc_transfer_func_predefined trans, build_freesync_hdr(rgb_regamma, MAX_HW_POINTS, coordinates_x, - fs_params); + fs_params, + cal_buffer); ret = true; } else if (trans == TRANSFER_FUNCTION_HLG) { @@ -2008,7 +2012,8 @@ static bool calculate_curve(enum dc_transfer_func_predefined trans, build_regamma(rgb_regamma, MAX_HW_POINTS, coordinates_x, - trans); + trans, + cal_buffer); ret = true; } @@ -2018,7 +2023,8 @@ static bool calculate_curve(enum dc_transfer_func_predefined trans, bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, const struct dc_gamma *ramp, bool mapUserRamp, bool canRomBeUsed, - const struct freesync_hdr_tf_params *fs_params) + const struct freesync_hdr_tf_params *fs_params, + struct calculate_buffer *cal_buffer) { struct dc_transfer_func_distributed_points *tf_pts = &output_tf->tf_pts; struct dividers dividers; @@ -2090,7 +2096,8 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, tf_pts, rgb_regamma, fs_params, - output_tf->sdr_ref_white_level); + output_tf->sdr_ref_white_level, + cal_buffer); if (ret) { map_regamma_hw_to_x_user(ramp, coeff, rgb_user, diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h index 7f56226ba77a..37ffbef6602b 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h @@ -26,6 +26,8 @@ #ifndef COLOR_MOD_COLOR_GAMMA_H_ #define COLOR_MOD_COLOR_GAMMA_H_ +#include "color_table.h" + struct dc_transfer_func; struct dc_gamma; struct dc_transfer_func_distributed_points; @@ -83,6 +85,12 @@ struct freesync_hdr_tf_params { unsigned int skip_tm; // skip tm }; +struct calculate_buffer { + int buffer_index; + struct fixed31_32 buffer[NUM_PTS_IN_REGION]; + struct fixed31_32 gamma_of_2; +}; + struct translate_from_linear_space_args { struct fixed31_32 arg; struct fixed31_32 a0; @@ -90,6 +98,7 @@ struct translate_from_linear_space_args { struct fixed31_32 a2; struct fixed31_32 a3; struct fixed31_32 gamma; + struct calculate_buffer *cal_buffer; }; void setup_x_points_distribution(void); @@ -99,7 +108,8 @@ void precompute_de_pq(void); bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, const struct dc_gamma *ramp, bool mapUserRamp, bool canRomBeUsed, - const struct freesync_hdr_tf_params *fs_params); + const struct freesync_hdr_tf_params *fs_params, + struct calculate_buffer *cal_buffer); bool mod_color_calculate_degamma_params(struct dc_color_caps *dc_caps, struct dc_transfer_func *output_tf, @@ -109,10 +119,12 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, struct dc_transfer_func_distributed_points *points); bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf, - const struct regamma_lut *regamma); + const struct regamma_lut *regamma, + struct calculate_buffer *cal_buffer); bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf, - const struct regamma_lut *regamma); + const struct regamma_lut *regamma, + struct calculate_buffer *cal_buffer); #endif /* COLOR_MOD_COLOR_GAMMA_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/color/color_table.c b/drivers/gpu/drm/amd/display/modules/color/color_table.c new file mode 100644 index 000000000000..692e536e7d05 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color_table.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Advanced Micro Devices, Inc. (unpublished) + * + * All rights reserved. This notice is intended as a precaution against + * inadvertent publication and does not imply publication or any waiver + * of confidentiality. The year included in the foregoing notice is the + * year of creation of the work. + */ + +#include "color_table.h" + +static struct fixed31_32 pq_table[MAX_HW_POINTS + 2]; +static struct fixed31_32 de_pq_table[MAX_HW_POINTS + 2]; +static bool pq_initialized; +static bool de_pg_initialized; + +bool mod_color_is_table_init(enum table_type type) +{ + bool ret = false; + + if (type == type_pq_table) + ret = pq_initialized; + if (type == type_de_pq_table) + ret = de_pg_initialized; + + return ret; +} + +struct fixed31_32 *mod_color_get_table(enum table_type type) +{ + struct fixed31_32 *table = NULL; + + if (type == type_pq_table) + table = pq_table; + if (type == type_de_pq_table) + table = de_pq_table; + + return table; +} + +void mod_color_set_table_init_state(enum table_type type, bool state) +{ + if (type == type_pq_table) + pq_initialized = state; + if (type == type_de_pq_table) + de_pg_initialized = state; +} + diff --git a/drivers/gpu/drm/amd/display/modules/color/color_table.h b/drivers/gpu/drm/amd/display/modules/color/color_table.h new file mode 100644 index 000000000000..2621dd619402 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color_table.h @@ -0,0 +1,47 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef COLOR_MOD_COLOR_TABLE_H_ +#define COLOR_MOD_COLOR_TABLE_H_ + +#include "dc_types.h" + +#define NUM_PTS_IN_REGION 16 +#define NUM_REGIONS 32 +#define MAX_HW_POINTS (NUM_PTS_IN_REGION*NUM_REGIONS) + +enum table_type { + type_pq_table, + type_de_pq_table +}; + +bool mod_color_is_table_init(enum table_type type); + +struct fixed31_32 *mod_color_get_table(enum table_type type); + +void mod_color_set_table_init_state(enum table_type type, bool state); + +#endif /* COLOR_MOD_COLOR_TABLE_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index eb7421e83b86..81820f3d6b3b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -32,7 +32,7 @@ #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 -#define MIN_REFRESH_RANGE_IN_US 10000000 +#define MIN_REFRESH_RANGE 10 /* Refresh rate ramp at a fixed rate of 65 Hz/second */ #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65) /* Number of elements in the render times cache array */ @@ -760,9 +760,35 @@ static void build_vrr_infopacket_v2(enum signal_type signal, infopacket->valid = true; } +#ifndef TRIM_FSFT +static void build_vrr_infopacket_fast_transport_data( + bool ftActive, + unsigned int ftOutputRate, + struct dc_info_packet *infopacket) +{ + /* PB9 : bit7 - fast transport Active*/ + unsigned char activeBit = (ftActive) ? 1 << 7 : 0; + + infopacket->sb[1] &= ~activeBit; //clear bit + infopacket->sb[1] |= activeBit; //set bit + + /* PB13 : Target Output Pixel Rate [kHz] - bits 7:0 */ + infopacket->sb[13] = ftOutputRate & 0xFF; + + /* PB14 : Target Output Pixel Rate [kHz] - bits 15:8 */ + infopacket->sb[14] = (ftOutputRate >> 8) & 0xFF; + + /* PB15 : Target Output Pixel Rate [kHz] - bits 23:16 */ + infopacket->sb[15] = (ftOutputRate >> 16) & 0xFF; + +} +#endif static void build_vrr_infopacket_v3(enum signal_type signal, const struct mod_vrr_params *vrr, +#ifndef TRIM_FSFT + bool ftActive, unsigned int ftOutputRate, +#endif enum color_transfer_func app_tf, struct dc_info_packet *infopacket) { @@ -773,6 +799,13 @@ static void build_vrr_infopacket_v3(enum signal_type signal, build_vrr_infopacket_fs2_data(app_tf, infopacket); +#ifndef TRIM_FSFT + build_vrr_infopacket_fast_transport_data( + ftActive, + ftOutputRate, + infopacket); +#endif + build_vrr_infopacket_checksum(&payload_size, infopacket); infopacket->valid = true; @@ -790,12 +823,23 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, * Check if Freesync is supported. Return if false. If true, * set the corresponding bit in the info packet */ - if (!vrr->supported || (!vrr->send_info_frame)) + if (!vrr->send_info_frame) return; switch (packet_type) { case PACKET_TYPE_FS_V3: +#ifndef TRIM_FSFT + // always populate with pixel rate. + build_vrr_infopacket_v3( + stream->signal, vrr, + stream->timing.flags.FAST_TRANSPORT, + (stream->timing.flags.FAST_TRANSPORT) ? + stream->timing.fast_transport_output_rate_100hz : + stream->timing.pix_clk_100hz, + app_tf, infopacket); +#else build_vrr_infopacket_v3(stream->signal, vrr, app_tf, infopacket); +#endif break; case PACKET_TYPE_FS_V2: build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket); @@ -878,8 +922,8 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, else in_out_vrr->fixed_refresh_in_uhz = 0; - refresh_range = in_out_vrr->max_refresh_in_uhz - - in_out_vrr->min_refresh_in_uhz; + refresh_range = div_u64(in_out_vrr->max_refresh_in_uhz + 500000, 1000000) - ++ div_u64(in_out_vrr->min_refresh_in_uhz + 500000, 1000000); in_out_vrr->supported = true; } @@ -918,7 +962,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, in_out_vrr->adjust.v_total_min = stream->timing.v_total; in_out_vrr->adjust.v_total_max = stream->timing.v_total; } else if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE && - refresh_range >= MIN_REFRESH_RANGE_IN_US) { + refresh_range >= MIN_REFRESH_RANGE) { in_out_vrr->adjust.v_total_min = calc_v_total_from_refresh(stream, @@ -1105,16 +1149,10 @@ unsigned long long mod_freesync_calc_nominal_field_rate( return nominal_field_rate_in_uhz; } -bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, - const struct dc_stream_state *stream, - uint32_t min_refresh_cap_in_uhz, +bool mod_freesync_is_valid_range(uint32_t min_refresh_cap_in_uhz, uint32_t max_refresh_cap_in_uhz, - uint32_t min_refresh_request_in_uhz, - uint32_t max_refresh_request_in_uhz) + uint32_t nominal_field_rate_in_uhz) { - /* Calculate nominal field rate for stream */ - unsigned long long nominal_field_rate_in_uhz = - mod_freesync_calc_nominal_field_rate(stream); /* Typically nominal refresh calculated can have some fractional part. * Allow for some rounding error of actual video timing by taking floor @@ -1153,8 +1191,6 @@ bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, div_u64(nominal_field_rate_in_uhz + 500000, 1000000); min_refresh_cap_in_uhz /= 1000000; max_refresh_cap_in_uhz /= 1000000; - min_refresh_request_in_uhz /= 1000000; - max_refresh_request_in_uhz /= 1000000; // Check nominal is within range if (nominal_field_rate_in_uhz > max_refresh_cap_in_uhz || @@ -1165,23 +1201,12 @@ bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, if (nominal_field_rate_in_uhz < max_refresh_cap_in_uhz) max_refresh_cap_in_uhz = nominal_field_rate_in_uhz; - // Don't allow min > max - if (min_refresh_request_in_uhz > max_refresh_request_in_uhz) - return false; - // Check min is within range - if (min_refresh_request_in_uhz > max_refresh_cap_in_uhz || - min_refresh_request_in_uhz < min_refresh_cap_in_uhz) - return false; - - // Check max is within range - if (max_refresh_request_in_uhz > max_refresh_cap_in_uhz || - max_refresh_request_in_uhz < min_refresh_cap_in_uhz) + if (min_refresh_cap_in_uhz > max_refresh_cap_in_uhz) return false; // For variable range, check for at least 10 Hz range - if ((max_refresh_request_in_uhz != min_refresh_request_in_uhz) && - (max_refresh_request_in_uhz - min_refresh_request_in_uhz < 10)) + if (nominal_field_rate_in_uhz - min_refresh_cap_in_uhz < 10) return false; return true; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 0ba3cf7f336a..c80fc10d732c 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -170,12 +170,9 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, unsigned long long mod_freesync_calc_nominal_field_rate( const struct dc_stream_state *stream); -bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, - const struct dc_stream_state *stream, - uint32_t min_refresh_cap_in_uhz, +bool mod_freesync_is_valid_range(uint32_t min_refresh_cap_in_uhz, uint32_t max_refresh_cap_in_uhz, - uint32_t min_refresh_request_in_uhz, - uint32_t max_refresh_request_in_uhz); + uint32_t nominal_field_rate_in_uhz); diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h index 3812094b52e8..4220fd8fdd60 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h @@ -36,7 +36,13 @@ struct mod_stats_caps { bool dummy; }; -struct mod_stats *mod_stats_create(struct dc *dc); +struct mod_stats_init_params { + unsigned int stats_enable; + unsigned int stats_entries; +}; + +struct mod_stats *mod_stats_create(struct dc *dc, + struct mod_stats_init_params *init_params); void mod_stats_destroy(struct mod_stats *mod_stats); diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index 8c37bcc27132..859724771a75 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -27,8 +27,11 @@ #include "dc/inc/hw/abm.h" #include "dc.h" #include "core_types.h" +#include "dmub_cmd.h" #define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b)) +#define bswap16_based_on_endian(big_endian, value) \ + (big_endian) ? cpu_to_be16(value) : cpu_to_le16(value) /* Possible Min Reduction config from least aggressive to most aggressive * 0 1 2 3 4 5 6 7 8 9 10 11 12 @@ -350,6 +353,7 @@ void fill_iram_v_2(struct iram_table_v_2 *ram_table, struct dmcu_iram_parameters ram_table->bright_pos_gain[4][1] = 0x20; ram_table->bright_pos_gain[4][2] = 0x20; ram_table->bright_pos_gain[4][3] = 0x20; + ram_table->bright_neg_gain[0][0] = 0x00; ram_table->bright_neg_gain[0][1] = 0x00; ram_table->bright_neg_gain[0][2] = 0x00; ram_table->bright_neg_gain[0][3] = 0x00; @@ -624,30 +628,30 @@ void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame ram_table->iir_curve[4] = 0x65; //Gamma 2.2 - ram_table->crgb_thresh[0] = (big_endian) ? cpu_to_be16(0x127c) : cpu_to_le16(0x127c); - ram_table->crgb_thresh[1] = (big_endian) ? cpu_to_be16(0x151b) : cpu_to_le16(0x151b); - ram_table->crgb_thresh[2] = (big_endian) ? cpu_to_be16(0x17d5) : cpu_to_le16(0x17d5); - ram_table->crgb_thresh[3] = (big_endian) ? cpu_to_be16(0x1a56) : cpu_to_le16(0x1a56); - ram_table->crgb_thresh[4] = (big_endian) ? cpu_to_be16(0x1c83) : cpu_to_le16(0x1c83); - ram_table->crgb_thresh[5] = (big_endian) ? cpu_to_be16(0x1e72) : cpu_to_le16(0x1e72); - ram_table->crgb_thresh[6] = (big_endian) ? cpu_to_be16(0x20f0) : cpu_to_le16(0x20f0); - ram_table->crgb_thresh[7] = (big_endian) ? cpu_to_be16(0x232b) : cpu_to_le16(0x232b); - ram_table->crgb_offset[0] = (big_endian) ? cpu_to_be16(0x2999) : cpu_to_le16(0x2999); - ram_table->crgb_offset[1] = (big_endian) ? cpu_to_be16(0x3999) : cpu_to_le16(0x3999); - ram_table->crgb_offset[2] = (big_endian) ? cpu_to_be16(0x4666) : cpu_to_le16(0x4666); - ram_table->crgb_offset[3] = (big_endian) ? cpu_to_be16(0x5999) : cpu_to_le16(0x5999); - ram_table->crgb_offset[4] = (big_endian) ? cpu_to_be16(0x6333) : cpu_to_le16(0x6333); - ram_table->crgb_offset[5] = (big_endian) ? cpu_to_be16(0x7800) : cpu_to_le16(0x7800); - ram_table->crgb_offset[6] = (big_endian) ? cpu_to_be16(0x8c00) : cpu_to_le16(0x8c00); - ram_table->crgb_offset[7] = (big_endian) ? cpu_to_be16(0xa000) : cpu_to_le16(0xa000); - ram_table->crgb_slope[0] = (big_endian) ? cpu_to_be16(0x3609) : cpu_to_le16(0x3609); - ram_table->crgb_slope[1] = (big_endian) ? cpu_to_be16(0x2dfa) : cpu_to_le16(0x2dfa); - ram_table->crgb_slope[2] = (big_endian) ? cpu_to_be16(0x27ea) : cpu_to_le16(0x27ea); - ram_table->crgb_slope[3] = (big_endian) ? cpu_to_be16(0x235d) : cpu_to_le16(0x235d); - ram_table->crgb_slope[4] = (big_endian) ? cpu_to_be16(0x2042) : cpu_to_le16(0x2042); - ram_table->crgb_slope[5] = (big_endian) ? cpu_to_be16(0x1dc3) : cpu_to_le16(0x1dc3); - ram_table->crgb_slope[6] = (big_endian) ? cpu_to_be16(0x1b1a) : cpu_to_le16(0x1b1a); - ram_table->crgb_slope[7] = (big_endian) ? cpu_to_be16(0x1910) : cpu_to_le16(0x1910); + ram_table->crgb_thresh[0] = bswap16_based_on_endian(big_endian, 0x127c); + ram_table->crgb_thresh[1] = bswap16_based_on_endian(big_endian, 0x151b); + ram_table->crgb_thresh[2] = bswap16_based_on_endian(big_endian, 0x17d5); + ram_table->crgb_thresh[3] = bswap16_based_on_endian(big_endian, 0x1a56); + ram_table->crgb_thresh[4] = bswap16_based_on_endian(big_endian, 0x1c83); + ram_table->crgb_thresh[5] = bswap16_based_on_endian(big_endian, 0x1e72); + ram_table->crgb_thresh[6] = bswap16_based_on_endian(big_endian, 0x20f0); + ram_table->crgb_thresh[7] = bswap16_based_on_endian(big_endian, 0x232b); + ram_table->crgb_offset[0] = bswap16_based_on_endian(big_endian, 0x2999); + ram_table->crgb_offset[1] = bswap16_based_on_endian(big_endian, 0x3999); + ram_table->crgb_offset[2] = bswap16_based_on_endian(big_endian, 0x4666); + ram_table->crgb_offset[3] = bswap16_based_on_endian(big_endian, 0x5999); + ram_table->crgb_offset[4] = bswap16_based_on_endian(big_endian, 0x6333); + ram_table->crgb_offset[5] = bswap16_based_on_endian(big_endian, 0x7800); + ram_table->crgb_offset[6] = bswap16_based_on_endian(big_endian, 0x8c00); + ram_table->crgb_offset[7] = bswap16_based_on_endian(big_endian, 0xa000); + ram_table->crgb_slope[0] = bswap16_based_on_endian(big_endian, 0x3609); + ram_table->crgb_slope[1] = bswap16_based_on_endian(big_endian, 0x2dfa); + ram_table->crgb_slope[2] = bswap16_based_on_endian(big_endian, 0x27ea); + ram_table->crgb_slope[3] = bswap16_based_on_endian(big_endian, 0x235d); + ram_table->crgb_slope[4] = bswap16_based_on_endian(big_endian, 0x2042); + ram_table->crgb_slope[5] = bswap16_based_on_endian(big_endian, 0x1dc3); + ram_table->crgb_slope[6] = bswap16_based_on_endian(big_endian, 0x1b1a); + ram_table->crgb_slope[7] = bswap16_based_on_endian(big_endian, 0x1910); fill_backlight_transform_table_v_2_2( params, ram_table, big_endian); @@ -656,17 +660,55 @@ void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame bool dmub_init_abm_config(struct abm *abm, struct dmcu_iram_parameters params) { - unsigned char ram_table[IRAM_SIZE]; + struct iram_table_v_2_2 ram_table; + struct abm_config_table config; bool result = false; + uint32_t i, j = 0; if (abm == NULL) return false; memset(&ram_table, 0, sizeof(ram_table)); + memset(&config, 0, sizeof(config)); + + fill_iram_v_2_3(&ram_table, params, false); + + // We must copy to structure that is aligned to 32-bit + for (i = 0; i < NUM_POWER_FN_SEGS; i++) { + config.crgb_thresh[i] = ram_table.crgb_thresh[i]; + config.crgb_offset[i] = ram_table.crgb_offset[i]; + config.crgb_slope[i] = ram_table.crgb_slope[i]; + } + + for (i = 0; i < NUM_BL_CURVE_SEGS; i++) { + config.backlight_thresholds[i] = ram_table.backlight_thresholds[i]; + config.backlight_offsets[i] = ram_table.backlight_offsets[i]; + } + + for (i = 0; i < NUM_AMBI_LEVEL; i++) + config.iir_curve[i] = ram_table.iir_curve[i]; + + for (i = 0; i < NUM_AMBI_LEVEL; i++) { + for (j = 0; j < NUM_AGGR_LEVEL; j++) { + config.min_reduction[i][j] = ram_table.min_reduction[i][j]; + config.max_reduction[i][j] = ram_table.max_reduction[i][j]; + config.bright_pos_gain[i][j] = ram_table.bright_pos_gain[i][j]; + config.dark_pos_gain[i][j] = ram_table.dark_pos_gain[i][j]; + } + } + + for (i = 0; i < NUM_AGGR_LEVEL; i++) { + config.hybrid_factor[i] = ram_table.hybrid_factor[i]; + config.contrast_factor[i] = ram_table.contrast_factor[i]; + config.deviation_gain[i] = ram_table.deviation_gain[i]; + config.min_knee[i] = ram_table.min_knee[i]; + config.max_knee[i] = ram_table.max_knee[i]; + } + + config.min_abm_backlight = ram_table.min_abm_backlight; - fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, false); result = abm->funcs->init_abm_config( - abm, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2); + abm, (char *)(&config), sizeof(struct abm_config_table)); return result; } |