diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c073f4558cf46d265e7bb81463a27ee168caa026..364f2c970b6ebf933e1d0b0fdeabcc20729edc7b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -513,6 +513,7 @@ static void fill_gamma_from_crtc( struct dc_gamma *gamma; struct drm_crtc_state *state = crtc->state; struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; + struct dc_transfer_func *input_tf; gamma = dc_create_gamma(); @@ -529,6 +530,16 @@ static void fill_gamma_from_crtc( gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); 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( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f20701a507da0be514a4e4fe4d40f351ecc8edf5..df1bae8ea92bac83bf4dba638c4a2bc5c5479c84 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -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++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct core_stream *stream = pipe_ctx->stream; if (pipe_ctx->surface != surface) continue; @@ -1472,15 +1473,14 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].out_transfer_func && updates[i].out_transfer_func != - surface->public.out_transfer_func) { - if (surface->public.out_transfer_func != NULL) + stream->public.out_transfer_func) { + if (stream->public.out_transfer_func != NULL) dc_transfer_func_release( - surface->public. + stream->public. out_transfer_func); - dc_transfer_func_retain( updates[i].out_transfer_func); - surface->public.out_transfer_func = + stream->public.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 } } + 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] || updates[i].gamma || - updates[i].in_transfer_func || updates[i].out_transfer_func) - core_dc->hwss.set_gamma_correction( - pipe_ctx, pipe_ctx->surface); + core_dc->hwss.set_output_transfer_func( + pipe_ctx, + pipe_ctx->surface, + pipe_ctx->stream); + } if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 8d6aa607e1f5537eda417776ee6d8d36d14cdcbf..237436e22720dc8ade56335c4e667500d05fdaf0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -89,6 +89,9 @@ static bool construct(struct core_stream *stream, static void destruct(struct core_stream *stream) { 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) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 8d2668406f3a75eb65a97bb274f605009168cfec..3ec1f363e43e28d7573649a5be9c59059989382f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -76,9 +76,6 @@ static void destruct(struct surface *surface) if (surface->protected.public.in_transfer_func != NULL) dc_transfer_func_release( 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) 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)); if (tf == NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 36f1c96605e81a15c857d546de3330e039b71d9a..ffea10c73275575d59a373509f83fe9b3e247593 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -254,6 +254,7 @@ struct dc_transfer_func_distributed_points { enum dc_transfer_func_predefined { TRANSFER_FUNCTION_SRGB, TRANSFER_FUNCTION_BT709, + TRANSFER_FUNCTION_PQ, TRANSFER_FUNCTION_LINEAR, }; @@ -287,7 +288,6 @@ struct dc_surface { const struct dc_gamma *gamma_correction; const struct dc_transfer_func *in_transfer_func; - const struct dc_transfer_func *out_transfer_func; }; struct dc_plane_info { @@ -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_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 @@ -527,10 +527,11 @@ struct dc_stream { struct freesync_context freesync_ctx; - /* TODO: dithering */ - /* TODO: transfer function (CSC/regamma/gamut remap) */ + const struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; + + /* TODO: dithering */ /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f6984e9ed1691a35d31ce06ecbb771e1dc095b98..72017d5a8252cfe7552120c0401a78855e5e5862 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -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, const struct core_surface *surface) { 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; const struct core_gamma *ramp = NULL; struct ipp_prescale_params prescale_params = { 0 }; @@ -253,20 +303,10 @@ static bool dce110_set_gamma_correction( 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)) { - 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); } else { - if (ipp) - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); } @@ -1904,7 +1944,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, .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, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dce110_enable_timing_synchronization, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index a67d6756095d6eda30bf6574857db993756ce4f7..c2d35c2c28bfa0dd9a7115c63d055a3bc0b80ac6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -55,6 +55,9 @@ struct core_target { #define DC_GAMMA_TO_CORE(dc_gamma) \ 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 dc_surface public; struct dc_surface_status status; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 89a08342a51f0ea0496f56c305044c1e98a4c8b7..0e803ca83bb9df6fef943fc0e01a234571f8a117 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -77,10 +77,15 @@ struct hw_sequencer_funcs { void (*update_pending_status)( struct pipe_ctx *pipe_ctx); - bool (*set_gamma_correction)( + bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, 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 (*enable_accelerated_mode)(struct core_dc *dc);