diff options
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch')
-rw-r--r-- | meta-amdfalconx86/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch | 877 |
1 files changed, 0 insertions, 877 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch b/meta-amdfalconx86/recipes-kernel/linux/files/0778-drm-amd-dal-Add-timing-generator-for-underlay-pipe.patch deleted file mode 100644 index 93b86f71..00000000 --- a/meta-amdfalconx86/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 - |