aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0773-drm-amd-dal-Create-transform-for-underlay-pipe.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0773-drm-amd-dal-Create-transform-for-underlay-pipe.patch')
-rw-r--r--common/recipes-kernel/linux/files/0773-drm-amd-dal-Create-transform-for-underlay-pipe.patch1433
1 files changed, 1433 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0773-drm-amd-dal-Create-transform-for-underlay-pipe.patch b/common/recipes-kernel/linux/files/0773-drm-amd-dal-Create-transform-for-underlay-pipe.patch
new file mode 100644
index 00000000..7e4c61d8
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0773-drm-amd-dal-Create-transform-for-underlay-pipe.patch
@@ -0,0 +1,1433 @@
+From 0caa42dd0f4b24160cda117448794f3fef427b32 Mon Sep 17 00:00:00 2001
+From: Eric Yang <eric.yang2@amd.com>
+Date: Wed, 3 Feb 2016 15:02:13 -0500
+Subject: [PATCH 0773/1110] drm/amd/dal: Create transform for underlay pipe
+
+Signed-off-by: Eric Yang <eric.yang2@amd.com>
+Acked-by: Jordan Lazare <Jordan.Lazare@amd.com>
+---
+ drivers/gpu/drm/amd/dal/dc/dce110/Makefile | 4 +-
+ .../amd/dal/dc/dce110/dce110_transform_bit_depth.c | 115 ++++
+ .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c | 531 ----------------
+ .../gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c | 674 +++++++++++++++++++++
+ .../gpu/drm/amd/dal/dc/dce110/dce110_transform_v.h | 44 ++
+ 5 files changed, 835 insertions(+), 533 deletions(-)
+ delete mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
+ create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c
+ create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.h
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
+index ae9d2de..2d0007b 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
+@@ -5,8 +5,8 @@
+ DCE110 = dce110_ipp.o dce110_ipp_cursor.o \
+ dce110_ipp_gamma.o dce110_link_encoder.o dce110_opp.o \
+ dce110_opp_formatter.o dce110_opp_regamma.o dce110_stream_encoder.o \
+-dce110_timing_generator.o dce110_transform.o dce110_transform_gamut.o \
+-dce110_transform_scl.o dce110_transform_sclv.o dce110_opp_csc.o\
++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
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
+index fb5ef6d..70dedbc 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
+@@ -30,6 +30,7 @@
+ #include "dce/dce_11_0_sh_mask.h"
+
+ #include "dce110_transform.h"
++#include "dce110_transform_v.h"
+ #include "opp.h"
+ #include "include/logger_interface.h"
+ #include "include/fixed32_32.h"
+@@ -849,3 +850,117 @@ bool dce110_transform_power_up_line_buffer(struct transform *xfm)
+ return true;
+ }
+
++/* Underlay pipe functions*/
++
++bool dce110_transform_v_get_current_pixel_storage_depth(
++ struct transform *xfm,
++ enum lb_pixel_depth *depth)
++{
++ uint32_t value = 0;
++
++ if (depth == NULL)
++ return false;
++
++ value = dm_read_reg(
++ xfm->ctx,
++ mmLBV_DATA_FORMAT);
++
++ switch (get_reg_field_value(value, LBV_DATA_FORMAT, PIXEL_DEPTH)) {
++ case 0:
++ *depth = LB_PIXEL_DEPTH_30BPP;
++ break;
++ case 1:
++ *depth = LB_PIXEL_DEPTH_24BPP;
++ break;
++ case 2:
++ *depth = LB_PIXEL_DEPTH_18BPP;
++ break;
++ case 3:
++ *depth = LB_PIXEL_DEPTH_36BPP;
++ break;
++ default:
++ dal_logger_write(xfm->ctx->logger,
++ LOG_MAJOR_WARNING,
++ LOG_MINOR_COMPONENT_GPU,
++ "%s: Invalid LB pixel depth",
++ __func__);
++ *depth = LB_PIXEL_DEPTH_30BPP;
++ break;
++ }
++ return true;
++
++}
++
++bool dce110_transform_v_set_pixel_storage_depth(
++ struct transform *xfm,
++ enum lb_pixel_depth depth,
++ const struct bit_depth_reduction_params *bit_depth_params)
++{
++ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
++ bool ret = true;
++ uint32_t value;
++ enum dc_color_depth color_depth;
++
++ value = dm_read_reg(
++ xfm->ctx,
++ LB_REG(mmLBV_DATA_FORMAT));
++ switch (depth) {
++ case LB_PIXEL_DEPTH_18BPP:
++ color_depth = COLOR_DEPTH_666;
++ set_reg_field_value(value, 2, LBV_DATA_FORMAT, PIXEL_DEPTH);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, PIXEL_EXPAN_MODE);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, PIXEL_REDUCE_MODE);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, DITHER_EN);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, DOWNSCALE_PREFETCH_EN);
++ break;
++ case LB_PIXEL_DEPTH_24BPP:
++ color_depth = COLOR_DEPTH_888;
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, PIXEL_DEPTH);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, PIXEL_EXPAN_MODE);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, PIXEL_REDUCE_MODE);
++ set_reg_field_value(value, 0, LBV_DATA_FORMAT, DITHER_EN);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, DOWNSCALE_PREFETCH_EN);
++ break;
++ case LB_PIXEL_DEPTH_30BPP:
++ color_depth = COLOR_DEPTH_101010;
++ set_reg_field_value(value, 0, LBV_DATA_FORMAT, PIXEL_DEPTH);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, PIXEL_EXPAN_MODE);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, PIXEL_REDUCE_MODE);
++ set_reg_field_value(value, 0, LBV_DATA_FORMAT, DITHER_EN);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, DOWNSCALE_PREFETCH_EN);
++ break;
++ case LB_PIXEL_DEPTH_36BPP:
++ color_depth = COLOR_DEPTH_121212;
++ set_reg_field_value(value, 3, LBV_DATA_FORMAT, PIXEL_DEPTH);
++ set_reg_field_value(value, 0, LBV_DATA_FORMAT, PIXEL_EXPAN_MODE);
++ set_reg_field_value(value, 0, LBV_DATA_FORMAT, PIXEL_REDUCE_MODE);
++ set_reg_field_value(value, 0, LBV_DATA_FORMAT, DITHER_EN);
++ set_reg_field_value(value, 1, LBV_DATA_FORMAT, DOWNSCALE_PREFETCH_EN);
++ break;
++ default:
++ ret = false;
++ break;
++ }
++
++ if (ret == true) {
++ set_denormalization(xfm110, color_depth);
++ ret = program_bit_depth_reduction(xfm110, color_depth,
++ bit_depth_params);
++
++ set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN);
++ dm_write_reg(
++ xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value);
++ if (!(xfm110->lb_pixel_depth_supported & depth)) {
++ /*we should use unsupported capabilities
++ * unless it is required by w/a*/
++ dal_logger_write(xfm->ctx->logger,
++ LOG_MAJOR_WARNING,
++ LOG_MINOR_COMPONENT_GPU,
++ "%s: Capability not supported",
++ __func__);
++ }
++ }
++
++ return ret;
++}
++
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
+deleted file mode 100644
+index 1968296..0000000
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
++++ /dev/null
+@@ -1,531 +0,0 @@
+-/* Copyright 2012-15 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"
+-
+-#include "dce110_transform.h"
+-
+-#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_CONTROLLER,\
+- "TRANSFORM SCALER:%s()\n", __func__)
+-
+-/*
+-*****************************************************************************
+-* Function: calculateViewport
+-*
+-* @brief
+-* Calculates all of the data required to set the viewport
+-*
+-* @param [in] pData: scaler settings data
+-* @param [out] pLumaVp: luma viewport information
+-* @param [out] pChromaVp: chroma viewport information
+-* @param [out] srcResCx2: source chroma resolution times 2 - for multi-taps
+-*
+-*****************************************************************************
+-*/
+-static void calculate_viewport(
+- const struct scaler_data *scl_data,
+- struct rect *luma_viewport,
+- struct rect *chroma_viewport)
+-{
+- /*Do not set chroma vp for rgb444 pixel format*/
+- luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
+- luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
+- luma_viewport->width =
+- scl_data->viewport.width - scl_data->viewport.width % 2;
+- luma_viewport->height =
+- scl_data->viewport.height - scl_data->viewport.height % 2;
+-
+-
+- if (scl_data->dal_pixel_format == PIXEL_FORMAT_422BPP16) {
+- luma_viewport->width += luma_viewport->width % 2;
+-
+- chroma_viewport->x = luma_viewport->x / 2;
+- chroma_viewport->width = luma_viewport->width / 2;
+- } else if (scl_data->dal_pixel_format == PIXEL_FORMAT_420BPP12) {
+- luma_viewport->height += luma_viewport->height % 2;
+- luma_viewport->width += luma_viewport->width % 2;
+- /*for 420 video chroma is 1/4 the area of luma, scaled
+- *vertically and horizontally
+- */
+- chroma_viewport->x = luma_viewport->x / 2;
+- chroma_viewport->y = luma_viewport->y / 2;
+- chroma_viewport->height = luma_viewport->height / 2;
+- chroma_viewport->width = luma_viewport->width / 2;
+- }
+-}
+-
+-
+-static void program_viewport(
+- struct dce110_transform *xfm110,
+- struct rect *luma_view_port,
+- struct rect *chroma_view_port)
+-{
+- struct dc_context *ctx = xfm110->base.ctx;
+- uint32_t value = 0;
+- uint32_t addr = 0;
+-
+- if (luma_view_port->width != 0 && luma_view_port->height != 0) {
+- addr = mmSCLV_VIEWPORT_START;
+- value = 0;
+- set_reg_field_value(
+- value,
+- luma_view_port->x,
+- SCLV_VIEWPORT_START,
+- VIEWPORT_X_START);
+- set_reg_field_value(
+- value,
+- luma_view_port->y,
+- SCLV_VIEWPORT_START,
+- VIEWPORT_Y_START);
+- dm_write_reg(ctx, addr, value);
+-
+- addr = mmSCLV_VIEWPORT_SIZE;
+- value = 0;
+- set_reg_field_value(
+- value,
+- luma_view_port->height,
+- SCLV_VIEWPORT_SIZE,
+- VIEWPORT_HEIGHT);
+- set_reg_field_value(
+- value,
+- luma_view_port->width,
+- SCLV_VIEWPORT_SIZE,
+- VIEWPORT_WIDTH);
+- dm_write_reg(ctx, addr, value);
+- }
+-
+- if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
+- addr = mmSCLV_VIEWPORT_START_C;
+- value = 0;
+- set_reg_field_value(
+- value,
+- chroma_view_port->x,
+- SCLV_VIEWPORT_START_C,
+- VIEWPORT_X_START_C);
+- set_reg_field_value(
+- value,
+- chroma_view_port->y,
+- SCLV_VIEWPORT_START_C,
+- VIEWPORT_Y_START_C);
+- dm_write_reg(ctx, addr, value);
+-
+- addr = mmSCLV_VIEWPORT_SIZE_C;
+- value = 0;
+- set_reg_field_value(
+- value,
+- chroma_view_port->height,
+- SCLV_VIEWPORT_SIZE_C,
+- VIEWPORT_HEIGHT_C);
+- set_reg_field_value(
+- value,
+- chroma_view_port->width,
+- SCLV_VIEWPORT_SIZE_C,
+- VIEWPORT_WIDTH_C);
+- dm_write_reg(ctx, addr, value);
+- }
+- /* TODO: add stereo support */
+-}
+-
+-
+-/* Until and For MPO video play story, to reduce time for implementation,
+- * below limits are applied for now: 2_TAPS only
+- * Use auto-calculated filter values
+- * Following routines will be empty for now:
+- *
+- * programSclRatiosInits -- calcualate scaler ratio manually
+- * calculateInits --- calcualate scaler ratio manually
+- * programFilter -- multi-taps
+- * GetOptimalNumberOfTaps -- will hard coded to 2 TAPS
+- * GetNextLowerNumberOfTaps -- will hard coded to 2TAPS
+- * validateRequestedScaleRatio - used by GetOptimalNumberOfTaps internally
+- */
+-
+-/**
+-* Function:
+-* void setup_scaling_configuration
+-*
+-* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+-* Input: data
+-*
+-* Output:
+- void
+-*/
+-static bool setup_scaling_configuration(
+- struct dce110_transform *xfm110,
+- const struct scaler_data *data)
+-{
+- bool is_scaling_needed = false;
+- struct dc_context *ctx = xfm110->base.ctx;
+- uint32_t value = 0;
+-
+- if (data->taps.h_taps + data->taps.v_taps > 2) {
+- set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
+- set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
+- is_scaling_needed = true;
+- } else {
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+- }
+-
+- if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
+- set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
+- set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
+- is_scaling_needed = true;
+- } else if (data->dal_pixel_format != PIXEL_FORMAT_420BPP12 &&
+- data->dal_pixel_format != PIXEL_FORMAT_422BPP16) {
+- set_reg_field_value(
+- value,
+- get_reg_field_value(value, SCLV_MODE, SCL_MODE),
+- SCLV_MODE,
+- SCL_MODE_C);
+- set_reg_field_value(
+- value,
+- get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
+- SCLV_MODE,
+- SCL_PSCL_EN_C);
+- } else {
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+- }
+- dm_write_reg(ctx, mmSCLV_MODE, value);
+-
+- {
+- value = dm_read_reg(ctx, mmSCLV_TAP_CONTROL);
+-
+- set_reg_field_value(value, data->taps.h_taps - 1,
+- SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+-
+- set_reg_field_value(value, data->taps.v_taps - 1,
+- SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+-
+- set_reg_field_value(value, data->taps.h_taps_c - 1,
+- SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
+-
+- set_reg_field_value(value, data->taps.v_taps_c - 1,
+- SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
+-
+- dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
+- }
+-
+- {
+- /* we can ignore this register because we are ok with hw
+- * default 0 -- change to 1 according to dal2 code*/
+- value = dm_read_reg(ctx, mmSCLV_CONTROL);
+- /* 0 - Replaced out of bound pixels with black pixel
+- * (or any other required color) */
+- set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
+-
+- /* 1 - Replaced out of bound pixels with the edge pixel. */
+- dm_write_reg(ctx, mmSCLV_CONTROL, value);
+- }
+-
+- return is_scaling_needed;
+-}
+-
+-/**
+-* Function:
+-* void program_overscan
+-*
+-* Purpose: Programs overscan border
+-* Input: overscan
+-*
+-* Output:
+- void
+-*/
+-static void program_overscan(
+- struct dce110_transform *xfm110,
+- const struct overscan_info *overscan)
+-{
+- uint32_t overscan_left_right = 0;
+- uint32_t overscan_top_bottom = 0;
+-
+- set_reg_field_value(overscan_left_right, overscan->left,
+- SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
+-
+- set_reg_field_value(overscan_left_right, overscan->right,
+- SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
+-
+- set_reg_field_value(overscan_top_bottom, overscan->top,
+- SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
+-
+- set_reg_field_value(overscan_top_bottom, overscan->bottom,
+- SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
+-
+- dm_write_reg(xfm110->base.ctx,
+- mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
+- overscan_left_right);
+-
+- dm_write_reg(xfm110->base.ctx,
+- mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
+- overscan_top_bottom);
+-}
+-/*
+-static void setup_auto_scaling(struct dce110_transform *xfm110)
+-{
+- uint32_t value = 0;
+- set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+- SCL_V_CALC_AUTO_RATIO_EN);
+- set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+- SCL_H_CALC_AUTO_RATIO_EN);
+- dal_write_reg(xfm->ctx,
+- xfm->regs[IDX_SCL_AUTOMATIC_MODE_CONTROL],
+- value);
+-}
+-*/
+-
+-static void program_two_taps_filter_horz(
+- struct dce110_transform *xfm110,
+- bool hardcode_coff)
+-{
+- uint32_t value = 0;
+-
+- if (hardcode_coff)
+- set_reg_field_value(
+- value,
+- 1,
+- SCLV_HORZ_FILTER_CONTROL,
+- SCL_H_2TAP_HARDCODE_COEF_EN);
+-
+- dm_write_reg(xfm110->base.ctx,
+- mmSCLV_HORZ_FILTER_CONTROL,
+- value);
+-}
+-
+-static void program_two_taps_filter_vert(
+- struct dce110_transform *xfm110,
+- bool hardcode_coff)
+-{
+- uint32_t value = 0;
+-
+- if (hardcode_coff)
+- set_reg_field_value(value, 1, SCLV_VERT_FILTER_CONTROL,
+- SCL_V_2TAP_HARDCODE_COEF_EN);
+-
+- dm_write_reg(xfm110->base.ctx,
+- mmSCLV_VERT_FILTER_CONTROL,
+- value);
+-}
+-
+-static void set_coeff_update_complete(
+- struct dce110_transform *xfm110)
+-{
+- /*TODO: Until now, only scaler bypass, up-scaler 2 -TAPS coeff auto
+- * calculation are implemented. Coefficient RAM is not used
+- * Do not check this flag yet
+- */
+-
+- /*uint32_t value;
+- uint32_t addr = xfm->regs[IDX_SCL_UPDATE];
+-
+- value = dal_read_reg(xfm->ctx, addr);
+- set_reg_field_value(value, 0,
+- SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
+- dal_write_reg(xfm->ctx, addr, value);*/
+-}
+-
+-static bool program_multi_taps_filter(
+- struct dce110_transform *xfm110,
+- const struct scaler_data *data,
+- bool horizontal)
+-{
+- struct dc_context *ctx = xfm110->base.ctx;
+-
+- NOT_IMPLEMENTED();
+- return false;
+-}
+-
+-static void calculate_inits(
+- struct dce110_transform *xfm110,
+- const struct scaler_data *data,
+- struct sclv_ratios_inits *inits,
+- struct rect *luma_viewport,
+- struct rect *chroma_viewport)
+-{
+- if (data->dal_pixel_format == PIXEL_FORMAT_420BPP12 ||
+- data->dal_pixel_format == PIXEL_FORMAT_422BPP16)
+- inits->chroma_enable = true;
+-
+- /* TODO: implement rest of this function properly */
+- if (inits->chroma_enable) {
+- inits->h_int_scale_ratio_luma = 0x1000000;
+- inits->v_int_scale_ratio_luma = 0x1000000;
+- inits->h_int_scale_ratio_chroma = 0x800000;
+- inits->v_int_scale_ratio_chroma = 0x800000;
+- }
+-}
+-
+-static void program_scl_ratios_inits(
+- struct dce110_transform *xfm110,
+- struct sclv_ratios_inits *inits)
+-{
+- struct dc_context *ctx = xfm110->base.ctx;
+- uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
+- uint32_t value = dm_read_reg(ctx, addr);
+-
+- set_reg_field_value(
+- value,
+- inits->h_int_scale_ratio_luma,
+- SCLV_HORZ_FILTER_SCALE_RATIO,
+- SCL_H_SCALE_RATIO);
+- dm_write_reg(ctx, addr, value);
+-
+- addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
+- value = dm_read_reg(ctx, addr);
+- set_reg_field_value(
+- value,
+- inits->v_int_scale_ratio_luma,
+- SCLV_VERT_FILTER_SCALE_RATIO,
+- SCL_V_SCALE_RATIO);
+- dm_write_reg(ctx, addr, value);
+-
+- addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
+- value = dm_read_reg(ctx, addr);
+- set_reg_field_value(
+- value,
+- inits->h_int_scale_ratio_chroma,
+- SCLV_HORZ_FILTER_SCALE_RATIO_C,
+- SCL_H_SCALE_RATIO_C);
+- dm_write_reg(ctx, addr, value);
+-
+- addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
+- value = dm_read_reg(ctx, addr);
+- set_reg_field_value(
+- value,
+- inits->v_int_scale_ratio_chroma,
+- SCLV_VERT_FILTER_SCALE_RATIO_C,
+- SCL_V_SCALE_RATIO_C);
+- dm_write_reg(ctx, addr, value);
+-}
+-
+-void dce110_transform_underlay_set_scalerv_bypass(struct transform *xfm)
+-{
+- uint32_t addr = mmSCLV_MODE;
+- uint32_t value = dm_read_reg(xfm->ctx, addr);
+-
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+- set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+- dm_write_reg(xfm->ctx, addr, value);
+-}
+-
+-bool dce110_transform_underlay_is_scaling_enabled(struct transform *xfm)
+-{
+- uint32_t value = dm_read_reg(xfm->ctx, mmSCLV_MODE);
+- uint8_t scl_mode = get_reg_field_value(value, SCLV_MODE, SCL_MODE);
+-
+- return scl_mode == 0;
+-}
+-
+-/* TODO: sync this one with DAL2 */
+-bool dce110_transform_underlay_set_scaler(
+- struct transform *xfm,
+- const struct scaler_data *data)
+-{
+- struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+- bool is_scaling_required;
+- struct rect luma_viewport = {0};
+- struct rect chroma_viewport = {0};
+- struct dc_context *ctx = xfm->ctx;
+-
+- /* 1. Lock Scaler TODO: enable?*/
+- /*set_scaler_update_lock(xfm, true);*/
+-
+- /* 2. Calculate viewport, viewport programming should happen after init
+- * calculations as they may require an adjustment in the viewport.
+- */
+-
+- calculate_viewport(data, &luma_viewport, &chroma_viewport);
+-
+- /* 3. Program overscan */
+- program_overscan(xfm110, &data->overscan);
+-
+- /* 4. Program taps and configuration */
+- is_scaling_required = setup_scaling_configuration(xfm110, data);
+-
+- if (is_scaling_required) {
+- /* 5. Calculate and program ratio, filter initialization */
+-
+- struct sclv_ratios_inits inits = { 0 };
+-
+- calculate_inits(
+- xfm110,
+- data,
+- &inits,
+- &luma_viewport,
+- &chroma_viewport);
+-
+- program_scl_ratios_inits(xfm110, &inits);
+-
+- /*scaler coeff of 2-TAPS use hardware auto calculated value*/
+-
+- /* 6. Program vertical filters */
+- if (data->taps.v_taps > 2) {
+- program_two_taps_filter_vert(xfm110, false);
+-
+- if (!program_multi_taps_filter(xfm110, data, false)) {
+- dal_logger_write(ctx->logger,
+- LOG_MAJOR_DCP,
+- LOG_MINOR_DCP_SCALER,
+- "Failed vertical taps programming\n");
+- return false;
+- }
+- } else
+- program_two_taps_filter_vert(xfm110, true);
+-
+- /* 7. Program horizontal filters */
+- if (data->taps.h_taps > 2) {
+- program_two_taps_filter_horz(xfm110, false);
+-
+- if (!program_multi_taps_filter(xfm110, data, true)) {
+- dal_logger_write(ctx->logger,
+- LOG_MAJOR_DCP,
+- LOG_MINOR_DCP_SCALER,
+- "Failed horizontal taps programming\n");
+- return false;
+- }
+- } else
+- program_two_taps_filter_horz(xfm110, true);
+- }
+-
+- /* 8. Program the viewport */
+- if (data->flags.bits.SHOULD_PROGRAM_VIEWPORT)
+- program_viewport(xfm110, &luma_viewport, &chroma_viewport);
+-
+- /* 9. Unlock the Scaler TODO: enable?*/
+- /* Every call to "set_scaler_update_lock(xfm, TRUE)"
+- * must have a corresponding call to
+- * "set_scaler_update_lock(xfm, FALSE)" */
+- /*set_scaler_update_lock(xfm, false);*/
+-
+- /* TODO: investigate purpose/need of SHOULD_UNLOCK */
+- if (data->flags.bits.SHOULD_UNLOCK == false)
+- set_coeff_update_complete(xfm110);
+-
+- return true;
+-}
+-
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c
+new file mode 100644
+index 0000000..a7c62e0
+--- /dev/null
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c
+@@ -0,0 +1,674 @@
++/*
++ * Copyright 2012-15 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 "dc_types.h"
++#include "core_types.h"
++
++#include "dce110_transform.h"
++#include "dce110_transform_v.h"
++
++#include "dce/dce_11_0_d.h"
++#include "dce/dce_11_0_sh_mask.h"
++
++#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_CONTROLLER,\
++ "TRANSFORM SCALER:%s()\n", __func__)
++#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
++/*
++*****************************************************************************
++* Function: calculateViewport
++*
++* @brief
++* Calculates all of the data required to set the viewport
++*
++* @param [in] pData: scaler settings data
++* @param [out] pLumaVp: luma viewport information
++* @param [out] pChromaVp: chroma viewport information
++* @param [out] srcResCx2: source chroma resolution times 2 - for multi-taps
++*
++*****************************************************************************
++*/
++static void calculate_viewport(
++ const struct scaler_data *scl_data,
++ struct rect *luma_viewport,
++ struct rect *chroma_viewport)
++{
++ /*Do not set chroma vp for rgb444 pixel format*/
++ luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
++ luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
++ luma_viewport->width =
++ scl_data->viewport.width - scl_data->viewport.width % 2;
++ luma_viewport->height =
++ scl_data->viewport.height - scl_data->viewport.height % 2;
++
++
++ if (scl_data->dal_pixel_format == PIXEL_FORMAT_422BPP16) {
++ luma_viewport->width += luma_viewport->width % 2;
++
++ chroma_viewport->x = luma_viewport->x / 2;
++ chroma_viewport->width = luma_viewport->width / 2;
++ } else if (scl_data->dal_pixel_format == PIXEL_FORMAT_420BPP12) {
++ luma_viewport->height += luma_viewport->height % 2;
++ luma_viewport->width += luma_viewport->width % 2;
++ /*for 420 video chroma is 1/4 the area of luma, scaled
++ *vertically and horizontally
++ */
++ chroma_viewport->x = luma_viewport->x / 2;
++ chroma_viewport->y = luma_viewport->y / 2;
++ chroma_viewport->height = luma_viewport->height / 2;
++ chroma_viewport->width = luma_viewport->width / 2;
++ }
++}
++
++
++static void program_viewport(
++ struct dce110_transform *xfm110,
++ struct rect *luma_view_port,
++ struct rect *chroma_view_port)
++{
++ struct dc_context *ctx = xfm110->base.ctx;
++ uint32_t value = 0;
++ uint32_t addr = 0;
++
++ if (luma_view_port->width != 0 && luma_view_port->height != 0) {
++ addr = mmSCLV_VIEWPORT_START;
++ value = 0;
++ set_reg_field_value(
++ value,
++ luma_view_port->x,
++ SCLV_VIEWPORT_START,
++ VIEWPORT_X_START);
++ set_reg_field_value(
++ value,
++ luma_view_port->y,
++ SCLV_VIEWPORT_START,
++ VIEWPORT_Y_START);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_VIEWPORT_SIZE;
++ value = 0;
++ set_reg_field_value(
++ value,
++ luma_view_port->height,
++ SCLV_VIEWPORT_SIZE,
++ VIEWPORT_HEIGHT);
++ set_reg_field_value(
++ value,
++ luma_view_port->width,
++ SCLV_VIEWPORT_SIZE,
++ VIEWPORT_WIDTH);
++ dm_write_reg(ctx, addr, value);
++ }
++
++ if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
++ addr = mmSCLV_VIEWPORT_START_C;
++ value = 0;
++ set_reg_field_value(
++ value,
++ chroma_view_port->x,
++ SCLV_VIEWPORT_START_C,
++ VIEWPORT_X_START_C);
++ set_reg_field_value(
++ value,
++ chroma_view_port->y,
++ SCLV_VIEWPORT_START_C,
++ VIEWPORT_Y_START_C);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_VIEWPORT_SIZE_C;
++ value = 0;
++ set_reg_field_value(
++ value,
++ chroma_view_port->height,
++ SCLV_VIEWPORT_SIZE_C,
++ VIEWPORT_HEIGHT_C);
++ set_reg_field_value(
++ value,
++ chroma_view_port->width,
++ SCLV_VIEWPORT_SIZE_C,
++ VIEWPORT_WIDTH_C);
++ dm_write_reg(ctx, addr, value);
++ }
++ /* TODO: add stereo support */
++}
++
++
++/*
++ * Until and For MPO video play story, to reduce time for implementation,
++ * below limits are applied for now: 2_TAPS only
++ * Use auto-calculated filter values
++ * Following routines will be empty for now:
++ *
++ * programSclRatiosInits -- calcualate scaler ratio manually
++ * calculateInits --- calcualate scaler ratio manually
++ * programFilter -- multi-taps
++ * GetOptimalNumberOfTaps -- will hard coded to 2 TAPS
++ * GetNextLowerNumberOfTaps -- will hard coded to 2TAPS
++ * validateRequestedScaleRatio - used by GetOptimalNumberOfTaps internally
++ */
++
++/*
++ * Function:
++ * void setup_scaling_configuration
++ *
++ * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
++ * Input: data
++ *
++ * Output:
++ * void
++ */
++static bool setup_scaling_configuration(
++ struct dce110_transform *xfm110,
++ const struct scaler_data *data)
++{
++ bool is_scaling_needed = false;
++ struct dc_context *ctx = xfm110->base.ctx;
++ uint32_t value = 0;
++
++ if (data->taps.h_taps + data->taps.v_taps > 2) {
++ set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
++ set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
++ is_scaling_needed = true;
++ } else {
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
++ }
++
++ if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
++ set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
++ set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
++ is_scaling_needed = true;
++ } else if (data->dal_pixel_format != PIXEL_FORMAT_420BPP12 &&
++ data->dal_pixel_format != PIXEL_FORMAT_422BPP16) {
++ set_reg_field_value(
++ value,
++ get_reg_field_value(value, SCLV_MODE, SCL_MODE),
++ SCLV_MODE,
++ SCL_MODE_C);
++ set_reg_field_value(
++ value,
++ get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
++ SCLV_MODE,
++ SCL_PSCL_EN_C);
++ } else {
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
++ }
++ dm_write_reg(ctx, mmSCLV_MODE, value);
++
++ {
++ value = dm_read_reg(ctx, mmSCLV_TAP_CONTROL);
++
++ set_reg_field_value(value, data->taps.h_taps - 1,
++ SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
++
++ set_reg_field_value(value, data->taps.v_taps - 1,
++ SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
++
++ set_reg_field_value(value, data->taps.h_taps_c - 1,
++ SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
++
++ set_reg_field_value(value, data->taps.v_taps_c - 1,
++ SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
++
++ dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
++ }
++
++ {
++ /*
++ * we can ignore this register because we are ok with hw
++ * default 0 -- change to 1 according to dal2 code
++ */
++ value = dm_read_reg(ctx, mmSCLV_CONTROL);
++ /*
++ * 0 - Replaced out of bound pixels with black pixel
++ * (or any other required color)
++ */
++ set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
++
++ /* 1 - Replaced out of bound pixels with the edge pixel. */
++ dm_write_reg(ctx, mmSCLV_CONTROL, value);
++ }
++
++ return is_scaling_needed;
++}
++
++/**
++* Function:
++* void program_overscan
++*
++* Purpose: Programs overscan border
++* Input: overscan
++*
++* Output:
++ void
++*/
++static void program_overscan(
++ struct dce110_transform *xfm110,
++ const struct overscan_info *overscan)
++{
++ uint32_t overscan_left_right = 0;
++ uint32_t overscan_top_bottom = 0;
++
++ set_reg_field_value(overscan_left_right, overscan->left,
++ SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
++
++ set_reg_field_value(overscan_left_right, overscan->right,
++ SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
++
++ set_reg_field_value(overscan_top_bottom, overscan->top,
++ SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
++
++ set_reg_field_value(overscan_top_bottom, overscan->bottom,
++ SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
++
++ dm_write_reg(xfm110->base.ctx,
++ mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
++ overscan_left_right);
++
++ dm_write_reg(xfm110->base.ctx,
++ mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
++ overscan_top_bottom);
++}
++
++static void program_two_taps_filter_horz(
++ struct dce110_transform *xfm110,
++ bool hardcode_coff)
++{
++ uint32_t value = 0;
++
++ if (hardcode_coff)
++ set_reg_field_value(
++ value,
++ 1,
++ SCLV_HORZ_FILTER_CONTROL,
++ SCL_H_2TAP_HARDCODE_COEF_EN);
++
++ dm_write_reg(xfm110->base.ctx,
++ mmSCLV_HORZ_FILTER_CONTROL,
++ value);
++}
++
++static void program_two_taps_filter_vert(
++ struct dce110_transform *xfm110,
++ bool hardcode_coff)
++{
++ uint32_t value = 0;
++
++ if (hardcode_coff)
++ set_reg_field_value(value, 1, SCLV_VERT_FILTER_CONTROL,
++ SCL_V_2TAP_HARDCODE_COEF_EN);
++
++ dm_write_reg(xfm110->base.ctx,
++ mmSCLV_VERT_FILTER_CONTROL,
++ value);
++}
++
++static void set_coeff_update_complete(
++ struct dce110_transform *xfm110)
++{
++ /*TODO: Until now, only scaler bypass, up-scaler 2 -TAPS coeff auto
++ * calculation are implemented. Coefficient RAM is not used
++ * Do not check this flag yet
++ */
++
++ /*uint32_t value;
++ uint32_t addr = xfm->regs[IDX_SCL_UPDATE];
++
++ value = dal_read_reg(xfm->ctx, addr);
++ set_reg_field_value(value, 0,
++ SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
++ dal_write_reg(xfm->ctx, addr, value);*/
++}
++
++static bool program_multi_taps_filter(
++ struct dce110_transform *xfm110,
++ const struct scaler_data *data,
++ bool horizontal)
++{
++ struct dc_context *ctx = xfm110->base.ctx;
++
++ NOT_IMPLEMENTED();
++ return false;
++}
++
++static void calculate_inits(
++ struct dce110_transform *xfm110,
++ const struct scaler_data *data,
++ struct sclv_ratios_inits *inits,
++ struct rect *luma_viewport,
++ struct rect *chroma_viewport)
++{
++ if (data->dal_pixel_format == PIXEL_FORMAT_420BPP12 ||
++ data->dal_pixel_format == PIXEL_FORMAT_422BPP16)
++ inits->chroma_enable = true;
++
++ /* TODO: implement rest of this function properly */
++ if (inits->chroma_enable) {
++ inits->h_int_scale_ratio_luma = 0x1000000;
++ inits->v_int_scale_ratio_luma = 0x1000000;
++ inits->h_int_scale_ratio_chroma = 0x800000;
++ inits->v_int_scale_ratio_chroma = 0x800000;
++ }
++}
++
++static void program_scl_ratios_inits(
++ struct dce110_transform *xfm110,
++ struct sclv_ratios_inits *inits)
++{
++ struct dc_context *ctx = xfm110->base.ctx;
++ uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
++ uint32_t value = dm_read_reg(ctx, addr);
++
++ set_reg_field_value(
++ value,
++ inits->h_int_scale_ratio_luma,
++ SCLV_HORZ_FILTER_SCALE_RATIO,
++ SCL_H_SCALE_RATIO);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
++ value = dm_read_reg(ctx, addr);
++ set_reg_field_value(
++ value,
++ inits->v_int_scale_ratio_luma,
++ SCLV_VERT_FILTER_SCALE_RATIO,
++ SCL_V_SCALE_RATIO);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
++ value = dm_read_reg(ctx, addr);
++ set_reg_field_value(
++ value,
++ inits->h_int_scale_ratio_chroma,
++ SCLV_HORZ_FILTER_SCALE_RATIO_C,
++ SCL_H_SCALE_RATIO_C);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
++ value = dm_read_reg(ctx, addr);
++ set_reg_field_value(
++ value,
++ inits->v_int_scale_ratio_chroma,
++ SCLV_VERT_FILTER_SCALE_RATIO_C,
++ SCL_V_SCALE_RATIO_C);
++ dm_write_reg(ctx, addr, value);
++}
++
++static void dce110_transform_v_set_scalerv_bypass(struct transform *xfm)
++{
++ uint32_t addr = mmSCLV_MODE;
++ uint32_t value = dm_read_reg(xfm->ctx, addr);
++
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
++ set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
++ dm_write_reg(xfm->ctx, addr, value);
++}
++
++/* TODO: sync this one with DAL2 */
++static bool dce110_transform_v_set_scaler(
++ struct transform *xfm,
++ const struct scaler_data *data)
++{
++ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
++ bool is_scaling_required;
++ struct rect luma_viewport = {0};
++ struct rect chroma_viewport = {0};
++ struct dc_context *ctx = xfm->ctx;
++
++ /* 1. Lock Scaler TODO: enable?*/
++ /*set_scaler_update_lock(xfm, true);*/
++
++ /* 2. Calculate viewport, viewport programming should happen after init
++ * calculations as they may require an adjustment in the viewport.
++ */
++
++ calculate_viewport(data, &luma_viewport, &chroma_viewport);
++
++ /* 3. Program overscan */
++ program_overscan(xfm110, &data->overscan);
++
++ /* 4. Program taps and configuration */
++ is_scaling_required = setup_scaling_configuration(xfm110, data);
++
++ if (is_scaling_required) {
++ /* 5. Calculate and program ratio, filter initialization */
++
++ struct sclv_ratios_inits inits = { 0 };
++
++ calculate_inits(
++ xfm110,
++ data,
++ &inits,
++ &luma_viewport,
++ &chroma_viewport);
++
++ program_scl_ratios_inits(xfm110, &inits);
++
++ /*scaler coeff of 2-TAPS use hardware auto calculated value*/
++
++ /* 6. Program vertical filters */
++ if (data->taps.v_taps > 2) {
++ program_two_taps_filter_vert(xfm110, false);
++
++ if (!program_multi_taps_filter(xfm110, data, false)) {
++ dal_logger_write(ctx->logger,
++ LOG_MAJOR_DCP,
++ LOG_MINOR_DCP_SCALER,
++ "Failed vertical taps programming\n");
++ return false;
++ }
++ } else
++ program_two_taps_filter_vert(xfm110, true);
++
++ /* 7. Program horizontal filters */
++ if (data->taps.h_taps > 2) {
++ program_two_taps_filter_horz(xfm110, false);
++
++ if (!program_multi_taps_filter(xfm110, data, true)) {
++ dal_logger_write(ctx->logger,
++ LOG_MAJOR_DCP,
++ LOG_MINOR_DCP_SCALER,
++ "Failed horizontal taps programming\n");
++ return false;
++ }
++ } else
++ program_two_taps_filter_horz(xfm110, true);
++ }
++
++ /* 8. Program the viewport */
++ if (data->flags.bits.SHOULD_PROGRAM_VIEWPORT)
++ program_viewport(xfm110, &luma_viewport, &chroma_viewport);
++
++ /* 9. Unlock the Scaler TODO: enable?
++ * Every call to "set_scaler_update_lock(xfm, TRUE)"
++ * must have a corresponding call to
++ * "set_scaler_update_lock(xfm, FALSE)" */
++
++ /*set_scaler_update_lock(xfm, false);*/
++
++ /* TODO: investigate purpose/need of SHOULD_UNLOCK */
++ if (data->flags.bits.SHOULD_UNLOCK == false)
++ set_coeff_update_complete(xfm110);
++
++ return true;
++}
++
++static bool dce110_transform_v_power_up_line_buffer(struct transform *xfm)
++{
++ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
++ uint32_t value;
++
++ value = dm_read_reg(xfm110->base.ctx, mmLBV_MEMORY_CTRL);
++
++ /*Use all three pieces of memory always*/
++ set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG);
++ /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
++ set_reg_field_value(value, LB_TOTAL_NUMBER_OF_ENTRIES, LBV_MEMORY_CTRL,
++ LB_MEMORY_SIZE);
++
++ dm_write_reg(xfm110->base.ctx, mmLBV_MEMORY_CTRL, value);
++
++ return true;
++}
++
++static void get_viewport(
++ struct dce110_transform *xfm110,
++ struct rect *current_view_port)
++{
++ uint32_t value_start;
++ uint32_t value_size;
++
++ if (current_view_port == NULL)
++ return;
++
++ value_start = dm_read_reg(xfm110->base.ctx, mmSCLV_VIEWPORT_START);
++ value_size = dm_read_reg(xfm110->base.ctx, mmSCLV_VIEWPORT_SIZE);
++
++ current_view_port->x = get_reg_field_value(
++ value_start,
++ SCLV_VIEWPORT_START,
++ VIEWPORT_X_START);
++ current_view_port->y = get_reg_field_value(
++ value_start,
++ SCLV_VIEWPORT_START,
++ VIEWPORT_Y_START);
++ current_view_port->height = get_reg_field_value(
++ value_size,
++ SCLV_VIEWPORT_SIZE,
++ VIEWPORT_HEIGHT);
++ current_view_port->width = get_reg_field_value(
++ value_size,
++ SCLV_VIEWPORT_SIZE,
++ VIEWPORT_WIDTH);
++}
++
++static void program_luma_viewport(
++ struct dce110_transform *xfm110,
++ const struct rect *view_port)
++{
++ struct dc_context *ctx = xfm110->base.ctx;
++ uint32_t value = 0;
++ uint32_t addr = 0;
++
++ addr = mmSCLV_VIEWPORT_START;
++ value = dm_read_reg(ctx, addr);
++ set_reg_field_value(
++ value,
++ view_port->x,
++ SCLV_VIEWPORT_START,
++ VIEWPORT_X_START);
++ set_reg_field_value(
++ value,
++ view_port->y,
++ SCLV_VIEWPORT_START,
++ VIEWPORT_Y_START);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_VIEWPORT_SIZE;
++ value = dm_read_reg(ctx, addr);
++ set_reg_field_value(
++ value,
++ view_port->height,
++ SCLV_VIEWPORT_SIZE,
++ VIEWPORT_HEIGHT);
++ set_reg_field_value(
++ value,
++ view_port->width,
++ SCLV_VIEWPORT_SIZE,
++ VIEWPORT_WIDTH);
++ dm_write_reg(ctx, addr, value);
++
++ /* TODO: add stereo support */
++}
++
++static bool dce110_transform_v_update_viewport(
++ struct transform *xfm,
++ const struct rect *view_port,
++ bool is_fbc_attached)
++{
++ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
++ bool program_req = false;
++ struct rect current_view_port;
++
++ if (view_port == NULL)
++ return program_req;
++
++ get_viewport(xfm110, &current_view_port);
++
++ if (current_view_port.x != view_port->x ||
++ current_view_port.y != view_port->y ||
++ current_view_port.height != view_port->height ||
++ current_view_port.width != view_port->width)
++ program_req = true;
++
++ if (program_req) {
++ /*underlay viewport is programmed with scaler
++ *program_viewport function pointer is not exposed*/
++ program_luma_viewport(xfm110, view_port);
++ }
++
++ return program_req;
++}
++
++static struct transform_funcs dce110_transform_v_funcs = {
++ .transform_power_up =
++ dce110_transform_v_power_up_line_buffer,
++ .transform_set_scaler =
++ dce110_transform_v_set_scaler,
++ .transform_set_scaler_bypass =
++ dce110_transform_v_set_scalerv_bypass,
++ .transform_update_viewport =
++ dce110_transform_v_update_viewport,
++ .transform_set_scaler_filter =
++ dce110_transform_set_scaler_filter,
++ .transform_set_gamut_remap =
++ dce110_transform_set_gamut_remap,
++ .transform_set_pixel_storage_depth =
++ dce110_transform_v_set_pixel_storage_depth,
++ .transform_get_current_pixel_storage_depth =
++ dce110_transform_v_get_current_pixel_storage_depth
++};
++/*****************************************/
++/* Constructor, Destructor */
++/*****************************************/
++
++bool dce110_transform_v_construct(
++ struct dce110_transform *xfm110,
++ struct dc_context *ctx)
++{
++ xfm110->base.ctx = ctx;
++
++ xfm110->base.funcs = &dce110_transform_v_funcs;
++
++ xfm110->lb_pixel_depth_supported =
++ LB_PIXEL_DEPTH_18BPP |
++ LB_PIXEL_DEPTH_24BPP |
++ LB_PIXEL_DEPTH_30BPP;
++
++ return true;
++}
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.h
+new file mode 100644
+index 0000000..b51bd78
+--- /dev/null
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.h
+@@ -0,0 +1,44 @@
++/* Copyright 2012-15 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 __DAL_TRANSFORM_V_DCE110_H__
++#define __DAL_TRANSFORM_V_DCE110_H__
++
++#include "inc/transform.h"
++#include "include/grph_csc_types.h"
++
++bool dce110_transform_v_construct(
++ struct dce110_transform *xfm110,
++ struct dc_context *ctx);
++
++bool dce110_transform_v_get_current_pixel_storage_depth(
++ struct transform *xfm,
++ enum lb_pixel_depth *depth);
++
++bool dce110_transform_v_set_pixel_storage_depth(
++ struct transform *xfm,
++ enum lb_pixel_depth depth,
++ const struct bit_depth_reduction_params *bit_depth_params);
++
++#endif
+--
+2.7.4
+