Commit 975507d7 authored by yi-lchen's avatar yi-lchen Committed by Alex Deucher

drm/amd/display: Keep VBios pixel rate div setting until next mode set

[why]
Vbios & Driver have difference pixel rate div policy.
When enabling fast boot & performing blank & unblank w/o timing setting,
pixel clock & pixel rate dividor are not match.
It would cause too high pixel reate and eDP would be black screen.

[How]
We would keep pixel rate div setting by Vbios until next timing setting.
Reviewed-by: default avatarJun Lei <jun.lei@amd.com>
Acked-by: default avatarZaeem Mohamed <zaeem.mohamed@amd.com>
Signed-off-by: default avataryi-lchen <yi-lchen@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a9ebd104
......@@ -3969,6 +3969,12 @@ enum dc_status dc_validate_with_context(struct dc *dc,
res = dc_validate_global_state(dc, context, fast_validate);
/* calculate pixel rate divider after deciding pxiel clock & odm combine */
if ((dc->hwss.calculate_pix_rate_divider) && (res == DC_OK)) {
for (i = 0; i < add_streams_count; i++)
dc->hwss.calculate_pix_rate_divider(dc, context, add_streams[i]);
}
fail:
if (res != DC_OK)
DC_LOG_WARNING("%s:resource validation failed, dc_status:%d\n",
......
......@@ -58,8 +58,8 @@ static void dccg314_trigger_dio_fifo_resync(
static void dccg314_get_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
enum pixel_rate_div *k1,
enum pixel_rate_div *k2)
uint32_t *k1,
uint32_t *k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
......@@ -93,8 +93,8 @@ static void dccg314_get_pixel_rate_div(
return;
}
*k1 = (enum pixel_rate_div)val_k1;
*k2 = (enum pixel_rate_div)val_k2;
*k1 = val_k1;
*k2 = val_k2;
}
static void dccg314_set_pixel_rate_div(
......@@ -104,7 +104,8 @@ static void dccg314_set_pixel_rate_div(
enum pixel_rate_div k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
uint32_t cur_k2 = PIXEL_RATE_DIV_NA;
// Don't program 0xF into the register field. Not valid since
// K1 / K2 field is only 1 / 2 bits wide
......@@ -373,6 +374,7 @@ static const struct dccg_funcs dccg314_funcs = {
.disable_dsc = dccg31_disable_dscclk,
.enable_dsc = dccg31_enable_dscclk,
.set_pixel_rate_div = dccg314_set_pixel_rate_div,
.get_pixel_rate_div = dccg314_get_pixel_rate_div,
.trigger_dio_fifo_resync = dccg314_trigger_dio_fifo_resync,
.set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
.set_dtbclk_p_src = dccg314_set_dtbclk_p_src
......
......@@ -58,8 +58,8 @@ static void dccg32_trigger_dio_fifo_resync(
static void dccg32_get_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
enum pixel_rate_div *k1,
enum pixel_rate_div *k2)
uint32_t *k1,
uint32_t *k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
......@@ -93,8 +93,8 @@ static void dccg32_get_pixel_rate_div(
return;
}
*k1 = (enum pixel_rate_div)val_k1;
*k2 = (enum pixel_rate_div)val_k2;
*k1 = val_k1;
*k2 = val_k2;
}
static void dccg32_set_pixel_rate_div(
......@@ -104,7 +104,8 @@ static void dccg32_set_pixel_rate_div(
enum pixel_rate_div k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
uint32_t cur_k2 = PIXEL_RATE_DIV_NA;
// Don't program 0xF into the register field. Not valid since
// K1 / K2 field is only 1 / 2 bits wide
......@@ -343,6 +344,7 @@ static const struct dccg_funcs dccg32_funcs = {
.otg_add_pixel = dccg32_otg_add_pixel,
.otg_drop_pixel = dccg32_otg_drop_pixel,
.set_pixel_rate_div = dccg32_set_pixel_rate_div,
.get_pixel_rate_div = dccg32_get_pixel_rate_div,
.trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync,
.set_dtbclk_p_src = dccg32_set_dtbclk_p_src,
};
......
......@@ -146,8 +146,8 @@ static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg,
static void dccg35_get_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
enum pixel_rate_div *k1,
enum pixel_rate_div *k2)
uint32_t *k1,
uint32_t *k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
......@@ -181,8 +181,8 @@ static void dccg35_get_pixel_rate_div(
return;
}
*k1 = (enum pixel_rate_div)val_k1;
*k2 = (enum pixel_rate_div)val_k2;
*k1 = val_k1;
*k2 = val_k2;
}
static void dccg35_set_pixel_rate_div(
......@@ -192,7 +192,9 @@ static void dccg35_set_pixel_rate_div(
enum pixel_rate_div k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
uint32_t cur_k2 = PIXEL_RATE_DIV_NA;
// Don't program 0xF into the register field. Not valid since
// K1 / K2 field is only 1 / 2 bits wide
......@@ -1018,6 +1020,7 @@ static const struct dccg_funcs dccg35_funcs = {
.disable_dsc = dccg35_disable_dscclk,
.enable_dsc = dccg35_enable_dscclk,
.set_pixel_rate_div = dccg35_set_pixel_rate_div,
.get_pixel_rate_div = dccg35_get_pixel_rate_div,
.trigger_dio_fifo_resync = dccg35_trigger_dio_fifo_resync,
.set_valid_pixel_rate = dccg35_set_valid_pixel_rate,
.enable_symclk_se = dccg35_enable_symclk_se,
......
......@@ -119,7 +119,7 @@ static void dccg401_wait_for_dentist_change_done(
static void dccg401_get_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
enum pixel_rate_div *tmds_div,
uint32_t *tmds_div,
uint32_t *dp_dto_int)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
......@@ -161,7 +161,7 @@ static void dccg401_set_pixel_rate_div(
enum pixel_rate_div unused)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
enum pixel_rate_div cur_tmds_div = PIXEL_RATE_DIV_NA;
uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
uint32_t dp_dto_int;
uint32_t reg_val;
......@@ -962,6 +962,7 @@ static const struct dccg_funcs dccg401_funcs = {
.otg_add_pixel = dccg401_otg_add_pixel,
.otg_drop_pixel = dccg401_otg_drop_pixel,
.set_pixel_rate_div = dccg401_set_pixel_rate_div,
.get_pixel_rate_div = dccg401_get_pixel_rate_div,
.set_dp_dto = dccg401_set_dp_dto,
.enable_symclk_se = dccg401_enable_symclk_se,
.disable_symclk_se = dccg401_disable_symclk_se,
......
......@@ -52,11 +52,11 @@
static void enc32_dp_set_odm_combine(
struct stream_encoder *enc,
bool odm_combine)
bool two_pixel_per_cyle)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, odm_combine ? 1 : 0);
REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, two_pixel_per_cyle ? 1 : 0);
}
/* setup stream encoder in dvi mode */
......@@ -241,46 +241,12 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
return two_pix;
}
static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
{
/* math borrowed from function of same name in inc/resource
* checks if h_timing is divisible by 2
*/
bool divisible = false;
uint16_t h_blank_start = 0;
uint16_t h_blank_end = 0;
if (timing) {
h_blank_start = timing->h_total - timing->h_front_porch;
h_blank_end = h_blank_start - timing->h_addressable;
/* HTOTAL, Hblank start/end, and Hsync start/end all must be
* divisible by 2 in order for the horizontal timing params
* to be considered divisible by 2. Hsync start is always 0.
*/
divisible = (timing->h_total % 2 == 0) &&
(h_blank_start % 2 == 0) &&
(h_blank_end % 2 == 0) &&
(timing->h_sync_width % 2 == 0);
}
return divisible;
}
static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
{
/* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
return is_h_timing_divisible_by_2(timing) &&
dc->debug.enable_dp_dig_pixel_rate_div_policy;
}
void enc32_stream_encoder_dp_unblank(
struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
struct dc *dc = enc->ctx->dc;
if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
uint32_t n_vid = 0x8000;
......@@ -291,7 +257,7 @@ void enc32_stream_encoder_dp_unblank(
/* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
|| is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
|| param->pix_per_cycle > 1) {
/*this logic should be the same in get_pixel_clock_parameters() */
n_multiply = 1;
pix_per_cycle = 1;
......
......@@ -273,46 +273,12 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
return two_pix;
}
static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
{
/* math borrowed from function of same name in inc/resource
* checks if h_timing is divisible by 2
*/
bool divisible = false;
uint16_t h_blank_start = 0;
uint16_t h_blank_end = 0;
if (timing) {
h_blank_start = timing->h_total - timing->h_front_porch;
h_blank_end = h_blank_start - timing->h_addressable;
/* HTOTAL, Hblank start/end, and Hsync start/end all must be
* divisible by 2 in order for the horizontal timing params
* to be considered divisible by 2. Hsync start is always 0.
*/
divisible = (timing->h_total % 2 == 0) &&
(h_blank_start % 2 == 0) &&
(h_blank_end % 2 == 0) &&
(timing->h_sync_width % 2 == 0);
}
return divisible;
}
static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
{
/* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
return is_h_timing_divisible_by_2(timing) &&
dc->debug.enable_dp_dig_pixel_rate_div_policy;
}
static void enc35_stream_encoder_dp_unblank(
struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
struct dc *dc = enc->ctx->dc;
if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
uint32_t n_vid = 0x8000;
......@@ -323,7 +289,7 @@ static void enc35_stream_encoder_dp_unblank(
/* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
|| is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
|| param->pix_per_cycle > 1) {
/*this logic should be the same in get_pixel_clock_parameters() */
n_multiply = 1;
pix_per_cycle = 1;
......
......@@ -1779,6 +1779,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
struct dc_stream_state *edp_streams[MAX_NUM_EDP];
struct dc_link *edp_link_with_sink = NULL;
struct dc_link *edp_link = NULL;
struct pipe_ctx *pipe_ctx = NULL;
struct dce_hwseq *hws = dc->hwseq;
int edp_with_sink_num;
int edp_num;
......@@ -1815,9 +1816,26 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
can_apply_edp_fast_boot = dc_validate_boot_timing(dc,
edp_stream->sink, &edp_stream->timing);
edp_stream->apply_edp_fast_boot_optimization = can_apply_edp_fast_boot;
if (can_apply_edp_fast_boot)
DC_LOG_EVENT_LINK_TRAINING("eDP fast boot disabled to optimize link rate\n");
if (can_apply_edp_fast_boot) {
DC_LOG_EVENT_LINK_TRAINING("eDP fast boot Enable\n");
// Vbios & Driver support different pixel rate div policy.
pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, edp_stream);
if (pipe_ctx &&
hws->funcs.is_dp_dig_pixel_rate_div_policy &&
hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
// Get Vbios div factor from register
dc->res_pool->dccg->funcs->get_pixel_rate_div(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
&pipe_ctx->pixel_rate_divider.div_factor1,
&pipe_ctx->pixel_rate_divider.div_factor2);
// VBios doesn't support pixel rate div, so force it.
// If VBios supports it, we check it from reigster or other flags.
pipe_ctx->stream_res.pix_clk_params.dio_se_pix_per_cycle = 1;
}
}
break;
}
}
......
......@@ -829,20 +829,17 @@ enum dc_status dcn20_enable_stream_timing(
bool is_two_pixels_per_container =
pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
bool rate_control_2x_pclk = (interlace || is_two_pixels_per_container);
unsigned int k1_div = PIXEL_RATE_DIV_NA;
unsigned int k2_div = PIXEL_RATE_DIV_NA;
int odm_slice_width;
int last_odm_slice_width;
struct pipe_ctx *opp_heads[MAX_PIPES];
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);
if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
dc->res_pool->dccg->funcs->set_pixel_rate_div(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
k1_div, k2_div);
}
pipe_ctx->pixel_rate_divider.div_factor1,
pipe_ctx->pixel_rate_divider.div_factor2);
/* 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.
......@@ -2685,6 +2682,7 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
params.opp_cnt = 1;
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
params.opp_cnt++;
}
......@@ -2940,9 +2938,7 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
struct dccg *dccg = dc->res_pool->dccg;
enum phyd32clk_clock_source phyd32clk;
int dp_hpo_inst;
struct dce_hwseq *hws = dc->hwseq;
unsigned int k1_div = PIXEL_RATE_DIV_NA;
unsigned int k2_div = PIXEL_RATE_DIV_NA;
struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);
struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
......@@ -2963,14 +2959,13 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
link_enc->transmitter - TRANSMITTER_UNIPHY_A);
}
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);
if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
dc->res_pool->dccg->funcs->set_pixel_rate_div(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
k1_div, k2_div);
}
pipe_ctx->pixel_rate_divider.div_factor1,
pipe_ctx->pixel_rate_divider.div_factor2);
link_hwss->setup_stream_encoder(pipe_ctx);
......
......@@ -334,6 +334,27 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig
return odm_combine_factor;
}
void dcn314_calculate_pix_rate_divider(
struct dc *dc,
struct dc_state *context,
const struct dc_stream_state *stream)
{
struct dce_hwseq *hws = dc->hwseq;
struct pipe_ctx *pipe_ctx = NULL;
unsigned int k1_div = PIXEL_RATE_DIV_NA;
unsigned int k2_div = PIXEL_RATE_DIV_NA;
pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (pipe_ctx) {
if (hws->funcs.calculate_dccg_k1_k2_values)
hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
pipe_ctx->pixel_rate_divider.div_factor1 = k1_div;
pipe_ctx->pixel_rate_divider.div_factor2 = k2_div;
}
}
void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context)
{
unsigned int i;
......
......@@ -39,6 +39,8 @@ void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable);
unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div);
void dcn314_calculate_pix_rate_divider(struct dc *dc, struct dc_state *context, const struct dc_stream_state *stream);
void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context);
void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on);
......
......@@ -114,6 +114,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
.optimize_pwr_state = dcn21_optimize_pwr_state,
.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
.update_visual_confirm_color = dcn10_update_visual_confirm_color,
.calculate_pix_rate_divider = dcn314_calculate_pix_rate_divider,
};
static const struct hwseq_private_funcs dcn314_private_funcs = {
......
......@@ -1164,6 +1164,28 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
return odm_combine_factor;
}
void dcn32_calculate_pix_rate_divider(
struct dc *dc,
struct dc_state *context,
const struct dc_stream_state *stream)
{
struct dce_hwseq *hws = dc->hwseq;
struct pipe_ctx *pipe_ctx = NULL;
unsigned int k1_div = PIXEL_RATE_DIV_NA;
unsigned int k2_div = PIXEL_RATE_DIV_NA;
pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (pipe_ctx) {
if (hws->funcs.calculate_dccg_k1_k2_values)
hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
pipe_ctx->pixel_rate_divider.div_factor1 = k1_div;
pipe_ctx->pixel_rate_divider.div_factor2 = k2_div;
}
}
void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context)
{
unsigned int i;
......@@ -1202,9 +1224,10 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link *link = stream->link;
struct dce_hwseq *hws = link->dc->hwseq;
struct pipe_ctx *odm_pipe;
uint32_t pix_per_cycle = 1;
params.opp_cnt = 1;
params.pix_per_cycle = pipe_ctx->stream_res.pix_clk_params.dio_se_pix_per_cycle;
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
params.opp_cnt++;
......@@ -1219,13 +1242,13 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
pipe_ctx->stream_res.hpo_dp_stream_enc,
pipe_ctx->stream_res.tg->inst);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing) || params.opp_cnt > 1
|| dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing) ||
params.opp_cnt > 1) {
params.timing.pix_clk_100hz /= 2;
pix_per_cycle = 2;
params.pix_per_cycle = 2;
}
pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
pipe_ctx->stream_res.stream_enc, pix_per_cycle > 1);
pipe_ctx->stream_res.stream_enc, params.pix_per_cycle > 1);
pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, &params);
}
......
......@@ -91,6 +91,8 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
void dcn32_calculate_pix_rate_divider(struct dc *dc, struct dc_state *context, const struct dc_stream_state *stream);
void dcn32_disable_link_output(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal);
......
......@@ -119,6 +119,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
.blank_phantom = dcn32_blank_phantom,
.is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
.calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
};
static const struct hwseq_private_funcs dcn32_private_funcs = {
......
......@@ -123,6 +123,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
.hw_block_power_down = dcn35_hw_block_power_down,
.root_clock_control = dcn35_root_clock_control,
.set_long_vtotal = dcn35_set_long_vblank,
.calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
};
static const struct hwseq_private_funcs dcn35_private_funcs = {
......
......@@ -122,6 +122,7 @@ static const struct hw_sequencer_funcs dcn351_funcs = {
.hw_block_power_down = dcn351_hw_block_power_down,
.root_clock_control = dcn35_root_clock_control,
.set_long_vtotal = dcn35_set_long_vblank,
.calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
};
static const struct hwseq_private_funcs dcn351_private_funcs = {
......
......@@ -339,6 +339,9 @@ struct hw_sequencer_funcs {
struct dc_state *context);
void (*exit_optimized_pwr_state)(const struct dc *dc,
struct dc_state *context);
void (*calculate_pix_rate_divider)(struct dc *dc,
struct dc_state *context,
const struct dc_stream_state *stream);
/* Audio Related */
void (*enable_audio_stream)(struct pipe_ctx *pipe_ctx);
......
......@@ -399,6 +399,11 @@ union pipe_update_flags {
uint32_t raw;
};
struct pixel_rate_divider {
uint32_t div_factor1;
uint32_t div_factor2;
};
enum p_state_switch_method {
P_STATE_UNKNOWN = 0,
P_STATE_V_BLANK = 1,
......@@ -464,6 +469,7 @@ struct pipe_ctx {
bool has_vactive_margin;
/* subvp_index: only valid if the pipe is a SUBVP_MAIN*/
uint8_t subvp_index;
struct pixel_rate_divider pixel_rate_divider;
};
/* Data used for dynamic link encoder assignment.
......
......@@ -176,6 +176,11 @@ struct dccg_funcs {
enum pixel_rate_div k1,
enum pixel_rate_div k2);
void (*get_pixel_rate_div)(struct dccg *dccg,
uint32_t otg_inst,
uint32_t *div_factor1,
uint32_t *div_factor2);
void (*set_valid_pixel_rate)(
struct dccg *dccg,
int ref_dtbclk_khz,
......
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