Commit feb4a3cd authored by Eric Bernstein's avatar Eric Bernstein Committed by Alex Deucher

drm/amd/display: Integrating MPC pseudocode

Integrating MPC pseudocode to support new blending cases
with secondary MPCC list.
This includes a design change to MPC data structures and
interfaces.
Signed-off-by: default avatarEric Bernstein <eric.bernstein@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4b87d3a8
......@@ -579,8 +579,6 @@ enum dc_timing_standard {
TIMING_STANDARD_MAX
};
enum dc_color_depth {
COLOR_DEPTH_UNDEFINED,
COLOR_DEPTH_666,
......
......@@ -573,28 +573,25 @@ static void plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
int fe_idx = pipe_ctx->pipe_idx;
struct hubp *hubp = dc->res_pool->hubps[fe_idx];
struct mpc *mpc = dc->res_pool->mpc;
int opp_id, z_idx;
int mpcc_id = -1;
int opp_id;
struct mpc_tree *mpc_tree_params;
struct mpcc *mpcc_to_remove = NULL;
/* look at tree rather than mi here to know if we already reset */
for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) {
struct output_pixel_processor *opp = dc->res_pool->opps[opp_id];
for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) {
if (opp->mpc_tree.dpp[z_idx] == fe_idx) {
mpcc_id = opp->mpc_tree.mpcc[z_idx];
break;
}
}
if (mpcc_id != -1)
mpc_tree_params = &(opp->mpc_tree_params);
mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, fe_idx);
if (mpcc_to_remove != NULL)
break;
}
/*Already reset*/
if (opp_id == dc->res_pool->pipe_count)
return;
mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree),
dc->res_pool->opps[opp_id]->inst, fe_idx);
mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
if (hubp->funcs->hubp_disconnect)
hubp->funcs->hubp_disconnect(hubp);
......@@ -652,7 +649,7 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
REG_UPDATE(DPP_CONTROL[fe_idx],
DPP_CLOCK_ENABLE, 0);
if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0)
if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree_params.opp_list == NULL)
REG_UPDATE(OPP_PIPE_CONTROL[opp_id],
OPP_PIPE_CLOCK_EN, 0);
......@@ -677,7 +674,7 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
static void dcn10_init_hw(struct dc *dc)
{
int i;
int i, opp_id;
struct abm *abm = dc->res_pool->abm;
struct dmcu *dmcu = dc->res_pool->dmcu;
struct dce_hwseq *hws = dc->hwseq;
......@@ -740,17 +737,19 @@ static void dcn10_init_hw(struct dc *dc)
}
}
/* Initialize MPC tree based on HW values */
for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) {
struct output_pixel_processor *opp = dc->res_pool->opps[opp_id];
struct mpc_tree *mpc_tree_params = &(opp->mpc_tree_params);
dc->res_pool->mpc->funcs->init_mpcc_list_from_hw(dc->res_pool->mpc, mpc_tree_params);
}
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct timing_generator *tg = dc->res_pool->timing_generators[i];
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct output_pixel_processor *opp = dc->res_pool->opps[i];
struct mpc_tree_cfg *mpc_tree = &opp->mpc_tree;
struct hubp *hubp = dc->res_pool->hubps[i];
mpc_tree->dpp[0] = i;
mpc_tree->mpcc[0] = i;
mpc_tree->num_pipes = 1;
pipe_ctx->stream_res.tg = tg;
pipe_ctx->pipe_idx = i;
......@@ -1694,38 +1693,6 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
}
}
static void set_mpc_output_csc(struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum dc_color_space colorspace,
uint16_t *matrix,
int opp_id)
{
struct mpc *mpc = dc->res_pool->mpc;
int i;
struct out_csc_color_matrix tbl_entry;
enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
//uint16_t matrix[12];
for (i = 0; i < 12; i++)
tbl_entry.regval[i] = matrix[i];
tbl_entry.color_space = colorspace;
if (mpc->funcs->set_output_csc != NULL)
mpc->funcs->set_output_csc(mpc,
opp_id,
&tbl_entry,
ocsc_mode);
} else {
if (mpc->funcs->set_ocsc_default != NULL)
mpc->funcs->set_ocsc_default(mpc,
opp_id,
colorspace,
ocsc_mode);
}
}
static void program_output_csc(struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum dc_color_space colorspace,
......@@ -1736,13 +1703,6 @@ static void program_output_csc(struct dc *dc,
program_csc_matrix(pipe_ctx,
colorspace,
matrix);
else
set_mpc_output_csc(dc,
pipe_ctx,
colorspace,
matrix,
opp_id);
}
static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
......@@ -1914,35 +1874,73 @@ static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
static void update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct mpcc_cfg mpcc_cfg = {0};
struct hubp *hubp = pipe_ctx->plane_res.hubp;
struct pipe_ctx *top_pipe;
bool per_pixel_alpha =
pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
struct mpcc_blnd_cfg blnd_cfg;
bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
int mpcc_id;
struct mpcc *new_mpcc;
struct mpc *mpc = dc->res_pool->mpc;
struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
/* TODO: proper fix once fpga works */
mpcc_cfg.dpp_id = hubp->inst;
mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst;
mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree);
for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe)
mpcc_cfg.z_index++;
if (dc->debug.surface_visual_confirm)
dcn10_get_surface_visual_confirm_color(
pipe_ctx, &mpcc_cfg.black_color);
pipe_ctx, &blnd_cfg.black_color);
else
color_space_to_black_color(
dc, pipe_ctx->stream->output_color_space,
&mpcc_cfg.black_color);
mpcc_cfg.per_pixel_alpha = per_pixel_alpha;
&blnd_cfg.black_color);
if (per_pixel_alpha)
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
else
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
blnd_cfg.overlap_only = false;
blnd_cfg.global_alpha = 0xff;
blnd_cfg.global_gain = 0xff;
/* DCN1.0 has output CM before MPC which seems to screw with
* pre-multiplied alpha.
*/
mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace(
blnd_cfg.pre_multiplied_alpha = is_rgb_cspace(
pipe_ctx->stream->output_color_space)
&& per_pixel_alpha;
hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg);
hubp->opp_id = mpcc_cfg.opp_id;
/*
* TODO: remove hack
* Note: currently there is a bug in init_hw such that
* on resume from hibernate, BIOS sets up MPCC0, and
* we do mpcc_remove but the mpcc cannot go to idle
* after remove. This cause us to pick mpcc1 here,
* which causes a pstate hang for yet unknown reason.
*/
mpcc_id = hubp->inst;
/* check if this MPCC is already being used */
new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
/* remove MPCC if being used */
if (new_mpcc != NULL)
mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
if (dc->debug.sanity_checks)
mpc->funcs->assert_mpcc_idle_before_connect(
dc->res_pool->mpc, mpcc_id);
/* Call MPC to insert new plane */
new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
mpc_tree_params,
&blnd_cfg,
NULL,
NULL,
hubp->inst,
mpcc_id);
ASSERT(new_mpcc != NULL);
hubp->opp_id = pipe_ctx->stream_res.opp->inst;
hubp->mpcc_id = mpcc_id;
}
static void update_scaler(struct pipe_ctx *pipe_ctx)
......
......@@ -30,9 +30,6 @@
#define TO_DCN10_MPC(mpc_base) \
container_of(mpc_base, struct dcn10_mpc, base)
#define MAX_MPCC 6
#define MAX_OPP 6
#define MPC_COMMON_REG_LIST_DCN1_0(inst) \
SRII(MPCC_TOP_SEL, MPCC, inst),\
SRII(MPCC_BOT_SEL, MPCC, inst),\
......@@ -42,7 +39,8 @@
SRII(MPCC_BG_G_Y, MPCC, inst),\
SRII(MPCC_BG_R_CR, MPCC, inst),\
SRII(MPCC_BG_B_CB, MPCC, inst),\
SRII(MPCC_BG_B_CB, MPCC, inst)
SRII(MPCC_BG_B_CB, MPCC, inst),\
SRII(MPCC_SM_CONTROL, MPCC, inst)
#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \
SRII(MUX, MPC_OUT, inst)
......@@ -56,6 +54,7 @@
uint32_t MPCC_BG_G_Y[MAX_MPCC]; \
uint32_t MPCC_BG_R_CR[MAX_MPCC]; \
uint32_t MPCC_BG_B_CB[MAX_MPCC]; \
uint32_t MPCC_SM_CONTROL[MAX_MPCC]; \
uint32_t MUX[MAX_OPP];
#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\
......@@ -65,12 +64,20 @@
SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\
SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\
SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\
SF(MPCC0_MPCC_CONTROL, MPCC_GLOBAL_ALPHA, mask_sh),\
SF(MPCC0_MPCC_CONTROL, MPCC_GLOBAL_GAIN, mask_sh),\
SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\
SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\
SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\
SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\
SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\
SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_EN, mask_sh),\
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_MODE, mask_sh),\
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FRAME_ALT, mask_sh),\
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\
SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\
SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh)
#define MPC_REG_FIELD_LIST(type) \
......@@ -80,12 +87,20 @@
type MPCC_ALPHA_BLND_MODE;\
type MPCC_ALPHA_MULTIPLIED_MODE;\
type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\
type MPCC_GLOBAL_ALPHA;\
type MPCC_GLOBAL_GAIN;\
type MPCC_IDLE;\
type MPCC_BUSY;\
type MPCC_OPP_ID;\
type MPCC_BG_G_Y;\
type MPCC_BG_R_CR;\
type MPCC_BG_B_CB;\
type MPCC_SM_EN;\
type MPCC_SM_MODE;\
type MPCC_SM_FRAME_ALT;\
type MPCC_SM_FIELD_ALT;\
type MPCC_SM_FORCE_NEXT_FRAME_POL;\
type MPCC_SM_FORCE_NEXT_TOP_POL;\
type MPC_OUT_MUX;
struct dcn_mpc_registers {
......@@ -117,23 +132,57 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpcc10,
const struct dcn_mpc_mask *mpc_mask,
int num_mpcc);
int mpc10_mpcc_add(
struct mpc *mpc,
struct mpcc_cfg *cfg);
void mpc10_mpcc_remove(
struct mpc *mpc,
struct mpc_tree_cfg *tree_cfg,
int opp_id,
int dpp_id);
void mpc10_assert_idle_mpcc(
struct mpc *mpc,
int id);
void mpc10_update_blend_mode(
struct mpc *mpc,
struct mpcc_cfg *cfg);
int mpc10_get_opp_id(struct mpc *mpc, int mpcc_id);
struct mpcc *mpc1_insert_plane(
struct mpc *mpc,
struct mpc_tree *tree,
struct mpcc_blnd_cfg *blnd_cfg,
struct mpcc_sm_cfg *sm_cfg,
struct mpcc *insert_above_mpcc,
int dpp_id,
int mpcc_id);
void mpc1_remove_mpcc(
struct mpc *mpc,
struct mpc_tree *tree,
struct mpcc *mpcc);
void mpc1_reset_mpcc(
struct mpc *mpc,
int mpcc_id);
void mpc1_assert_idle_mpcc(
struct mpc *mpc,
int id);
void mpc1_set_bg_color(
struct mpc *mpc,
struct tg_color *bg_color,
int id);
void mpc1_update_stereo_mix(
struct mpc *mpc,
struct mpcc_sm_cfg *sm_cfg,
int mpcc_id);
bool mpc1_is_mpcc_idle(
struct mpc *mpc,
int mpcc_id);
void mpc1_assert_mpcc_idle_before_connect(
struct mpc *mpc,
int mpcc_id);
void mpc1_init_mpcc_list_from_hw(
struct mpc *mpc,
struct mpc_tree *tree);
struct mpcc *mpc1_get_mpcc(
struct mpc *mpc,
int mpcc_id);
struct mpcc *mpc1_get_mpcc_for_dpp(
struct mpc_tree *tree,
int dpp_id);
#endif
......@@ -330,12 +330,19 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10,
const struct dcn10_opp_shift *opp_shift,
const struct dcn10_opp_mask *opp_mask)
{
int i;
oppn10->base.ctx = ctx;
oppn10->base.inst = inst;
oppn10->base.funcs = &dcn10_opp_funcs;
oppn10->base.mpc_tree_params.opp_id = inst;
oppn10->base.mpc_tree_params.opp_list = NULL;
for (i = 0; i < MAX_PIPES; i++)
oppn10->base.mpcc_disconnect_pending[i] = false;
oppn10->regs = regs;
oppn10->opp_shift = opp_shift;
oppn10->opp_mask = opp_mask;
}
......@@ -26,7 +26,10 @@
#define __DC_MPCC_H__
#include "dc_hw_types.h"
#include "opp.h"
#include "hw_shared.h"
#define MAX_MPCC 6
#define MAX_OPP 6
enum mpc_output_csc_mode {
MPC_OUTPUT_CSC_DISABLE = 0,
......@@ -34,45 +37,156 @@ enum mpc_output_csc_mode {
MPC_OUTPUT_CSC_COEF_B
};
struct mpcc_cfg {
int dpp_id;
int opp_id;
struct mpc_tree_cfg *tree_cfg;
unsigned int z_index;
struct tg_color black_color;
bool per_pixel_alpha;
bool pre_multiplied_alpha;
enum mpcc_blend_mode {
MPCC_BLEND_MODE_BYPASS,
MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH,
MPCC_BLEND_MODE_TOP_LAYER_ONLY,
MPCC_BLEND_MODE_TOP_BOT_BLENDING
};
enum mpcc_alpha_blend_mode {
MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA,
MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN,
MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA
};
/*
* MPCC blending configuration
*/
struct mpcc_blnd_cfg {
struct tg_color black_color; /* background color */
enum mpcc_alpha_blend_mode alpha_mode; /* alpha blend mode */
bool pre_multiplied_alpha; /* alpha pre-multiplied mode flag */
int global_gain;
int global_alpha;
bool overlap_only;
};
struct mpcc_sm_cfg {
bool enable;
/* 0-single plane,2-row subsampling,4-column subsampling,6-checkboard subsampling */
int sm_mode;
/* 0- disable frame alternate, 1- enable frame alternate */
bool frame_alt;
/* 0- disable field alternate, 1- enable field alternate */
bool field_alt;
/* 0-no force,2-force frame polarity from top,3-force frame polarity from bottom */
int force_next_frame_porlarity;
/* 0-no force,2-force field polarity from top,3-force field polarity from bottom */
int force_next_field_polarity;
};
/*
* MPCC connection and blending configuration for a single MPCC instance.
* This struct is used as a node in an MPC tree.
*/
struct mpcc {
int mpcc_id; /* MPCC physical instance */
int dpp_id; /* DPP input to this MPCC */
struct mpcc *mpcc_bot; /* pointer to bottom layer MPCC. NULL when not connected */
struct mpcc_blnd_cfg blnd_cfg; /* The blending configuration for this MPCC */
struct mpcc_sm_cfg sm_cfg; /* stereo mix setting for this MPCC */
};
/*
* MPC tree represents all MPCC connections for a pipe.
*/
struct mpc_tree {
int opp_id; /* The OPP instance that owns this MPC tree */
struct mpcc *opp_list; /* The top MPCC layer of the MPC tree that outputs to OPP endpoint */
};
struct mpc {
const struct mpc_funcs *funcs;
struct dc_context *ctx;
struct mpcc mpcc_array[MAX_MPCC];
};
struct mpc_funcs {
int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg);
/*
* Insert DPP into MPC tree based on specified blending position.
* Only used for planes that are part of blending chain for OPP output
*
* Parameters:
* [in/out] mpc - MPC context.
* [in/out] tree - MPC tree structure that plane will be added to.
* [in] blnd_cfg - MPCC blending configuration for the new blending layer.
* [in] sm_cfg - MPCC stereo mix configuration for the new blending layer.
* stereo mix must disable for the very bottom layer of the tree config.
* [in] insert_above_mpcc - Insert new plane above this MPCC. If NULL, insert as bottom plane.
* [in] dpp_id - DPP instance for the plane to be added.
* [in] mpcc_id - The MPCC physical instance to use for blending.
*
* Return: struct mpcc* - MPCC that was added.
*/
struct mpcc* (*insert_plane)(
struct mpc *mpc,
struct mpc_tree *tree,
struct mpcc_blnd_cfg *blnd_cfg,
struct mpcc_sm_cfg *sm_cfg,
struct mpcc *insert_above_mpcc,
int dpp_id,
int mpcc_id);
void (*remove)(struct mpc *mpc,
struct mpc_tree_cfg *tree_cfg,
int opp_id,
int mpcc_inst);
/*
* Remove a specified MPCC from the MPC tree.
*
* Parameters:
* [in/out] mpc - MPC context.
* [in/out] tree - MPC tree structure that plane will be removed from.
* [in/out] mpcc - MPCC to be removed from tree.
*
* Return: void
*/
void (*remove_mpcc)(
struct mpc *mpc,
struct mpc_tree *tree,
struct mpcc *mpcc);
void (*wait_for_idle)(struct mpc *mpc, int id);
/*
* Reset the MPCC HW status by disconnecting all muxes.
*
* Parameters:
* [in/out] mpc - MPC context.
* [in] mpcc_id - The MPCC physical instance to reset.
*
* Return: void
*/
void (*reset_mpcc)(
struct mpc *mpc,
int mpcc_id);
void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg);
/*
* Update the blending configuration for a specified MPCC.
*
* Parameters:
* [in/out] mpc - MPC context.
* [in] blnd_cfg - MPCC blending configuration.
* [in] mpcc_id - The MPCC physical instance.
*
* Return: void
*/
void (*update_blending)(
struct mpc *mpc,
struct mpcc_blnd_cfg *blnd_cfg,
int mpcc_id);
int (*get_opp_id)(struct mpc *mpc, int mpcc_id);
struct mpcc* (*get_mpcc_for_dpp)(
struct mpc_tree *tree,
int dpp_id);
void (*wait_for_idle)(struct mpc *mpc, int id);
void (*set_output_csc)(struct mpc *mpc,
int opp_id,
const struct out_csc_color_matrix *tbl_entry,
enum mpc_output_csc_mode ocsc_mode);
void (*assert_mpcc_idle_before_connect)(struct mpc *mpc, int mpcc_id);
void (*set_ocsc_default)(struct mpc *mpc,
int opp_id,
enum dc_color_space color_space,
enum mpc_output_csc_mode ocsc_mode);
void (*init_mpcc_list_from_hw)(
struct mpc *mpc,
struct mpc_tree *tree);
int (*get_opp_id)(struct mpc *mpc, int mpcc_id);
};
......
......@@ -29,6 +29,7 @@
#include "hw_shared.h"
#include "dc_hw_types.h"
#include "transform.h"
#include "mpc.h"
struct fixed31_32;
......@@ -204,7 +205,7 @@ struct output_pixel_processor {
struct dc_context *ctx;
uint32_t inst;
struct pwl_params regamma_params;
struct mpc_tree_cfg mpc_tree;
struct mpc_tree mpc_tree_params;
bool mpcc_disconnect_pending[MAX_PIPES];
const struct opp_funcs *funcs;
};
......
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