int i;
bool allow_self_fresh_force_enable = true;
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+ if (dc->hwss.s0i3_golden_init_wa && dc->hwss.s0i3_golden_init_wa(dc))
+ return;
+#endif
if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
allow_self_fresh_force_enable =
dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
}
- tg->funcs->set_blank_data_double_buffer(tg, true);
+ if (tg->funcs->set_blank_data_double_buffer)
+ tg->funcs->set_blank_data_double_buffer(tg, true);
if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
tg->funcs->clear_optc_underflow(tg);
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
/* DPMS may already disable */
if (!pipe_ctx->stream->dpms_off)
- core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
- else if (pipe_ctx->stream_res.audio) {
- dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
+ core_link_disable_stream(pipe_ctx);
+ else if (pipe_ctx->stream_res.audio)
+ dc->hwss.disable_audio_stream(pipe_ctx);
+
+ if (pipe_ctx->stream_res.audio) {
+ /*disable az_endpoint*/
+ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+
+ /*free audio*/
+ if (dc->caps.dynamic_audio == true) {
+ /*we have to dynamic arbitrate the audio endpoints*/
+ /*we free the resource, need reset is_audio_acquired*/
+ update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
+ pipe_ctx->stream_res.audio, false);
+ pipe_ctx->stream_res.audio = NULL;
+ }
}
-
}
/* by upper caller loop, parent pipe: pipe0, will be reset last.
}
}
- /* Cannot reset the MPC mux if seamless boot */
- if (!can_apply_seamless_boot)
- dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ /* Cannot reset the MPC mux if seamless boot */
+ if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
+ continue;
+
+ dc->res_pool->mpc->funcs->mpc_init_single_inst(
+ dc->res_pool->mpc, i);
+ }
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct timing_generator *tg = dc->res_pool->timing_generators[i];
return;
}
- if (!dcb->funcs->is_accelerated_mode(dcb)) {
- dc->hwss.bios_golden_init(dc);
- if (dc->ctx->dc_bios->fw_info_valid) {
- res_pool->ref_clocks.xtalin_clock_inKhz =
- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
-
- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
- if (res_pool->dccg && res_pool->hubbub) {
-
- (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
- &res_pool->ref_clocks.dccg_ref_clock_inKhz);
-
- (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
- res_pool->ref_clocks.dccg_ref_clock_inKhz,
- &res_pool->ref_clocks.dchub_ref_clock_inKhz);
- } else {
- // Not all ASICs have DCCG sw component
- res_pool->ref_clocks.dccg_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- res_pool->ref_clocks.dchub_ref_clock_inKhz =
- res_pool->ref_clocks.xtalin_clock_inKhz;
- }
- }
- } else
- ASSERT_CRITICAL(false);
+ if (!dcb->funcs->is_accelerated_mode(dcb))
dc->hwss.disable_vga(dc->hwseq);
- }
+
+ dc->hwss.bios_golden_init(dc);
+ if (dc->ctx->dc_bios->fw_info_valid) {
+ res_pool->ref_clocks.xtalin_clock_inKhz =
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
+
+ if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+ if (res_pool->dccg && res_pool->hubbub) {
+
+ (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+ &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+
+ (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+ res_pool->ref_clocks.dccg_ref_clock_inKhz,
+ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+ } else {
+ // Not all ASICs have DCCG sw component
+ res_pool->ref_clocks.dccg_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ res_pool->ref_clocks.dchub_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ }
+ }
+ } else
+ ASSERT_CRITICAL(false);
for (i = 0; i < dc->link_count; i++) {
/* Power up AND update implementation according to the
*/
if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
dc->hwss.init_pipes(dc, dc->current_state);
- for (i = 0; i < res_pool->pipe_count; i++) {
- struct hubp *hubp = res_pool->hubps[i];
- struct dpp *dpp = res_pool->dpps[i];
-
- hubp->funcs->hubp_init(hubp);
- res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
- dc->hwss.plane_atomic_power_down(dc, dpp, hubp);
- }
-
- apply_DEGVIDCN10_253_wa(dc);
}
-
for (i = 0; i < res_pool->audio_count; i++) {
struct audio *audio = res_pool->audios[i];
}
dc->hwss.enable_power_gating_plane(dc->hwseq, true);
+
+ if (dc->clk_mgr->funcs->notify_wm_ranges)
+ dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+
}
static void dcn10_reset_hw_ctx_wrap(
return result;
}
+#define MAX_NUM_HW_POINTS 0x200
+
+static void log_tf(struct dc_context *ctx,
+ struct dc_transfer_func *tf, uint32_t hw_points_num)
+{
+ // DC_LOG_GAMMA is default logging of all hw points
+ // DC_LOG_ALL_GAMMA logs all points, not only hw points
+ // DC_LOG_ALL_TF_POINTS logs all channels of the tf
+ int i = 0;
+
+ DC_LOGGER_INIT(ctx->logger);
+ DC_LOG_GAMMA("Gamma Correction TF");
+ DC_LOG_ALL_GAMMA("Logging all tf points...");
+ DC_LOG_ALL_TF_CHANNELS("Logging all channels...");
+
+ for (i = 0; i < hw_points_num; i++) {
+ DC_LOG_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+ DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+ DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
+ }
+
+ for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) {
+ DC_LOG_ALL_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+ DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+ DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
+ }
+}
+
static bool
dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
} else
dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
+ if (stream != NULL && stream->ctx != NULL &&
+ stream->out_transfer_func != NULL) {
+ log_tf(stream->ctx,
+ stream->out_transfer_func,
+ dpp->regamma_params.hw_points_num);
+ }
+
return true;
}
pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
}
+
+static bool dcn10_is_rear_mpo_fix_required(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace)
+{
+ if (pipe_ctx->plane_state && pipe_ctx->plane_state->layer_index > 0 && is_rgb_cspace(colorspace)) {
+ if (pipe_ctx->top_pipe) {
+ struct pipe_ctx *top = pipe_ctx->top_pipe;
+
+ while (top->top_pipe)
+ top = top->top_pipe; // Traverse to top pipe_ctx
+ if (top->plane_state && top->plane_state->layer_index == 0)
+ return true; // Front MPO plane not hidden
+ }
+ }
+ return false;
+}
+
+static void dcn10_set_csc_adjustment_rgb_mpo_fix(struct pipe_ctx *pipe_ctx, uint16_t *matrix)
+{
+ // Override rear plane RGB bias to fix MPO brightness
+ uint16_t rgb_bias = matrix[3];
+
+ matrix[3] = 0;
+ matrix[7] = 0;
+ matrix[11] = 0;
+ pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+ matrix[3] = rgb_bias;
+ matrix[7] = rgb_bias;
+ matrix[11] = rgb_bias;
+}
+
static void dcn10_program_output_csc(struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum dc_color_space colorspace,
int opp_id)
{
if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
- if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL)
- pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+ if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
+
+ /* MPO is broken with RGB colorspaces when OCSC matrix
+ * brightness offset >= 0 on DCN1 due to OCSC before MPC
+ * Blending adds offsets from front + rear to rear plane
+ *
+ * Fix is to set RGB bias to 0 on rear plane, top plane
+ * black value pixels add offset instead of rear + front
+ */
+
+ int16_t rgb_bias = matrix[3];
+ // matrix[3/7/11] are all the same offset value
+
+ if (rgb_bias > 0 && dcn10_is_rear_mpo_fix_required(pipe_ctx, colorspace)) {
+ dcn10_set_csc_adjustment_rgb_mpo_fix(pipe_ctx, matrix);
+ } else {
+ pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+ }
+ }
} else {
if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
dc->res_pool->dccg->funcs->update_dpp_dto(
dc->res_pool->dccg,
dpp->inst,
- pipe_ctx->plane_res.bw.dppclk_khz,
- false);
+ pipe_ctx->plane_res.bw.dppclk_khz);
else
dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ?
dc->clk_mgr->clks.dispclk_khz / 2 :
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
- dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
+ if (dc->hwss.setup_vupdate_interrupt)
+ dc->hwss.setup_vupdate_interrupt(pipe_ctx);
+ dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
}
if (pipe_ctx->plane_state != NULL)
if (pipe_ctx->stream != stream)
continue;
- if (!pipe_ctx->top_pipe)
+ if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
return pipe_ctx;
}
return NULL;
}
static void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
- int num_pipes, int vmin, int vmax)
+ int num_pipes, unsigned int vmin, unsigned int vmax,
+ unsigned int vmid, unsigned int vmid_frame_number)
{
int i = 0;
struct drr_params params = {0};
params.vertical_total_max = vmax;
params.vertical_total_min = vmin;
+ params.vertical_total_mid = vmid;
+ params.vertical_total_mid_frame_num = vmid_frame_number;
/* TODO: If multiple pipes are to be supported, you need
* some GSL stuff. Static screen triggers may be programmed differently
static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
{
- if (hws->ctx->dc->res_pool->hubbub != NULL) {
- struct hubp *hubp = hws->ctx->dc->res_pool->hubps[0];
+ struct hubbub *hubbub = hws->ctx->dc->res_pool->hubbub;
- if (hubp->funcs->hubp_update_dchub)
- hubp->funcs->hubp_update_dchub(hubp, dh_data);
- else
- hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data);
- }
+ /* In DCN, this programming sequence is owned by the hubbub */
+ hubbub->funcs->update_dchub(hubbub, dh_data);
}
static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
pos_cpy.enable = false;
+ // Swap axis and mirror horizontally
+ if (param.rotation == ROTATION_ANGLE_90) {
+ uint32_t temp_x = pos_cpy.x;
+ pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width -
+ (pos_cpy.y - pipe_ctx->plane_res.scl_data.viewport.x) + pipe_ctx->plane_res.scl_data.viewport.x;
+ pos_cpy.y = temp_x;
+ }
+ // Swap axis and mirror vertically
+ else if (param.rotation == ROTATION_ANGLE_270) {
+ uint32_t temp_y = pos_cpy.y;
+ if (pos_cpy.x > pipe_ctx->plane_res.scl_data.viewport.height) {
+ pos_cpy.x = pos_cpy.x - pipe_ctx->plane_res.scl_data.viewport.height;
+ pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
+ } else {
+ pos_cpy.y = 2 * pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
+ }
+ pos_cpy.x = temp_y;
+ }
+ // Mirror horizontally and vertically
+ else if (param.rotation == ROTATION_ANGLE_180) {
+ if (pos_cpy.x >= pipe_ctx->plane_res.scl_data.viewport.width + pipe_ctx->plane_res.scl_data.viewport.x) {
+ pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.width
+ - pos_cpy.x + 2 * pipe_ctx->plane_res.scl_data.viewport.x;
+ } else {
+ uint32_t temp_x = pos_cpy.x;
+ pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.x - pos_cpy.x;
+ if (temp_x >= pipe_ctx->plane_res.scl_data.viewport.x + (int)hubp->curs_attr.width
+ || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) {
+ pos_cpy.x = temp_x + pipe_ctx->plane_res.scl_data.viewport.width;
+ }
+ }
+ pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
+ }
+
hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m);
dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height);
}
pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
pipe_ctx->plane_res.hubp, attributes);
pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
- pipe_ctx->plane_res.dpp, attributes->color_format);
+ pipe_ctx->plane_res.dpp, attributes);
}
static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)