aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/modules
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c146
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.h6
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c159
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c8
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c7
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c43
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.h1
9 files changed, 279 insertions, 95 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..5c67e12b2e55 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -30,6 +30,14 @@
#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
@@ -151,7 +159,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 +169,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 +201,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)
{
@@ -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;
}
@@ -830,7 +841,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 +948,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 +959,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)
@@ -972,10 +987,11 @@ 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) {
- /*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 +1006,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 +1133,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 +1157,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 +1391,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 +1417,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 +1659,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 +1685,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 +1708,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 +1737,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 +1749,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 +1791,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 +1803,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 +1851,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 +1996,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 +2117,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 +2184,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..4762273b5bb9 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;
}
@@ -567,6 +569,12 @@ static void build_vrr_infopacket_data_v1(const struct mod_vrr_params *vrr,
static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr,
struct dc_info_packet *infopacket)
{
+ unsigned int min_refresh;
+ unsigned int max_refresh;
+ unsigned int fixed_refresh;
+ unsigned int min_programmed;
+ unsigned int max_programmed;
+
/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
infopacket->sb[1] = 0x1A;
@@ -596,23 +604,33 @@ static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr,
vrr->state == VRR_STATE_ACTIVE_FIXED)
infopacket->sb[6] |= 0x04;
- if (vrr->state == VRR_STATE_ACTIVE_FIXED) {
- /* PB7 = FreeSync Minimum refresh rate (Hz) */
- infopacket->sb[7] = (unsigned char)((vrr->fixed_refresh_in_uhz + 500000) / 1000000);
- /* PB8 = FreeSync Maximum refresh rate (Hz) */
- infopacket->sb[8] = (unsigned char)((vrr->fixed_refresh_in_uhz + 500000) / 1000000);
- } else if (vrr->state == VRR_STATE_ACTIVE_VARIABLE) {
- /* PB7 = FreeSync Minimum refresh rate (Hz) */
- infopacket->sb[7] = (unsigned char)((vrr->min_refresh_in_uhz + 500000) / 1000000);
- /* PB8 = FreeSync Maximum refresh rate (Hz) */
- infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000);
- } else {
- // Non-fs case, program nominal range
- /* PB7 = FreeSync Minimum refresh rate (Hz) */
- infopacket->sb[7] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000);
- /* PB8 = FreeSync Maximum refresh rate (Hz) */
- infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000);
- }
+ min_refresh = (vrr->min_refresh_in_uhz + 500000) / 1000000;
+ max_refresh = (vrr->max_refresh_in_uhz + 500000) / 1000000;
+ fixed_refresh = (vrr->fixed_refresh_in_uhz + 500000) / 1000000;
+
+ min_programmed = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? fixed_refresh :
+ (vrr->state == VRR_STATE_ACTIVE_VARIABLE) ? min_refresh :
+ (vrr->state == VRR_STATE_INACTIVE) ? min_refresh :
+ max_refresh; // Non-fs case, program nominal range
+
+ max_programmed = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? fixed_refresh :
+ (vrr->state == VRR_STATE_ACTIVE_VARIABLE) ? max_refresh :
+ max_refresh;// Non-fs case, program nominal range
+
+ /* PB7 = FreeSync Minimum refresh rate (Hz) */
+ infopacket->sb[7] = min_programmed & 0xFF;
+
+ /* PB8 = FreeSync Maximum refresh rate (Hz) */
+ infopacket->sb[8] = max_programmed & 0xFF;
+
+ /* PB11 : MSB FreeSync Minimum refresh rate [Hz] - bits 9:8 */
+ infopacket->sb[11] = (min_programmed >> 8) & 0x03;
+
+ /* PB12 : MSB FreeSync Maximum refresh rate [Hz] - bits 9:8 */
+ infopacket->sb[12] = (max_programmed >> 8) & 0x03;
+
+ /* PB16 : Reserved bits 7:1, FixedRate bit 0 */
+ infopacket->sb[16] = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? 1 : 0;
//FreeSync HDR
infopacket->sb[9] = 0;
@@ -731,6 +749,58 @@ static void build_vrr_infopacket_header_v2(enum signal_type signal,
}
}
+static void build_vrr_infopacket_header_v3(enum signal_type signal,
+ struct dc_info_packet *infopacket,
+ unsigned int *payload_size)
+{
+ unsigned char version;
+
+ version = 3;
+ if (dc_is_hdmi_signal(signal)) {
+
+ /* HEADER */
+
+ /* HB0 = Packet Type = 0x83 (Source Product
+ * Descriptor InfoFrame)
+ */
+ infopacket->hb0 = DC_HDMI_INFOFRAME_TYPE_SPD;
+
+ /* HB1 = Version = 0x03 */
+ infopacket->hb1 = version;
+
+ /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length] */
+ *payload_size = 0x10;
+ infopacket->hb2 = *payload_size - 1; //-1 for checksum
+
+ } else if (dc_is_dp_signal(signal)) {
+
+ /* HEADER */
+
+ /* HB0 = Secondary-data Packet ID = 0 - Only non-zero
+ * when used to associate audio related info packets
+ */
+ infopacket->hb0 = 0x00;
+
+ /* HB1 = Packet Type = 0x83 (Source Product
+ * Descriptor InfoFrame)
+ */
+ infopacket->hb1 = DC_HDMI_INFOFRAME_TYPE_SPD;
+
+ /* HB2 = [Bits 7:0 = Least significant eight bits -
+ * For INFOFRAME, the value must be 1Bh]
+ */
+ infopacket->hb2 = 0x1B;
+
+ /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x2]
+ * [Bits 1:0 = Most significant two bits = 0x00]
+ */
+
+ infopacket->hb3 = (version & 0x3F) << 2;
+
+ *payload_size = 0x1B;
+ }
+}
+
static void build_vrr_infopacket_checksum(unsigned int *payload_size,
struct dc_info_packet *infopacket)
{
@@ -816,7 +886,7 @@ static void build_vrr_infopacket_v3(enum signal_type signal,
{
unsigned int payload_size = 0;
- build_vrr_infopacket_header_v2(signal, infopacket, &payload_size);
+ build_vrr_infopacket_header_v3(signal, infopacket, &payload_size);
build_vrr_infopacket_data_v3(vrr, infopacket);
build_vrr_infopacket_fs2_data(app_tf, infopacket);
@@ -897,15 +967,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 +1112,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 +1120,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 +1195,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 +1285,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_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
index f244b72e74e0..73ca49f05bd3 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
@@ -128,8 +128,12 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp)
static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp)
{
- /* device count must be greater than or equal to tracked hdcp displays */
- return (get_device_count(hdcp) < get_active_display_count(hdcp)) ?
+ /* Some MST display may choose to report the internal panel as an HDCP RX.
+ * To update this condition with 1(because the immediate repeater's internal
+ * panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp).
+ * Device count must be greater than or equal to tracked hdcp displays.
+ */
+ return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ?
MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE :
MOD_HDCP_STATUS_SUCCESS;
}
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/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
index 549c113abcf7..a0895a7efda2 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
@@ -207,8 +207,11 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp)
static enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp)
{
- /* device count must be greater than or equal to tracked hdcp displays */
- return (get_device_count(hdcp) < get_active_display_count(hdcp)) ?
+ /* Some MST display may choose to report the internal panel as an HDCP RX. */
+ /* To update this condition with 1(because the immediate repeater's internal */
+ /* panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp). */
+ /* Device count must be greater than or equal to tracked hdcp displays. */
+ return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ?
MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE :
MOD_HDCP_STATUS_SUCCESS;
}
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..4fd8bce95d84 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -82,22 +82,24 @@ struct abm_parameters {
unsigned char deviation_gain;
unsigned char min_knee;
unsigned char max_knee;
+ unsigned short blRampReduction;
+ unsigned short blRampStart;
};
static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = {
-// min_red max_red bright_pos dark_pos brightness_gain contrast deviation min_knee max_knee
- {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0},
- {0xde, 0x85, 0x20, 0x00, 0xff, 0x90, 0xa8, 0x40, 0xdf},
- {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0},
- {0x82, 0x40, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70},
+// min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blStart blRed
+ {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0, 0xCCCC, 0xCCCC},
+ {0xde, 0x85, 0x20, 0x00, 0xff, 0x90, 0xa8, 0x40, 0xdf, 0xCCCC, 0xCCCC},
+ {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0, 0xCCCC, 0xCCCC},
+ {0x82, 0x40, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC},
};
static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = {
-// min_red max_red bright_pos dark_pos brightness_gain contrast deviation min_knee max_knee
- {0xf0, 0xd9, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70},
- {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70},
- {0x99, 0x65, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70},
- {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70},
+// min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blStart blRed
+ {0xf0, 0xd9, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC},
+ {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC},
+ {0x99, 0x65, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC},
+ {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC},
};
static const struct abm_parameters * const abm_settings[] = {
@@ -662,10 +664,11 @@ bool dmub_init_abm_config(struct resource_pool *res_pool,
{
struct iram_table_v_2_2 ram_table;
struct abm_config_table config;
+ unsigned int set = params.set;
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
@@ -710,13 +713,25 @@ bool dmub_init_abm_config(struct resource_pool *res_pool,
config.max_knee[i] = ram_table.max_knee[i];
}
+ if (params.backlight_ramping_override) {
+ for (i = 0; i < NUM_AGGR_LEVEL; i++) {
+ config.blRampReduction[i] = params.backlight_ramping_reduction;
+ config.blRampStart[i] = params.backlight_ramping_start;
+ }
+ } else {
+ for (i = 0; i < NUM_AGGR_LEVEL; i++) {
+ config.blRampReduction[i] = abm_settings[set][i].blRampReduction;
+ config.blRampStart[i] = abm_settings[set][i].blRampStart;
+ }
+ }
+
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));
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
index fa4728d88092..6f2eecce6baa 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
@@ -39,6 +39,7 @@ enum abm_defines {
struct dmcu_iram_parameters {
unsigned int *backlight_lut_array;
unsigned int backlight_lut_array_size;
+ bool backlight_ramping_override;
unsigned int backlight_ramping_reduction;
unsigned int backlight_ramping_start;
unsigned int min_abm_backlight;