diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/hwss')
16 files changed, 997 insertions, 68 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/Makefile b/drivers/gpu/drm/amd/display/dc/hwss/Makefile index 40ecebea1ba0..bee617ca0838 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hwss/Makefile @@ -27,6 +27,24 @@ # DCE ############################################################################### +ifdef CONFIG_DRM_AMD_DC_SI +HWSS_DCE60 = dce60_hwseq.o + +AMD_DAL_HWSS_DCE60 = $(addprefix $(AMDDALPATH)/dc/hwss/dce60/,$(HWSS_DCE60)) + +AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCE60) +endif + +############################################################################### + +HWSS_DCE80 = dce80_hwseq.o + +AMD_DAL_HWSS_DCE80 = $(addprefix $(AMDDALPATH)/dc/hwss/dce80/,$(HWSS_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCE80) + +############################################################################### + HWSS_DCE = dce_hwseq.o AMD_DAL_HWSS_DCE = $(addprefix $(AMDDALPATH)/dc/hwss/dce/,$(HWSS_DCE)) @@ -65,14 +83,6 @@ AMD_DAL_HWSS_DCE120 = $(addprefix $(AMDDALPATH)/dc/hwss/dce120/,$(HWSS_DCE120)) AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCE120) -############################################################################### - -HWSS_DCE80 = dce80_hwseq.o - -AMD_DAL_HWSS_DCE80 = $(addprefix $(AMDDALPATH)/dc/hwss/dce80/,$(HWSS_DCE80)) - -AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCE80) - ifdef CONFIG_DRM_AMD_DC_FP ############################################################################### # DCN diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 5656d10368ad..23bec5d25ed6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -2763,12 +2763,12 @@ static void dce110_enable_per_frame_crtc_position_reset( } -static void init_pipes(struct dc *dc, struct dc_state *context) +static void dce110_init_pipes(struct dc *dc, struct dc_state *context) { // Do nothing } -static void init_hw(struct dc *dc) +static void dce110_init_hw(struct dc *dc) { int i; struct dc_bios *bp; @@ -3327,7 +3327,7 @@ void dce110_disable_link_output(struct dc_link *link, static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, .program_output_csc = program_output_csc, - .init_hw = init_hw, + .init_hw = dce110_init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, .post_unlock_program_front_end = dce110_post_unlock_program_front_end, @@ -3371,7 +3371,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { }; static const struct hwseq_private_funcs dce110_private_funcs = { - .init_pipes = init_pipes, + .init_pipes = dce110_init_pipes, .set_input_transfer_func = dce110_set_input_transfer_func, .set_output_transfer_func = dce110_set_output_transfer_func, .power_down = dce110_power_down, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.c new file mode 100644 index 000000000000..a08e9f9eec17 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.c @@ -0,0 +1,433 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * 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 "dm_services.h" +#include "dc.h" +#include "core_types.h" +#include "dce60_hwseq.h" + +#include "dce/dce_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dce100/dce100_hwseq.h" + +/* include DCE6 register header files */ +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" + +#define DC_LOGGER_INIT() + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +/***************************PIPE_CONTROL***********************************/ + +/* + * Check if FBC can be enabled + */ +static bool dce60_should_enable_fbc(struct dc *dc, + struct dc_state *context, + uint32_t *pipe_idx) +{ + uint32_t i; + struct pipe_ctx *pipe_ctx = NULL; + struct resource_context *res_ctx = &context->res_ctx; + unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; + + + ASSERT(dc->fbc_compressor); + + /* FBC memory should be allocated */ + if (!dc->ctx->fbc_gpu_addr) + return false; + + /* Only supports single display */ + if (context->stream_count != 1) + return false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (res_ctx->pipe_ctx[i].stream) { + + pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (!pipe_ctx) + continue; + + /* fbc not applicable on underlay pipe */ + if (pipe_ctx->pipe_idx != underlay_idx) { + *pipe_idx = i; + break; + } + } + } + + if (i == dc->res_pool->pipe_count) + return false; + + if (!pipe_ctx->stream->link) + return false; + + /* Only supports eDP */ + if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP) + return false; + + /* PSR should not be enabled */ + if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled) + return false; + + /* Nothing to compress */ + if (!pipe_ctx->plane_state) + return false; + + /* Only for non-linear tiling */ + if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) + return false; + + return true; +} + +/* + * Enable FBC + */ +static void dce60_enable_fbc( + struct dc *dc, + struct dc_state *context) +{ + uint32_t pipe_idx = 0; + + if (dce60_should_enable_fbc(dc, context, &pipe_idx)) { + /* Program GRPH COMPRESSED ADDRESS and PITCH */ + struct compr_addr_and_pitch_params params = {0, 0, 0}; + struct compressor *compr = dc->fbc_compressor; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + params.source_view_width = pipe_ctx->stream->timing.h_addressable; + params.source_view_height = pipe_ctx->stream->timing.v_addressable; + params.inst = pipe_ctx->stream_res.tg->inst; + compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; + + compr->funcs->surface_address_and_pitch(compr, ¶ms); + compr->funcs->set_fbc_invalidation_triggers(compr, 1); + + compr->funcs->enable_fbc(compr, ¶ms); + } +} + + +/******************************************************************************* + * Front End programming + ******************************************************************************/ + +static void dce60_set_default_colors(struct pipe_ctx *pipe_ctx) +{ + struct default_adjustment default_adjust = { 0 }; + + default_adjust.force_hw_default = false; + default_adjust.in_color_space = pipe_ctx->plane_state->color_space; + default_adjust.out_color_space = pipe_ctx->stream->output_color_space; + default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; + default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; + + /* display color depth */ + default_adjust.color_depth = + pipe_ctx->stream->timing.display_color_depth; + + /* Lb color depth */ + default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; + + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( + pipe_ctx->plane_res.xfm, &default_adjust); +} + +/******************************************************************************* + * In order to turn on surface we will program + * CRTC + * + * DCE6 has no bottom_pipe and no Blender HW + * We need to set 'blank_target' to false in order to turn on the display + * + * |-----------|------------|---------| + * |curr pipe | set_blank | | + * |Surface |blank_target| CRCT | + * |visibility | argument | | + * |-----------|------------|---------| + * | off | true | blank | + * | on | false | unblank | + * |-----------|------------|---------| + * + ******************************************************************************/ +static void dce60_program_surface_visibility(const struct dc *dc, + struct pipe_ctx *pipe_ctx) +{ + bool blank_target = false; + + /* DCE6 has no bottom_pipe and no Blender HW */ + + if (!pipe_ctx->plane_state->visible) + blank_target = true; + + /* DCE6 skip dce_set_blender_mode() but then proceed to 'unblank' CRTC */ + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); + +} + + +static void dce60_get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4; + + switch (pipe_ctx->plane_res.scl_data.format) { + case PIXEL_FORMAT_ARGB8888: + /* set boarder color to red */ + color->color_r_cr = color_value; + break; + + case PIXEL_FORMAT_ARGB2101010: + /* set boarder color to blue */ + color->color_b_cb = color_value; + break; + case PIXEL_FORMAT_420BPP8: + /* set boarder color to green */ + color->color_g_y = color_value; + break; + case PIXEL_FORMAT_420BPP10: + /* set boarder color to yellow */ + color->color_g_y = color_value; + color->color_r_cr = color_value; + break; + case PIXEL_FORMAT_FP16: + /* set boarder color to white */ + color->color_r_cr = color_value; + color->color_b_cb = color_value; + color->color_g_y = color_value; + break; + default: + break; + } +} + +static void dce60_program_scaler(const struct dc *dc, + const struct pipe_ctx *pipe_ctx) +{ + struct tg_color color = {0}; + + /* DCE6 skips DCN TOFPGA check for transform_set_pixel_storage_depth == NULL */ + + if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) + dce60_get_surface_visual_confirm_color(pipe_ctx, &color); + else + color_space_to_black_color(dc, + pipe_ctx->stream->output_color_space, + &color); + + pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( + pipe_ctx->plane_res.xfm, + pipe_ctx->plane_res.scl_data.lb_params.depth, + &pipe_ctx->stream->bit_depth_params); + + if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) { + /* + * The way 420 is packed, 2 channels carry Y component, 1 channel + * alternate between Cb and Cr, so both channels need the pixel + * value for Y + */ + if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + color.color_r_cr = color.color_g_y; + + pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( + pipe_ctx->stream_res.tg, + &color); + } + + pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, + &pipe_ctx->plane_res.scl_data); +} + +static void +dce60_program_front_end_for_pipe( + struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + struct mem_input *mi = pipe_ctx->plane_res.mi; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct xfm_grph_csc_adjustment adjust; + struct out_csc_color_matrix tbl_entry; + unsigned int i; + struct dce_hwseq *hws = dc->hwseq; + + DC_LOGGER_INIT(); + memset(&tbl_entry, 0, sizeof(tbl_entry)); + + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + dce_enable_fe_clock(dc->hwseq, mi->inst, true); + + dce60_set_default_colors(pipe_ctx); + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment + == true) { + tbl_entry.color_space = + pipe_ctx->stream->output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = + pipe_ctx->stream->csc_color_matrix.matrix[i]; + + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->plane_res.xfm, &tbl_entry); + } + + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + + for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) + adjust.temperature_matrix[i] = + pipe_ctx->stream->gamut_remap_matrix.matrix[i]; + } + + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + + dce60_program_scaler(dc, pipe_ctx); + + mi->funcs->mem_input_program_surface_config( + mi, + plane_state->format, + &plane_state->tiling_info, + &plane_state->plane_size, + plane_state->rotation, + NULL, + false); + if (mi->funcs->set_blank) + mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); + + if (dc->config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->plane_res.mi, + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); + + /* Moved programming gamma from dc to hwss */ + if (pipe_ctx->plane_state->update_flags.bits.full_update || + pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || + pipe_ctx->plane_state->update_flags.bits.gamma_change) + hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state); + + if (pipe_ctx->plane_state->update_flags.bits.full_update) + hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); + + DC_LOG_SURFACE( + "Pipe:%d %p: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;" + "clip: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + (void *) pipe_ctx->plane_state, + pipe_ctx->plane_state->address.grph.addr.high_part, + pipe_ctx->plane_state->address.grph.addr.low_part, + pipe_ctx->plane_state->src_rect.x, + pipe_ctx->plane_state->src_rect.y, + pipe_ctx->plane_state->src_rect.width, + pipe_ctx->plane_state->src_rect.height, + pipe_ctx->plane_state->dst_rect.x, + pipe_ctx->plane_state->dst_rect.y, + pipe_ctx->plane_state->dst_rect.width, + pipe_ctx->plane_state->dst_rect.height, + pipe_ctx->plane_state->clip_rect.x, + pipe_ctx->plane_state->clip_rect.y, + pipe_ctx->plane_state->clip_rect.width, + pipe_ctx->plane_state->clip_rect.height); + + DC_LOG_SURFACE( + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.recout.width, + pipe_ctx->plane_res.scl_data.recout.height, + pipe_ctx->plane_res.scl_data.recout.x, + pipe_ctx->plane_res.scl_data.recout.y); +} + +static void dce60_apply_ctx_for_surface( + struct dc *dc, + const struct dc_stream_state *stream, + int num_planes, + struct dc_state *context) +{ + int i; + + if (num_planes == 0) + return; + + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream != stream) + continue; + + /* Need to allocate mem before program front end for Fiji */ + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, + pipe_ctx->stream->timing.pix_clk_100hz / 10, + context->stream_count); + + dce60_program_front_end_for_pipe(dc, pipe_ctx); + + dc->hwss.update_plane_addr(dc, pipe_ctx); + + dce60_program_surface_visibility(dc, pipe_ctx); + + } + + if (dc->fbc_compressor) + dce60_enable_fbc(dc, context); +} + +void dce60_hw_sequencer_construct(struct dc *dc) +{ + dce110_hw_sequencer_construct(dc); + + dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating; + dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface; + dc->hwss.cursor_lock = dce60_pipe_control_lock; + dc->hwss.pipe_control_lock = dce60_pipe_control_lock; + dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; + dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; + dc->hwss.clear_surface_dcc_and_tiling = dce100_reset_surface_dcc_and_tiling; +} + diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.h new file mode 100644 index 000000000000..f3b2d8b60d5b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * 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 __DC_HWSS_DCE60_H__ +#define __DC_HWSS_DCE60_H__ + +#include "core_types.h" +#include "hw_sequencer_private.h" + +struct dc; + +void dce60_hw_sequencer_construct(struct dc *dc); + +#endif /* __DC_HWSS_DCE60_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 912f96323ed6..f9ee55998b6b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -94,6 +94,128 @@ static void print_microsec(struct dc_context *dc_ctx, us_x10 % frac); } +/* + * Delay until we passed busy-until-point to which we can + * do necessary locking/programming on consecutive full updates + */ +void dcn10_wait_for_pipe_update_if_needed(struct dc *dc, struct pipe_ctx *pipe_ctx, bool is_surface_update_only) +{ + struct crtc_position position; + struct dc_stream_state *stream = pipe_ctx->stream; + unsigned int vpos, frame_count; + uint32_t vupdate_start, vupdate_end, vblank_start; + unsigned int lines_to_vupdate, us_to_vupdate; + unsigned int us_per_line, us_vupdate; + + if (!pipe_ctx->stream || + !pipe_ctx->stream_res.tg || + !pipe_ctx->stream_res.stream_enc) + return; + + if (pipe_ctx->prev_odm_pipe && + pipe_ctx->stream) + return; + + if (!pipe_ctx->wait_is_required) + return; + + struct timing_generator *tg = pipe_ctx->stream_res.tg; + + if (tg->funcs->is_tg_enabled && !tg->funcs->is_tg_enabled(tg)) + return; + + dc->hwss.calc_vupdate_position(dc, pipe_ctx, &vupdate_start, + &vupdate_end); + + dc->hwss.get_position(&pipe_ctx, 1, &position); + vpos = position.vertical_count; + + frame_count = tg->funcs->get_frame_count(tg); + + if (frame_count - pipe_ctx->wait_frame_count > 2) + return; + + vblank_start = pipe_ctx->pipe_dlg_param.vblank_start; + + if (vpos >= vupdate_start && vupdate_start >= vblank_start) + lines_to_vupdate = stream->timing.v_total - vpos + vupdate_start; + else + lines_to_vupdate = vupdate_start - vpos; + + us_per_line = + stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz; + us_to_vupdate = lines_to_vupdate * us_per_line; + + if (vupdate_end < vupdate_start) + vupdate_end += stream->timing.v_total; + + if (lines_to_vupdate > stream->timing.v_total - vupdate_end + vupdate_start) + us_to_vupdate = 0; + + us_vupdate = (vupdate_end - vupdate_start + 1) * us_per_line; + + if (is_surface_update_only && us_to_vupdate + us_vupdate > 200) { + //surface updates come in at high irql + pipe_ctx->wait_is_required = true; + return; + } + + fsleep(us_to_vupdate + us_vupdate); + + //clear + pipe_ctx->next_vupdate = 0; + pipe_ctx->wait_frame_count = 0; + pipe_ctx->wait_is_required = false; +} + +/* + * On pipe unlock and programming, indicate pipe will be busy + * until some frame and line (vupdate), this is required for consecutive + * full updates, need to wait for updates + * to latch to try and program the next update + */ +void dcn10_set_wait_for_update_needed_for_pipe(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + uint32_t vupdate_start, vupdate_end; + struct crtc_position position; + unsigned int vpos, cur_frame; + + if (!pipe_ctx->stream || + !pipe_ctx->stream_res.tg || + !pipe_ctx->stream_res.stream_enc) + return; + + dc->hwss.get_position(&pipe_ctx, 1, &position); + vpos = position.vertical_count; + + dc->hwss.calc_vupdate_position(dc, pipe_ctx, &vupdate_start, + &vupdate_end); + + struct timing_generator *tg = pipe_ctx->stream_res.tg; + + struct optc *optc1 = DCN10TG_FROM_TG(tg); + + ASSERT(optc1->max_frame_count != 0); + + if (tg->funcs->is_tg_enabled && !tg->funcs->is_tg_enabled(tg)) + return; + + pipe_ctx->next_vupdate = vupdate_start; + + cur_frame = tg->funcs->get_frame_count(tg); + + if (vpos < vupdate_start) { + pipe_ctx->wait_frame_count = cur_frame; + } else { + if (cur_frame + 1 > optc1->max_frame_count) + pipe_ctx->wait_frame_count = cur_frame + 1 - optc1->max_frame_count; + else + pipe_ctx->wait_frame_count = cur_frame + 1; + } + + pipe_ctx->wait_is_required = true; +} + void dcn10_lock_all_pipes(struct dc *dc, struct dc_state *context, bool lock) @@ -2664,7 +2786,6 @@ void dcn10_update_visual_confirm_color(struct dc *dc, struct mpc *mpc = dc->res_pool->mpc; if (mpc->funcs->set_bg_color) { - memcpy(&pipe_ctx->plane_state->visual_confirm_color, &(pipe_ctx->visual_confirm_color), sizeof(struct tg_color)); mpc->funcs->set_bg_color(mpc, &(pipe_ctx->visual_confirm_color), mpcc_id); } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h index 42ffd1e1299c..57d30ea225f2 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h @@ -50,6 +50,13 @@ void dcn10_optimize_bandwidth( void dcn10_prepare_bandwidth( struct dc *dc, struct dc_state *context); +void dcn10_wait_for_pipe_update_if_needed( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + bool is_surface_update_only); +void dcn10_set_wait_for_update_needed_for_pipe( + struct dc *dc, + struct pipe_ctx *pipe_ctx); void dcn10_pipe_control_lock( struct dc *dc, struct pipe_ctx *pipe, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 846c9c51f2d9..858288c3b1ac 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -2053,7 +2053,7 @@ 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 (!pipe->top_pipe && !pipe->prev_odm_pipe && pipe->plane_state) { + if (pipe->plane_state) { ASSERT(!pipe->plane_state->triplebuffer_flips); /*turn off triple buffer for full update*/ dc->hwss.program_triplebuffer( @@ -2482,7 +2482,7 @@ bool dcn20_update_bandwidth( struct dce_hwseq *hws = dc->hwseq; /* recalculate DML parameters */ - if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) + if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) return false; /* apply updated bandwidth parameters */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c index be26c925fdfa..e68f21fd5f0f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c @@ -84,6 +84,20 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) struct dsc_config dsc_cfg; struct dsc_optc_config dsc_optc_cfg = {0}; enum optc_dsc_mode optc_dsc_mode; + struct dcn_dsc_state dsc_state = {0}; + + if (!dsc) { + DC_LOG_DSC("DSC is NULL for tg instance %d:", pipe_ctx->stream_res.tg->inst); + return; + } + + if (dsc->funcs->dsc_read_state) { + dsc->funcs->dsc_read_state(dsc, &dsc_state); + if (!dsc_state.dsc_fw_en) { + DC_LOG_DSC("DSC has been disabled for tg instance %d:", pipe_ctx->stream_res.tg->inst); + return; + } + } /* Enable DSC hw block */ dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index cd0adf72b223..a0b05b9ef660 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -1181,6 +1181,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign struct dc_stream_state *stream = pipe_ctx->stream; unsigned int odm_combine_factor = 0; bool two_pix_per_container = false; + struct dce_hwseq *hws = stream->ctx->dc->hwseq; two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); @@ -1201,7 +1202,8 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign } else { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_4; - if ((odm_combine_factor == 2) || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) + if ((odm_combine_factor == 2) || (hws->funcs.is_dp_dig_pixel_rate_div_policy && + hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx))) *k2_div = PIXEL_RATE_DIV_BY_2; } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 922b8d71cf1a..c814d957305a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -241,11 +241,6 @@ void dcn35_init_hw(struct dc *dc) dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); } - if (res_pool->dccg->funcs->dccg_root_gate_disable_control) { - for (i = 0; i < res_pool->pipe_count; i++) - res_pool->dccg->funcs->dccg_root_gate_disable_control(res_pool->dccg, i, 0); - } - for (i = 0; i < res_pool->audio_count; i++) { struct audio *audio = res_pool->audios[i]; @@ -901,12 +896,18 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context) void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_state *context) { + struct dpp *dpp = pipe_ctx->plane_res.dpp; + struct dccg *dccg = dc->res_pool->dccg; + + /* enable DCFCLK current DCHUB */ pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true); /* initialize HUBP on power up */ pipe_ctx->plane_res.hubp->funcs->hubp_init(pipe_ctx->plane_res.hubp); - + /*make sure DPPCLK is on*/ + dccg->funcs->dccg_root_gate_disable_control(dccg, dpp->inst, true); + dpp->funcs->dpp_dppclk_control(dpp, false, true); /* make sure OPP_PIPE_CLOCK_EN = 1 */ pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control( pipe_ctx->stream_res.opp, @@ -923,6 +924,7 @@ void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx, // Program system aperture settings pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt); } + //DC_LOG_DEBUG("%s: dpp_inst(%d) =\n", __func__, dpp->inst); if (!pipe_ctx->top_pipe && pipe_ctx->plane_state @@ -938,6 +940,8 @@ void dcn35_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) { struct hubp *hubp = pipe_ctx->plane_res.hubp; struct dpp *dpp = pipe_ctx->plane_res.dpp; + struct dccg *dccg = dc->res_pool->dccg; + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); @@ -955,7 +959,8 @@ void dcn35_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) hubp->funcs->hubp_clk_cntl(hubp, false); dpp->funcs->dpp_dppclk_control(dpp, false, false); -/*to do, need to support both case*/ + dccg->funcs->dccg_root_gate_disable_control(dccg, dpp->inst, false); + hubp->power_gated = true; hubp->funcs->hubp_reset(hubp); @@ -967,6 +972,8 @@ void dcn35_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) pipe_ctx->top_pipe = NULL; pipe_ctx->bottom_pipe = NULL; pipe_ctx->plane_state = NULL; + //DC_LOG_DEBUG("%s: dpp_inst(%d)=\n", __func__, dpp->inst); + } void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx) @@ -1543,7 +1550,7 @@ static bool should_avoid_empty_tu(struct pipe_ctx *pipe_ctx) struct dc_link_settings *link_settings = &pipe_ctx->link_config.dp_link_settings; const struct dc *dc = pipe_ctx->stream->link->dc; - if (pipe_ctx->stream->link->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) + if (pipe_ctx->link_config.dp_tunnel_settings.should_enable_dp_tunneling == false) return false; // Not necessary for MST configurations diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index 6a82a865209c..a3ccf805bd16 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -168,6 +168,8 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { .dsc_pg_control = dcn35_dsc_pg_control, .dsc_pg_status = dcn32_dsc_pg_status, .enable_plane = dcn35_enable_plane, + .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, + .set_wait_for_update_needed_for_pipe = dcn10_set_wait_for_update_needed_for_pipe, }; void dcn35_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c index 902a96940a01..58f2be2a326b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c @@ -158,10 +158,12 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { .set_mcm_luts = dcn32_set_mcm_luts, .setup_hpo_hw_control = dcn35_setup_hpo_hw_control, .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, - .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy, + .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy, .dsc_pg_control = dcn35_dsc_pg_control, .dsc_pg_status = dcn32_dsc_pg_status, .enable_plane = dcn35_enable_plane, + .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, + .set_wait_for_update_needed_for_pipe = dcn10_set_wait_for_update_needed_for_pipe, }; void dcn351_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 3af6a3402b89..c4177a9a662f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -396,6 +396,249 @@ static void dcn401_get_mcm_lut_xable_from_pipe_ctx(struct dc *dc, struct pipe_ct } } +static void dcn401_set_mcm_location_post_blend(struct dc *dc, struct pipe_ctx *pipe_ctx, bool bPostBlend) +{ + struct mpc *mpc = dc->res_pool->mpc; + int mpcc_id = pipe_ctx->plane_res.hubp->inst; + + if (!pipe_ctx->plane_state) + return; + + mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); + pipe_ctx->plane_state->mcm_location = (bPostBlend) ? + MPCC_MOVABLE_CM_LOCATION_AFTER : + MPCC_MOVABLE_CM_LOCATION_BEFORE; +} + +static void dc_get_lut_mode( + enum dc_cm2_gpu_mem_layout layout, + enum hubp_3dlut_fl_mode *mode, + enum hubp_3dlut_fl_addressing_mode *addr_mode) +{ + switch (layout) { + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB: + *mode = hubp_3dlut_fl_mode_native_1; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR: + *mode = hubp_3dlut_fl_mode_native_2; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR: + *mode = hubp_3dlut_fl_mode_transform; + *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear; + break; + default: + *mode = hubp_3dlut_fl_mode_disable; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + } +} + +static void dc_get_lut_format( + enum dc_cm2_gpu_mem_format dc_format, + enum hubp_3dlut_fl_format *format) +{ + switch (dc_format) { + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB: + *format = hubp_3dlut_fl_format_unorm_12msb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB: + *format = hubp_3dlut_fl_format_unorm_12lsb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10: + *format = hubp_3dlut_fl_format_float_fp1_5_10; + break; + } +} + +static void dc_get_lut_xbar( + enum dc_cm2_gpu_mem_pixel_component_order order, + enum hubp_3dlut_fl_crossbar_bit_slice *cr_r, + enum hubp_3dlut_fl_crossbar_bit_slice *y_g, + enum hubp_3dlut_fl_crossbar_bit_slice *cb_b) +{ + switch (order) { + case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA: + *cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47; + *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; + *cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15; + break; + case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA: + *cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; + *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; + *cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; + break; + } +} + +static void dc_get_lut_width( + enum dc_cm2_gpu_mem_size size, + enum hubp_3dlut_fl_width *width) +{ + switch (size) { + case DC_CM2_GPU_MEM_SIZE_333333: + *width = hubp_3dlut_fl_width_33; + break; + case DC_CM2_GPU_MEM_SIZE_171717: + *width = hubp_3dlut_fl_width_17; + break; + case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: + *width = hubp_3dlut_fl_width_transformed; + break; + } +} +static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc) +{ + if (mpc->funcs->rmcm.update_3dlut_fast_load_select && + mpc->funcs->rmcm.program_lut_read_write_control && + hubp->funcs->hubp_program_3dlut_fl_addr && + mpc->funcs->rmcm.program_bit_depth && + hubp->funcs->hubp_program_3dlut_fl_mode && + hubp->funcs->hubp_program_3dlut_fl_addressing_mode && + hubp->funcs->hubp_program_3dlut_fl_format && + hubp->funcs->hubp_update_3dlut_fl_bias_scale && + mpc->funcs->rmcm.program_bias_scale && + hubp->funcs->hubp_program_3dlut_fl_crossbar && + hubp->funcs->hubp_program_3dlut_fl_width && + mpc->funcs->rmcm.update_3dlut_fast_load_select && + mpc->funcs->rmcm.populate_lut && + mpc->funcs->rmcm.program_lut_mode && + hubp->funcs->hubp_enable_3dlut_fl && + mpc->funcs->rmcm.enable_3dlut_fl) + return true; + + return false; +} + +bool dcn401_program_rmcm_luts( + struct hubp *hubp, + struct pipe_ctx *pipe_ctx, + enum dc_cm2_transfer_func_source lut3d_src, + struct dc_cm2_func_luts *mcm_luts, + struct mpc *mpc, + bool lut_bank_a, + int mpcc_id) +{ + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; + union mcm_lut_params m_lut_params; + enum MCM_LUT_XABLE shaper_xable, lut3d_xable = MCM_LUT_DISABLE, lut1d_xable; + enum hubp_3dlut_fl_mode mode; + enum hubp_3dlut_fl_addressing_mode addr_mode; + enum hubp_3dlut_fl_format format = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0; + enum hubp_3dlut_fl_width width = 0; + struct dc *dc = hubp->ctx->dc; + + bool bypass_rmcm_3dlut = false; + bool bypass_rmcm_shaper = false; + + dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); + + /* 3DLUT */ + switch (lut3d_src) { + case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: + memset(&m_lut_params, 0, sizeof(m_lut_params)); + // Don't know what to do in this case. + //case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: + break; + case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: + dc_get_lut_width(mcm_luts->lut3d_data.gpu_mem_params.size, &width); + if (!dc_is_rmcm_3dlut_supported(hubp, mpc) || + !mpc->funcs->rmcm.is_config_supported(width)) + return false; + + //0. disable fl on mpc + mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, 0xF); + + //1. power down the block + mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, false); + + //2. program RMCM + //2a. 3dlut reg programming + mpc->funcs->rmcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, + (!bypass_rmcm_3dlut) && lut3d_xable != MCM_LUT_DISABLE, mpcc_id); + + hubp->funcs->hubp_program_3dlut_fl_addr(hubp, + mcm_luts->lut3d_data.gpu_mem_params.addr); + + mpc->funcs->rmcm.program_bit_depth(mpc, + mcm_luts->lut3d_data.gpu_mem_params.bit_depth, mpcc_id); + + // setting native or transformed mode, + dc_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout, &mode, &addr_mode); + + //these program the mcm 3dlut + hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode); + + hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode); + + //seems to be only for the MCM + dc_get_lut_format(mcm_luts->lut3d_data.gpu_mem_params.format_params.format, &format); + hubp->funcs->hubp_program_3dlut_fl_format(hubp, format); + + mpc->funcs->rmcm.program_bias_scale(mpc, + mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale, + mpcc_id); + hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp, + mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale); + + dc_get_lut_xbar( + mcm_luts->lut3d_data.gpu_mem_params.component_order, + &crossbar_bit_slice_cr_r, + &crossbar_bit_slice_y_g, + &crossbar_bit_slice_cb_b); + + hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, + crossbar_bit_slice_cr_r, + crossbar_bit_slice_y_g, + crossbar_bit_slice_cb_b); + + mpc->funcs->rmcm.program_3dlut_size(mpc, width, mpcc_id); + + mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst); + + //2b. shaper reg programming + memset(&m_lut_params, 0, sizeof(m_lut_params)); + + if (mcm_luts->shaper->type == TF_TYPE_HWPWL) { + m_lut_params.pwl = &mcm_luts->shaper->pwl; + } else if (mcm_luts->shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { + ASSERT(false); + cm_helper_translate_curve_to_hw_format( + dc->ctx, + mcm_luts->shaper, + &dpp_base->regamma_params, true); + m_lut_params.pwl = &dpp_base->regamma_params; + } + if (m_lut_params.pwl) { + mpc->funcs->rmcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id); + mpc->funcs->rmcm.program_lut_mode(mpc, !bypass_rmcm_shaper, lut_bank_a, mpcc_id); + } else { + //RMCM 3dlut won't work without its shaper + return false; + } + + //3. Select the hubp connected to this RMCM + hubp->funcs->hubp_enable_3dlut_fl(hubp, true); + mpc->funcs->rmcm.enable_3dlut_fl(mpc, true, mpcc_id); + + //4. power on the block + if (m_lut_params.pwl) + mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, true); + + break; + default: + return false; + } + + return true; +} + void dcn401_populate_mcm_luts(struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_cm2_func_luts mcm_luts, @@ -407,21 +650,39 @@ void dcn401_populate_mcm_luts(struct dc *dc, struct mpc *mpc = dc->res_pool->mpc; union mcm_lut_params m_lut_params; enum dc_cm2_transfer_func_source lut3d_src = mcm_luts.lut3d_data.lut3d_src; - enum hubp_3dlut_fl_format format; + enum hubp_3dlut_fl_format format = 0; enum hubp_3dlut_fl_mode mode; - enum hubp_3dlut_fl_width width; + enum hubp_3dlut_fl_width width = 0; enum hubp_3dlut_fl_addressing_mode addr_mode; - enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g; - enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b; - enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0; enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE; enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE; enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE; - bool is_17x17x17 = true; bool rval; dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); + //MCM - setting its location (Before/After) blender + //set to post blend (true) + dcn401_set_mcm_location_post_blend( + dc, + pipe_ctx, + mcm_luts.lut3d_data.mpc_mcm_post_blend); + + //RMCM - 3dLUT+Shaper + if (mcm_luts.lut3d_data.rmcm_3dlut_enable) { + dcn401_program_rmcm_luts( + hubp, + pipe_ctx, + lut3d_src, + &mcm_luts, + mpc, + lut_bank_a, + mpcc_id); + } + /* 1D LUT */ if (mcm_luts.lut1d_func) { memset(&m_lut_params, 0, sizeof(m_lut_params)); @@ -442,7 +703,7 @@ void dcn401_populate_mcm_luts(struct dc *dc, } /* Shaper */ - if (mcm_luts.shaper) { + if (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) { memset(&m_lut_params, 0, sizeof(m_lut_params)); if (mcm_luts.shaper->type == TF_TYPE_HWPWL) m_lut_params.pwl = &mcm_luts.shaper->pwl; @@ -454,11 +715,11 @@ void dcn401_populate_mcm_luts(struct dc *dc, m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL; } if (m_lut_params.pwl) { - if (mpc->funcs->populate_lut) - mpc->funcs->populate_lut(mpc, MCM_LUT_SHAPER, m_lut_params, lut_bank_a, mpcc_id); + if (mpc->funcs->mcm.populate_lut) + mpc->funcs->mcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id); + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_ENABLE, lut_bank_a, mpcc_id); } - if (mpc->funcs->program_lut_mode) - mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, shaper_xable, lut_bank_a, mpcc_id); } /* 3DLUT */ @@ -467,6 +728,7 @@ void dcn401_populate_mcm_luts(struct dc *dc, memset(&m_lut_params, 0, sizeof(m_lut_params)); if (hubp->funcs->hubp_enable_3dlut_fl) hubp->funcs->hubp_enable_3dlut_fl(hubp, false); + if (mcm_luts.lut3d_data.lut3d_func && mcm_luts.lut3d_data.lut3d_func->state.bits.initialized) { m_lut_params.lut3d = &mcm_luts.lut3d_data.lut3d_func->lut_3d; if (mpc->funcs->populate_lut) @@ -476,16 +738,35 @@ void dcn401_populate_mcm_luts(struct dc *dc, mpcc_id); } break; - case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: + case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: + switch (mcm_luts.lut3d_data.gpu_mem_params.size) { + case DC_CM2_GPU_MEM_SIZE_333333: + width = hubp_3dlut_fl_width_33; + break; + case DC_CM2_GPU_MEM_SIZE_171717: + width = hubp_3dlut_fl_width_17; + break; + case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: + width = hubp_3dlut_fl_width_transformed; + break; + } + + //check for support + if (mpc->funcs->mcm.is_config_supported && + !mpc->funcs->mcm.is_config_supported(width)) + break; if (mpc->funcs->program_lut_read_write_control) mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id); if (mpc->funcs->program_lut_mode) mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id); - if (mpc->funcs->program_3dlut_size) - mpc->funcs->program_3dlut_size(mpc, is_17x17x17, mpcc_id); + if (hubp->funcs->hubp_program_3dlut_fl_addr) hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr); + + if (mpc->funcs->mcm.program_bit_depth) + mpc->funcs->mcm.program_bit_depth(mpc, mcm_luts.lut3d_data.gpu_mem_params.bit_depth, mpcc_id); + switch (mcm_luts.lut3d_data.gpu_mem_params.layout) { case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB: mode = hubp_3dlut_fl_mode_native_1; @@ -512,7 +793,6 @@ void dcn401_populate_mcm_luts(struct dc *dc, switch (mcm_luts.lut3d_data.gpu_mem_params.format_params.format) { case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB: - default: format = hubp_3dlut_fl_format_unorm_12msb_bitslice; break; case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB: @@ -524,37 +804,37 @@ void dcn401_populate_mcm_luts(struct dc *dc, } if (hubp->funcs->hubp_program_3dlut_fl_format) hubp->funcs->hubp_program_3dlut_fl_format(hubp, format); - if (hubp->funcs->hubp_update_3dlut_fl_bias_scale) + if (hubp->funcs->hubp_update_3dlut_fl_bias_scale && + mpc->funcs->mcm.program_bias_scale) { + mpc->funcs->mcm.program_bias_scale(mpc, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale, + mpcc_id); hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp, - mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias, - mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale); - - switch (mcm_luts.lut3d_data.gpu_mem_params.component_order) { - case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA: - default: - crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; - crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; - crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; - break; + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale); } + //navi 4x has a bug and r and blue are swapped and need to be worked around here in + //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x + dc_get_lut_xbar( + mcm_luts.lut3d_data.gpu_mem_params.component_order, + &crossbar_bit_slice_cr_r, + &crossbar_bit_slice_y_g, + &crossbar_bit_slice_cb_b); + if (hubp->funcs->hubp_program_3dlut_fl_crossbar) hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, + crossbar_bit_slice_cr_r, crossbar_bit_slice_y_g, - crossbar_bit_slice_cb_b, - crossbar_bit_slice_cr_r); + crossbar_bit_slice_cb_b); + + if (mpc->funcs->mcm.program_lut_read_write_control) + mpc->funcs->mcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, true, mpcc_id); + + if (mpc->funcs->mcm.program_3dlut_size) + mpc->funcs->mcm.program_3dlut_size(mpc, width, mpcc_id); - switch (mcm_luts.lut3d_data.gpu_mem_params.size) { - case DC_CM2_GPU_MEM_SIZE_171717: - default: - width = hubp_3dlut_fl_width_17; - break; - case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: - width = hubp_3dlut_fl_width_transformed; - break; - } - if (hubp->funcs->hubp_program_3dlut_fl_width) - hubp->funcs->hubp_program_3dlut_fl_width(hubp, width); if (mpc->funcs->update_3dlut_fast_load_select) mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst); @@ -2081,7 +2361,7 @@ void dcn401_program_front_end_for_ctx( 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) { if (pipe->plane_state->triplebuffer_flips) BREAK_TO_DEBUGGER(); @@ -2371,7 +2651,7 @@ bool dcn401_update_bandwidth( struct dce_hwseq *hws = dc->hwseq; /* recalculate DML parameters */ - if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) + if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) return false; /* apply updated bandwidth parameters */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h index 781cf0efccc6..ce65b4f6c672 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h @@ -109,4 +109,12 @@ void dcn401_detect_pipe_changes( void dcn401_plane_atomic_power_down(struct dc *dc, struct dpp *dpp, struct hubp *hubp); +bool dcn401_program_rmcm_luts( + struct hubp *hubp, + struct pipe_ctx *pipe_ctx, + enum dc_cm2_transfer_func_source lut3d_src, + struct dc_cm2_func_luts *mcm_luts, + struct mpc *mpc, + bool lut_bank_a, + int mpcc_id); #endif /* __DC_HWSS_DCN401_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index c8b5ed834579..3a0795045bc6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -195,6 +195,8 @@ enum block_sequence_func { DMUB_SUBVP_SAVE_SURF_ADDR, HUBP_WAIT_FOR_DCC_META_PROP, DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST, + /* This must be the last value in this enum, add new ones above */ + HWSS_BLOCK_SEQUENCE_FUNC_COUNT }; struct block_sequence { @@ -202,6 +204,8 @@ struct block_sequence { enum block_sequence_func func; }; +#define MAX_HWSS_BLOCK_SEQUENCE_SIZE (HWSS_BLOCK_SEQUENCE_FUNC_COUNT * MAX_PIPES) + struct hw_sequencer_funcs { void (*hardware_release)(struct dc *dc); /* Embedded Display Related */ @@ -534,13 +538,13 @@ void set_drr_and_clear_adjust_pending( struct drr_params *params); void hwss_execute_sequence(struct dc *dc, - struct block_sequence block_sequence[], + struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE], int num_steps); void hwss_build_fast_sequence(struct dc *dc, struct dc_dmub_cmd *dc_dmub_cmd, unsigned int dmub_cmd_count, - struct block_sequence block_sequence[], + struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE], unsigned int *num_steps, struct pipe_ctx *pipe_ctx, struct dc_stream_status *stream_status, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h index 22a5d4a03c98..09bc65c2fa23 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h @@ -183,6 +183,8 @@ struct hwseq_private_funcs { struct dc_cm2_func_luts mcm_luts, bool lut_bank_a); void (*perform_3dlut_wa_unlock)(struct pipe_ctx *pipe_ctx); + void (*wait_for_pipe_update_if_needed)(struct dc *dc, struct pipe_ctx *pipe_ctx, bool is_surface_update_only); + void (*set_wait_for_update_needed_for_pipe)(struct dc *dc, struct pipe_ctx *pipe_ctx); }; struct dce_hwseq { |