mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-09-01 16:21:30 +00:00
drm/amd/display: DML2.1 Post-Si Cleanup
[Why] There are a few cleanup and refactoring tasks that need to be done with the DML2.1 wrapper and DC interface to remove dependencies on legacy structures and N-1 prototypes. [How] Implemented pipe_ctx->global_sync. Implemented new functions to use pipe_ctx->hubp_regs and pipe_ctx->global_sync: - hubp_setup2 - hubp_setup_interdependent2 - Several other new functions for DCN 4.01 to support newer structures Removed dml21_update_pipe_ctx_dchub_regs Removed dml21_extract_legacy_watermark_set Removed dml21_populate_pipe_ctx_dlg_param Removed outdated dcn references in DML2.1 wrapper. Reviewed-by: Austin Zheng <austin.zheng@amd.com> Reviewed-by: Dillon Varone <dillon.varone@amd.com> Signed-off-by: Rafal Ostrowski <rostrows@amd.com> Signed-off-by: Tom Chung <chiahsuan.chung@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
00d53a0d8a
commit
63ab80d9ac
@ -4478,7 +4478,7 @@ static void set_hfvs_info_packet(
|
||||
static void adaptive_sync_override_dp_info_packets_sdp_line_num(
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct enc_sdp_line_num *sdp_line_num,
|
||||
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
|
||||
unsigned int vstartup_start)
|
||||
{
|
||||
uint32_t asic_blank_start = 0;
|
||||
uint32_t asic_blank_end = 0;
|
||||
@ -4493,8 +4493,8 @@ static void adaptive_sync_override_dp_info_packets_sdp_line_num(
|
||||
asic_blank_end = (asic_blank_start - tg->v_border_bottom -
|
||||
tg->v_addressable - tg->v_border_top);
|
||||
|
||||
if (pipe_dlg_param->vstartup_start > asic_blank_end) {
|
||||
v_update = (tg->v_total - (pipe_dlg_param->vstartup_start - asic_blank_end));
|
||||
if (vstartup_start > asic_blank_end) {
|
||||
v_update = (tg->v_total - (vstartup_start - asic_blank_end));
|
||||
sdp_line_num->adaptive_sync_line_num_valid = true;
|
||||
sdp_line_num->adaptive_sync_line_num = (tg->v_total - v_update - 1);
|
||||
} else {
|
||||
@ -4507,7 +4507,7 @@ static void set_adaptive_sync_info_packet(
|
||||
struct dc_info_packet *info_packet,
|
||||
const struct dc_stream_state *stream,
|
||||
struct encoder_info_frame *info_frame,
|
||||
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
|
||||
unsigned int vstartup_start)
|
||||
{
|
||||
if (!stream->adaptive_sync_infopacket.valid)
|
||||
return;
|
||||
@ -4515,7 +4515,7 @@ static void set_adaptive_sync_info_packet(
|
||||
adaptive_sync_override_dp_info_packets_sdp_line_num(
|
||||
&stream->timing,
|
||||
&info_frame->sdp_line_num,
|
||||
pipe_dlg_param);
|
||||
vstartup_start);
|
||||
|
||||
*info_packet = stream->adaptive_sync_infopacket;
|
||||
}
|
||||
@ -4548,6 +4548,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
enum signal_type signal = SIGNAL_TYPE_NONE;
|
||||
struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame;
|
||||
unsigned int vstartup_start = 0;
|
||||
|
||||
/* default all packets to invalid */
|
||||
info->avi.valid = false;
|
||||
@ -4561,6 +4562,9 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
|
||||
info->adaptive_sync.valid = false;
|
||||
signal = pipe_ctx->stream->signal;
|
||||
|
||||
if (pipe_ctx->stream->ctx->dc->res_pool->funcs->get_vstartup_for_pipe)
|
||||
vstartup_start = pipe_ctx->stream->ctx->dc->res_pool->funcs->get_vstartup_for_pipe(pipe_ctx);
|
||||
|
||||
/* HDMi and DP have different info packets*/
|
||||
if (dc_is_hdmi_signal(signal)) {
|
||||
set_avi_info_frame(&info->avi, pipe_ctx);
|
||||
@ -4582,7 +4586,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
|
||||
set_adaptive_sync_info_packet(&info->adaptive_sync,
|
||||
pipe_ctx->stream,
|
||||
info,
|
||||
&pipe_ctx->pipe_dlg_param);
|
||||
vstartup_start);
|
||||
}
|
||||
|
||||
patch_gamut_packet_checksum(&info->gamut);
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "dml21_utils.h"
|
||||
#include "dml21_translation_helper.h"
|
||||
#include "bounding_boxes/dcn4_soc_bb.h"
|
||||
#include "bounding_boxes/dcn3_soc_bb.h"
|
||||
|
||||
static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_init,
|
||||
const struct dml2_configuration_options *config,
|
||||
@ -20,10 +19,6 @@ static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_
|
||||
const struct dml2_soc_qos_parameters *qos_params;
|
||||
|
||||
switch (in_dc->ctx->dce_version) {
|
||||
case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
|
||||
soc_bb = &dml2_socbb_dcn31;
|
||||
qos_params = &dml_dcn31_soc_qos_params;
|
||||
break;
|
||||
case DCN_VERSION_4_01:
|
||||
default:
|
||||
if (config->bb_from_dmub)
|
||||
@ -60,9 +55,6 @@ static void dml21_init_ip_params(struct dml2_initialize_instance_in_out *dml_ini
|
||||
const struct dml2_ip_capabilities *ip_caps;
|
||||
|
||||
switch (in_dc->ctx->dce_version) {
|
||||
case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
|
||||
ip_caps = &dml2_dcn31_max_ip_caps;
|
||||
break;
|
||||
case DCN_VERSION_4_01:
|
||||
default:
|
||||
ip_caps = &dml2_dcn401_max_ip_caps;
|
||||
@ -1091,28 +1083,6 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state
|
||||
context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
|
||||
}
|
||||
|
||||
void dml21_extract_legacy_watermark_set(const struct dc *in_dc, struct dcn_watermarks *watermark, enum dml2_dchub_watermark_reg_set_index reg_set_idx, struct dml2_context *in_ctx)
|
||||
{
|
||||
struct dml2_core_internal_display_mode_lib *mode_lib = &in_ctx->v21.dml_init.dml2_instance->core_instance.clean_me_up.mode_lib;
|
||||
double refclk_freq_in_mhz = (in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz > 0) ? (double)in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
|
||||
|
||||
if (reg_set_idx >= DML2_DCHUB_WATERMARK_SET_NUM) {
|
||||
/* invalid register set index */
|
||||
return;
|
||||
}
|
||||
|
||||
/* convert to legacy format (time in ns) */
|
||||
watermark->urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
|
||||
watermark->pte_meta_urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
|
||||
watermark->cstate_pstate.cstate_enter_plus_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_enter / refclk_freq_in_mhz) * 1000.0;
|
||||
watermark->cstate_pstate.cstate_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_exit / refclk_freq_in_mhz) * 1000.0;
|
||||
watermark->cstate_pstate.pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].uclk_pstate / refclk_freq_in_mhz) * 1000.0;
|
||||
watermark->urgent_latency_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
|
||||
watermark->cstate_pstate.fclk_pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].fclk_pstate / refclk_freq_in_mhz) * 1000.0;
|
||||
watermark->frac_urg_bw_flip = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_flip;
|
||||
watermark->frac_urg_bw_nom = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_nom;
|
||||
}
|
||||
|
||||
static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
|
||||
{
|
||||
struct dml2_dchub_watermark_regs *wm_regs = NULL;
|
||||
@ -1156,53 +1126,6 @@ void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_se
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming)
|
||||
{
|
||||
unsigned int hactive, vactive, hblank_start, vblank_start, hblank_end, vblank_end;
|
||||
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
|
||||
union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
|
||||
|
||||
hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right + pipe_ctx->hblank_borrow;
|
||||
vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
|
||||
hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
|
||||
vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;
|
||||
|
||||
hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right - pipe_ctx->hblank_borrow;
|
||||
vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
|
||||
|
||||
if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
|
||||
/* phantom has its own global sync */
|
||||
global_sync = &stream_programming->phantom_stream.global_sync;
|
||||
}
|
||||
|
||||
pipe_ctx->pipe_dlg_param.vstartup_start = global_sync->dcn4x.vstartup_lines;
|
||||
pipe_ctx->pipe_dlg_param.vupdate_offset = global_sync->dcn4x.vupdate_offset_pixels;
|
||||
pipe_ctx->pipe_dlg_param.vupdate_width = global_sync->dcn4x.vupdate_vupdate_width_pixels;
|
||||
pipe_ctx->pipe_dlg_param.vready_offset = global_sync->dcn4x.vready_offset_pixels;
|
||||
pipe_ctx->pipe_dlg_param.pstate_keepout = global_sync->dcn4x.pstate_keepout_start_lines;
|
||||
|
||||
pipe_ctx->pipe_dlg_param.otg_inst = pipe_ctx->stream_res.tg->inst;
|
||||
|
||||
pipe_ctx->pipe_dlg_param.hactive = hactive;
|
||||
pipe_ctx->pipe_dlg_param.vactive = vactive;
|
||||
pipe_ctx->pipe_dlg_param.htotal = pipe_ctx->stream->timing.h_total;
|
||||
pipe_ctx->pipe_dlg_param.vtotal = pipe_ctx->stream->timing.v_total;
|
||||
pipe_ctx->pipe_dlg_param.hblank_end = hblank_end;
|
||||
pipe_ctx->pipe_dlg_param.vblank_end = vblank_end;
|
||||
pipe_ctx->pipe_dlg_param.hblank_start = hblank_start;
|
||||
pipe_ctx->pipe_dlg_param.vblank_start = vblank_start;
|
||||
pipe_ctx->pipe_dlg_param.vfront_porch = pipe_ctx->stream->timing.v_front_porch;
|
||||
pipe_ctx->pipe_dlg_param.pixel_rate_mhz = pipe_ctx->stream->timing.pix_clk_100hz / 10000.00;
|
||||
pipe_ctx->pipe_dlg_param.refresh_rate = ((timing->pix_clk_100hz * 100) / timing->h_total) / timing->v_total;
|
||||
pipe_ctx->pipe_dlg_param.vtotal_max = pipe_ctx->stream->adjust.v_total_max;
|
||||
pipe_ctx->pipe_dlg_param.vtotal_min = pipe_ctx->stream->adjust.v_total_min;
|
||||
pipe_ctx->pipe_dlg_param.recout_height = pipe_ctx->plane_res.scl_data.recout.height;
|
||||
pipe_ctx->pipe_dlg_param.recout_width = pipe_ctx->plane_res.scl_data.recout.width;
|
||||
pipe_ctx->pipe_dlg_param.full_recout_height = pipe_ctx->plane_res.scl_data.recout.height;
|
||||
pipe_ctx->pipe_dlg_param.full_recout_width = pipe_ctx->plane_res.scl_data.recout.width;
|
||||
}
|
||||
|
||||
void dml21_map_hw_resources(struct dml2_context *dml_ctx)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
@ -21,8 +21,6 @@ void dml21_initialize_soc_bb_params(struct dml2_initialize_instance_in_out *dml_
|
||||
void dml21_initialize_ip_params(struct dml2_initialize_instance_in_out *dml_init, const struct dml2_configuration_options *config, const struct dc *in_dc);
|
||||
bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
|
||||
void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state *context);
|
||||
void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming);
|
||||
void dml21_extract_legacy_watermark_set(const struct dc *in_dc, struct dcn_watermarks *watermark, enum dml2_dchub_watermark_reg_set_index reg_set_idx, struct dml2_context *in_ctx);
|
||||
void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_set *watermarks, struct dml2_context *in_ctx);
|
||||
void dml21_map_hw_resources(struct dml2_context *dml_ctx);
|
||||
void dml21_get_pipe_mcache_config(struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_plane_programming *pln_prog, struct dml2_pipe_configuration_descriptor *mcache_pipe_config);
|
||||
|
@ -142,108 +142,21 @@ int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,
|
||||
return num_pipes;
|
||||
}
|
||||
|
||||
|
||||
void dml21_update_pipe_ctx_dchub_regs(struct dml2_display_rq_regs *rq_regs,
|
||||
struct dml2_display_dlg_regs *disp_dlg_regs,
|
||||
struct dml2_display_ttu_regs *disp_ttu_regs,
|
||||
struct pipe_ctx *out)
|
||||
void dml21_pipe_populate_global_sync(struct dml2_context *dml_ctx,
|
||||
struct dc_state *context,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dml2_per_stream_programming *stream_programming)
|
||||
{
|
||||
memset(&out->rq_regs, 0, sizeof(out->rq_regs));
|
||||
out->rq_regs.rq_regs_l.chunk_size = rq_regs->rq_regs_l.chunk_size;
|
||||
out->rq_regs.rq_regs_l.min_chunk_size = rq_regs->rq_regs_l.min_chunk_size;
|
||||
//out->rq_regs.rq_regs_l.meta_chunk_size = rq_regs->rq_regs_l.meta_chunk_size;
|
||||
//out->rq_regs.rq_regs_l.min_meta_chunk_size = rq_regs->rq_regs_l.min_meta_chunk_size;
|
||||
out->rq_regs.rq_regs_l.dpte_group_size = rq_regs->rq_regs_l.dpte_group_size;
|
||||
out->rq_regs.rq_regs_l.mpte_group_size = rq_regs->rq_regs_l.mpte_group_size;
|
||||
out->rq_regs.rq_regs_l.swath_height = rq_regs->rq_regs_l.swath_height;
|
||||
out->rq_regs.rq_regs_l.pte_row_height_linear = rq_regs->rq_regs_l.pte_row_height_linear;
|
||||
union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
|
||||
|
||||
out->rq_regs.rq_regs_c.chunk_size = rq_regs->rq_regs_c.chunk_size;
|
||||
out->rq_regs.rq_regs_c.min_chunk_size = rq_regs->rq_regs_c.min_chunk_size;
|
||||
//out->rq_regs.rq_regs_c.meta_chunk_size = rq_regs->rq_regs_c.meta_chunk_size;
|
||||
//out->rq_regs.rq_regs_c.min_meta_chunk_size = rq_regs->rq_regs_c.min_meta_chunk_size;
|
||||
out->rq_regs.rq_regs_c.dpte_group_size = rq_regs->rq_regs_c.dpte_group_size;
|
||||
out->rq_regs.rq_regs_c.mpte_group_size = rq_regs->rq_regs_c.mpte_group_size;
|
||||
out->rq_regs.rq_regs_c.swath_height = rq_regs->rq_regs_c.swath_height;
|
||||
out->rq_regs.rq_regs_c.pte_row_height_linear = rq_regs->rq_regs_c.pte_row_height_linear;
|
||||
if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
|
||||
/* phantom has its own global sync */
|
||||
global_sync = &stream_programming->phantom_stream.global_sync;
|
||||
}
|
||||
|
||||
out->rq_regs.drq_expansion_mode = rq_regs->drq_expansion_mode;
|
||||
out->rq_regs.prq_expansion_mode = rq_regs->prq_expansion_mode;
|
||||
//out->rq_regs.mrq_expansion_mode = rq_regs->mrq_expansion_mode;
|
||||
out->rq_regs.crq_expansion_mode = rq_regs->crq_expansion_mode;
|
||||
out->rq_regs.plane1_base_address = rq_regs->plane1_base_address;
|
||||
out->unbounded_req = rq_regs->unbounded_request_enabled;
|
||||
|
||||
memset(&out->dlg_regs, 0, sizeof(out->dlg_regs));
|
||||
out->dlg_regs.refcyc_h_blank_end = disp_dlg_regs->refcyc_h_blank_end;
|
||||
out->dlg_regs.dlg_vblank_end = disp_dlg_regs->dlg_vblank_end;
|
||||
out->dlg_regs.min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start;
|
||||
out->dlg_regs.refcyc_per_htotal = disp_dlg_regs->refcyc_per_htotal;
|
||||
out->dlg_regs.refcyc_x_after_scaler = disp_dlg_regs->refcyc_x_after_scaler;
|
||||
out->dlg_regs.dst_y_after_scaler = disp_dlg_regs->dst_y_after_scaler;
|
||||
out->dlg_regs.dst_y_prefetch = disp_dlg_regs->dst_y_prefetch;
|
||||
out->dlg_regs.dst_y_per_vm_vblank = disp_dlg_regs->dst_y_per_vm_vblank;
|
||||
out->dlg_regs.dst_y_per_row_vblank = disp_dlg_regs->dst_y_per_row_vblank;
|
||||
out->dlg_regs.dst_y_per_vm_flip = disp_dlg_regs->dst_y_per_vm_flip;
|
||||
out->dlg_regs.dst_y_per_row_flip = disp_dlg_regs->dst_y_per_row_flip;
|
||||
out->dlg_regs.ref_freq_to_pix_freq = disp_dlg_regs->ref_freq_to_pix_freq;
|
||||
out->dlg_regs.vratio_prefetch = disp_dlg_regs->vratio_prefetch;
|
||||
out->dlg_regs.vratio_prefetch_c = disp_dlg_regs->vratio_prefetch_c;
|
||||
out->dlg_regs.refcyc_per_tdlut_group = disp_dlg_regs->refcyc_per_tdlut_group;
|
||||
out->dlg_regs.refcyc_per_pte_group_vblank_l = disp_dlg_regs->refcyc_per_pte_group_vblank_l;
|
||||
out->dlg_regs.refcyc_per_pte_group_vblank_c = disp_dlg_regs->refcyc_per_pte_group_vblank_c;
|
||||
//out->dlg_regs.refcyc_per_meta_chunk_vblank_l = disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;
|
||||
//out->dlg_regs.refcyc_per_meta_chunk_vblank_c = disp_dlg_regs->refcyc_per_meta_chunk_vblank_c;
|
||||
out->dlg_regs.refcyc_per_pte_group_flip_l = disp_dlg_regs->refcyc_per_pte_group_flip_l;
|
||||
out->dlg_regs.refcyc_per_pte_group_flip_c = disp_dlg_regs->refcyc_per_pte_group_flip_c;
|
||||
//out->dlg_regs.refcyc_per_meta_chunk_flip_l = disp_dlg_regs->refcyc_per_meta_chunk_flip_l;
|
||||
//out->dlg_regs.refcyc_per_meta_chunk_flip_c = disp_dlg_regs->refcyc_per_meta_chunk_flip_c;
|
||||
out->dlg_regs.dst_y_per_pte_row_nom_l = disp_dlg_regs->dst_y_per_pte_row_nom_l;
|
||||
out->dlg_regs.dst_y_per_pte_row_nom_c = disp_dlg_regs->dst_y_per_pte_row_nom_c;
|
||||
out->dlg_regs.refcyc_per_pte_group_nom_l = disp_dlg_regs->refcyc_per_pte_group_nom_l;
|
||||
out->dlg_regs.refcyc_per_pte_group_nom_c = disp_dlg_regs->refcyc_per_pte_group_nom_c;
|
||||
//out->dlg_regs.dst_y_per_meta_row_nom_l = disp_dlg_regs->dst_y_per_meta_row_nom_l;
|
||||
//out->dlg_regs.dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_c;
|
||||
//out->dlg_regs.refcyc_per_meta_chunk_nom_l = disp_dlg_regs->refcyc_per_meta_chunk_nom_l;
|
||||
//out->dlg_regs.refcyc_per_meta_chunk_nom_c = disp_dlg_regs->refcyc_per_meta_chunk_nom_c;
|
||||
out->dlg_regs.refcyc_per_line_delivery_pre_l = disp_dlg_regs->refcyc_per_line_delivery_pre_l;
|
||||
out->dlg_regs.refcyc_per_line_delivery_pre_c = disp_dlg_regs->refcyc_per_line_delivery_pre_c;
|
||||
out->dlg_regs.refcyc_per_line_delivery_l = disp_dlg_regs->refcyc_per_line_delivery_l;
|
||||
out->dlg_regs.refcyc_per_line_delivery_c = disp_dlg_regs->refcyc_per_line_delivery_c;
|
||||
out->dlg_regs.refcyc_per_vm_group_vblank = disp_dlg_regs->refcyc_per_vm_group_vblank;
|
||||
out->dlg_regs.refcyc_per_vm_group_flip = disp_dlg_regs->refcyc_per_vm_group_flip;
|
||||
out->dlg_regs.refcyc_per_vm_req_vblank = disp_dlg_regs->refcyc_per_vm_req_vblank;
|
||||
out->dlg_regs.refcyc_per_vm_req_flip = disp_dlg_regs->refcyc_per_vm_req_flip;
|
||||
out->dlg_regs.dst_y_offset_cur0 = disp_dlg_regs->dst_y_offset_cur0;
|
||||
out->dlg_regs.chunk_hdl_adjust_cur0 = disp_dlg_regs->chunk_hdl_adjust_cur0;
|
||||
//out->dlg_regs.dst_y_offset_cur1 = disp_dlg_regs->dst_y_offset_cur1;
|
||||
//out->dlg_regs.chunk_hdl_adjust_cur1 = disp_dlg_regs->chunk_hdl_adjust_cur1;
|
||||
out->dlg_regs.vready_after_vcount0 = disp_dlg_regs->vready_after_vcount0;
|
||||
out->dlg_regs.dst_y_delta_drq_limit = disp_dlg_regs->dst_y_delta_drq_limit;
|
||||
out->dlg_regs.refcyc_per_vm_dmdata = disp_dlg_regs->refcyc_per_vm_dmdata;
|
||||
out->dlg_regs.dmdata_dl_delta = disp_dlg_regs->dmdata_dl_delta;
|
||||
|
||||
memset(&out->ttu_regs, 0, sizeof(out->ttu_regs));
|
||||
out->ttu_regs.qos_level_low_wm = disp_ttu_regs->qos_level_low_wm;
|
||||
out->ttu_regs.qos_level_high_wm = disp_ttu_regs->qos_level_high_wm;
|
||||
out->ttu_regs.min_ttu_vblank = disp_ttu_regs->min_ttu_vblank;
|
||||
out->ttu_regs.qos_level_flip = disp_ttu_regs->qos_level_flip;
|
||||
out->ttu_regs.refcyc_per_req_delivery_l = disp_ttu_regs->refcyc_per_req_delivery_l;
|
||||
out->ttu_regs.refcyc_per_req_delivery_c = disp_ttu_regs->refcyc_per_req_delivery_c;
|
||||
out->ttu_regs.refcyc_per_req_delivery_cur0 = disp_ttu_regs->refcyc_per_req_delivery_cur0;
|
||||
//out->ttu_regs.refcyc_per_req_delivery_cur1 = disp_ttu_regs->refcyc_per_req_delivery_cur1;
|
||||
out->ttu_regs.refcyc_per_req_delivery_pre_l = disp_ttu_regs->refcyc_per_req_delivery_pre_l;
|
||||
out->ttu_regs.refcyc_per_req_delivery_pre_c = disp_ttu_regs->refcyc_per_req_delivery_pre_c;
|
||||
out->ttu_regs.refcyc_per_req_delivery_pre_cur0 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur0;
|
||||
//out->ttu_regs.refcyc_per_req_delivery_pre_cur1 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur1;
|
||||
out->ttu_regs.qos_level_fixed_l = disp_ttu_regs->qos_level_fixed_l;
|
||||
out->ttu_regs.qos_level_fixed_c = disp_ttu_regs->qos_level_fixed_c;
|
||||
out->ttu_regs.qos_level_fixed_cur0 = disp_ttu_regs->qos_level_fixed_cur0;
|
||||
//out->ttu_regs.qos_level_fixed_cur1 = disp_ttu_regs->qos_level_fixed_cur1;
|
||||
out->ttu_regs.qos_ramp_disable_l = disp_ttu_regs->qos_ramp_disable_l;
|
||||
out->ttu_regs.qos_ramp_disable_c = disp_ttu_regs->qos_ramp_disable_c;
|
||||
out->ttu_regs.qos_ramp_disable_cur0 = disp_ttu_regs->qos_ramp_disable_cur0;
|
||||
//out->ttu_regs.qos_ramp_disable_cur1 = disp_ttu_regs->qos_ramp_disable_cur1;
|
||||
memcpy(&pipe_ctx->global_sync,
|
||||
global_sync,
|
||||
sizeof(union dml2_global_sync_programming));
|
||||
}
|
||||
|
||||
void dml21_populate_mall_allocation_size(struct dc_state *context,
|
||||
@ -301,28 +214,16 @@ void dml21_program_dc_pipe(struct dml2_context *dml_ctx, struct dc_state *contex
|
||||
{
|
||||
unsigned int pipe_reg_index = 0;
|
||||
|
||||
dml21_populate_pipe_ctx_dlg_params(dml_ctx, context, pipe_ctx, stream_prog);
|
||||
dml21_pipe_populate_global_sync(dml_ctx, context, pipe_ctx, stream_prog);
|
||||
find_pipe_regs_idx(dml_ctx, pipe_ctx, &pipe_reg_index);
|
||||
|
||||
if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
|
||||
memcpy(&pipe_ctx->hubp_regs, pln_prog->phantom_plane.pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));
|
||||
pipe_ctx->unbounded_req = false;
|
||||
|
||||
/* legacy only, should be removed later */
|
||||
dml21_update_pipe_ctx_dchub_regs(&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->rq_regs,
|
||||
&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->dlg_regs,
|
||||
&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx);
|
||||
|
||||
pipe_ctx->det_buffer_size_kb = 0;
|
||||
} else {
|
||||
memcpy(&pipe_ctx->hubp_regs, pln_prog->pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));
|
||||
pipe_ctx->unbounded_req = pln_prog->pipe_regs[pipe_reg_index]->rq_regs.unbounded_request_enabled;
|
||||
|
||||
/* legacy only, should be removed later */
|
||||
dml21_update_pipe_ctx_dchub_regs(&pln_prog->pipe_regs[pipe_reg_index]->rq_regs,
|
||||
&pln_prog->pipe_regs[pipe_reg_index]->dlg_regs,
|
||||
&pln_prog->pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx);
|
||||
|
||||
pipe_ctx->det_buffer_size_kb = pln_prog->pipe_regs[pipe_reg_index]->det_size * 64;
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,10 @@ struct dml2_display_ttu_regs;
|
||||
int dml21_helper_find_dml_pipe_idx_by_stream_id(struct dml2_context *ctx, unsigned int stream_id);
|
||||
int dml21_find_dml_pipe_idx_by_plane_id(struct dml2_context *ctx, unsigned int plane_id);
|
||||
bool dml21_get_plane_id(const struct dc_state *state, const struct dc_plane_state *plane, unsigned int *plane_id);
|
||||
void dml21_update_pipe_ctx_dchub_regs(struct dml2_display_rq_regs *rq_regs,
|
||||
struct dml2_display_dlg_regs *disp_dlg_regs,
|
||||
struct dml2_display_ttu_regs *disp_ttu_regs,
|
||||
struct pipe_ctx *out);
|
||||
void dml21_pipe_populate_global_sync(struct dml2_context *dml_ctx,
|
||||
struct dc_state *context,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dml2_per_stream_programming *stream_programming);
|
||||
void dml21_populate_mall_allocation_size(struct dc_state *context,
|
||||
struct dml2_context *in_ctx,
|
||||
struct dml2_per_plane_programming *pln_prog,
|
||||
|
@ -75,7 +75,6 @@ static void dml21_init(const struct dc *in_dc, struct dml2_context **dml_ctx, co
|
||||
{
|
||||
switch (in_dc->ctx->dce_version) {
|
||||
case DCN_VERSION_4_01:
|
||||
case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
|
||||
(*dml_ctx)->v21.dml_init.options.project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
|
||||
break;
|
||||
default:
|
||||
@ -233,13 +232,6 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s
|
||||
dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
|
||||
dml21_copy_clocks_to_dc_state(dml_ctx, context);
|
||||
dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
|
||||
if (in_dc->ctx->dce_version == DCN_VERSION_3_2) {
|
||||
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.a, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
|
||||
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.b, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
|
||||
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.c, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
|
||||
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.d, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
|
||||
}
|
||||
|
||||
dml21_build_fams2_programming(in_dc, context, dml_ctx);
|
||||
}
|
||||
|
||||
|
@ -1,401 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DML_DML_DCN3_SOC_BB__
|
||||
#define __DML_DML_DCN3_SOC_BB__
|
||||
|
||||
#include "dml_top_soc_parameter_types.h"
|
||||
|
||||
static const struct dml2_soc_qos_parameters dml_dcn31_soc_qos_params = {
|
||||
.derate_table = {
|
||||
.system_active_urgent = {
|
||||
.dram_derate_percent_pixel = 22,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 76,
|
||||
.dcfclk_derate_percent = 100,
|
||||
},
|
||||
.system_active_average = {
|
||||
.dram_derate_percent_pixel = 17,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 57,
|
||||
.dcfclk_derate_percent = 75,
|
||||
},
|
||||
.dcn_mall_prefetch_urgent = {
|
||||
.dram_derate_percent_pixel = 22,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 76,
|
||||
.dcfclk_derate_percent = 100,
|
||||
},
|
||||
.dcn_mall_prefetch_average = {
|
||||
.dram_derate_percent_pixel = 17,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 57,
|
||||
.dcfclk_derate_percent = 75,
|
||||
},
|
||||
.system_idle_average = {
|
||||
.dram_derate_percent_pixel = 17,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 57,
|
||||
.dcfclk_derate_percent = 100,
|
||||
},
|
||||
},
|
||||
.writeback = {
|
||||
.base_latency_us = 12,
|
||||
.scaling_factor_us = 0,
|
||||
.scaling_factor_mhz = 0,
|
||||
},
|
||||
.qos_params = {
|
||||
.dcn4x = {
|
||||
.df_qos_response_time_fclk_cycles = 300,
|
||||
.max_round_trip_to_furthest_cs_fclk_cycles = 350,
|
||||
.mall_overhead_fclk_cycles = 50,
|
||||
.meta_trip_adder_fclk_cycles = 36,
|
||||
.average_transport_distance_fclk_cycles = 257,
|
||||
.umc_urgent_ramp_latency_margin = 50,
|
||||
.umc_max_latency_margin = 30,
|
||||
.umc_average_latency_margin = 20,
|
||||
.fabric_max_transport_latency_margin = 20,
|
||||
.fabric_average_transport_latency_margin = 10,
|
||||
|
||||
.per_uclk_dpm_params = {
|
||||
{
|
||||
.minimum_uclk_khz = 97,
|
||||
.urgent_ramp_uclk_cycles = 472,
|
||||
.trip_to_memory_uclk_cycles = 827,
|
||||
.meta_trip_to_memory_uclk_cycles = 827,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 72,
|
||||
.average_latency_when_urgent_uclk_cycles = 61,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 827,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 118,
|
||||
},
|
||||
{
|
||||
.minimum_uclk_khz = 435,
|
||||
.urgent_ramp_uclk_cycles = 546,
|
||||
.trip_to_memory_uclk_cycles = 848,
|
||||
.meta_trip_to_memory_uclk_cycles = 848,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 146,
|
||||
.average_latency_when_urgent_uclk_cycles = 90,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 848,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 135,
|
||||
},
|
||||
{
|
||||
.minimum_uclk_khz = 731,
|
||||
.urgent_ramp_uclk_cycles = 632,
|
||||
.trip_to_memory_uclk_cycles = 874,
|
||||
.meta_trip_to_memory_uclk_cycles = 874,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 232,
|
||||
.average_latency_when_urgent_uclk_cycles = 124,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 874,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 155,
|
||||
},
|
||||
{
|
||||
.minimum_uclk_khz = 1187,
|
||||
.urgent_ramp_uclk_cycles = 716,
|
||||
.trip_to_memory_uclk_cycles = 902,
|
||||
.meta_trip_to_memory_uclk_cycles = 902,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 316,
|
||||
.average_latency_when_urgent_uclk_cycles = 160,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 902,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 177,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
.qos_type = dml2_qos_param_type_dcn4x,
|
||||
};
|
||||
|
||||
static const struct dml2_soc_bb dml2_socbb_dcn31 = {
|
||||
.clk_table = {
|
||||
.uclk = {
|
||||
.clk_values_khz = {97000, 435000, 731000, 1187000},
|
||||
.num_clk_values = 4,
|
||||
},
|
||||
.fclk = {
|
||||
.clk_values_khz = {300000, 2500000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.dcfclk = {
|
||||
.clk_values_khz = {200000, 1800000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.dispclk = {
|
||||
.clk_values_khz = {100000, 2000000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.dppclk = {
|
||||
.clk_values_khz = {100000, 2000000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.dtbclk = {
|
||||
.clk_values_khz = {100000, 2000000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.phyclk = {
|
||||
.clk_values_khz = {810000, 810000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.socclk = {
|
||||
.clk_values_khz = {300000, 1600000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.dscclk = {
|
||||
.clk_values_khz = {666667, 666667},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.phyclk_d18 = {
|
||||
.clk_values_khz = {625000, 625000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.phyclk_d32 = {
|
||||
.clk_values_khz = {2000000, 2000000},
|
||||
.num_clk_values = 2,
|
||||
},
|
||||
.dram_config = {
|
||||
.channel_width_bytes = 2,
|
||||
.channel_count = 16,
|
||||
.transactions_per_clock = 16,
|
||||
},
|
||||
},
|
||||
|
||||
.qos_parameters = {
|
||||
.derate_table = {
|
||||
.system_active_urgent = {
|
||||
.dram_derate_percent_pixel = 22,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 76,
|
||||
.dcfclk_derate_percent = 100,
|
||||
},
|
||||
.system_active_average = {
|
||||
.dram_derate_percent_pixel = 17,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 57,
|
||||
.dcfclk_derate_percent = 75,
|
||||
},
|
||||
.dcn_mall_prefetch_urgent = {
|
||||
.dram_derate_percent_pixel = 22,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 76,
|
||||
.dcfclk_derate_percent = 100,
|
||||
},
|
||||
.dcn_mall_prefetch_average = {
|
||||
.dram_derate_percent_pixel = 17,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 57,
|
||||
.dcfclk_derate_percent = 75,
|
||||
},
|
||||
.system_idle_average = {
|
||||
.dram_derate_percent_pixel = 17,
|
||||
.dram_derate_percent_vm = 0,
|
||||
.dram_derate_percent_pixel_and_vm = 0,
|
||||
.fclk_derate_percent = 57,
|
||||
.dcfclk_derate_percent = 100,
|
||||
},
|
||||
},
|
||||
.writeback = {
|
||||
.base_latency_us = 0,
|
||||
.scaling_factor_us = 0,
|
||||
.scaling_factor_mhz = 0,
|
||||
},
|
||||
.qos_params = {
|
||||
.dcn4x = {
|
||||
.df_qos_response_time_fclk_cycles = 300,
|
||||
.max_round_trip_to_furthest_cs_fclk_cycles = 350,
|
||||
.mall_overhead_fclk_cycles = 50,
|
||||
.meta_trip_adder_fclk_cycles = 36,
|
||||
.average_transport_distance_fclk_cycles = 260,
|
||||
.umc_urgent_ramp_latency_margin = 50,
|
||||
.umc_max_latency_margin = 30,
|
||||
.umc_average_latency_margin = 20,
|
||||
.fabric_max_transport_latency_margin = 20,
|
||||
.fabric_average_transport_latency_margin = 10,
|
||||
|
||||
.per_uclk_dpm_params = {
|
||||
{
|
||||
// State 1
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 472,
|
||||
.trip_to_memory_uclk_cycles = 827,
|
||||
.meta_trip_to_memory_uclk_cycles = 827,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 72,
|
||||
.average_latency_when_urgent_uclk_cycles = 72,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 827,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 117,
|
||||
},
|
||||
{
|
||||
// State 2
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 546,
|
||||
.trip_to_memory_uclk_cycles = 848,
|
||||
.meta_trip_to_memory_uclk_cycles = 848,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 146,
|
||||
.average_latency_when_urgent_uclk_cycles = 146,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 848,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 133,
|
||||
},
|
||||
{
|
||||
// State 3
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 564,
|
||||
.trip_to_memory_uclk_cycles = 853,
|
||||
.meta_trip_to_memory_uclk_cycles = 853,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 164,
|
||||
.average_latency_when_urgent_uclk_cycles = 164,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 853,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 136,
|
||||
},
|
||||
{
|
||||
// State 4
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 613,
|
||||
.trip_to_memory_uclk_cycles = 869,
|
||||
.meta_trip_to_memory_uclk_cycles = 869,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 213,
|
||||
.average_latency_when_urgent_uclk_cycles = 213,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 869,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 149,
|
||||
},
|
||||
{
|
||||
// State 5
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 632,
|
||||
.trip_to_memory_uclk_cycles = 874,
|
||||
.meta_trip_to_memory_uclk_cycles = 874,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 232,
|
||||
.average_latency_when_urgent_uclk_cycles = 232,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 874,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 153,
|
||||
},
|
||||
{
|
||||
// State 6
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 665,
|
||||
.trip_to_memory_uclk_cycles = 885,
|
||||
.meta_trip_to_memory_uclk_cycles = 885,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 265,
|
||||
.average_latency_when_urgent_uclk_cycles = 265,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 885,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 161,
|
||||
},
|
||||
{
|
||||
// State 7
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 689,
|
||||
.trip_to_memory_uclk_cycles = 895,
|
||||
.meta_trip_to_memory_uclk_cycles = 895,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 289,
|
||||
.average_latency_when_urgent_uclk_cycles = 289,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 895,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 167,
|
||||
},
|
||||
{
|
||||
// State 8
|
||||
.minimum_uclk_khz = 0,
|
||||
.urgent_ramp_uclk_cycles = 716,
|
||||
.trip_to_memory_uclk_cycles = 902,
|
||||
.meta_trip_to_memory_uclk_cycles = 902,
|
||||
.maximum_latency_when_urgent_uclk_cycles = 316,
|
||||
.average_latency_when_urgent_uclk_cycles = 316,
|
||||
.maximum_latency_when_non_urgent_uclk_cycles = 902,
|
||||
.average_latency_when_non_urgent_uclk_cycles = 174,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
.qos_type = dml2_qos_param_type_dcn4x,
|
||||
},
|
||||
|
||||
.power_management_parameters = {
|
||||
.dram_clk_change_blackout_us = 400,
|
||||
.fclk_change_blackout_us = 0,
|
||||
.g7_ppt_blackout_us = 0,
|
||||
.stutter_enter_plus_exit_latency_us = 50,
|
||||
.stutter_exit_latency_us = 43,
|
||||
.z8_stutter_enter_plus_exit_latency_us = 0,
|
||||
.z8_stutter_exit_latency_us = 0,
|
||||
},
|
||||
|
||||
.vmin_limit = {
|
||||
.dispclk_khz = 600 * 1000,
|
||||
},
|
||||
|
||||
.dprefclk_mhz = 700,
|
||||
.xtalclk_mhz = 100,
|
||||
.pcie_refclk_mhz = 100,
|
||||
.dchub_refclk_mhz = 50,
|
||||
.mall_allocated_for_dcn_mbytes = 64,
|
||||
.max_outstanding_reqs = 512,
|
||||
.fabric_datapath_to_dcn_data_return_bytes = 64,
|
||||
.return_bus_width_bytes = 64,
|
||||
.hostvm_min_page_size_kbytes = 0,
|
||||
.gpuvm_min_page_size_kbytes = 256,
|
||||
.phy_downspread_percent = 0,
|
||||
.dcn_downspread_percent = 0,
|
||||
.dispclk_dppclk_vco_speed_mhz = 4500,
|
||||
.do_urgent_latency_adjustment = 0,
|
||||
.mem_word_bytes = 32,
|
||||
.num_dcc_mcaches = 8,
|
||||
.mcache_size_bytes = 2048,
|
||||
.mcache_line_size_bytes = 32,
|
||||
.max_fclk_for_uclk_dpm_khz = 1250 * 1000,
|
||||
};
|
||||
|
||||
static const struct dml2_ip_capabilities dml2_dcn31_max_ip_caps = {
|
||||
.pipe_count = 4,
|
||||
.otg_count = 4,
|
||||
.num_dsc = 4,
|
||||
.max_num_dp2p0_streams = 4,
|
||||
.max_num_hdmi_frl_outputs = 1,
|
||||
.max_num_dp2p0_outputs = 4,
|
||||
.rob_buffer_size_kbytes = 192,
|
||||
.config_return_buffer_size_in_kbytes = 1152,
|
||||
.meta_fifo_size_in_kentries = 22,
|
||||
.compressed_buffer_segment_size_in_kbytes = 64,
|
||||
.subvp_drr_scheduling_margin_us = 100,
|
||||
.subvp_prefetch_end_to_mall_start_us = 15,
|
||||
.subvp_fw_processing_delay = 15,
|
||||
|
||||
.fams2 = {
|
||||
.max_allow_delay_us = 100 * 1000,
|
||||
.scheduling_delay_us = 50,
|
||||
.vertical_interrupt_ack_delay_us = 18,
|
||||
.allow_programming_delay_us = 18,
|
||||
.min_allow_width_us = 20,
|
||||
.subvp_df_throttle_delay_us = 100,
|
||||
.subvp_programming_delay_us = 18,
|
||||
.subvp_prefetch_to_mall_delay_us = 18,
|
||||
.drr_programming_delay_us = 18,
|
||||
},
|
||||
};
|
||||
|
||||
#endif /* __DML_DML_DCN3_SOC_BB__ */
|
@ -747,11 +747,10 @@ static inline struct dml2_context *dml2_allocate_memory(void)
|
||||
|
||||
static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
|
||||
{
|
||||
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
|
||||
dml21_reinit(in_dc, dml2, config);
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01)) {
|
||||
dml21_reinit(in_dc, dml2, config);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Store config options
|
||||
(*dml2)->config = *config;
|
||||
@ -786,10 +785,8 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op
|
||||
|
||||
bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
|
||||
{
|
||||
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01))
|
||||
return dml21_create(in_dc, dml2, config);
|
||||
}
|
||||
|
||||
// Allocate Mode Lib Ctx
|
||||
*dml2 = dml2_allocate_memory();
|
||||
@ -857,8 +854,7 @@ void dml2_reinit(const struct dc *in_dc,
|
||||
const struct dml2_configuration_options *config,
|
||||
struct dml2_context **dml2)
|
||||
{
|
||||
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01)) {
|
||||
dml21_reinit(in_dc, dml2, config);
|
||||
return;
|
||||
}
|
||||
|
@ -145,30 +145,44 @@ void hubp401_init(struct hubp *hubp)
|
||||
}
|
||||
|
||||
void hubp401_vready_at_or_After_vsync(struct hubp *hubp,
|
||||
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest)
|
||||
union dml2_global_sync_programming *pipe_global_sync,
|
||||
struct dc_crtc_timing *timing)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
unsigned int vstartup_lines = pipe_global_sync->dcn4x.vstartup_lines;
|
||||
unsigned int vupdate_offset_pixels = pipe_global_sync->dcn4x.vupdate_offset_pixels;
|
||||
unsigned int vupdate_width_pixels = pipe_global_sync->dcn4x.vupdate_vupdate_width_pixels;
|
||||
unsigned int vready_offset_pixels = pipe_global_sync->dcn4x.vready_offset_pixels;
|
||||
unsigned int htotal = timing->h_total;
|
||||
unsigned int vblank_start = 0;
|
||||
unsigned int vblank_end = 0;
|
||||
unsigned int pixel_width = 0;
|
||||
uint32_t reg_value = 0;
|
||||
bool is_vready_at_or_after_vsync = false;
|
||||
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
|
||||
|
||||
/*
|
||||
* if (VSTARTUP_START - (VREADY_OFFSET+VUPDATE_WIDTH+VUPDATE_OFFSET)/htotal) <= OTG_V_BLANK_END
|
||||
* Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 1
|
||||
* else
|
||||
* Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0
|
||||
*/
|
||||
if (pipe_dest->htotal != 0) {
|
||||
if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width
|
||||
+ pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) {
|
||||
value = 1;
|
||||
} else
|
||||
value = 0;
|
||||
if (htotal != 0) {
|
||||
vblank_start = timing->v_total - timing->v_front_porch;
|
||||
vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
|
||||
pixel_width = vready_offset_pixels + vupdate_width_pixels + vupdate_offset_pixels;
|
||||
|
||||
is_vready_at_or_after_vsync = (vstartup_lines - pixel_width / htotal) <= vblank_end;
|
||||
|
||||
if (is_vready_at_or_after_vsync)
|
||||
reg_value = 1;
|
||||
}
|
||||
|
||||
REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value);
|
||||
REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, reg_value);
|
||||
}
|
||||
|
||||
void hubp401_program_requestor(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_rq_regs_st *rq_regs)
|
||||
struct dml2_display_rq_regs *rq_regs)
|
||||
{
|
||||
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
|
||||
|
||||
@ -196,8 +210,8 @@ void hubp401_program_requestor(
|
||||
|
||||
void hubp401_program_deadline(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
|
||||
struct _vcs_dpi_display_ttu_regs_st *ttu_attr)
|
||||
struct dml2_display_dlg_regs *dlg_attr,
|
||||
struct dml2_display_ttu_regs *ttu_attr)
|
||||
{
|
||||
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
|
||||
|
||||
@ -294,66 +308,64 @@ void hubp401_program_deadline(
|
||||
|
||||
void hubp401_setup(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
|
||||
struct _vcs_dpi_display_ttu_regs_st *ttu_attr,
|
||||
struct _vcs_dpi_display_rq_regs_st *rq_regs,
|
||||
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest)
|
||||
struct dml2_dchub_per_pipe_register_set *pipe_regs,
|
||||
union dml2_global_sync_programming *pipe_global_sync,
|
||||
struct dc_crtc_timing *timing)
|
||||
{
|
||||
/* otg is locked when this func is called. Register are double buffered.
|
||||
* disable the requestors is not needed
|
||||
*/
|
||||
hubp401_vready_at_or_After_vsync(hubp, pipe_dest);
|
||||
hubp401_program_requestor(hubp, rq_regs);
|
||||
hubp401_program_deadline(hubp, dlg_attr, ttu_attr);
|
||||
hubp401_vready_at_or_After_vsync(hubp, pipe_global_sync, timing);
|
||||
hubp401_program_requestor(hubp, &pipe_regs->rq_regs);
|
||||
hubp401_program_deadline(hubp, &pipe_regs->dlg_regs, &pipe_regs->ttu_regs);
|
||||
}
|
||||
|
||||
void hubp401_setup_interdependent(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
|
||||
struct _vcs_dpi_display_ttu_regs_st *ttu_attr)
|
||||
struct dml2_dchub_per_pipe_register_set *pipe_regs)
|
||||
{
|
||||
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
|
||||
|
||||
REG_SET_2(PREFETCH_SETTINGS, 0,
|
||||
DST_Y_PREFETCH, dlg_attr->dst_y_prefetch,
|
||||
VRATIO_PREFETCH, dlg_attr->vratio_prefetch);
|
||||
DST_Y_PREFETCH, pipe_regs->dlg_regs.dst_y_prefetch,
|
||||
VRATIO_PREFETCH, pipe_regs->dlg_regs.vratio_prefetch);
|
||||
|
||||
REG_SET(PREFETCH_SETTINGS_C, 0,
|
||||
VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c);
|
||||
VRATIO_PREFETCH_C, pipe_regs->dlg_regs.vratio_prefetch_c);
|
||||
|
||||
REG_SET_2(VBLANK_PARAMETERS_0, 0,
|
||||
DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank,
|
||||
DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank);
|
||||
DST_Y_PER_VM_VBLANK, pipe_regs->dlg_regs.dst_y_per_vm_vblank,
|
||||
DST_Y_PER_ROW_VBLANK, pipe_regs->dlg_regs.dst_y_per_row_vblank);
|
||||
|
||||
REG_SET_2(FLIP_PARAMETERS_0, 0,
|
||||
DST_Y_PER_VM_FLIP, dlg_attr->dst_y_per_vm_flip,
|
||||
DST_Y_PER_ROW_FLIP, dlg_attr->dst_y_per_row_flip);
|
||||
DST_Y_PER_VM_FLIP, pipe_regs->dlg_regs.dst_y_per_vm_flip,
|
||||
DST_Y_PER_ROW_FLIP, pipe_regs->dlg_regs.dst_y_per_row_flip);
|
||||
|
||||
REG_SET(VBLANK_PARAMETERS_3, 0,
|
||||
REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l);
|
||||
REFCYC_PER_META_CHUNK_VBLANK_L, pipe_regs->dlg_regs.refcyc_per_meta_chunk_vblank_l);
|
||||
|
||||
REG_SET(VBLANK_PARAMETERS_4, 0,
|
||||
REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c);
|
||||
REFCYC_PER_META_CHUNK_VBLANK_C, pipe_regs->dlg_regs.refcyc_per_meta_chunk_vblank_c);
|
||||
|
||||
REG_SET(FLIP_PARAMETERS_2, 0,
|
||||
REFCYC_PER_META_CHUNK_FLIP_L, dlg_attr->refcyc_per_meta_chunk_flip_l);
|
||||
REFCYC_PER_META_CHUNK_FLIP_L, pipe_regs->dlg_regs.refcyc_per_meta_chunk_flip_l);
|
||||
|
||||
REG_SET_2(PER_LINE_DELIVERY_PRE, 0,
|
||||
REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l,
|
||||
REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c);
|
||||
REFCYC_PER_LINE_DELIVERY_PRE_L, pipe_regs->dlg_regs.refcyc_per_line_delivery_pre_l,
|
||||
REFCYC_PER_LINE_DELIVERY_PRE_C, pipe_regs->dlg_regs.refcyc_per_line_delivery_pre_c);
|
||||
|
||||
REG_SET(DCN_SURF0_TTU_CNTL1, 0,
|
||||
REFCYC_PER_REQ_DELIVERY_PRE,
|
||||
ttu_attr->refcyc_per_req_delivery_pre_l);
|
||||
pipe_regs->ttu_regs.refcyc_per_req_delivery_pre_l);
|
||||
REG_SET(DCN_SURF1_TTU_CNTL1, 0,
|
||||
REFCYC_PER_REQ_DELIVERY_PRE,
|
||||
ttu_attr->refcyc_per_req_delivery_pre_c);
|
||||
pipe_regs->ttu_regs.refcyc_per_req_delivery_pre_c);
|
||||
REG_SET(DCN_CUR0_TTU_CNTL1, 0,
|
||||
REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur0);
|
||||
REFCYC_PER_REQ_DELIVERY_PRE, pipe_regs->ttu_regs.refcyc_per_req_delivery_pre_cur0);
|
||||
|
||||
REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0,
|
||||
MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank,
|
||||
QoS_LEVEL_FLIP, ttu_attr->qos_level_flip);
|
||||
MIN_TTU_VBLANK, pipe_regs->ttu_regs.min_ttu_vblank,
|
||||
QoS_LEVEL_FLIP, pipe_regs->ttu_regs.qos_level_flip);
|
||||
}
|
||||
|
||||
|
||||
@ -981,8 +993,8 @@ static struct hubp_funcs dcn401_hubp_funcs = {
|
||||
.hubp_program_surface_flip_and_addr = hubp401_program_surface_flip_and_addr,
|
||||
.hubp_program_surface_config = hubp401_program_surface_config,
|
||||
.hubp_is_flip_pending = hubp2_is_flip_pending,
|
||||
.hubp_setup = hubp401_setup,
|
||||
.hubp_setup_interdependent = hubp401_setup_interdependent,
|
||||
.hubp_setup2 = hubp401_setup,
|
||||
.hubp_setup_interdependent2 = hubp401_setup_interdependent,
|
||||
.hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
|
||||
.set_blank = hubp2_set_blank,
|
||||
.set_blank_regs = hubp2_set_blank_regs,
|
||||
|
@ -256,29 +256,15 @@
|
||||
|
||||
void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor);
|
||||
|
||||
void hubp401_vready_at_or_After_vsync(struct hubp *hubp,
|
||||
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
|
||||
|
||||
void hubp401_program_requestor(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_rq_regs_st *rq_regs);
|
||||
|
||||
void hubp401_program_deadline(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
|
||||
struct _vcs_dpi_display_ttu_regs_st *ttu_attr);
|
||||
|
||||
void hubp401_setup(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
|
||||
struct _vcs_dpi_display_ttu_regs_st *ttu_attr,
|
||||
struct _vcs_dpi_display_rq_regs_st *rq_regs,
|
||||
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
|
||||
struct dml2_dchub_per_pipe_register_set *pipe_regs,
|
||||
union dml2_global_sync_programming *pipe_global_sync,
|
||||
struct dc_crtc_timing *timing);
|
||||
|
||||
void hubp401_setup_interdependent(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
|
||||
struct _vcs_dpi_display_ttu_regs_st *ttu_attr);
|
||||
struct dml2_dchub_per_pipe_register_set *pipe_regs);
|
||||
|
||||
bool hubp401_program_surface_flip_and_addr(
|
||||
struct hubp *hubp,
|
||||
@ -365,4 +351,17 @@ void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mo
|
||||
|
||||
void hubp401_clear_tiling(struct hubp *hubp);
|
||||
|
||||
void hubp401_vready_at_or_After_vsync(struct hubp *hubp,
|
||||
union dml2_global_sync_programming *pipe_global_sync,
|
||||
struct dc_crtc_timing *timing);
|
||||
|
||||
void hubp401_program_requestor(
|
||||
struct hubp *hubp,
|
||||
struct dml2_display_rq_regs *rq_regs);
|
||||
|
||||
void hubp401_program_deadline(
|
||||
struct hubp *hubp,
|
||||
struct dml2_display_dlg_regs *dlg_attr,
|
||||
struct dml2_display_ttu_regs *ttu_attr);
|
||||
|
||||
#endif /* __DC_HUBP_DCN401_H__ */
|
||||
|
@ -1288,7 +1288,7 @@ static void dcn20_power_on_plane_resources(
|
||||
}
|
||||
}
|
||||
|
||||
static void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
|
||||
void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context)
|
||||
{
|
||||
//if (dc->debug.sanity_checks) {
|
||||
@ -1467,7 +1467,7 @@ void dcn20_pipe_control_lock(
|
||||
}
|
||||
}
|
||||
|
||||
static void dcn20_detect_pipe_changes(struct dc_state *old_state,
|
||||
void dcn20_detect_pipe_changes(struct dc_state *old_state,
|
||||
struct dc_state *new_state,
|
||||
struct pipe_ctx *old_pipe,
|
||||
struct pipe_ctx *new_pipe)
|
||||
@ -1655,7 +1655,7 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state,
|
||||
}
|
||||
}
|
||||
|
||||
static void dcn20_update_dchubp_dpp(
|
||||
void dcn20_update_dchubp_dpp(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context)
|
||||
@ -1678,25 +1678,41 @@ static void dcn20_update_dchubp_dpp(
|
||||
* VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
|
||||
* VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
|
||||
*/
|
||||
|
||||
if (pipe_ctx->update_flags.bits.hubp_rq_dlg_ttu) {
|
||||
hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
|
||||
|
||||
hubp->funcs->hubp_setup(
|
||||
hubp,
|
||||
&pipe_ctx->dlg_regs,
|
||||
&pipe_ctx->ttu_regs,
|
||||
&pipe_ctx->rq_regs,
|
||||
&pipe_ctx->pipe_dlg_param);
|
||||
if (hubp->funcs->hubp_setup2) {
|
||||
hubp->funcs->hubp_setup2(
|
||||
hubp,
|
||||
&pipe_ctx->hubp_regs,
|
||||
&pipe_ctx->global_sync,
|
||||
&pipe_ctx->stream->timing);
|
||||
} else {
|
||||
hubp->funcs->hubp_setup(
|
||||
hubp,
|
||||
&pipe_ctx->dlg_regs,
|
||||
&pipe_ctx->ttu_regs,
|
||||
&pipe_ctx->rq_regs,
|
||||
&pipe_ctx->pipe_dlg_param);
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe_ctx->update_flags.bits.unbounded_req && hubp->funcs->set_unbounded_requesting)
|
||||
hubp->funcs->set_unbounded_requesting(hubp, pipe_ctx->unbounded_req);
|
||||
|
||||
if (pipe_ctx->update_flags.bits.hubp_interdependent)
|
||||
hubp->funcs->hubp_setup_interdependent(
|
||||
hubp,
|
||||
&pipe_ctx->dlg_regs,
|
||||
&pipe_ctx->ttu_regs);
|
||||
if (pipe_ctx->update_flags.bits.hubp_interdependent) {
|
||||
if (hubp->funcs->hubp_setup_interdependent2) {
|
||||
hubp->funcs->hubp_setup_interdependent2(
|
||||
hubp,
|
||||
&pipe_ctx->hubp_regs);
|
||||
} else {
|
||||
hubp->funcs->hubp_setup_interdependent(
|
||||
hubp,
|
||||
&pipe_ctx->dlg_regs,
|
||||
&pipe_ctx->ttu_regs);
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe_ctx->update_flags.bits.enable ||
|
||||
pipe_ctx->update_flags.bits.plane_changed ||
|
||||
@ -1756,10 +1772,9 @@ static void dcn20_update_dchubp_dpp(
|
||||
&pipe_ctx->plane_res.scl_data.viewport_c);
|
||||
viewport_changed = true;
|
||||
}
|
||||
if (hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
|
||||
hubp->funcs->hubp_program_mcache_id_and_split_coordinate(
|
||||
hubp,
|
||||
&pipe_ctx->mcache_regs);
|
||||
|
||||
if (hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
|
||||
hubp->funcs->hubp_program_mcache_id_and_split_coordinate(hubp, &pipe_ctx->mcache_regs);
|
||||
|
||||
/* Any updates are handled in dc interface, just need to apply existing for plane enable */
|
||||
if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
|
||||
@ -1838,7 +1853,7 @@ static void dcn20_update_dchubp_dpp(
|
||||
hubp->funcs->phantom_hubp_post_enable(hubp);
|
||||
}
|
||||
|
||||
static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
|
||||
static int dcn20_calculate_vready_offset_for_group(struct pipe_ctx *pipe)
|
||||
{
|
||||
struct pipe_ctx *other_pipe;
|
||||
int vready_offset = pipe->pipe_dlg_param.vready_offset;
|
||||
@ -1864,6 +1879,30 @@ static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
|
||||
return vready_offset;
|
||||
}
|
||||
|
||||
static void dcn20_program_tg(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context,
|
||||
struct dce_hwseq *hws)
|
||||
{
|
||||
pipe_ctx->stream_res.tg->funcs->program_global_sync(
|
||||
pipe_ctx->stream_res.tg,
|
||||
dcn20_calculate_vready_offset_for_group(pipe_ctx),
|
||||
pipe_ctx->pipe_dlg_param.vstartup_start,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_offset,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_width,
|
||||
pipe_ctx->pipe_dlg_param.pstate_keepout);
|
||||
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)
|
||||
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
|
||||
|
||||
if (hws->funcs.setup_vupdate_interrupt)
|
||||
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
|
||||
}
|
||||
|
||||
static void dcn20_program_pipe(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
@ -1874,33 +1913,17 @@ static void dcn20_program_pipe(
|
||||
/* Only need to unblank on top pipe */
|
||||
if (resource_is_pipe_type(pipe_ctx, OTG_MASTER)) {
|
||||
if (pipe_ctx->update_flags.bits.enable ||
|
||||
pipe_ctx->update_flags.bits.odm ||
|
||||
pipe_ctx->stream->update_flags.bits.abm_level)
|
||||
pipe_ctx->update_flags.bits.odm ||
|
||||
pipe_ctx->stream->update_flags.bits.abm_level)
|
||||
hws->funcs.blank_pixel_data(dc, pipe_ctx,
|
||||
!pipe_ctx->plane_state ||
|
||||
!pipe_ctx->plane_state->visible);
|
||||
!pipe_ctx->plane_state ||
|
||||
!pipe_ctx->plane_state->visible);
|
||||
}
|
||||
|
||||
/* Only update TG on top pipe */
|
||||
if (pipe_ctx->update_flags.bits.global_sync && !pipe_ctx->top_pipe
|
||||
&& !pipe_ctx->prev_odm_pipe) {
|
||||
pipe_ctx->stream_res.tg->funcs->program_global_sync(
|
||||
pipe_ctx->stream_res.tg,
|
||||
calculate_vready_offset_for_group(pipe_ctx),
|
||||
pipe_ctx->pipe_dlg_param.vstartup_start,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_offset,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_width,
|
||||
pipe_ctx->pipe_dlg_param.pstate_keepout);
|
||||
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)
|
||||
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
|
||||
|
||||
if (hws->funcs.setup_vupdate_interrupt)
|
||||
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
|
||||
}
|
||||
&& !pipe_ctx->prev_odm_pipe)
|
||||
dcn20_program_tg(dc, pipe_ctx, context, hws);
|
||||
|
||||
if (pipe_ctx->update_flags.bits.odm)
|
||||
hws->funcs.update_odm(dc, context, pipe_ctx);
|
||||
@ -1931,22 +1954,22 @@ static void dcn20_program_pipe(
|
||||
dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
|
||||
|
||||
if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable ||
|
||||
pipe_ctx->plane_state->update_flags.bits.hdr_mult))
|
||||
pipe_ctx->plane_state->update_flags.bits.hdr_mult))
|
||||
hws->funcs.set_hdr_multiplier(pipe_ctx);
|
||||
|
||||
if (hws->funcs.populate_mcm_luts) {
|
||||
if (pipe_ctx->plane_state) {
|
||||
hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts,
|
||||
pipe_ctx->plane_state->lut_bank_a);
|
||||
pipe_ctx->plane_state->lut_bank_a);
|
||||
pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a;
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe_ctx->plane_state &&
|
||||
(pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
|
||||
pipe_ctx->plane_state->update_flags.bits.gamma_change ||
|
||||
pipe_ctx->plane_state->update_flags.bits.lut_3d ||
|
||||
pipe_ctx->update_flags.bits.enable))
|
||||
(pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
|
||||
pipe_ctx->plane_state->update_flags.bits.gamma_change ||
|
||||
pipe_ctx->plane_state->update_flags.bits.lut_3d ||
|
||||
pipe_ctx->update_flags.bits.enable))
|
||||
hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
|
||||
|
||||
/* dcn10_translate_regamma_to_hw_format takes 750us to finish
|
||||
@ -1954,10 +1977,10 @@ static void dcn20_program_pipe(
|
||||
* updating on slave planes
|
||||
*/
|
||||
if (pipe_ctx->update_flags.bits.enable ||
|
||||
pipe_ctx->update_flags.bits.plane_changed ||
|
||||
pipe_ctx->stream->update_flags.bits.out_tf ||
|
||||
(pipe_ctx->plane_state &&
|
||||
pipe_ctx->plane_state->update_flags.bits.output_tf_change))
|
||||
pipe_ctx->update_flags.bits.plane_changed ||
|
||||
pipe_ctx->stream->update_flags.bits.out_tf ||
|
||||
(pipe_ctx->plane_state &&
|
||||
pipe_ctx->plane_state->update_flags.bits.output_tf_change))
|
||||
hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
|
||||
|
||||
/* If the pipe has been enabled or has a different opp, we
|
||||
@ -1966,7 +1989,7 @@ static void dcn20_program_pipe(
|
||||
* causes a different pipe to be chosen to odm combine with.
|
||||
*/
|
||||
if (pipe_ctx->update_flags.bits.enable
|
||||
|| pipe_ctx->update_flags.bits.opp_changed) {
|
||||
|| pipe_ctx->update_flags.bits.opp_changed) {
|
||||
|
||||
pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
|
||||
pipe_ctx->stream_res.opp,
|
||||
@ -1996,14 +2019,14 @@ static void dcn20_program_pipe(
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
|
||||
dc->hwss.set_disp_pattern_generator(dc,
|
||||
pipe_ctx,
|
||||
pipe_ctx->stream_res.test_pattern_params.test_pattern,
|
||||
pipe_ctx->stream_res.test_pattern_params.color_space,
|
||||
pipe_ctx->stream_res.test_pattern_params.color_depth,
|
||||
NULL,
|
||||
pipe_ctx->stream_res.test_pattern_params.width,
|
||||
pipe_ctx->stream_res.test_pattern_params.height,
|
||||
pipe_ctx->stream_res.test_pattern_params.offset);
|
||||
pipe_ctx,
|
||||
pipe_ctx->stream_res.test_pattern_params.test_pattern,
|
||||
pipe_ctx->stream_res.test_pattern_params.color_space,
|
||||
pipe_ctx->stream_res.test_pattern_params.color_depth,
|
||||
NULL,
|
||||
pipe_ctx->stream_res.test_pattern_params.width,
|
||||
pipe_ctx->stream_res.test_pattern_params.height,
|
||||
pipe_ctx->stream_res.test_pattern_params.offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2012,11 +2035,12 @@ void dcn20_program_front_end_for_ctx(
|
||||
struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
unsigned int prev_hubp_count = 0;
|
||||
unsigned int hubp_count = 0;
|
||||
struct pipe_ctx *pipe;
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
struct pipe_ctx *pipe = NULL;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (resource_is_pipe_topology_changed(dc->current_state, context))
|
||||
resource_log_pipe_topology_update(dc, context);
|
||||
@ -2029,7 +2053,7 @@ void dcn20_program_front_end_for_ctx(
|
||||
ASSERT(!pipe->plane_state->triplebuffer_flips);
|
||||
/*turn off triple buffer for full update*/
|
||||
dc->hwss.program_triplebuffer(
|
||||
dc, pipe, pipe->plane_state->triplebuffer_flips);
|
||||
dc, pipe, pipe->plane_state->triplebuffer_flips);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2044,30 +2068,31 @@ void dcn20_program_front_end_for_ctx(
|
||||
if (prev_hubp_count == 0 && hubp_count > 0) {
|
||||
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control(
|
||||
dc->res_pool->hubbub, true, false);
|
||||
dc->res_pool->hubbub, true, false);
|
||||
udelay(500);
|
||||
}
|
||||
|
||||
/* Set pipe update flags and lock pipes */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
dcn20_detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i],
|
||||
&context->res_ctx.pipe_ctx[i]);
|
||||
&context->res_ctx.pipe_ctx[i]);
|
||||
|
||||
/* When disabling phantom pipes, turn on phantom OTG first (so we can get double
|
||||
* buffer updates properly)
|
||||
*/
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct dc_stream_state *stream = dc->current_state->res_ctx.pipe_ctx[i].stream;
|
||||
|
||||
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && stream &&
|
||||
dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
|
||||
dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
|
||||
struct timing_generator *tg = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg;
|
||||
|
||||
if (tg->funcs->enable_crtc) {
|
||||
if (dc->hwseq->funcs.blank_pixel_data) {
|
||||
if (dc->hwseq->funcs.blank_pixel_data)
|
||||
dc->hwseq->funcs.blank_pixel_data(dc, pipe, true);
|
||||
}
|
||||
|
||||
tg->funcs->enable_crtc(tg);
|
||||
}
|
||||
}
|
||||
@ -2075,15 +2100,15 @@ void dcn20_program_front_end_for_ctx(
|
||||
/* OTG blank before disabling all front ends */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
|
||||
&& !context->res_ctx.pipe_ctx[i].top_pipe
|
||||
&& !context->res_ctx.pipe_ctx[i].prev_odm_pipe
|
||||
&& context->res_ctx.pipe_ctx[i].stream)
|
||||
&& !context->res_ctx.pipe_ctx[i].top_pipe
|
||||
&& !context->res_ctx.pipe_ctx[i].prev_odm_pipe
|
||||
&& context->res_ctx.pipe_ctx[i].stream)
|
||||
hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true);
|
||||
|
||||
/* Disconnect mpcc */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
|
||||
|| context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
|
||||
|| context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
|
||||
struct hubbub *hubbub = dc->res_pool->hubbub;
|
||||
|
||||
/* Phantom pipe DET should be 0, but if a pipe in use is being transitioned to phantom
|
||||
@ -2093,13 +2118,18 @@ void dcn20_program_front_end_for_ctx(
|
||||
* DET allocation.
|
||||
*/
|
||||
if ((context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
|
||||
(context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM))) {
|
||||
(context->res_ctx.pipe_ctx[i].plane_state &&
|
||||
dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i])
|
||||
== SUBVP_PHANTOM))) {
|
||||
if (hubbub->funcs->program_det_size)
|
||||
hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
|
||||
hubbub->funcs->program_det_size(hubbub,
|
||||
dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
|
||||
if (dc->res_pool->hubbub->funcs->program_det_segments)
|
||||
dc->res_pool->hubbub->funcs->program_det_segments(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
|
||||
dc->res_pool->hubbub->funcs->program_det_segments(
|
||||
hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
|
||||
}
|
||||
hws->funcs.plane_atomic_disconnect(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
hws->funcs.plane_atomic_disconnect(dc, dc->current_state,
|
||||
&dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
|
||||
}
|
||||
|
||||
@ -2107,9 +2137,9 @@ void dcn20_program_front_end_for_ctx(
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
!resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
pipe->update_flags.bits.odm &&
|
||||
hws->funcs.update_odm)
|
||||
!resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
pipe->update_flags.bits.odm &&
|
||||
hws->funcs.update_odm)
|
||||
hws->funcs.update_odm(dc, context, pipe);
|
||||
}
|
||||
|
||||
@ -2127,25 +2157,28 @@ void dcn20_program_front_end_for_ctx(
|
||||
else {
|
||||
/* Don't program phantom pipes in the regular front end programming sequence.
|
||||
* There is an MPO transition case where a pipe being used by a video plane is
|
||||
* transitioned directly to be a phantom pipe when closing the MPO video. However
|
||||
* the phantom pipe will program a new HUBP_VTG_SEL (update takes place right away),
|
||||
* but the MPO still exists until the double buffered update of the main pipe so we
|
||||
* will get a frame of underflow if the phantom pipe is programmed here.
|
||||
* transitioned directly to be a phantom pipe when closing the MPO video.
|
||||
* However the phantom pipe will program a new HUBP_VTG_SEL (update takes place
|
||||
* right away) but the MPO still exists until the double buffered update of the
|
||||
* main pipe so we will get a frame of underflow if the phantom pipe is
|
||||
* programmed here.
|
||||
*/
|
||||
if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM)
|
||||
if (pipe->stream &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM)
|
||||
dcn20_program_pipe(dc, pipe, context);
|
||||
}
|
||||
|
||||
pipe = pipe->bottom_pipe;
|
||||
}
|
||||
}
|
||||
|
||||
/* Program secondary blending tree and writeback pipes */
|
||||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
if (!pipe->top_pipe && !pipe->prev_odm_pipe
|
||||
&& pipe->stream && pipe->stream->num_wb_info > 0
|
||||
&& (pipe->update_flags.raw || (pipe->plane_state && pipe->plane_state->update_flags.raw)
|
||||
|| pipe->stream->update_flags.raw)
|
||||
&& hws->funcs.program_all_writeback_pipes_in_tree)
|
||||
&& pipe->stream && pipe->stream->num_wb_info > 0
|
||||
&& (pipe->update_flags.raw || (pipe->plane_state && pipe->plane_state->update_flags.raw)
|
||||
|| pipe->stream->update_flags.raw)
|
||||
&& hws->funcs.program_all_writeback_pipes_in_tree)
|
||||
hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
|
||||
|
||||
/* Avoid underflow by check of pipe line read when adding 2nd plane. */
|
||||
@ -2164,7 +2197,7 @@ void dcn20_program_front_end_for_ctx(
|
||||
* buffered pending status clear and reset opp head pipe's none double buffered
|
||||
* registers to their initial state.
|
||||
*/
|
||||
static void post_unlock_reset_opp(struct dc *dc,
|
||||
void dcn20_post_unlock_reset_opp(struct dc *dc,
|
||||
struct pipe_ctx *opp_head)
|
||||
{
|
||||
struct display_stream_compressor *dsc = opp_head->stream_res.dsc;
|
||||
@ -2201,16 +2234,17 @@ void dcn20_post_unlock_program_front_end(
|
||||
struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
const unsigned int TIMEOUT_FOR_PIPE_ENABLE_US = 100000;
|
||||
// Timeout for pipe enable
|
||||
unsigned int timeout_us = 100000;
|
||||
unsigned int polling_interval_us = 1;
|
||||
struct dce_hwseq *hwseq = dc->hwseq;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
|
||||
!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
|
||||
post_unlock_reset_opp(dc,
|
||||
&dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
|
||||
dcn20_post_unlock_reset_opp(dc,
|
||||
&dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
|
||||
@ -2226,11 +2260,12 @@ void dcn20_post_unlock_program_front_end(
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
// Don't check flip pending on phantom pipes
|
||||
if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
|
||||
struct hubp *hubp = pipe->plane_res.hubp;
|
||||
int j = 0;
|
||||
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us
|
||||
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
|
||||
|
||||
for (j = 0; j < timeout_us / polling_interval_us
|
||||
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
|
||||
udelay(polling_interval_us);
|
||||
}
|
||||
}
|
||||
@ -2244,15 +2279,14 @@ void dcn20_post_unlock_program_front_end(
|
||||
* before we've transitioned to 2:1 or 4:1
|
||||
*/
|
||||
if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
|
||||
resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
|
||||
int j = 0;
|
||||
struct timing_generator *tg = pipe->stream_res.tg;
|
||||
|
||||
|
||||
if (tg->funcs->get_optc_double_buffer_pending) {
|
||||
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us
|
||||
&& tg->funcs->get_optc_double_buffer_pending(tg); j++)
|
||||
for (j = 0; j < timeout_us / polling_interval_us
|
||||
&& tg->funcs->get_optc_double_buffer_pending(tg); j++)
|
||||
udelay(polling_interval_us);
|
||||
}
|
||||
}
|
||||
@ -2260,7 +2294,7 @@ void dcn20_post_unlock_program_front_end(
|
||||
|
||||
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control(
|
||||
dc->res_pool->hubbub, false, false);
|
||||
dc->res_pool->hubbub, false, false);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
@ -2291,11 +2325,11 @@ void dcn20_post_unlock_program_front_end(
|
||||
return;
|
||||
|
||||
/* P-State support transitions:
|
||||
* Natural -> FPO: P-State disabled in prepare, force disallow anytime is safe
|
||||
* FPO -> Natural: Unforce anytime after FW disable is safe (P-State will assert naturally)
|
||||
* Unsupported -> FPO: P-State enabled in optimize, force disallow anytime is safe
|
||||
* FPO -> Unsupported: P-State disabled in prepare, unforce disallow anytime is safe
|
||||
* FPO <-> SubVP: Force disallow is maintained on the FPO / SubVP pipes
|
||||
* Natural -> FPO: P-State disabled in prepare, force disallow anytime is safe
|
||||
* FPO -> Natural: Unforce anytime after FW disable is safe (P-State will assert naturally)
|
||||
* Unsupported -> FPO: P-State enabled in optimize, force disallow anytime is safe
|
||||
* FPO -> Unsupported: P-State disabled in prepare, unforce disallow anytime is safe
|
||||
* FPO <-> SubVP: Force disallow is maintained on the FPO / SubVP pipes
|
||||
*/
|
||||
if (hwseq->funcs.update_force_pstate)
|
||||
dc->hwseq->funcs.update_force_pstate(dc, context);
|
||||
@ -2310,12 +2344,11 @@ void dcn20_post_unlock_program_front_end(
|
||||
if (hwseq->wa.DEGVIDCN21)
|
||||
dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
|
||||
|
||||
|
||||
/* WA for stutter underflow during MPO transitions when adding 2nd plane */
|
||||
if (hwseq->wa.disallow_self_refresh_during_multi_plane_transition) {
|
||||
|
||||
if (dc->current_state->stream_status[0].plane_count == 1 &&
|
||||
context->stream_status[0].plane_count > 1) {
|
||||
context->stream_status[0].plane_count > 1) {
|
||||
|
||||
struct timing_generator *tg = dc->res_pool->timing_generators[0];
|
||||
|
||||
@ -2463,7 +2496,7 @@ bool dcn20_update_bandwidth(
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->program_global_sync(
|
||||
pipe_ctx->stream_res.tg,
|
||||
calculate_vready_offset_for_group(pipe_ctx),
|
||||
dcn20_calculate_vready_offset_for_group(pipe_ctx),
|
||||
pipe_ctx->pipe_dlg_param.vstartup_start,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_offset,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_width,
|
||||
|
@ -154,6 +154,21 @@ void dcn20_setup_gsl_group_as_lock(
|
||||
const struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
bool enable);
|
||||
|
||||
void dcn20_detect_pipe_changes(
|
||||
struct dc_state *old_state,
|
||||
struct dc_state *new_state,
|
||||
struct pipe_ctx *old_pipe,
|
||||
struct pipe_ctx *new_pipe);
|
||||
void dcn20_enable_plane(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context);
|
||||
void dcn20_update_dchubp_dpp(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context);
|
||||
void dcn20_post_unlock_reset_opp(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *opp_head);
|
||||
#endif /* __DC_HWSS_DCN20_H__ */
|
||||
|
||||
|
@ -123,6 +123,10 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
|
||||
.set_long_vtotal = dcn35_set_long_vblank,
|
||||
.calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
|
||||
.hardware_release = dcn35_hardware_release,
|
||||
.detect_pipe_changes = dcn20_detect_pipe_changes,
|
||||
.enable_plane = dcn20_enable_plane,
|
||||
.update_dchubp_dpp = dcn20_update_dchubp_dpp,
|
||||
.post_unlock_reset_opp = dcn20_post_unlock_reset_opp,
|
||||
};
|
||||
|
||||
static const struct hwseq_private_funcs dcn35_private_funcs = {
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Copyright 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
#include "dm_services.h"
|
||||
#include "basics/dc_common.h"
|
||||
#include "dm_helpers.h"
|
||||
#include "core_types.h"
|
||||
#include "resource.h"
|
||||
@ -881,15 +882,15 @@ enum dc_status dcn401_enable_stream_timing(
|
||||
patched_crtc_timing.h_addressable = patched_crtc_timing.h_addressable + pipe_ctx->hblank_borrow;
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->program_timing(
|
||||
pipe_ctx->stream_res.tg,
|
||||
&patched_crtc_timing,
|
||||
pipe_ctx->pipe_dlg_param.vready_offset,
|
||||
pipe_ctx->pipe_dlg_param.vstartup_start,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_offset,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_width,
|
||||
pipe_ctx->pipe_dlg_param.pstate_keepout,
|
||||
pipe_ctx->stream->signal,
|
||||
true);
|
||||
pipe_ctx->stream_res.tg,
|
||||
&patched_crtc_timing,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vready_offset_pixels,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vstartup_lines,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vupdate_offset_pixels,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vupdate_vupdate_width_pixels,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.pstate_keepout_start_lines,
|
||||
pipe_ctx->stream->signal,
|
||||
true);
|
||||
|
||||
for (i = 0; i < opp_cnt; i++) {
|
||||
opp_heads[i]->stream_res.opp->funcs->opp_pipe_clock_control(
|
||||
@ -2013,3 +2014,730 @@ void dcn401_reset_hw_ctx_wrap(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int dcn401_calculate_vready_offset_for_group(struct pipe_ctx *pipe)
|
||||
{
|
||||
struct pipe_ctx *other_pipe;
|
||||
unsigned int vready_offset = pipe->global_sync.dcn4x.vready_offset_pixels;
|
||||
|
||||
/* Always use the largest vready_offset of all connected pipes */
|
||||
for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) {
|
||||
if (other_pipe->global_sync.dcn4x.vready_offset_pixels > vready_offset)
|
||||
vready_offset = other_pipe->global_sync.dcn4x.vready_offset_pixels;
|
||||
}
|
||||
for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) {
|
||||
if (other_pipe->global_sync.dcn4x.vready_offset_pixels > vready_offset)
|
||||
vready_offset = other_pipe->global_sync.dcn4x.vready_offset_pixels;
|
||||
}
|
||||
for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) {
|
||||
if (other_pipe->global_sync.dcn4x.vready_offset_pixels > vready_offset)
|
||||
vready_offset = other_pipe->global_sync.dcn4x.vready_offset_pixels;
|
||||
}
|
||||
for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) {
|
||||
if (other_pipe->global_sync.dcn4x.vready_offset_pixels > vready_offset)
|
||||
vready_offset = other_pipe->global_sync.dcn4x.vready_offset_pixels;
|
||||
}
|
||||
|
||||
return vready_offset;
|
||||
}
|
||||
|
||||
static void dcn401_program_tg(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context,
|
||||
struct dce_hwseq *hws)
|
||||
{
|
||||
pipe_ctx->stream_res.tg->funcs->program_global_sync(
|
||||
pipe_ctx->stream_res.tg,
|
||||
dcn401_calculate_vready_offset_for_group(pipe_ctx),
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vstartup_lines,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vupdate_offset_pixels,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vupdate_vupdate_width_pixels,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.pstate_keepout_start_lines);
|
||||
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)
|
||||
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
|
||||
|
||||
if (hws->funcs.setup_vupdate_interrupt)
|
||||
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
|
||||
}
|
||||
|
||||
static void dcn401_program_pipe(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context)
|
||||
{
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
|
||||
/* Only need to unblank on top pipe */
|
||||
if (resource_is_pipe_type(pipe_ctx, OTG_MASTER)) {
|
||||
if (pipe_ctx->update_flags.bits.enable ||
|
||||
pipe_ctx->update_flags.bits.odm ||
|
||||
pipe_ctx->stream->update_flags.bits.abm_level)
|
||||
hws->funcs.blank_pixel_data(dc, pipe_ctx,
|
||||
!pipe_ctx->plane_state ||
|
||||
!pipe_ctx->plane_state->visible);
|
||||
}
|
||||
|
||||
/* Only update TG on top pipe */
|
||||
if (pipe_ctx->update_flags.bits.global_sync && !pipe_ctx->top_pipe
|
||||
&& !pipe_ctx->prev_odm_pipe)
|
||||
dcn401_program_tg(dc, pipe_ctx, context, hws);
|
||||
|
||||
if (pipe_ctx->update_flags.bits.odm)
|
||||
hws->funcs.update_odm(dc, context, pipe_ctx);
|
||||
|
||||
if (pipe_ctx->update_flags.bits.enable) {
|
||||
if (hws->funcs.enable_plane)
|
||||
hws->funcs.enable_plane(dc, pipe_ctx, context);
|
||||
else
|
||||
dc->hwss.enable_plane(dc, pipe_ctx, context);
|
||||
|
||||
if (dc->res_pool->hubbub->funcs->force_wm_propagate_to_pipes)
|
||||
dc->res_pool->hubbub->funcs->force_wm_propagate_to_pipes(dc->res_pool->hubbub);
|
||||
}
|
||||
|
||||
if (pipe_ctx->update_flags.bits.det_size) {
|
||||
if (dc->res_pool->hubbub->funcs->program_det_size)
|
||||
dc->res_pool->hubbub->funcs->program_det_size(
|
||||
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb);
|
||||
if (dc->res_pool->hubbub->funcs->program_det_segments)
|
||||
dc->res_pool->hubbub->funcs->program_det_segments(
|
||||
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);
|
||||
}
|
||||
|
||||
if (pipe_ctx->update_flags.raw ||
|
||||
(pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) ||
|
||||
pipe_ctx->stream->update_flags.raw)
|
||||
dc->hwss.update_dchubp_dpp(dc, pipe_ctx, context);
|
||||
|
||||
if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable ||
|
||||
pipe_ctx->plane_state->update_flags.bits.hdr_mult))
|
||||
hws->funcs.set_hdr_multiplier(pipe_ctx);
|
||||
|
||||
if (hws->funcs.populate_mcm_luts) {
|
||||
if (pipe_ctx->plane_state) {
|
||||
hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts,
|
||||
pipe_ctx->plane_state->lut_bank_a);
|
||||
pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a;
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe_ctx->plane_state &&
|
||||
(pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
|
||||
pipe_ctx->plane_state->update_flags.bits.gamma_change ||
|
||||
pipe_ctx->plane_state->update_flags.bits.lut_3d ||
|
||||
pipe_ctx->update_flags.bits.enable))
|
||||
hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
|
||||
|
||||
/* dcn10_translate_regamma_to_hw_format takes 750us to finish
|
||||
* only do gamma programming for powering on, internal memcmp to avoid
|
||||
* updating on slave planes
|
||||
*/
|
||||
if (pipe_ctx->update_flags.bits.enable ||
|
||||
pipe_ctx->update_flags.bits.plane_changed ||
|
||||
pipe_ctx->stream->update_flags.bits.out_tf ||
|
||||
(pipe_ctx->plane_state &&
|
||||
pipe_ctx->plane_state->update_flags.bits.output_tf_change))
|
||||
hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
|
||||
|
||||
/* If the pipe has been enabled or has a different opp, we
|
||||
* should reprogram the fmt. This deals with cases where
|
||||
* interation between mpc and odm combine on different streams
|
||||
* causes a different pipe to be chosen to odm combine with.
|
||||
*/
|
||||
if (pipe_ctx->update_flags.bits.enable
|
||||
|| pipe_ctx->update_flags.bits.opp_changed) {
|
||||
|
||||
pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
|
||||
pipe_ctx->stream_res.opp,
|
||||
COLOR_SPACE_YCBCR601,
|
||||
pipe_ctx->stream->timing.display_color_depth,
|
||||
pipe_ctx->stream->signal);
|
||||
|
||||
pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
|
||||
pipe_ctx->stream_res.opp,
|
||||
&pipe_ctx->stream->bit_depth_params,
|
||||
&pipe_ctx->stream->clamping);
|
||||
}
|
||||
|
||||
/* Set ABM pipe after other pipe configurations done */
|
||||
if ((pipe_ctx->plane_state && pipe_ctx->plane_state->visible)) {
|
||||
if (pipe_ctx->stream_res.abm) {
|
||||
dc->hwss.set_pipe(pipe_ctx);
|
||||
pipe_ctx->stream_res.abm->funcs->set_abm_level(pipe_ctx->stream_res.abm,
|
||||
pipe_ctx->stream->abm_level);
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe_ctx->update_flags.bits.test_pattern_changed) {
|
||||
struct output_pixel_processor *odm_opp = pipe_ctx->stream_res.opp;
|
||||
struct bit_depth_reduction_params params;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
|
||||
dc->hwss.set_disp_pattern_generator(dc,
|
||||
pipe_ctx,
|
||||
pipe_ctx->stream_res.test_pattern_params.test_pattern,
|
||||
pipe_ctx->stream_res.test_pattern_params.color_space,
|
||||
pipe_ctx->stream_res.test_pattern_params.color_depth,
|
||||
NULL,
|
||||
pipe_ctx->stream_res.test_pattern_params.width,
|
||||
pipe_ctx->stream_res.test_pattern_params.height,
|
||||
pipe_ctx->stream_res.test_pattern_params.offset);
|
||||
}
|
||||
}
|
||||
|
||||
void dcn401_program_front_end_for_ctx(
|
||||
struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
unsigned int prev_hubp_count = 0;
|
||||
unsigned int hubp_count = 0;
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
struct pipe_ctx *pipe = NULL;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (resource_is_pipe_topology_changed(dc->current_state, context))
|
||||
resource_log_pipe_topology_update(dc, context);
|
||||
|
||||
if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (!pipe->top_pipe && !pipe->prev_odm_pipe && pipe->plane_state) {
|
||||
if (pipe->plane_state->triplebuffer_flips)
|
||||
BREAK_TO_DEBUGGER();
|
||||
|
||||
/*turn off triple buffer for full update*/
|
||||
dc->hwss.program_triplebuffer(
|
||||
dc, pipe, pipe->plane_state->triplebuffer_flips);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
|
||||
prev_hubp_count++;
|
||||
if (context->res_ctx.pipe_ctx[i].plane_state)
|
||||
hubp_count++;
|
||||
}
|
||||
|
||||
if (prev_hubp_count == 0 && hubp_count > 0) {
|
||||
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control(
|
||||
dc->res_pool->hubbub, true, false);
|
||||
udelay(500);
|
||||
}
|
||||
|
||||
/* Set pipe update flags and lock pipes */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
dc->hwss.detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i],
|
||||
&context->res_ctx.pipe_ctx[i]);
|
||||
|
||||
/* When disabling phantom pipes, turn on phantom OTG first (so we can get double
|
||||
* buffer updates properly)
|
||||
*/
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct dc_stream_state *stream = dc->current_state->res_ctx.pipe_ctx[i].stream;
|
||||
|
||||
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && stream &&
|
||||
dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
|
||||
struct timing_generator *tg = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg;
|
||||
|
||||
if (tg->funcs->enable_crtc) {
|
||||
if (dc->hwseq->funcs.blank_pixel_data)
|
||||
dc->hwseq->funcs.blank_pixel_data(dc, pipe, true);
|
||||
|
||||
tg->funcs->enable_crtc(tg);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* OTG blank before disabling all front ends */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
|
||||
&& !context->res_ctx.pipe_ctx[i].top_pipe
|
||||
&& !context->res_ctx.pipe_ctx[i].prev_odm_pipe
|
||||
&& context->res_ctx.pipe_ctx[i].stream)
|
||||
hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true);
|
||||
|
||||
|
||||
/* Disconnect mpcc */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
|
||||
|| context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
|
||||
struct hubbub *hubbub = dc->res_pool->hubbub;
|
||||
|
||||
/* Phantom pipe DET should be 0, but if a pipe in use is being transitioned to phantom
|
||||
* then we want to do the programming here (effectively it's being disabled). If we do
|
||||
* the programming later the DET won't be updated until the OTG for the phantom pipe is
|
||||
* turned on (i.e. in an MCLK switch) which can come in too late and cause issues with
|
||||
* DET allocation.
|
||||
*/
|
||||
if ((context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
|
||||
(context->res_ctx.pipe_ctx[i].plane_state &&
|
||||
dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) ==
|
||||
SUBVP_PHANTOM))) {
|
||||
if (hubbub->funcs->program_det_size)
|
||||
hubbub->funcs->program_det_size(hubbub,
|
||||
dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
|
||||
if (dc->res_pool->hubbub->funcs->program_det_segments)
|
||||
dc->res_pool->hubbub->funcs->program_det_segments(
|
||||
hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
|
||||
}
|
||||
hws->funcs.plane_atomic_disconnect(dc, dc->current_state,
|
||||
&dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
|
||||
}
|
||||
|
||||
/* update ODM for blanked OTG master pipes */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
!resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
pipe->update_flags.bits.odm &&
|
||||
hws->funcs.update_odm)
|
||||
hws->funcs.update_odm(dc, context, pipe);
|
||||
}
|
||||
|
||||
/*
|
||||
* Program all updated pipes, order matters for mpcc setup. Start with
|
||||
* top pipe and program all pipes that follow in order
|
||||
*/
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->plane_state && !pipe->top_pipe) {
|
||||
while (pipe) {
|
||||
if (hws->funcs.program_pipe)
|
||||
hws->funcs.program_pipe(dc, pipe, context);
|
||||
else {
|
||||
/* Don't program phantom pipes in the regular front end programming sequence.
|
||||
* There is an MPO transition case where a pipe being used by a video plane is
|
||||
* transitioned directly to be a phantom pipe when closing the MPO video.
|
||||
* However the phantom pipe will program a new HUBP_VTG_SEL (update takes place
|
||||
* right away) but the MPO still exists until the double buffered update of the
|
||||
* main pipe so we will get a frame of underflow if the phantom pipe is
|
||||
* programmed here.
|
||||
*/
|
||||
if (pipe->stream &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM)
|
||||
dcn401_program_pipe(dc, pipe, context);
|
||||
}
|
||||
|
||||
pipe = pipe->bottom_pipe;
|
||||
}
|
||||
}
|
||||
|
||||
/* Program secondary blending tree and writeback pipes */
|
||||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
if (!pipe->top_pipe && !pipe->prev_odm_pipe
|
||||
&& pipe->stream && pipe->stream->num_wb_info > 0
|
||||
&& (pipe->update_flags.raw || (pipe->plane_state && pipe->plane_state->update_flags.raw)
|
||||
|| pipe->stream->update_flags.raw)
|
||||
&& hws->funcs.program_all_writeback_pipes_in_tree)
|
||||
hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
|
||||
|
||||
/* Avoid underflow by check of pipe line read when adding 2nd plane. */
|
||||
if (hws->wa.wait_hubpret_read_start_during_mpo_transition &&
|
||||
!pipe->top_pipe &&
|
||||
pipe->stream &&
|
||||
pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start &&
|
||||
dc->current_state->stream_status[0].plane_count == 1 &&
|
||||
context->stream_status[0].plane_count > 1) {
|
||||
pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start(pipe->plane_res.hubp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dcn401_post_unlock_program_front_end(
|
||||
struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
// Timeout for pipe enable
|
||||
unsigned int timeout_us = 100000;
|
||||
unsigned int polling_interval_us = 1;
|
||||
struct dce_hwseq *hwseq = dc->hwseq;
|
||||
int i;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
|
||||
!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
|
||||
dc->hwss.post_unlock_reset_opp(dc,
|
||||
&dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
|
||||
dc->hwss.disable_plane(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
|
||||
/*
|
||||
* If we are enabling a pipe, we need to wait for pending clear as this is a critical
|
||||
* part of the enable operation otherwise, DM may request an immediate flip which
|
||||
* will cause HW to perform an "immediate enable" (as opposed to "vsync enable") which
|
||||
* is unsupported on DCN.
|
||||
*/
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
// Don't check flip pending on phantom pipes
|
||||
if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
|
||||
struct hubp *hubp = pipe->plane_res.hubp;
|
||||
int j = 0;
|
||||
|
||||
for (j = 0; j < timeout_us / polling_interval_us
|
||||
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
|
||||
udelay(polling_interval_us);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
/* When going from a smaller ODM slice count to larger, we must ensure double
|
||||
* buffer update completes before we return to ensure we don't reduce DISPCLK
|
||||
* before we've transitioned to 2:1 or 4:1
|
||||
*/
|
||||
if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
|
||||
int j = 0;
|
||||
struct timing_generator *tg = pipe->stream_res.tg;
|
||||
|
||||
if (tg->funcs->get_optc_double_buffer_pending) {
|
||||
for (j = 0; j < timeout_us / polling_interval_us
|
||||
&& tg->funcs->get_optc_double_buffer_pending(tg); j++)
|
||||
udelay(polling_interval_us);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control(
|
||||
dc->res_pool->hubbub, false, false);
|
||||
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->plane_state && !pipe->top_pipe) {
|
||||
/* Program phantom pipe here to prevent a frame of underflow in the MPO transition
|
||||
* case (if a pipe being used for a video plane transitions to a phantom pipe, it
|
||||
* can underflow due to HUBP_VTG_SEL programming if done in the regular front end
|
||||
* programming sequence).
|
||||
*/
|
||||
while (pipe) {
|
||||
if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
|
||||
/* When turning on the phantom pipe we want to run through the
|
||||
* entire enable sequence, so apply all the "enable" flags.
|
||||
*/
|
||||
if (dc->hwss.apply_update_flags_for_phantom)
|
||||
dc->hwss.apply_update_flags_for_phantom(pipe);
|
||||
if (dc->hwss.update_phantom_vp_position)
|
||||
dc->hwss.update_phantom_vp_position(dc, context, pipe);
|
||||
dcn401_program_pipe(dc, pipe, context);
|
||||
}
|
||||
pipe = pipe->bottom_pipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hwseq)
|
||||
return;
|
||||
|
||||
/* P-State support transitions:
|
||||
* Natural -> FPO: P-State disabled in prepare, force disallow anytime is safe
|
||||
* FPO -> Natural: Unforce anytime after FW disable is safe (P-State will assert naturally)
|
||||
* Unsupported -> FPO: P-State enabled in optimize, force disallow anytime is safe
|
||||
* FPO -> Unsupported: P-State disabled in prepare, unforce disallow anytime is safe
|
||||
* FPO <-> SubVP: Force disallow is maintained on the FPO / SubVP pipes
|
||||
*/
|
||||
if (hwseq->funcs.update_force_pstate)
|
||||
dc->hwseq->funcs.update_force_pstate(dc, context);
|
||||
|
||||
/* Only program the MALL registers after all the main and phantom pipes
|
||||
* are done programming.
|
||||
*/
|
||||
if (hwseq->funcs.program_mall_pipe_config)
|
||||
hwseq->funcs.program_mall_pipe_config(dc, context);
|
||||
|
||||
/* WA to apply WM setting*/
|
||||
if (hwseq->wa.DEGVIDCN21)
|
||||
dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
|
||||
|
||||
|
||||
/* WA for stutter underflow during MPO transitions when adding 2nd plane */
|
||||
if (hwseq->wa.disallow_self_refresh_during_multi_plane_transition) {
|
||||
|
||||
if (dc->current_state->stream_status[0].plane_count == 1 &&
|
||||
context->stream_status[0].plane_count > 1) {
|
||||
|
||||
struct timing_generator *tg = dc->res_pool->timing_generators[0];
|
||||
|
||||
dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, false);
|
||||
|
||||
hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = true;
|
||||
hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame =
|
||||
tg->funcs->get_frame_count(tg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool dcn401_update_bandwidth(
|
||||
struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
|
||||
/* recalculate DML parameters */
|
||||
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false))
|
||||
return false;
|
||||
|
||||
/* apply updated bandwidth parameters */
|
||||
dc->hwss.prepare_bandwidth(dc, context);
|
||||
|
||||
/* update hubp configs for all pipes */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe_ctx->plane_state == NULL)
|
||||
continue;
|
||||
|
||||
if (pipe_ctx->top_pipe == NULL) {
|
||||
bool blank = !is_pipe_tree_visible(pipe_ctx);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->program_global_sync(
|
||||
pipe_ctx->stream_res.tg,
|
||||
dcn401_calculate_vready_offset_for_group(pipe_ctx),
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vstartup_lines,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vupdate_offset_pixels,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.vupdate_vupdate_width_pixels,
|
||||
(unsigned int)pipe_ctx->global_sync.dcn4x.pstate_keepout_start_lines);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, false);
|
||||
|
||||
if (pipe_ctx->prev_odm_pipe == NULL)
|
||||
hws->funcs.blank_pixel_data(dc, pipe_ctx, blank);
|
||||
|
||||
if (hws->funcs.setup_vupdate_interrupt)
|
||||
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
|
||||
}
|
||||
|
||||
if (pipe_ctx->plane_res.hubp->funcs->hubp_setup2)
|
||||
pipe_ctx->plane_res.hubp->funcs->hubp_setup2(
|
||||
pipe_ctx->plane_res.hubp,
|
||||
&pipe_ctx->hubp_regs,
|
||||
&pipe_ctx->global_sync,
|
||||
&pipe_ctx->stream->timing);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dcn401_detect_pipe_changes(struct dc_state *old_state,
|
||||
struct dc_state *new_state,
|
||||
struct pipe_ctx *old_pipe,
|
||||
struct pipe_ctx *new_pipe)
|
||||
{
|
||||
bool old_is_phantom = dc_state_get_pipe_subvp_type(old_state, old_pipe) == SUBVP_PHANTOM;
|
||||
bool new_is_phantom = dc_state_get_pipe_subvp_type(new_state, new_pipe) == SUBVP_PHANTOM;
|
||||
|
||||
unsigned int old_pipe_vready_offset_pixels = old_pipe->global_sync.dcn4x.vready_offset_pixels;
|
||||
unsigned int new_pipe_vready_offset_pixels = new_pipe->global_sync.dcn4x.vready_offset_pixels;
|
||||
unsigned int old_pipe_vstartup_lines = old_pipe->global_sync.dcn4x.vstartup_lines;
|
||||
unsigned int new_pipe_vstartup_lines = new_pipe->global_sync.dcn4x.vstartup_lines;
|
||||
unsigned int old_pipe_vupdate_offset_pixels = old_pipe->global_sync.dcn4x.vupdate_offset_pixels;
|
||||
unsigned int new_pipe_vupdate_offset_pixels = new_pipe->global_sync.dcn4x.vupdate_offset_pixels;
|
||||
unsigned int old_pipe_vupdate_width_pixels = old_pipe->global_sync.dcn4x.vupdate_vupdate_width_pixels;
|
||||
unsigned int new_pipe_vupdate_width_pixels = new_pipe->global_sync.dcn4x.vupdate_vupdate_width_pixels;
|
||||
|
||||
new_pipe->update_flags.raw = 0;
|
||||
|
||||
/* If non-phantom pipe is being transitioned to a phantom pipe,
|
||||
* set disable and return immediately. This is because the pipe
|
||||
* that was previously in use must be fully disabled before we
|
||||
* can "enable" it as a phantom pipe (since the OTG will certainly
|
||||
* be different). The post_unlock sequence will set the correct
|
||||
* update flags to enable the phantom pipe.
|
||||
*/
|
||||
if (old_pipe->plane_state && !old_is_phantom &&
|
||||
new_pipe->plane_state && new_is_phantom) {
|
||||
new_pipe->update_flags.bits.disable = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (resource_is_pipe_type(new_pipe, OTG_MASTER) &&
|
||||
resource_is_odm_topology_changed(new_pipe, old_pipe))
|
||||
/* Detect odm changes */
|
||||
new_pipe->update_flags.bits.odm = 1;
|
||||
|
||||
/* Exit on unchanged, unused pipe */
|
||||
if (!old_pipe->plane_state && !new_pipe->plane_state)
|
||||
return;
|
||||
/* Detect pipe enable/disable */
|
||||
if (!old_pipe->plane_state && new_pipe->plane_state) {
|
||||
new_pipe->update_flags.bits.enable = 1;
|
||||
new_pipe->update_flags.bits.mpcc = 1;
|
||||
new_pipe->update_flags.bits.dppclk = 1;
|
||||
new_pipe->update_flags.bits.hubp_interdependent = 1;
|
||||
new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
|
||||
new_pipe->update_flags.bits.unbounded_req = 1;
|
||||
new_pipe->update_flags.bits.gamut_remap = 1;
|
||||
new_pipe->update_flags.bits.scaler = 1;
|
||||
new_pipe->update_flags.bits.viewport = 1;
|
||||
new_pipe->update_flags.bits.det_size = 1;
|
||||
if (new_pipe->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE &&
|
||||
new_pipe->stream_res.test_pattern_params.width != 0 &&
|
||||
new_pipe->stream_res.test_pattern_params.height != 0)
|
||||
new_pipe->update_flags.bits.test_pattern_changed = 1;
|
||||
if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) {
|
||||
new_pipe->update_flags.bits.odm = 1;
|
||||
new_pipe->update_flags.bits.global_sync = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* For SubVP we need to unconditionally enable because any phantom pipes are
|
||||
* always removed then newly added for every full updates whenever SubVP is in use.
|
||||
* The remove-add sequence of the phantom pipe always results in the pipe
|
||||
* being blanked in enable_stream_timing (DPG).
|
||||
*/
|
||||
if (new_pipe->stream && dc_state_get_pipe_subvp_type(new_state, new_pipe) == SUBVP_PHANTOM)
|
||||
new_pipe->update_flags.bits.enable = 1;
|
||||
|
||||
/* Phantom pipes are effectively disabled, if the pipe was previously phantom
|
||||
* we have to enable
|
||||
*/
|
||||
if (old_pipe->plane_state && old_is_phantom &&
|
||||
new_pipe->plane_state && !new_is_phantom)
|
||||
new_pipe->update_flags.bits.enable = 1;
|
||||
|
||||
if (old_pipe->plane_state && !new_pipe->plane_state) {
|
||||
new_pipe->update_flags.bits.disable = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Detect plane change */
|
||||
if (old_pipe->plane_state != new_pipe->plane_state)
|
||||
new_pipe->update_flags.bits.plane_changed = true;
|
||||
|
||||
/* Detect top pipe only changes */
|
||||
if (resource_is_pipe_type(new_pipe, OTG_MASTER)) {
|
||||
/* Detect global sync changes */
|
||||
if ((old_pipe_vready_offset_pixels != new_pipe_vready_offset_pixels)
|
||||
|| (old_pipe_vstartup_lines != new_pipe_vstartup_lines)
|
||||
|| (old_pipe_vupdate_offset_pixels != new_pipe_vupdate_offset_pixels)
|
||||
|| (old_pipe_vupdate_width_pixels != new_pipe_vupdate_width_pixels))
|
||||
new_pipe->update_flags.bits.global_sync = 1;
|
||||
}
|
||||
|
||||
if (old_pipe->det_buffer_size_kb != new_pipe->det_buffer_size_kb)
|
||||
new_pipe->update_flags.bits.det_size = 1;
|
||||
|
||||
/*
|
||||
* Detect opp / tg change, only set on change, not on enable
|
||||
* Assume mpcc inst = pipe index, if not this code needs to be updated
|
||||
* since mpcc is what is affected by these. In fact all of our sequence
|
||||
* makes this assumption at the moment with how hubp reset is matched to
|
||||
* same index mpcc reset.
|
||||
*/
|
||||
if (old_pipe->stream_res.opp != new_pipe->stream_res.opp)
|
||||
new_pipe->update_flags.bits.opp_changed = 1;
|
||||
if (old_pipe->stream_res.tg != new_pipe->stream_res.tg)
|
||||
new_pipe->update_flags.bits.tg_changed = 1;
|
||||
|
||||
/*
|
||||
* Detect mpcc blending changes, only dpp inst and opp matter here,
|
||||
* mpccs getting removed/inserted update connected ones during their own
|
||||
* programming
|
||||
*/
|
||||
if (old_pipe->plane_res.dpp != new_pipe->plane_res.dpp
|
||||
|| old_pipe->stream_res.opp != new_pipe->stream_res.opp)
|
||||
new_pipe->update_flags.bits.mpcc = 1;
|
||||
|
||||
/* Detect dppclk change */
|
||||
if (old_pipe->plane_res.bw.dppclk_khz != new_pipe->plane_res.bw.dppclk_khz)
|
||||
new_pipe->update_flags.bits.dppclk = 1;
|
||||
|
||||
/* Check for scl update */
|
||||
if (memcmp(&old_pipe->plane_res.scl_data, &new_pipe->plane_res.scl_data, sizeof(struct scaler_data)))
|
||||
new_pipe->update_flags.bits.scaler = 1;
|
||||
/* Check for vp update */
|
||||
if (memcmp(&old_pipe->plane_res.scl_data.viewport, &new_pipe->plane_res.scl_data.viewport, sizeof(struct rect))
|
||||
|| memcmp(&old_pipe->plane_res.scl_data.viewport_c,
|
||||
&new_pipe->plane_res.scl_data.viewport_c, sizeof(struct rect)))
|
||||
new_pipe->update_flags.bits.viewport = 1;
|
||||
|
||||
/* Detect dlg/ttu/rq updates */
|
||||
{
|
||||
struct dml2_display_dlg_regs old_dlg_regs = old_pipe->hubp_regs.dlg_regs;
|
||||
struct dml2_display_ttu_regs old_ttu_regs = old_pipe->hubp_regs.ttu_regs;
|
||||
struct dml2_display_rq_regs old_rq_regs = old_pipe->hubp_regs.rq_regs;
|
||||
struct dml2_display_dlg_regs *new_dlg_regs = &new_pipe->hubp_regs.dlg_regs;
|
||||
struct dml2_display_ttu_regs *new_ttu_regs = &new_pipe->hubp_regs.ttu_regs;
|
||||
struct dml2_display_rq_regs *new_rq_regs = &new_pipe->hubp_regs.rq_regs;
|
||||
|
||||
/* Detect pipe interdependent updates */
|
||||
if ((old_dlg_regs.dst_y_prefetch != new_dlg_regs->dst_y_prefetch)
|
||||
|| (old_dlg_regs.vratio_prefetch != new_dlg_regs->vratio_prefetch)
|
||||
|| (old_dlg_regs.vratio_prefetch_c != new_dlg_regs->vratio_prefetch_c)
|
||||
|| (old_dlg_regs.dst_y_per_vm_vblank != new_dlg_regs->dst_y_per_vm_vblank)
|
||||
|| (old_dlg_regs.dst_y_per_row_vblank != new_dlg_regs->dst_y_per_row_vblank)
|
||||
|| (old_dlg_regs.dst_y_per_vm_flip != new_dlg_regs->dst_y_per_vm_flip)
|
||||
|| (old_dlg_regs.dst_y_per_row_flip != new_dlg_regs->dst_y_per_row_flip)
|
||||
|| (old_dlg_regs.refcyc_per_meta_chunk_vblank_l != new_dlg_regs->refcyc_per_meta_chunk_vblank_l)
|
||||
|| (old_dlg_regs.refcyc_per_meta_chunk_vblank_c != new_dlg_regs->refcyc_per_meta_chunk_vblank_c)
|
||||
|| (old_dlg_regs.refcyc_per_meta_chunk_flip_l != new_dlg_regs->refcyc_per_meta_chunk_flip_l)
|
||||
|| (old_dlg_regs.refcyc_per_line_delivery_pre_l != new_dlg_regs->refcyc_per_line_delivery_pre_l)
|
||||
|| (old_dlg_regs.refcyc_per_line_delivery_pre_c != new_dlg_regs->refcyc_per_line_delivery_pre_c)
|
||||
|| (old_ttu_regs.refcyc_per_req_delivery_pre_l != new_ttu_regs->refcyc_per_req_delivery_pre_l)
|
||||
|| (old_ttu_regs.refcyc_per_req_delivery_pre_c != new_ttu_regs->refcyc_per_req_delivery_pre_c)
|
||||
|| (old_ttu_regs.refcyc_per_req_delivery_pre_cur0 !=
|
||||
new_ttu_regs->refcyc_per_req_delivery_pre_cur0)
|
||||
|| (old_ttu_regs.min_ttu_vblank != new_ttu_regs->min_ttu_vblank)
|
||||
|| (old_ttu_regs.qos_level_flip != new_ttu_regs->qos_level_flip)) {
|
||||
old_dlg_regs.dst_y_prefetch = new_dlg_regs->dst_y_prefetch;
|
||||
old_dlg_regs.vratio_prefetch = new_dlg_regs->vratio_prefetch;
|
||||
old_dlg_regs.vratio_prefetch_c = new_dlg_regs->vratio_prefetch_c;
|
||||
old_dlg_regs.dst_y_per_vm_vblank = new_dlg_regs->dst_y_per_vm_vblank;
|
||||
old_dlg_regs.dst_y_per_row_vblank = new_dlg_regs->dst_y_per_row_vblank;
|
||||
old_dlg_regs.dst_y_per_vm_flip = new_dlg_regs->dst_y_per_vm_flip;
|
||||
old_dlg_regs.dst_y_per_row_flip = new_dlg_regs->dst_y_per_row_flip;
|
||||
old_dlg_regs.refcyc_per_meta_chunk_vblank_l = new_dlg_regs->refcyc_per_meta_chunk_vblank_l;
|
||||
old_dlg_regs.refcyc_per_meta_chunk_vblank_c = new_dlg_regs->refcyc_per_meta_chunk_vblank_c;
|
||||
old_dlg_regs.refcyc_per_meta_chunk_flip_l = new_dlg_regs->refcyc_per_meta_chunk_flip_l;
|
||||
old_dlg_regs.refcyc_per_line_delivery_pre_l = new_dlg_regs->refcyc_per_line_delivery_pre_l;
|
||||
old_dlg_regs.refcyc_per_line_delivery_pre_c = new_dlg_regs->refcyc_per_line_delivery_pre_c;
|
||||
old_ttu_regs.refcyc_per_req_delivery_pre_l = new_ttu_regs->refcyc_per_req_delivery_pre_l;
|
||||
old_ttu_regs.refcyc_per_req_delivery_pre_c = new_ttu_regs->refcyc_per_req_delivery_pre_c;
|
||||
old_ttu_regs.refcyc_per_req_delivery_pre_cur0 = new_ttu_regs->refcyc_per_req_delivery_pre_cur0;
|
||||
old_ttu_regs.min_ttu_vblank = new_ttu_regs->min_ttu_vblank;
|
||||
old_ttu_regs.qos_level_flip = new_ttu_regs->qos_level_flip;
|
||||
new_pipe->update_flags.bits.hubp_interdependent = 1;
|
||||
}
|
||||
/* Detect any other updates to ttu/rq/dlg */
|
||||
if (memcmp(&old_dlg_regs, new_dlg_regs, sizeof(old_dlg_regs)) ||
|
||||
memcmp(&old_ttu_regs, new_ttu_regs, sizeof(old_ttu_regs)) ||
|
||||
memcmp(&old_rq_regs, new_rq_regs, sizeof(old_rq_regs)))
|
||||
new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
|
||||
}
|
||||
|
||||
if (old_pipe->unbounded_req != new_pipe->unbounded_req)
|
||||
new_pipe->update_flags.bits.unbounded_req = 1;
|
||||
|
||||
if (memcmp(&old_pipe->stream_res.test_pattern_params,
|
||||
&new_pipe->stream_res.test_pattern_params, sizeof(struct test_pattern_params))) {
|
||||
new_pipe->update_flags.bits.test_pattern_changed = 1;
|
||||
}
|
||||
}
|
||||
|
@ -96,5 +96,12 @@ void dcn401_reset_hw_ctx_wrap(
|
||||
struct dc *dc,
|
||||
struct dc_state *context);
|
||||
void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx);
|
||||
|
||||
void dcn401_program_front_end_for_ctx(struct dc *dc, struct dc_state *context);
|
||||
void dcn401_post_unlock_program_front_end(struct dc *dc, struct dc_state *context);
|
||||
bool dcn401_update_bandwidth(struct dc *dc, struct dc_state *context);
|
||||
void dcn401_detect_pipe_changes(
|
||||
struct dc_state *old_state,
|
||||
struct dc_state *new_state,
|
||||
struct pipe_ctx *old_pipe,
|
||||
struct pipe_ctx *new_pipe);
|
||||
#endif /* __DC_HWSS_DCN401_H__ */
|
||||
|
@ -17,9 +17,9 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
|
||||
.init_hw = dcn401_init_hw,
|
||||
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
||||
.apply_ctx_for_surface = NULL,
|
||||
.program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
|
||||
.program_front_end_for_ctx = dcn401_program_front_end_for_ctx,
|
||||
.wait_for_pending_cleared = dcn10_wait_for_pending_cleared,
|
||||
.post_unlock_program_front_end = dcn20_post_unlock_program_front_end,
|
||||
.post_unlock_program_front_end = dcn401_post_unlock_program_front_end,
|
||||
.update_plane_addr = dcn20_update_plane_addr,
|
||||
.update_dchub = dcn10_update_dchub,
|
||||
.update_pending_status = dcn10_update_pending_status,
|
||||
@ -42,7 +42,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
|
||||
.cursor_lock = dcn10_cursor_lock,
|
||||
.prepare_bandwidth = dcn401_prepare_bandwidth,
|
||||
.optimize_bandwidth = dcn401_optimize_bandwidth,
|
||||
.update_bandwidth = dcn20_update_bandwidth,
|
||||
.update_bandwidth = dcn401_update_bandwidth,
|
||||
.set_drr = dcn10_set_drr,
|
||||
.get_position = dcn10_get_position,
|
||||
.set_static_screen_control = dcn31_set_static_screen_control,
|
||||
@ -99,6 +99,10 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
|
||||
.fams2_global_control_lock_fast = dcn401_fams2_global_control_lock_fast,
|
||||
.program_outstanding_updates = dcn401_program_outstanding_updates,
|
||||
.wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
|
||||
.detect_pipe_changes = dcn401_detect_pipe_changes,
|
||||
.enable_plane = dcn20_enable_plane,
|
||||
.update_dchubp_dpp = dcn20_update_dchubp_dpp,
|
||||
.post_unlock_reset_opp = dcn20_post_unlock_reset_opp,
|
||||
};
|
||||
|
||||
static const struct hwseq_private_funcs dcn401_private_funcs = {
|
||||
|
@ -457,6 +457,18 @@ struct hw_sequencer_funcs {
|
||||
struct dc_state *context);
|
||||
void (*setup_hpo_hw_control)(const struct dce_hwseq *hws, bool enable);
|
||||
void (*wait_for_all_pending_updates)(const struct pipe_ctx *pipe_ctx);
|
||||
void (*detect_pipe_changes)(struct dc_state *old_state,
|
||||
struct dc_state *new_state,
|
||||
struct pipe_ctx *old_pipe,
|
||||
struct pipe_ctx *new_pipe);
|
||||
void (*enable_plane)(struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context);
|
||||
void (*update_dchubp_dpp)(struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context);
|
||||
void (*post_unlock_reset_opp)(struct dc *dc,
|
||||
struct pipe_ctx *opp_head);
|
||||
};
|
||||
|
||||
void color_space_to_black_color(
|
||||
|
@ -217,6 +217,7 @@ struct resource_funcs {
|
||||
*/
|
||||
int (*get_power_profile)(const struct dc_state *context);
|
||||
unsigned int (*get_det_buffer_size)(const struct dc_state *context);
|
||||
unsigned int (*get_vstartup_for_pipe)(struct pipe_ctx *pipe_ctx);
|
||||
};
|
||||
|
||||
struct audio_support{
|
||||
@ -465,6 +466,7 @@ struct pipe_ctx {
|
||||
unsigned int surface_size_in_mall_bytes;
|
||||
struct dml2_dchub_per_pipe_register_set hubp_regs;
|
||||
struct dml2_hubp_pipe_mcache_regs mcache_regs;
|
||||
union dml2_global_sync_programming global_sync;
|
||||
|
||||
struct dwbc *dwbc;
|
||||
struct mcif_wb *mcif_wb;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "cursor_reg_cache.h"
|
||||
|
||||
#include "dml2/dml21/inc/dml_top_dchub_registers.h"
|
||||
#include "dml2/dml21/inc/dml_top_types.h"
|
||||
|
||||
#define OPP_ID_INVALID 0xf
|
||||
#define MAX_TTU 0xffffff
|
||||
@ -144,11 +145,21 @@ struct hubp_funcs {
|
||||
struct _vcs_dpi_display_rq_regs_st *rq_regs,
|
||||
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
|
||||
|
||||
void (*hubp_setup2)(
|
||||
struct hubp *hubp,
|
||||
struct dml2_dchub_per_pipe_register_set *pipe_regs,
|
||||
union dml2_global_sync_programming *pipe_global_sync,
|
||||
struct dc_crtc_timing *timing);
|
||||
|
||||
void (*hubp_setup_interdependent)(
|
||||
struct hubp *hubp,
|
||||
struct _vcs_dpi_display_dlg_regs_st *dlg_regs,
|
||||
struct _vcs_dpi_display_ttu_regs_st *ttu_regs);
|
||||
|
||||
void (*hubp_setup_interdependent2)(
|
||||
struct hubp *hubp,
|
||||
struct dml2_dchub_per_pipe_register_set *pipe_regs);
|
||||
|
||||
void (*dcc_control)(struct hubp *hubp, bool enable,
|
||||
enum hubp_ind_block_size blk_size);
|
||||
|
||||
|
@ -302,7 +302,6 @@ void optc1_program_timing(
|
||||
/* Enable stereo - only when we need to pack 3D frame. Other types
|
||||
* of stereo handled in explicit call
|
||||
*/
|
||||
|
||||
if (optc->funcs->is_two_pixels_per_container(&patched_crtc_timing) || optc1->opp_count == 2)
|
||||
h_div = H_TIMING_DIV_BY2;
|
||||
|
||||
|
@ -1258,6 +1258,11 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int dcn10_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
return pipe_ctx->pipe_dlg_param.vstartup_start;
|
||||
}
|
||||
|
||||
static const struct dc_cap_funcs cap_funcs = {
|
||||
.get_dcc_compression_cap = dcn10_get_dcc_compression_cap
|
||||
};
|
||||
@ -1272,7 +1277,8 @@ static const struct resource_funcs dcn10_res_pool_funcs = {
|
||||
.validate_global = dcn10_validate_global,
|
||||
.add_stream_to_ctx = dcn10_add_stream_to_ctx,
|
||||
.patch_unknown_plane_state = dcn10_patch_unknown_plane_state,
|
||||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link
|
||||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static uint32_t read_pipe_fuses(struct dc_context *ctx)
|
||||
|
@ -51,6 +51,7 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link(
|
||||
const struct resource_pool *pool,
|
||||
struct dc_stream_state *stream);
|
||||
|
||||
unsigned int dcn10_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx);
|
||||
|
||||
#endif /* __DC_RESOURCE_DCN10_H__ */
|
||||
|
||||
|
@ -2229,7 +2229,8 @@ static const struct resource_funcs dcn20_res_pool_funcs = {
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
|
||||
.populate_dml_pipes = dcn20_populate_dml_pipes_from_context,
|
||||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link
|
||||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
|
||||
|
@ -1079,7 +1079,8 @@ static struct resource_funcs dcn201_res_pool_funcs = {
|
||||
.populate_dml_writeback_from_context = dcn201_populate_dml_writeback_from_context,
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
|
||||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link
|
||||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static bool dcn201_resource_construct(
|
||||
|
@ -1378,6 +1378,7 @@ static const struct resource_funcs dcn21_res_pool_funcs = {
|
||||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
|
||||
.update_bw_bounding_box = dcn21_update_bw_bounding_box,
|
||||
.get_panel_config_defaults = dcn21_get_panel_config_defaults,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static bool dcn21_resource_construct(
|
||||
|
@ -2250,6 +2250,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = {
|
||||
.update_bw_bounding_box = dcn30_update_bw_bounding_box,
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.get_panel_config_defaults = dcn30_get_panel_config_defaults,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
#define CTX ctx
|
||||
|
@ -1400,7 +1400,8 @@ static struct resource_funcs dcn301_res_pool_funcs = {
|
||||
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
|
||||
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
|
||||
.update_bw_bounding_box = dcn301_update_bw_bounding_box,
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static bool dcn301_resource_construct(
|
||||
|
@ -1151,6 +1151,7 @@ static struct resource_funcs dcn302_res_pool_funcs = {
|
||||
.update_bw_bounding_box = dcn302_update_bw_bounding_box,
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.get_panel_config_defaults = dcn302_get_panel_config_defaults,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static struct dc_cap_funcs cap_funcs = {
|
||||
|
@ -1096,6 +1096,7 @@ static struct resource_funcs dcn303_res_pool_funcs = {
|
||||
.update_bw_bounding_box = dcn303_update_bw_bounding_box,
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.get_panel_config_defaults = dcn303_get_panel_config_defaults,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static struct dc_cap_funcs cap_funcs = {
|
||||
|
@ -1849,6 +1849,7 @@ static struct resource_funcs dcn31_res_pool_funcs = {
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.get_panel_config_defaults = dcn31_get_panel_config_defaults,
|
||||
.get_det_buffer_size = dcn31_get_det_buffer_size,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static struct clock_source *dcn30_clock_source_create(
|
||||
|
@ -1778,6 +1778,7 @@ static struct resource_funcs dcn314_res_pool_funcs = {
|
||||
.get_panel_config_defaults = dcn314_get_panel_config_defaults,
|
||||
.get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia,
|
||||
.get_det_buffer_size = dcn31_get_det_buffer_size,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static struct clock_source *dcn30_clock_source_create(
|
||||
|
@ -1846,6 +1846,7 @@ static struct resource_funcs dcn315_res_pool_funcs = {
|
||||
.get_panel_config_defaults = dcn315_get_panel_config_defaults,
|
||||
.get_power_profile = dcn315_get_power_profile,
|
||||
.get_det_buffer_size = dcn31_get_det_buffer_size,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static bool dcn315_resource_construct(
|
||||
|
@ -1720,6 +1720,7 @@ static struct resource_funcs dcn316_res_pool_funcs = {
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.get_panel_config_defaults = dcn316_get_panel_config_defaults,
|
||||
.get_det_buffer_size = dcn31_get_det_buffer_size,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static bool dcn316_resource_construct(
|
||||
|
@ -2066,6 +2066,7 @@ static struct resource_funcs dcn32_res_pool_funcs = {
|
||||
.add_phantom_pipes = dcn32_add_phantom_pipes,
|
||||
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
|
||||
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static uint32_t read_pipe_fuses(struct dc_context *ctx)
|
||||
|
@ -1624,6 +1624,7 @@ static struct resource_funcs dcn321_res_pool_funcs = {
|
||||
.add_phantom_pipes = dcn32_add_phantom_pipes,
|
||||
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
|
||||
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static uint32_t read_pipe_fuses(struct dc_context *ctx)
|
||||
|
@ -1786,6 +1786,7 @@ static struct resource_funcs dcn35_res_pool_funcs = {
|
||||
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
|
||||
.get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia,
|
||||
.get_det_buffer_size = dcn31_get_det_buffer_size,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static bool dcn35_resource_construct(
|
||||
|
@ -1758,6 +1758,7 @@ static struct resource_funcs dcn351_res_pool_funcs = {
|
||||
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
|
||||
.get_preferred_eng_id_dpia = dcn351_get_preferred_eng_id_dpia,
|
||||
.get_det_buffer_size = dcn31_get_det_buffer_size,
|
||||
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static bool dcn351_resource_construct(
|
||||
|
@ -1709,6 +1709,11 @@ static int dcn401_get_power_profile(const struct dc_state *context)
|
||||
return dpm_level;
|
||||
}
|
||||
|
||||
static unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
return pipe_ctx->global_sync.dcn4x.vstartup_lines;
|
||||
}
|
||||
|
||||
static unsigned int dcn401_calc_num_avail_chans_for_mall(struct dc *dc, unsigned int num_chans)
|
||||
{
|
||||
unsigned int num_available_chans = 1;
|
||||
@ -1759,6 +1764,7 @@ static struct resource_funcs dcn401_res_pool_funcs = {
|
||||
.build_pipe_pix_clk_params = dcn401_build_pipe_pix_clk_params,
|
||||
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
|
||||
.get_power_profile = dcn401_get_power_profile,
|
||||
.get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe
|
||||
};
|
||||
|
||||
static uint32_t read_pipe_fuses(struct dc_context *ctx)
|
||||
|
Loading…
Reference in New Issue
Block a user