aboutsummaryrefslogtreecommitdiffstats
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.c367
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.h10
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c303
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h2
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h2
-rw-r--r--drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c69
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c121
7 files changed, 498 insertions, 376 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 88898935a5e6..2d8f14b69117 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -30,7 +30,6 @@
#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)
@@ -40,6 +39,33 @@ 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
+ * The idea is that our regions for X points are exponential and currently they all use
+ * the same number of points (NUM_PTS_IN_REGION) and in each region every point
+ * is exactly 2x the one at the same index in the previous region. In other words
+ * X[i] = 2 * X[i-NUM_PTS_IN_REGION] for i>=16
+ * The other fact is that (2x)^gamma = 2^gamma * x^gamma
+ * So we compute and save x^gamma for the first 16 regions, and for every next region
+ * 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};
+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; */
@@ -71,6 +97,18 @@ void setup_x_points_distribution(void)
}
}
+void log_x_points_distribution(struct dal_logger *logger)
+{
+ int i = 0;
+
+ if (logger != NULL) {
+ LOG_GAMMA_WRITE("Log X Distribution\n");
+
+ for (i = 0; i < MAX_HW_POINTS; i++)
+ LOG_GAMMA_WRITE("%llu\n", coordinates_x[i].x.value);
+ }
+}
+
static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y)
{
/* consts for PQ gamma formula. */
@@ -135,59 +173,68 @@ static void compute_de_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y)
}
+
/*de gamma, none linear to linear*/
-static void compute_hlg_oetf(struct fixed31_32 in_x, bool is_light0_12, struct fixed31_32 *out_y)
+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)
{
struct fixed31_32 a;
struct fixed31_32 b;
struct fixed31_32 c;
struct fixed31_32 threshold;
- struct fixed31_32 reference_white_level;
+ struct fixed31_32 x;
+ struct fixed31_32 scaling_factor =
+ dc_fixpt_from_fraction(max_luminance_nits, sdr_white_level);
a = dc_fixpt_from_fraction(17883277, 100000000);
- if (is_light0_12) {
- /*light 0-12*/
- b = dc_fixpt_from_fraction(28466892, 100000000);
- c = dc_fixpt_from_fraction(55991073, 100000000);
- threshold = dc_fixpt_one;
- reference_white_level = dc_fixpt_half;
+ b = dc_fixpt_from_fraction(28466892, 100000000);
+ c = dc_fixpt_from_fraction(55991073, 100000000);
+ threshold = dc_fixpt_from_fraction(1, 2);
+
+ if (dc_fixpt_lt(in_x, threshold)) {
+ x = dc_fixpt_mul(in_x, in_x);
+ x = dc_fixpt_div_int(x, 3);
} else {
- /*light 0-1*/
- b = dc_fixpt_from_fraction(2372241, 100000000);
- c = dc_fixpt_add(dc_fixpt_one, dc_fixpt_from_fraction(429347, 100000000));
- threshold = dc_fixpt_from_fraction(1, 12);
- reference_white_level = dc_fixpt_pow(dc_fixpt_from_fraction(3, 1), dc_fixpt_half);
+ x = dc_fixpt_sub(in_x, c);
+ x = dc_fixpt_div(x, a);
+ x = dc_fixpt_exp(x);
+ x = dc_fixpt_add(x, b);
+ x = dc_fixpt_div_int(x, 12);
}
- if (dc_fixpt_lt(threshold, in_x))
- *out_y = dc_fixpt_add(c, dc_fixpt_mul(a, dc_fixpt_log(dc_fixpt_sub(in_x, b))));
- else
- *out_y = dc_fixpt_mul(dc_fixpt_pow(in_x, dc_fixpt_half), reference_white_level);
+ *out_y = dc_fixpt_mul(x, scaling_factor);
+
}
/*re gamma, linear to none linear*/
-static void compute_hlg_eotf(struct fixed31_32 in_x, bool is_light0_12, struct fixed31_32 *out_y)
+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)
{
struct fixed31_32 a;
struct fixed31_32 b;
struct fixed31_32 c;
- struct fixed31_32 reference_white_level;
+ struct fixed31_32 threshold;
+ struct fixed31_32 x;
+ struct fixed31_32 scaling_factor =
+ dc_fixpt_from_fraction(sdr_white_level, max_luminance_nits);
a = dc_fixpt_from_fraction(17883277, 100000000);
- if (is_light0_12) {
- /*light 0-12*/
- b = dc_fixpt_from_fraction(28466892, 100000000);
- c = dc_fixpt_from_fraction(55991073, 100000000);
- reference_white_level = dc_fixpt_from_fraction(4, 1);
+ b = dc_fixpt_from_fraction(28466892, 100000000);
+ c = dc_fixpt_from_fraction(55991073, 100000000);
+ threshold = dc_fixpt_from_fraction(1, 12);
+ x = dc_fixpt_mul(in_x, scaling_factor);
+
+
+ if (dc_fixpt_lt(x, threshold)) {
+ x = dc_fixpt_mul(x, dc_fixpt_from_fraction(3, 1));
+ *out_y = dc_fixpt_pow(x, dc_fixpt_half);
} else {
- /*light 0-1*/
- b = dc_fixpt_from_fraction(2372241, 100000000);
- c = dc_fixpt_add(dc_fixpt_one, dc_fixpt_from_fraction(429347, 100000000));
- reference_white_level = dc_fixpt_from_fraction(1, 3);
+ x = dc_fixpt_mul(x, dc_fixpt_from_fraction(12, 1));
+ x = dc_fixpt_sub(x, b);
+ x = dc_fixpt_log(x);
+ x = dc_fixpt_mul(a, x);
+ *out_y = dc_fixpt_add(x, c);
}
- if (dc_fixpt_lt(dc_fixpt_half, in_x))
- *out_y = dc_fixpt_add(dc_fixpt_exp(dc_fixpt_div(dc_fixpt_sub(in_x, c), a)), b);
- else
- *out_y = dc_fixpt_mul(dc_fixpt_pow(in_x, dc_fixpt_from_fraction(2, 1)), reference_white_level);
}
@@ -243,93 +290,101 @@ struct dividers {
struct fixed31_32 divider3;
};
-enum gamma_type_index {
- gamma_type_index_2_4,
- gamma_type_index_2_2,
- gamma_type_index_2_2_flat
-};
-static void build_coefficients(struct gamma_coefficients *coefficients, enum gamma_type_index type)
+static bool build_coefficients(struct gamma_coefficients *coefficients, enum dc_transfer_func_predefined type)
{
- static const int32_t numerator01[] = { 31308, 180000, 0};
- static const int32_t numerator02[] = { 12920, 4500, 0};
- static const int32_t numerator03[] = { 55, 99, 0};
- static const int32_t numerator04[] = { 55, 99, 0};
- static const int32_t numerator05[] = { 2400, 2200, 2200};
uint32_t i = 0;
uint32_t index = 0;
+ bool ret = true;
- if (type == gamma_type_index_2_2)
+ if (type == TRANSFER_FUNCTION_SRGB)
+ index = 0;
+ else if (type == TRANSFER_FUNCTION_BT709)
index = 1;
- else if (type == gamma_type_index_2_2_flat)
+ else if (type == TRANSFER_FUNCTION_GAMMA22)
index = 2;
+ else if (type == TRANSFER_FUNCTION_GAMMA24)
+ index = 3;
+ else if (type == TRANSFER_FUNCTION_GAMMA26)
+ index = 4;
+ else {
+ ret = false;
+ goto release;
+ }
do {
coefficients->a0[i] = dc_fixpt_from_fraction(
- numerator01[index], 10000000);
+ gamma_numerator01[index], 10000000);
coefficients->a1[i] = dc_fixpt_from_fraction(
- numerator02[index], 1000);
+ gamma_numerator02[index], 1000);
coefficients->a2[i] = dc_fixpt_from_fraction(
- numerator03[index], 1000);
+ gamma_numerator03[index], 1000);
coefficients->a3[i] = dc_fixpt_from_fraction(
- numerator04[index], 1000);
+ gamma_numerator04[index], 1000);
coefficients->user_gamma[i] = dc_fixpt_from_fraction(
- numerator05[index], 1000);
+ gamma_numerator05[index], 1000);
++i;
} while (i != ARRAY_SIZE(coefficients->a0));
+release:
+ return ret;
}
static struct fixed31_32 translate_from_linear_space(
- struct fixed31_32 arg,
- struct fixed31_32 a0,
- struct fixed31_32 a1,
- struct fixed31_32 a2,
- struct fixed31_32 a3,
- struct fixed31_32 gamma)
+ struct translate_from_linear_space_args *args)
{
const struct fixed31_32 one = dc_fixpt_from_int(1);
- if (dc_fixpt_lt(one, arg))
+ if (dc_fixpt_le(one, args->arg))
return one;
- if (dc_fixpt_le(arg, dc_fixpt_neg(a0)))
- return dc_fixpt_sub(
- a2,
- dc_fixpt_mul(
- dc_fixpt_add(
- one,
- a3),
- dc_fixpt_pow(
- dc_fixpt_neg(arg),
- dc_fixpt_recip(gamma))));
- else if (dc_fixpt_le(a0, arg))
- return dc_fixpt_sub(
- dc_fixpt_mul(
- dc_fixpt_add(
- one,
- a3),
- dc_fixpt_pow(
- arg,
- dc_fixpt_recip(gamma))),
- a2);
+ if (dc_fixpt_le(args->arg, dc_fixpt_neg(args->a0))) {
+ scratch_1 = dc_fixpt_add(one, args->a3);
+ scratch_2 = dc_fixpt_pow(
+ dc_fixpt_neg(args->arg),
+ dc_fixpt_recip(args->gamma));
+ scratch_1 = dc_fixpt_mul(scratch_1, scratch_2);
+ scratch_1 = dc_fixpt_sub(args->a2, scratch_1);
+
+ 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),
+ dc_fixpt_recip(args->gamma));
+ }
+ scratch_1 = dc_fixpt_add(one, args->a3);
+ if (pow_buffer_ptr < 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]);
+
+ pow_buffer[pow_buffer_ptr%16] = scratch_2;
+ pow_buffer_ptr++;
+
+ scratch_1 = dc_fixpt_mul(scratch_1, scratch_2);
+ scratch_1 = dc_fixpt_sub(scratch_1, args->a2);
+
+ return scratch_1;
+ }
else
- return dc_fixpt_mul(
- arg,
- a1);
+ return dc_fixpt_mul(args->arg, args->a1);
}
static struct fixed31_32 calculate_gamma22(struct fixed31_32 arg)
{
struct fixed31_32 gamma = dc_fixpt_from_fraction(22, 10);
- return translate_from_linear_space(arg,
- dc_fixpt_zero,
- dc_fixpt_zero,
- dc_fixpt_zero,
- dc_fixpt_zero,
- gamma);
+ 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.gamma = gamma;
+
+ return translate_from_linear_space(&scratch_gamma_args);
}
static struct fixed31_32 translate_to_linear_space(
@@ -365,18 +420,19 @@ static struct fixed31_32 translate_to_linear_space(
return linear;
}
-static inline struct fixed31_32 translate_from_linear_space_ex(
+static struct fixed31_32 translate_from_linear_space_ex(
struct fixed31_32 arg,
struct gamma_coefficients *coeff,
uint32_t color_index)
{
- return translate_from_linear_space(
- arg,
- coeff->a0[color_index],
- coeff->a1[color_index],
- coeff->a2[color_index],
- coeff->a3[color_index],
- coeff->user_gamma[color_index]);
+ 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];
+
+ return translate_from_linear_space(&scratch_gamma_args);
}
@@ -709,30 +765,42 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq,
}
}
-static void build_regamma(struct pwl_float_data_ex *rgb_regamma,
+static bool build_regamma(struct pwl_float_data_ex *rgb_regamma,
uint32_t hw_points_num,
- const struct hw_x_point *coordinate_x, enum gamma_type_index type)
+ const struct hw_x_point *coordinate_x, enum dc_transfer_func_predefined type)
{
uint32_t i;
+ bool ret = false;
- struct gamma_coefficients coeff;
+ struct gamma_coefficients *coeff;
struct pwl_float_data_ex *rgb = rgb_regamma;
const struct hw_x_point *coord_x = coordinate_x;
- build_coefficients(&coeff, type);
+ coeff = kvzalloc(sizeof(*coeff), GFP_KERNEL);
+ if (!coeff)
+ goto release;
- i = 0;
+ if (!build_coefficients(coeff, type))
+ goto release;
- while (i != hw_points_num + 1) {
+ memset(pow_buffer, 0, NUM_PTS_IN_REGION * sizeof(struct fixed31_32));
+ pow_buffer_ptr = 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);
rgb->g = rgb->r;
rgb->b = rgb->r;
++coord_x;
++rgb;
++i;
}
+ pow_buffer_ptr = -1; // reset back to no optimize
+ ret = true;
+release:
+ kfree(coeff);
+ return ret;
}
static void hermite_spline_eetf(struct fixed31_32 input_x,
@@ -862,6 +930,8 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma,
else
max_content = max_display;
+ if (!use_eetf)
+ pow_buffer_ptr = 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++) {
@@ -900,19 +970,23 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma,
++coord_x;
++rgb;
}
+ pow_buffer_ptr = -1;
return true;
}
-static void build_degamma(struct pwl_float_data_ex *curve,
+static bool build_degamma(struct pwl_float_data_ex *curve,
uint32_t hw_points_num,
- const struct hw_x_point *coordinate_x, enum gamma_type_index type)
+ const struct hw_x_point *coordinate_x, enum dc_transfer_func_predefined type)
{
uint32_t i;
struct gamma_coefficients coeff;
uint32_t begin_index, end_index;
+ bool ret = false;
+
+ if (!build_coefficients(&coeff, type))
+ goto release;
- build_coefficients(&coeff, type);
i = 0;
/* X points is 2^-25 to 2^7
@@ -941,11 +1015,19 @@ static void build_degamma(struct pwl_float_data_ex *curve,
curve[i].b = dc_fixpt_one;
i++;
}
+ ret = true;
+release:
+ return ret;
}
+
+
+
+
static void build_hlg_degamma(struct pwl_float_data_ex *degamma,
uint32_t hw_points_num,
- const struct hw_x_point *coordinate_x, bool is_light0_12)
+ const struct hw_x_point *coordinate_x,
+ uint32_t sdr_white_level, uint32_t max_luminance_nits)
{
uint32_t i;
@@ -953,9 +1035,9 @@ 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
while (i != hw_points_num + 1) {
- compute_hlg_oetf(coord_x->x, is_light0_12, &rgb->r);
+ compute_hlg_eotf(coord_x->x, &rgb->r, sdr_white_level, max_luminance_nits);
rgb->g = rgb->r;
rgb->b = rgb->r;
++coord_x;
@@ -964,9 +1046,11 @@ static void build_hlg_degamma(struct pwl_float_data_ex *degamma,
}
}
+
static void build_hlg_regamma(struct pwl_float_data_ex *regamma,
uint32_t hw_points_num,
- const struct hw_x_point *coordinate_x, bool is_light0_12)
+ const struct hw_x_point *coordinate_x,
+ uint32_t sdr_white_level, uint32_t max_luminance_nits)
{
uint32_t i;
@@ -975,8 +1059,9 @@ static void build_hlg_regamma(struct pwl_float_data_ex *regamma,
i = 0;
+ //when i == 471
while (i != hw_points_num + 1) {
- compute_hlg_eotf(coord_x->x, is_light0_12, &rgb->r);
+ compute_hlg_oetf(coord_x->x, &rgb->r, sdr_white_level, max_luminance_nits);
rgb->g = rgb->r;
rgb->b = rgb->r;
++coord_x;
@@ -1572,14 +1657,15 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
output_tf->tf == TRANSFER_FUNCTION_SRGB) {
if (ramp == NULL)
return true;
- if ((ramp->is_logical_identity) ||
+ if ((ramp->is_identity && ramp->type != GAMMA_CS_TFM_1D) ||
(!mapUserRamp && ramp->type == GAMMA_RGB_256))
return true;
}
output_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
- if (ramp && (mapUserRamp || ramp->type != GAMMA_RGB_256)) {
+ if (ramp && ramp->type != GAMMA_CS_TFM_1D &&
+ (mapUserRamp || ramp->type != GAMMA_RGB_256)) {
rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS,
sizeof(*rgb_user),
GFP_KERNEL);
@@ -1634,6 +1720,12 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
MAX_HW_POINTS,
coordinates_x,
fs_params);
+ } else if (tf == TRANSFER_FUNCTION_HLG) {
+ build_freesync_hdr(rgb_regamma,
+ MAX_HW_POINTS,
+ coordinates_x,
+ fs_params);
+
} else {
tf_pts->end_exponent = 0;
tf_pts->x_point_at_y1_red = 1;
@@ -1642,9 +1734,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
build_regamma(rgb_regamma,
MAX_HW_POINTS,
- coordinates_x, tf == TRANSFER_FUNCTION_SRGB ? gamma_type_index_2_4 :
- tf == TRANSFER_FUNCTION_GAMMA22 ?
- gamma_type_index_2_2_flat : gamma_type_index_2_2);
+ coordinates_x, tf);
}
map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
coordinates_x, axis_x, rgb_regamma,
@@ -1845,13 +1935,19 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
MAX_HW_POINTS,
coordinates_x);
else if (tf == TRANSFER_FUNCTION_SRGB ||
- tf == TRANSFER_FUNCTION_BT709)
+ tf == TRANSFER_FUNCTION_BT709 ||
+ tf == TRANSFER_FUNCTION_GAMMA22 ||
+ tf == TRANSFER_FUNCTION_GAMMA24 ||
+ tf == TRANSFER_FUNCTION_GAMMA26)
build_degamma(curve,
MAX_HW_POINTS,
coordinates_x,
- tf == TRANSFER_FUNCTION_SRGB ?
- gamma_type_index_2_4 : tf == TRANSFER_FUNCTION_GAMMA22 ?
- gamma_type_index_2_2_flat : gamma_type_index_2_2);
+ tf);
+ else if (tf == TRANSFER_FUNCTION_HLG)
+ build_hlg_degamma(curve,
+ MAX_HW_POINTS,
+ coordinates_x,
+ 80, 1000);
else if (tf == TRANSFER_FUNCTION_LINEAR) {
// just copy coordinates_x into curve
i = 0;
@@ -1938,7 +2034,10 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
kvfree(rgb_regamma);
} else if (trans == TRANSFER_FUNCTION_SRGB ||
- trans == TRANSFER_FUNCTION_BT709) {
+ trans == TRANSFER_FUNCTION_BT709 ||
+ trans == TRANSFER_FUNCTION_GAMMA22 ||
+ trans == TRANSFER_FUNCTION_GAMMA24 ||
+ trans == TRANSFER_FUNCTION_GAMMA26) {
rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_regamma),
GFP_KERNEL);
@@ -1952,9 +2051,7 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
build_regamma(rgb_regamma,
MAX_HW_POINTS,
coordinates_x,
- trans == TRANSFER_FUNCTION_SRGB ?
- gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ?
- gamma_type_index_2_2_flat : gamma_type_index_2_2);
+ trans);
for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_regamma[i].r;
points->green[i] = rgb_regamma[i].g;
@@ -1963,18 +2060,21 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
ret = true;
kvfree(rgb_regamma);
- } else if (trans == TRANSFER_FUNCTION_HLG ||
- trans == TRANSFER_FUNCTION_HLG12) {
+ } else if (trans == TRANSFER_FUNCTION_HLG) {
rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_regamma),
GFP_KERNEL);
if (!rgb_regamma)
goto rgb_regamma_alloc_fail;
+ points->end_exponent = 4;
+ points->x_point_at_y1_red = 12;
+ points->x_point_at_y1_green = 12;
+ points->x_point_at_y1_blue = 12;
build_hlg_regamma(rgb_regamma,
MAX_HW_POINTS,
coordinates_x,
- trans == TRANSFER_FUNCTION_HLG12 ? true:false);
+ 80, 1000);
for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_regamma[i].r;
points->green[i] = rgb_regamma[i].g;
@@ -2024,8 +2124,10 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
kvfree(rgb_degamma);
} else if (trans == TRANSFER_FUNCTION_SRGB ||
- trans == TRANSFER_FUNCTION_BT709 ||
- trans == TRANSFER_FUNCTION_GAMMA22) {
+ trans == TRANSFER_FUNCTION_BT709 ||
+ trans == TRANSFER_FUNCTION_GAMMA22 ||
+ trans == TRANSFER_FUNCTION_GAMMA24 ||
+ trans == TRANSFER_FUNCTION_GAMMA26) {
rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_degamma),
GFP_KERNEL);
@@ -2035,9 +2137,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
build_degamma(rgb_degamma,
MAX_HW_POINTS,
coordinates_x,
- trans == TRANSFER_FUNCTION_SRGB ?
- gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ?
- gamma_type_index_2_2_flat : gamma_type_index_2_2);
+ trans);
for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_degamma[i].r;
points->green[i] = rgb_degamma[i].g;
@@ -2046,8 +2146,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
ret = true;
kvfree(rgb_degamma);
- } else if (trans == TRANSFER_FUNCTION_HLG ||
- trans == TRANSFER_FUNCTION_HLG12) {
+ } else if (trans == TRANSFER_FUNCTION_HLG) {
rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
sizeof(*rgb_degamma),
GFP_KERNEL);
@@ -2057,7 +2156,7 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
build_hlg_degamma(rgb_degamma,
MAX_HW_POINTS,
coordinates_x,
- trans == TRANSFER_FUNCTION_HLG12 ? true:false);
+ 80, 1000);
for (i = 0; i <= MAX_HW_POINTS ; i++) {
points->red[i] = rgb_degamma[i].r;
points->green[i] = rgb_degamma[i].g;
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 369953fafadf..44ddea58523a 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
@@ -82,7 +82,17 @@ struct freesync_hdr_tf_params {
unsigned int skip_tm; // skip tm
};
+struct translate_from_linear_space_args {
+ struct fixed31_32 arg;
+ struct fixed31_32 a0;
+ struct fixed31_32 a1;
+ struct fixed31_32 a2;
+ struct fixed31_32 a3;
+ struct fixed31_32 gamma;
+};
+
void setup_x_points_distribution(void);
+void log_x_points_distribution(struct dal_logger *logger);
void precompute_pq(void);
void precompute_de_pq(void);
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index 7c20171a3b6d..ec70c9b12e1a 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -52,93 +52,6 @@ struct core_freesync {
struct dc *dc;
};
-void setFieldWithMask(unsigned char *dest, unsigned int mask, unsigned int value)
-{
- unsigned int shift = 0;
-
- if (!mask || !dest)
- return;
-
- while (!((mask >> shift) & 1))
- shift++;
-
- //reset
- *dest = *dest & ~mask;
- //set
- //dont let value span past mask
- value = value & (mask >> shift);
- //insert value
- *dest = *dest | (value << shift);
-}
-
-// VTEM Byte Offset
-#define VRR_VTEM_PB0 0
-#define VRR_VTEM_PB1 1
-#define VRR_VTEM_PB2 2
-#define VRR_VTEM_PB3 3
-#define VRR_VTEM_PB4 4
-#define VRR_VTEM_PB5 5
-#define VRR_VTEM_PB6 6
-
-#define VRR_VTEM_MD0 7
-#define VRR_VTEM_MD1 8
-#define VRR_VTEM_MD2 9
-#define VRR_VTEM_MD3 10
-
-
-// VTEM Byte Masks
-//PB0
-#define MASK__VRR_VTEM_PB0__RESERVED0 0x01
-#define MASK__VRR_VTEM_PB0__SYNC 0x02
-#define MASK__VRR_VTEM_PB0__VFR 0x04
-#define MASK__VRR_VTEM_PB0__AFR 0x08
-#define MASK__VRR_VTEM_PB0__DS_TYPE 0x30
- //0: Periodic pseudo-static EM Data Set
- //1: Periodic dynamic EM Data Set
- //2: Unique EM Data Set
- //3: Reserved
-#define MASK__VRR_VTEM_PB0__END 0x40
-#define MASK__VRR_VTEM_PB0__NEW 0x80
-
-//PB1
-#define MASK__VRR_VTEM_PB1__RESERVED1 0xFF
-
-//PB2
-#define MASK__VRR_VTEM_PB2__ORGANIZATION_ID 0xFF
- //0: This is a Vendor Specific EM Data Set
- //1: This EM Data Set is defined by This Specification (HDMI 2.1 r102.clean)
- //2: This EM Data Set is defined by CTA-861-G
- //3: This EM Data Set is defined by VESA
-//PB3
-#define MASK__VRR_VTEM_PB3__DATA_SET_TAG_MSB 0xFF
-//PB4
-#define MASK__VRR_VTEM_PB4__DATA_SET_TAG_LSB 0xFF
-//PB5
-#define MASK__VRR_VTEM_PB5__DATA_SET_LENGTH_MSB 0xFF
-//PB6
-#define MASK__VRR_VTEM_PB6__DATA_SET_LENGTH_LSB 0xFF
-
-
-
-//PB7-27 (20 bytes):
-//PB7 = MD0
-#define MASK__VRR_VTEM_MD0__VRR_EN 0x01
-#define MASK__VRR_VTEM_MD0__M_CONST 0x02
-#define MASK__VRR_VTEM_MD0__RESERVED2 0x0C
-#define MASK__VRR_VTEM_MD0__FVA_FACTOR_M1 0xF0
-
-//MD1
-#define MASK__VRR_VTEM_MD1__BASE_VFRONT 0xFF
-
-//MD2
-#define MASK__VRR_VTEM_MD2__BASE_REFRESH_RATE_98 0x03
-#define MASK__VRR_VTEM_MD2__RB 0x04
-#define MASK__VRR_VTEM_MD2__RESERVED3 0xF8
-
-//MD3
-#define MASK__VRR_VTEM_MD3__BASE_REFRESH_RATE_07 0xFF
-
-
#define MOD_FREESYNC_TO_CORE(mod_freesync)\
container_of(mod_freesync, struct core_freesync, public)
@@ -435,6 +348,12 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
/* Either we've calculated the number of frames to insert,
* or we need to insert min duration frames
*/
+ if (last_render_time_in_us / frames_to_insert <
+ in_out_vrr->min_duration_in_us){
+ frames_to_insert -= (frames_to_insert > 1) ?
+ 1 : 0;
+ }
+
if (frames_to_insert > 0)
inserted_frame_duration_in_us = last_render_time_in_us /
frames_to_insert;
@@ -568,22 +487,64 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync,
return false;
}
-static void build_vrr_infopacket_header_vtem(enum signal_type signal,
+static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr,
struct dc_info_packet *infopacket)
{
- // HEADER
-
- // HB0, HB1, HB2 indicates PacketType VTEMPacket
- infopacket->hb0 = 0x7F;
- infopacket->hb1 = 0xC0;
- infopacket->hb2 = 0x00; //sequence_index
-
- setFieldWithMask(&infopacket->sb[VRR_VTEM_PB0], MASK__VRR_VTEM_PB0__VFR, 1);
- setFieldWithMask(&infopacket->sb[VRR_VTEM_PB2], MASK__VRR_VTEM_PB2__ORGANIZATION_ID, 1);
- setFieldWithMask(&infopacket->sb[VRR_VTEM_PB3], MASK__VRR_VTEM_PB3__DATA_SET_TAG_MSB, 0);
- setFieldWithMask(&infopacket->sb[VRR_VTEM_PB4], MASK__VRR_VTEM_PB4__DATA_SET_TAG_LSB, 1);
- setFieldWithMask(&infopacket->sb[VRR_VTEM_PB5], MASK__VRR_VTEM_PB5__DATA_SET_LENGTH_MSB, 0);
- setFieldWithMask(&infopacket->sb[VRR_VTEM_PB6], MASK__VRR_VTEM_PB6__DATA_SET_LENGTH_LSB, 4);
+ /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
+ infopacket->sb[1] = 0x1A;
+
+ /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
+ infopacket->sb[2] = 0x00;
+
+ /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
+ infopacket->sb[3] = 0x00;
+
+ /* PB4 = Reserved */
+
+ /* PB5 = Reserved */
+
+ /* PB6 = [Bits 7:3 = Reserved] */
+
+ /* PB6 = [Bit 0 = FreeSync Supported] */
+ if (vrr->state != VRR_STATE_UNSUPPORTED)
+ infopacket->sb[6] |= 0x01;
+
+ /* PB6 = [Bit 1 = FreeSync Enabled] */
+ if (vrr->state != VRR_STATE_DISABLED &&
+ vrr->state != VRR_STATE_UNSUPPORTED)
+ infopacket->sb[6] |= 0x02;
+
+ /* PB6 = [Bit 2 = FreeSync Active] */
+ if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
+ vrr->state == VRR_STATE_ACTIVE_FIXED)
+ infopacket->sb[6] |= 0x04;
+
+ /* PB7 = FreeSync Minimum refresh rate (Hz) */
+ infopacket->sb[7] = (unsigned char)(vrr->min_refresh_in_uhz / 1000000);
+
+ /* PB8 = FreeSync Maximum refresh rate (Hz)
+ * Note: We should never go above the field rate of the mode timing set.
+ */
+ infopacket->sb[8] = (unsigned char)(vrr->max_refresh_in_uhz / 1000000);
+
+
+ //FreeSync HDR
+ infopacket->sb[9] = 0;
+ infopacket->sb[10] = 0;
+}
+
+static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf,
+ struct dc_info_packet *infopacket)
+{
+ if (app_tf != TRANSFER_FUNC_UNKNOWN) {
+ infopacket->valid = true;
+
+ infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active]
+
+ if (app_tf == TRANSFER_FUNC_GAMMA_22) {
+ infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active]
+ }
+ }
}
static void build_vrr_infopacket_header_v1(enum signal_type signal,
@@ -684,105 +645,6 @@ static void build_vrr_infopacket_header_v2(enum signal_type signal,
}
}
-static void build_vrr_vtem_infopacket_data(const struct dc_stream_state *stream,
- const struct mod_vrr_params *vrr,
- struct dc_info_packet *infopacket)
-{
- unsigned int fieldRateInHz;
-
- if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
- vrr->state == VRR_STATE_ACTIVE_FIXED) {
- setFieldWithMask(&infopacket->sb[VRR_VTEM_MD0], MASK__VRR_VTEM_MD0__VRR_EN, 1);
- } else {
- setFieldWithMask(&infopacket->sb[VRR_VTEM_MD0], MASK__VRR_VTEM_MD0__VRR_EN, 0);
- }
-
- if (!stream->timing.vic) {
- setFieldWithMask(&infopacket->sb[VRR_VTEM_MD1], MASK__VRR_VTEM_MD1__BASE_VFRONT,
- stream->timing.v_front_porch);
-
-
- /* TODO: In dal2, we check mode flags for a reduced blanking timing.
- * Need a way to relay that information to this function.
- * if("ReducedBlanking")
- * {
- * setFieldWithMask(&infopacket->sb[VRR_VTEM_MD2], MASK__VRR_VTEM_MD2__RB, 1;
- * }
- */
-
- //TODO: DAL2 does FixPoint and rounding. Here we might need to account for that
- fieldRateInHz = (stream->timing.pix_clk_100hz * 100)/
- (stream->timing.h_total * stream->timing.v_total);
-
- setFieldWithMask(&infopacket->sb[VRR_VTEM_MD2], MASK__VRR_VTEM_MD2__BASE_REFRESH_RATE_98,
- fieldRateInHz >> 8);
- setFieldWithMask(&infopacket->sb[VRR_VTEM_MD3], MASK__VRR_VTEM_MD3__BASE_REFRESH_RATE_07,
- fieldRateInHz);
-
- }
- infopacket->valid = true;
-}
-
-static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr,
- struct dc_info_packet *infopacket)
-{
- /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
- infopacket->sb[1] = 0x1A;
-
- /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
- infopacket->sb[2] = 0x00;
-
- /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
- infopacket->sb[3] = 0x00;
-
- /* PB4 = Reserved */
-
- /* PB5 = Reserved */
-
- /* PB6 = [Bits 7:3 = Reserved] */
-
- /* PB6 = [Bit 0 = FreeSync Supported] */
- if (vrr->state != VRR_STATE_UNSUPPORTED)
- infopacket->sb[6] |= 0x01;
-
- /* PB6 = [Bit 1 = FreeSync Enabled] */
- if (vrr->state != VRR_STATE_DISABLED &&
- vrr->state != VRR_STATE_UNSUPPORTED)
- infopacket->sb[6] |= 0x02;
-
- /* PB6 = [Bit 2 = FreeSync Active] */
- if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
- vrr->state == VRR_STATE_ACTIVE_FIXED)
- infopacket->sb[6] |= 0x04;
-
- /* PB7 = FreeSync Minimum refresh rate (Hz) */
- infopacket->sb[7] = (unsigned char)(vrr->min_refresh_in_uhz / 1000000);
-
- /* PB8 = FreeSync Maximum refresh rate (Hz)
- * Note: We should never go above the field rate of the mode timing set.
- */
- infopacket->sb[8] = (unsigned char)(vrr->max_refresh_in_uhz / 1000000);
-
-
- //FreeSync HDR
- infopacket->sb[9] = 0;
- infopacket->sb[10] = 0;
-}
-
-static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf,
- struct dc_info_packet *infopacket)
-{
- if (app_tf != TRANSFER_FUNC_UNKNOWN) {
- infopacket->valid = true;
-
- infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active]
-
- if (app_tf == TRANSFER_FUNC_GAMMA_22) {
- infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active]
- }
- }
-}
-
static void build_vrr_infopacket_checksum(unsigned int *payload_size,
struct dc_info_packet *infopacket)
{
@@ -835,21 +697,6 @@ static void build_vrr_infopacket_v2(enum signal_type signal,
infopacket->valid = true;
}
-static void build_vrr_infopacket_vtem(const struct dc_stream_state *stream,
- const struct mod_vrr_params *vrr,
- struct dc_info_packet *infopacket)
-{
- //VTEM info packet for HdmiVrr
-
- memset(infopacket, 0, sizeof(struct dc_info_packet));
-
- //VTEM Packet is structured differently
- build_vrr_infopacket_header_vtem(stream->signal, infopacket);
- build_vrr_vtem_infopacket_data(stream, vrr, infopacket);
-
- infopacket->valid = true;
-}
-
void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync,
const struct dc_stream_state *stream,
const struct mod_vrr_params *vrr,
@@ -862,16 +709,13 @@ 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 && packet_type != PACKET_TYPE_VTEM))
+ if (!vrr->supported || (!vrr->send_info_frame))
return;
switch (packet_type) {
case PACKET_TYPE_FS2:
build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket);
break;
- case PACKET_TYPE_VTEM:
- build_vrr_infopacket_vtem(stream, vrr, infopacket);
- break;
case PACKET_TYPE_VRR:
case PACKET_TYPE_FS1:
default:
@@ -887,8 +731,8 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
struct core_freesync *core_freesync = NULL;
unsigned long long nominal_field_rate_in_uhz = 0;
unsigned int refresh_range = 0;
- unsigned int min_refresh_in_uhz = 0;
- unsigned int max_refresh_in_uhz = 0;
+ unsigned long long min_refresh_in_uhz = 0;
+ unsigned long long max_refresh_in_uhz = 0;
if (mod_freesync == NULL)
return;
@@ -915,7 +759,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
min_refresh_in_uhz = nominal_field_rate_in_uhz;
if (!vrr_settings_require_update(core_freesync,
- in_config, min_refresh_in_uhz, max_refresh_in_uhz,
+ in_config, (unsigned int)min_refresh_in_uhz, (unsigned int)max_refresh_in_uhz,
in_out_vrr))
return;
@@ -931,15 +775,15 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
return;
} else {
- in_out_vrr->min_refresh_in_uhz = min_refresh_in_uhz;
+ in_out_vrr->min_refresh_in_uhz = (unsigned int)min_refresh_in_uhz;
in_out_vrr->max_duration_in_us =
calc_duration_in_us_from_refresh_in_uhz(
- min_refresh_in_uhz);
+ (unsigned int)min_refresh_in_uhz);
- in_out_vrr->max_refresh_in_uhz = max_refresh_in_uhz;
+ in_out_vrr->max_refresh_in_uhz = (unsigned int)max_refresh_in_uhz;
in_out_vrr->min_duration_in_us =
calc_duration_in_us_from_refresh_in_uhz(
- max_refresh_in_uhz);
+ (unsigned int)max_refresh_in_uhz);
refresh_range = in_out_vrr->max_refresh_in_uhz -
in_out_vrr->min_refresh_in_uhz;
@@ -950,17 +794,18 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
in_out_vrr->fixed.ramping_active = in_config->ramping;
in_out_vrr->btr.btr_enabled = in_config->btr;
+
if (in_out_vrr->max_refresh_in_uhz <
2 * in_out_vrr->min_refresh_in_uhz)
in_out_vrr->btr.btr_enabled = false;
+
in_out_vrr->btr.btr_active = false;
in_out_vrr->btr.inserted_duration_in_us = 0;
in_out_vrr->btr.frames_to_insert = 0;
in_out_vrr->btr.frame_counter = 0;
in_out_vrr->btr.mid_point_in_us =
- in_out_vrr->min_duration_in_us +
- (in_out_vrr->max_duration_in_us -
- in_out_vrr->min_duration_in_us) / 2;
+ (in_out_vrr->min_duration_in_us +
+ in_out_vrr->max_duration_in_us) / 2;
if (in_out_vrr->state == VRR_STATE_UNSUPPORTED) {
in_out_vrr->adjust.v_total_min = stream->timing.v_total;
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 dcef85994c45..dc187844d10b 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
@@ -173,4 +173,6 @@ bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync,
uint32_t min_refresh_request_in_uhz,
uint32_t max_refresh_request_in_uhz);
+
+
#endif
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
index 5b1c9a4c7643..d930bdecb117 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
@@ -27,10 +27,10 @@
#define MOD_INFO_PACKET_H_
#include "mod_shared.h"
-
//Forward Declarations
struct dc_stream_state;
struct dc_info_packet;
+struct mod_vrr_params;
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet);
diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index bc13c552797f..d885d642ed7f 100644
--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -27,9 +27,78 @@
#include "core_types.h"
#include "dc_types.h"
#include "mod_shared.h"
+#include "mod_freesync.h"
+#include "dc.h"
#define HDMI_INFOFRAME_TYPE_VENDOR 0x81
+// VTEM Byte Offset
+#define VTEM_PB0 0
+#define VTEM_PB1 1
+#define VTEM_PB2 2
+#define VTEM_PB3 3
+#define VTEM_PB4 4
+#define VTEM_PB5 5
+#define VTEM_PB6 6
+
+#define VTEM_MD0 7
+#define VTEM_MD1 8
+#define VTEM_MD2 9
+#define VTEM_MD3 10
+
+
+// VTEM Byte Masks
+//PB0
+#define MASK_VTEM_PB0__RESERVED0 0x01
+#define MASK_VTEM_PB0__SYNC 0x02
+#define MASK_VTEM_PB0__VFR 0x04
+#define MASK_VTEM_PB0__AFR 0x08
+#define MASK_VTEM_PB0__DS_TYPE 0x30
+ //0: Periodic pseudo-static EM Data Set
+ //1: Periodic dynamic EM Data Set
+ //2: Unique EM Data Set
+ //3: Reserved
+#define MASK_VTEM_PB0__END 0x40
+#define MASK_VTEM_PB0__NEW 0x80
+
+//PB1
+#define MASK_VTEM_PB1__RESERVED1 0xFF
+
+//PB2
+#define MASK_VTEM_PB2__ORGANIZATION_ID 0xFF
+ //0: This is a Vendor Specific EM Data Set
+ //1: This EM Data Set is defined by This Specification (HDMI 2.1 r102.clean)
+ //2: This EM Data Set is defined by CTA-861-G
+ //3: This EM Data Set is defined by VESA
+//PB3
+#define MASK_VTEM_PB3__DATA_SET_TAG_MSB 0xFF
+//PB4
+#define MASK_VTEM_PB4__DATA_SET_TAG_LSB 0xFF
+//PB5
+#define MASK_VTEM_PB5__DATA_SET_LENGTH_MSB 0xFF
+//PB6
+#define MASK_VTEM_PB6__DATA_SET_LENGTH_LSB 0xFF
+
+
+
+//PB7-27 (20 bytes):
+//PB7 = MD0
+#define MASK_VTEM_MD0__VRR_EN 0x01
+#define MASK_VTEM_MD0__M_CONST 0x02
+#define MASK_VTEM_MD0__RESERVED2 0x0C
+#define MASK_VTEM_MD0__FVA_FACTOR_M1 0xF0
+
+//MD1
+#define MASK_VTEM_MD1__BASE_VFRONT 0xFF
+
+//MD2
+#define MASK_VTEM_MD2__BASE_REFRESH_RATE_98 0x03
+#define MASK_VTEM_MD2__RB 0x04
+#define MASK_VTEM_MD2__RESERVED3 0xF8
+
+//MD3
+#define MASK_VTEM_MD3__BASE_REFRESH_RATE_07 0xFF
+
enum ColorimetryRGBDP {
ColorimetryRGB_DP_sRGB = 0,
ColorimetryRGB_DP_AdobeRGB = 3,
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 b3810b864676..05e2be856037 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -66,6 +66,39 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le
{ 3, 6, 10, 12 }, /* Alt #3 - Super aggressiveness */
};
+struct abm_parameters {
+ unsigned char min_reduction;
+ unsigned char max_reduction;
+ unsigned char bright_pos_gain;
+ unsigned char dark_pos_gain;
+ unsigned char brightness_gain;
+ unsigned char contrast_factor;
+ unsigned char deviation_gain;
+ unsigned char min_knee;
+ unsigned char max_knee;
+};
+
+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},
+ {0xff, 0x85, 0x20, 0x00, 0xff, 0x90, 0xa8, 0x40, 0xE0},
+ {0xff, 0x40, 0x20, 0x00, 0xff, 0x90, 0x68, 0x40, 0xE0},
+ {0x82, 0x4d, 0x20, 0x00, 0x00, 0x90, 0xb3, 0x70, 0x70},
+};
+
+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, 0xa8, 0xb3, 0x70, 0x70},
+ {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xa8, 0xb3, 0x70, 0x70},
+ {0x99, 0x65, 0x20, 0x00, 0x00, 0xa8, 0xb3, 0x70, 0x70},
+ {0x82, 0x4d, 0x20, 0x00, 0x00, 0xa8, 0xb3, 0x70, 0x70},
+};
+
+static const struct abm_parameters * const abm_settings[] = {
+ abm_settings_config0,
+ abm_settings_config1,
+};
+
#define NUM_AMBI_LEVEL 5
#define NUM_AGGR_LEVEL 4
#define NUM_POWER_FN_SEGS 8
@@ -131,11 +164,13 @@ struct iram_table_v_2_2 {
uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x16 U0.8 */
uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x2a U2.6 */
uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x3e U2.6 */
- uint8_t hybridFactor[NUM_AGGR_LEVEL]; /* 0x52 U0.8 */
- uint8_t contrastFactor[NUM_AGGR_LEVEL]; /* 0x56 U0.8 */
+ uint8_t hybrid_factor[NUM_AGGR_LEVEL]; /* 0x52 U0.8 */
+ uint8_t contrast_factor[NUM_AGGR_LEVEL]; /* 0x56 U0.8 */
uint8_t deviation_gain[NUM_AGGR_LEVEL]; /* 0x5a U0.8 */
uint8_t iir_curve[NUM_AMBI_LEVEL]; /* 0x5e U0.8 */
- uint8_t pad[29]; /* 0x63 U0.8 */
+ uint8_t min_knee[NUM_AGGR_LEVEL]; /* 0x63 U0.8 */
+ uint8_t max_knee[NUM_AGGR_LEVEL]; /* 0x67 U0.8 */
+ uint8_t pad[21]; /* 0x6b U0.8 */
/* parameters for crgb conversion */
uint16_t crgb_thresh[NUM_POWER_FN_SEGS]; /* 0x80 U3.13 */
@@ -501,15 +536,72 @@ void fill_iram_v_2_2(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame
ram_table->dark_pos_gain[4][2] = 0x00;
ram_table->dark_pos_gain[4][3] = 0x00;
- ram_table->hybridFactor[0] = 0xff;
- ram_table->hybridFactor[1] = 0xff;
- ram_table->hybridFactor[2] = 0xff;
- ram_table->hybridFactor[3] = 0xc0;
+ ram_table->hybrid_factor[0] = 0xff;
+ ram_table->hybrid_factor[1] = 0xff;
+ ram_table->hybrid_factor[2] = 0xff;
+ ram_table->hybrid_factor[3] = 0xc0;
- ram_table->contrastFactor[0] = 0x99;
- ram_table->contrastFactor[1] = 0x99;
- ram_table->contrastFactor[2] = 0x90;
- ram_table->contrastFactor[3] = 0x80;
+ ram_table->contrast_factor[0] = 0x99;
+ ram_table->contrast_factor[1] = 0x99;
+ ram_table->contrast_factor[2] = 0x90;
+ ram_table->contrast_factor[3] = 0x80;
+
+ ram_table->iir_curve[0] = 0x65;
+ ram_table->iir_curve[1] = 0x65;
+ ram_table->iir_curve[2] = 0x65;
+ ram_table->iir_curve[3] = 0x65;
+ ram_table->iir_curve[4] = 0x65;
+
+ //Gamma 2.2
+ ram_table->crgb_thresh[0] = cpu_to_be16(0x127c);
+ ram_table->crgb_thresh[1] = cpu_to_be16(0x151b);
+ ram_table->crgb_thresh[2] = cpu_to_be16(0x17d5);
+ ram_table->crgb_thresh[3] = cpu_to_be16(0x1a56);
+ ram_table->crgb_thresh[4] = cpu_to_be16(0x1c83);
+ ram_table->crgb_thresh[5] = cpu_to_be16(0x1e72);
+ ram_table->crgb_thresh[6] = cpu_to_be16(0x20f0);
+ ram_table->crgb_thresh[7] = cpu_to_be16(0x232b);
+ ram_table->crgb_offset[0] = cpu_to_be16(0x2999);
+ ram_table->crgb_offset[1] = cpu_to_be16(0x3999);
+ ram_table->crgb_offset[2] = cpu_to_be16(0x4666);
+ ram_table->crgb_offset[3] = cpu_to_be16(0x5999);
+ ram_table->crgb_offset[4] = cpu_to_be16(0x6333);
+ ram_table->crgb_offset[5] = cpu_to_be16(0x7800);
+ ram_table->crgb_offset[6] = cpu_to_be16(0x8c00);
+ ram_table->crgb_offset[7] = cpu_to_be16(0xa000);
+ ram_table->crgb_slope[0] = cpu_to_be16(0x3609);
+ ram_table->crgb_slope[1] = cpu_to_be16(0x2dfa);
+ ram_table->crgb_slope[2] = cpu_to_be16(0x27ea);
+ ram_table->crgb_slope[3] = cpu_to_be16(0x235d);
+ ram_table->crgb_slope[4] = cpu_to_be16(0x2042);
+ ram_table->crgb_slope[5] = cpu_to_be16(0x1dc3);
+ ram_table->crgb_slope[6] = cpu_to_be16(0x1b1a);
+ ram_table->crgb_slope[7] = cpu_to_be16(0x1910);
+
+ fill_backlight_transform_table_v_2_2(
+ params, ram_table);
+}
+
+void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params)
+{
+ unsigned int i, j;
+ unsigned int set = params.set;
+
+ ram_table->flags = 0x0;
+ for (i = 0; i < NUM_AGGR_LEVEL; i++) {
+ ram_table->hybrid_factor[i] = abm_settings[set][i].brightness_gain;
+ ram_table->contrast_factor[i] = abm_settings[set][i].contrast_factor;
+ ram_table->deviation_gain[i] = abm_settings[set][i].deviation_gain;
+ ram_table->min_knee[i] = abm_settings[set][i].min_knee;
+ ram_table->max_knee[i] = abm_settings[set][i].max_knee;
+
+ for (j = 0; j < NUM_AMBI_LEVEL; j++) {
+ ram_table->min_reduction[j][i] = abm_settings[set][i].min_reduction;
+ ram_table->max_reduction[j][i] = abm_settings[set][i].max_reduction;
+ ram_table->bright_pos_gain[j][i] = abm_settings[set][i].bright_pos_gain;
+ ram_table->dark_pos_gain[j][i] = abm_settings[set][i].dark_pos_gain;
+ }
+ }
ram_table->iir_curve[0] = 0x65;
ram_table->iir_curve[1] = 0x65;
@@ -561,7 +653,12 @@ bool dmcu_load_iram(struct dmcu *dmcu,
memset(&ram_table, 0, sizeof(ram_table));
- if (dmcu->dmcu_version.abm_version == 0x22) {
+ if (dmcu->dmcu_version.abm_version == 0x23) {
+ fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params);
+
+ result = dmcu->funcs->load_iram(
+ dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
+ } else if (dmcu->dmcu_version.abm_version == 0x22) {
fill_iram_v_2_2((struct iram_table_v_2_2 *)ram_table, params);
result = dmcu->funcs->load_iram(