/* * Copyright 2016 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 *
*/ #include <linux/delay.h>
staticint find_free_gsl_group(conststruct dc *dc)
{ if (dc->res_pool->gsl_groups.gsl_0 == 0) return 1; if (dc->res_pool->gsl_groups.gsl_1 == 0) return 2; if (dc->res_pool->gsl_groups.gsl_2 == 0) return 3;
return 0;
}
/* NOTE: This is not a generic setup_gsl function (hence the suffix as_lock) * This is only used to lock pipes in pipe splitting case with immediate flip * Ordinary MPC/OTG locks suppress VUPDATE which doesn't help with immediate, * so we get tearing with freesync since we cannot flip multiple pipes * atomically. * We use GSL for this: * - immediate flip: find first available GSL group if not already assigned * program gsl with that group, set current OTG as master * and always us 0x4 = AND of flip_ready from all pipes * - vsync flip: disable GSL if used * * Groups in stream_res are stored as +1 from HW registers, i.e. * gsl_0 <=> pipe_ctx->stream_res.gsl_group == 1 * Using a magic value like -1 would require tracking all inits/resets
*/ void dcn20_setup_gsl_group_as_lock( conststruct dc *dc, struct pipe_ctx *pipe_ctx, bool enable)
{ struct gsl_params gsl; int group_idx;
memset(&gsl, 0, sizeof(struct gsl_params));
if (enable) { /* return if group already assigned since GSL was set up * for vsync flip, we would unassign so it can't be "left over"
*/ if (pipe_ctx->stream_res.gsl_group > 0) return;
/* set gsl group reg field and mark resource used */ switch (group_idx) { case 1:
gsl.gsl0_en = 1;
dc->res_pool->gsl_groups.gsl_0 = 1; break; case 2:
gsl.gsl1_en = 1;
dc->res_pool->gsl_groups.gsl_1 = 1; break; case 3:
gsl.gsl2_en = 1;
dc->res_pool->gsl_groups.gsl_2 = 1; break; default:
BREAK_TO_DEBUGGER(); return; // invalid case
}
gsl.gsl_master_en = 1;
} else {
group_idx = pipe_ctx->stream_res.gsl_group; if (group_idx == 0) return; // if not in use, just return
pipe_ctx->stream_res.gsl_group = 0;
/* unset gsl group reg field and mark resource free */ switch (group_idx) { case 1:
gsl.gsl0_en = 0;
dc->res_pool->gsl_groups.gsl_0 = 0; break; case 2:
gsl.gsl1_en = 0;
dc->res_pool->gsl_groups.gsl_1 = 0; break; case 3:
gsl.gsl2_en = 0;
dc->res_pool->gsl_groups.gsl_2 = 0; break; default:
BREAK_TO_DEBUGGER(); return;
}
gsl.gsl_master_en = 0;
}
/* at this point we want to program whether it's to enable or disable */ if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL) {
pipe_ctx->stream_res.tg->funcs->set_gsl(
pipe_ctx->stream_res.tg,
&gsl); if (pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL)
pipe_ctx->stream_res.tg->funcs->set_gsl_source_select(
pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0);
} else
BREAK_TO_DEBUGGER();
}
/* program opp dpg blank color */
color_space = COLOR_SPACE_SRGB;
color_space_to_black_color(dc, color_space, &black_color);
/* get the OTG active size */
tg->funcs->get_otg_active_size(tg,
&otg_active_width,
&otg_active_height);
/* get the OPTC source */
tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
if (opp_id_src0 >= dc->res_pool->res_cap->num_opp) {
ASSERT(false); return;
}
opp = dc->res_pool->opps[opp_id_src0];
/* don't override the blank pattern if already enabled with the correct one. */ if (opp->funcs->dpg_is_blanked && opp->funcs->dpg_is_blanked(opp)) return;
if (num_opps == 2) {
otg_active_width = otg_active_width / 2;
REG_WAIT(DOMAIN9_PG_STATUS,
DOMAIN9_PGFSM_PWR_STATUS, pwr_status,
1, 1000); break; case 5: /* DPP5 */ /* * Do not power gate DPP5, should be left at HW default, power on permanently. * PG on Pipe5 is De-featured, attempting to put it to PG state may result in hard * reset. * REG_UPDATE(DOMAIN11_PG_CONFIG, * DOMAIN11_POWER_GATE, power_gate); * * REG_WAIT(DOMAIN11_PG_STATUS, * DOMAIN11_PGFSM_PWR_STATUS, pwr_status, * 1, 1000);
*/ break; default:
BREAK_TO_DEBUGGER(); break;
}
}
REG_WAIT(DOMAIN8_PG_STATUS,
DOMAIN8_PGFSM_PWR_STATUS, pwr_status,
1, 1000); break; case 5: /* DCHUBP5 */ /* * Do not power gate DCHUB5, should be left at HW default, power on permanently. * PG on Pipe5 is De-featured, attempting to put it to PG state may result in hard * reset. * REG_UPDATE(DOMAIN10_PG_CONFIG, * DOMAIN10_POWER_GATE, power_gate); * * REG_WAIT(DOMAIN10_PG_STATUS, * DOMAIN10_PGFSM_PWR_STATUS, pwr_status, * 1, 1000);
*/ break; default:
BREAK_TO_DEBUGGER(); break;
}
}
/* disable HW used by plane. * note: cannot disable until disconnect is complete
*/ void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
{ struct dce_hwseq *hws = dc->hwseq; struct hubp *hubp = pipe_ctx->plane_res.hubp; struct dpp *dpp = pipe_ctx->plane_res.dpp;
/* In flip immediate with pipe splitting case GSL is used for * synchronization so we must disable it when the plane is disabled.
*/ if (pipe_ctx->stream_res.gsl_group != 0)
dcn20_setup_gsl_group_as_lock(dc, pipe_ctx, false);
if (hubp->funcs->hubp_update_mall_sel)
hubp->funcs->hubp_update_mall_sel(hubp, 0, false);
if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated) return;
dcn20_plane_atomic_disable(dc, pipe_ctx);
/* Turn back off the phantom OTG after the phantom plane is fully disabled
*/ if (is_phantom) if (tg && tg->funcs->disable_phantom_crtc)
tg->funcs->disable_phantom_crtc(tg);
DC_LOG_DC("Power down front end %d\n",
pipe_ctx->pipe_idx);
}
if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
dc->res_pool->dccg->funcs->set_pixel_rate_div(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
pipe_ctx->pixel_rate_divider.div_factor1,
pipe_ctx->pixel_rate_divider.div_factor2);
/* by upper caller loop, pipe0 is parent pipe and be called first. * back end is set up by for pipe0. Other children pipe share back end * with pipe 0. No program is needed.
*/ if (pipe_ctx->top_pipe != NULL) return DC_OK;
/* TODO check if timing_changed, disable stream if timing changed */
opp_cnt = resource_get_opp_heads_for_otg_master(pipe_ctx, &context->res_ctx, opp_heads); for (i = 0; i < opp_cnt; i++)
opp_inst[i] = opp_heads[i]->stream_res.opp->inst;
rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
flow_control.flow_ctrl_mode = 0;
flow_control.flow_ctrl_cnt0 = 0x80;
flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt,
is_two_pixels_per_container); if (mpc->funcs->set_out_rate_control) { for (i = 0; i < opp_cnt; ++i) {
mpc->funcs->set_out_rate_control(
mpc, opp_inst[i], true,
rate_control_2x_pclk,
&flow_control);
}
}
for (i = 0; i < opp_cnt; i++) {
opp_heads[i]->stream_res.opp->funcs->opp_pipe_clock_control(
opp_heads[i]->stream_res.opp, true);
opp_heads[i]->stream_res.opp->funcs->opp_program_left_edge_extra_pixel(
opp_heads[i]->stream_res.opp,
stream->timing.pixel_encoding,
resource_is_pipe_type(opp_heads[i], OTG_MASTER));
}
hws->funcs.blank_pixel_data(dc, pipe_ctx, true);
/* VTG is within DCHUB command block. DCFCLK is always on */ if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED;
}
// DRR should set trigger event to monitor surface update event if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
event_triggers = 0x80; /* Event triggers and num frames initialized for DRR, but can be * later updated for PSR use. Note DRR trigger events are generated * regardless of whether num frames met.
*/ if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
pipe_ctx->stream_res.tg, event_triggers, 2);
/* TODO program crtc source select for non-virtual signal*/ /* TODO program FMT */ /* TODO setup link_enc */ /* TODO set stream attributes */ /* TODO program audio */ /* TODO enable stream if timing changed */ /* TODO unblank stream if DP */
if (dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) { if (pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable)
pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg);
}
return DC_OK;
}
void dcn20_program_output_csc(struct dc *dc, struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace,
uint16_t *matrix, int opp_id)
{ struct mpc *mpc = dc->res_pool->mpc; enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A; int mpcc_id = pipe_ctx->plane_res.hubp->inst;
if (mpc->funcs->power_on_mpc_mem_pwr)
mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { if (mpc->funcs->set_output_csc != NULL)
mpc->funcs->set_output_csc(mpc,
opp_id,
matrix,
ocsc_mode);
} else { if (mpc->funcs->set_ocsc_default != NULL)
mpc->funcs->set_ocsc_default(mpc,
opp_id,
colorspace,
ocsc_mode);
}
}
bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, conststruct dc_stream_state *stream)
{ int mpcc_id = pipe_ctx->plane_res.hubp->inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; conststruct pwl_params *params = NULL; /* * program OGAM only for the top pipe * if there is a pipe split then fix diagnostic is required: * how to pass OGAM parameter for stream. * if programming for all pipes is required then remove condition * pipe_ctx->top_pipe == NULL ,but then fix the diagnostic.
*/ if (mpc->funcs->power_on_mpc_mem_pwr)
mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true); if (pipe_ctx->top_pipe == NULL
&& mpc->funcs->set_output_gamma) { if (stream->out_transfer_func.type == TF_TYPE_HWPWL)
params = &stream->out_transfer_func.pwl; elseif (pipe_ctx->stream->out_transfer_func.type ==
TF_TYPE_DISTRIBUTED_POINTS &&
cm_helper_translate_curve_to_hw_format(dc->ctx,
&stream->out_transfer_func,
&mpc->blender_params, false))
params = &mpc->blender_params; /* * there is no ROM
*/ if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED)
BREAK_TO_DEBUGGER();
} /* * if above if is not executed then 'params' equal to 0 and set in bypass
*/ if (mpc->funcs->set_output_gamma)
mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
result = dpp_base->funcs->dpp_program_shaper_lut(dpp_base, shaper_lut); if (plane_state->lut3d_func.state.bits.initialized == 1)
result = dpp_base->funcs->dpp_program_3dlut(dpp_base,
&plane_state->lut3d_func.lut_3d); else
result = dpp_base->funcs->dpp_program_3dlut(dpp_base, NULL);
if (use_degamma_ram == true) { if (tf->type == TF_TYPE_HWPWL)
dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
&tf->pwl); elseif (tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
cm_helper_translate_curve_to_degamma_hw_format(tf,
&dpp_base->degamma_params);
dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
&dpp_base->degamma_params);
} returntrue;
} /* handle here the optimized cases when de-gamma ROM could be used. *
*/ if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB:
dpp_base->funcs->dpp_set_degamma(dpp_base,
IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709:
dpp_base->funcs->dpp_set_degamma(dpp_base,
IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR:
dpp_base->funcs->dpp_set_degamma(dpp_base,
IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ:
dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_USER_PWL);
cm_helper_translate_curve_to_degamma_hw_format(tf, &dpp_base->degamma_params);
dpp_base->funcs->dpp_program_degamma_pwl(dpp_base, &dpp_base->degamma_params);
result = true; break; default:
result = false; break;
}
} elseif (tf->type == TF_TYPE_BYPASS)
dpp_base->funcs->dpp_set_degamma(dpp_base,
IPP_DEGAMMA_MODE_BYPASS); else { /* * if we are here, we did not handle correctly. * fix is required for this use case
*/
BREAK_TO_DEBUGGER();
dpp_base->funcs->dpp_set_degamma(dpp_base,
IPP_DEGAMMA_MODE_BYPASS);
}
return result;
}
void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{ struct pipe_ctx *odm_pipe; int opp_cnt = 1; int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst }; int odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, false); int last_odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, true);
/* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock
*/ if (!pipe || pipe->top_pipe) return;
if (pipe->plane_state != NULL)
flip_immediate = pipe->plane_state->flip_immediate;
if (pipe->stream_res.gsl_group > 0) {
temp_pipe = pipe->bottom_pipe; while (!flip_immediate && temp_pipe) { if (temp_pipe->plane_state != NULL)
flip_immediate = temp_pipe->plane_state->flip_immediate;
temp_pipe = temp_pipe->bottom_pipe;
}
}
if (flip_immediate && lock) { constint TIMEOUT_FOR_FLIP_PENDING_US = 100000; unsignedint polling_interval_us = 1; int i;
temp_pipe = pipe; while (temp_pipe) { if (temp_pipe->plane_state && temp_pipe->plane_state->flip_immediate) { for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING_US / polling_interval_us; ++i) { if (!temp_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(temp_pipe->plane_res.hubp)) break;
udelay(polling_interval_us);
}
/* no reason it should take this long for immediate flips */
ASSERT(i != TIMEOUT_FOR_FLIP_PENDING_US);
}
temp_pipe = temp_pipe->bottom_pipe;
}
}
/* In flip immediate and pipe splitting case, we need to use GSL * for synchronization. Only do setup on locking and on flip type change.
*/ if (lock && (pipe->bottom_pipe != NULL || !flip_immediate)) if ((flip_immediate && pipe->stream_res.gsl_group == 0) ||
(!flip_immediate && pipe->stream_res.gsl_group > 0))
dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
if (pipe->plane_state != NULL)
flip_immediate = pipe->plane_state->flip_immediate;
temp_pipe = pipe->bottom_pipe; while (flip_immediate && temp_pipe) { if (temp_pipe->plane_state != NULL)
flip_immediate = temp_pipe->plane_state->flip_immediate;
temp_pipe = temp_pipe->bottom_pipe;
}
/* 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;
}
/* 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 top pipe only changes */ if (resource_is_pipe_type(new_pipe, OTG_MASTER)) { /* Detect global sync changes */ if (old_pipe->pipe_dlg_param.vready_offset != new_pipe->pipe_dlg_param.vready_offset
|| old_pipe->pipe_dlg_param.vstartup_start != new_pipe->pipe_dlg_param.vstartup_start
|| old_pipe->pipe_dlg_param.vupdate_offset != new_pipe->pipe_dlg_param.vupdate_offset
|| old_pipe->pipe_dlg_param.vupdate_width != new_pipe->pipe_dlg_param.vupdate_width)
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;
if (pipe_ctx->update_flags.bits.dppclk)
dpp->funcs->dpp_dppclk_control(dpp, false, true);
if (pipe_ctx->update_flags.bits.enable)
dccg->funcs->update_dpp_dto(dccg, dpp->inst, pipe_ctx->plane_res.bw.dppclk_khz);
/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG * 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);
// program the input csc
dpp->funcs->dpp_setup(dpp,
plane_state->format,
EXPANSION_MODE_ZERO,
plane_state->input_csc_color_matrix,
plane_state->color_space,
NULL);
if (dpp->funcs->set_cursor_matrix) {
dpp->funcs->set_cursor_matrix(dpp,
plane_state->color_space,
plane_state->cursor_csc_color_matrix);
} if (dpp->funcs->dpp_program_bias_and_scale) { //TODO :for CNVC set scale and bias registers if necessary
dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
}
}
if (pipe_ctx->update_flags.bits.mpcc
|| pipe_ctx->update_flags.bits.plane_changed
|| plane_state->update_flags.bits.global_alpha_change
|| plane_state->update_flags.bits.per_pixel_alpha_change) { // MPCC inst is equal to pipe index in practice
hws->funcs.update_mpcc(dc, pipe_ctx);
}
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 ||
pipe_ctx->update_flags.bits.scaler || viewport_changed == true) &&
pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
dc->hwss.set_cursor_attribute(pipe_ctx);
dc->hwss.set_cursor_position(pipe_ctx);
if (dc->hwss.set_cursor_sdr_white_level)
dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
}
/* Any updates are handled in dc interface, just need
* to apply existing for plane enable / opp change */ if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed
|| pipe_ctx->update_flags.bits.plane_changed
|| pipe_ctx->stream->update_flags.bits.gamut_remap
|| plane_state->update_flags.bits.gamut_remap_change
|| pipe_ctx->stream->update_flags.bits.out_csc) { /* dpp/cm gamut remap*/
dc->hwss.program_gamut_remap(pipe_ctx);
/*call the dcn2 method which uses mpc csc*/
dc->hwss.program_output_csc(dc,
pipe_ctx,
pipe_ctx->stream->output_color_space,
pipe_ctx->stream->csc_color_matrix.matrix,
hubp->opp_id);
}
if (pipe_ctx->update_flags.bits.enable)
hubp->funcs->set_blank(hubp, false); /* If the stream paired with this plane is phantom, the plane is also phantom */ if (pipe_mall_type == SUBVP_PHANTOM && hubp->funcs->phantom_hubp_post_enable)
hubp->funcs->phantom_hubp_post_enable(hubp);
}
/* 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)
dcn20_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
dcn20_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);
}
/* 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)
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) {
/* 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,
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.