diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10')
16 files changed, 189 insertions, 279 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 2edf566b3a72..9a1f40eb5c47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -51,6 +51,8 @@ SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI(DSCL_MEM_PWR_STATUS, DSCL, id), \ + SRI(DSCL_MEM_PWR_CTRL, DSCL, id), \ SRI(OTG_H_BLANK, DSCL, id), \ SRI(OTG_V_BLANK, DSCL, id), \ SRI(SCL_MODE, DSCL, id), \ @@ -252,6 +254,8 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh), \ + TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh), \ TF_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ @@ -536,6 +540,8 @@ type SCL_V_INIT_INT_BOT_C; \ type SCL_CHROMA_COEF_MODE; \ type SCL_COEF_RAM_SELECT_CURRENT; \ + type LUT_MEM_PWR_FORCE; \ + type LUT_MEM_PWR_STATE; \ type CM_GAMUT_REMAP_MODE; \ type CM_GAMUT_REMAP_C11; \ type CM_GAMUT_REMAP_C12; \ @@ -1096,6 +1102,8 @@ struct dcn_dpp_mask { uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; \ uint32_t OTG_H_BLANK; \ uint32_t OTG_V_BLANK; \ + uint32_t DSCL_MEM_PWR_CTRL; \ + uint32_t DSCL_MEM_PWR_STATUS; \ uint32_t SCL_MODE; \ uint32_t LB_DATA_FORMAT; \ uint32_t LB_MEMORY_CTRL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index fce37c527a0b..efa86d5c6847 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -198,6 +198,20 @@ static enum dscl_mode_sel dpp1_dscl_get_dscl_mode( return DSCL_MODE_SCALING_420_YCBCR_ENABLE; } +static void dpp1_power_on_dscl( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + + if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) { + REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, power_on ? 0 : 3); + if (power_on) + REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5); + } +} + + static void dpp1_dscl_set_lb( struct dcn10_dpp *dpp, const struct line_buffer_params *lb_params, @@ -656,7 +670,7 @@ static void dpp1_dscl_set_recout( RECOUT_WIDTH, recout->width, /* Number of RECOUT vertical lines */ RECOUT_HEIGHT, recout->height - - visual_confirm_on * 4 * (dpp->base.inst + 1)); + - visual_confirm_on * 2 * (dpp->base.inst + 1)); } /* Main function to program scaler and line buffer in manual scaling mode */ @@ -678,6 +692,11 @@ void dpp1_dscl_set_scaler_manual_scale( dpp->scl_data = *scl_data; + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.dscl) { + if (dscl_mode != DSCL_MODE_DSCL_BYPASS) + dpp1_power_on_dscl(dpp_base, true); + } + /* Autocal off */ REG_SET_3(DSCL_AUTOCAL, 0, AUTOCAL_MODE, AUTOCAL_MODE_OFF, @@ -697,8 +716,11 @@ void dpp1_dscl_set_scaler_manual_scale( /* SCL mode */ REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) { + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.dscl) + dpp1_power_on_dscl(dpp_base, false); return; + } /* LB */ lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index 75637c291e75..6f42d10dd772 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -124,11 +124,11 @@ bool hubbub1_verify_allow_pstate_change_high( * still not asserted, we are probably stuck and going to hang * * TODO: Figure out why it takes ~100us on linux - * pstate takes around ~100us on linux. Unknown currently as to - * why it takes that long on linux + * pstate takes around ~100us (up to 200us) on linux. Unknown currently + * as to why it takes that long on linux */ const unsigned int pstate_wait_timeout_us = 200; - const unsigned int pstate_wait_expected_timeout_us = 40; + const unsigned int pstate_wait_expected_timeout_us = 180; static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index db5615a51fea..9e796dfeac20 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -326,7 +326,6 @@ void hubp1_program_pixel_format( REG_UPDATE(DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, 119); break; -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) case SURFACE_PIXEL_FORMAT_GRPH_RGBE: REG_UPDATE_2(DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, 116, @@ -337,7 +336,6 @@ void hubp1_program_pixel_format( SURFACE_PIXEL_FORMAT, 116, ALPHA_PLANE_EN, 1); break; -#endif default: BREAK_TO_DEBUGGER(); break; @@ -1243,6 +1241,22 @@ void hubp1_vtg_sel(struct hubp *hubp, uint32_t otg_inst) REG_UPDATE(DCHUBP_CNTL, HUBP_VTG_SEL, otg_inst); } +bool hubp1_in_blank(struct hubp *hubp) +{ + uint32_t in_blank; + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + REG_GET(DCHUBP_CNTL, HUBP_IN_BLANK, &in_blank); + return in_blank ? true : false; +} + +void hubp1_soft_reset(struct hubp *hubp, bool reset) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + + REG_UPDATE(DCHUBP_CNTL, HUBP_DISABLE, reset ? 1 : 0); +} + void hubp1_init(struct hubp *hubp) { //do nothing @@ -1274,6 +1288,8 @@ static const struct hubp_funcs dcn10_hubp_funcs = { .dmdata_set_attributes = NULL, .dmdata_load = NULL, + .hubp_soft_reset = hubp1_soft_reset, + .hubp_in_blank = hubp1_in_blank, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h index 780af5b3c16f..a9a6ed7f4f99 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -260,6 +260,7 @@ HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\ HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_IN_BLANK, mask_sh),\ HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ @@ -455,6 +456,7 @@ type HUBP_VTG_SEL;\ type HUBP_UNDERFLOW_STATUS;\ type HUBP_UNDERFLOW_CLEAR;\ + type HUBP_IN_BLANK;\ type NUM_PIPES;\ type NUM_BANKS;\ type PIPE_INTERLEAVE;\ @@ -772,5 +774,7 @@ void hubp1_vready_workaround(struct hubp *hubp, void hubp1_init(struct hubp *hubp); void hubp1_read_state_common(struct hubp *hubp); +bool hubp1_in_blank(struct hubp *hubp); +void hubp1_soft_reset(struct hubp *hubp, bool reset); #endif 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, ¶m); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index b24c8ae8b1ec..254300b06b43 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -34,7 +34,6 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .post_unlock_program_front_end = dcn10_post_unlock_program_front_end, - .disconnect_pipes = dcn10_disconnect_pipes, .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .update_plane_addr = dcn10_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index 04dabed5f1c5..d4caad670855 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -154,12 +154,10 @@ struct dcn10_link_enc_registers { uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_3; uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_2; uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_3; -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) uint32_t TMDS_DCBALANCER_CONTROL; uint32_t PHYA_LINK_CNTL2; uint32_t PHYB_LINK_CNTL2; uint32_t PHYC_LINK_CNTL2; -#endif }; #define LE_SF(reg_name, field_name, post_fix)\ @@ -449,14 +447,25 @@ struct dcn10_link_enc_registers { type AUX_RX_TIMEOUT_LEN;\ type AUX_RX_TIMEOUT_LEN_MUL +#define DCN30_LINK_ENCODER_REG_FIELD_LIST(type) \ + type TMDS_SYNC_DCBAL_EN;\ + type PHY_HPO_DIG_SRC_SEL;\ + type PHY_HPO_ENC_SRC_SEL;\ + type DPCS_TX_HDMI_FRL_MODE;\ + type DPCS_TX_DATA_SWAP_10_BIT;\ + type DPCS_TX_DATA_ORDER_INVERT_18_BIT;\ + type RDPCS_TX_CLK_EN + struct dcn10_link_enc_shift { DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t); }; struct dcn10_link_enc_mask { DCN_LINK_ENCODER_REG_FIELD_LIST(uint32_t); DCN20_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t); }; struct dcn10_link_encoder { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 3fcd408e9103..a46cb20596fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -467,6 +467,17 @@ void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock) REG_SET(CUR[opp_id], 0, CUR_VUPDATE_LOCK_SET, lock ? 1 : 0); } +unsigned int mpc1_get_mpc_out_mux(struct mpc *mpc, int opp_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + uint32_t val; + + if (opp_id < MAX_OPP && REG(MUX[opp_id])) + REG_GET(MUX[opp_id], MPC_OUT_MUX, &val); + + return val; +} + static const struct mpc_funcs dcn10_mpc_funcs = { .read_mpcc_state = mpc1_read_mpcc_state, .insert_plane = mpc1_insert_plane, @@ -483,6 +494,7 @@ static const struct mpc_funcs dcn10_mpc_funcs = { .set_denorm_clamp = NULL, .set_output_csc = NULL, .set_output_gamma = NULL, + .get_mpc_out_mux = mpc1_get_mpc_out_mux, }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 66a4719c22a0..dbfffc6383dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -200,4 +200,5 @@ void mpc1_read_mpcc_state( void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock); +unsigned int mpc1_get_mpc_out_mux(struct mpc *mpc, int opp_id); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index d79718fde5a6..d54d731415d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -403,6 +403,7 @@ static const struct opp_funcs dcn10_opp_funcs = { .opp_program_stereo = opp1_program_stereo, .opp_pipe_clock_control = opp1_pipe_clock_control, .opp_set_disp_pattern_generator = NULL, + .opp_program_dpg_dimensions = NULL, .dpg_is_blanked = NULL, .opp_destroy = opp1_destroy }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 800be2693fac..f033397a84e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -272,7 +272,7 @@ void optc1_program_timing( vupdate_offset, vupdate_width); - optc->funcs->set_vtg_params(optc, dc_crtc_timing); + optc->funcs->set_vtg_params(optc, dc_crtc_timing, true); /* TODO * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 @@ -299,23 +299,20 @@ void optc1_program_timing( REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); } -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) if (optc1->tg_mask->OTG_H_TIMING_DIV_MODE != 0) { if (optc1->opp_count == 4) h_div = H_TIMING_DIV_BY4; REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, h_div); - } else -#endif - { + } else { REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, h_div); } } void optc1_set_vtg_params(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing) + const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2) { struct dc_crtc_timing patched_crtc_timing; uint32_t asic_blank_end; @@ -351,9 +348,12 @@ void optc1_set_vtg_params(struct timing_generator *optc, } } - REG_UPDATE_2(CONTROL, - VTG0_FP2, v_fp2, - VTG0_VCOUNT_INIT, v_init); + if (program_fp2) + REG_UPDATE_2(CONTROL, + VTG0_FP2, v_fp2, + VTG0_VCOUNT_INIT, v_init); + else + REG_UPDATE(CONTROL, VTG0_VCOUNT_INIT, v_init); } void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) @@ -1543,7 +1543,7 @@ void dcn10_timing_generator_init(struct optc *optc1) optc1->min_h_blank = 32; optc1->min_v_blank = 3; optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 8; + optc1->min_h_sync_width = 4; optc1->min_v_sync_width = 1; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index b38475285835..b12bd9aae52f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -171,7 +171,6 @@ struct dcn_optc_registers { uint32_t OPTC_DATA_FORMAT_CONTROL; uint32_t OPTC_BYTES_PER_PIXEL; uint32_t OPTC_WIDTH_CONTROL; -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) uint32_t OTG_BLANK_DATA_COLOR; uint32_t OTG_BLANK_DATA_COLOR_EXT; uint32_t OTG_DRR_TRIGGER_WINDOW; @@ -179,7 +178,6 @@ struct dcn_optc_registers { uint32_t OTG_M_CONST_DTO1; uint32_t OTG_DRR_V_TOTAL_CHANGE; uint32_t OTG_GLOBAL_CONTROL4; -#endif }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ @@ -474,8 +472,6 @@ struct dcn_optc_registers { type MANUAL_FLOW_CONTROL;\ type MANUAL_FLOW_CONTROL_SEL; -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) - #define TG_REG_FIELD_LIST(type) \ TG_REG_FIELD_LIST_DCN1_0(type)\ type OTG_V_SYNC_MODE;\ @@ -517,33 +513,6 @@ struct dcn_optc_registers { type OTG_CRC_DATA_STREAM_COMBINE_MODE;\ type OTG_CRC_DATA_STREAM_SPLIT_MODE;\ type OTG_CRC_DATA_FORMAT; -#else - -#define TG_REG_FIELD_LIST(type) \ - TG_REG_FIELD_LIST_DCN1_0(type)\ - type MASTER_UPDATE_LOCK_DB_X;\ - type MASTER_UPDATE_LOCK_DB_Y;\ - type MASTER_UPDATE_LOCK_DB_EN;\ - type GLOBAL_UPDATE_LOCK_EN;\ - type DIG_UPDATE_LOCATION;\ - type OTG_DSC_START_POSITION_X;\ - type OTG_DSC_START_POSITION_LINE_NUM;\ - type OPTC_NUM_OF_INPUT_SEGMENT;\ - type OPTC_SEG0_SRC_SEL;\ - type OPTC_SEG1_SRC_SEL;\ - type OPTC_MEM_SEL;\ - type OPTC_DATA_FORMAT;\ - type OPTC_DSC_MODE;\ - type OPTC_DSC_BYTES_PER_PIXEL;\ - type OPTC_DSC_SLICE_WIDTH;\ - type OPTC_SEGMENT_WIDTH;\ - type OPTC_DWB0_SOURCE_SELECT;\ - type OPTC_DWB1_SOURCE_SELECT;\ - type OTG_CRC_DSC_MODE;\ - type OTG_CRC_DATA_STREAM_COMBINE_MODE;\ - type OTG_CRC_DATA_STREAM_SPLIT_MODE;\ - type OTG_CRC_DATA_FORMAT; -#endif struct dcn_optc_shift { @@ -731,6 +700,6 @@ bool optc1_get_crc(struct timing_generator *optc, bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); void optc1_set_vtg_params(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing); + const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2); #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index a78712caf124..bdc37831535e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1416,7 +1416,9 @@ static bool dcn10_resource_construct( dc->caps.max_video_width = 3840; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; dc->caps.max_slave_planes = 1; dc->caps.is_apu = true; dc->caps.post_blend_color_processing = false; @@ -1437,6 +1439,7 @@ static bool dcn10_resource_construct( dc->caps.color.dpp.dgam_rom_caps.hlg = 0; dc->caps.color.dpp.post_csc = 0; dc->caps.color.dpp.gamma_corr = 0; + dc->caps.color.dpp.dgam_rom_for_yuv = 1; dc->caps.color.dpp.hw_3d_lut = 0; dc->caps.color.dpp.ogam_ram = 1; // RGAM on DCN1 diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index f70fcadf1ee5..73ac78b16bd4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -1021,88 +1021,6 @@ void enc1_reset_hdmi_stream_attribute( #include "include/audio_types.h" -/** -* speakersToChannels -* -* @brief -* translate speakers to channels -* -* FL - Front Left -* FR - Front Right -* RL - Rear Left -* RR - Rear Right -* RC - Rear Center -* FC - Front Center -* FLC - Front Left Center -* FRC - Front Right Center -* RLC - Rear Left Center -* RRC - Rear Right Center -* LFE - Low Freq Effect -* -* FC -* FLC FRC -* FL FR -* -* LFE -* () -* -* -* RL RR -* RLC RRC -* RC -* -* ch 8 7 6 5 4 3 2 1 -* 0b00000011 - - - - - - FR FL -* 0b00000111 - - - - - LFE FR FL -* 0b00001011 - - - - FC - FR FL -* 0b00001111 - - - - FC LFE FR FL -* 0b00010011 - - - RC - - FR FL -* 0b00010111 - - - RC - LFE FR FL -* 0b00011011 - - - RC FC - FR FL -* 0b00011111 - - - RC FC LFE FR FL -* 0b00110011 - - RR RL - - FR FL -* 0b00110111 - - RR RL - LFE FR FL -* 0b00111011 - - RR RL FC - FR FL -* 0b00111111 - - RR RL FC LFE FR FL -* 0b01110011 - RC RR RL - - FR FL -* 0b01110111 - RC RR RL - LFE FR FL -* 0b01111011 - RC RR RL FC - FR FL -* 0b01111111 - RC RR RL FC LFE FR FL -* 0b11110011 RRC RLC RR RL - - FR FL -* 0b11110111 RRC RLC RR RL - LFE FR FL -* 0b11111011 RRC RLC RR RL FC - FR FL -* 0b11111111 RRC RLC RR RL FC LFE FR FL -* 0b11000011 FRC FLC - - - - FR FL -* 0b11000111 FRC FLC - - - LFE FR FL -* 0b11001011 FRC FLC - - FC - FR FL -* 0b11001111 FRC FLC - - FC LFE FR FL -* 0b11010011 FRC FLC - RC - - FR FL -* 0b11010111 FRC FLC - RC - LFE FR FL -* 0b11011011 FRC FLC - RC FC - FR FL -* 0b11011111 FRC FLC - RC FC LFE FR FL -* 0b11110011 FRC FLC RR RL - - FR FL -* 0b11110111 FRC FLC RR RL - LFE FR FL -* 0b11111011 FRC FLC RR RL FC - FR FL -* 0b11111111 FRC FLC RR RL FC LFE FR FL -* -* @param -* speakers - speaker information as it comes from CEA audio block -*/ -/* translate speakers to channels */ - -union audio_cea_channels { - uint8_t all; - struct audio_cea_channels_bits { - uint32_t FL:1; - uint32_t FR:1; - uint32_t LFE:1; - uint32_t FC:1; - uint32_t RL_RC:1; - uint32_t RR:1; - uint32_t RC_RLC_FLC:1; - uint32_t RRC_FRC:1; - } channels; -}; /* 25.2MHz/1.001*/ /* 25.2MHz/1.001*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index b99d2527cf03..76b334644f9e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -81,7 +81,9 @@ SRI(DP_MSE_RATE_UPDATE, DP, id), \ SRI(DP_PIXEL_FORMAT, DP, id), \ SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ SRI(DP_SEC_CNTL2, DP, id), \ + SRI(DP_SEC_CNTL5, DP, id), \ SRI(DP_SEC_CNTL6, DP, id), \ SRI(DP_STEER_FIFO, DP, id), \ SRI(DP_VID_M, DP, id), \ @@ -126,7 +128,9 @@ struct dcn10_stream_enc_registers { uint32_t DP_MSE_RATE_UPDATE; uint32_t DP_PIXEL_FORMAT; uint32_t DP_SEC_CNTL; + uint32_t DP_SEC_CNTL1; uint32_t DP_SEC_CNTL2; + uint32_t DP_SEC_CNTL5; uint32_t DP_SEC_CNTL6; uint32_t DP_STEER_FIFO; uint32_t DP_VID_M; @@ -169,14 +173,12 @@ struct dcn10_stream_enc_registers { uint32_t DP_SEC_METADATA_TRANSMISSION; uint32_t HDMI_METADATA_PACKET_CONTROL; uint32_t DP_SEC_FRAMING4; -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) uint32_t DP_GSP11_CNTL; uint32_t HDMI_GENERIC_PACKET_CONTROL6; uint32_t HDMI_GENERIC_PACKET_CONTROL7; uint32_t HDMI_GENERIC_PACKET_CONTROL8; uint32_t HDMI_GENERIC_PACKET_CONTROL9; uint32_t HDMI_GENERIC_PACKET_CONTROL10; -#endif uint32_t DIG_CLOCK_PATTERN; }; @@ -413,6 +415,8 @@ struct dcn10_stream_enc_registers { type DP_SEC_GSP3_ENABLE;\ type DP_SEC_GSP4_ENABLE;\ type DP_SEC_GSP5_ENABLE;\ + type DP_SEC_GSP5_LINE_NUM;\ + type DP_SEC_GSP5_LINE_REFERENCE;\ type DP_SEC_GSP6_ENABLE;\ type DP_SEC_GSP7_ENABLE;\ type DP_SEC_GSP7_PPS;\ @@ -505,7 +509,6 @@ struct dcn10_stream_enc_registers { type DP_PIXEL_COMBINE;\ type DP_SST_SDP_SPLITTING -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) #define SE_REG_FIELD_LIST_DCN3_0(type) \ type HDMI_GENERIC8_CONT;\ type HDMI_GENERIC8_SEND;\ @@ -531,22 +534,17 @@ struct dcn10_stream_enc_registers { type DP_SEC_GSP11_PPS;\ type DP_SEC_GSP11_ENABLE;\ type DP_SEC_GSP11_LINE_NUM -#endif struct dcn10_stream_encoder_shift { SE_REG_FIELD_LIST_DCN1_0(uint8_t); SE_REG_FIELD_LIST_DCN2_0(uint8_t); -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) SE_REG_FIELD_LIST_DCN3_0(uint8_t); -#endif }; struct dcn10_stream_encoder_mask { SE_REG_FIELD_LIST_DCN1_0(uint32_t); SE_REG_FIELD_LIST_DCN2_0(uint32_t); -#if defined(CONFIG_DRM_AMD_DC_DCN3_0) SE_REG_FIELD_LIST_DCN3_0(uint32_t); -#endif }; struct dcn10_stream_encoder { |