diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3020-drm-amd-display-Only-blank-DCN-when-we-have-set_blan.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3020-drm-amd-display-Only-blank-DCN-when-we-have-set_blan.patch | 3757 |
1 files changed, 3757 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3020-drm-amd-display-Only-blank-DCN-when-we-have-set_blan.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3020-drm-amd-display-Only-blank-DCN-when-we-have-set_blan.patch new file mode 100644 index 00000000..7ca6a6a2 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3020-drm-amd-display-Only-blank-DCN-when-we-have-set_blan.patch @@ -0,0 +1,3757 @@ +From b4b80336420aead17ed60d6133ae6889b11f4866 Mon Sep 17 00:00:00 2001 +From: Yue Hin Lau <Yuehin.Lau@amd.com> +Date: Mon, 4 Dec 2017 16:58:11 -0500 +Subject: [PATCH 3020/4131] drm/amd/display: Only blank DCN when we have + set_blank implementation + +Also rename timing_generator to optc + +Signed-off-by: Yue Hin Lau <Yuehin.Lau@amd.com> +Reviewed-by: Eric Bernstein <Eric.Bernstein@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +--- + drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 33 +- + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 1279 ++++++++++++++++++++ + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | 490 ++++++++ + .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- + .../amd/display/dc/dcn10/dcn10_timing_generator.c | 1279 -------------------- + .../amd/display/dc/dcn10/dcn10_timing_generator.h | 490 -------- + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 19 - + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 + + 9 files changed, 1798 insertions(+), 1797 deletions(-) + create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c + create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h + delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c + delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +index a6ca1f9..e9be515 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +@@ -2,7 +2,7 @@ + # Makefile for DCN. + + DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ +- dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ ++ dcn10_dpp.o dcn10_opp.o dcn10_optc.o \ + dcn10_hubp.o dcn10_mpc.o \ + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o \ + dcn10_hubbub.o +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index 824de36..c9d717c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -32,7 +32,7 @@ + #include "dce/dce_hwseq.h" + #include "abm.h" + #include "dmcu.h" +-#include "dcn10/dcn10_timing_generator.h" ++#include "dcn10_optc.h" + #include "dcn10/dcn10_dpp.h" + #include "dcn10/dcn10_mpc.h" + #include "timing_generator.h" +@@ -465,6 +465,8 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( + bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? + false:true; + bool rightEyePolarity = stream->timing.flags.RIGHT_EYE_3D_POLARITY; ++ int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; ++ int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top; + + /* by upper caller loop, pipe0 is parent pipe and be called first. + * back end is set up by for pipe0. Other children pipe share back end +@@ -518,11 +520,14 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( + /* program otg blank color */ + color_space = stream->output_color_space; + color_space_to_black_color(dc, color_space, &black_color); +- pipe_ctx->stream_res.tg->funcs->set_blank_color( +- pipe_ctx->stream_res.tg, +- &black_color); + +- if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) { ++ if (pipe_ctx->stream_res.tg->funcs->set_blank_color) ++ pipe_ctx->stream_res.tg->funcs->set_blank_color( ++ pipe_ctx->stream_res.tg, ++ &black_color); ++ ++ if (pipe_ctx->stream_res.tg->funcs->is_blanked && ++ !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) { + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); + hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); + false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg); +@@ -1808,6 +1813,10 @@ static void program_all_pipe_in_tree( + struct pipe_ctx *pipe_ctx, + struct dc_state *context) + { ++ struct dc_stream_state *stream = pipe_ctx->stream; ++ int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; ++ int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top; ++ + if (pipe_ctx->top_pipe == NULL) { + + pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; +@@ -1818,7 +1827,11 @@ static void program_all_pipe_in_tree( + + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg); +- pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, !is_pipe_tree_visible(pipe_ctx)); ++ ++ if (pipe_ctx->stream_res.tg->funcs->set_blank) ++ pipe_ctx->stream_res.tg->funcs->set_blank( ++ pipe_ctx->stream_res.tg, ++ !is_pipe_tree_visible(pipe_ctx)); + } + + if (pipe_ctx->plane_state != NULL) { +@@ -1925,9 +1938,12 @@ static void dcn10_apply_ctx_for_surface( + { + int i; + struct timing_generator *tg; ++ struct output_pixel_processor *opp; + bool removed_pipe[4] = { false }; + unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; + bool program_water_mark = false; ++ int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; ++ int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top; + + struct pipe_ctx *top_pipe_to_program = + find_top_pipe_for_stream(dc, context, stream); +@@ -1935,6 +1951,8 @@ static void dcn10_apply_ctx_for_surface( + if (!top_pipe_to_program) + return; + ++ opp = top_pipe_to_program->stream_res.opp; ++ + tg = top_pipe_to_program->stream_res.tg; + + tg->funcs->lock(tg); +@@ -1942,7 +1960,8 @@ static void dcn10_apply_ctx_for_surface( + if (num_planes == 0) { + + /* OTG blank before remove all front end */ +- tg->funcs->set_blank(tg, true); ++ if (tg->funcs->set_blank) ++ tg->funcs->set_blank(tg, true); + } + + /* Disconnect unused mpcc */ +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +new file mode 100644 +index 0000000..827dd14 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +@@ -0,0 +1,1279 @@ ++/* ++ * 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 "reg_helper.h" ++#include "dcn10_optc.h" ++#include "dc.h" ++ ++#define REG(reg)\ ++ optc1->tg_regs->reg ++ ++#define CTX \ ++ optc1->base.ctx ++ ++#undef FN ++#define FN(reg_name, field_name) \ ++ optc1->tg_shift->field_name, optc1->tg_mask->field_name ++ ++#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 ++ ++/** ++* apply_front_porch_workaround TODO FPGA still need? ++* ++* This is a workaround for a bug that has existed since R5xx and has not been ++* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. ++*/ ++static void optc1_apply_front_porch_workaround( ++ struct timing_generator *optc, ++ struct dc_crtc_timing *timing) ++{ ++ if (timing->flags.INTERLACE == 1) { ++ if (timing->v_front_porch < 2) ++ timing->v_front_porch = 2; ++ } else { ++ if (timing->v_front_porch < 1) ++ timing->v_front_porch = 1; ++ } ++} ++ ++void optc1_program_global_sync( ++ struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ if (optc->dlg_otg_param.vstartup_start == 0) { ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++ ++ REG_SET(OTG_VSTARTUP_PARAM, 0, ++ VSTARTUP_START, optc->dlg_otg_param.vstartup_start); ++ ++ REG_SET_2(OTG_VUPDATE_PARAM, 0, ++ VUPDATE_OFFSET, optc->dlg_otg_param.vupdate_offset, ++ VUPDATE_WIDTH, optc->dlg_otg_param.vupdate_width); ++ ++ REG_SET(OTG_VREADY_PARAM, 0, ++ VREADY_OFFSET, optc->dlg_otg_param.vready_offset); ++} ++ ++static void optc1_disable_stereo(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_SET(OTG_STEREO_CONTROL, 0, ++ OTG_STEREO_EN, 0); ++ ++ REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0, ++ OTG_3D_STRUCTURE_EN, 0, ++ OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, ++ OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); ++ ++ REG_UPDATE(OPPBUF_CONTROL, ++ OPPBUF_ACTIVE_WIDTH, 0); ++ REG_UPDATE(OPPBUF_3D_PARAMETERS_0, ++ OPPBUF_3D_VACT_SPACE1_SIZE, 0); ++} ++ ++/** ++ * program_timing_generator used by mode timing set ++ * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. ++ * Including SYNC. Call BIOS command table to program Timings. ++ */ ++void optc1_program_timing( ++ struct timing_generator *optc, ++ const struct dc_crtc_timing *dc_crtc_timing, ++ bool use_vbios) ++{ ++ struct dc_crtc_timing patched_crtc_timing; ++ uint32_t vesa_sync_start; ++ uint32_t asic_blank_end; ++ uint32_t asic_blank_start; ++ uint32_t v_total; ++ uint32_t v_sync_end; ++ uint32_t v_init, v_fp2; ++ uint32_t h_sync_polarity, v_sync_polarity; ++ uint32_t interlace_factor; ++ uint32_t start_point = 0; ++ uint32_t field_num = 0; ++ uint32_t h_div_2; ++ int32_t vertical_line_start; ++ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ patched_crtc_timing = *dc_crtc_timing; ++ optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); ++ ++ /* Load horizontal timing */ ++ ++ /* CRTC_H_TOTAL = vesa.h_total - 1 */ ++ REG_SET(OTG_H_TOTAL, 0, ++ OTG_H_TOTAL, patched_crtc_timing.h_total - 1); ++ ++ /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */ ++ REG_UPDATE_2(OTG_H_SYNC_A, ++ OTG_H_SYNC_A_START, 0, ++ OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width); ++ ++ /* asic_h_blank_end = HsyncWidth + HbackPorch = ++ * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart - ++ * vesa.h_left_border ++ */ ++ vesa_sync_start = patched_crtc_timing.h_addressable + ++ patched_crtc_timing.h_border_right + ++ patched_crtc_timing.h_front_porch; ++ ++ asic_blank_end = patched_crtc_timing.h_total - ++ vesa_sync_start - ++ patched_crtc_timing.h_border_left; ++ ++ /* h_blank_start = v_blank_end + v_active */ ++ asic_blank_start = asic_blank_end + ++ patched_crtc_timing.h_border_left + ++ patched_crtc_timing.h_addressable + ++ patched_crtc_timing.h_border_right; ++ ++ REG_UPDATE_2(OTG_H_BLANK_START_END, ++ OTG_H_BLANK_START, asic_blank_start, ++ OTG_H_BLANK_END, asic_blank_end); ++ ++ /* h_sync polarity */ ++ h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? ++ 0 : 1; ++ ++ REG_UPDATE(OTG_H_SYNC_A_CNTL, ++ OTG_H_SYNC_A_POL, h_sync_polarity); ++ ++ /* Load vertical timing */ ++ ++ /* CRTC_V_TOTAL = v_total - 1 */ ++ if (patched_crtc_timing.flags.INTERLACE) { ++ interlace_factor = 2; ++ v_total = 2 * patched_crtc_timing.v_total; ++ } else { ++ interlace_factor = 1; ++ v_total = patched_crtc_timing.v_total - 1; ++ } ++ REG_SET(OTG_V_TOTAL, 0, ++ OTG_V_TOTAL, v_total); ++ ++ /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and ++ * OTG_V_TOTAL_MIN are equal to V_TOTAL. ++ */ ++ REG_SET(OTG_V_TOTAL_MAX, 0, ++ OTG_V_TOTAL_MAX, v_total); ++ REG_SET(OTG_V_TOTAL_MIN, 0, ++ OTG_V_TOTAL_MIN, v_total); ++ ++ /* v_sync_start = 0, v_sync_end = v_sync_width */ ++ v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor; ++ ++ REG_UPDATE_2(OTG_V_SYNC_A, ++ OTG_V_SYNC_A_START, 0, ++ OTG_V_SYNC_A_END, v_sync_end); ++ ++ vesa_sync_start = patched_crtc_timing.v_addressable + ++ patched_crtc_timing.v_border_bottom + ++ patched_crtc_timing.v_front_porch; ++ ++ asic_blank_end = (patched_crtc_timing.v_total - ++ vesa_sync_start - ++ patched_crtc_timing.v_border_top) ++ * interlace_factor; ++ ++ /* v_blank_start = v_blank_end + v_active */ ++ asic_blank_start = asic_blank_end + ++ (patched_crtc_timing.v_border_top + ++ patched_crtc_timing.v_addressable + ++ patched_crtc_timing.v_border_bottom) ++ * interlace_factor; ++ ++ REG_UPDATE_2(OTG_V_BLANK_START_END, ++ OTG_V_BLANK_START, asic_blank_start, ++ OTG_V_BLANK_END, asic_blank_end); ++ ++ /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, ++ * program the reg for interrupt postition. ++ */ ++ vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; ++ if (vertical_line_start < 0) { ++ ASSERT(0); ++ vertical_line_start = 0; ++ } ++ REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, ++ OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start); ++ ++ /* v_sync polarity */ ++ v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? ++ 0 : 1; ++ ++ REG_UPDATE(OTG_V_SYNC_A_CNTL, ++ OTG_V_SYNC_A_POL, v_sync_polarity); ++ ++ v_init = asic_blank_start; ++ if (optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || ++ optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || ++ optc->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { ++ start_point = 1; ++ if (patched_crtc_timing.flags.INTERLACE == 1) ++ field_num = 1; ++ } ++ v_fp2 = 0; ++ if (optc->dlg_otg_param.vstartup_start > asic_blank_end) ++ v_fp2 = optc->dlg_otg_param.vstartup_start > asic_blank_end; ++ ++ /* Interlace */ ++ if (patched_crtc_timing.flags.INTERLACE == 1) { ++ REG_UPDATE(OTG_INTERLACE_CONTROL, ++ OTG_INTERLACE_ENABLE, 1); ++ v_init = v_init / 2; ++ if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) ++ v_fp2 = v_fp2 / 2; ++ } else ++ REG_UPDATE(OTG_INTERLACE_CONTROL, ++ OTG_INTERLACE_ENABLE, 0); ++ ++ ++ /* VTG enable set to 0 first VInit */ ++ REG_UPDATE(CONTROL, ++ VTG0_ENABLE, 0); ++ ++ REG_UPDATE_2(CONTROL, ++ VTG0_FP2, v_fp2, ++ VTG0_VCOUNT_INIT, v_init); ++ ++ /* original code is using VTG offset to address OTG reg, seems wrong */ ++ REG_UPDATE_2(OTG_CONTROL, ++ OTG_START_POINT_CNTL, start_point, ++ OTG_FIELD_NUMBER_CNTL, field_num); ++ ++ optc1_program_global_sync(optc); ++ ++ /* TODO ++ * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 ++ * program_horz_count_by_2 ++ * for DVI 30bpp mode, 0 otherwise ++ * program_horz_count_by_2(optc, &patched_crtc_timing); ++ */ ++ ++ /* Enable stereo - only when we need to pack 3D frame. Other types ++ * of stereo handled in explicit call ++ */ ++ h_div_2 = (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ? ++ 1 : 0; ++ ++ REG_UPDATE(OTG_H_TIMING_CNTL, ++ OTG_H_TIMING_DIV_BY2, h_div_2); ++ ++} ++ ++static void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ uint32_t blank_data_double_buffer_enable = enable ? 1 : 0; ++ ++ REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, ++ OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable); ++} ++ ++/** ++ * unblank_crtc ++ * Call ASIC Control Object to UnBlank CRTC. ++ */ ++static void optc1_unblank_crtc(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t vertical_interrupt_enable = 0; ++ ++ REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, ++ OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable); ++ ++ /* temporary work around for vertical interrupt, once vertical interrupt enabled, ++ * this check will be removed. ++ */ ++ if (vertical_interrupt_enable) ++ optc1_set_blank_data_double_buffer(optc, true); ++ ++ REG_UPDATE_2(OTG_BLANK_CONTROL, ++ OTG_BLANK_DATA_EN, 0, ++ OTG_BLANK_DE_MODE, 0); ++} ++ ++/** ++ * blank_crtc ++ * Call ASIC Control Object to Blank CRTC. ++ */ ++ ++static void optc1_blank_crtc(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_UPDATE_2(OTG_BLANK_CONTROL, ++ OTG_BLANK_DATA_EN, 1, ++ OTG_BLANK_DE_MODE, 0); ++ ++ optc1_set_blank_data_double_buffer(optc, false); ++} ++ ++void optc1_set_blank(struct timing_generator *optc, ++ bool enable_blanking) ++{ ++ if (enable_blanking) ++ optc1_blank_crtc(optc); ++ else ++ optc1_unblank_crtc(optc); ++} ++ ++bool optc1_is_blanked(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t blank_en; ++ uint32_t blank_state; ++ ++ REG_GET_2(OTG_BLANK_CONTROL, ++ OTG_BLANK_DATA_EN, &blank_en, ++ OTG_CURRENT_BLANK_STATE, &blank_state); ++ ++ return blank_en && blank_state; ++} ++ ++void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ if (enable) { ++ REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, ++ OPTC_INPUT_CLK_EN, 1, ++ OPTC_INPUT_CLK_GATE_DIS, 1); ++ ++ REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, ++ OPTC_INPUT_CLK_ON, 1, ++ 1, 1000); ++ ++ /* Enable clock */ ++ REG_UPDATE_2(OTG_CLOCK_CONTROL, ++ OTG_CLOCK_EN, 1, ++ OTG_CLOCK_GATE_DIS, 1); ++ REG_WAIT(OTG_CLOCK_CONTROL, ++ OTG_CLOCK_ON, 1, ++ 1, 1000); ++ } else { ++ REG_UPDATE_2(OTG_CLOCK_CONTROL, ++ OTG_CLOCK_GATE_DIS, 0, ++ OTG_CLOCK_EN, 0); ++ ++ REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, ++ OPTC_INPUT_CLK_GATE_DIS, 0, ++ OPTC_INPUT_CLK_EN, 0); ++ } ++} ++ ++/** ++ * Enable CRTC ++ * Enable CRTC - call ASIC Control Object to enable Timing generator. ++ */ ++static bool optc1_enable_crtc(struct timing_generator *optc) ++{ ++ /* TODO FPGA wait for answer ++ * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE ++ * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK ++ */ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ /* opp instance for OTG. For DCN1.0, ODM is remoed. ++ * OPP and OPTC should 1:1 mapping ++ */ ++ REG_UPDATE(OPTC_DATA_SOURCE_SELECT, ++ OPTC_SRC_SEL, optc->inst); ++ ++ /* VTG enable first is for HW workaround */ ++ REG_UPDATE(CONTROL, ++ VTG0_ENABLE, 1); ++ ++ /* Enable CRTC */ ++ REG_UPDATE_2(OTG_CONTROL, ++ OTG_DISABLE_POINT_CNTL, 3, ++ OTG_MASTER_EN, 1); ++ ++ return true; ++} ++ ++/* disable_crtc - call ASIC Control Object to disable Timing generator. */ ++bool optc1_disable_crtc(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ /* disable otg request until end of the first line ++ * in the vertical blank region ++ */ ++ REG_UPDATE_2(OTG_CONTROL, ++ OTG_DISABLE_POINT_CNTL, 3, ++ OTG_MASTER_EN, 0); ++ ++ REG_UPDATE(CONTROL, ++ VTG0_ENABLE, 0); ++ ++ /* CRTC disabled, so disable clock. */ ++ REG_WAIT(OTG_CLOCK_CONTROL, ++ OTG_BUSY, 0, ++ 1, 100000); ++ ++ return true; ++} ++ ++ ++void optc1_program_blank_color( ++ struct timing_generator *optc, ++ const struct tg_color *black_color) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_SET_3(OTG_BLACK_COLOR, 0, ++ OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, ++ OTG_BLACK_COLOR_G_Y, black_color->color_g_y, ++ OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); ++} ++ ++bool optc1_validate_timing( ++ struct timing_generator *optc, ++ const struct dc_crtc_timing *timing) ++{ ++ uint32_t interlace_factor; ++ uint32_t v_blank; ++ uint32_t h_blank; ++ uint32_t min_v_blank; ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ ASSERT(timing != NULL); ++ ++ interlace_factor = timing->flags.INTERLACE ? 2 : 1; ++ v_blank = (timing->v_total - timing->v_addressable - ++ timing->v_border_top - timing->v_border_bottom) * ++ interlace_factor; ++ ++ h_blank = (timing->h_total - timing->h_addressable - ++ timing->h_border_right - ++ timing->h_border_left); ++ ++ if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && ++ timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && ++ timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && ++ timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && ++ timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && ++ timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) ++ return false; ++ ++ /* Temporarily blocking interlacing mode until it's supported */ ++ if (timing->flags.INTERLACE == 1) ++ return false; ++ ++ /* Check maximum number of pixels supported by Timing Generator ++ * (Currently will never fail, in order to fail needs display which ++ * needs more than 8192 horizontal and ++ * more than 8192 vertical total pixels) ++ */ ++ if (timing->h_total > optc1->max_h_total || ++ timing->v_total > optc1->max_v_total) ++ return false; ++ ++ ++ if (h_blank < optc1->min_h_blank) ++ return false; ++ ++ if (timing->h_sync_width < optc1->min_h_sync_width || ++ timing->v_sync_width < optc1->min_v_sync_width) ++ return false; ++ ++ min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; ++ ++ if (v_blank < min_v_blank) ++ return false; ++ ++ return true; ++ ++} ++ ++/* ++ * get_vblank_counter ++ * ++ * @brief ++ * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which ++ * holds the counter of frames. ++ * ++ * @param ++ * struct timing_generator *optc - [in] timing generator which controls the ++ * desired CRTC ++ * ++ * @return ++ * Counter of frames, which should equal to number of vblanks. ++ */ ++uint32_t optc1_get_vblank_counter(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t frame_count; ++ ++ REG_GET(OTG_STATUS_FRAME_COUNT, ++ OTG_FRAME_COUNT, &frame_count); ++ ++ return frame_count; ++} ++ ++void optc1_lock(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_SET(OTG_GLOBAL_CONTROL0, 0, ++ OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); ++ REG_SET(OTG_MASTER_UPDATE_LOCK, 0, ++ OTG_MASTER_UPDATE_LOCK, 1); ++ ++ /* Should be fast, status does not update on maximus */ ++ if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) ++ REG_WAIT(OTG_MASTER_UPDATE_LOCK, ++ UPDATE_LOCK_STATUS, 1, ++ 1, 10); ++} ++ ++void optc1_unlock(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_SET(OTG_MASTER_UPDATE_LOCK, 0, ++ OTG_MASTER_UPDATE_LOCK, 0); ++} ++ ++void optc1_get_position(struct timing_generator *optc, ++ struct crtc_position *position) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_GET_2(OTG_STATUS_POSITION, ++ OTG_HORZ_COUNT, &position->horizontal_count, ++ OTG_VERT_COUNT, &position->vertical_count); ++ ++ REG_GET(OTG_NOM_VERT_POSITION, ++ OTG_VERT_COUNT_NOM, &position->nominal_vcount); ++} ++ ++bool optc1_is_counter_moving(struct timing_generator *optc) ++{ ++ struct crtc_position position1, position2; ++ ++ optc->funcs->get_position(optc, &position1); ++ optc->funcs->get_position(optc, &position2); ++ ++ if (position1.horizontal_count == position2.horizontal_count && ++ position1.vertical_count == position2.vertical_count) ++ return false; ++ else ++ return true; ++} ++ ++bool optc1_did_triggered_reset_occur( ++ struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t occurred_force, occurred_vsync; ++ ++ REG_GET(OTG_FORCE_COUNT_NOW_CNTL, ++ OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force); ++ ++ REG_GET(OTG_VERT_SYNC_CONTROL, ++ OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync); ++ ++ return occurred_vsync != 0 || occurred_force != 0; ++} ++ ++void optc1_disable_reset_trigger(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_WRITE(OTG_TRIGA_CNTL, 0); ++ ++ REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, ++ OTG_FORCE_COUNT_NOW_CLEAR, 1); ++ ++ REG_SET(OTG_VERT_SYNC_CONTROL, 0, ++ OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1); ++} ++ ++void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t falling_edge; ++ ++ REG_GET(OTG_V_SYNC_A_CNTL, ++ OTG_V_SYNC_A_POL, &falling_edge); ++ ++ if (falling_edge) ++ REG_SET_3(OTG_TRIGA_CNTL, 0, ++ /* vsync signal from selected OTG pipe based ++ * on OTG_TRIG_SOURCE_PIPE_SELECT setting ++ */ ++ OTG_TRIGA_SOURCE_SELECT, 20, ++ OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, ++ /* always detect falling edge */ ++ OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1); ++ else ++ REG_SET_3(OTG_TRIGA_CNTL, 0, ++ /* vsync signal from selected OTG pipe based ++ * on OTG_TRIG_SOURCE_PIPE_SELECT setting ++ */ ++ OTG_TRIGA_SOURCE_SELECT, 20, ++ OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, ++ /* always detect rising edge */ ++ OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1); ++ ++ REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, ++ /* force H count to H_TOTAL and V count to V_TOTAL in ++ * progressive mode and V_TOTAL-1 in interlaced mode ++ */ ++ OTG_FORCE_COUNT_NOW_MODE, 2); ++} ++ ++void optc1_enable_crtc_reset( ++ struct timing_generator *optc, ++ int source_tg_inst, ++ struct crtc_trigger_info *crtc_tp) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t falling_edge = 0; ++ uint32_t rising_edge = 0; ++ ++ switch (crtc_tp->event) { ++ ++ case CRTC_EVENT_VSYNC_RISING: ++ rising_edge = 1; ++ break; ++ ++ case CRTC_EVENT_VSYNC_FALLING: ++ falling_edge = 1; ++ break; ++ } ++ ++ REG_SET_4(OTG_TRIGA_CNTL, 0, ++ /* vsync signal from selected OTG pipe based ++ * on OTG_TRIG_SOURCE_PIPE_SELECT setting ++ */ ++ OTG_TRIGA_SOURCE_SELECT, 20, ++ OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, ++ /* always detect falling edge */ ++ OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge, ++ OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge); ++ ++ switch (crtc_tp->delay) { ++ case TRIGGER_DELAY_NEXT_LINE: ++ REG_SET(OTG_VERT_SYNC_CONTROL, 0, ++ OTG_AUTO_FORCE_VSYNC_MODE, 1); ++ break; ++ case TRIGGER_DELAY_NEXT_PIXEL: ++ REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, ++ /* force H count to H_TOTAL and V count to V_TOTAL in ++ * progressive mode and V_TOTAL-1 in interlaced mode ++ */ ++ OTG_FORCE_COUNT_NOW_MODE, 2); ++ break; ++ } ++} ++ ++void optc1_wait_for_state(struct timing_generator *optc, ++ enum crtc_state state) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ switch (state) { ++ case CRTC_STATE_VBLANK: ++ REG_WAIT(OTG_STATUS, ++ OTG_V_BLANK, 1, ++ 1, 100000); /* 1 vupdate at 10hz */ ++ break; ++ ++ case CRTC_STATE_VACTIVE: ++ REG_WAIT(OTG_STATUS, ++ OTG_V_ACTIVE_DISP, 1, ++ 1, 100000); /* 1 vupdate at 10hz */ ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++void optc1_set_early_control( ++ struct timing_generator *optc, ++ uint32_t early_cntl) ++{ ++ /* asic design change, do not need this control ++ * empty for share caller logic ++ */ ++} ++ ++ ++void optc1_set_static_screen_control( ++ struct timing_generator *optc, ++ uint32_t value) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ /* Bit 8 is no longer applicable in RV for PSR case, ++ * set bit 8 to 0 if given ++ */ ++ if ((value & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN) ++ != 0) ++ value = value & ++ ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN; ++ ++ REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0, ++ OTG_STATIC_SCREEN_EVENT_MASK, value, ++ OTG_STATIC_SCREEN_FRAME_COUNT, 2); ++} ++ ++ ++/** ++ ***************************************************************************** ++ * Function: set_drr ++ * ++ * @brief ++ * Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. ++ * ++ ***************************************************************************** ++ */ ++void optc1_set_drr( ++ struct timing_generator *optc, ++ const struct drr_params *params) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ if (params != NULL && ++ params->vertical_total_max > 0 && ++ params->vertical_total_min > 0) { ++ ++ REG_SET(OTG_V_TOTAL_MAX, 0, ++ OTG_V_TOTAL_MAX, params->vertical_total_max - 1); ++ ++ REG_SET(OTG_V_TOTAL_MIN, 0, ++ OTG_V_TOTAL_MIN, params->vertical_total_min - 1); ++ ++ REG_UPDATE_5(OTG_V_TOTAL_CONTROL, ++ OTG_V_TOTAL_MIN_SEL, 1, ++ OTG_V_TOTAL_MAX_SEL, 1, ++ OTG_FORCE_LOCK_ON_EVENT, 0, ++ OTG_SET_V_TOTAL_MIN_MASK_EN, 0, ++ OTG_SET_V_TOTAL_MIN_MASK, 0); ++ } else { ++ REG_SET(OTG_V_TOTAL_MIN, 0, ++ OTG_V_TOTAL_MIN, 0); ++ ++ REG_SET(OTG_V_TOTAL_MAX, 0, ++ OTG_V_TOTAL_MAX, 0); ++ ++ REG_UPDATE_4(OTG_V_TOTAL_CONTROL, ++ OTG_SET_V_TOTAL_MIN_MASK, 0, ++ OTG_V_TOTAL_MIN_SEL, 0, ++ OTG_V_TOTAL_MAX_SEL, 0, ++ OTG_FORCE_LOCK_ON_EVENT, 0); ++ } ++} ++ ++static void optc1_set_test_pattern( ++ struct timing_generator *optc, ++ /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' ++ * because this is not DP-specific (which is probably somewhere in DP ++ * encoder) */ ++ enum controller_dp_test_pattern test_pattern, ++ enum dc_color_depth color_depth) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ enum test_pattern_color_format bit_depth; ++ enum test_pattern_dyn_range dyn_range; ++ enum test_pattern_mode mode; ++ uint32_t pattern_mask; ++ uint32_t pattern_data; ++ /* color ramp generator mixes 16-bits color */ ++ uint32_t src_bpc = 16; ++ /* requested bpc */ ++ uint32_t dst_bpc; ++ uint32_t index; ++ /* RGB values of the color bars. ++ * Produce two RGB colors: RGB0 - white (all Fs) ++ * and RGB1 - black (all 0s) ++ * (three RGB components for two colors) ++ */ ++ uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, ++ 0x0000, 0x0000}; ++ /* dest color (converted to the specified color format) */ ++ uint16_t dst_color[6]; ++ uint32_t inc_base; ++ ++ /* translate to bit depth */ ++ switch (color_depth) { ++ case COLOR_DEPTH_666: ++ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; ++ break; ++ case COLOR_DEPTH_888: ++ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; ++ break; ++ case COLOR_DEPTH_101010: ++ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; ++ break; ++ case COLOR_DEPTH_121212: ++ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; ++ break; ++ default: ++ bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; ++ break; ++ } ++ ++ switch (test_pattern) { ++ case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: ++ case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: ++ { ++ dyn_range = (test_pattern == ++ CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? ++ TEST_PATTERN_DYN_RANGE_CEA : ++ TEST_PATTERN_DYN_RANGE_VESA); ++ mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; ++ ++ REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS, ++ OTG_TEST_PATTERN_VRES, 6, ++ OTG_TEST_PATTERN_HRES, 6); ++ ++ REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, ++ OTG_TEST_PATTERN_EN, 1, ++ OTG_TEST_PATTERN_MODE, mode, ++ OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, ++ OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); ++ } ++ break; ++ ++ case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: ++ case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: ++ { ++ mode = (test_pattern == ++ CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? ++ TEST_PATTERN_MODE_VERTICALBARS : ++ TEST_PATTERN_MODE_HORIZONTALBARS); ++ ++ switch (bit_depth) { ++ case TEST_PATTERN_COLOR_FORMAT_BPC_6: ++ dst_bpc = 6; ++ break; ++ case TEST_PATTERN_COLOR_FORMAT_BPC_8: ++ dst_bpc = 8; ++ break; ++ case TEST_PATTERN_COLOR_FORMAT_BPC_10: ++ dst_bpc = 10; ++ break; ++ default: ++ dst_bpc = 8; ++ break; ++ } ++ ++ /* adjust color to the required colorFormat */ ++ for (index = 0; index < 6; index++) { ++ /* dst = 2^dstBpc * src / 2^srcBpc = src >> ++ * (srcBpc - dstBpc); ++ */ ++ dst_color[index] = ++ src_color[index] >> (src_bpc - dst_bpc); ++ /* CRTC_TEST_PATTERN_DATA has 16 bits, ++ * lowest 6 are hardwired to ZERO ++ * color bits should be left aligned aligned to MSB ++ * XXXXXXXXXX000000 for 10 bit, ++ * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 ++ */ ++ dst_color[index] <<= (16 - dst_bpc); ++ } ++ ++ REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); ++ ++ /* We have to write the mask before data, similar to pipeline. ++ * For example, for 8 bpc, if we want RGB0 to be magenta, ++ * and RGB1 to be cyan, ++ * we need to make 7 writes: ++ * MASK DATA ++ * 000001 00000000 00000000 set mask to R0 ++ * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 ++ * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 ++ * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 ++ * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 ++ * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 ++ * 100000 11111111 00000000 B1 255, 0xFF00 ++ * ++ * we will make a loop of 6 in which we prepare the mask, ++ * then write, then prepare the color for next write. ++ * first iteration will write mask only, ++ * but each next iteration color prepared in ++ * previous iteration will be written within new mask, ++ * the last component will written separately, ++ * mask is not changing between 6th and 7th write ++ * and color will be prepared by last iteration ++ */ ++ ++ /* write color, color values mask in CRTC_TEST_PATTERN_MASK ++ * is B1, G1, R1, B0, G0, R0 ++ */ ++ pattern_data = 0; ++ for (index = 0; index < 6; index++) { ++ /* prepare color mask, first write PATTERN_DATA ++ * will have all zeros ++ */ ++ pattern_mask = (1 << index); ++ ++ /* write color component */ ++ REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, ++ OTG_TEST_PATTERN_MASK, pattern_mask, ++ OTG_TEST_PATTERN_DATA, pattern_data); ++ ++ /* prepare next color component, ++ * will be written in the next iteration ++ */ ++ pattern_data = dst_color[index]; ++ } ++ /* write last color component, ++ * it's been already prepared in the loop ++ */ ++ REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, ++ OTG_TEST_PATTERN_MASK, pattern_mask, ++ OTG_TEST_PATTERN_DATA, pattern_data); ++ ++ /* enable test pattern */ ++ REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, ++ OTG_TEST_PATTERN_EN, 1, ++ OTG_TEST_PATTERN_MODE, mode, ++ OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, ++ OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); ++ } ++ break; ++ ++ case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: ++ { ++ mode = (bit_depth == ++ TEST_PATTERN_COLOR_FORMAT_BPC_10 ? ++ TEST_PATTERN_MODE_DUALRAMP_RGB : ++ TEST_PATTERN_MODE_SINGLERAMP_RGB); ++ ++ switch (bit_depth) { ++ case TEST_PATTERN_COLOR_FORMAT_BPC_6: ++ dst_bpc = 6; ++ break; ++ case TEST_PATTERN_COLOR_FORMAT_BPC_8: ++ dst_bpc = 8; ++ break; ++ case TEST_PATTERN_COLOR_FORMAT_BPC_10: ++ dst_bpc = 10; ++ break; ++ default: ++ dst_bpc = 8; ++ break; ++ } ++ ++ /* increment for the first ramp for one color gradation ++ * 1 gradation for 6-bit color is 2^10 ++ * gradations in 16-bit color ++ */ ++ inc_base = (src_bpc - dst_bpc); ++ ++ switch (bit_depth) { ++ case TEST_PATTERN_COLOR_FORMAT_BPC_6: ++ { ++ REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, ++ OTG_TEST_PATTERN_INC0, inc_base, ++ OTG_TEST_PATTERN_INC1, 0, ++ OTG_TEST_PATTERN_HRES, 6, ++ OTG_TEST_PATTERN_VRES, 6, ++ OTG_TEST_PATTERN_RAMP0_OFFSET, 0); ++ } ++ break; ++ case TEST_PATTERN_COLOR_FORMAT_BPC_8: ++ { ++ REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, ++ OTG_TEST_PATTERN_INC0, inc_base, ++ OTG_TEST_PATTERN_INC1, 0, ++ OTG_TEST_PATTERN_HRES, 8, ++ OTG_TEST_PATTERN_VRES, 6, ++ OTG_TEST_PATTERN_RAMP0_OFFSET, 0); ++ } ++ break; ++ case TEST_PATTERN_COLOR_FORMAT_BPC_10: ++ { ++ REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, ++ OTG_TEST_PATTERN_INC0, inc_base, ++ OTG_TEST_PATTERN_INC1, inc_base + 2, ++ OTG_TEST_PATTERN_HRES, 8, ++ OTG_TEST_PATTERN_VRES, 5, ++ OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); ++ ++ /* enable test pattern */ ++ REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); ++ ++ REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0, ++ OTG_TEST_PATTERN_EN, 1, ++ OTG_TEST_PATTERN_MODE, mode, ++ OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, ++ OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); ++ } ++ break; ++ case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: ++ { ++ REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); ++ REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); ++ REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); ++ } ++ break; ++ default: ++ break; ++ ++ } ++} ++ ++void optc1_get_crtc_scanoutpos( ++ struct timing_generator *optc, ++ uint32_t *v_blank_start, ++ uint32_t *v_blank_end, ++ uint32_t *h_position, ++ uint32_t *v_position) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ struct crtc_position position; ++ ++ REG_GET_2(OTG_V_BLANK_START_END, ++ OTG_V_BLANK_START, v_blank_start, ++ OTG_V_BLANK_END, v_blank_end); ++ ++ optc1_get_position(optc, &position); ++ ++ *h_position = position.horizontal_count; ++ *v_position = position.vertical_count; ++} ++ ++ ++ ++static void optc1_enable_stereo(struct timing_generator *optc, ++ const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ uint32_t active_width = timing->h_addressable; ++ uint32_t space1_size = timing->v_total - timing->v_addressable; ++ ++ if (flags) { ++ uint32_t stereo_en; ++ stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; ++ ++ if (flags->PROGRAM_STEREO) ++ REG_UPDATE_3(OTG_STEREO_CONTROL, ++ OTG_STEREO_EN, stereo_en, ++ OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, ++ OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); ++ ++ if (flags->PROGRAM_POLARITY) ++ REG_UPDATE(OTG_STEREO_CONTROL, ++ OTG_STEREO_EYE_FLAG_POLARITY, ++ flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); ++ ++ if (flags->DISABLE_STEREO_DP_SYNC) ++ REG_UPDATE(OTG_STEREO_CONTROL, ++ OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); ++ ++ if (flags->PROGRAM_STEREO) ++ REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, ++ OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED, ++ OTG_3D_STRUCTURE_V_UPDATE_MODE, flags->FRAME_PACKED, ++ OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); ++ ++ } ++ ++ REG_UPDATE(OPPBUF_CONTROL, ++ OPPBUF_ACTIVE_WIDTH, active_width); ++ ++ REG_UPDATE(OPPBUF_3D_PARAMETERS_0, ++ OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); ++} ++ ++void optc1_program_stereo(struct timing_generator *optc, ++ const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) ++{ ++ if (flags->PROGRAM_STEREO) ++ optc1_enable_stereo(optc, timing, flags); ++ else ++ optc1_disable_stereo(optc); ++} ++ ++ ++bool optc1_is_stereo_left_eye(struct timing_generator *optc) ++{ ++ bool ret = false; ++ uint32_t left_eye = 0; ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_GET(OTG_STEREO_STATUS, ++ OTG_STEREO_CURRENT_EYE, &left_eye); ++ if (left_eye == 1) ++ ret = true; ++ else ++ ret = false; ++ ++ return ret; ++} ++ ++void optc1_read_otg_state(struct optc *optc1, ++ struct dcn_otg_state *s) ++{ ++ REG_GET(OTG_CONTROL, ++ OTG_MASTER_EN, &s->otg_enabled); ++ ++ REG_GET_2(OTG_V_BLANK_START_END, ++ OTG_V_BLANK_START, &s->v_blank_start, ++ OTG_V_BLANK_END, &s->v_blank_end); ++ ++ REG_GET(OTG_V_SYNC_A_CNTL, ++ OTG_V_SYNC_A_POL, &s->v_sync_a_pol); ++ ++ REG_GET(OTG_V_TOTAL, ++ OTG_V_TOTAL, &s->v_total); ++ ++ REG_GET(OTG_V_TOTAL_MAX, ++ OTG_V_TOTAL_MAX, &s->v_total_max); ++ ++ REG_GET(OTG_V_TOTAL_MIN, ++ OTG_V_TOTAL_MIN, &s->v_total_min); ++ ++ REG_GET_2(OTG_V_SYNC_A, ++ OTG_V_SYNC_A_START, &s->v_sync_a_start, ++ OTG_V_SYNC_A_END, &s->v_sync_a_end); ++ ++ REG_GET_2(OTG_H_BLANK_START_END, ++ OTG_H_BLANK_START, &s->h_blank_start, ++ OTG_H_BLANK_END, &s->h_blank_end); ++ ++ REG_GET_2(OTG_H_SYNC_A, ++ OTG_H_SYNC_A_START, &s->h_sync_a_start, ++ OTG_H_SYNC_A_END, &s->h_sync_a_end); ++ ++ REG_GET(OTG_H_SYNC_A_CNTL, ++ OTG_H_SYNC_A_POL, &s->h_sync_a_pol); ++ ++ REG_GET(OTG_H_TOTAL, ++ OTG_H_TOTAL, &s->h_total); ++ ++ REG_GET(OPTC_INPUT_GLOBAL_CONTROL, ++ OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); ++} ++ ++static void optc1_clear_optc_underflow(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ ++ REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); ++} ++ ++static void optc1_tg_init(struct timing_generator *optc) ++{ ++ optc1_set_blank_data_double_buffer(optc, true); ++ optc1_clear_optc_underflow(optc); ++} ++ ++static bool optc1_is_tg_enabled(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t otg_enabled = 0; ++ ++ REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled); ++ ++ return (otg_enabled != 0); ++ ++} ++ ++static bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) ++{ ++ struct optc *optc1 = DCN10TG_FROM_TG(optc); ++ uint32_t underflow_occurred = 0; ++ ++ REG_GET(OPTC_INPUT_GLOBAL_CONTROL, ++ OPTC_UNDERFLOW_OCCURRED_STATUS, ++ &underflow_occurred); ++ ++ return (underflow_occurred == 1); ++} ++ ++static const struct timing_generator_funcs dcn10_tg_funcs = { ++ .validate_timing = optc1_validate_timing, ++ .program_timing = optc1_program_timing, ++ .program_global_sync = optc1_program_global_sync, ++ .enable_crtc = optc1_enable_crtc, ++ .disable_crtc = optc1_disable_crtc, ++ /* used by enable_timing_synchronization. Not need for FPGA */ ++ .is_counter_moving = optc1_is_counter_moving, ++ .get_position = optc1_get_position, ++ .get_frame_count = optc1_get_vblank_counter, ++ .get_scanoutpos = optc1_get_crtc_scanoutpos, ++ .set_early_control = optc1_set_early_control, ++ /* used by enable_timing_synchronization. Not need for FPGA */ ++ .wait_for_state = optc1_wait_for_state, ++ .set_blank = optc1_set_blank, ++ .is_blanked = optc1_is_blanked, ++ .set_blank_color = optc1_program_blank_color, ++ .did_triggered_reset_occur = optc1_did_triggered_reset_occur, ++ .enable_reset_trigger = optc1_enable_reset_trigger, ++ .enable_crtc_reset = optc1_enable_crtc_reset, ++ .disable_reset_trigger = optc1_disable_reset_trigger, ++ .lock = optc1_lock, ++ .unlock = optc1_unlock, ++ .enable_optc_clock = optc1_enable_optc_clock, ++ .set_drr = optc1_set_drr, ++ .set_static_screen_control = optc1_set_static_screen_control, ++ .set_test_pattern = optc1_set_test_pattern, ++ .program_stereo = optc1_program_stereo, ++ .is_stereo_left_eye = optc1_is_stereo_left_eye, ++ .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, ++ .tg_init = optc1_tg_init, ++ .is_tg_enabled = optc1_is_tg_enabled, ++ .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, ++ .clear_optc_underflow = optc1_clear_optc_underflow, ++}; ++ ++void dcn10_timing_generator_init(struct optc *optc1) ++{ ++ optc1->base.funcs = &dcn10_tg_funcs; ++ ++ optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; ++ optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; ++ ++ optc1->min_h_blank = 32; ++ optc1->min_v_blank = 3; ++ optc1->min_v_blank_interlace = 5; ++ optc1->min_h_sync_width = 8; ++ optc1->min_v_sync_width = 1; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +new file mode 100644 +index 0000000..eec860fa +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +@@ -0,0 +1,490 @@ ++/* ++ * 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_DCN10_H__ ++#define __DC_TIMING_GENERATOR_DCN10_H__ ++ ++#include "timing_generator.h" ++ ++#define DCN10TG_FROM_TG(tg)\ ++ container_of(tg, struct optc, base) ++ ++#define TG_COMMON_REG_LIST_DCN(inst) \ ++ SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ ++ SRI(OTG_VUPDATE_PARAM, OTG, inst),\ ++ SRI(OTG_VREADY_PARAM, OTG, inst),\ ++ SRI(OTG_BLANK_CONTROL, OTG, inst),\ ++ SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ ++ SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ ++ SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ ++ SRI(OTG_H_TOTAL, OTG, inst),\ ++ SRI(OTG_H_BLANK_START_END, OTG, inst),\ ++ SRI(OTG_H_SYNC_A, OTG, inst),\ ++ SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ ++ SRI(OTG_H_TIMING_CNTL, OTG, inst),\ ++ SRI(OTG_V_TOTAL, OTG, inst),\ ++ SRI(OTG_V_BLANK_START_END, OTG, inst),\ ++ SRI(OTG_V_SYNC_A, OTG, inst),\ ++ SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ ++ SRI(OTG_INTERLACE_CONTROL, OTG, inst),\ ++ SRI(OTG_CONTROL, OTG, inst),\ ++ SRI(OTG_STEREO_CONTROL, OTG, inst),\ ++ SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ ++ SRI(OTG_STEREO_STATUS, OTG, inst),\ ++ SRI(OTG_V_TOTAL_MAX, OTG, inst),\ ++ SRI(OTG_V_TOTAL_MIN, OTG, inst),\ ++ SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ ++ SRI(OTG_TRIGA_CNTL, OTG, inst),\ ++ SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ ++ SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ ++ SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ ++ SRI(OTG_STATUS, OTG, inst),\ ++ SRI(OTG_STATUS_POSITION, OTG, inst),\ ++ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ ++ SRI(OTG_BLACK_COLOR, OTG, inst),\ ++ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ ++ SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ ++ SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ ++ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ ++ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ ++ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ ++ SRI(OPPBUF_CONTROL, OPPBUF, inst),\ ++ SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ ++ SRI(CONTROL, VTG, inst),\ ++ SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ ++ SRI(OTG_MASTER_UPDATE_MODE, OTG, inst),\ ++ SRI(OTG_GSL_CONTROL, OTG, inst) ++ ++#define TG_COMMON_REG_LIST_DCN1_0(inst) \ ++ TG_COMMON_REG_LIST_DCN(inst),\ ++ SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ ++ SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ ++ SRI(OTG_TEST_PATTERN_COLOR, OTG, inst) ++ ++ ++struct dcn_optc_registers { ++ uint32_t OTG_VERT_SYNC_CONTROL; ++ uint32_t OTG_MASTER_UPDATE_MODE; ++ uint32_t OTG_GSL_CONTROL; ++ uint32_t OTG_VSTARTUP_PARAM; ++ uint32_t OTG_VUPDATE_PARAM; ++ uint32_t OTG_VREADY_PARAM; ++ uint32_t OTG_BLANK_CONTROL; ++ uint32_t OTG_MASTER_UPDATE_LOCK; ++ uint32_t OTG_GLOBAL_CONTROL0; ++ uint32_t OTG_DOUBLE_BUFFER_CONTROL; ++ uint32_t OTG_H_TOTAL; ++ uint32_t OTG_H_BLANK_START_END; ++ uint32_t OTG_H_SYNC_A; ++ uint32_t OTG_H_SYNC_A_CNTL; ++ uint32_t OTG_H_TIMING_CNTL; ++ uint32_t OTG_V_TOTAL; ++ uint32_t OTG_V_BLANK_START_END; ++ uint32_t OTG_V_SYNC_A; ++ uint32_t OTG_V_SYNC_A_CNTL; ++ uint32_t OTG_INTERLACE_CONTROL; ++ uint32_t OTG_CONTROL; ++ uint32_t OTG_STEREO_CONTROL; ++ uint32_t OTG_3D_STRUCTURE_CONTROL; ++ uint32_t OTG_STEREO_STATUS; ++ uint32_t OTG_V_TOTAL_MAX; ++ uint32_t OTG_V_TOTAL_MIN; ++ uint32_t OTG_V_TOTAL_CONTROL; ++ uint32_t OTG_TRIGA_CNTL; ++ uint32_t OTG_FORCE_COUNT_NOW_CNTL; ++ uint32_t OTG_STATIC_SCREEN_CONTROL; ++ uint32_t OTG_STATUS_FRAME_COUNT; ++ uint32_t OTG_STATUS; ++ uint32_t OTG_STATUS_POSITION; ++ uint32_t OTG_NOM_VERT_POSITION; ++ uint32_t OTG_BLACK_COLOR; ++ uint32_t OTG_TEST_PATTERN_PARAMETERS; ++ uint32_t OTG_TEST_PATTERN_CONTROL; ++ uint32_t OTG_TEST_PATTERN_COLOR; ++ uint32_t OTG_CLOCK_CONTROL; ++ uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; ++ uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; ++ uint32_t OPTC_INPUT_CLOCK_CONTROL; ++ uint32_t OPTC_DATA_SOURCE_SELECT; ++ uint32_t OPTC_INPUT_GLOBAL_CONTROL; ++ uint32_t OPPBUF_CONTROL; ++ uint32_t OPPBUF_3D_PARAMETERS_0; ++ uint32_t CONTROL; ++ uint32_t OTG_GSL_WINDOW_X; ++ uint32_t OTG_GSL_WINDOW_Y; ++ uint32_t OTG_VUPDATE_KEEPOUT; ++ uint32_t OTG_DSC_START_POSITION; ++}; ++ ++#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ ++ SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ ++ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ ++ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ ++ SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ ++ SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, mask_sh),\ ++ SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ ++ SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ ++ SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ ++ SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ ++ SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ ++ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ ++ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ ++ SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ ++ SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ ++ SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ ++ SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ ++ SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ ++ SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ ++ SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ ++ SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ ++ SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ ++ SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ ++ SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ ++ SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ ++ SF(OTG0_OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, mask_sh),\ ++ SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ ++ SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ ++ SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ ++ SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ ++ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ ++ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ ++ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ ++ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ ++ SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ ++ SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ ++ SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ ++ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ ++ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ ++ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ ++ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ ++ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ ++ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ ++ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ ++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ ++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ ++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ ++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ ++ SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ ++ SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ ++ SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ ++ SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ ++ SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ ++ SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ ++ SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ ++ SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ ++ SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ ++ SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ ++ SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ ++ SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ ++ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ ++ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ ++ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ ++ SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ ++ SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ ++ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ ++ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ ++ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ ++ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ ++ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ ++ SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ ++ SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ ++ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ ++ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ ++ SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ ++ SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ ++ SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ ++ SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ ++ SF(OTG0_OTG_MASTER_UPDATE_MODE, MASTER_UPDATE_INTERLACED_MODE, mask_sh),\ ++ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ ++ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ ++ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ ++ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ ++ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ ++ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh) ++ ++ ++#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ ++ TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ ++ SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ ++ SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh) ++ ++#define TG_REG_FIELD_LIST(type) \ ++ type VSTARTUP_START;\ ++ type VUPDATE_OFFSET;\ ++ type VUPDATE_WIDTH;\ ++ type VREADY_OFFSET;\ ++ type OTG_BLANK_DATA_EN;\ ++ type OTG_BLANK_DE_MODE;\ ++ type OTG_CURRENT_BLANK_STATE;\ ++ type OTG_MASTER_UPDATE_LOCK;\ ++ type UPDATE_LOCK_STATUS;\ ++ type OTG_UPDATE_PENDING;\ ++ type OTG_MASTER_UPDATE_LOCK_SEL;\ ++ type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ ++ type OTG_H_TOTAL;\ ++ type OTG_H_BLANK_START;\ ++ type OTG_H_BLANK_END;\ ++ type OTG_H_SYNC_A_START;\ ++ type OTG_H_SYNC_A_END;\ ++ type OTG_H_SYNC_A_POL;\ ++ type OTG_H_TIMING_DIV_BY2;\ ++ type OTG_V_TOTAL;\ ++ type OTG_V_BLANK_START;\ ++ type OTG_V_BLANK_END;\ ++ type OTG_V_SYNC_A_START;\ ++ type OTG_V_SYNC_A_END;\ ++ type OTG_V_SYNC_A_POL;\ ++ type OTG_INTERLACE_ENABLE;\ ++ type OTG_MASTER_EN;\ ++ type OTG_START_POINT_CNTL;\ ++ type OTG_DISABLE_POINT_CNTL;\ ++ type OTG_FIELD_NUMBER_CNTL;\ ++ type OTG_STEREO_EN;\ ++ type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ ++ type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ ++ type OTG_STEREO_EYE_FLAG_POLARITY;\ ++ type OTG_STEREO_CURRENT_EYE;\ ++ type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ ++ type OTG_3D_STRUCTURE_EN;\ ++ type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ ++ type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ ++ type OTG_V_TOTAL_MAX;\ ++ type OTG_V_TOTAL_MIN;\ ++ type OTG_V_TOTAL_MIN_SEL;\ ++ type OTG_V_TOTAL_MAX_SEL;\ ++ type OTG_FORCE_LOCK_ON_EVENT;\ ++ type OTG_SET_V_TOTAL_MIN_MASK_EN;\ ++ type OTG_SET_V_TOTAL_MIN_MASK;\ ++ type OTG_FORCE_COUNT_NOW_CLEAR;\ ++ type OTG_FORCE_COUNT_NOW_MODE;\ ++ type OTG_FORCE_COUNT_NOW_OCCURRED;\ ++ type OTG_TRIGA_SOURCE_SELECT;\ ++ type OTG_TRIGA_SOURCE_PIPE_SELECT;\ ++ type OTG_TRIGA_RISING_EDGE_DETECT_CNTL;\ ++ type OTG_TRIGA_FALLING_EDGE_DETECT_CNTL;\ ++ type OTG_STATIC_SCREEN_EVENT_MASK;\ ++ type OTG_STATIC_SCREEN_FRAME_COUNT;\ ++ type OTG_FRAME_COUNT;\ ++ type OTG_V_BLANK;\ ++ type OTG_V_ACTIVE_DISP;\ ++ type OTG_HORZ_COUNT;\ ++ type OTG_VERT_COUNT;\ ++ type OTG_VERT_COUNT_NOM;\ ++ type OTG_BLACK_COLOR_B_CB;\ ++ type OTG_BLACK_COLOR_G_Y;\ ++ type OTG_BLACK_COLOR_R_CR;\ ++ type OTG_TEST_PATTERN_INC0;\ ++ type OTG_TEST_PATTERN_INC1;\ ++ type OTG_TEST_PATTERN_VRES;\ ++ type OTG_TEST_PATTERN_HRES;\ ++ type OTG_TEST_PATTERN_RAMP0_OFFSET;\ ++ type OTG_TEST_PATTERN_EN;\ ++ type OTG_TEST_PATTERN_MODE;\ ++ type OTG_TEST_PATTERN_DYNAMIC_RANGE;\ ++ type OTG_TEST_PATTERN_COLOR_FORMAT;\ ++ type OTG_TEST_PATTERN_MASK;\ ++ type OTG_TEST_PATTERN_DATA;\ ++ type OTG_BUSY;\ ++ type OTG_CLOCK_EN;\ ++ type OTG_CLOCK_ON;\ ++ type OTG_CLOCK_GATE_DIS;\ ++ type OTG_VERTICAL_INTERRUPT2_INT_ENABLE;\ ++ type OTG_VERTICAL_INTERRUPT2_LINE_START;\ ++ type OPTC_INPUT_CLK_EN;\ ++ type OPTC_INPUT_CLK_ON;\ ++ type OPTC_INPUT_CLK_GATE_DIS;\ ++ type OPTC_SRC_SEL;\ ++ type OPTC_SEG0_SRC_SEL;\ ++ type OPTC_UNDERFLOW_OCCURRED_STATUS;\ ++ type OPTC_UNDERFLOW_CLEAR;\ ++ type OPPBUF_ACTIVE_WIDTH;\ ++ type OPPBUF_3D_VACT_SPACE1_SIZE;\ ++ type VTG0_ENABLE;\ ++ type VTG0_FP2;\ ++ type VTG0_VCOUNT_INIT;\ ++ type OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED;\ ++ type OTG_FORCE_VSYNC_NEXT_LINE_CLEAR;\ ++ type OTG_AUTO_FORCE_VSYNC_MODE;\ ++ type MASTER_UPDATE_INTERLACED_MODE;\ ++ type OTG_GSL0_EN;\ ++ type OTG_GSL1_EN;\ ++ type OTG_GSL2_EN;\ ++ type OTG_GSL_MASTER_EN;\ ++ type OTG_GSL_FORCE_DELAY;\ ++ type OTG_GSL_CHECK_ALL_FIELDS;\ ++ type OTG_GSL_WINDOW_START_X;\ ++ type OTG_GSL_WINDOW_END_X;\ ++ type OTG_GSL_WINDOW_START_Y;\ ++ type OTG_GSL_WINDOW_END_Y;\ ++ type OTG_RANGE_TIMING_DBUF_UPDATE_MODE;\ ++ type OTG_GSL_MASTER_MODE;\ ++ type OTG_MASTER_UPDATE_LOCK_GSL_EN;\ ++ type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\ ++ type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET;\ ++ type OTG_DSC_START_POSITION_X;\ ++ type OTG_DSC_START_POSITION_LINE_NUM;\ ++ type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN; ++ ++ ++struct dcn_optc_shift { ++ TG_REG_FIELD_LIST(uint8_t) ++}; ++ ++struct dcn_optc_mask { ++ TG_REG_FIELD_LIST(uint32_t) ++}; ++ ++struct optc { ++ struct timing_generator base; ++ ++ const struct dcn_optc_registers *tg_regs; ++ const struct dcn_optc_shift *tg_shift; ++ const struct dcn_optc_mask *tg_mask; ++ ++ enum controller_id controller_id; ++ ++ uint32_t max_h_total; ++ uint32_t max_v_total; ++ ++ uint32_t min_h_blank; ++ ++ uint32_t min_h_sync_width; ++ uint32_t min_v_sync_width; ++ uint32_t min_v_blank; ++ uint32_t min_v_blank_interlace; ++}; ++ ++void dcn10_timing_generator_init(struct optc *optc); ++ ++struct dcn_otg_state { ++ uint32_t v_blank_start; ++ uint32_t v_blank_end; ++ uint32_t v_sync_a_pol; ++ uint32_t v_total; ++ uint32_t v_total_max; ++ uint32_t v_total_min; ++ uint32_t v_sync_a_start; ++ uint32_t v_sync_a_end; ++ uint32_t h_blank_start; ++ uint32_t h_blank_end; ++ uint32_t h_sync_a_start; ++ uint32_t h_sync_a_end; ++ uint32_t h_sync_a_pol; ++ uint32_t h_total; ++ uint32_t underflow_occurred_status; ++ uint32_t otg_enabled; ++}; ++ ++void optc1_read_otg_state(struct optc *optc1, ++ struct dcn_otg_state *s); ++ ++bool optc1_validate_timing( ++ struct timing_generator *optc, ++ const struct dc_crtc_timing *timing); ++ ++void optc1_program_timing( ++ struct timing_generator *optc, ++ const struct dc_crtc_timing *dc_crtc_timing, ++ bool use_vbios); ++ ++void optc1_program_global_sync( ++ struct timing_generator *optc); ++ ++bool optc1_disable_crtc(struct timing_generator *optc); ++ ++bool optc1_is_counter_moving(struct timing_generator *optc); ++ ++void optc1_get_position(struct timing_generator *optc, ++ struct crtc_position *position); ++ ++uint32_t optc1_get_vblank_counter(struct timing_generator *optc); ++ ++void optc1_get_crtc_scanoutpos( ++ struct timing_generator *optc, ++ uint32_t *v_blank_start, ++ uint32_t *v_blank_end, ++ uint32_t *h_position, ++ uint32_t *v_position); ++ ++void optc1_set_early_control( ++ struct timing_generator *optc, ++ uint32_t early_cntl); ++ ++void optc1_wait_for_state(struct timing_generator *optc, ++ enum crtc_state state); ++ ++void optc1_set_blank(struct timing_generator *optc, ++ bool enable_blanking); ++ ++bool optc1_is_blanked(struct timing_generator *optc); ++ ++void optc1_program_blank_color( ++ struct timing_generator *optc, ++ const struct tg_color *black_color); ++ ++bool optc1_did_triggered_reset_occur( ++ struct timing_generator *optc); ++ ++void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst); ++ ++void optc1_disable_reset_trigger(struct timing_generator *optc); ++ ++void optc1_lock(struct timing_generator *optc); ++ ++void optc1_unlock(struct timing_generator *optc); ++ ++void optc1_enable_optc_clock(struct timing_generator *optc, bool enable); ++ ++void optc1_set_drr( ++ struct timing_generator *optc, ++ const struct drr_params *params); ++ ++void optc1_set_static_screen_control( ++ struct timing_generator *optc, ++ uint32_t value); ++ ++void optc1_program_stereo(struct timing_generator *optc, ++ const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); ++ ++bool optc1_is_stereo_left_eye(struct timing_generator *optc); ++ ++#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +index 65ce96b..44825e2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +@@ -34,7 +34,7 @@ + #include "dcn10/dcn10_mpc.h" + #include "irq/dcn10/irq_service_dcn10.h" + #include "dcn10/dcn10_dpp.h" +-#include "dcn10/dcn10_timing_generator.h" ++#include "dcn10_optc.h" + #include "dcn10/dcn10_hw_sequencer.h" + #include "dce110/dce110_hw_sequencer.h" + #include "dcn10/dcn10_opp.h" +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +deleted file mode 100644 +index f73752c..0000000 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c ++++ /dev/null +@@ -1,1279 +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 "reg_helper.h" +-#include "dcn10_timing_generator.h" +-#include "dc.h" +- +-#define REG(reg)\ +- optc1->tg_regs->reg +- +-#define CTX \ +- optc1->base.ctx +- +-#undef FN +-#define FN(reg_name, field_name) \ +- optc1->tg_shift->field_name, optc1->tg_mask->field_name +- +-#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 +- +-/** +-* apply_front_porch_workaround TODO FPGA still need? +-* +-* This is a workaround for a bug that has existed since R5xx and has not been +-* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. +-*/ +-static void optc1_apply_front_porch_workaround( +- struct timing_generator *optc, +- struct dc_crtc_timing *timing) +-{ +- if (timing->flags.INTERLACE == 1) { +- if (timing->v_front_porch < 2) +- timing->v_front_porch = 2; +- } else { +- if (timing->v_front_porch < 1) +- timing->v_front_porch = 1; +- } +-} +- +-void optc1_program_global_sync( +- struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- if (optc->dlg_otg_param.vstartup_start == 0) { +- BREAK_TO_DEBUGGER(); +- return; +- } +- +- REG_SET(OTG_VSTARTUP_PARAM, 0, +- VSTARTUP_START, optc->dlg_otg_param.vstartup_start); +- +- REG_SET_2(OTG_VUPDATE_PARAM, 0, +- VUPDATE_OFFSET, optc->dlg_otg_param.vupdate_offset, +- VUPDATE_WIDTH, optc->dlg_otg_param.vupdate_width); +- +- REG_SET(OTG_VREADY_PARAM, 0, +- VREADY_OFFSET, optc->dlg_otg_param.vready_offset); +-} +- +-static void optc1_disable_stereo(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_SET(OTG_STEREO_CONTROL, 0, +- OTG_STEREO_EN, 0); +- +- REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0, +- OTG_3D_STRUCTURE_EN, 0, +- OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, +- OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); +- +- REG_UPDATE(OPPBUF_CONTROL, +- OPPBUF_ACTIVE_WIDTH, 0); +- REG_UPDATE(OPPBUF_3D_PARAMETERS_0, +- OPPBUF_3D_VACT_SPACE1_SIZE, 0); +-} +- +-/** +- * program_timing_generator used by mode timing set +- * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. +- * Including SYNC. Call BIOS command table to program Timings. +- */ +-void optc1_program_timing( +- struct timing_generator *optc, +- const struct dc_crtc_timing *dc_crtc_timing, +- bool use_vbios) +-{ +- struct dc_crtc_timing patched_crtc_timing; +- uint32_t vesa_sync_start; +- uint32_t asic_blank_end; +- uint32_t asic_blank_start; +- uint32_t v_total; +- uint32_t v_sync_end; +- uint32_t v_init, v_fp2; +- uint32_t h_sync_polarity, v_sync_polarity; +- uint32_t interlace_factor; +- uint32_t start_point = 0; +- uint32_t field_num = 0; +- uint32_t h_div_2; +- int32_t vertical_line_start; +- +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- patched_crtc_timing = *dc_crtc_timing; +- optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); +- +- /* Load horizontal timing */ +- +- /* CRTC_H_TOTAL = vesa.h_total - 1 */ +- REG_SET(OTG_H_TOTAL, 0, +- OTG_H_TOTAL, patched_crtc_timing.h_total - 1); +- +- /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */ +- REG_UPDATE_2(OTG_H_SYNC_A, +- OTG_H_SYNC_A_START, 0, +- OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width); +- +- /* asic_h_blank_end = HsyncWidth + HbackPorch = +- * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart - +- * vesa.h_left_border +- */ +- vesa_sync_start = patched_crtc_timing.h_addressable + +- patched_crtc_timing.h_border_right + +- patched_crtc_timing.h_front_porch; +- +- asic_blank_end = patched_crtc_timing.h_total - +- vesa_sync_start - +- patched_crtc_timing.h_border_left; +- +- /* h_blank_start = v_blank_end + v_active */ +- asic_blank_start = asic_blank_end + +- patched_crtc_timing.h_border_left + +- patched_crtc_timing.h_addressable + +- patched_crtc_timing.h_border_right; +- +- REG_UPDATE_2(OTG_H_BLANK_START_END, +- OTG_H_BLANK_START, asic_blank_start, +- OTG_H_BLANK_END, asic_blank_end); +- +- /* h_sync polarity */ +- h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? +- 0 : 1; +- +- REG_UPDATE(OTG_H_SYNC_A_CNTL, +- OTG_H_SYNC_A_POL, h_sync_polarity); +- +- /* Load vertical timing */ +- +- /* CRTC_V_TOTAL = v_total - 1 */ +- if (patched_crtc_timing.flags.INTERLACE) { +- interlace_factor = 2; +- v_total = 2 * patched_crtc_timing.v_total; +- } else { +- interlace_factor = 1; +- v_total = patched_crtc_timing.v_total - 1; +- } +- REG_SET(OTG_V_TOTAL, 0, +- OTG_V_TOTAL, v_total); +- +- /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and +- * OTG_V_TOTAL_MIN are equal to V_TOTAL. +- */ +- REG_SET(OTG_V_TOTAL_MAX, 0, +- OTG_V_TOTAL_MAX, v_total); +- REG_SET(OTG_V_TOTAL_MIN, 0, +- OTG_V_TOTAL_MIN, v_total); +- +- /* v_sync_start = 0, v_sync_end = v_sync_width */ +- v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor; +- +- REG_UPDATE_2(OTG_V_SYNC_A, +- OTG_V_SYNC_A_START, 0, +- OTG_V_SYNC_A_END, v_sync_end); +- +- vesa_sync_start = patched_crtc_timing.v_addressable + +- patched_crtc_timing.v_border_bottom + +- patched_crtc_timing.v_front_porch; +- +- asic_blank_end = (patched_crtc_timing.v_total - +- vesa_sync_start - +- patched_crtc_timing.v_border_top) +- * interlace_factor; +- +- /* v_blank_start = v_blank_end + v_active */ +- asic_blank_start = asic_blank_end + +- (patched_crtc_timing.v_border_top + +- patched_crtc_timing.v_addressable + +- patched_crtc_timing.v_border_bottom) +- * interlace_factor; +- +- REG_UPDATE_2(OTG_V_BLANK_START_END, +- OTG_V_BLANK_START, asic_blank_start, +- OTG_V_BLANK_END, asic_blank_end); +- +- /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, +- * program the reg for interrupt postition. +- */ +- vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; +- if (vertical_line_start < 0) { +- ASSERT(0); +- vertical_line_start = 0; +- } +- REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, +- OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start); +- +- /* v_sync polarity */ +- v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? +- 0 : 1; +- +- REG_UPDATE(OTG_V_SYNC_A_CNTL, +- OTG_V_SYNC_A_POL, v_sync_polarity); +- +- v_init = asic_blank_start; +- if (optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || +- optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || +- optc->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { +- start_point = 1; +- if (patched_crtc_timing.flags.INTERLACE == 1) +- field_num = 1; +- } +- v_fp2 = 0; +- if (optc->dlg_otg_param.vstartup_start > asic_blank_end) +- v_fp2 = optc->dlg_otg_param.vstartup_start > asic_blank_end; +- +- /* Interlace */ +- if (patched_crtc_timing.flags.INTERLACE == 1) { +- REG_UPDATE(OTG_INTERLACE_CONTROL, +- OTG_INTERLACE_ENABLE, 1); +- v_init = v_init / 2; +- if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) +- v_fp2 = v_fp2 / 2; +- } +- else +- REG_UPDATE(OTG_INTERLACE_CONTROL, +- OTG_INTERLACE_ENABLE, 0); +- +- +- /* VTG enable set to 0 first VInit */ +- REG_UPDATE(CONTROL, +- VTG0_ENABLE, 0); +- +- REG_UPDATE_2(CONTROL, +- VTG0_FP2, v_fp2, +- VTG0_VCOUNT_INIT, v_init); +- +- /* original code is using VTG offset to address OTG reg, seems wrong */ +- REG_UPDATE_2(OTG_CONTROL, +- OTG_START_POINT_CNTL, start_point, +- OTG_FIELD_NUMBER_CNTL, field_num); +- +- optc1_program_global_sync(optc); +- +- /* TODO +- * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 +- * program_horz_count_by_2 +- * for DVI 30bpp mode, 0 otherwise +- * program_horz_count_by_2(optc, &patched_crtc_timing); +- */ +- +- /* Enable stereo - only when we need to pack 3D frame. Other types +- * of stereo handled in explicit call +- */ +- h_div_2 = (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ? +- 1 : 0; +- +- REG_UPDATE(OTG_H_TIMING_CNTL, +- OTG_H_TIMING_DIV_BY2, h_div_2); +- +-} +- +-static void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- uint32_t blank_data_double_buffer_enable = enable ? 1 : 0; +- +- REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, +- OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable); +-} +- +-/** +- * unblank_crtc +- * Call ASIC Control Object to UnBlank CRTC. +- */ +-static void optc1_unblank_crtc(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t vertical_interrupt_enable = 0; +- +- REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, +- OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable); +- +- /* temporary work around for vertical interrupt, once vertical interrupt enabled, +- * this check will be removed. +- */ +- if (vertical_interrupt_enable) +- optc1_set_blank_data_double_buffer(optc, true); +- +- REG_UPDATE_2(OTG_BLANK_CONTROL, +- OTG_BLANK_DATA_EN, 0, +- OTG_BLANK_DE_MODE, 0); +-} +- +-/** +- * blank_crtc +- * Call ASIC Control Object to Blank CRTC. +- */ +- +-static void optc1_blank_crtc(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_UPDATE_2(OTG_BLANK_CONTROL, +- OTG_BLANK_DATA_EN, 1, +- OTG_BLANK_DE_MODE, 0); +- +- optc1_set_blank_data_double_buffer(optc, false); +-} +- +-void optc1_set_blank(struct timing_generator *optc, +- bool enable_blanking) +-{ +- if (enable_blanking) +- optc1_blank_crtc(optc); +- else +- optc1_unblank_crtc(optc); +-} +- +-bool optc1_is_blanked(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t blank_en; +- uint32_t blank_state; +- +- REG_GET_2(OTG_BLANK_CONTROL, +- OTG_BLANK_DATA_EN, &blank_en, +- OTG_CURRENT_BLANK_STATE, &blank_state); +- +- return blank_en && blank_state; +-} +- +-void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- if (enable) { +- REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, +- OPTC_INPUT_CLK_EN, 1, +- OPTC_INPUT_CLK_GATE_DIS, 1); +- +- REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, +- OPTC_INPUT_CLK_ON, 1, +- 1, 1000); +- +- /* Enable clock */ +- REG_UPDATE_2(OTG_CLOCK_CONTROL, +- OTG_CLOCK_EN, 1, +- OTG_CLOCK_GATE_DIS, 1); +- REG_WAIT(OTG_CLOCK_CONTROL, +- OTG_CLOCK_ON, 1, +- 1, 1000); +- } else { +- REG_UPDATE_2(OTG_CLOCK_CONTROL, +- OTG_CLOCK_GATE_DIS, 0, +- OTG_CLOCK_EN, 0); +- +- REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, +- OPTC_INPUT_CLK_GATE_DIS, 0, +- OPTC_INPUT_CLK_EN, 0); +- } +-} +- +-/** +- * Enable CRTC +- * Enable CRTC - call ASIC Control Object to enable Timing generator. +- */ +-static bool optc1_enable_crtc(struct timing_generator *optc) +-{ +- /* TODO FPGA wait for answer +- * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE +- * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK +- */ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- /* opp instance for OTG. For DCN1.0, ODM is remoed. +- * OPP and OPTC should 1:1 mapping +- */ +- REG_UPDATE(OPTC_DATA_SOURCE_SELECT, +- OPTC_SRC_SEL, optc->inst); +- +- /* VTG enable first is for HW workaround */ +- REG_UPDATE(CONTROL, +- VTG0_ENABLE, 1); +- +- /* Enable CRTC */ +- REG_UPDATE_2(OTG_CONTROL, +- OTG_DISABLE_POINT_CNTL, 3, +- OTG_MASTER_EN, 1); +- +- return true; +-} +- +-/* disable_crtc - call ASIC Control Object to disable Timing generator. */ +-bool optc1_disable_crtc(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- /* disable otg request until end of the first line +- * in the vertical blank region +- */ +- REG_UPDATE_2(OTG_CONTROL, +- OTG_DISABLE_POINT_CNTL, 3, +- OTG_MASTER_EN, 0); +- +- REG_UPDATE(CONTROL, +- VTG0_ENABLE, 0); +- +- /* CRTC disabled, so disable clock. */ +- REG_WAIT(OTG_CLOCK_CONTROL, +- OTG_BUSY, 0, +- 1, 100000); +- +- return true; +-} +- +- +-void optc1_program_blank_color( +- struct timing_generator *optc, +- const struct tg_color *black_color) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_SET_3(OTG_BLACK_COLOR, 0, +- OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, +- OTG_BLACK_COLOR_G_Y, black_color->color_g_y, +- OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); +-} +- +-bool optc1_validate_timing( +- struct timing_generator *optc, +- const struct dc_crtc_timing *timing) +-{ +- uint32_t interlace_factor; +- uint32_t v_blank; +- uint32_t h_blank; +- uint32_t min_v_blank; +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- ASSERT(timing != NULL); +- +- interlace_factor = timing->flags.INTERLACE ? 2 : 1; +- v_blank = (timing->v_total - timing->v_addressable - +- timing->v_border_top - timing->v_border_bottom) * +- interlace_factor; +- +- h_blank = (timing->h_total - timing->h_addressable - +- timing->h_border_right - +- timing->h_border_left); +- +- if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && +- timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && +- timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && +- timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && +- timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && +- timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) +- return false; +- +- /* Temporarily blocking interlacing mode until it's supported */ +- if (timing->flags.INTERLACE == 1) +- return false; +- +- /* Check maximum number of pixels supported by Timing Generator +- * (Currently will never fail, in order to fail needs display which +- * needs more than 8192 horizontal and +- * more than 8192 vertical total pixels) +- */ +- if (timing->h_total > optc1->max_h_total || +- timing->v_total > optc1->max_v_total) +- return false; +- +- +- if (h_blank < optc1->min_h_blank) +- return false; +- +- if (timing->h_sync_width < optc1->min_h_sync_width || +- timing->v_sync_width < optc1->min_v_sync_width) +- return false; +- +- min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; +- +- if (v_blank < min_v_blank) +- return false; +- +- return true; +- +-} +- +-/* +- * get_vblank_counter +- * +- * @brief +- * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which +- * holds the counter of frames. +- * +- * @param +- * struct timing_generator *optc - [in] timing generator which controls the +- * desired CRTC +- * +- * @return +- * Counter of frames, which should equal to number of vblanks. +- */ +-uint32_t optc1_get_vblank_counter(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t frame_count; +- +- REG_GET(OTG_STATUS_FRAME_COUNT, +- OTG_FRAME_COUNT, &frame_count); +- +- return frame_count; +-} +- +-void optc1_lock(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_SET(OTG_GLOBAL_CONTROL0, 0, +- OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); +- REG_SET(OTG_MASTER_UPDATE_LOCK, 0, +- OTG_MASTER_UPDATE_LOCK, 1); +- +- /* Should be fast, status does not update on maximus */ +- if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) +- REG_WAIT(OTG_MASTER_UPDATE_LOCK, +- UPDATE_LOCK_STATUS, 1, +- 1, 10); +-} +- +-void optc1_unlock(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_SET(OTG_MASTER_UPDATE_LOCK, 0, +- OTG_MASTER_UPDATE_LOCK, 0); +-} +- +-void optc1_get_position(struct timing_generator *optc, +- struct crtc_position *position) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_GET_2(OTG_STATUS_POSITION, +- OTG_HORZ_COUNT, &position->horizontal_count, +- OTG_VERT_COUNT, &position->vertical_count); +- +- REG_GET(OTG_NOM_VERT_POSITION, +- OTG_VERT_COUNT_NOM, &position->nominal_vcount); +-} +- +-bool optc1_is_counter_moving(struct timing_generator *optc) +-{ +- struct crtc_position position1, position2; +- +- optc->funcs->get_position(optc, &position1); +- optc->funcs->get_position(optc, &position2); +- +- if (position1.horizontal_count == position2.horizontal_count && +- position1.vertical_count == position2.vertical_count) +- return false; +- else +- return true; +-} +- +-bool optc1_did_triggered_reset_occur( +- struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t occurred_force, occurred_vsync; +- +- REG_GET(OTG_FORCE_COUNT_NOW_CNTL, +- OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force); +- +- REG_GET(OTG_VERT_SYNC_CONTROL, +- OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync); +- +- return occurred_vsync != 0 || occurred_force != 0; +-} +- +-void optc1_disable_reset_trigger(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_WRITE(OTG_TRIGA_CNTL, 0); +- +- REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, +- OTG_FORCE_COUNT_NOW_CLEAR, 1); +- +- REG_SET(OTG_VERT_SYNC_CONTROL, 0, +- OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1); +-} +- +-void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t falling_edge; +- +- REG_GET(OTG_V_SYNC_A_CNTL, +- OTG_V_SYNC_A_POL, &falling_edge); +- +- if (falling_edge) +- REG_SET_3(OTG_TRIGA_CNTL, 0, +- /* vsync signal from selected OTG pipe based +- * on OTG_TRIG_SOURCE_PIPE_SELECT setting +- */ +- OTG_TRIGA_SOURCE_SELECT, 20, +- OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, +- /* always detect falling edge */ +- OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1); +- else +- REG_SET_3(OTG_TRIGA_CNTL, 0, +- /* vsync signal from selected OTG pipe based +- * on OTG_TRIG_SOURCE_PIPE_SELECT setting +- */ +- OTG_TRIGA_SOURCE_SELECT, 20, +- OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, +- /* always detect rising edge */ +- OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1); +- +- REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, +- /* force H count to H_TOTAL and V count to V_TOTAL in +- * progressive mode and V_TOTAL-1 in interlaced mode +- */ +- OTG_FORCE_COUNT_NOW_MODE, 2); +-} +- +-void optc1_enable_crtc_reset( +- struct timing_generator *optc, +- int source_tg_inst, +- struct crtc_trigger_info *crtc_tp) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t falling_edge = 0; +- uint32_t rising_edge = 0; +- +- switch (crtc_tp->event) { +- +- case CRTC_EVENT_VSYNC_RISING: +- rising_edge = 1; +- break; +- +- case CRTC_EVENT_VSYNC_FALLING: +- falling_edge = 1; +- break; +- } +- +- REG_SET_4(OTG_TRIGA_CNTL, 0, +- /* vsync signal from selected OTG pipe based +- * on OTG_TRIG_SOURCE_PIPE_SELECT setting +- */ +- OTG_TRIGA_SOURCE_SELECT, 20, +- OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, +- /* always detect falling edge */ +- OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge, +- OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge); +- +- switch (crtc_tp->delay) { +- case TRIGGER_DELAY_NEXT_LINE: +- REG_SET(OTG_VERT_SYNC_CONTROL, 0, +- OTG_AUTO_FORCE_VSYNC_MODE, 1); +- break; +- case TRIGGER_DELAY_NEXT_PIXEL: +- REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, +- /* force H count to H_TOTAL and V count to V_TOTAL in +- * progressive mode and V_TOTAL-1 in interlaced mode +- */ +- OTG_FORCE_COUNT_NOW_MODE, 2); +- break; +- } +-} +- +-void optc1_wait_for_state(struct timing_generator *optc, +- enum crtc_state state) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- switch (state) { +- case CRTC_STATE_VBLANK: +- REG_WAIT(OTG_STATUS, +- OTG_V_BLANK, 1, +- 1, 100000); /* 1 vupdate at 10hz */ +- break; +- +- case CRTC_STATE_VACTIVE: +- REG_WAIT(OTG_STATUS, +- OTG_V_ACTIVE_DISP, 1, +- 1, 100000); /* 1 vupdate at 10hz */ +- break; +- +- default: +- break; +- } +-} +- +-void optc1_set_early_control( +- struct timing_generator *optc, +- uint32_t early_cntl) +-{ +- /* asic design change, do not need this control +- * empty for share caller logic +- */ +-} +- +- +-void optc1_set_static_screen_control( +- struct timing_generator *optc, +- uint32_t value) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- /* Bit 8 is no longer applicable in RV for PSR case, +- * set bit 8 to 0 if given +- */ +- if ((value & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN) +- != 0) +- value = value & +- ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN; +- +- REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0, +- OTG_STATIC_SCREEN_EVENT_MASK, value, +- OTG_STATIC_SCREEN_FRAME_COUNT, 2); +-} +- +- +-/** +- ***************************************************************************** +- * Function: set_drr +- * +- * @brief +- * Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. +- * +- ***************************************************************************** +- */ +-void optc1_set_drr( +- struct timing_generator *optc, +- const struct drr_params *params) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- if (params != NULL && +- params->vertical_total_max > 0 && +- params->vertical_total_min > 0) { +- +- REG_SET(OTG_V_TOTAL_MAX, 0, +- OTG_V_TOTAL_MAX, params->vertical_total_max - 1); +- +- REG_SET(OTG_V_TOTAL_MIN, 0, +- OTG_V_TOTAL_MIN, params->vertical_total_min - 1); +- +- REG_UPDATE_5(OTG_V_TOTAL_CONTROL, +- OTG_V_TOTAL_MIN_SEL, 1, +- OTG_V_TOTAL_MAX_SEL, 1, +- OTG_FORCE_LOCK_ON_EVENT, 0, +- OTG_SET_V_TOTAL_MIN_MASK_EN, 0, +- OTG_SET_V_TOTAL_MIN_MASK, 0); +- } else { +- REG_SET(OTG_V_TOTAL_MIN, 0, +- OTG_V_TOTAL_MIN, 0); +- +- REG_SET(OTG_V_TOTAL_MAX, 0, +- OTG_V_TOTAL_MAX, 0); +- +- REG_UPDATE_4(OTG_V_TOTAL_CONTROL, +- OTG_SET_V_TOTAL_MIN_MASK, 0, +- OTG_V_TOTAL_MIN_SEL, 0, +- OTG_V_TOTAL_MAX_SEL, 0, +- OTG_FORCE_LOCK_ON_EVENT, 0); +- } +-} +- +-static void optc1_set_test_pattern( +- struct timing_generator *optc, +- /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' +- * because this is not DP-specific (which is probably somewhere in DP +- * encoder) */ +- enum controller_dp_test_pattern test_pattern, +- enum dc_color_depth color_depth) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- enum test_pattern_color_format bit_depth; +- enum test_pattern_dyn_range dyn_range; +- enum test_pattern_mode mode; +- uint32_t pattern_mask; +- uint32_t pattern_data; +- /* color ramp generator mixes 16-bits color */ +- uint32_t src_bpc = 16; +- /* requested bpc */ +- uint32_t dst_bpc; +- uint32_t index; +- /* RGB values of the color bars. +- * Produce two RGB colors: RGB0 - white (all Fs) +- * and RGB1 - black (all 0s) +- * (three RGB components for two colors) +- */ +- uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, +- 0x0000, 0x0000}; +- /* dest color (converted to the specified color format) */ +- uint16_t dst_color[6]; +- uint32_t inc_base; +- +- /* translate to bit depth */ +- switch (color_depth) { +- case COLOR_DEPTH_666: +- bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; +- break; +- case COLOR_DEPTH_888: +- bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; +- break; +- case COLOR_DEPTH_101010: +- bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; +- break; +- case COLOR_DEPTH_121212: +- bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; +- break; +- default: +- bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; +- break; +- } +- +- switch (test_pattern) { +- case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: +- case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: +- { +- dyn_range = (test_pattern == +- CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? +- TEST_PATTERN_DYN_RANGE_CEA : +- TEST_PATTERN_DYN_RANGE_VESA); +- mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; +- +- REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS, +- OTG_TEST_PATTERN_VRES, 6, +- OTG_TEST_PATTERN_HRES, 6); +- +- REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, +- OTG_TEST_PATTERN_EN, 1, +- OTG_TEST_PATTERN_MODE, mode, +- OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, +- OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); +- } +- break; +- +- case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: +- case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: +- { +- mode = (test_pattern == +- CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? +- TEST_PATTERN_MODE_VERTICALBARS : +- TEST_PATTERN_MODE_HORIZONTALBARS); +- +- switch (bit_depth) { +- case TEST_PATTERN_COLOR_FORMAT_BPC_6: +- dst_bpc = 6; +- break; +- case TEST_PATTERN_COLOR_FORMAT_BPC_8: +- dst_bpc = 8; +- break; +- case TEST_PATTERN_COLOR_FORMAT_BPC_10: +- dst_bpc = 10; +- break; +- default: +- dst_bpc = 8; +- break; +- } +- +- /* adjust color to the required colorFormat */ +- for (index = 0; index < 6; index++) { +- /* dst = 2^dstBpc * src / 2^srcBpc = src >> +- * (srcBpc - dstBpc); +- */ +- dst_color[index] = +- src_color[index] >> (src_bpc - dst_bpc); +- /* CRTC_TEST_PATTERN_DATA has 16 bits, +- * lowest 6 are hardwired to ZERO +- * color bits should be left aligned aligned to MSB +- * XXXXXXXXXX000000 for 10 bit, +- * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 +- */ +- dst_color[index] <<= (16 - dst_bpc); +- } +- +- REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); +- +- /* We have to write the mask before data, similar to pipeline. +- * For example, for 8 bpc, if we want RGB0 to be magenta, +- * and RGB1 to be cyan, +- * we need to make 7 writes: +- * MASK DATA +- * 000001 00000000 00000000 set mask to R0 +- * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 +- * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 +- * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 +- * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 +- * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 +- * 100000 11111111 00000000 B1 255, 0xFF00 +- * +- * we will make a loop of 6 in which we prepare the mask, +- * then write, then prepare the color for next write. +- * first iteration will write mask only, +- * but each next iteration color prepared in +- * previous iteration will be written within new mask, +- * the last component will written separately, +- * mask is not changing between 6th and 7th write +- * and color will be prepared by last iteration +- */ +- +- /* write color, color values mask in CRTC_TEST_PATTERN_MASK +- * is B1, G1, R1, B0, G0, R0 +- */ +- pattern_data = 0; +- for (index = 0; index < 6; index++) { +- /* prepare color mask, first write PATTERN_DATA +- * will have all zeros +- */ +- pattern_mask = (1 << index); +- +- /* write color component */ +- REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, +- OTG_TEST_PATTERN_MASK, pattern_mask, +- OTG_TEST_PATTERN_DATA, pattern_data); +- +- /* prepare next color component, +- * will be written in the next iteration +- */ +- pattern_data = dst_color[index]; +- } +- /* write last color component, +- * it's been already prepared in the loop +- */ +- REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, +- OTG_TEST_PATTERN_MASK, pattern_mask, +- OTG_TEST_PATTERN_DATA, pattern_data); +- +- /* enable test pattern */ +- REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, +- OTG_TEST_PATTERN_EN, 1, +- OTG_TEST_PATTERN_MODE, mode, +- OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, +- OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); +- } +- break; +- +- case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: +- { +- mode = (bit_depth == +- TEST_PATTERN_COLOR_FORMAT_BPC_10 ? +- TEST_PATTERN_MODE_DUALRAMP_RGB : +- TEST_PATTERN_MODE_SINGLERAMP_RGB); +- +- switch (bit_depth) { +- case TEST_PATTERN_COLOR_FORMAT_BPC_6: +- dst_bpc = 6; +- break; +- case TEST_PATTERN_COLOR_FORMAT_BPC_8: +- dst_bpc = 8; +- break; +- case TEST_PATTERN_COLOR_FORMAT_BPC_10: +- dst_bpc = 10; +- break; +- default: +- dst_bpc = 8; +- break; +- } +- +- /* increment for the first ramp for one color gradation +- * 1 gradation for 6-bit color is 2^10 +- * gradations in 16-bit color +- */ +- inc_base = (src_bpc - dst_bpc); +- +- switch (bit_depth) { +- case TEST_PATTERN_COLOR_FORMAT_BPC_6: +- { +- REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, +- OTG_TEST_PATTERN_INC0, inc_base, +- OTG_TEST_PATTERN_INC1, 0, +- OTG_TEST_PATTERN_HRES, 6, +- OTG_TEST_PATTERN_VRES, 6, +- OTG_TEST_PATTERN_RAMP0_OFFSET, 0); +- } +- break; +- case TEST_PATTERN_COLOR_FORMAT_BPC_8: +- { +- REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, +- OTG_TEST_PATTERN_INC0, inc_base, +- OTG_TEST_PATTERN_INC1, 0, +- OTG_TEST_PATTERN_HRES, 8, +- OTG_TEST_PATTERN_VRES, 6, +- OTG_TEST_PATTERN_RAMP0_OFFSET, 0); +- } +- break; +- case TEST_PATTERN_COLOR_FORMAT_BPC_10: +- { +- REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, +- OTG_TEST_PATTERN_INC0, inc_base, +- OTG_TEST_PATTERN_INC1, inc_base + 2, +- OTG_TEST_PATTERN_HRES, 8, +- OTG_TEST_PATTERN_VRES, 5, +- OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); +- } +- break; +- default: +- break; +- } +- +- REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); +- +- /* enable test pattern */ +- REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); +- +- REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0, +- OTG_TEST_PATTERN_EN, 1, +- OTG_TEST_PATTERN_MODE, mode, +- OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, +- OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); +- } +- break; +- case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: +- { +- REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); +- REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); +- REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); +- } +- break; +- default: +- break; +- +- } +-} +- +-void optc1_get_crtc_scanoutpos( +- struct timing_generator *optc, +- uint32_t *v_blank_start, +- uint32_t *v_blank_end, +- uint32_t *h_position, +- uint32_t *v_position) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- struct crtc_position position; +- +- REG_GET_2(OTG_V_BLANK_START_END, +- OTG_V_BLANK_START, v_blank_start, +- OTG_V_BLANK_END, v_blank_end); +- +- optc1_get_position(optc, &position); +- +- *h_position = position.horizontal_count; +- *v_position = position.vertical_count; +-} +- +- +- +-static void optc1_enable_stereo(struct timing_generator *optc, +- const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- uint32_t active_width = timing->h_addressable; +- uint32_t space1_size = timing->v_total - timing->v_addressable; +- +- if (flags) { +- uint32_t stereo_en; +- stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; +- +- if (flags->PROGRAM_STEREO) +- REG_UPDATE_3(OTG_STEREO_CONTROL, +- OTG_STEREO_EN, stereo_en, +- OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, +- OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); +- +- if (flags->PROGRAM_POLARITY) +- REG_UPDATE(OTG_STEREO_CONTROL, +- OTG_STEREO_EYE_FLAG_POLARITY, +- flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); +- +- if (flags->DISABLE_STEREO_DP_SYNC) +- REG_UPDATE(OTG_STEREO_CONTROL, +- OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); +- +- if (flags->PROGRAM_STEREO) +- REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, +- OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED, +- OTG_3D_STRUCTURE_V_UPDATE_MODE, flags->FRAME_PACKED, +- OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); +- +- } +- +- REG_UPDATE(OPPBUF_CONTROL, +- OPPBUF_ACTIVE_WIDTH, active_width); +- +- REG_UPDATE(OPPBUF_3D_PARAMETERS_0, +- OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); +-} +- +-void optc1_program_stereo(struct timing_generator *optc, +- const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +-{ +- if (flags->PROGRAM_STEREO) +- optc1_enable_stereo(optc, timing, flags); +- else +- optc1_disable_stereo(optc); +-} +- +- +-bool optc1_is_stereo_left_eye(struct timing_generator *optc) +-{ +- bool ret = false; +- uint32_t left_eye = 0; +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_GET(OTG_STEREO_STATUS, +- OTG_STEREO_CURRENT_EYE, &left_eye); +- if (left_eye == 1) +- ret = true; +- else +- ret = false; +- +- return ret; +-} +- +-void optc1_read_otg_state(struct optc *optc1, +- struct dcn_otg_state *s) +-{ +- REG_GET(OTG_CONTROL, +- OTG_MASTER_EN, &s->otg_enabled); +- +- REG_GET_2(OTG_V_BLANK_START_END, +- OTG_V_BLANK_START, &s->v_blank_start, +- OTG_V_BLANK_END, &s->v_blank_end); +- +- REG_GET(OTG_V_SYNC_A_CNTL, +- OTG_V_SYNC_A_POL, &s->v_sync_a_pol); +- +- REG_GET(OTG_V_TOTAL, +- OTG_V_TOTAL, &s->v_total); +- +- REG_GET(OTG_V_TOTAL_MAX, +- OTG_V_TOTAL_MAX, &s->v_total_max); +- +- REG_GET(OTG_V_TOTAL_MIN, +- OTG_V_TOTAL_MIN, &s->v_total_min); +- +- REG_GET_2(OTG_V_SYNC_A, +- OTG_V_SYNC_A_START, &s->v_sync_a_start, +- OTG_V_SYNC_A_END, &s->v_sync_a_end); +- +- REG_GET_2(OTG_H_BLANK_START_END, +- OTG_H_BLANK_START, &s->h_blank_start, +- OTG_H_BLANK_END, &s->h_blank_end); +- +- REG_GET_2(OTG_H_SYNC_A, +- OTG_H_SYNC_A_START, &s->h_sync_a_start, +- OTG_H_SYNC_A_END, &s->h_sync_a_end); +- +- REG_GET(OTG_H_SYNC_A_CNTL, +- OTG_H_SYNC_A_POL, &s->h_sync_a_pol); +- +- REG_GET(OTG_H_TOTAL, +- OTG_H_TOTAL, &s->h_total); +- +- REG_GET(OPTC_INPUT_GLOBAL_CONTROL, +- OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); +-} +- +-static void optc1_clear_optc_underflow(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- +- REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); +-} +- +-static void optc1_tg_init(struct timing_generator *optc) +-{ +- optc1_set_blank_data_double_buffer(optc, true); +- optc1_clear_optc_underflow(optc); +-} +- +-static bool optc1_is_tg_enabled(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t otg_enabled = 0; +- +- REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled); +- +- return (otg_enabled != 0); +- +-} +- +-static bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) +-{ +- struct optc *optc1 = DCN10TG_FROM_TG(optc); +- uint32_t underflow_occurred = 0; +- +- REG_GET(OPTC_INPUT_GLOBAL_CONTROL, +- OPTC_UNDERFLOW_OCCURRED_STATUS, +- &underflow_occurred); +- +- return (underflow_occurred == 1); +-} +- +-static const struct timing_generator_funcs dcn10_tg_funcs = { +- .validate_timing = optc1_validate_timing, +- .program_timing = optc1_program_timing, +- .program_global_sync = optc1_program_global_sync, +- .enable_crtc = optc1_enable_crtc, +- .disable_crtc = optc1_disable_crtc, +- /* used by enable_timing_synchronization. Not need for FPGA */ +- .is_counter_moving = optc1_is_counter_moving, +- .get_position = optc1_get_position, +- .get_frame_count = optc1_get_vblank_counter, +- .get_scanoutpos = optc1_get_crtc_scanoutpos, +- .set_early_control = optc1_set_early_control, +- /* used by enable_timing_synchronization. Not need for FPGA */ +- .wait_for_state = optc1_wait_for_state, +- .set_blank = optc1_set_blank, +- .is_blanked = optc1_is_blanked, +- .set_blank_color = optc1_program_blank_color, +- .did_triggered_reset_occur = optc1_did_triggered_reset_occur, +- .enable_reset_trigger = optc1_enable_reset_trigger, +- .enable_crtc_reset = optc1_enable_crtc_reset, +- .disable_reset_trigger = optc1_disable_reset_trigger, +- .lock = optc1_lock, +- .unlock = optc1_unlock, +- .enable_optc_clock = optc1_enable_optc_clock, +- .set_drr = optc1_set_drr, +- .set_static_screen_control = optc1_set_static_screen_control, +- .set_test_pattern = optc1_set_test_pattern, +- .program_stereo = optc1_program_stereo, +- .is_stereo_left_eye = optc1_is_stereo_left_eye, +- .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, +- .tg_init = optc1_tg_init, +- .is_tg_enabled = optc1_is_tg_enabled, +- .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, +- .clear_optc_underflow = optc1_clear_optc_underflow, +-}; +- +-void dcn10_timing_generator_init(struct optc *optc1) +-{ +- optc1->base.funcs = &dcn10_tg_funcs; +- +- optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; +- optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; +- +- optc1->min_h_blank = 32; +- optc1->min_v_blank = 3; +- optc1->min_v_blank_interlace = 5; +- optc1->min_h_sync_width = 8; +- optc1->min_v_sync_width = 1; +-} +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +deleted file mode 100644 +index eec860fa..0000000 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h ++++ /dev/null +@@ -1,490 +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 +- * +- */ +- +-#ifndef __DC_TIMING_GENERATOR_DCN10_H__ +-#define __DC_TIMING_GENERATOR_DCN10_H__ +- +-#include "timing_generator.h" +- +-#define DCN10TG_FROM_TG(tg)\ +- container_of(tg, struct optc, base) +- +-#define TG_COMMON_REG_LIST_DCN(inst) \ +- SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ +- SRI(OTG_VUPDATE_PARAM, OTG, inst),\ +- SRI(OTG_VREADY_PARAM, OTG, inst),\ +- SRI(OTG_BLANK_CONTROL, OTG, inst),\ +- SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ +- SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ +- SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ +- SRI(OTG_H_TOTAL, OTG, inst),\ +- SRI(OTG_H_BLANK_START_END, OTG, inst),\ +- SRI(OTG_H_SYNC_A, OTG, inst),\ +- SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ +- SRI(OTG_H_TIMING_CNTL, OTG, inst),\ +- SRI(OTG_V_TOTAL, OTG, inst),\ +- SRI(OTG_V_BLANK_START_END, OTG, inst),\ +- SRI(OTG_V_SYNC_A, OTG, inst),\ +- SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ +- SRI(OTG_INTERLACE_CONTROL, OTG, inst),\ +- SRI(OTG_CONTROL, OTG, inst),\ +- SRI(OTG_STEREO_CONTROL, OTG, inst),\ +- SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ +- SRI(OTG_STEREO_STATUS, OTG, inst),\ +- SRI(OTG_V_TOTAL_MAX, OTG, inst),\ +- SRI(OTG_V_TOTAL_MIN, OTG, inst),\ +- SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ +- SRI(OTG_TRIGA_CNTL, OTG, inst),\ +- SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ +- SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ +- SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ +- SRI(OTG_STATUS, OTG, inst),\ +- SRI(OTG_STATUS_POSITION, OTG, inst),\ +- SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ +- SRI(OTG_BLACK_COLOR, OTG, inst),\ +- SRI(OTG_CLOCK_CONTROL, OTG, inst),\ +- SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ +- SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ +- SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ +- SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ +- SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ +- SRI(OPPBUF_CONTROL, OPPBUF, inst),\ +- SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ +- SRI(CONTROL, VTG, inst),\ +- SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ +- SRI(OTG_MASTER_UPDATE_MODE, OTG, inst),\ +- SRI(OTG_GSL_CONTROL, OTG, inst) +- +-#define TG_COMMON_REG_LIST_DCN1_0(inst) \ +- TG_COMMON_REG_LIST_DCN(inst),\ +- SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ +- SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ +- SRI(OTG_TEST_PATTERN_COLOR, OTG, inst) +- +- +-struct dcn_optc_registers { +- uint32_t OTG_VERT_SYNC_CONTROL; +- uint32_t OTG_MASTER_UPDATE_MODE; +- uint32_t OTG_GSL_CONTROL; +- uint32_t OTG_VSTARTUP_PARAM; +- uint32_t OTG_VUPDATE_PARAM; +- uint32_t OTG_VREADY_PARAM; +- uint32_t OTG_BLANK_CONTROL; +- uint32_t OTG_MASTER_UPDATE_LOCK; +- uint32_t OTG_GLOBAL_CONTROL0; +- uint32_t OTG_DOUBLE_BUFFER_CONTROL; +- uint32_t OTG_H_TOTAL; +- uint32_t OTG_H_BLANK_START_END; +- uint32_t OTG_H_SYNC_A; +- uint32_t OTG_H_SYNC_A_CNTL; +- uint32_t OTG_H_TIMING_CNTL; +- uint32_t OTG_V_TOTAL; +- uint32_t OTG_V_BLANK_START_END; +- uint32_t OTG_V_SYNC_A; +- uint32_t OTG_V_SYNC_A_CNTL; +- uint32_t OTG_INTERLACE_CONTROL; +- uint32_t OTG_CONTROL; +- uint32_t OTG_STEREO_CONTROL; +- uint32_t OTG_3D_STRUCTURE_CONTROL; +- uint32_t OTG_STEREO_STATUS; +- uint32_t OTG_V_TOTAL_MAX; +- uint32_t OTG_V_TOTAL_MIN; +- uint32_t OTG_V_TOTAL_CONTROL; +- uint32_t OTG_TRIGA_CNTL; +- uint32_t OTG_FORCE_COUNT_NOW_CNTL; +- uint32_t OTG_STATIC_SCREEN_CONTROL; +- uint32_t OTG_STATUS_FRAME_COUNT; +- uint32_t OTG_STATUS; +- uint32_t OTG_STATUS_POSITION; +- uint32_t OTG_NOM_VERT_POSITION; +- uint32_t OTG_BLACK_COLOR; +- uint32_t OTG_TEST_PATTERN_PARAMETERS; +- uint32_t OTG_TEST_PATTERN_CONTROL; +- uint32_t OTG_TEST_PATTERN_COLOR; +- uint32_t OTG_CLOCK_CONTROL; +- uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; +- uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; +- uint32_t OPTC_INPUT_CLOCK_CONTROL; +- uint32_t OPTC_DATA_SOURCE_SELECT; +- uint32_t OPTC_INPUT_GLOBAL_CONTROL; +- uint32_t OPPBUF_CONTROL; +- uint32_t OPPBUF_3D_PARAMETERS_0; +- uint32_t CONTROL; +- uint32_t OTG_GSL_WINDOW_X; +- uint32_t OTG_GSL_WINDOW_Y; +- uint32_t OTG_VUPDATE_KEEPOUT; +- uint32_t OTG_DSC_START_POSITION; +-}; +- +-#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ +- SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ +- SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ +- SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ +- SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ +- SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, mask_sh),\ +- SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ +- SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ +- SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ +- SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ +- SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ +- SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ +- SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ +- SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ +- SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ +- SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ +- SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ +- SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ +- SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ +- SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ +- SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ +- SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ +- SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ +- SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ +- SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ +- SF(OTG0_OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, mask_sh),\ +- SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ +- SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ +- SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ +- SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ +- SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ +- SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ +- SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ +- SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ +- SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ +- SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ +- SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ +- SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ +- SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ +- SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ +- SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ +- SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ +- SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ +- SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ +- SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ +- SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ +- SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ +- SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ +- SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ +- SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ +- SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ +- SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ +- SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ +- SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ +- SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ +- SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ +- SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ +- SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ +- SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ +- SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ +- SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ +- SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ +- SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ +- SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ +- SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ +- SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ +- SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ +- SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ +- SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ +- SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ +- SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ +- SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ +- SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ +- SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ +- SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ +- SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ +- SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ +- SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ +- SF(OTG0_OTG_MASTER_UPDATE_MODE, MASTER_UPDATE_INTERLACED_MODE, mask_sh),\ +- SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ +- SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ +- SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ +- SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ +- SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ +- SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh) +- +- +-#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ +- TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ +- SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ +- SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh) +- +-#define TG_REG_FIELD_LIST(type) \ +- type VSTARTUP_START;\ +- type VUPDATE_OFFSET;\ +- type VUPDATE_WIDTH;\ +- type VREADY_OFFSET;\ +- type OTG_BLANK_DATA_EN;\ +- type OTG_BLANK_DE_MODE;\ +- type OTG_CURRENT_BLANK_STATE;\ +- type OTG_MASTER_UPDATE_LOCK;\ +- type UPDATE_LOCK_STATUS;\ +- type OTG_UPDATE_PENDING;\ +- type OTG_MASTER_UPDATE_LOCK_SEL;\ +- type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ +- type OTG_H_TOTAL;\ +- type OTG_H_BLANK_START;\ +- type OTG_H_BLANK_END;\ +- type OTG_H_SYNC_A_START;\ +- type OTG_H_SYNC_A_END;\ +- type OTG_H_SYNC_A_POL;\ +- type OTG_H_TIMING_DIV_BY2;\ +- type OTG_V_TOTAL;\ +- type OTG_V_BLANK_START;\ +- type OTG_V_BLANK_END;\ +- type OTG_V_SYNC_A_START;\ +- type OTG_V_SYNC_A_END;\ +- type OTG_V_SYNC_A_POL;\ +- type OTG_INTERLACE_ENABLE;\ +- type OTG_MASTER_EN;\ +- type OTG_START_POINT_CNTL;\ +- type OTG_DISABLE_POINT_CNTL;\ +- type OTG_FIELD_NUMBER_CNTL;\ +- type OTG_STEREO_EN;\ +- type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ +- type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ +- type OTG_STEREO_EYE_FLAG_POLARITY;\ +- type OTG_STEREO_CURRENT_EYE;\ +- type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ +- type OTG_3D_STRUCTURE_EN;\ +- type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ +- type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ +- type OTG_V_TOTAL_MAX;\ +- type OTG_V_TOTAL_MIN;\ +- type OTG_V_TOTAL_MIN_SEL;\ +- type OTG_V_TOTAL_MAX_SEL;\ +- type OTG_FORCE_LOCK_ON_EVENT;\ +- type OTG_SET_V_TOTAL_MIN_MASK_EN;\ +- type OTG_SET_V_TOTAL_MIN_MASK;\ +- type OTG_FORCE_COUNT_NOW_CLEAR;\ +- type OTG_FORCE_COUNT_NOW_MODE;\ +- type OTG_FORCE_COUNT_NOW_OCCURRED;\ +- type OTG_TRIGA_SOURCE_SELECT;\ +- type OTG_TRIGA_SOURCE_PIPE_SELECT;\ +- type OTG_TRIGA_RISING_EDGE_DETECT_CNTL;\ +- type OTG_TRIGA_FALLING_EDGE_DETECT_CNTL;\ +- type OTG_STATIC_SCREEN_EVENT_MASK;\ +- type OTG_STATIC_SCREEN_FRAME_COUNT;\ +- type OTG_FRAME_COUNT;\ +- type OTG_V_BLANK;\ +- type OTG_V_ACTIVE_DISP;\ +- type OTG_HORZ_COUNT;\ +- type OTG_VERT_COUNT;\ +- type OTG_VERT_COUNT_NOM;\ +- type OTG_BLACK_COLOR_B_CB;\ +- type OTG_BLACK_COLOR_G_Y;\ +- type OTG_BLACK_COLOR_R_CR;\ +- type OTG_TEST_PATTERN_INC0;\ +- type OTG_TEST_PATTERN_INC1;\ +- type OTG_TEST_PATTERN_VRES;\ +- type OTG_TEST_PATTERN_HRES;\ +- type OTG_TEST_PATTERN_RAMP0_OFFSET;\ +- type OTG_TEST_PATTERN_EN;\ +- type OTG_TEST_PATTERN_MODE;\ +- type OTG_TEST_PATTERN_DYNAMIC_RANGE;\ +- type OTG_TEST_PATTERN_COLOR_FORMAT;\ +- type OTG_TEST_PATTERN_MASK;\ +- type OTG_TEST_PATTERN_DATA;\ +- type OTG_BUSY;\ +- type OTG_CLOCK_EN;\ +- type OTG_CLOCK_ON;\ +- type OTG_CLOCK_GATE_DIS;\ +- type OTG_VERTICAL_INTERRUPT2_INT_ENABLE;\ +- type OTG_VERTICAL_INTERRUPT2_LINE_START;\ +- type OPTC_INPUT_CLK_EN;\ +- type OPTC_INPUT_CLK_ON;\ +- type OPTC_INPUT_CLK_GATE_DIS;\ +- type OPTC_SRC_SEL;\ +- type OPTC_SEG0_SRC_SEL;\ +- type OPTC_UNDERFLOW_OCCURRED_STATUS;\ +- type OPTC_UNDERFLOW_CLEAR;\ +- type OPPBUF_ACTIVE_WIDTH;\ +- type OPPBUF_3D_VACT_SPACE1_SIZE;\ +- type VTG0_ENABLE;\ +- type VTG0_FP2;\ +- type VTG0_VCOUNT_INIT;\ +- type OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED;\ +- type OTG_FORCE_VSYNC_NEXT_LINE_CLEAR;\ +- type OTG_AUTO_FORCE_VSYNC_MODE;\ +- type MASTER_UPDATE_INTERLACED_MODE;\ +- type OTG_GSL0_EN;\ +- type OTG_GSL1_EN;\ +- type OTG_GSL2_EN;\ +- type OTG_GSL_MASTER_EN;\ +- type OTG_GSL_FORCE_DELAY;\ +- type OTG_GSL_CHECK_ALL_FIELDS;\ +- type OTG_GSL_WINDOW_START_X;\ +- type OTG_GSL_WINDOW_END_X;\ +- type OTG_GSL_WINDOW_START_Y;\ +- type OTG_GSL_WINDOW_END_Y;\ +- type OTG_RANGE_TIMING_DBUF_UPDATE_MODE;\ +- type OTG_GSL_MASTER_MODE;\ +- type OTG_MASTER_UPDATE_LOCK_GSL_EN;\ +- type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\ +- type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET;\ +- type OTG_DSC_START_POSITION_X;\ +- type OTG_DSC_START_POSITION_LINE_NUM;\ +- type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN; +- +- +-struct dcn_optc_shift { +- TG_REG_FIELD_LIST(uint8_t) +-}; +- +-struct dcn_optc_mask { +- TG_REG_FIELD_LIST(uint32_t) +-}; +- +-struct optc { +- struct timing_generator base; +- +- const struct dcn_optc_registers *tg_regs; +- const struct dcn_optc_shift *tg_shift; +- const struct dcn_optc_mask *tg_mask; +- +- enum controller_id controller_id; +- +- uint32_t max_h_total; +- uint32_t max_v_total; +- +- uint32_t min_h_blank; +- +- uint32_t min_h_sync_width; +- uint32_t min_v_sync_width; +- uint32_t min_v_blank; +- uint32_t min_v_blank_interlace; +-}; +- +-void dcn10_timing_generator_init(struct optc *optc); +- +-struct dcn_otg_state { +- uint32_t v_blank_start; +- uint32_t v_blank_end; +- uint32_t v_sync_a_pol; +- uint32_t v_total; +- uint32_t v_total_max; +- uint32_t v_total_min; +- uint32_t v_sync_a_start; +- uint32_t v_sync_a_end; +- uint32_t h_blank_start; +- uint32_t h_blank_end; +- uint32_t h_sync_a_start; +- uint32_t h_sync_a_end; +- uint32_t h_sync_a_pol; +- uint32_t h_total; +- uint32_t underflow_occurred_status; +- uint32_t otg_enabled; +-}; +- +-void optc1_read_otg_state(struct optc *optc1, +- struct dcn_otg_state *s); +- +-bool optc1_validate_timing( +- struct timing_generator *optc, +- const struct dc_crtc_timing *timing); +- +-void optc1_program_timing( +- struct timing_generator *optc, +- const struct dc_crtc_timing *dc_crtc_timing, +- bool use_vbios); +- +-void optc1_program_global_sync( +- struct timing_generator *optc); +- +-bool optc1_disable_crtc(struct timing_generator *optc); +- +-bool optc1_is_counter_moving(struct timing_generator *optc); +- +-void optc1_get_position(struct timing_generator *optc, +- struct crtc_position *position); +- +-uint32_t optc1_get_vblank_counter(struct timing_generator *optc); +- +-void optc1_get_crtc_scanoutpos( +- struct timing_generator *optc, +- uint32_t *v_blank_start, +- uint32_t *v_blank_end, +- uint32_t *h_position, +- uint32_t *v_position); +- +-void optc1_set_early_control( +- struct timing_generator *optc, +- uint32_t early_cntl); +- +-void optc1_wait_for_state(struct timing_generator *optc, +- enum crtc_state state); +- +-void optc1_set_blank(struct timing_generator *optc, +- bool enable_blanking); +- +-bool optc1_is_blanked(struct timing_generator *optc); +- +-void optc1_program_blank_color( +- struct timing_generator *optc, +- const struct tg_color *black_color); +- +-bool optc1_did_triggered_reset_occur( +- struct timing_generator *optc); +- +-void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst); +- +-void optc1_disable_reset_trigger(struct timing_generator *optc); +- +-void optc1_lock(struct timing_generator *optc); +- +-void optc1_unlock(struct timing_generator *optc); +- +-void optc1_enable_optc_clock(struct timing_generator *optc, bool enable); +- +-void optc1_set_drr( +- struct timing_generator *optc, +- const struct drr_params *params); +- +-void optc1_set_static_screen_control( +- struct timing_generator *optc, +- uint32_t value); +- +-void optc1_program_stereo(struct timing_generator *optc, +- const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); +- +-bool optc1_is_stereo_left_eye(struct timing_generator *optc); +- +-#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +index 6da125d..17e143e 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +@@ -282,25 +282,6 @@ struct opp_funcs { + bool enable, + bool rightEyePolarity); + +- void (*opp_set_test_pattern)( +- struct output_pixel_processor *opp, +- enum controller_dp_test_pattern test_pattern, +- enum dc_color_depth color_depth, +- int width, +- int height); +- +- void (*opp_dpg_blank_enable)( +- struct output_pixel_processor *opp, +- bool enable, +- const struct tg_color *color, +- int width, +- int height); +- +- void (*opp_convert_pti)( +- struct output_pixel_processor *opp, +- bool enable, +- bool polarity); +- + }; + + #endif +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +index a32c745..4c0aa56 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +@@ -28,6 +28,7 @@ + #include "dc_types.h" + #include "clock_source.h" + #include "inc/hw/timing_generator.h" ++#include "inc/hw/opp.h" + #include "inc/hw/link_encoder.h" + #include "core_status.h" + +-- +2.7.4 + |