aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0792-drm-amd-dal-Instantiate-Underlay-version-of-Memory-I.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0792-drm-amd-dal-Instantiate-Underlay-version-of-Memory-I.patch')
-rw-r--r--common/recipes-kernel/linux/files/0792-drm-amd-dal-Instantiate-Underlay-version-of-Memory-I.patch1041
1 files changed, 1041 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0792-drm-amd-dal-Instantiate-Underlay-version-of-Memory-I.patch b/common/recipes-kernel/linux/files/0792-drm-amd-dal-Instantiate-Underlay-version-of-Memory-I.patch
new file mode 100644
index 00000000..2da4f723
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0792-drm-amd-dal-Instantiate-Underlay-version-of-Memory-I.patch
@@ -0,0 +1,1041 @@
+From 3534a935d81f0487de2dc4f45453578c1d224dde Mon Sep 17 00:00:00 2001
+From: David Rokhvarg <David.Rokhvarg@amd.com>
+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 <David.Rokhvarg@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ .../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
+