Commit d7194cf6 authored by Aric Cyr's avatar Aric Cyr Committed by Alex Deucher
Browse files

drm/amd/display: Implement gamma correction using input LUT



The dc_gamma in dc_surface will be programmed to the input
LUT if provided.  If dc_gamma is not provided in dc_surface
regamma may be used to emulate gamma.

Some refactor and cleanup included as well.

Signed-off-by: default avatarAric Cyr <aric.cyr@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3c25e920
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -521,14 +521,11 @@ static void fill_gamma_from_crtc(
		return;

	for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) {
		gamma->gamma_ramp_rgb256x3x16.red[i] = lut[i].red;
		gamma->gamma_ramp_rgb256x3x16.green[i] = lut[i].green;
		gamma->gamma_ramp_rgb256x3x16.blue[i] = lut[i].blue;
		gamma->red[i] = lut[i].red;
		gamma->green[i] = lut[i].green;
		gamma->blue[i] = lut[i].blue;
	}

	gamma->type = GAMMA_RAMP_RBG256X3X16;
	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);

	dc_surface->gamma_correction = gamma;

	input_tf = dc_create_transfer_func();
@@ -822,6 +819,12 @@ static void fill_stream_properties_from_drm_display_mode(

	stream->output_color_space = get_output_color_space(timing_out);

	{
		struct dc_transfer_func *tf = dc_create_transfer_func();
		tf->type = TF_TYPE_PREDEFINED;
		tf->tf = TRANSFER_FUNCTION_SRGB;
		stream->out_transfer_func = tf;
	}
}

static void fill_audio_info(
@@ -3066,7 +3069,7 @@ static bool is_dp_capable_without_timing_msa(
	    dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index,
			 DP_DOWN_STREAM_PORT_COUNT,
			 &dpcd_data, sizeof(dpcd_data)) )
		capable = dpcd_data & DP_MSA_TIMING_PAR_IGNORED? true:false;
		capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false;

	return capable;
}
+11 −18
Original line number Diff line number Diff line
@@ -573,7 +573,7 @@ static bool find_software_points(
	uint32_t *index_right,
	enum hw_point_position *pos)
{
	const uint32_t max_number = RGB_256X3X16 + 3;
	const uint32_t max_number = INPUT_LUT_ENTRIES + 3;

	struct fixed31_32 left, right;

@@ -686,12 +686,12 @@ static bool build_custom_gamma_mapping_coefficients_worker(
			return false;
		}

		if (index_left >= RGB_256X3X16 + 3) {
		if (index_left >= INPUT_LUT_ENTRIES + 3) {
			BREAK_TO_DEBUGGER();
			return false;
		}

		if (index_right >= RGB_256X3X16 + 3) {
		if (index_right >= INPUT_LUT_ENTRIES + 3) {
			BREAK_TO_DEBUGGER();
			return false;
		}
@@ -958,20 +958,13 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb,
		const struct core_gamma *ramp,
		struct dividers dividers)
{
	const struct dc_gamma_ramp_rgb256x3x16 *gamma;
	const struct dc_gamma *gamma = &ramp->public;
	const uint16_t max_driver = 0xFFFF;
	const uint16_t max_os = 0xFF00;
	uint16_t scaler = max_os;
	uint32_t i;
	uint32_t i = 0;
	struct pwl_float_data *rgb = pwl_rgb;
	struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;

	if (ramp->public.type == GAMMA_RAMP_RBG256X3X16)
		gamma = &ramp->public.gamma_ramp_rgb256x3x16;
	else
		return false; /* invalid option */

	i = 0;
	struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1;

	do {
		if ((gamma->red[i] > max_os) ||
@@ -981,7 +974,7 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb,
			break;
		}
		++i;
	} while (i != RGB_256X3X16);
	} while (i != INPUT_LUT_ENTRIES);

	i = 0;

@@ -995,7 +988,7 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb,

		++rgb;
		++i;
	} while (i != RGB_256X3X16);
	} while (i != INPUT_LUT_ENTRIES);

	rgb->r = dal_fixed31_32_mul(rgb_last->r,
			dividers.divider1);
@@ -1110,7 +1103,7 @@ static bool calculate_interpolated_hardware_curve(
		return false;

	coeff = coeff128;
	max_entries += RGB_256X3X16;
	max_entries += INPUT_LUT_ENTRIES;

	/* TODO: float point case */

@@ -1440,13 +1433,13 @@ bool calculate_regamma_params(struct pwl_params *params,
	coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3));
	if (!coordinates_x)
		goto coordinates_x_alloc_fail;
	rgb_user = dm_alloc(sizeof(*rgb_user) * (FLOAT_GAMMA_RAMP_MAX + 3));
	rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3));
	if (!rgb_user)
		goto rgb_user_alloc_fail;
	rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3));
	if (!rgb_regamma)
		goto rgb_regamma_alloc_fail;
	rgb_oem = dm_alloc(sizeof(*rgb_oem) * (FLOAT_GAMMA_RAMP_MAX + 3));
	rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3));
	if (!rgb_oem)
		goto rgb_oem_alloc_fail;
	axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3));
+0 −36
Original line number Diff line number Diff line
@@ -183,43 +183,9 @@ void dc_destroy(struct dc **dc);
 ******************************************************************************/

enum {
	RGB_256X3X16 = 256,
	FLOAT_GAMMA_RAMP_MAX = 1025,
	TRANSFER_FUNC_POINTS = 1025
};

enum dc_gamma_ramp_type {
	GAMMA_RAMP_RBG256X3X16,
	GAMMA_RAMP_FLOAT,
};

struct float_rgb {
	struct fixed32_32 red;
	struct fixed32_32 green;
	struct fixed32_32 blue;
};

struct dc_gamma_ramp_float {
	struct float_rgb scale;
	struct float_rgb offset;
	struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX];
};

struct dc_gamma_ramp_rgb256x3x16 {
	uint16_t red[RGB_256X3X16];
	uint16_t green[RGB_256X3X16];
	uint16_t blue[RGB_256X3X16];
};

struct dc_gamma {
	enum dc_gamma_ramp_type type;
	union {
		struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16;
		struct dc_gamma_ramp_float gamma_ramp_float;
	};
	uint32_t size;
};

enum dc_transfer_func_type {
	TF_TYPE_PREDEFINED,
	TF_TYPE_DISTRIBUTED_POINTS,
@@ -266,9 +232,7 @@ struct dc_surface {
	bool horizontal_mirror;
	enum plane_stereo_format stereo_format;

	/* TO BE REMOVED AFTER BELOW TRANSFER FUNCTIONS IMPLEMENTED */
	const struct dc_gamma *gamma_correction;

	const struct dc_transfer_func *in_transfer_func;
};

+10 −0
Original line number Diff line number Diff line
@@ -370,6 +370,16 @@ struct dc_cursor_mi_param {

/* IPP related types */

enum {
	INPUT_LUT_ENTRIES = 256
};

struct dc_gamma {
	uint16_t red[INPUT_LUT_ENTRIES];
	uint16_t green[INPUT_LUT_ENTRIES];
	uint16_t blue[INPUT_LUT_ENTRIES];
};

/* Used by both ipp amd opp functions*/
/* TODO: to be consolidated with enum color_space */

+0 −2
Original line number Diff line number Diff line
@@ -28,8 +28,6 @@

#include "dce_opp.h"

#include "gamma_types.h"

#include "reg_helper.h"

#define REG(reg)\
Loading