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();
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(
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;
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;
}
}
}
}
+ 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);
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)
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);
}
/*******************************************************************************
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)
enum dc_transfer_func_predefined {
TRANSFER_FUNCTION_SRGB,
TRANSFER_FUNCTION_BT709,
+ TRANSFER_FUNCTION_PQ,
TRANSFER_FUNCTION_LINEAR,
};
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 {
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
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 */
}
}
-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 };
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);
}
.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,
#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;
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);