Commit 49f59499 authored by Jun Lei's avatar Jun Lei Committed by Alex Deucher
Browse files

drm/amd/display: add new pixel rate programming



[why]
New dividers in DCCG need to be programmed depending
on encoder/stream type since pixels per clock in
OTG/DIO is different

DIO also needs additional programming depending on
pixels per clock

Signed-off-by: default avatarJun Lei <Jun.Lei@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
parent 452e9214
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -576,6 +576,7 @@ struct dcn10_stream_enc_registers {
	type DP_SEC_GSP11_LINE_NUM

#define SE_REG_FIELD_LIST_DCN3_2(type) \
	type DIG_FIFO_OUTPUT_PIXEL_MODE;\
	type DIG_SYMCLK_FE_ON;\
	type DIG_FIFO_READ_START_LEVEL;\
	type DIG_FIFO_ENABLE;\
+14 −0
Original line number Diff line number Diff line
@@ -661,7 +661,17 @@ enum dc_status dcn20_enable_stream_timing(
	struct mpc_dwb_flow_control flow_control;
	struct mpc *mpc = dc->res_pool->mpc;
	bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing));
	unsigned int k1_div = PIXEL_RATE_DIV_NA;
	unsigned int k2_div = PIXEL_RATE_DIV_NA;

	if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) {
		hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);

		dc->res_pool->dccg->funcs->set_pixel_rate_div(
			dc->res_pool->dccg,
			pipe_ctx->stream_res.tg->inst,
			k1_div, k2_div);
	}
	/* by upper caller loop, pipe0 is parent pipe and be called first.
	 * back end is set up by for pipe0. Other children pipe share back end
	 * with pipe 0. No program is needed.
@@ -2485,6 +2495,10 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)

	tg->funcs->set_early_control(tg, early_control);

	if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
		pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc,
			timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 ? 2 : 1);

	/* enable audio only within mode set */
	if (pipe_ctx->stream_res.audio != NULL) {
		if (is_dp_128b_132b_signal(pipe_ctx))
+1 −0
Original line number Diff line number Diff line
@@ -272,6 +272,7 @@ static const struct dccg_funcs dccg32_funcs = {
	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
	.otg_add_pixel = dccg32_otg_add_pixel,
	.otg_drop_pixel = dccg32_otg_drop_pixel,
	.set_pixel_rate_div = dccg32_set_pixel_rate_div,
};

struct dccg *dccg32_create(
+2 −1
Original line number Diff line number Diff line
@@ -240,7 +240,8 @@
	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\
	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\
	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\
	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh)
	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\
	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, mask_sh)

#if defined(CONFIG_DRM_AMD_DC_HDCP)
#define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\
+66 −6
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#include "clk_mgr.h"
#include "dsc.h"
#include "dcn20/dcn20_optc.h"
#include "dc_link_dp.h"

#define DC_LOGGER_INIT(logger)

@@ -836,20 +837,44 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
	}
}

/*
* Given any pipe_ctx, return the total ODM combine factor, and optionally return
* the OPPids which are used
* */
static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_instances)
{
	unsigned int opp_count = 1;
	struct pipe_ctx *odm_pipe;

	/* First get to the top pipe */
	for (odm_pipe = pipe_ctx; odm_pipe->prev_odm_pipe; odm_pipe = odm_pipe->prev_odm_pipe)
		;

	/* First pipe is always used */
	if (opp_instances)
		opp_instances[0] = odm_pipe->stream_res.opp->inst;

	/* Find and count odm pipes, if any */
	for (odm_pipe = odm_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
		if (opp_instances)
			opp_instances[opp_count] = odm_pipe->stream_res.opp->inst;
		opp_count++;
	}

	return opp_count;
}

void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
	struct pipe_ctx *odm_pipe;
	int opp_cnt = 1;
	int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
	int opp_cnt = 0;
	int opp_inst[MAX_PIPES] = {0};
	bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
	struct mpc_dwb_flow_control flow_control;
	struct mpc *mpc = dc->res_pool->mpc;
	int i;

	for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
		opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
		opp_cnt++;
	}
	opp_cnt = get_odm_config(pipe_ctx, opp_inst);

	if (opp_cnt > 1)
		pipe_ctx->stream_res.tg->funcs->set_odm_combine(
@@ -892,3 +917,38 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
		update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC);
}

unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
{
	struct dc_stream_state *stream = pipe_ctx->stream;
	unsigned int odm_combine_factor = 0;

	odm_combine_factor = get_odm_config(pipe_ctx, NULL);

	if (is_dp_128b_132b_signal(pipe_ctx)) {
		*k2_div = PIXEL_RATE_DIV_BY_1;
	} else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) {
		*k1_div = PIXEL_RATE_DIV_BY_1;
		if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
			*k2_div = PIXEL_RATE_DIV_BY_2;
		else
			*k2_div = PIXEL_RATE_DIV_BY_4;
	} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
		if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
			*k1_div = PIXEL_RATE_DIV_BY_1;
			*k2_div = PIXEL_RATE_DIV_BY_2;
		} else if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) {
			*k1_div = PIXEL_RATE_DIV_BY_2;
			*k2_div = PIXEL_RATE_DIV_BY_2;
		} else {
			if (odm_combine_factor == 1)
				*k2_div = PIXEL_RATE_DIV_BY_4;
			else if (odm_combine_factor == 2)
				*k2_div = PIXEL_RATE_DIV_BY_2;
		}
	}

	if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA))
		ASSERT(false);

	return odm_combine_factor;
}
Loading