summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_surface.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h7
8 files changed, 97 insertions, 30 deletions
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 c073f45..364f2c9 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 f20701a..df1bae8 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;
}
}
@@ -1517,11 +1517,18 @@ 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 8d6aa60..237436e 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 8d26684..3ec1f36 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 36f1c96..ffea10c 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 f6984e9..72017d5 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 a67d675..c2d35c2 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 89a0834..0e803ca 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);
OpenPOWER on IntegriCloud