diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
6 files changed, 139 insertions, 58 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 b8695660b480..eced40a2fce4 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -151,7 +151,7 @@ static void compute_de_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) div = dc_fixpt_sub(c2, dc_fixpt_mul(c3, l_pow_m1)); base2 = dc_fixpt_div(base, div); - //avoid complex numbers + // avoid complex numbers if (dc_fixpt_lt(base2, dc_fixpt_zero)) base2 = dc_fixpt_sub(dc_fixpt_zero, base2); @@ -161,7 +161,7 @@ static void compute_de_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) } -/*de gamma, none linear to linear*/ +/* de gamma, non-linear to linear */ static void compute_hlg_eotf(struct fixed31_32 in_x, struct fixed31_32 *out_y, uint32_t sdr_white_level, uint32_t max_luminance_nits) @@ -193,7 +193,7 @@ static void compute_hlg_eotf(struct fixed31_32 in_x, } -/*re gamma, linear to none linear*/ +/* re gamma, linear to non-linear */ static void compute_hlg_oetf(struct fixed31_32 in_x, struct fixed31_32 *out_y, uint32_t sdr_white_level, uint32_t max_luminance_nits) { @@ -830,7 +830,7 @@ static bool build_regamma(struct pwl_float_data_ex *rgb_regamma, i = 0; while (i <= hw_points_num) { - /*TODO use y vs r,g,b*/ + /* TODO use y vs r,g,b */ rgb->r = translate_from_linear_space_ex( coord_x->x, coeff, 0, cal_buffer); rgb->g = rgb->r; @@ -937,6 +937,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, uint32_t i; struct pwl_float_data_ex *rgb = rgb_regamma; const struct hw_x_point *coord_x = coordinate_x; + const struct hw_x_point *prv_coord_x = coord_x; struct fixed31_32 scaledX = dc_fixpt_zero; struct fixed31_32 scaledX1 = dc_fixpt_zero; struct fixed31_32 max_display; @@ -947,6 +948,9 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, bool use_eetf = false; bool is_clipped = false; struct fixed31_32 sdr_white_level; + struct fixed31_32 coordX_diff; + struct fixed31_32 out_dist_max; + struct fixed31_32 bright_norm; if (fs_params->max_content == 0 || fs_params->max_display == 0) @@ -975,7 +979,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, for (i = 32; i <= hw_points_num; i++) { if (!is_clipped) { if (use_eetf) { - /*max content is equal 1 */ + /* max content is equal 1 */ scaledX1 = dc_fixpt_div(coord_x->x, dc_fixpt_div(max_content, sdr_white_level)); hermite_spline_eetf(scaledX1, max_display, min_display, @@ -990,21 +994,65 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, else output = calculate_gamma22(scaledX, use_eetf, cal_buffer); + // Ensure output respects reasonable boundaries + output = dc_fixpt_clamp(output, dc_fixpt_zero, dc_fixpt_one); + rgb->r = output; rgb->g = output; rgb->b = output; } else { + /* Here clipping happens for the first time */ is_clipped = true; - rgb->r = clip; - rgb->g = clip; - rgb->b = clip; + + /* The next few lines implement the equation + * output = prev_out + + * (coord_x->x - prev_coord_x->x) * + * (1.0 - prev_out) / + * (maxDisp/sdr_white_level - prevCoordX) + * + * This equation interpolates the first point + * after max_display/80 so that the slope from + * hw_x_before_max and hw_x_after_max is such + * that we hit Y=1.0 at max_display/80. + */ + + coordX_diff = dc_fixpt_sub(coord_x->x, prv_coord_x->x); + out_dist_max = dc_fixpt_sub(dc_fixpt_one, output); + bright_norm = dc_fixpt_div(max_display, sdr_white_level); + + output = dc_fixpt_add( + output, dc_fixpt_mul( + coordX_diff, dc_fixpt_div( + out_dist_max, + dc_fixpt_sub(bright_norm, prv_coord_x->x) + ) + ) + ); + + /* Relaxing the maximum boundary to 1.07 (instead of 1.0) + * because the last point in the curve must be such that + * the maximum display pixel brightness interpolates to + * exactly 1.0. The worst case scenario was calculated + * around 1.057, so the limit of 1.07 leaves some safety + * margin. + */ + output = dc_fixpt_clamp(output, dc_fixpt_zero, + dc_fixpt_from_fraction(107, 100)); + + rgb->r = output; + rgb->g = output; + rgb->b = output; } } else { + /* Every other clipping after the first + * one is dealt with here + */ rgb->r = clip; rgb->g = clip; rgb->b = clip; } + prv_coord_x = coord_x; ++coord_x; ++rgb; } @@ -1073,7 +1121,7 @@ static void build_hlg_degamma(struct pwl_float_data_ex *degamma, const struct hw_x_point *coord_x = coordinate_x; i = 0; - //check when i == 434 + // check when i == 434 while (i != hw_points_num + 1) { compute_hlg_eotf(coord_x->x, &rgb->r, sdr_white_level, max_luminance_nits); rgb->g = rgb->r; @@ -1097,7 +1145,7 @@ static void build_hlg_regamma(struct pwl_float_data_ex *regamma, i = 0; - //when i == 471 + // when i == 471 while (i != hw_points_num + 1) { compute_hlg_oetf(coord_x->x, &rgb->r, sdr_white_level, max_luminance_nits); rgb->g = rgb->r; @@ -1331,6 +1379,8 @@ static void apply_lut_1d( struct fixed31_32 lut1; struct fixed31_32 lut2; const int max_lut_index = 4095; + const struct fixed31_32 penult_lut_index_f = + dc_fixpt_from_int(max_lut_index-1); const struct fixed31_32 max_lut_index_f = dc_fixpt_from_int(max_lut_index); int32_t index = 0, index_next = 0; @@ -1355,10 +1405,21 @@ static void apply_lut_1d( index = dc_fixpt_floor(norm_y); index_f = dc_fixpt_from_int(index); - if (index < 0 || index > max_lut_index) + if (index < 0) continue; - index_next = (index == max_lut_index) ? index : index+1; + if (index <= max_lut_index) + index_next = (index == max_lut_index) ? index : index+1; + else { + /* Here we are dealing with the last point in the curve, + * which in some cases might exceed the range given by + * max_lut_index. So we interpolate the value using + * max_lut_index and max_lut_index - 1. + */ + index = max_lut_index - 1; + index_next = max_lut_index; + index_f = penult_lut_index_f; + } if (color == 0) { lut1 = ramp->entries.red[index]; @@ -1586,9 +1647,7 @@ static void build_new_custom_resulted_curve( uint32_t hw_points_num, struct dc_transfer_func_distributed_points *tf_pts) { - uint32_t i; - - i = 0; + uint32_t i = 0; while (i != hw_points_num + 1) { tf_pts->red[i] = dc_fixpt_clamp( @@ -1614,7 +1673,7 @@ static void apply_degamma_for_user_regamma(struct pwl_float_data_ex *rgb_regamma struct pwl_float_data_ex *rgb = rgb_regamma; const struct hw_x_point *coord_x = coordinates_x; - build_coefficients(&coeff, true); + build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB); i = 0; while (i != hw_points_num + 1) { @@ -1637,7 +1696,8 @@ static bool map_regamma_hw_to_x_user( const struct pwl_float_data_ex *rgb_regamma, uint32_t hw_points_num, struct dc_transfer_func_distributed_points *tf_pts, - bool mapUserRamp) + bool mapUserRamp, + bool doClamping) { /* setup to spare calculated ideal regamma values */ @@ -1665,8 +1725,10 @@ static bool map_regamma_hw_to_x_user( } } - /* this should be named differently, all it does is clamp to 0-1 */ - build_new_custom_resulted_curve(hw_points_num, tf_pts); + if (doClamping) { + /* this should be named differently, all it does is clamp to 0-1 */ + build_new_custom_resulted_curve(hw_points_num, tf_pts); + } return true; } @@ -1675,7 +1737,8 @@ static bool map_regamma_hw_to_x_user( bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf, const struct regamma_lut *regamma, - struct calculate_buffer *cal_buffer) + struct calculate_buffer *cal_buffer, + const struct dc_gamma *ramp) { struct gamma_coefficients coeff; const struct hw_x_point *coord_x = coordinates_x; @@ -1716,6 +1779,9 @@ bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf, ++i; } + if (ramp && ramp->type == GAMMA_CS_TFM_1D) + apply_lut_1d(ramp, MAX_HW_POINTS, &output_tf->tf_pts); + // this function just clamps output to 0-1 build_new_custom_resulted_curve(MAX_HW_POINTS, &output_tf->tf_pts); output_tf->type = TF_TYPE_DISTRIBUTED_POINTS; @@ -1725,7 +1791,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, - struct calculate_buffer *cal_buffer) + struct calculate_buffer *cal_buffer, + const struct dc_gamma *ramp) { struct dc_transfer_func_distributed_points *tf_pts = &output_tf->tf_pts; struct dividers dividers; @@ -1772,6 +1839,9 @@ bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf, tf_pts->x_point_at_y1_green = 1; tf_pts->x_point_at_y1_blue = 1; + if (ramp && ramp->type == GAMMA_CS_TFM_1D) + apply_lut_1d(ramp, MAX_HW_POINTS, &output_tf->tf_pts); + // this function just clamps output to 0-1 build_new_custom_resulted_curve(MAX_HW_POINTS, tf_pts); @@ -1914,11 +1984,12 @@ bool mod_color_calculate_degamma_params(struct dc_color_caps *dc_caps, ++i; } } else { - //clamps to 0-1 + // clamps to 0-1 map_regamma_hw_to_x_user(ramp, coeff, rgb_user, coordinates_x, axis_x, curve, MAX_HW_POINTS, tf_pts, - mapUserRamp && ramp && ramp->type == GAMMA_RGB_256); + mapUserRamp && ramp && ramp->type == GAMMA_RGB_256, + true); } @@ -2034,6 +2105,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, struct gamma_pixel *axis_x = NULL; struct pixel_gamma_point *coeff = NULL; enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; + bool doClamping = true; bool ret = false; if (output_tf->type == TF_TYPE_BYPASS) @@ -2100,11 +2172,15 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, cal_buffer); if (ret) { + doClamping = !(output_tf->tf == TRANSFER_FUNCTION_GAMMA22 && + fs_params != NULL && fs_params->skip_tm == 0); + map_regamma_hw_to_x_user(ramp, coeff, rgb_user, coordinates_x, axis_x, rgb_regamma, MAX_HW_POINTS, tf_pts, (mapUserRamp || (ramp && ramp->type != GAMMA_RGB_256)) && - (ramp && ramp->type != GAMMA_CS_TFM_1D)); + (ramp && ramp->type != GAMMA_CS_TFM_1D), + doClamping); if (ramp && ramp->type == GAMMA_CS_TFM_1D) apply_lut_1d(ramp, MAX_HW_POINTS, tf_pts); 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 37ffbef6602b..7563457e2ff4 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h @@ -120,11 +120,13 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, bool calculate_user_regamma_coeff(struct dc_transfer_func *output_tf, const struct regamma_lut *regamma, - struct calculate_buffer *cal_buffer); + struct calculate_buffer *cal_buffer, + const struct dc_gamma *ramp); bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf, const struct regamma_lut *regamma, - struct calculate_buffer *cal_buffer); + struct calculate_buffer *cal_buffer, + const struct dc_gamma *ramp); #endif /* COLOR_MOD_COLOR_GAMMA_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index d988533d4af5..52c3cb6b439a 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -41,11 +41,11 @@ #define BTR_MAX_MARGIN 2500 /* Threshold to change BTR multiplier (to avoid frequent changes) */ #define BTR_DRIFT_MARGIN 2000 -/*Threshold to exit fixed refresh rate*/ -#define FIXED_REFRESH_EXIT_MARGIN_IN_HZ 4 -/* Number of consecutive frames to check before entering/exiting fixed refresh*/ +/* Threshold to exit fixed refresh rate */ +#define FIXED_REFRESH_EXIT_MARGIN_IN_HZ 1 +/* Number of consecutive frames to check before entering/exiting fixed refresh */ #define FIXED_REFRESH_ENTER_FRAME_COUNT 5 -#define FIXED_REFRESH_EXIT_FRAME_COUNT 5 +#define FIXED_REFRESH_EXIT_FRAME_COUNT 10 struct core_freesync { struct mod_freesync public; @@ -85,7 +85,7 @@ void mod_freesync_destroy(struct mod_freesync *mod_freesync) kfree(core_freesync); } -#if 0 /* unused currently */ +#if 0 /* Unused currently */ static unsigned int calc_refresh_in_uhz_from_duration( unsigned int duration_in_ns) { @@ -184,7 +184,7 @@ static void update_v_total_for_static_ramp( bool ramp_direction_is_up = (current_duration_in_us > target_duration_in_us) ? true : false; - /* Calc ratio between new and current frame duration with 3 digit */ + /* Calculate ratio between new and current frame duration with 3 digit */ unsigned int frame_duration_ratio = div64_u64(1000000, (1000 + div64_u64(((unsigned long long)( STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME) * @@ -204,10 +204,10 @@ static void update_v_total_for_static_ramp( /* Going to a higher refresh rate (lower frame duration) */ if (ramp_direction_is_up) { - /* reduce frame duration */ + /* Reduce frame duration */ current_duration_in_us -= ramp_rate_interpolated; - /* adjust for frame duration below min */ + /* Adjust for frame duration below min */ if (current_duration_in_us <= target_duration_in_us) { in_out_vrr->fixed.ramping_active = false; in_out_vrr->fixed.ramping_done = true; @@ -217,10 +217,10 @@ static void update_v_total_for_static_ramp( } /* Going to a lower refresh rate (larger frame duration) */ } else { - /* increase frame duration */ + /* Increase frame duration */ current_duration_in_us += ramp_rate_interpolated; - /* adjust for frame duration above max */ + /* Adjust for frame duration above max */ if (current_duration_in_us >= target_duration_in_us) { in_out_vrr->fixed.ramping_active = false; in_out_vrr->fixed.ramping_done = true; @@ -289,7 +289,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, } else { /* Calculate number of midPoint frames that could fit within - * the render time interval- take ceil of this value + * the render time interval - take ceil of this value */ mid_point_frames_ceil = (last_render_time_in_us + in_out_vrr->btr.mid_point_in_us - 1) / @@ -306,7 +306,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, } /* Calculate number of midPoint frames that could fit within - * the render time interval- take floor of this value + * the render time interval - take floor of this value */ mid_point_frames_floor = last_render_time_in_us / in_out_vrr->btr.mid_point_in_us; @@ -420,7 +420,8 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, in_out_vrr->fixed.target_refresh_in_uhz = 0; update = true; } - } + } else + in_out_vrr->fixed.frame_counter = 0; } else if (last_render_time_in_us > max_render_time_in_us) { /* Enter Fixed Refresh mode */ if (!in_out_vrr->fixed.fixed_active) { @@ -434,7 +435,8 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, in_out_vrr->max_refresh_in_uhz; update = true; } - } + } else + in_out_vrr->fixed.frame_counter = 0; } if (update) { @@ -559,7 +561,7 @@ static void build_vrr_infopacket_data_v1(const struct mod_vrr_params *vrr, */ infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000); - //FreeSync HDR + /* FreeSync HDR */ infopacket->sb[9] = 0; infopacket->sb[10] = 0; } @@ -897,15 +899,15 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, min_refresh_in_uhz = in_config->min_refresh_in_uhz; max_refresh_in_uhz = in_config->max_refresh_in_uhz; - // Full range may be larger than current video timing, so cap at nominal + /* Full range may be larger than current video timing, so cap at nominal */ if (max_refresh_in_uhz > nominal_field_rate_in_uhz) max_refresh_in_uhz = nominal_field_rate_in_uhz; - // Full range may be larger than current video timing, so cap at nominal + /* Full range may be larger than current video timing, so cap at nominal */ if (min_refresh_in_uhz > max_refresh_in_uhz) min_refresh_in_uhz = max_refresh_in_uhz; - // If a monitor reports exactly max refresh of 2x of min, enforce it on nominal + /* If a monitor reports exactly max refresh of 2x of min, enforce it on nominal */ rounded_nominal_in_uhz = div_u64(nominal_field_rate_in_uhz + 50000, 100000) * 100000; if (in_config->max_refresh_in_uhz == (2 * in_config->min_refresh_in_uhz) && @@ -1042,7 +1044,7 @@ void mod_freesync_handle_preflip(struct mod_freesync *mod_freesync, last_render_time_in_us = curr_time_stamp_in_us - plane->time.prev_update_time_in_us; - // Sum off all entries except oldest one + /* Sum off all entries except oldest one */ for (i = 0; i < DC_PLANE_UPDATE_TIMES_MAX; i++) { average_render_time_in_us += plane->time.time_elapsed_in_us[i]; @@ -1050,7 +1052,7 @@ void mod_freesync_handle_preflip(struct mod_freesync *mod_freesync, average_render_time_in_us -= plane->time.time_elapsed_in_us[oldest_index]; - // Add render time for current flip + /* Add render time for current flip */ average_render_time_in_us += last_render_time_in_us; average_render_time_in_us /= DC_PLANE_UPDATE_TIMES_MAX; @@ -1125,8 +1127,9 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE) in_out_vrr->fixed.ramping_active = false; - /* Gradual Static Screen Ramping Logic */ - /* Execute if ramp is active and user enabled freesync static screen*/ + /* Gradual Static Screen Ramping Logic + * Execute if ramp is active and user enabled freesync static screen + */ if (in_out_vrr->state == VRR_STATE_ACTIVE_FIXED && in_out_vrr->fixed.ramping_active) { update_v_total_for_static_ramp( @@ -1214,20 +1217,20 @@ bool mod_freesync_is_valid_range(uint32_t min_refresh_cap_in_uhz, min_refresh_cap_in_uhz /= 1000000; max_refresh_cap_in_uhz /= 1000000; - // Check nominal is within range + /* Check nominal is within range */ if (nominal_field_rate_in_uhz > max_refresh_cap_in_uhz || nominal_field_rate_in_uhz < min_refresh_cap_in_uhz) return false; - // If nominal is less than max, limit the max allowed refresh rate + /* If nominal is less than max, limit the max allowed refresh rate */ if (nominal_field_rate_in_uhz < max_refresh_cap_in_uhz) max_refresh_cap_in_uhz = nominal_field_rate_in_uhz; - // Check min is within range + /* Check min is within range */ if (min_refresh_cap_in_uhz > max_refresh_cap_in_uhz) return false; - // For variable range, check for at least 10 Hz range + /* For variable range, check for at least 10 Hz range */ if (nominal_field_rate_in_uhz - min_refresh_cap_in_uhz < 10) return false; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c index f3711914364e..24ab95b093f7 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c @@ -231,7 +231,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp, fail_and_restart_in_ms(0, &status, output); break; } else if (conn->hdcp1_retry_count < conn->link.adjust.hdcp1.min_auth_retries_wa) { - fail_and_restart_in_ms(0, &status, output); + fail_and_restart_in_ms(200, &status, output); break; } if (conn->is_repeater) { diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c index fb6a19d020f9..ee5230ccf3c4 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c @@ -280,6 +280,6 @@ char *mod_hdcp_state_id_to_str(int32_t id) return "D2_A9_VALIDATE_STREAM_READY"; default: return "UNKNOWN_STATE_ID"; - }; + } } 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 61497954e67e..cc983f662157 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -665,7 +665,7 @@ bool dmub_init_abm_config(struct resource_pool *res_pool, bool result = false; uint32_t i, j = 0; -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) +#if defined(CONFIG_DRM_AMD_DC_DCN) if (res_pool->abm == NULL && res_pool->multiple_abms[0] == NULL) return false; #else @@ -712,11 +712,11 @@ bool dmub_init_abm_config(struct resource_pool *res_pool, config.min_abm_backlight = ram_table.min_abm_backlight; -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) - if (res_pool->multiple_abms[0]) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (res_pool->multiple_abms[0]) result = res_pool->multiple_abms[0]->funcs->init_abm_config( res_pool->multiple_abms[0], (char *)(&config), sizeof(struct abm_config_table)); - } else + else #endif result = res_pool->abm->funcs->init_abm_config( res_pool->abm, (char *)(&config), sizeof(struct abm_config_table)); |
