drm/amd/display: Refactor output transfer function to stream
authorAnthony Koo <Anthony.Koo@amd.com>
Thu, 15 Dec 2016 17:09:46 +0000 (12:09 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 21:05:32 +0000 (17:05 -0400)
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: Anthony Koo <anthony.koo@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/core/dc_surface.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index c073f4558cf46d265e7bb81463a27ee168caa026..364f2c970b6ebf933e1d0b0fdeabcc20729edc7b 100644 (file)
@@ -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(
index f20701a507da0be514a4e4fe4d40f351ecc8edf5..df1bae8ea92bac83bf4dba638c4a2bc5c5479c84 100644 (file)
@@ -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);
index 8d6aa607e1f5537eda417776ee6d8d36d14cdcbf..237436e22720dc8ade56335c4e667500d05fdaf0 100644 (file)
@@ -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)
index 8d2668406f3a75eb65a97bb274f605009168cfec..3ec1f363e43e28d7573649a5be9c59059989382f 100644 (file)
@@ -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)
index 36f1c96605e81a15c857d546de3330e039b71d9a..ffea10c73275575d59a373509f83fe9b3e247593 100644 (file)
@@ -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 */
index f6984e9ed1691a35d31ce06ecbb771e1dc095b98..72017d5a8252cfe7552120c0401a78855e5e5862 100644 (file)
@@ -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,
index a67d6756095d6eda30bf6574857db993756ce4f7..c2d35c2c28bfa0dd9a7115c63d055a3bc0b80ac6 100644 (file)
@@ -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;
index 89a08342a51f0ea0496f56c305044c1e98a4c8b7..0e803ca83bb9df6fef943fc0e01a234571f8a117 100644 (file)
@@ -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);