aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch')
-rw-r--r--common/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch877
1 files changed, 0 insertions, 877 deletions
diff --git a/common/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch b/common/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch
deleted file mode 100644
index 93b86f71..00000000
--- a/common/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch
+++ /dev/null
@@ -1,877 +0,0 @@
-From 7da2abf1b61ca0b039d2d1683aff6cef8f086934 Mon Sep 17 00:00:00 2001
-From: Eric Yang <eric.yang2@amd.com>
-Date: Wed, 3 Feb 2016 16:13:11 -0500
-Subject: [PATCH 0778/1110] drm/amd/dal: Add timing generator for underlay pipe
-
-Signed-off-by: Eric Yang <eric.yang2@amd.com>
-Acked-by: Jordan Lazare <Jordan.Lazare@amd.com>
----
- .../amd/dal/dc/dce110/dce110_timing_generator.c | 2 +-
- .../amd/dal/dc/dce110/dce110_timing_generator.h | 3 +
- .../amd/dal/dc/dce110/dce110_timing_generator_v.c | 785 +++++++++++++++++++++
- .../amd/dal/dc/dce110/dce110_timing_generator_v.h | 34 +
- 4 files changed, 823 insertions(+), 1 deletion(-)
- create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.c
- create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.h
-
-diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
-index d7cdd91..8fb90c0 100644
---- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
-+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
-@@ -190,7 +190,7 @@ static void dce110_timing_generator_apply_front_porch_workaround(
- }
- }
-
--static void dce110_timing_generator_color_space_to_black_color(
-+void dce110_timing_generator_color_space_to_black_color(
- enum color_space colorspace,
- struct crtc_black_color *black_color)
- {
-diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
-index 163fadd..3579736 100644
---- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
-+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
-@@ -175,6 +175,9 @@ void dce110_timing_generator_program_blank_color(
- void dce110_timing_generator_set_overscan_color_black(
- struct timing_generator *tg,
- enum color_space black_color);
-+void dce110_timing_generator_color_space_to_black_color(
-+ enum color_space colorspace,
-+ struct crtc_black_color *black_color);
- /*************** End-of-move ********************/
-
-
-diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.c
-new file mode 100644
-index 0000000..722f636
---- /dev/null
-+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.c
-@@ -0,0 +1,785 @@
-+
-+
-+#include "dm_services.h"
-+
-+/* include DCE11 register header files */
-+#include "dce/dce_11_0_d.h"
-+#include "dce/dce_11_0_sh_mask.h"
-+
-+#include "dc_types.h"
-+#include "dc_bios_types.h"
-+
-+#include "include/grph_object_id.h"
-+#include "include/adapter_service_interface.h"
-+#include "include/logger_interface.h"
-+#include "dce110_timing_generator.h"
-+#include "dce110_timing_generator_v.h"
-+
-+#include "../inc/timing_generator.h"
-+
-+
-+/** ********************************************************************************
-+ *
-+ * DCE11 Timing Generator Implementation
-+ *
-+ **********************************************************************************/
-+
-+/**
-+* Enable CRTCV
-+*/
-+
-+static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg)
-+{
-+ /*
-+ * Set MASTER_UPDATE_MODE to 0
-+ * This is needed for DRR, and also suggested to be default value by Syed.
-+ */
-+
-+ uint32_t value;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ value = dm_read_reg(tg->ctx,
-+ mmCRTCV_MASTER_UPDATE_MODE);
-+ set_reg_field_value(value, 0,
-+ CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE);
-+ dm_write_reg(tg->ctx,
-+ mmCRTCV_MASTER_UPDATE_MODE, value);
-+
-+ value = dm_read_reg(tg->ctx,
-+ mmCRTCV_MASTER_EN);
-+ set_reg_field_value(value, 1,
-+ CRTCV_MASTER_EN, CRTC_MASTER_EN);
-+ dm_write_reg(tg->ctx,
-+ mmCRTCV_MASTER_EN, value);
-+
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg)
-+{
-+ uint32_t value;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ value = dm_read_reg(tg->ctx,
-+ mmCRTCV_CONTROL);
-+ set_reg_field_value(value, 0,
-+ CRTCV_CONTROL, CRTC_DISABLE_POINT_CNTL);
-+ set_reg_field_value(value, 0,
-+ CRTCV_CONTROL, CRTC_MASTER_EN);
-+ dm_write_reg(tg->ctx,
-+ mmCRTCV_CONTROL, value);
-+ /*
-+ * TODO: call this when adding stereo support
-+ * tg->funcs->disable_stereo(tg);
-+ */
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t addr = mmCRTCV_BLANK_CONTROL;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+ uint8_t counter = 100;
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DATA_EN);
-+
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DE_MODE);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+
-+ while (counter > 0) {
-+ value = dm_read_reg(tg->ctx, addr);
-+
-+ if (get_reg_field_value(
-+ value,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DATA_EN) == 1 &&
-+ get_reg_field_value(
-+ value,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_CURRENT_BLANK_STATE) == 1)
-+ break;
-+
-+ dm_sleep_in_milliseconds(tg->ctx, 1);
-+ counter--;
-+ }
-+
-+ if (!counter) {
-+ dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
-+ LOG_MINOR_COMPONENT_CONTROLLER,
-+ "timing generator %d blank timing out.\n",
-+ tg110->controller_id);
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t addr = mmCRTCV_BLANK_CONTROL;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DATA_EN);
-+
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_BLANK_CONTROL,
-+ CRTC_BLANK_DE_MODE);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+
-+ return true;
-+}
-+
-+static bool dce110_timing_generator_v_is_in_vertical_blank(
-+ struct timing_generator *tg)
-+{
-+ uint32_t addr = 0;
-+ uint32_t value = 0;
-+ uint32_t field = 0;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ addr = mmCRTCV_STATUS;
-+ value = dm_read_reg(tg->ctx, addr);
-+ field = get_reg_field_value(value, CRTCV_STATUS, CRTC_V_BLANK);
-+ return field == 1;
-+}
-+
-+static bool dce110_timing_generator_v_is_counter_moving(struct timing_generator *tg)
-+{
-+ uint32_t value;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ uint32_t h1 = 0;
-+ uint32_t h2 = 0;
-+ uint32_t v1 = 0;
-+ uint32_t v2 = 0;
-+
-+ value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
-+
-+ h1 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_HORZ_COUNT);
-+
-+ v1 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_VERT_COUNT);
-+
-+ value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
-+
-+ h2 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_HORZ_COUNT);
-+
-+ v2 = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_VERT_COUNT);
-+
-+ if (h1 == h2 && v1 == v2)
-+ return false;
-+ else
-+ return true;
-+}
-+
-+static void dce110_timing_generator_v_wait_for_vblank(struct timing_generator *tg)
-+{
-+ /* We want to catch beginning of VBlank here, so if the first try are
-+ * in VBlank, we might be very close to Active, in this case wait for
-+ * another frame
-+ */
-+ while (dce110_timing_generator_v_is_in_vertical_blank(tg)) {
-+ if (!dce110_timing_generator_v_is_counter_moving(tg)) {
-+ /* error - no point to wait if counter is not moving */
-+ break;
-+ }
-+ }
-+
-+ while (!dce110_timing_generator_v_is_in_vertical_blank(tg)) {
-+ if (!dce110_timing_generator_v_is_counter_moving(tg)) {
-+ /* error - no point to wait if counter is not moving */
-+ break;
-+ }
-+ }
-+}
-+
-+/**
-+* Wait till we are in VActive (anywhere in VActive)
-+*/
-+static void dce110_timing_generator_v_wait_for_vactive(struct timing_generator *tg)
-+{
-+ while (dce110_timing_generator_v_is_in_vertical_blank(tg)) {
-+ if (!dce110_timing_generator_v_is_counter_moving(tg)) {
-+ /* error - no point to wait if counter is not moving */
-+ break;
-+ }
-+ }
-+}
-+
-+static void dce110_timing_generator_v_wait_for_state(struct timing_generator *tg,
-+ enum crtc_state state)
-+{
-+ switch (state) {
-+ case CRTC_STATE_VBLANK:
-+ dce110_timing_generator_v_wait_for_vblank(tg);
-+ break;
-+
-+ case CRTC_STATE_VACTIVE:
-+ dce110_timing_generator_v_wait_for_vactive(tg);
-+ break;
-+
-+ default:
-+ break;
-+ }
-+}
-+
-+static void dce110_timing_generator_v_program_blanking(
-+ struct timing_generator *tg,
-+ const struct dc_crtc_timing *timing)
-+{
-+ uint32_t vsync_offset = timing->v_border_bottom +
-+ timing->v_front_porch;
-+ uint32_t v_sync_start = timing->v_addressable + vsync_offset;
-+
-+ uint32_t hsync_offset = timing->h_border_right +
-+ timing->h_front_porch;
-+ uint32_t h_sync_start = timing->h_addressable + hsync_offset;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ struct dc_context *ctx = tg->ctx;
-+ uint32_t value = 0;
-+ uint32_t addr = 0;
-+ uint32_t tmp = 0;
-+
-+ addr = mmCRTCV_H_TOTAL;
-+ value = dm_read_reg(ctx, addr);
-+ set_reg_field_value(
-+ value,
-+ timing->h_total - 1,
-+ CRTCV_H_TOTAL,
-+ CRTC_H_TOTAL);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_V_TOTAL;
-+ value = dm_read_reg(ctx, addr);
-+ set_reg_field_value(
-+ value,
-+ timing->v_total - 1,
-+ CRTCV_V_TOTAL,
-+ CRTC_V_TOTAL);
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_H_BLANK_START_END;
-+ value = dm_read_reg(ctx, addr);
-+
-+ tmp = timing->h_total -
-+ (h_sync_start + timing->h_border_left);
-+
-+ set_reg_field_value(
-+ value,
-+ tmp,
-+ CRTCV_H_BLANK_START_END,
-+ CRTC_H_BLANK_END);
-+
-+ tmp = tmp + timing->h_addressable +
-+ timing->h_border_left + timing->h_border_right;
-+
-+ set_reg_field_value(
-+ value,
-+ tmp,
-+ CRTCV_H_BLANK_START_END,
-+ CRTC_H_BLANK_START);
-+
-+ dm_write_reg(ctx, addr, value);
-+
-+ addr = mmCRTCV_V_BLANK_START_END;
-+ value = dm_read_reg(ctx, addr);
-+
-+ tmp = timing->v_total - (v_sync_start + timing->v_border_top);
-+
-+ set_reg_field_value(
-+ value,
-+ tmp,
-+ CRTCV_V_BLANK_START_END,
-+ CRTC_V_BLANK_END);
-+
-+ tmp = tmp + timing->v_addressable + timing->v_border_top +
-+ timing->v_border_bottom;
-+
-+ set_reg_field_value(
-+ value,
-+ tmp,
-+ CRTCV_V_BLANK_START_END,
-+ CRTC_V_BLANK_START);
-+
-+ dm_write_reg(ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_enable_advanced_request(
-+ struct timing_generator *tg,
-+ bool enable,
-+ const struct dc_crtc_timing *timing)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t addr = mmCRTCV_START_LINE_CONTROL;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ if (enable) {
-+ if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
-+ set_reg_field_value(
-+ value,
-+ 3,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_ADVANCED_START_LINE_POSITION);
-+ } else {
-+ set_reg_field_value(
-+ value,
-+ 4,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_ADVANCED_START_LINE_POSITION);
-+ }
-+ set_reg_field_value(
-+ value,
-+ 0,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_LEGACY_REQUESTOR_EN);
-+ } else {
-+ set_reg_field_value(
-+ value,
-+ 2,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_ADVANCED_START_LINE_POSITION);
-+ set_reg_field_value(
-+ value,
-+ 1,
-+ CRTCV_START_LINE_CONTROL,
-+ CRTC_LEGACY_REQUESTOR_EN);
-+ }
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg,
-+ bool enable_blanking)
-+{
-+ if (enable_blanking)
-+ return dce110_timing_generator_v_blank_crtc(tg);
-+ else
-+ return dce110_timing_generator_v_unblank_crtc(tg);
-+}
-+
-+static void dce110_timing_generator_v_program_timing(struct timing_generator *tg,
-+ const struct dc_crtc_timing *timing,
-+ bool use_vbios)
-+{
-+ if (use_vbios)
-+ dce110_timing_generator_program_timing_generator(tg, timing);
-+ else
-+ dce110_timing_generator_v_program_blanking(tg, timing);
-+}
-+
-+static void dce110_timing_generator_v_program_blank_color(
-+ struct timing_generator *tg,
-+ enum color_space color_space)
-+{
-+ struct crtc_black_color black_color;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t addr = mmCRTCV_BLACK_COLOR;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ dce110_timing_generator_color_space_to_black_color(
-+ color_space,
-+ &black_color);
-+
-+ set_reg_field_value(
-+ value,
-+ black_color.black_color_b_cb,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_B_CB);
-+ set_reg_field_value(
-+ value,
-+ black_color.black_color_g_y,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_G_Y);
-+ set_reg_field_value(
-+ value,
-+ black_color.black_color_r_cr,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_R_CR);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_set_overscan_color_black(
-+ struct timing_generator *tg,
-+ enum color_space black_color)
-+{
-+ struct dc_context *ctx = tg->ctx;
-+ uint32_t value = 0;
-+ uint32_t addr;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ /* Overscan Color for YUV display modes:
-+ * to achieve a black color for both the explicit and implicit overscan,
-+ * the overscan color registers should be programmed to: */
-+
-+ switch (black_color) {
-+ case COLOR_SPACE_YPBPR601:
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+ break;
-+
-+ case COLOR_SPACE_YPBPR709:
-+ case COLOR_SPACE_YCBCR601:
-+ case COLOR_SPACE_YCBCR709:
-+ case COLOR_SPACE_YCBCR601_YONLY:
-+ case COLOR_SPACE_YCBCR709_YONLY:
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+ break;
-+
-+ case COLOR_SPACE_N_MVPU_SUPER_AA:
-+ /* In crossfire SuperAA mode, the slave overscan data is forced
-+ * to 0 in the pixel mixer on the master. As a result, we need
-+ * to adjust the blank color so that after blending the
-+ * master+slave, it will appear black */
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+ break;
-+
-+ case COLOR_SPACE_SRGB_LIMITED_RANGE:
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ set_reg_field_value(
-+ value,
-+ CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+ break;
-+
-+ default:
-+ /* default is sRGB black 0. */
-+ break;
-+ }
-+ addr = mmCRTCV_OVERSCAN_COLOR;
-+ dm_write_reg(ctx, addr, value);
-+ addr = mmCRTCV_BLACK_COLOR;
-+ dm_write_reg(ctx, addr, value);
-+ /* This is desirable to have a constant DAC output voltage during the
-+ * blank time that is higher than the 0 volt reference level that the
-+ * DAC outputs when the NBLANK signal
-+ * is asserted low, such as for output to an analog TV. */
-+ addr = mmCRTCV_BLANK_DATA_COLOR;
-+ dm_write_reg(ctx, addr, value);
-+
-+ /* TO DO we have to program EXT registers and we need to know LB DATA
-+ * format because it is used when more 10 , i.e. 12 bits per color
-+ *
-+ * m_mmDxCRTC_OVERSCAN_COLOR_EXT
-+ * m_mmDxCRTC_BLACK_COLOR_EXT
-+ * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
-+ */
-+
-+}
-+
-+static void dce110_tg_v_program_blank_color(struct timing_generator *tg,
-+ const struct crtc_black_color *black_color)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t addr = mmCRTCV_BLACK_COLOR;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+
-+ set_reg_field_value(
-+ value,
-+ black_color->black_color_b_cb,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_B_CB);
-+ set_reg_field_value(
-+ value,
-+ black_color->black_color_g_y,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_G_Y);
-+ set_reg_field_value(
-+ value,
-+ black_color->black_color_r_cr,
-+ CRTCV_BLACK_COLOR,
-+ CRTC_BLACK_COLOR_R_CR);
-+
-+ dm_write_reg(tg->ctx, addr, value);
-+
-+ addr = mmCRTCV_BLANK_DATA_COLOR;
-+ dm_write_reg(tg->ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg,
-+ const struct crtc_black_color *overscan_color)
-+{
-+ struct dc_context *ctx = tg->ctx;
-+ uint32_t value = 0;
-+ uint32_t addr;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->black_color_b_cb,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_BLUE);
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->black_color_g_y,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_GREEN);
-+
-+ set_reg_field_value(
-+ value,
-+ overscan_color->black_color_r_cr,
-+ CRTCV_OVERSCAN_COLOR,
-+ CRTC_OVERSCAN_COLOR_RED);
-+
-+ addr = mmCRTCV_OVERSCAN_COLOR;
-+ dm_write_reg(ctx, addr, value);
-+}
-+
-+static void dce110_timing_generator_v_set_colors(struct timing_generator *tg,
-+ const struct crtc_black_color *blank_color,
-+ const struct crtc_black_color *overscan_color)
-+{
-+ if (blank_color != NULL)
-+ dce110_tg_v_program_blank_color(tg, blank_color);
-+ if (overscan_color != NULL)
-+ dce110_timing_generator_v_set_overscan_color(tg, overscan_color);
-+}
-+
-+
-+static void dce110_timing_generator_v_set_early_control(
-+ struct timing_generator *tg,
-+ uint32_t early_cntl)
-+{
-+ uint32_t regval;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t address = mmCRTC_CONTROL;
-+
-+ regval = dm_read_reg(tg->ctx, address);
-+ set_reg_field_value(regval, early_cntl,
-+ CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
-+ dm_write_reg(tg->ctx, address, regval);
-+}
-+
-+static void dce110_timing_generator_v_get_crtc_positions(
-+ struct timing_generator *tg,
-+ int32_t *h_position,
-+ int32_t *v_position)
-+{
-+ uint32_t value;
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+
-+ value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
-+
-+ *h_position = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_HORZ_COUNT);
-+
-+ *v_position = get_reg_field_value(
-+ value,
-+ CRTCV_STATUS_POSITION,
-+ CRTC_VERT_COUNT);
-+}
-+
-+static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg)
-+{
-+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-+ uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT;
-+ uint32_t value = dm_read_reg(tg->ctx, addr);
-+ uint32_t field = get_reg_field_value(
-+ value, CRTCV_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
-+
-+ return field;
-+}
-+
-+static bool dce110_timing_generator_v_did_triggered_reset_occur(
-+ struct timing_generator *tg)
-+{
-+ dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
-+ LOG_MINOR_COMPONENT_CONTROLLER,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return false;
-+}
-+
-+static void dce110_timing_generator_v_setup_global_swap_lock(
-+ struct timing_generator *tg,
-+ const struct dcp_gsl_params *gsl_params)
-+{
-+ dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
-+ LOG_MINOR_COMPONENT_CONTROLLER,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_enable_reset_trigger(
-+ struct timing_generator *tg,
-+ const struct trigger_params *trigger_params)
-+{
-+ dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
-+ LOG_MINOR_COMPONENT_CONTROLLER,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_disable_reset_trigger(
-+ struct timing_generator *tg)
-+{
-+ dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
-+ LOG_MINOR_COMPONENT_CONTROLLER,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_tear_down_global_swap_lock(
-+ struct timing_generator *tg)
-+{
-+ dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
-+ LOG_MINOR_COMPONENT_CONTROLLER,
-+ "Timing Sync not supported on underlay pipe\n");
-+ return;
-+}
-+
-+static void dce110_timing_generator_v_disable_vga(
-+ struct timing_generator *tg)
-+{
-+ return;
-+}
-+/** ********************************************************************************************
-+ *
-+ * DCE11 Timing Generator Constructor / Destructor
-+ *
-+ *********************************************************************************************/
-+static struct timing_generator_funcs dce110_tg_v_funcs = {
-+ .validate_timing = dce110_tg_validate_timing,
-+ .program_timing = dce110_timing_generator_v_program_timing,
-+ .enable_crtc = dce110_timing_generator_v_enable_crtc,
-+ .disable_crtc = dce110_timing_generator_v_disable_crtc,
-+ .is_counter_moving = dce110_timing_generator_v_is_counter_moving,
-+ .get_position = dce110_timing_generator_v_get_crtc_positions,
-+ .get_frame_count = dce110_timing_generator_v_get_vblank_counter,
-+ .set_early_control = dce110_timing_generator_v_set_early_control,
-+ .wait_for_state = dce110_timing_generator_v_wait_for_state,
-+ .set_blank = dce110_timing_generator_v_set_blank,
-+ .set_colors = dce110_timing_generator_v_set_colors,
-+ .set_overscan_blank_color =
-+ dce110_timing_generator_v_set_overscan_color_black,
-+ .set_blank_color = dce110_timing_generator_v_program_blank_color,
-+ .disable_vga = dce110_timing_generator_v_disable_vga,
-+ .did_triggered_reset_occur =
-+ dce110_timing_generator_v_did_triggered_reset_occur,
-+ .setup_global_swap_lock =
-+ dce110_timing_generator_v_setup_global_swap_lock,
-+ .enable_reset_trigger = dce110_timing_generator_v_enable_reset_trigger,
-+ .disable_reset_trigger = dce110_timing_generator_v_disable_reset_trigger,
-+ .tear_down_global_swap_lock =
-+ dce110_timing_generator_v_tear_down_global_swap_lock,
-+ .enable_advanced_request =
-+ dce110_timing_generator_v_enable_advanced_request
-+};
-+
-+bool dce110_timing_generator_v_construct(
-+ struct dce110_timing_generator *tg110,
-+ struct adapter_service *as,
-+ struct dc_context *ctx)
-+{
-+ if (!tg110)
-+ return false;
-+
-+ if (!as)
-+ return false;
-+
-+ tg110->controller_id = CONTROLLER_ID_UNDERLAY0;
-+
-+ tg110->base.funcs = &dce110_tg_v_funcs;
-+
-+ tg110->base.ctx = ctx;
-+ tg110->base.bp = dal_adapter_service_get_bios_parser(as);
-+
-+ tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
-+ tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
-+
-+ tg110->min_h_blank = 56;
-+ tg110->min_h_front_porch = 4;
-+ tg110->min_h_back_porch = 4;
-+
-+ return true;
-+}
-diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.h
-new file mode 100644
-index 0000000..fe3fb81
---- /dev/null
-+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator_v.h
-@@ -0,0 +1,34 @@
-+/*
-+ * 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 __DC_TIMING_GENERATOR_V_DCE110_H__
-+#define __DC_TIMING_GENERATOR_V_DCE110_H__
-+
-+bool dce110_timing_generator_v_construct(
-+ struct dce110_timing_generator *tg110,
-+ struct adapter_service *as,
-+ struct dc_context *ctx);
-+
-+#endif /* __DC_TIMING_GENERATOR_V_DCE110_H__ */
---
-2.7.4
-