From: Tony Cheng <tony.cheng@xxxxxxx> - dce_mem_input_allocate_dmif - dce_mem_input_free_dmif - mem_input_program_display_marks (DCE11.2) - also fix MC_HUB_RDREQ_DMIF_LIMIT wa is different in different DCE - also add more robust error checking in new programming model -- more asserts Change-Id: Iea64d3c771375ff3d09ea4e7d15be4c63fe0ca32 Signed-off-by: Tony Cheng <tony.cheng at amd.com> Acked-by: Harry Wentland <harry.wentland at amd.com> --- drivers/gpu/drm/amd/dal/dc/dc_helper.c | 6 +- drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.c | 191 ++++++++++ drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.h | 91 ++++- .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c | 16 +- .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c | 205 +---------- .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 17 +- .../gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c | 384 +-------------------- drivers/gpu/drm/amd/dal/dc/dce80/dce80_mem_input.c | 126 +------ drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c | 17 +- drivers/gpu/drm/amd/dal/dc/dm_services.h | 8 +- drivers/gpu/drm/amd/dal/dc/inc/hw/mem_input.h | 1 + drivers/gpu/drm/amd/dal/dc/inc/reg_helper.h | 2 +- 12 files changed, 334 insertions(+), 730 deletions(-) diff --git a/drivers/gpu/drm/amd/dal/dc/dc_helper.c b/drivers/gpu/drm/amd/dal/dc/dc_helper.c index 96724ba17e4b..22b72f0bcbbc 100644 --- a/drivers/gpu/drm/amd/dal/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/dal/dc/dc_helper.c @@ -114,7 +114,8 @@ uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value, - unsigned int delay_between_poll_us, unsigned int time_out_num_tries) + unsigned int delay_between_poll_us, unsigned int time_out_num_tries, + const char *func_name) { uint32_t field_value; uint32_t reg_val; @@ -137,6 +138,7 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, return reg_val; } - BREAK_TO_DEBUGGER(); + DC_ERR("REG_WAIT timeout %dus * %d tries - ", + delay_between_poll_us, time_out_num_tries, func_name); return reg_val; } diff --git a/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.c index 1b4a5b9bb8b6..654731cccdcd 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.c @@ -36,6 +36,78 @@ mi->shifts->field_name, mi->masks->field_name +static void program_urgency_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t urgency_low_wm, + uint32_t urgency_high_wm) +{ + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK, wm_select); + + REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0, + URGENCY_LOW_WATERMARK, urgency_low_wm, + URGENCY_HIGH_WATERMARK, urgency_high_wm); +} + +static void program_nbp_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t nbp_wm) +{ + if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) { + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select); + + REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE, 1, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); + + REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK, nbp_wm); + } +} + +static void program_stutter_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t stutter_mark) +{ + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); + + REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); +} + +void dce_mem_input_program_display_marks(struct mem_input *mi, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; + + program_urgency_watermark(mi, 0, /* set a */ + urgent.a_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 1, /* set b */ + urgent.b_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 2, /* set c */ + urgent.c_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 3, /* set d */ + urgent.d_mark, total_dest_line_time_ns); + + REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE, stutter_en, + STUTTER_IGNORE_FBC, 1); + program_nbp_watermark(mi, 0, nbp.a_mark); /* set a */ + program_nbp_watermark(mi, 1, nbp.b_mark); /* set b */ + program_nbp_watermark(mi, 2, nbp.c_mark); /* set c */ + program_nbp_watermark(mi, 3, nbp.d_mark); /* set d */ + + program_stutter_watermark(mi, 0, stutter.a_mark); /* set a */ + program_stutter_watermark(mi, 1, stutter.b_mark); /* set b */ + program_stutter_watermark(mi, 2, stutter.c_mark); /* set c */ + program_stutter_watermark(mi, 3, stutter.d_mark); /* set d */ +} static void program_tiling(struct mem_input *mi, const union dc_tiling_info *info) @@ -191,3 +263,122 @@ bool dce_mem_input_program_surface_config(struct mem_input *mi, return true; } + +static uint32_t get_dmif_switch_time_us( + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz) +{ + uint32_t frame_time; + uint32_t pixels_per_second; + uint32_t pixels_per_frame; + uint32_t refresh_rate; + const uint32_t us_in_sec = 1000000; + const uint32_t min_single_frame_time_us = 30000; + /*return double of frame time*/ + const uint32_t single_frame_time_multiplier = 2; + + if (!h_total || v_total || !pix_clk_khz) + return single_frame_time_multiplier * min_single_frame_time_us; + + /*TODO: should we use pixel format normalized pixel clock here?*/ + pixels_per_second = pix_clk_khz * 1000; + pixels_per_frame = h_total * v_total; + + if (!pixels_per_second || !pixels_per_frame) { + /* avoid division by zero */ + ASSERT(pixels_per_frame); + ASSERT(pixels_per_second); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + refresh_rate = pixels_per_second / pixels_per_frame; + + if (!refresh_rate) { + /* avoid division by zero*/ + ASSERT(refresh_rate); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + frame_time = us_in_sec / refresh_rate; + + if (frame_time < min_single_frame_time_us) + frame_time = min_single_frame_time_us; + + frame_time *= single_frame_time_multiplier; + + return frame_time; +} + +void dce_mem_input_allocate_dmif(struct mem_input *mi, + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz, + uint32_t total_stream_num) +{ + const uint32_t retry_delay = 10; + uint32_t retry_count = get_dmif_switch_time_us( + h_total, + v_total, + pix_clk_khz) / retry_delay; + + uint32_t pix_dur; + uint32_t buffers_allocated; + uint32_t dmif_buffer_control; + + dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATED, &buffers_allocated); + + if (buffers_allocated == 2) + return; + + REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, + DMIF_BUFFERS_ALLOCATED, 2); + + REG_WAIT(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, + retry_delay, retry_count); + + if (pix_clk_khz != 0) { + pix_dur = 1000000000ULL / pix_clk_khz; + + REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION, pix_dur); + } + + if (mi->wa.single_head_rdreq_dmif_limit) { + uint32_t eanble = (total_stream_num > 1) ? 0 : + mi->wa.single_head_rdreq_dmif_limit; + + REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, + ENABLE, eanble); + } +} + +void dce_mem_input_free_dmif(struct mem_input *mi, + uint32_t total_stream_num) +{ + uint32_t buffers_allocated; + uint32_t dmif_buffer_control; + + dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATED, &buffers_allocated); + + if (buffers_allocated == 0) + return; + + REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, + DMIF_BUFFERS_ALLOCATED, 0); + + REG_WAIT(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, + 10, 0xBB8); + + if (mi->wa.single_head_rdreq_dmif_limit) { + uint32_t eanble = (total_stream_num > 1) ? 0 : + mi->wa.single_head_rdreq_dmif_limit; + + REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, + ENABLE, eanble); + } +} diff --git a/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.h index 96c7736e223b..d5930a925fcb 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/dal/dc/dce/dce_mem_input.h @@ -25,7 +25,7 @@ #ifndef __DCE_MEM_INPUT_H__ #define __DCE_MEM_INPUT_H__ -#define MI_REG_LIST(id)\ +#define MI_DCE_BASE_REG_LIST(id)\ SRI(GRPH_ENABLE, DCP, id),\ SRI(GRPH_CONTROL, DCP, id),\ SRI(GRPH_X_START, DCP, id),\ @@ -35,9 +35,19 @@ SRI(GRPH_PITCH, DCP, id),\ SRI(HW_ROTATION, DCP, id),\ SRI(GRPH_SWAP_CNTL, DCP, id),\ - SRI(PRESCALE_GRPH_CONTROL, DCP, id) + SRI(PRESCALE_GRPH_CONTROL, DCP, id),\ + SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\ + SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\ + SRI(DMIF_BUFFER_CONTROL, PIPE, id) + +#define MI_REG_LIST(id)\ + MI_DCE_BASE_REG_LIST(id),\ + SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id) struct dce_mem_input_registers { + /* DCP */ uint32_t GRPH_ENABLE; uint32_t GRPH_CONTROL; uint32_t GRPH_X_START; @@ -48,6 +58,18 @@ struct dce_mem_input_registers { uint32_t HW_ROTATION; uint32_t GRPH_SWAP_CNTL; uint32_t PRESCALE_GRPH_CONTROL; + /* DMIF_PG */ + uint32_t DPG_PIPE_ARBITRATION_CONTROL1; + uint32_t DPG_WATERMARK_MASK_CONTROL; + uint32_t DPG_PIPE_URGENCY_CONTROL; + uint32_t DPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + uint32_t DPG_PIPE_LOW_POWER_CONTROL; + uint32_t DPG_PIPE_STUTTER_CONTROL; + uint32_t DPG_PIPE_STUTTER_CONTROL2; + /* DCI */ + uint32_t DMIF_BUFFER_CONTROL; + /* MC_HUB */ + uint32_t MC_HUB_RDREQ_DMIF_LIMIT; }; /* Set_Filed_for_Block */ @@ -81,9 +103,30 @@ struct dce_mem_input_registers { SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh) +#define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh) + +#define MI_DMIF_PG_MASK_SH_DCE(mask_sh, blk)\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh) + #define MI_DCE_MASK_SH_LIST(mask_sh)\ - MI_DCP_MASK_SH_LIST(mask_sh, ),\ - MI_GFX8_TILE_MASK_SH_LIST(mask_sh, ) + MI_DCP_MASK_SH_LIST(mask_sh,),\ + MI_DMIF_PG_MASK_SH_LIST(mask_sh,),\ + MI_DMIF_PG_MASK_SH_DCE(mask_sh,),\ + MI_GFX8_TILE_MASK_SH_LIST(mask_sh,) #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ @@ -113,6 +156,27 @@ struct dce_mem_input_registers { type GRPH_SW_MODE; \ type GRPH_NUM_SHADER_ENGINES; \ type GRPH_NUM_PIPES; \ + type PIXEL_DURATION; \ + type URGENCY_WATERMARK_MASK; \ + type PSTATE_CHANGE_WATERMARK_MASK; \ + type NB_PSTATE_CHANGE_WATERMARK_MASK; \ + type STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK; \ + type URGENCY_LOW_WATERMARK; \ + type URGENCY_HIGH_WATERMARK; \ + type NB_PSTATE_CHANGE_ENABLE; \ + type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST; \ + type NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \ + type NB_PSTATE_CHANGE_WATERMARK; \ + type PSTATE_CHANGE_ENABLE; \ + type PSTATE_CHANGE_URGENT_DURING_REQUEST; \ + type PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \ + type PSTATE_CHANGE_WATERMARK; \ + type STUTTER_ENABLE; \ + type STUTTER_IGNORE_FBC; \ + type STUTTER_EXIT_SELF_REFRESH_WATERMARK; \ + type DMIF_BUFFERS_ALLOCATED; \ + type DMIF_BUFFERS_ALLOCATION_COMPLETED; \ + type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\ struct dce_mem_input_shift { MI_REG_FIELD_LIST(uint8_t) @@ -122,6 +186,10 @@ struct dce_mem_input_mask { MI_REG_FIELD_LIST(uint32_t) }; +struct dce_mem_input_wa { + uint8_t single_head_rdreq_dmif_limit; +}; + struct mem_input; bool dce_mem_input_program_surface_config(struct mem_input *mi, enum surface_pixel_format format, @@ -131,4 +199,19 @@ bool dce_mem_input_program_surface_config(struct mem_input *mi, struct dc_plane_dcc_param *dcc, bool horizontal_mirror); +void dce_mem_input_allocate_dmif(struct mem_input *mi, + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz, + uint32_t total_stream_num); + +void dce_mem_input_free_dmif(struct mem_input *mi, + uint32_t total_stream_num); + +void dce_mem_input_program_display_marks(struct mem_input *mi, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + #endif /*__DCE_MEM_INPUT_H__*/ diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c index 6c17a52df574..851247c647a1 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c @@ -51,6 +51,10 @@ #include "dce/dce_10_0_d.h" #include "dce/dce_10_0_sh_mask.h" +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif #ifndef mmDP_DPHY_INTERNAL_CTRL #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 @@ -471,7 +475,10 @@ static const struct resource_create_funcs res_create_funcs = { .create_hwseq = dce100_hwseq_create, }; -#define mi_inst_regs(id) { MI_REG_LIST(id) } +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} static const struct dce_mem_input_registers mi_regs[] = { mi_inst_regs(0), mi_inst_regs(1), @@ -482,11 +489,13 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT) + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK) + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; static struct mem_input *dce100_mem_input_create( @@ -506,6 +515,7 @@ static struct mem_input *dce100_mem_input_create( mi->regs = &mi_regs[inst]; mi->shifts = &mi_shifts; mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 2; return mi; } diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c index 4092abe3812d..c0a68c6f585e 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c @@ -494,212 +494,11 @@ void dce110_mem_input_program_display_marks( stutter); } -static uint32_t get_dmif_switch_time_us( - uint32_t h_total, - uint32_t v_total, - uint32_t pix_clk_khz) -{ - uint32_t frame_time; - uint32_t pixels_per_second; - uint32_t pixels_per_frame; - uint32_t refresh_rate; - const uint32_t us_in_sec = 1000000; - const uint32_t min_single_frame_time_us = 30000; - /*return double of frame time*/ - const uint32_t single_frame_time_multiplier = 2; - - if (!h_total || v_total || !pix_clk_khz) - return single_frame_time_multiplier * min_single_frame_time_us; - - /*TODO: should we use pixel format normalized pixel clock here?*/ - pixels_per_second = pix_clk_khz * 1000; - pixels_per_frame = h_total * v_total; - - if (!pixels_per_second || !pixels_per_frame) { - /* avoid division by zero */ - ASSERT(pixels_per_frame); - ASSERT(pixels_per_second); - return single_frame_time_multiplier * min_single_frame_time_us; - } - - refresh_rate = pixels_per_second / pixels_per_frame; - - if (!refresh_rate) { - /* avoid division by zero*/ - ASSERT(refresh_rate); - return single_frame_time_multiplier * min_single_frame_time_us; - } - - frame_time = us_in_sec / refresh_rate; - - if (frame_time < min_single_frame_time_us) - frame_time = min_single_frame_time_us; - - frame_time *= single_frame_time_multiplier; - - return frame_time; -} - -void dce110_allocate_mem_input( - struct mem_input *mi, - uint32_t h_total,/* for current stream */ - uint32_t v_total,/* for current stream */ - uint32_t pix_clk_khz,/* for current stream */ - uint32_t total_stream_num) -{ - const uint32_t retry_delay = 10; - uint32_t retry_count = get_dmif_switch_time_us( - h_total, - v_total, - pix_clk_khz) / retry_delay; - - struct dce110_mem_input *bm110 = TO_DCE110_MEM_INPUT(mi); - uint32_t addr = bm110->offsets.pipe + mmPIPE0_DMIF_BUFFER_CONTROL; - uint32_t value; - uint32_t field; - uint32_t pix_dur; - - /*Allocate DMIF buffer*/ - value = dm_read_reg(mi->ctx, addr); - field = get_reg_field_value( - value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED); - if (field == 2) - goto register_underflow_int; - - set_reg_field_value( - value, - 2, - PIPE0_DMIF_BUFFER_CONTROL, - DMIF_BUFFERS_ALLOCATED); - - dm_write_reg(mi->ctx, addr, value); - - do { - value = dm_read_reg(mi->ctx, addr); - field = get_reg_field_value( - value, - PIPE0_DMIF_BUFFER_CONTROL, - DMIF_BUFFERS_ALLOCATION_COMPLETED); - - if (field) - break; - - udelay(retry_delay); - retry_count--; - - } while (retry_count > 0); - - if (field == 0) - dm_logger_write(mi->ctx->logger, LOG_ERROR, - "%s: DMIF allocation failed", - __func__); - - if (pix_clk_khz != 0) { - addr = mmDPG_PIPE_ARBITRATION_CONTROL1 + bm110->offsets.dmif; - value = dm_read_reg(mi->ctx, addr); - pix_dur = 1000000000ULL / pix_clk_khz; - - set_reg_field_value( - value, - pix_dur, - DPG_PIPE_ARBITRATION_CONTROL1, - PIXEL_DURATION); - - dm_write_reg(mi->ctx, addr, value); - } - - /* - * Stella Wong proposed the following change - * - * Value of mcHubRdReqDmifLimit.ENABLE: - * 00 - disable DMIF rdreq limit - * 01 - enable DMIF rdreq limit, disabled by DMIF stall = 1 || urg != 0 - * 02 - enable DMIF rdreq limit, disable by DMIF stall = 1 - * 03 - force enable DMIF rdreq limit, ignore DMIF stall / urgent - */ - if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) { - addr = mmMC_HUB_RDREQ_DMIF_LIMIT; - value = dm_read_reg(mi->ctx, addr); - - if (total_stream_num > 1) - set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); - else - set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); - dm_write_reg(mi->ctx, addr, value); - } - -register_underflow_int: - /*todo*/; - /*register_interrupt(bm110, irq_source, ctrl_id);*/ -} - -static void deallocate_dmif_buffer_helper( - struct dc_context *ctx, uint32_t offset) -{ - uint32_t value; - uint32_t count = 0xBB8; /* max retry count */ - - value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset); - - if (!get_reg_field_value( - value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED)) - return; - - set_reg_field_value( - value, 0, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED); - - dm_write_reg( - ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset, value); - - do { - value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset); - udelay(10); - count--; - } while (count > 0 && - !get_reg_field_value( - value, - PIPE0_DMIF_BUFFER_CONTROL, - DMIF_BUFFERS_ALLOCATION_COMPLETED)); -} - -void dce110_free_mem_input( - struct mem_input *mi, - uint32_t total_stream_num) -{ - struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi); - uint32_t value; - - /* De-allocate DMIF buffer first */ - if (mmPIPE0_DMIF_BUFFER_CONTROL + bm_dce110->offsets.pipe != 0) - deallocate_dmif_buffer_helper( - mi->ctx, bm_dce110->offsets.pipe); - - /* TODO: unregister underflow interrupt - unregisterInterrupt(); - */ - - /* Value of mcHubRdReqDmifLimit.ENABLE. - * 00 - disable dmif rdreq limit - * 01 - enable dmif rdreq limit, disable by dmif stall=1||urg!=0 - * 02 - enable dmif rdreq limit, disable by dmif stall=1 - * 03 - force enable dmif rdreq limit, ignore dmif stall/urgent - * Stella Wong proposed this change. */ - if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) { - value = dm_read_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT); - if (total_stream_num > 1) - set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); - else - set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); - - dm_write_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT, value); - } -} - static struct mem_input_funcs dce110_mem_input_funcs = { .mem_input_program_display_marks = dce110_mem_input_program_display_marks, - .allocate_mem_input = dce110_allocate_mem_input, - .free_mem_input = dce110_free_mem_input, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, .mem_input_program_surface_flip_and_addr = dce110_mem_input_program_surface_flip_and_addr, .mem_input_program_pte_vm = diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c index 7731f80db2fb..dac53df2cb86 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c @@ -54,6 +54,11 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif + #ifndef mmDP_DPHY_INTERNAL_CTRL #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 @@ -464,7 +469,10 @@ static const struct resource_create_funcs res_create_funcs = { .create_hwseq = dce110_hwseq_create, }; -#define mi_inst_regs(id) { MI_REG_LIST(id) } +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} static const struct dce_mem_input_registers mi_regs[] = { mi_inst_regs(0), mi_inst_regs(1), @@ -472,11 +480,13 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT) + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK) + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; static struct mem_input *dce110_mem_input_create( @@ -496,6 +506,7 @@ static struct mem_input *dce110_mem_input_create( mi->regs = &mi_regs[inst]; mi->shifts = &mi_shifts; mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 3; return mi; } diff --git a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c index 24b1b91abd71..c29007dafe21 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c +++ b/drivers/gpu/drm/amd/dal/dc/dce112/dce112_mem_input.c @@ -34,388 +34,6 @@ #define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) #define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) -static void program_urgency_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct bw_watermarks marks_low, - uint32_t total_dest_line_time_ns) -{ - /* register value */ - uint32_t urgency_cntl = 0; - uint32_t wm_mask_cntl = 0; - - uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; - uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - - /*Write mask to enable reading/writing of watermark set A*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 0, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value( - urgency_cntl, - marks_low.a_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value( - urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); - - /*Write mask to enable reading/writing of watermark set B*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 1, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value(urgency_cntl, - marks_low.b_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value(urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); - - /*Write mask to enable reading/writing of watermark set C*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 2, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value(urgency_cntl, - marks_low.c_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value(urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); - - /*Write mask to enable reading/writing of watermark set D*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 3, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value(urgency_cntl, - marks_low.d_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value(urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); -} - -static void program_stutter_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct bw_watermarks marks) -{ - /* register value */ - uint32_t stutter_cntl = 0; - uint32_t wm_mask_cntl = 0; - - uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL; - uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - - /*Write mask to enable reading/writing of watermark set A*/ - - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 0, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - - if (ctx->dc->debug.disable_stutter) { - set_reg_field_value(stutter_cntl, - 0, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE); - } else { - set_reg_field_value(stutter_cntl, - 1, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE); - } - - set_reg_field_value(stutter_cntl, - 1, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_IGNORE_FBC); - - /*Write watermark set A*/ - set_reg_field_value(stutter_cntl, - marks.a_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); - - /*Write mask to enable reading/writing of watermark set B*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 1, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - /*Write watermark set B*/ - set_reg_field_value(stutter_cntl, - marks.b_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); - - /*Write mask to enable reading/writing of watermark set C*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 2, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - /*Write watermark set C*/ - set_reg_field_value(stutter_cntl, - marks.c_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); - - /*Write mask to enable reading/writing of watermark set D*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 3, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - /*Write watermark set D*/ - set_reg_field_value(stutter_cntl, - marks.d_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); -} - -static void program_nbp_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct bw_watermarks marks) -{ - uint32_t value; - uint32_t addr; - /* Write mask to enable reading/writing of watermark set A */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 0, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set A */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.a_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); - - /* Write mask to enable reading/writing of watermark set B */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set B */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.b_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); - - /* Write mask to enable reading/writing of watermark set C */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 2, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set C */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.c_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); - - /* Write mask to enable reading/writing of watermark set D */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 3, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set D */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.d_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); -} - -static void dce112_mem_input_program_display_marks( - struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, - uint32_t total_dest_line_time_ns) -{ - struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); - - program_urgency_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - urgent, - total_dest_line_time_ns); - - program_nbp_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - nbp); - - program_stutter_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - stutter); -} - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -430,7 +48,7 @@ bool dce112_mem_input_construct( return false; mem_input110->base.funcs->mem_input_program_display_marks = - dce112_mem_input_program_display_marks; + dce_mem_input_program_display_marks; return true; } diff --git a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_mem_input.c index 8da0e31f1b6a..ebb8df3cdf4a 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_mem_input.c @@ -43,133 +43,11 @@ #define DMIF_REG(reg) (reg + mem_input80->offsets.dmif) #define PIPE_REG(reg) (reg + mem_input80->offsets.pipe) -static uint32_t get_dmif_switch_time_us( - uint32_t h_total, - uint32_t v_total, - uint32_t pix_clk_khz) -{ - uint32_t frame_time; - uint32_t pixels_per_second; - uint32_t pixels_per_frame; - uint32_t refresh_rate; - const uint32_t us_in_sec = 1000000; - const uint32_t min_single_frame_time_us = 30000; - /*return double of frame time*/ - const uint32_t single_frame_time_multiplier = 2; - - if (!h_total || v_total || !pix_clk_khz) - return single_frame_time_multiplier * min_single_frame_time_us; - - /*TODO: should we use pixel format normalized pixel clock here?*/ - pixels_per_second = pix_clk_khz * 1000; - pixels_per_frame = h_total * v_total; - - if (!pixels_per_second || !pixels_per_frame) { - /* avoid division by zero */ - ASSERT(pixels_per_frame); - ASSERT(pixels_per_second); - return single_frame_time_multiplier * min_single_frame_time_us; - } - - refresh_rate = pixels_per_second / pixels_per_frame; - - if (!refresh_rate) { - /* avoid division by zero*/ - ASSERT(refresh_rate); - return single_frame_time_multiplier * min_single_frame_time_us; - } - - frame_time = us_in_sec / refresh_rate; - - if (frame_time < min_single_frame_time_us) - frame_time = min_single_frame_time_us; - - frame_time *= single_frame_time_multiplier; - - return frame_time; -} - -static void allocate_mem_input( - struct mem_input *mi, - uint32_t h_total, - uint32_t v_total, - uint32_t pix_clk_khz, - uint32_t total_targets_num) -{ - const uint32_t retry_delay = 10; - uint32_t retry_count = get_dmif_switch_time_us( - h_total, - v_total, - pix_clk_khz) / retry_delay; - - struct dce110_mem_input *bm80 = TO_DCE110_MEM_INPUT(mi); - uint32_t addr = bm80->offsets.pipe + mmPIPE0_DMIF_BUFFER_CONTROL; - uint32_t value; - uint32_t field; - - /*Allocate DMIF buffer*/ - value = dm_read_reg(mi->ctx, addr); - field = get_reg_field_value( - value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED); - if (field == 2) - goto register_underflow_int; - - set_reg_field_value( - value, - 2, - PIPE0_DMIF_BUFFER_CONTROL, - DMIF_BUFFERS_ALLOCATED); - - dm_write_reg(mi->ctx, addr, value); - - do { - value = dm_read_reg(mi->ctx, addr); - field = get_reg_field_value( - value, - PIPE0_DMIF_BUFFER_CONTROL, - DMIF_BUFFERS_ALLOCATION_COMPLETED); - - if (field) - break; - - udelay(retry_delay); - retry_count--; - - } while (retry_count > 0); - - if (field == 0) - dm_logger_write(mi->ctx->logger, LOG_ERROR, - "%s: DMIF allocation failed", - __func__); - - /* - * Stella Wong proposed the following change - * - * Value of mcHubRdReqDmifLimit.ENABLE: - * 00 - disable DMIF rdreq limit - * 01 - enable DMIF rdreq limit, disabled by DMIF stall = 1 || urg != 0 - * 02 - enable DMIF rdreq limit, disable by DMIF stall = 1 - * 03 - force enable DMIF rdreq limit, ignore DMIF stall / urgent - */ - addr = mmMC_HUB_RDREQ_DMIF_LIMIT; - value = dm_read_reg(mi->ctx, addr); - if (total_targets_num > 1) - set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); - else - set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE); - dm_write_reg(mi->ctx, addr, value); - -register_underflow_int: - /*todo*/; - /*register_interrupt(bm80, irq_source, ctrl_id);*/ -} - static struct mem_input_funcs dce80_mem_input_funcs = { .mem_input_program_display_marks = dce110_mem_input_program_display_marks, - .allocate_mem_input = allocate_mem_input, - .free_mem_input = - dce110_free_mem_input, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, .mem_input_program_surface_flip_and_addr = dce110_mem_input_program_surface_flip_and_addr, .mem_input_program_surface_config = diff --git a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c index d2fd25b97996..73110341cb4d 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c @@ -56,6 +56,11 @@ /* TODO remove this include */ +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" +#endif + #ifndef mmDP_DPHY_INTERNAL_CTRL #define mmDP_DPHY_INTERNAL_CTRL 0x1CDE #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE @@ -453,7 +458,10 @@ static const struct resource_create_funcs res_create_funcs = { .create_hwseq = dce80_hwseq_create, }; -#define mi_inst_regs(id) { MI_REG_LIST(id) } +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} static const struct dce_mem_input_registers mi_regs[] = { mi_inst_regs(0), mi_inst_regs(1), @@ -464,11 +472,13 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT) + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK) + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; static struct mem_input *dce80_mem_input_create( @@ -488,6 +498,7 @@ static struct mem_input *dce80_mem_input_create( mi->regs = &mi_regs[inst]; mi->shifts = &mi_shifts; mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 2; return mi; } diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services.h b/drivers/gpu/drm/amd/dal/dc/dm_services.h index 289264403983..9cb874a03d54 100644 --- a/drivers/gpu/drm/amd/dal/dc/dm_services.h +++ b/drivers/gpu/drm/amd/dal/dc/dm_services.h @@ -70,10 +70,9 @@ #endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ - -#define DC_ERR(err_msg) do { \ +#define DC_ERR(...) do { \ + dm_error(__VA_ARGS__); \ BREAK_TO_DEBUGGER(); \ - dm_error(err_msg); \ } while (0) #define dm_alloc(size) kzalloc(size, GFP_KERNEL) @@ -202,7 +201,8 @@ uint32_t generic_reg_update_ex(const struct dc_context *ctx, */ unsigned int generic_reg_wait(const struct dc_context *ctx, uint32_t addr, uint32_t mask, uint32_t shift, uint32_t condition_value, - unsigned int delay_between_poll_us, unsigned int time_out_num_tries); + unsigned int delay_between_poll_us, unsigned int time_out_num_tries, + const char *func_name); /************************************** * Power Play (PP) interfaces diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/dal/dc/inc/hw/mem_input.h index e7026ec87bce..78dab74edc2d 100644 --- a/drivers/gpu/drm/amd/dal/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/dal/dc/inc/hw/mem_input.h @@ -48,6 +48,7 @@ struct mem_input { const struct dce_mem_input_registers *regs; const struct dce_mem_input_shift *shifts; const struct dce_mem_input_mask *masks; + struct dce_mem_input_wa wa; }; struct mem_input_funcs { diff --git a/drivers/gpu/drm/amd/dal/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/dal/dc/inc/reg_helper.h index 7a05141484c9..92a699337322 100644 --- a/drivers/gpu/drm/amd/dal/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/dal/dc/inc/reg_helper.h @@ -156,7 +156,7 @@ #define REG_WAIT(reg_name, field, val, delay, max_try) \ generic_reg_wait(CTX, \ REG(reg_name), FN(reg_name, field), val,\ - delay, max_try) + delay, max_try, __func__) /* macro to update (read, modify, write) register fields */ -- 2.10.1