Commit 90e508ba authored by Anthony Koo's avatar Anthony Koo Committed by Alex Deucher

drm/amd/display: Refactor output transfer function to stream

Refactor part 3 - Moving output transfer function from surface to stream

Split HWSS to program degamma and regamma separately.
Degamma should be dependent on input transfer function.
And Regamma should depend on the desired output transfer function.
Signed-off-by: default avatarAnthony Koo <anthony.koo@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9cdc4e7c
...@@ -513,6 +513,7 @@ static void fill_gamma_from_crtc( ...@@ -513,6 +513,7 @@ static void fill_gamma_from_crtc(
struct dc_gamma *gamma; struct dc_gamma *gamma;
struct drm_crtc_state *state = crtc->state; struct drm_crtc_state *state = crtc->state;
struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data;
struct dc_transfer_func *input_tf;
gamma = dc_create_gamma(); gamma = dc_create_gamma();
...@@ -529,6 +530,16 @@ static void fill_gamma_from_crtc( ...@@ -529,6 +530,16 @@ static void fill_gamma_from_crtc(
gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
dc_surface->gamma_correction = gamma; dc_surface->gamma_correction = gamma;
input_tf = dc_create_transfer_func();
if (input_tf == NULL)
return;
input_tf->type = TF_TYPE_PREDEFINED;
input_tf->tf = TRANSFER_FUNCTION_SRGB;
dc_surface->in_transfer_func = input_tf;
} }
static void fill_plane_attributes( static void fill_plane_attributes(
......
...@@ -1394,6 +1394,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda ...@@ -1394,6 +1394,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda
for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
struct core_stream *stream = pipe_ctx->stream;
if (pipe_ctx->surface != surface) if (pipe_ctx->surface != surface)
continue; continue;
...@@ -1472,15 +1473,14 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda ...@@ -1472,15 +1473,14 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda
if (updates[i].out_transfer_func && if (updates[i].out_transfer_func &&
updates[i].out_transfer_func != updates[i].out_transfer_func !=
surface->public.out_transfer_func) { stream->public.out_transfer_func) {
if (surface->public.out_transfer_func != NULL) if (stream->public.out_transfer_func != NULL)
dc_transfer_func_release( dc_transfer_func_release(
surface->public. stream->public.
out_transfer_func); out_transfer_func);
dc_transfer_func_retain( dc_transfer_func_retain(
updates[i].out_transfer_func); updates[i].out_transfer_func);
surface->public.out_transfer_func = stream->public.out_transfer_func =
updates[i].out_transfer_func; updates[i].out_transfer_func;
} }
} }
...@@ -1516,12 +1516,19 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda ...@@ -1516,12 +1516,19 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda
} }
} }
if (is_new_pipe_surface[j] ||
updates[i].in_transfer_func)
core_dc->hwss.set_input_transfer_func(
pipe_ctx, pipe_ctx->surface);
if (is_new_pipe_surface[j] || if (is_new_pipe_surface[j] ||
updates[i].gamma || updates[i].gamma ||
updates[i].in_transfer_func ||
updates[i].out_transfer_func) updates[i].out_transfer_func)
core_dc->hwss.set_gamma_correction( core_dc->hwss.set_output_transfer_func(
pipe_ctx, pipe_ctx->surface); pipe_ctx,
pipe_ctx->surface,
pipe_ctx->stream);
} }
if (apply_ctx) { if (apply_ctx) {
core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
......
...@@ -89,6 +89,9 @@ static bool construct(struct core_stream *stream, ...@@ -89,6 +89,9 @@ static bool construct(struct core_stream *stream,
static void destruct(struct core_stream *stream) static void destruct(struct core_stream *stream)
{ {
dc_sink_release(&stream->sink->public); dc_sink_release(&stream->sink->public);
if (stream->public.out_transfer_func != NULL)
dc_transfer_func_release(
stream->public.out_transfer_func);
} }
void dc_stream_retain(const struct dc_stream *dc_stream) void dc_stream_retain(const struct dc_stream *dc_stream)
......
...@@ -76,9 +76,6 @@ static void destruct(struct surface *surface) ...@@ -76,9 +76,6 @@ static void destruct(struct surface *surface)
if (surface->protected.public.in_transfer_func != NULL) if (surface->protected.public.in_transfer_func != NULL)
dc_transfer_func_release( dc_transfer_func_release(
surface->protected.public.in_transfer_func); surface->protected.public.in_transfer_func);
if (surface->protected.public.out_transfer_func != NULL)
dc_transfer_func_release(
surface->protected.public.out_transfer_func);
} }
/******************************************************************************* /*******************************************************************************
...@@ -223,9 +220,8 @@ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) ...@@ -223,9 +220,8 @@ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf)
dm_free(tf); dm_free(tf);
} }
struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc) struct dc_transfer_func *dc_create_transfer_func()
{ {
struct core_dc *core_dc = DC_TO_CORE(dc);
struct transfer_func *tf = dm_alloc(sizeof(*tf)); struct transfer_func *tf = dm_alloc(sizeof(*tf));
if (tf == NULL) if (tf == NULL)
......
...@@ -254,6 +254,7 @@ struct dc_transfer_func_distributed_points { ...@@ -254,6 +254,7 @@ struct dc_transfer_func_distributed_points {
enum dc_transfer_func_predefined { enum dc_transfer_func_predefined {
TRANSFER_FUNCTION_SRGB, TRANSFER_FUNCTION_SRGB,
TRANSFER_FUNCTION_BT709, TRANSFER_FUNCTION_BT709,
TRANSFER_FUNCTION_PQ,
TRANSFER_FUNCTION_LINEAR, TRANSFER_FUNCTION_LINEAR,
}; };
...@@ -287,7 +288,6 @@ struct dc_surface { ...@@ -287,7 +288,6 @@ struct dc_surface {
const struct dc_gamma *gamma_correction; const struct dc_gamma *gamma_correction;
const struct dc_transfer_func *in_transfer_func; const struct dc_transfer_func *in_transfer_func;
const struct dc_transfer_func *out_transfer_func;
}; };
struct dc_plane_info { struct dc_plane_info {
...@@ -353,7 +353,7 @@ struct dc_gamma *dc_create_gamma(void); ...@@ -353,7 +353,7 @@ struct dc_gamma *dc_create_gamma(void);
void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf);
void dc_transfer_func_release(const struct dc_transfer_func *dc_tf); void dc_transfer_func_release(const struct dc_transfer_func *dc_tf);
struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc); struct dc_transfer_func *dc_create_transfer_func(void);
/* /*
* This structure holds a surface address. There could be multiple addresses * This structure holds a surface address. There could be multiple addresses
...@@ -527,10 +527,11 @@ struct dc_stream { ...@@ -527,10 +527,11 @@ struct dc_stream {
struct freesync_context freesync_ctx; struct freesync_context freesync_ctx;
/* TODO: dithering */ const struct dc_transfer_func *out_transfer_func;
/* TODO: transfer function (CSC/regamma/gamut remap) */
struct colorspace_transform gamut_remap_matrix; struct colorspace_transform gamut_remap_matrix;
struct csc_transform csc_color_matrix; struct csc_transform csc_color_matrix;
/* TODO: dithering */
/* TODO: custom INFO packets */ /* TODO: custom INFO packets */
/* TODO: ABM info (DMCU) */ /* TODO: ABM info (DMCU) */
/* TODO: PSR info */ /* TODO: PSR info */
......
...@@ -231,11 +231,61 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, ...@@ -231,11 +231,61 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params,
} }
} }
static bool dce110_set_gamma_correction( static bool dce110_set_degamma(
struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx,
const struct core_surface *surface) const struct core_surface *surface)
{ {
struct input_pixel_processor *ipp = pipe_ctx->ipp; struct input_pixel_processor *ipp = pipe_ctx->ipp;
const struct core_transfer_func *tf = NULL;
struct ipp_prescale_params prescale_params = { 0 };
bool result = true;
if (ipp == NULL)
return false;
if (surface->public.in_transfer_func)
tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
build_prescale_params(&prescale_params, surface);
ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
if (tf == NULL) {
/* Default case if no input transfer function specified */
ipp->funcs->ipp_set_degamma(ipp,
IPP_DEGAMMA_MODE_BYPASS);
} else if (tf->public.type == TF_TYPE_PREDEFINED) {
switch (tf->public.tf) {
case TRANSFER_FUNCTION_SRGB:
ipp->funcs->ipp_set_degamma(ipp,
IPP_DEGAMMA_MODE_HW_sRGB);
break;
case TRANSFER_FUNCTION_BT709:
ipp->funcs->ipp_set_degamma(ipp,
IPP_DEGAMMA_MODE_HW_xvYCC);
break;
case TRANSFER_FUNCTION_LINEAR:
ipp->funcs->ipp_set_degamma(ipp,
IPP_DEGAMMA_MODE_BYPASS);
break;
case TRANSFER_FUNCTION_PQ:
result = false;
break;
default:
result = false;
}
} else {
/*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
result = false;
}
return result;
}
static bool dce110_set_output_transfer_func(
struct pipe_ctx *pipe_ctx,
const struct core_surface *surface, /* Surface - To be removed */
const struct core_stream *stream)
{
struct output_pixel_processor *opp = pipe_ctx->opp; struct output_pixel_processor *opp = pipe_ctx->opp;
const struct core_gamma *ramp = NULL; const struct core_gamma *ramp = NULL;
struct ipp_prescale_params prescale_params = { 0 }; struct ipp_prescale_params prescale_params = { 0 };
...@@ -253,20 +303,10 @@ static bool dce110_set_gamma_correction( ...@@ -253,20 +303,10 @@ static bool dce110_set_gamma_correction(
opp->funcs->opp_power_on_regamma_lut(opp, true); opp->funcs->opp_power_on_regamma_lut(opp, true);
if (ipp) {
build_prescale_params(&prescale_params, surface);
ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
}
if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) {
opp->funcs->opp_program_regamma_pwl(opp, regamma_params); opp->funcs->opp_program_regamma_pwl(opp, regamma_params);
if (ipp)
ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
} else { } else {
if (ipp)
ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
} }
...@@ -1904,7 +1944,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { ...@@ -1904,7 +1944,8 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.set_plane_config = set_plane_config, .set_plane_config = set_plane_config,
.update_plane_addr = update_plane_addr, .update_plane_addr = update_plane_addr,
.update_pending_status = dce110_update_pending_status, .update_pending_status = dce110_update_pending_status,
.set_gamma_correction = dce110_set_gamma_correction, .set_input_transfer_func = dce110_set_degamma,
.set_output_transfer_func = dce110_set_output_transfer_func,
.power_down = dce110_power_down, .power_down = dce110_power_down,
.enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_accelerated_mode = dce110_enable_accelerated_mode,
.enable_timing_synchronization = dce110_enable_timing_synchronization, .enable_timing_synchronization = dce110_enable_timing_synchronization,
......
...@@ -55,6 +55,9 @@ struct core_target { ...@@ -55,6 +55,9 @@ struct core_target {
#define DC_GAMMA_TO_CORE(dc_gamma) \ #define DC_GAMMA_TO_CORE(dc_gamma) \
container_of(dc_gamma, struct core_gamma, public) container_of(dc_gamma, struct core_gamma, public)
#define DC_TRANSFER_FUNC_TO_CORE(dc_transfer_func) \
container_of(dc_transfer_func, struct core_transfer_func, public)
struct core_surface { struct core_surface {
struct dc_surface public; struct dc_surface public;
struct dc_surface_status status; struct dc_surface_status status;
......
...@@ -77,10 +77,15 @@ struct hw_sequencer_funcs { ...@@ -77,10 +77,15 @@ struct hw_sequencer_funcs {
void (*update_pending_status)( void (*update_pending_status)(
struct pipe_ctx *pipe_ctx); struct pipe_ctx *pipe_ctx);
bool (*set_gamma_correction)( bool (*set_input_transfer_func)(
struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx,
const struct core_surface *surface); const struct core_surface *surface);
bool (*set_output_transfer_func)(
struct pipe_ctx *pipe_ctx,
const struct core_surface *surface,
const struct core_stream *stream);
void (*power_down)(struct core_dc *dc); void (*power_down)(struct core_dc *dc);
void (*enable_accelerated_mode)(struct core_dc *dc); void (*enable_accelerated_mode)(struct core_dc *dc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment