From 3534a935d81f0487de2dc4f45453578c1d224dde Mon Sep 17 00:00:00 2001 From: David Rokhvarg Date: Thu, 11 Feb 2016 14:01:39 -0500 Subject: [PATCH 0792/1110] drm/amd/dal: Instantiate Underlay version of Memory Input (surface). Signed-off-by: David Rokhvarg Acked-by: Harry Wentland --- .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c | 1 + drivers/gpu/drm/amd/dal/dc/dce110/Makefile | 3 +- .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.c | 899 +++++++++++++++++++++ .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.h | 84 ++ 4 files changed, 986 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.c create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.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 efa592f..dcf44d4 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c @@ -36,6 +36,7 @@ #include "dce110/dce110_timing_generator.h" #include "dce110/dce110_link_encoder.h" #include "dce110/dce110_mem_input.h" +#include "dce110/dce110_mem_input_v.h" #include "dce110/dce110_ipp.h" #include "dce110/dce110_transform.h" #include "dce110/dce110_stream_encoder.h" diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile index deae715..404b2bf 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile @@ -9,7 +9,8 @@ dce110_timing_generator.o dce110_transform.o dce110_transform_v.o \ dce110_transform_gamut.o dce110_transform_scl.o dce110_opp_csc.o\ dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ dce110_resource.o dce110_transform_bit_depth.o dce110_clock_source.o \ -dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o +dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ +dce110_mem_input_v.o AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110)) diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.c new file mode 100644 index 0000000..8a211d8 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.c @@ -0,0 +1,899 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * 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 "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" + +#include "include/logger_interface.h" +#include "adapter_service_interface.h" +#include "inc/bandwidth_calcs.h" + +#include "dce110_mem_input.h" + + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +/*#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif)*/ +/*#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe)*/ + + +static const struct dce110_mem_input_reg_offsets dce110_mi_v_reg_offsets[] = { + { + .dcp = 0, + .dmif = 0, + .pipe = 0, + } +}; + +static void set_flip_control( + struct dce110_mem_input *mem_input110, + bool immediate) +{ + uint32_t value = 0; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_FLIP_CONTROL)); + + set_reg_field_value(value, 1, + UNP_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_PENDING_MODE); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_FLIP_CONTROL), + value); +} + +/* chroma part */ +static void program_pri_addr_c( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + /*high register MUST be programmed first*/ + temp = address.high_part & +UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MASK; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C, + GRPH_PRIMARY_SURFACE_ADDRESS_C); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C), + value); +} + +/* luma part */ +static void program_pri_addr_l( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + + /*high register MUST be programmed first*/ + temp = address.high_part & +UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, + GRPH_PRIMARY_SURFACE_ADDRESS_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L), + value); +} + +static void program_addr( + struct dce110_mem_input *mem_input110, + const struct dc_plane_address *addr) +{ + switch (addr->type) { + case PLN_ADDR_TYPE_GRAPHICS: + program_pri_addr_l( + mem_input110, + addr->grph.addr); + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + program_pri_addr_l( + mem_input110, + addr->video_progressive.luma_addr); + program_pri_addr_c( + mem_input110, + addr->video_progressive.chroma_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + } +} + +static void enable(struct dce110_mem_input *mem_input110) +{ + uint32_t value = 0; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_ENABLE)); + set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_ENABLE), + value); +} + +static void program_tiling( + struct dce110_mem_input *mem_input110, + const struct dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + uint32_t value = 0; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL)); + + set_reg_field_value(value, info->num_banks, + UNP_GRPH_CONTROL, GRPH_NUM_BANKS); + + set_reg_field_value(value, info->bank_width, + UNP_GRPH_CONTROL, GRPH_BANK_WIDTH_L); + + set_reg_field_value(value, info->bank_height, + UNP_GRPH_CONTROL, GRPH_BANK_HEIGHT_L); + + set_reg_field_value(value, info->tile_aspect, + UNP_GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT_L); + + set_reg_field_value(value, info->tile_split, + UNP_GRPH_CONTROL, GRPH_TILE_SPLIT_L); + + set_reg_field_value(value, info->tile_mode, + UNP_GRPH_CONTROL, GRPH_MICRO_TILE_MODE_L); + + set_reg_field_value(value, info->pipe_config, + UNP_GRPH_CONTROL, GRPH_PIPE_CONFIG); + + set_reg_field_value(value, info->array_mode, + UNP_GRPH_CONTROL, GRPH_ARRAY_MODE); + + set_reg_field_value(value, 1, + UNP_GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE); + + set_reg_field_value(value, 0, + UNP_GRPH_CONTROL, GRPH_Z); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL), + value); +} + +static void program_size_and_rotation( + struct dce110_mem_input *mem_input110, + enum dc_rotation_angle rotation, + const union plane_size *plane_size) +{ + uint32_t value = 0; + union plane_size local_size = *plane_size; + + if (rotation == ROTATION_ANGLE_90 || + rotation == ROTATION_ANGLE_270) { + + uint32_t swap; + swap = local_size.video.luma_size.x; + local_size.video.luma_size.x = + local_size.video.luma_size.y; + local_size.video.luma_size.y = swap; + + swap = local_size.video.luma_size.width; + local_size.video.luma_size.width = + local_size.video.luma_size.height; + local_size.video.luma_size.height = swap; + + swap = local_size.video.chroma_size.x; + local_size.video.chroma_size.x = + local_size.video.chroma_size.y; + local_size.video.chroma_size.y = swap; + + swap = local_size.video.chroma_size.width; + local_size.video.chroma_size.width = + local_size.video.chroma_size.height; + local_size.video.chroma_size.height = swap; + } + + value = 0; + set_reg_field_value(value, local_size.video.luma_pitch, + UNP_GRPH_PITCH_L, GRPH_PITCH_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PITCH_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_pitch, + UNP_GRPH_PITCH_C, GRPH_PITCH_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PITCH_C), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_X_START_L, GRPH_X_START_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_START_L), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_X_START_C, GRPH_X_START_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_START_C), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_Y_START_L, GRPH_Y_START_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_START_L), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_Y_START_C, GRPH_Y_START_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_START_C), + value); + + value = 0; + set_reg_field_value(value, local_size.video.luma_size.x + + local_size.video.luma_size.width, + UNP_GRPH_X_END_L, GRPH_X_END_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_END_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_size.x + + local_size.video.chroma_size.width, + UNP_GRPH_X_END_C, GRPH_X_END_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_END_C), + value); + + value = 0; + set_reg_field_value(value, local_size.video.luma_size.y + + local_size.video.luma_size.height, + UNP_GRPH_Y_END_L, GRPH_Y_END_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_END_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_size.y + + local_size.video.chroma_size.height, + UNP_GRPH_Y_END_C, GRPH_Y_END_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_END_C), + value); + + value = 0; + switch (rotation) { + case ROTATION_ANGLE_90: + set_reg_field_value(value, 3, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + case ROTATION_ANGLE_180: + set_reg_field_value(value, 2, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + case ROTATION_ANGLE_270: + set_reg_field_value(value, 1, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + default: + set_reg_field_value(value, 0, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + } + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_HW_ROTATION), + value); +} + +static void program_pixel_format( + struct dce110_mem_input *mem_input110, + enum surface_pixel_format format) +{ + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN || + format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + uint32_t value; + uint8_t grph_depth; + uint8_t grph_format; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL)); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + grph_depth = 0; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + grph_depth = 1; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + grph_depth = 2; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + grph_depth = 2; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + grph_depth = 3; + grph_format = 0; + break; + default: + grph_depth = 2; + grph_format = 0; + break; + } + + set_reg_field_value( + value, + grph_depth, + UNP_GRPH_CONTROL, + GRPH_DEPTH); + set_reg_field_value( + value, + grph_format, + UNP_GRPH_CONTROL, + GRPH_FORMAT); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL), + value); + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + + /* VIDEO FORMAT 0 */ + set_reg_field_value( + value, + 0, + UNP_GRPH_CONTROL_EXP, + VIDEO_FORMAT); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP), + value); + + } else { + /* Video 422 and 420 needs UNP_GRPH_CONTROL_EXP programmed */ + uint32_t value; + uint8_t video_format; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + + switch (format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + video_format = 2; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + video_format = 3; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_YCb: + video_format = 4; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_YCr: + video_format = 5; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CbY: + video_format = 6; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_422_CrY: + video_format = 7; + break; + default: + break; + } + + set_reg_field_value( + value, + video_format, + UNP_GRPH_CONTROL_EXP, + VIDEO_FORMAT); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP), + value); + } +} + +static void wait_for_no_surface_update_pending( + struct dce110_mem_input *mem_input110) +{ + uint32_t value; + + do { + value = dm_read_reg(mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_UPDATE)); + + } while (get_reg_field_value(value, UNP_GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)); +} + +bool dce110_mem_input_v_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + set_flip_control(mem_input110, flip_immediate); + program_addr(mem_input110, + address); + + if (flip_immediate) + wait_for_no_surface_update_pending(mem_input110); + + return true; +} + +bool dce110_mem_input_v_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + struct dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + enable(mem_input110); + program_tiling(mem_input110, tiling_info, format); + program_size_and_rotation(mem_input110, rotation, plane_size); + program_pixel_format(mem_input110, format); + + return true; +} + +static void program_urgency_watermark( + const struct dc_context *ctx, + const uint32_t urgency_addr, + const uint32_t wm_addr, + 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; + + /*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, + 1, + DPGV0_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, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value( + urgency_cntl, + total_dest_line_time_ns, + DPGV0_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, + 2, + DPGV0_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, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value(urgency_cntl, + total_dest_line_time_ns, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + + dm_write_reg(ctx, urgency_addr, urgency_cntl); +} + +static void program_urgency_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark( + ctx, + mmDPGV0_PIPE_URGENCY_CONTROL, + mmDPGV0_WATERMARK_MASK_CONTROL, + marks_low, + total_dest_line_time_ns); +} + +static void program_urgency_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark( + ctx, + mmDPGV1_PIPE_URGENCY_CONTROL, + mmDPGV1_WATERMARK_MASK_CONTROL, + marks_low, + total_dest_line_time_ns); +} + +static void program_stutter_watermark( + const struct dc_context *ctx, + const uint32_t stutter_addr, + const uint32_t wm_addr, + struct bw_watermarks marks) +{ + /* register value */ + uint32_t stutter_cntl = 0; + uint32_t wm_mask_cntl = 0; + + /*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, + 1, + DPGV0_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); + + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set A*/ + set_reg_field_value(stutter_cntl, + marks.a_mark, + DPGV0_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, + 2, + DPGV0_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); + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set B*/ + set_reg_field_value(stutter_cntl, + marks.b_mark, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); +} + +static void program_stutter_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_stutter_watermark(ctx, + mmDPGV0_PIPE_STUTTER_CONTROL, + mmDPGV0_WATERMARK_MASK_CONTROL, + marks); +} + +static void program_stutter_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_stutter_watermark(ctx, + mmDPGV1_PIPE_STUTTER_CONTROL, + mmDPGV1_WATERMARK_MASK_CONTROL, + marks); +} + +static void program_nbp_watermark( + const struct dc_context *ctx, + const uint32_t wm_mask_ctrl_addr, + const uint32_t nbp_pstate_ctrl_addr, + struct bw_watermarks marks) +{ + uint32_t value; + + /* Write mask to enable reading/writing of watermark set A */ + + value = dm_read_reg(ctx, wm_mask_ctrl_addr); + + set_reg_field_value( + value, + 1, + DPGV0_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, wm_mask_ctrl_addr, value); + + + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write watermark set A */ + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + marks.a_mark, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write mask to enable reading/writing of watermark set B */ + value = dm_read_reg(ctx, wm_mask_ctrl_addr); + set_reg_field_value( + value, + 2, + DPGV0_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, wm_mask_ctrl_addr, value); + + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write watermark set B */ + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + marks.b_mark, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); +} + +static void program_nbp_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_nbp_watermark(ctx, + mmDPGV0_WATERMARK_MASK_CONTROL, + mmDPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + marks); +} + +static void program_nbp_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_nbp_watermark(ctx, + mmDPGV1_WATERMARK_MASK_CONTROL, + mmDPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL, + marks); +} + +void dce110_mem_input_v_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) +{ + program_urgency_watermark_l( + mem_input->ctx, + urgent, + total_dest_line_time_ns); + + program_urgency_watermark_c( + mem_input->ctx, + urgent, + total_dest_line_time_ns); + + program_nbp_watermark_l( + mem_input->ctx, + nbp); + + program_nbp_watermark_c( + mem_input->ctx, + nbp); + + program_stutter_watermark_l( + mem_input->ctx, + stutter); + + program_stutter_watermark_c( + mem_input->ctx, + stutter); +} + + +void dce110_allocate_mem_input_v( + 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) +{ +} + +void dce110_free_mem_input_v( + struct mem_input *mi, + uint32_t total_stream_num) +{ +} + +static struct mem_input_funcs dce110_mem_input_v_funcs = { + .mem_input_program_display_marks = + dce110_mem_input_v_program_display_marks, + .allocate_mem_input = dce110_allocate_mem_input_v, + .free_mem_input = dce110_free_mem_input_v, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_v_program_surface_flip_and_addr, + .mem_input_program_surface_config = + dce110_mem_input_v_program_surface_config, +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_mem_input_v_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx) +{ + mem_input110->base.funcs = &dce110_mem_input_v_funcs; + mem_input110->base.ctx = ctx; + + mem_input110->base.inst = 0; + + mem_input110->offsets = dce110_mi_v_reg_offsets[0]; + + mem_input110->supported_stutter_mode = 0; + dal_adapter_service_get_feature_value(FEATURE_STUTTER_MODE, + &(mem_input110->supported_stutter_mode), + sizeof(mem_input110->supported_stutter_mode)); + + return true; +} + +#if 0 +void dce110_mem_input_v_destroy(struct mem_input **mem_input) +{ + dm_free((*mem_input)->ctx, TO_DCE110_MEM_INPUT(*mem_input)); + *mem_input = NULL; +} +#endif diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.h new file mode 100644 index 0000000..529aace --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input_v.h @@ -0,0 +1,84 @@ +/* Copyright 2012-16 Advanced Micro Devices, Inc. + * + * 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_MEM_INPUT_V_DCE110_H__ +#define __DC_MEM_INPUT_V_DCE110_H__ + +#include "inc/mem_input.h" +#include "dce110_mem_input.h" + +bool dce110_mem_input_v_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx); + +/* + * This function will program nbp stutter and urgency watermarks to minimum + * allowable values + */ +void dce110_mem_input_v_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); + +/* + * This function will allocate a dmif buffer and program required + * pixel duration for pipe + */ +void dce110_allocate_mem_v_input( + struct mem_input *mem_input, + 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); + +/* + * This function will deallocate a dmif buffer from pipe + */ +void dce110_free_mem_v_input( + struct mem_input *mem_input, + uint32_t total_stream_num); + +/* + * This function programs hsync/vsync mode and surface address + */ +bool dce110_mem_input_v_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +/* + * This function will program surface tiling, size, rotation and pixel format + * to corresponding dcp registers. + */ +bool dce110_mem_input_v_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + struct dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation); + + +#endif -- 2.7.4