aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c224
1 files changed, 87 insertions, 137 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index d0f3bf953d02..cfc130e2d6fd 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -52,6 +52,7 @@
#include "dpcd_defs.h"
#include "dsc.h"
#include "dce/dmub_hw_lock_mgr.h"
+#include "dc_trace.h"
#define DC_LOGGER_INIT(logger)
@@ -1020,15 +1021,17 @@ static bool dcn10_hw_wa_force_recovery(struct dc *dc)
}
-
void dcn10_verify_allow_pstate_change_high(struct dc *dc)
{
static bool should_log_hw_state; /* prevent hw state log by default */
if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) {
- if (should_log_hw_state) {
+ int i = 0;
+
+ if (should_log_hw_state)
dcn10_log_hw_state(dc, NULL);
- }
+
+ TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
BREAK_TO_DEBUGGER();
if (dcn10_hw_wa_force_recovery(dc)) {
/*check again*/
@@ -1434,27 +1437,18 @@ void dcn10_init_hw(struct dc *dc)
if (dc->clk_mgr->funcs->notify_wm_ranges)
dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
-
-#ifdef CONFIG_DRM_AMD_DC_DCN3_0
- if (dc->clk_mgr->funcs->set_hard_max_memclk)
- dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
-#endif
-
}
/* In headless boot cases, DIG may be turned
* on which causes HW/SW discrepancies.
* To avoid this, power down hardware on boot
- * if DIG is turned on and seamless boot not enabled
+ * if DIG is turned on
*/
void dcn10_power_down_on_boot(struct dc *dc)
{
int i = 0;
struct dc_link *edp_link;
- if (!dc->config.power_down_display_on_boot)
- return;
-
edp_link = get_edp_link(dc);
if (edp_link &&
edp_link->link_enc->funcs->is_dig_enabled &&
@@ -1541,6 +1535,8 @@ static bool patch_address_for_sbs_tb_stereo(
plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
plane_state->address.grph_stereo.right_addr =
plane_state->address.grph_stereo.left_addr;
+ plane_state->address.grph_stereo.right_meta_addr =
+ plane_state->address.grph_stereo.left_meta_addr;
}
}
return false;
@@ -1851,10 +1847,20 @@ void dcn10_enable_timing_synchronization(
struct pipe_ctx *grouped_pipes[])
{
struct dc_context *dc_ctx = dc->ctx;
- int i;
+ struct output_pixel_processor *opp;
+ struct timing_generator *tg;
+ int i, width, height;
DC_SYNC_INFO("Setting up OTG reset trigger\n");
+ for (i = 1; i < group_size; i++) {
+ opp = grouped_pipes[i]->stream_res.opp;
+ tg = grouped_pipes[i]->stream_res.tg;
+ tg->funcs->get_otg_active_size(tg, &width, &height);
+ if (opp->funcs->opp_program_dpg_dimensions)
+ opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
+ }
+
for (i = 1; i < group_size; i++)
grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
grouped_pipes[i]->stream_res.tg,
@@ -1871,6 +1877,14 @@ void dcn10_enable_timing_synchronization(
grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
grouped_pipes[i]->stream_res.tg);
+ for (i = 1; i < group_size; i++) {
+ opp = grouped_pipes[i]->stream_res.opp;
+ tg = grouped_pipes[i]->stream_res.tg;
+ tg->funcs->get_otg_active_size(tg, &width, &height);
+ if (opp->funcs->opp_program_dpg_dimensions)
+ opp->funcs->opp_program_dpg_dimensions(opp, width, height);
+ }
+
DC_SYNC_INFO("Sync complete\n");
}
@@ -2722,7 +2736,7 @@ static void dcn10_program_all_pipe_in_tree(
pipe_ctx->pipe_dlg_param.vupdate_width);
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
- pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
if (hws->funcs.setup_vupdate_interrupt)
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
@@ -2761,122 +2775,6 @@ static struct pipe_ctx *dcn10_find_top_pipe_for_stream(
return NULL;
}
-bool dcn10_disconnect_pipes(
- struct dc *dc,
- struct dc_state *context)
-{
- bool found_pipe = false;
- int i, j;
- struct dce_hwseq *hws = dc->hwseq;
- struct dc_state *old_ctx = dc->current_state;
- bool mpcc_disconnected = false;
- struct pipe_ctx *old_pipe;
- struct pipe_ctx *new_pipe;
- DC_LOGGER_INIT(dc->ctx->logger);
-
- /* Set pipe update flags and lock pipes */
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- new_pipe = &context->res_ctx.pipe_ctx[i];
- new_pipe->update_flags.raw = 0;
-
- if (!old_pipe->plane_state && !new_pipe->plane_state)
- continue;
-
- if (old_pipe->plane_state && !new_pipe->plane_state)
- new_pipe->update_flags.bits.disable = 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;
-
- }
-
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- /* Disconnect mpcc here only if losing pipe split*/
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable &&
- old_ctx->res_ctx.pipe_ctx[i].top_pipe) {
-
- /* Find the top pipe in the new ctx for the bottom pipe that we
- * want to remove by comparing the streams and planes. If both
- * pipes are being disabled then do it in the regular pipe
- * programming sequence
- */
- for (j = 0; j < dc->res_pool->pipe_count; j++) {
- if (old_ctx->res_ctx.pipe_ctx[i].top_pipe->stream == context->res_ctx.pipe_ctx[j].stream &&
- old_ctx->res_ctx.pipe_ctx[i].top_pipe->plane_state == context->res_ctx.pipe_ctx[j].plane_state &&
- !context->res_ctx.pipe_ctx[j].top_pipe &&
- !context->res_ctx.pipe_ctx[j].update_flags.bits.disable) {
- found_pipe = true;
- break;
- }
- }
-
- // Disconnect if the top pipe lost it's pipe split
- if (found_pipe && !context->res_ctx.pipe_ctx[j].bottom_pipe) {
- hws->funcs.plane_atomic_disconnect(dc, &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);
- mpcc_disconnected = true;
- }
- }
- found_pipe = false;
- }
- }
-
- if (mpcc_disconnected) {
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
- struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- struct dc_plane_state *plane_state = pipe_ctx->plane_state;
- struct hubp *hubp = pipe_ctx->plane_res.hubp;
-
- if (!pipe_ctx || !plane_state || !pipe_ctx->stream)
- continue;
-
- // Only update scaler and viewport here if we lose a pipe split.
- // This is to prevent half the screen from being black when we
- // unlock after disconnecting MPCC.
- if (!(old_pipe && !pipe_ctx->top_pipe &&
- !pipe_ctx->bottom_pipe && old_pipe->bottom_pipe))
- continue;
-
- if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) {
- if (pipe_ctx->update_flags.bits.scaler ||
- plane_state->update_flags.bits.scaling_change ||
- plane_state->update_flags.bits.position_change ||
- plane_state->update_flags.bits.per_pixel_alpha_change ||
- pipe_ctx->stream->update_flags.bits.scaling) {
-
- pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha;
- ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP);
- /* scaler configuration */
- pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
- pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
- }
-
- if (pipe_ctx->update_flags.bits.viewport ||
- (context == dc->current_state && plane_state->update_flags.bits.position_change) ||
- (context == dc->current_state && plane_state->update_flags.bits.scaling_change) ||
- (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) {
-
- hubp->funcs->mem_program_viewport(
- hubp,
- &pipe_ctx->plane_res.scl_data.viewport,
- &pipe_ctx->plane_res.scl_data.viewport_c);
- }
- }
- }
- }
- return mpcc_disconnected;
-}
-
void dcn10_wait_for_pending_cleared(struct dc *dc,
struct dc_state *context)
{
@@ -3378,6 +3276,8 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
};
bool pipe_split_on = (pipe_ctx->top_pipe != NULL) ||
(pipe_ctx->bottom_pipe != NULL);
+ bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) ||
+ (pipe_ctx->prev_odm_pipe != NULL);
int x_plane = pipe_ctx->plane_state->dst_rect.x;
int y_plane = pipe_ctx->plane_state->dst_rect.y;
@@ -3461,16 +3361,56 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
uint32_t temp_y = pos_cpy.y;
int viewport_height =
pipe_ctx->plane_res.scl_data.viewport.height;
-
- if (pipe_split_on) {
+ int viewport_y =
+ pipe_ctx->plane_res.scl_data.viewport.y;
+
+ /**
+ * Display groups that are 1xnY, have pos_cpy.x > 2 * viewport.height
+ * For pipe split cases:
+ * - apply offset of viewport.y to normalize pos_cpy.x
+ * - calculate the pos_cpy.y as before
+ * - shift pos_cpy.y back by same offset to get final value
+ * - since we iterate through both pipes, use the lower
+ * viewport.y for offset
+ * For non pipe split cases, use the same calculation for
+ * pos_cpy.y as the 180 degree rotation case below,
+ * but use pos_cpy.x as our input because we are rotating
+ * 270 degrees
+ */
+ if (pipe_split_on || odm_combine_on) {
+ int pos_cpy_x_offset;
+ int other_pipe_viewport_y;
+
+ if (pipe_split_on) {
+ if (pipe_ctx->bottom_pipe) {
+ other_pipe_viewport_y =
+ pipe_ctx->bottom_pipe->plane_res.scl_data.viewport.y;
+ } else {
+ other_pipe_viewport_y =
+ pipe_ctx->top_pipe->plane_res.scl_data.viewport.y;
+ }
+ } else {
+ if (pipe_ctx->next_odm_pipe) {
+ other_pipe_viewport_y =
+ pipe_ctx->next_odm_pipe->plane_res.scl_data.viewport.y;
+ } else {
+ other_pipe_viewport_y =
+ pipe_ctx->prev_odm_pipe->plane_res.scl_data.viewport.y;
+ }
+ }
+ pos_cpy_x_offset = (viewport_y > other_pipe_viewport_y) ?
+ other_pipe_viewport_y : viewport_y;
+ pos_cpy.x -= pos_cpy_x_offset;
if (pos_cpy.x > viewport_height) {
pos_cpy.x = pos_cpy.x - viewport_height;
pos_cpy.y = viewport_height - pos_cpy.x;
} else {
pos_cpy.y = 2 * viewport_height - pos_cpy.x;
}
- } else
- pos_cpy.y = viewport_height - pos_cpy.x;
+ pos_cpy.y += pos_cpy_x_offset;
+ } else {
+ pos_cpy.y = (2 * viewport_y) + viewport_height - pos_cpy.x;
+ }
pos_cpy.x = temp_y;
}
// Mirror horizontally and vertically
@@ -3480,7 +3420,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
int viewport_x =
pipe_ctx->plane_res.scl_data.viewport.x;
- if (pipe_split_on) {
+ if (pipe_split_on || odm_combine_on) {
if (pos_cpy.x >= viewport_width + viewport_x) {
pos_cpy.x = 2 * viewport_width
- pos_cpy.x + 2 * viewport_x;
@@ -3498,7 +3438,17 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
} else {
pos_cpy.x = viewport_width - pos_cpy.x + 2 * viewport_x;
}
- pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
+
+ /**
+ * Display groups that are 1xnY, have pos_cpy.y > viewport.height
+ * Calculation:
+ * delta_from_bottom = viewport.y + viewport.height - pos_cpy.y
+ * pos_cpy.y_new = viewport.y + delta_from_bottom
+ * Simplify it as:
+ * pos_cpy.y = viewport.y * 2 + viewport.height - pos_cpy.y
+ */
+ pos_cpy.y = (2 * pipe_ctx->plane_res.scl_data.viewport.y) +
+ pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
}
hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);