1b8fdfcc6SHarry Wentland /*
2b8fdfcc6SHarry Wentland  * Copyright 2012-15 Advanced Micro Devices, Inc.
3b8fdfcc6SHarry Wentland  *
4b8fdfcc6SHarry Wentland  * Permission is hereby granted, free of charge, to any person obtaining a
5b8fdfcc6SHarry Wentland  * copy of this software and associated documentation files (the "Software"),
6b8fdfcc6SHarry Wentland  * to deal in the Software without restriction, including without limitation
7b8fdfcc6SHarry Wentland  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8fdfcc6SHarry Wentland  * and/or sell copies of the Software, and to permit persons to whom the
9b8fdfcc6SHarry Wentland  * Software is furnished to do so, subject to the following conditions:
10b8fdfcc6SHarry Wentland  *
11b8fdfcc6SHarry Wentland  * The above copyright notice and this permission notice shall be included in
12b8fdfcc6SHarry Wentland  * all copies or substantial portions of the Software.
13b8fdfcc6SHarry Wentland  *
14b8fdfcc6SHarry Wentland  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b8fdfcc6SHarry Wentland  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b8fdfcc6SHarry Wentland  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17b8fdfcc6SHarry Wentland  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18b8fdfcc6SHarry Wentland  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19b8fdfcc6SHarry Wentland  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20b8fdfcc6SHarry Wentland  * OTHER DEALINGS IN THE SOFTWARE.
21b8fdfcc6SHarry Wentland  *
22b8fdfcc6SHarry Wentland  * Authors: AMD
23b8fdfcc6SHarry Wentland  *
24b8fdfcc6SHarry Wentland  */
25b8fdfcc6SHarry Wentland 
26b8fdfcc6SHarry Wentland #include "dm_services.h"
27b8fdfcc6SHarry Wentland 
28135d4b10SFeifei Xu #include "dce/dce_12_0_offset.h"
29135d4b10SFeifei Xu #include "dce/dce_12_0_sh_mask.h"
30407e7517SHawking Zhang #include "soc15_hw_ip.h"
31407e7517SHawking Zhang #include "vega10_ip_offset.h"
32b8fdfcc6SHarry Wentland 
33b8fdfcc6SHarry Wentland #include "dc_types.h"
34b8fdfcc6SHarry Wentland #include "dc_bios_types.h"
35b8fdfcc6SHarry Wentland 
36b8fdfcc6SHarry Wentland #include "include/grph_object_id.h"
37b8fdfcc6SHarry Wentland #include "include/logger_interface.h"
38b8fdfcc6SHarry Wentland #include "dce120_timing_generator.h"
39b8fdfcc6SHarry Wentland 
40b8fdfcc6SHarry Wentland #include "timing_generator.h"
41b8fdfcc6SHarry Wentland 
42b8fdfcc6SHarry Wentland #define CRTC_REG_UPDATE_N(reg_name, n, ...)	\
43b8fdfcc6SHarry Wentland 		generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
44b8fdfcc6SHarry Wentland 
45b8fdfcc6SHarry Wentland #define CRTC_REG_SET_N(reg_name, n, ...)	\
46b8fdfcc6SHarry Wentland 		generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
47b8fdfcc6SHarry Wentland 
48b8fdfcc6SHarry Wentland #define CRTC_REG_UPDATE(reg, field, val)	\
49b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
50b8fdfcc6SHarry Wentland 
51b8fdfcc6SHarry Wentland #define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2)	\
52b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
53b8fdfcc6SHarry Wentland 
54b8fdfcc6SHarry Wentland #define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3)	\
55b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
56b8fdfcc6SHarry Wentland 
57b8fdfcc6SHarry Wentland #define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4)	\
58b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4)
59b8fdfcc6SHarry Wentland 
60b8fdfcc6SHarry Wentland #define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5)	\
61b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4, FD(reg##__##field5), val5)
62b8fdfcc6SHarry Wentland 
63b8fdfcc6SHarry Wentland #define CRTC_REG_SET(reg, field, val)	\
64b8fdfcc6SHarry Wentland 		CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val)
65b8fdfcc6SHarry Wentland 
66b8fdfcc6SHarry Wentland #define CRTC_REG_SET_2(reg, field1, val1, field2, val2)	\
67b8fdfcc6SHarry Wentland 		CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
68b8fdfcc6SHarry Wentland 
69b8fdfcc6SHarry Wentland #define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3)	\
70b8fdfcc6SHarry Wentland 		CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
71b8fdfcc6SHarry Wentland 
72d2b6564dSLee Jones /*
73b8fdfcc6SHarry Wentland  *****************************************************************************
74b8fdfcc6SHarry Wentland  *  Function: is_in_vertical_blank
75b8fdfcc6SHarry Wentland  *
76b8fdfcc6SHarry Wentland  *  @brief
77b8fdfcc6SHarry Wentland  *     check the current status of CRTC to check if we are in Vertical Blank
78b8fdfcc6SHarry Wentland  *     regioneased" state
79b8fdfcc6SHarry Wentland  *
80b8fdfcc6SHarry Wentland  *  @return
81b8fdfcc6SHarry Wentland  *     true if currently in blank region, false otherwise
82b8fdfcc6SHarry Wentland  *
83b8fdfcc6SHarry Wentland  *****************************************************************************
84b8fdfcc6SHarry Wentland  */
dce120_timing_generator_is_in_vertical_blank(struct timing_generator * tg)85b8fdfcc6SHarry Wentland static bool dce120_timing_generator_is_in_vertical_blank(
86b8fdfcc6SHarry Wentland 		struct timing_generator *tg)
87b8fdfcc6SHarry Wentland {
88b8fdfcc6SHarry Wentland 	uint32_t field = 0;
89b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
90b8fdfcc6SHarry Wentland 	uint32_t value = dm_read_reg_soc15(
91b8fdfcc6SHarry Wentland 					tg->ctx,
92b8fdfcc6SHarry Wentland 					mmCRTC0_CRTC_STATUS,
93b8fdfcc6SHarry Wentland 					tg110->offsets.crtc);
94b8fdfcc6SHarry Wentland 
95b8fdfcc6SHarry Wentland 	field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK);
96b8fdfcc6SHarry Wentland 	return field == 1;
97b8fdfcc6SHarry Wentland }
98b8fdfcc6SHarry Wentland 
99b8fdfcc6SHarry Wentland 
100b8fdfcc6SHarry Wentland /* determine if given timing can be supported by TG */
dce120_timing_generator_validate_timing(struct timing_generator * tg,const struct dc_crtc_timing * timing,enum signal_type signal)101eea08ecbSLee Jones static bool dce120_timing_generator_validate_timing(
102b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
103b8fdfcc6SHarry Wentland 	const struct dc_crtc_timing *timing,
104b8fdfcc6SHarry Wentland 	enum signal_type signal)
105b8fdfcc6SHarry Wentland {
106b8fdfcc6SHarry Wentland 	uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1;
107b8fdfcc6SHarry Wentland 	uint32_t v_blank =
108b8fdfcc6SHarry Wentland 					(timing->v_total - timing->v_addressable -
109b8fdfcc6SHarry Wentland 					timing->v_border_top - timing->v_border_bottom) *
110b8fdfcc6SHarry Wentland 					interlace_factor;
111b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
112b8fdfcc6SHarry Wentland 
113b8fdfcc6SHarry Wentland 	if (!dce110_timing_generator_validate_timing(
114b8fdfcc6SHarry Wentland 					tg,
115b8fdfcc6SHarry Wentland 					timing,
116b8fdfcc6SHarry Wentland 					signal))
117b8fdfcc6SHarry Wentland 		return false;
118b8fdfcc6SHarry Wentland 
119b8fdfcc6SHarry Wentland 
120b8fdfcc6SHarry Wentland 	if (v_blank < tg110->min_v_blank	||
121b8fdfcc6SHarry Wentland 		 timing->h_sync_width  < tg110->min_h_sync_width ||
122b8fdfcc6SHarry Wentland 		 timing->v_sync_width  < tg110->min_v_sync_width)
123b8fdfcc6SHarry Wentland 		return false;
124b8fdfcc6SHarry Wentland 
125b8fdfcc6SHarry Wentland 	return true;
126b8fdfcc6SHarry Wentland }
127b8fdfcc6SHarry Wentland 
dce120_tg_validate_timing(struct timing_generator * tg,const struct dc_crtc_timing * timing)128eea08ecbSLee Jones static bool dce120_tg_validate_timing(struct timing_generator *tg,
129b8fdfcc6SHarry Wentland 	const struct dc_crtc_timing *timing)
130b8fdfcc6SHarry Wentland {
131b8fdfcc6SHarry Wentland 	return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
132b8fdfcc6SHarry Wentland }
133b8fdfcc6SHarry Wentland 
134b8fdfcc6SHarry Wentland /******** HW programming ************/
135b8fdfcc6SHarry Wentland /* Disable/Enable Timing Generator */
dce120_timing_generator_enable_crtc(struct timing_generator * tg)136eea08ecbSLee Jones static bool dce120_timing_generator_enable_crtc(struct timing_generator *tg)
137b8fdfcc6SHarry Wentland {
138b8fdfcc6SHarry Wentland 	enum bp_result result;
139b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
140b8fdfcc6SHarry Wentland 
141b8fdfcc6SHarry Wentland 	/* Set MASTER_UPDATE_MODE to 0
142b8fdfcc6SHarry Wentland 	 * This is needed for DRR, and also suggested to be default value by Syed.*/
143b8fdfcc6SHarry Wentland 
144b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE,
145b8fdfcc6SHarry Wentland 			MASTER_UPDATE_MODE, 0);
146b8fdfcc6SHarry Wentland 
147b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK,
148b8fdfcc6SHarry Wentland 			UNDERFLOW_UPDATE_LOCK, 0);
149b8fdfcc6SHarry Wentland 
150b8fdfcc6SHarry Wentland 	/* TODO API for AtomFirmware didn't change*/
151b8fdfcc6SHarry Wentland 	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
152b8fdfcc6SHarry Wentland 
153b8fdfcc6SHarry Wentland 	return result == BP_RESULT_OK;
154b8fdfcc6SHarry Wentland }
155b8fdfcc6SHarry Wentland 
dce120_timing_generator_set_early_control(struct timing_generator * tg,uint32_t early_cntl)156eea08ecbSLee Jones static void dce120_timing_generator_set_early_control(
157b8fdfcc6SHarry Wentland 		struct timing_generator *tg,
158b8fdfcc6SHarry Wentland 		uint32_t early_cntl)
159b8fdfcc6SHarry Wentland {
160b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
161b8fdfcc6SHarry Wentland 
162b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL,
163b8fdfcc6SHarry Wentland 			CRTC_HBLANK_EARLY_CONTROL, early_cntl);
164b8fdfcc6SHarry Wentland }
165b8fdfcc6SHarry Wentland 
166b8fdfcc6SHarry Wentland /**************** TG current status ******************/
167b8fdfcc6SHarry Wentland 
168b8fdfcc6SHarry Wentland /* return the current frame counter. Used by Linux kernel DRM */
dce120_timing_generator_get_vblank_counter(struct timing_generator * tg)169eea08ecbSLee Jones static uint32_t dce120_timing_generator_get_vblank_counter(
170b8fdfcc6SHarry Wentland 		struct timing_generator *tg)
171b8fdfcc6SHarry Wentland {
172b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
173b8fdfcc6SHarry Wentland 	uint32_t value = dm_read_reg_soc15(
174b8fdfcc6SHarry Wentland 				tg->ctx,
175b8fdfcc6SHarry Wentland 				mmCRTC0_CRTC_STATUS_FRAME_COUNT,
176b8fdfcc6SHarry Wentland 				tg110->offsets.crtc);
177b8fdfcc6SHarry Wentland 	uint32_t field = get_reg_field_value(
178b8fdfcc6SHarry Wentland 				value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
179b8fdfcc6SHarry Wentland 
180b8fdfcc6SHarry Wentland 	return field;
181b8fdfcc6SHarry Wentland }
182b8fdfcc6SHarry Wentland 
183b8fdfcc6SHarry Wentland /* Get current H and V position */
dce120_timing_generator_get_crtc_position(struct timing_generator * tg,struct crtc_position * position)184eea08ecbSLee Jones static void dce120_timing_generator_get_crtc_position(
185b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
18672ada5f7SEric Cook 	struct crtc_position *position)
187b8fdfcc6SHarry Wentland {
188b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
189b8fdfcc6SHarry Wentland 	uint32_t value = dm_read_reg_soc15(
190b8fdfcc6SHarry Wentland 				tg->ctx,
191b8fdfcc6SHarry Wentland 				mmCRTC0_CRTC_STATUS_POSITION,
192b8fdfcc6SHarry Wentland 				tg110->offsets.crtc);
193b8fdfcc6SHarry Wentland 
19472ada5f7SEric Cook 	position->horizontal_count = get_reg_field_value(value,
19572ada5f7SEric Cook 			CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
196b8fdfcc6SHarry Wentland 
19772ada5f7SEric Cook 	position->vertical_count = get_reg_field_value(value,
19872ada5f7SEric Cook 			CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
19972ada5f7SEric Cook 
20072ada5f7SEric Cook 	value = dm_read_reg_soc15(
20172ada5f7SEric Cook 				tg->ctx,
20272ada5f7SEric Cook 				mmCRTC0_CRTC_NOM_VERT_POSITION,
20372ada5f7SEric Cook 				tg110->offsets.crtc);
20472ada5f7SEric Cook 
20572ada5f7SEric Cook 	position->nominal_vcount = get_reg_field_value(value,
20672ada5f7SEric Cook 			CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM);
207b8fdfcc6SHarry Wentland }
208b8fdfcc6SHarry Wentland 
209b8fdfcc6SHarry Wentland /* wait until TG is in beginning of vertical blank region */
dce120_timing_generator_wait_for_vblank(struct timing_generator * tg)210eea08ecbSLee Jones static void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg)
211b8fdfcc6SHarry Wentland {
212b8fdfcc6SHarry Wentland 	/* We want to catch beginning of VBlank here, so if the first try are
213b8fdfcc6SHarry Wentland 	 * in VBlank, we might be very close to Active, in this case wait for
214b8fdfcc6SHarry Wentland 	 * another frame
215b8fdfcc6SHarry Wentland 	 */
216b8fdfcc6SHarry Wentland 	while (dce120_timing_generator_is_in_vertical_blank(tg)) {
217b8fdfcc6SHarry Wentland 		if (!tg->funcs->is_counter_moving(tg)) {
218b8fdfcc6SHarry Wentland 			/* error - no point to wait if counter is not moving */
219b8fdfcc6SHarry Wentland 			break;
220b8fdfcc6SHarry Wentland 		}
221b8fdfcc6SHarry Wentland 	}
222b8fdfcc6SHarry Wentland 
223b8fdfcc6SHarry Wentland 	while (!dce120_timing_generator_is_in_vertical_blank(tg)) {
224b8fdfcc6SHarry Wentland 		if (!tg->funcs->is_counter_moving(tg)) {
225b8fdfcc6SHarry Wentland 			/* error - no point to wait if counter is not moving */
226b8fdfcc6SHarry Wentland 			break;
227b8fdfcc6SHarry Wentland 		}
228b8fdfcc6SHarry Wentland 	}
229b8fdfcc6SHarry Wentland }
230b8fdfcc6SHarry Wentland 
231b8fdfcc6SHarry Wentland /* wait until TG is in beginning of active region */
dce120_timing_generator_wait_for_vactive(struct timing_generator * tg)232eea08ecbSLee Jones static void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg)
233b8fdfcc6SHarry Wentland {
234b8fdfcc6SHarry Wentland 	while (dce120_timing_generator_is_in_vertical_blank(tg)) {
235b8fdfcc6SHarry Wentland 		if (!tg->funcs->is_counter_moving(tg)) {
236b8fdfcc6SHarry Wentland 			/* error - no point to wait if counter is not moving */
237b8fdfcc6SHarry Wentland 			break;
238b8fdfcc6SHarry Wentland 		}
239b8fdfcc6SHarry Wentland 	}
240b8fdfcc6SHarry Wentland }
241b8fdfcc6SHarry Wentland 
242b8fdfcc6SHarry Wentland /*********** Timing Generator Synchronization routines ****/
243b8fdfcc6SHarry Wentland 
244b8fdfcc6SHarry Wentland /* Setups Global Swap Lock group, TimingServer or TimingClient*/
dce120_timing_generator_setup_global_swap_lock(struct timing_generator * tg,const struct dcp_gsl_params * gsl_params)245eea08ecbSLee Jones static void dce120_timing_generator_setup_global_swap_lock(
246b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
247b8fdfcc6SHarry Wentland 	const struct dcp_gsl_params *gsl_params)
248b8fdfcc6SHarry Wentland {
249b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
250b8fdfcc6SHarry Wentland 	uint32_t value_crtc_vtotal =
251b8fdfcc6SHarry Wentland 							dm_read_reg_soc15(tg->ctx,
252b8fdfcc6SHarry Wentland 							mmCRTC0_CRTC_V_TOTAL,
253b8fdfcc6SHarry Wentland 							tg110->offsets.crtc);
254b8fdfcc6SHarry Wentland 	/* Checkpoint relative to end of frame */
255b8fdfcc6SHarry Wentland 	uint32_t check_point =
256b8fdfcc6SHarry Wentland 							get_reg_field_value(value_crtc_vtotal,
257b8fdfcc6SHarry Wentland 							CRTC0_CRTC_V_TOTAL,
258b8fdfcc6SHarry Wentland 							CRTC_V_TOTAL);
259b8fdfcc6SHarry Wentland 
260b8fdfcc6SHarry Wentland 
261b8fdfcc6SHarry Wentland 	dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0);
262b8fdfcc6SHarry Wentland 
263b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6,
264b8fdfcc6SHarry Wentland 		/* This pipe will belong to GSL Group zero. */
265b8fdfcc6SHarry Wentland 		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1,
266b8fdfcc6SHarry Wentland 		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst,
267b8fdfcc6SHarry Wentland 		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
268b8fdfcc6SHarry Wentland 		/* Keep signal low (pending high) during 6 lines.
269b8fdfcc6SHarry Wentland 		 * Also defines minimum interval before re-checking signal. */
270b8fdfcc6SHarry Wentland 		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
271b8fdfcc6SHarry Wentland 		/* DCP_GSL_PURPOSE_SURFACE_FLIP */
272b8fdfcc6SHarry Wentland 		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
273b8fdfcc6SHarry Wentland 		FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1);
274b8fdfcc6SHarry Wentland 
275b8fdfcc6SHarry Wentland 	CRTC_REG_SET_2(
276b8fdfcc6SHarry Wentland 			CRTC0_CRTC_GSL_CONTROL,
277b8fdfcc6SHarry Wentland 			CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP,
278b8fdfcc6SHarry Wentland 			CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY);
279b8fdfcc6SHarry Wentland }
280b8fdfcc6SHarry Wentland 
281b8fdfcc6SHarry Wentland /* Clear all the register writes done by setup_global_swap_lock */
dce120_timing_generator_tear_down_global_swap_lock(struct timing_generator * tg)282eea08ecbSLee Jones static void dce120_timing_generator_tear_down_global_swap_lock(
283b8fdfcc6SHarry Wentland 	struct timing_generator *tg)
284b8fdfcc6SHarry Wentland {
285b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
286b8fdfcc6SHarry Wentland 
287b8fdfcc6SHarry Wentland 	/* Settig HW default values from reg specs */
288b8fdfcc6SHarry Wentland 	CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6,
289b8fdfcc6SHarry Wentland 			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0,
290b8fdfcc6SHarry Wentland 			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0,
291b8fdfcc6SHarry Wentland 			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
292b8fdfcc6SHarry Wentland 			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
293b8fdfcc6SHarry Wentland 			/* DCP_GSL_PURPOSE_SURFACE_FLIP */
294b8fdfcc6SHarry Wentland 			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
295b8fdfcc6SHarry Wentland 			FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0);
296b8fdfcc6SHarry Wentland 
297bf5563edSDave Airlie 	CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL,
298b8fdfcc6SHarry Wentland 		       CRTC_GSL_CHECK_LINE_NUM, 0,
299b8fdfcc6SHarry Wentland 		       CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/
300b8fdfcc6SHarry Wentland }
301b8fdfcc6SHarry Wentland 
302b8fdfcc6SHarry Wentland /* Reset slave controllers on master VSync */
dce120_timing_generator_enable_reset_trigger(struct timing_generator * tg,int source)303eea08ecbSLee Jones static void dce120_timing_generator_enable_reset_trigger(
304b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
305b8fdfcc6SHarry Wentland 	int source)
306b8fdfcc6SHarry Wentland {
307b8fdfcc6SHarry Wentland 	enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
308b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
309b8fdfcc6SHarry Wentland 	uint32_t rising_edge = 0;
310b8fdfcc6SHarry Wentland 	uint32_t falling_edge = 0;
311b8fdfcc6SHarry Wentland 	/* Setup trigger edge */
312b8fdfcc6SHarry Wentland 	uint32_t pol_value = dm_read_reg_soc15(
313b8fdfcc6SHarry Wentland 									tg->ctx,
314b8fdfcc6SHarry Wentland 									mmCRTC0_CRTC_V_SYNC_A_CNTL,
315b8fdfcc6SHarry Wentland 									tg110->offsets.crtc);
316b8fdfcc6SHarry Wentland 
317b8fdfcc6SHarry Wentland 	/* Register spec has reversed definition:
318b8fdfcc6SHarry Wentland 	 *	0 for positive, 1 for negative */
319b8fdfcc6SHarry Wentland 	if (get_reg_field_value(pol_value,
320b8fdfcc6SHarry Wentland 			CRTC0_CRTC_V_SYNC_A_CNTL,
321b8fdfcc6SHarry Wentland 			CRTC_V_SYNC_A_POL) == 0) {
322b8fdfcc6SHarry Wentland 		rising_edge = 1;
323b8fdfcc6SHarry Wentland 	} else {
324b8fdfcc6SHarry Wentland 		falling_edge = 1;
325b8fdfcc6SHarry Wentland 	}
326b8fdfcc6SHarry Wentland 
327b8fdfcc6SHarry Wentland 	/* TODO What about other sources ?*/
328b8fdfcc6SHarry Wentland 	trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
329b8fdfcc6SHarry Wentland 
330b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7,
331b8fdfcc6SHarry Wentland 		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select,
332b8fdfcc6SHarry Wentland 		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
333b8fdfcc6SHarry Wentland 		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge,
334b8fdfcc6SHarry Wentland 		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge,
335b8fdfcc6SHarry Wentland 		/* send every signal */
336b8fdfcc6SHarry Wentland 		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0,
337b8fdfcc6SHarry Wentland 		/* no delay */
338b8fdfcc6SHarry Wentland 		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0,
339b8fdfcc6SHarry Wentland 		/* clear trigger status */
340b8fdfcc6SHarry Wentland 		FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1);
341b8fdfcc6SHarry Wentland 
342b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_3(
343b8fdfcc6SHarry Wentland 			CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
344b8fdfcc6SHarry Wentland 			CRTC_FORCE_COUNT_NOW_MODE, 2,
345b8fdfcc6SHarry Wentland 			CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1,
346b8fdfcc6SHarry Wentland 			CRTC_FORCE_COUNT_NOW_CLEAR, 1);
347b8fdfcc6SHarry Wentland }
348b8fdfcc6SHarry Wentland 
349b8fdfcc6SHarry Wentland /* disabling trigger-reset */
dce120_timing_generator_disable_reset_trigger(struct timing_generator * tg)350eea08ecbSLee Jones static void dce120_timing_generator_disable_reset_trigger(
351b8fdfcc6SHarry Wentland 	struct timing_generator *tg)
352b8fdfcc6SHarry Wentland {
353b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
354b8fdfcc6SHarry Wentland 
355b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_2(
356b8fdfcc6SHarry Wentland 		CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
357b8fdfcc6SHarry Wentland 		CRTC_FORCE_COUNT_NOW_MODE, 0,
358b8fdfcc6SHarry Wentland 		CRTC_FORCE_COUNT_NOW_CLEAR, 1);
359b8fdfcc6SHarry Wentland 
360b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_3(
361b8fdfcc6SHarry Wentland 		CRTC0_CRTC_TRIGB_CNTL,
362b8fdfcc6SHarry Wentland 		CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
363b8fdfcc6SHarry Wentland 		CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
364b8fdfcc6SHarry Wentland 		/* clear trigger status */
365b8fdfcc6SHarry Wentland 		CRTC_TRIGB_CLEAR, 1);
366b8fdfcc6SHarry Wentland 
367b8fdfcc6SHarry Wentland }
368b8fdfcc6SHarry Wentland 
369b8fdfcc6SHarry Wentland /* Checks whether CRTC triggered reset occurred */
dce120_timing_generator_did_triggered_reset_occur(struct timing_generator * tg)370eea08ecbSLee Jones static bool dce120_timing_generator_did_triggered_reset_occur(
371b8fdfcc6SHarry Wentland 	struct timing_generator *tg)
372b8fdfcc6SHarry Wentland {
373b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
374b8fdfcc6SHarry Wentland 	uint32_t value = dm_read_reg_soc15(
375b8fdfcc6SHarry Wentland 			tg->ctx,
376b8fdfcc6SHarry Wentland 			mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
377b8fdfcc6SHarry Wentland 			tg110->offsets.crtc);
378b8fdfcc6SHarry Wentland 
379b8fdfcc6SHarry Wentland 	return get_reg_field_value(value,
380b8fdfcc6SHarry Wentland 			CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
381b8fdfcc6SHarry Wentland 			CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
382b8fdfcc6SHarry Wentland }
383b8fdfcc6SHarry Wentland 
384b8fdfcc6SHarry Wentland 
385b8fdfcc6SHarry Wentland /******** Stuff to move to other virtual HW objects *****************/
386b8fdfcc6SHarry Wentland /* Move to enable accelerated mode */
dce120_timing_generator_disable_vga(struct timing_generator * tg)387eea08ecbSLee Jones static void dce120_timing_generator_disable_vga(struct timing_generator *tg)
388b8fdfcc6SHarry Wentland {
389b8fdfcc6SHarry Wentland 	uint32_t offset = 0;
390b8fdfcc6SHarry Wentland 	uint32_t value = 0;
391b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
392b8fdfcc6SHarry Wentland 
393b8fdfcc6SHarry Wentland 	switch (tg110->controller_id) {
394b8fdfcc6SHarry Wentland 	case CONTROLLER_ID_D0:
395b8fdfcc6SHarry Wentland 		offset = 0;
396b8fdfcc6SHarry Wentland 		break;
397b8fdfcc6SHarry Wentland 	case CONTROLLER_ID_D1:
398b8fdfcc6SHarry Wentland 		offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL;
399b8fdfcc6SHarry Wentland 		break;
400b8fdfcc6SHarry Wentland 	case CONTROLLER_ID_D2:
401b8fdfcc6SHarry Wentland 		offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL;
402b8fdfcc6SHarry Wentland 		break;
403b8fdfcc6SHarry Wentland 	case CONTROLLER_ID_D3:
404b8fdfcc6SHarry Wentland 		offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL;
405b8fdfcc6SHarry Wentland 		break;
406b8fdfcc6SHarry Wentland 	case CONTROLLER_ID_D4:
407ccaf31ecSRoman Li 		offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL;
408b8fdfcc6SHarry Wentland 		break;
409b8fdfcc6SHarry Wentland 	case CONTROLLER_ID_D5:
410b8fdfcc6SHarry Wentland 		offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL;
411b8fdfcc6SHarry Wentland 		break;
412b8fdfcc6SHarry Wentland 	default:
413b8fdfcc6SHarry Wentland 		break;
414b8fdfcc6SHarry Wentland 	}
415b8fdfcc6SHarry Wentland 
416b8fdfcc6SHarry Wentland 	value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset);
417b8fdfcc6SHarry Wentland 
418b8fdfcc6SHarry Wentland 	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
419b8fdfcc6SHarry Wentland 	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
420b8fdfcc6SHarry Wentland 	set_reg_field_value(
421b8fdfcc6SHarry Wentland 			value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
422b8fdfcc6SHarry Wentland 	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
423b8fdfcc6SHarry Wentland 
424b8fdfcc6SHarry Wentland 	dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value);
425b8fdfcc6SHarry Wentland }
426b8fdfcc6SHarry Wentland /* TODO: Should we move it to transform */
427b8fdfcc6SHarry Wentland /* Fully program CRTC timing in timing generator */
dce120_timing_generator_program_blanking(struct timing_generator * tg,const struct dc_crtc_timing * timing)428eea08ecbSLee Jones static void dce120_timing_generator_program_blanking(
429b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
430b8fdfcc6SHarry Wentland 	const struct dc_crtc_timing *timing)
431b8fdfcc6SHarry Wentland {
432b8fdfcc6SHarry Wentland 	uint32_t tmp1 = 0;
433b8fdfcc6SHarry Wentland 	uint32_t tmp2 = 0;
434b8fdfcc6SHarry Wentland 	uint32_t vsync_offset = timing->v_border_bottom +
435b8fdfcc6SHarry Wentland 			timing->v_front_porch;
436b8fdfcc6SHarry Wentland 	uint32_t v_sync_start = timing->v_addressable + vsync_offset;
437b8fdfcc6SHarry Wentland 
438b8fdfcc6SHarry Wentland 	uint32_t hsync_offset = timing->h_border_right +
439b8fdfcc6SHarry Wentland 			timing->h_front_porch;
440b8fdfcc6SHarry Wentland 	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
441b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
442b8fdfcc6SHarry Wentland 
443b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE(
444b8fdfcc6SHarry Wentland 		CRTC0_CRTC_H_TOTAL,
445b8fdfcc6SHarry Wentland 		CRTC_H_TOTAL,
446b8fdfcc6SHarry Wentland 		timing->h_total - 1);
447b8fdfcc6SHarry Wentland 
448b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE(
449b8fdfcc6SHarry Wentland 		CRTC0_CRTC_V_TOTAL,
450b8fdfcc6SHarry Wentland 		CRTC_V_TOTAL,
45197416d4cSYongqiang Sun 		timing->v_total - 1);
45297416d4cSYongqiang Sun 
45397416d4cSYongqiang Sun 	/* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
45497416d4cSYongqiang Sun 	 * V_TOTAL_MIN are equal to V_TOTAL.
45597416d4cSYongqiang Sun 	 */
45697416d4cSYongqiang Sun 	CRTC_REG_UPDATE(
45797416d4cSYongqiang Sun 		CRTC0_CRTC_V_TOTAL_MAX,
45897416d4cSYongqiang Sun 		CRTC_V_TOTAL_MAX,
45997416d4cSYongqiang Sun 		timing->v_total - 1);
46097416d4cSYongqiang Sun 
46197416d4cSYongqiang Sun 	CRTC_REG_UPDATE(
46297416d4cSYongqiang Sun 		CRTC0_CRTC_V_TOTAL_MIN,
46397416d4cSYongqiang Sun 		CRTC_V_TOTAL_MIN,
464b8fdfcc6SHarry Wentland 		timing->v_total - 1);
465b8fdfcc6SHarry Wentland 
466b8fdfcc6SHarry Wentland 	tmp1 = timing->h_total -
467b8fdfcc6SHarry Wentland 			(h_sync_start + timing->h_border_left);
468b8fdfcc6SHarry Wentland 	tmp2 = tmp1 + timing->h_addressable +
469b8fdfcc6SHarry Wentland 			timing->h_border_left + timing->h_border_right;
470b8fdfcc6SHarry Wentland 
471b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_2(
472b8fdfcc6SHarry Wentland 			CRTC0_CRTC_H_BLANK_START_END,
473b8fdfcc6SHarry Wentland 			CRTC_H_BLANK_END, tmp1,
474b8fdfcc6SHarry Wentland 			CRTC_H_BLANK_START, tmp2);
475b8fdfcc6SHarry Wentland 
476b8fdfcc6SHarry Wentland 	tmp1 = timing->v_total - (v_sync_start + timing->v_border_top);
477b8fdfcc6SHarry Wentland 	tmp2 = tmp1 + timing->v_addressable + timing->v_border_top +
478b8fdfcc6SHarry Wentland 			timing->v_border_bottom;
479b8fdfcc6SHarry Wentland 
480b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_2(
481b8fdfcc6SHarry Wentland 		CRTC0_CRTC_V_BLANK_START_END,
482b8fdfcc6SHarry Wentland 		CRTC_V_BLANK_END, tmp1,
483b8fdfcc6SHarry Wentland 		CRTC_V_BLANK_START, tmp2);
484b8fdfcc6SHarry Wentland }
485b8fdfcc6SHarry Wentland 
486b8fdfcc6SHarry Wentland /* TODO: Should we move it to opp? */
487b8fdfcc6SHarry Wentland /* Combine with below and move YUV/RGB color conversion to SW layer */
dce120_timing_generator_program_blank_color(struct timing_generator * tg,const struct tg_color * black_color)488eea08ecbSLee Jones static void dce120_timing_generator_program_blank_color(
489b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
490b8fdfcc6SHarry Wentland 	const struct tg_color *black_color)
491b8fdfcc6SHarry Wentland {
492b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
493b8fdfcc6SHarry Wentland 
494b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_3(
495b8fdfcc6SHarry Wentland 		CRTC0_CRTC_BLACK_COLOR,
496b8fdfcc6SHarry Wentland 		CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
497b8fdfcc6SHarry Wentland 		CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
498b8fdfcc6SHarry Wentland 		CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
499b8fdfcc6SHarry Wentland }
500b8fdfcc6SHarry Wentland /* Combine with above and move YUV/RGB color conversion to SW layer */
dce120_timing_generator_set_overscan_color_black(struct timing_generator * tg,const struct tg_color * color)501eea08ecbSLee Jones static void dce120_timing_generator_set_overscan_color_black(
502b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
503b8fdfcc6SHarry Wentland 	const struct tg_color *color)
504b8fdfcc6SHarry Wentland {
505b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
506b8fdfcc6SHarry Wentland 	uint32_t value = 0;
507b8fdfcc6SHarry Wentland 	CRTC_REG_SET_3(
508b8fdfcc6SHarry Wentland 		CRTC0_CRTC_OVERSCAN_COLOR,
509b8fdfcc6SHarry Wentland 		CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb,
510b8fdfcc6SHarry Wentland 		CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y,
511b8fdfcc6SHarry Wentland 		CRTC_OVERSCAN_COLOR_RED, color->color_r_cr);
512b8fdfcc6SHarry Wentland 
513b8fdfcc6SHarry Wentland 	value = dm_read_reg_soc15(
514b8fdfcc6SHarry Wentland 			tg->ctx,
515b8fdfcc6SHarry Wentland 			mmCRTC0_CRTC_OVERSCAN_COLOR,
516b8fdfcc6SHarry Wentland 			tg110->offsets.crtc);
517b8fdfcc6SHarry Wentland 
518b8fdfcc6SHarry Wentland 	dm_write_reg_soc15(
519b8fdfcc6SHarry Wentland 			tg->ctx,
520b8fdfcc6SHarry Wentland 			mmCRTC0_CRTC_BLACK_COLOR,
521b8fdfcc6SHarry Wentland 			tg110->offsets.crtc,
522b8fdfcc6SHarry Wentland 			value);
523b8fdfcc6SHarry Wentland 
524b8fdfcc6SHarry Wentland 	/* This is desirable to have a constant DAC output voltage during the
525b8fdfcc6SHarry Wentland 	 * blank time that is higher than the 0 volt reference level that the
526b8fdfcc6SHarry Wentland 	 * DAC outputs when the NBLANK signal
527b8fdfcc6SHarry Wentland 	 * is asserted low, such as for output to an analog TV. */
528b8fdfcc6SHarry Wentland 	dm_write_reg_soc15(
529b8fdfcc6SHarry Wentland 		tg->ctx,
530b8fdfcc6SHarry Wentland 		mmCRTC0_CRTC_BLANK_DATA_COLOR,
531b8fdfcc6SHarry Wentland 		tg110->offsets.crtc,
532b8fdfcc6SHarry Wentland 		value);
533b8fdfcc6SHarry Wentland 
534b8fdfcc6SHarry Wentland 	/* TO DO we have to program EXT registers and we need to know LB DATA
535b8fdfcc6SHarry Wentland 	 * format because it is used when more 10 , i.e. 12 bits per color
536b8fdfcc6SHarry Wentland 	 *
537b8fdfcc6SHarry Wentland 	 * m_mmDxCRTC_OVERSCAN_COLOR_EXT
538b8fdfcc6SHarry Wentland 	 * m_mmDxCRTC_BLACK_COLOR_EXT
539b8fdfcc6SHarry Wentland 	 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
540b8fdfcc6SHarry Wentland 	 */
541b8fdfcc6SHarry Wentland }
542b8fdfcc6SHarry Wentland 
dce120_timing_generator_set_drr(struct timing_generator * tg,const struct drr_params * params)543eea08ecbSLee Jones static void dce120_timing_generator_set_drr(
544b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
545b8fdfcc6SHarry Wentland 	const struct drr_params *params)
546b8fdfcc6SHarry Wentland {
547b8fdfcc6SHarry Wentland 
548b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
549b8fdfcc6SHarry Wentland 
550b8fdfcc6SHarry Wentland 	if (params != NULL &&
551b8fdfcc6SHarry Wentland 		params->vertical_total_max > 0 &&
552b8fdfcc6SHarry Wentland 		params->vertical_total_min > 0) {
553b8fdfcc6SHarry Wentland 
554b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE(
555b8fdfcc6SHarry Wentland 				CRTC0_CRTC_V_TOTAL_MIN,
5566c626ffbSYongqiang Sun 				CRTC_V_TOTAL_MIN, params->vertical_total_min - 1);
557b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE(
558b8fdfcc6SHarry Wentland 				CRTC0_CRTC_V_TOTAL_MAX,
5596c626ffbSYongqiang Sun 				CRTC_V_TOTAL_MAX, params->vertical_total_max - 1);
560b8fdfcc6SHarry Wentland 		CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6,
561b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1,
562b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1,
563b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
564b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
565b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0,
566b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
567b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE(
568b8fdfcc6SHarry Wentland 				CRTC0_CRTC_STATIC_SCREEN_CONTROL,
569b8fdfcc6SHarry Wentland 				CRTC_STATIC_SCREEN_EVENT_MASK,
570b8fdfcc6SHarry Wentland 				0x180);
571b8fdfcc6SHarry Wentland 
572b8fdfcc6SHarry Wentland 	} else {
573b8fdfcc6SHarry Wentland 		CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5,
574b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0,
575b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0,
576b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
577b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
578b8fdfcc6SHarry Wentland 				FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
579b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE(
5800c8df4bbSAnthony Koo 				CRTC0_CRTC_V_TOTAL_MIN,
5810c8df4bbSAnthony Koo 				CRTC_V_TOTAL_MIN, 0);
5820c8df4bbSAnthony Koo 		CRTC_REG_UPDATE(
5830c8df4bbSAnthony Koo 				CRTC0_CRTC_V_TOTAL_MAX,
5840c8df4bbSAnthony Koo 				CRTC_V_TOTAL_MAX, 0);
5850c8df4bbSAnthony Koo 		CRTC_REG_UPDATE(
586b8fdfcc6SHarry Wentland 				CRTC0_CRTC_STATIC_SCREEN_CONTROL,
587b8fdfcc6SHarry Wentland 				CRTC_STATIC_SCREEN_EVENT_MASK,
588b8fdfcc6SHarry Wentland 				0);
589b8fdfcc6SHarry Wentland 	}
590b8fdfcc6SHarry Wentland }
591b8fdfcc6SHarry Wentland 
dce120_timing_generator_get_crtc_scanoutpos(struct timing_generator * tg,uint32_t * v_blank_start,uint32_t * v_blank_end,uint32_t * h_position,uint32_t * v_position)592eea08ecbSLee Jones static void dce120_timing_generator_get_crtc_scanoutpos(
593b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
59481c50963SSylvia Tsai 	uint32_t *v_blank_start,
59581c50963SSylvia Tsai 	uint32_t *v_blank_end,
59681c50963SSylvia Tsai 	uint32_t *h_position,
59781c50963SSylvia Tsai 	uint32_t *v_position)
598b8fdfcc6SHarry Wentland {
599b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
60072ada5f7SEric Cook 	struct crtc_position position;
601b8fdfcc6SHarry Wentland 
60281c50963SSylvia Tsai 	uint32_t v_blank_start_end = dm_read_reg_soc15(
603b8fdfcc6SHarry Wentland 			tg->ctx,
604b8fdfcc6SHarry Wentland 			mmCRTC0_CRTC_V_BLANK_START_END,
605b8fdfcc6SHarry Wentland 			tg110->offsets.crtc);
606b8fdfcc6SHarry Wentland 
60781c50963SSylvia Tsai 	*v_blank_start = get_reg_field_value(v_blank_start_end,
60881c50963SSylvia Tsai 					     CRTC0_CRTC_V_BLANK_START_END,
60981c50963SSylvia Tsai 					     CRTC_V_BLANK_START);
61081c50963SSylvia Tsai 	*v_blank_end = get_reg_field_value(v_blank_start_end,
61181c50963SSylvia Tsai 					   CRTC0_CRTC_V_BLANK_START_END,
61281c50963SSylvia Tsai 					   CRTC_V_BLANK_END);
613b8fdfcc6SHarry Wentland 
61472ada5f7SEric Cook 	dce120_timing_generator_get_crtc_position(
61572ada5f7SEric Cook 			tg, &position);
61672ada5f7SEric Cook 
61772ada5f7SEric Cook 	*h_position = position.horizontal_count;
61872ada5f7SEric Cook 	*v_position = position.vertical_count;
619b8fdfcc6SHarry Wentland }
620b8fdfcc6SHarry Wentland 
dce120_timing_generator_enable_advanced_request(struct timing_generator * tg,bool enable,const struct dc_crtc_timing * timing)621eea08ecbSLee Jones static void dce120_timing_generator_enable_advanced_request(
622b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
623b8fdfcc6SHarry Wentland 	bool enable,
624b8fdfcc6SHarry Wentland 	const struct dc_crtc_timing *timing)
625b8fdfcc6SHarry Wentland {
626b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
627b8fdfcc6SHarry Wentland 	uint32_t v_sync_width_and_b_porch =
628b8fdfcc6SHarry Wentland 				timing->v_total - timing->v_addressable -
629b8fdfcc6SHarry Wentland 				timing->v_border_bottom - timing->v_front_porch;
630b8fdfcc6SHarry Wentland 	uint32_t value = dm_read_reg_soc15(
631b8fdfcc6SHarry Wentland 				tg->ctx,
632b8fdfcc6SHarry Wentland 				mmCRTC0_CRTC_START_LINE_CONTROL,
633b8fdfcc6SHarry Wentland 				tg110->offsets.crtc);
634b8fdfcc6SHarry Wentland 
635b8fdfcc6SHarry Wentland 	set_reg_field_value(
636b8fdfcc6SHarry Wentland 		value,
637a4b0a5b8STom St Denis 		enable ? 0 : 1,
638b8fdfcc6SHarry Wentland 		CRTC0_CRTC_START_LINE_CONTROL,
639b8fdfcc6SHarry Wentland 		CRTC_LEGACY_REQUESTOR_EN);
640b8fdfcc6SHarry Wentland 
641b8fdfcc6SHarry Wentland 	/* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency
642b8fdfcc6SHarry Wentland 	 * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines)
643b8fdfcc6SHarry Wentland 	 */
644b8fdfcc6SHarry Wentland 	if (v_sync_width_and_b_porch > 10)
645a4b0a5b8STom St Denis 		v_sync_width_and_b_porch = 10;
646a4b0a5b8STom St Denis 
647b8fdfcc6SHarry Wentland 	set_reg_field_value(
648b8fdfcc6SHarry Wentland 		value,
649b8fdfcc6SHarry Wentland 		v_sync_width_and_b_porch,
650b8fdfcc6SHarry Wentland 		CRTC0_CRTC_START_LINE_CONTROL,
651b8fdfcc6SHarry Wentland 		CRTC_ADVANCED_START_LINE_POSITION);
652b8fdfcc6SHarry Wentland 
653b8fdfcc6SHarry Wentland 	dm_write_reg_soc15(tg->ctx,
654b8fdfcc6SHarry Wentland 			mmCRTC0_CRTC_START_LINE_CONTROL,
655b8fdfcc6SHarry Wentland 			tg110->offsets.crtc,
656b8fdfcc6SHarry Wentland 			value);
657b8fdfcc6SHarry Wentland }
658b8fdfcc6SHarry Wentland 
dce120_tg_program_blank_color(struct timing_generator * tg,const struct tg_color * black_color)659eea08ecbSLee Jones static void dce120_tg_program_blank_color(struct timing_generator *tg,
660b8fdfcc6SHarry Wentland 	const struct tg_color *black_color)
661b8fdfcc6SHarry Wentland {
662b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
663b8fdfcc6SHarry Wentland 	uint32_t value = 0;
664b8fdfcc6SHarry Wentland 
665b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_3(
666b8fdfcc6SHarry Wentland 		CRTC0_CRTC_BLACK_COLOR,
667b8fdfcc6SHarry Wentland 		CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
668b8fdfcc6SHarry Wentland 		CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
669b8fdfcc6SHarry Wentland 		CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
670b8fdfcc6SHarry Wentland 
671b8fdfcc6SHarry Wentland 	value = dm_read_reg_soc15(
672b8fdfcc6SHarry Wentland 				tg->ctx,
673b8fdfcc6SHarry Wentland 				mmCRTC0_CRTC_BLACK_COLOR,
674b8fdfcc6SHarry Wentland 				tg110->offsets.crtc);
675b8fdfcc6SHarry Wentland 	dm_write_reg_soc15(
676b8fdfcc6SHarry Wentland 		tg->ctx,
677b8fdfcc6SHarry Wentland 		mmCRTC0_CRTC_BLANK_DATA_COLOR,
678b8fdfcc6SHarry Wentland 		tg110->offsets.crtc,
679b8fdfcc6SHarry Wentland 		value);
680b8fdfcc6SHarry Wentland }
681b8fdfcc6SHarry Wentland 
dce120_tg_set_overscan_color(struct timing_generator * tg,const struct tg_color * overscan_color)682eea08ecbSLee Jones static void dce120_tg_set_overscan_color(struct timing_generator *tg,
683b8fdfcc6SHarry Wentland 	const struct tg_color *overscan_color)
684b8fdfcc6SHarry Wentland {
685b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
686b8fdfcc6SHarry Wentland 
687b8fdfcc6SHarry Wentland 	CRTC_REG_SET_3(
688b8fdfcc6SHarry Wentland 		CRTC0_CRTC_OVERSCAN_COLOR,
689b8fdfcc6SHarry Wentland 		CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb,
690b8fdfcc6SHarry Wentland 		CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y,
691b8fdfcc6SHarry Wentland 		CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr);
692b8fdfcc6SHarry Wentland }
693b8fdfcc6SHarry Wentland 
dce120_tg_program_timing(struct timing_generator * tg,const struct dc_crtc_timing * timing,int vready_offset,int vstartup_start,int vupdate_offset,int vupdate_width,const enum signal_type signal,bool use_vbios)694e7e10c46SDmytro Laktyushkin static void dce120_tg_program_timing(struct timing_generator *tg,
695b8fdfcc6SHarry Wentland 	const struct dc_crtc_timing *timing,
696e7e10c46SDmytro Laktyushkin 	int vready_offset,
697e7e10c46SDmytro Laktyushkin 	int vstartup_start,
698e7e10c46SDmytro Laktyushkin 	int vupdate_offset,
699e7e10c46SDmytro Laktyushkin 	int vupdate_width,
700e7e10c46SDmytro Laktyushkin 	const enum signal_type signal,
701b8fdfcc6SHarry Wentland 	bool use_vbios)
702b8fdfcc6SHarry Wentland {
703b8fdfcc6SHarry Wentland 	if (use_vbios)
704b8fdfcc6SHarry Wentland 		dce110_timing_generator_program_timing_generator(tg, timing);
705b8fdfcc6SHarry Wentland 	else
706b8fdfcc6SHarry Wentland 		dce120_timing_generator_program_blanking(tg, timing);
707b8fdfcc6SHarry Wentland }
708b8fdfcc6SHarry Wentland 
dce120_tg_is_blanked(struct timing_generator * tg)709eea08ecbSLee Jones static bool dce120_tg_is_blanked(struct timing_generator *tg)
710b8fdfcc6SHarry Wentland {
711b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
712b8fdfcc6SHarry Wentland 	uint32_t value = dm_read_reg_soc15(
713b8fdfcc6SHarry Wentland 			tg->ctx,
714b8fdfcc6SHarry Wentland 			mmCRTC0_CRTC_BLANK_CONTROL,
715b8fdfcc6SHarry Wentland 			tg110->offsets.crtc);
716b8fdfcc6SHarry Wentland 
7177b7d6865STom St Denis 	if (get_reg_field_value(
718b8fdfcc6SHarry Wentland 		value,
719b8fdfcc6SHarry Wentland 		CRTC0_CRTC_BLANK_CONTROL,
720b8fdfcc6SHarry Wentland 		CRTC_BLANK_DATA_EN) == 1 &&
721b8fdfcc6SHarry Wentland 	    get_reg_field_value(
722b8fdfcc6SHarry Wentland 		value,
723b8fdfcc6SHarry Wentland 		CRTC0_CRTC_BLANK_CONTROL,
724b8fdfcc6SHarry Wentland 		CRTC_CURRENT_BLANK_STATE) == 1)
725b8fdfcc6SHarry Wentland 			return true;
726b8fdfcc6SHarry Wentland 
727b8fdfcc6SHarry Wentland 	return false;
728b8fdfcc6SHarry Wentland }
729b8fdfcc6SHarry Wentland 
dce120_tg_set_blank(struct timing_generator * tg,bool enable_blanking)730eea08ecbSLee Jones static void dce120_tg_set_blank(struct timing_generator *tg,
731b8fdfcc6SHarry Wentland 		bool enable_blanking)
732b8fdfcc6SHarry Wentland {
733b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
734b8fdfcc6SHarry Wentland 
735b8fdfcc6SHarry Wentland 	CRTC_REG_SET(
736b8fdfcc6SHarry Wentland 		CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
7377cb52855SJerry (Fangzhi) Zuo 		CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 1);
738b8fdfcc6SHarry Wentland 
739cedaf307STom St Denis 	if (enable_blanking)
740cedaf307STom St Denis 		CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
741cedaf307STom St Denis 	else
742cedaf307STom St Denis 		dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
743cedaf307STom St Denis 			tg110->offsets.crtc, 0);
744b8fdfcc6SHarry Wentland }
745b8fdfcc6SHarry Wentland 
746b8fdfcc6SHarry Wentland bool dce120_tg_validate_timing(struct timing_generator *tg,
747b8fdfcc6SHarry Wentland 	const struct dc_crtc_timing *timing);
748b8fdfcc6SHarry Wentland 
dce120_tg_wait_for_state(struct timing_generator * tg,enum crtc_state state)749eea08ecbSLee Jones static void dce120_tg_wait_for_state(struct timing_generator *tg,
750b8fdfcc6SHarry Wentland 	enum crtc_state state)
751b8fdfcc6SHarry Wentland {
752b8fdfcc6SHarry Wentland 	switch (state) {
753b8fdfcc6SHarry Wentland 	case CRTC_STATE_VBLANK:
754b8fdfcc6SHarry Wentland 		dce120_timing_generator_wait_for_vblank(tg);
755b8fdfcc6SHarry Wentland 		break;
756b8fdfcc6SHarry Wentland 
757b8fdfcc6SHarry Wentland 	case CRTC_STATE_VACTIVE:
758b8fdfcc6SHarry Wentland 		dce120_timing_generator_wait_for_vactive(tg);
759b8fdfcc6SHarry Wentland 		break;
760b8fdfcc6SHarry Wentland 
761b8fdfcc6SHarry Wentland 	default:
762b8fdfcc6SHarry Wentland 		break;
763b8fdfcc6SHarry Wentland 	}
764b8fdfcc6SHarry Wentland }
765b8fdfcc6SHarry Wentland 
dce120_tg_set_colors(struct timing_generator * tg,const struct tg_color * blank_color,const struct tg_color * overscan_color)766eea08ecbSLee Jones static void dce120_tg_set_colors(struct timing_generator *tg,
767b8fdfcc6SHarry Wentland 	const struct tg_color *blank_color,
768b8fdfcc6SHarry Wentland 	const struct tg_color *overscan_color)
769b8fdfcc6SHarry Wentland {
770b8fdfcc6SHarry Wentland 	if (blank_color != NULL)
771b8fdfcc6SHarry Wentland 		dce120_tg_program_blank_color(tg, blank_color);
772b8fdfcc6SHarry Wentland 
773b8fdfcc6SHarry Wentland 	if (overscan_color != NULL)
774b8fdfcc6SHarry Wentland 		dce120_tg_set_overscan_color(tg, overscan_color);
775b8fdfcc6SHarry Wentland }
776b8fdfcc6SHarry Wentland 
dce120_timing_generator_set_static_screen_control(struct timing_generator * tg,uint32_t event_triggers,uint32_t num_frames)777b8fdfcc6SHarry Wentland static void dce120_timing_generator_set_static_screen_control(
778b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
7795b5abe95SAnthony Koo 	uint32_t event_triggers,
7805b5abe95SAnthony Koo 	uint32_t num_frames)
781b8fdfcc6SHarry Wentland {
782b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
783b8fdfcc6SHarry Wentland 
7845b5abe95SAnthony Koo 	// By register spec, it only takes 8 bit value
7855b5abe95SAnthony Koo 	if (num_frames > 0xFF)
7865b5abe95SAnthony Koo 		num_frames = 0xFF;
7875b5abe95SAnthony Koo 
788b8fdfcc6SHarry Wentland 	CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
7895b5abe95SAnthony Koo 			CRTC_STATIC_SCREEN_EVENT_MASK, event_triggers,
7905b5abe95SAnthony Koo 			CRTC_STATIC_SCREEN_FRAME_COUNT, num_frames);
791b8fdfcc6SHarry Wentland }
792b8fdfcc6SHarry Wentland 
dce120_timing_generator_set_test_pattern(struct timing_generator * tg,enum controller_dp_test_pattern test_pattern,enum dc_color_depth color_depth)793eea08ecbSLee Jones static void dce120_timing_generator_set_test_pattern(
794b8fdfcc6SHarry Wentland 	struct timing_generator *tg,
795b8fdfcc6SHarry Wentland 	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
796b8fdfcc6SHarry Wentland 	 * because this is not DP-specific (which is probably somewhere in DP
797b8fdfcc6SHarry Wentland 	 * encoder) */
798b8fdfcc6SHarry Wentland 	enum controller_dp_test_pattern test_pattern,
799b8fdfcc6SHarry Wentland 	enum dc_color_depth color_depth)
800b8fdfcc6SHarry Wentland {
801b8fdfcc6SHarry Wentland 	struct dc_context *ctx = tg->ctx;
802b8fdfcc6SHarry Wentland 	uint32_t value;
803b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
804b8fdfcc6SHarry Wentland 	enum test_pattern_color_format bit_depth;
805b8fdfcc6SHarry Wentland 	enum test_pattern_dyn_range dyn_range;
806b8fdfcc6SHarry Wentland 	enum test_pattern_mode mode;
807b8fdfcc6SHarry Wentland 	/* color ramp generator mixes 16-bits color */
808b8fdfcc6SHarry Wentland 	uint32_t src_bpc = 16;
809b8fdfcc6SHarry Wentland 	/* requested bpc */
810b8fdfcc6SHarry Wentland 	uint32_t dst_bpc;
811b8fdfcc6SHarry Wentland 	uint32_t index;
812b8fdfcc6SHarry Wentland 	/* RGB values of the color bars.
813b8fdfcc6SHarry Wentland 	 * Produce two RGB colors: RGB0 - white (all Fs)
814b8fdfcc6SHarry Wentland 	 * and RGB1 - black (all 0s)
815b8fdfcc6SHarry Wentland 	 * (three RGB components for two colors)
816b8fdfcc6SHarry Wentland 	 */
817b8fdfcc6SHarry Wentland 	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
818b8fdfcc6SHarry Wentland 						0x0000, 0x0000};
819b8fdfcc6SHarry Wentland 	/* dest color (converted to the specified color format) */
820b8fdfcc6SHarry Wentland 	uint16_t dst_color[6];
821b8fdfcc6SHarry Wentland 	uint32_t inc_base;
822b8fdfcc6SHarry Wentland 
823b8fdfcc6SHarry Wentland 	/* translate to bit depth */
824b8fdfcc6SHarry Wentland 	switch (color_depth) {
825b8fdfcc6SHarry Wentland 	case COLOR_DEPTH_666:
826b8fdfcc6SHarry Wentland 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
827b8fdfcc6SHarry Wentland 	break;
828b8fdfcc6SHarry Wentland 	case COLOR_DEPTH_888:
829b8fdfcc6SHarry Wentland 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
830b8fdfcc6SHarry Wentland 	break;
831b8fdfcc6SHarry Wentland 	case COLOR_DEPTH_101010:
832b8fdfcc6SHarry Wentland 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
833b8fdfcc6SHarry Wentland 	break;
834b8fdfcc6SHarry Wentland 	case COLOR_DEPTH_121212:
835b8fdfcc6SHarry Wentland 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
836b8fdfcc6SHarry Wentland 	break;
837b8fdfcc6SHarry Wentland 	default:
838b8fdfcc6SHarry Wentland 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
839b8fdfcc6SHarry Wentland 	break;
840b8fdfcc6SHarry Wentland 	}
841b8fdfcc6SHarry Wentland 
842b8fdfcc6SHarry Wentland 	switch (test_pattern) {
843b8fdfcc6SHarry Wentland 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
844b8fdfcc6SHarry Wentland 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
845b8fdfcc6SHarry Wentland 	{
846b8fdfcc6SHarry Wentland 		dyn_range = (test_pattern ==
847b8fdfcc6SHarry Wentland 				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
848b8fdfcc6SHarry Wentland 				TEST_PATTERN_DYN_RANGE_CEA :
849b8fdfcc6SHarry Wentland 				TEST_PATTERN_DYN_RANGE_VESA);
850b8fdfcc6SHarry Wentland 		mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
851b8fdfcc6SHarry Wentland 
852b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
853b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_VRES, 6,
854b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_HRES, 6);
855b8fdfcc6SHarry Wentland 
856b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
857b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_EN, 1,
858b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_MODE, mode,
859b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
860b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
861b8fdfcc6SHarry Wentland 	}
862b8fdfcc6SHarry Wentland 	break;
863b8fdfcc6SHarry Wentland 
864b8fdfcc6SHarry Wentland 	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
865b8fdfcc6SHarry Wentland 	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
866b8fdfcc6SHarry Wentland 	{
867b8fdfcc6SHarry Wentland 		mode = (test_pattern ==
868b8fdfcc6SHarry Wentland 			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
869b8fdfcc6SHarry Wentland 			TEST_PATTERN_MODE_VERTICALBARS :
870b8fdfcc6SHarry Wentland 			TEST_PATTERN_MODE_HORIZONTALBARS);
871b8fdfcc6SHarry Wentland 
872b8fdfcc6SHarry Wentland 		switch (bit_depth) {
873b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
874b8fdfcc6SHarry Wentland 			dst_bpc = 6;
875b8fdfcc6SHarry Wentland 		break;
876b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
877b8fdfcc6SHarry Wentland 			dst_bpc = 8;
878b8fdfcc6SHarry Wentland 		break;
879b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
880b8fdfcc6SHarry Wentland 			dst_bpc = 10;
881b8fdfcc6SHarry Wentland 		break;
882b8fdfcc6SHarry Wentland 		default:
883b8fdfcc6SHarry Wentland 			dst_bpc = 8;
884b8fdfcc6SHarry Wentland 		break;
885b8fdfcc6SHarry Wentland 		}
886b8fdfcc6SHarry Wentland 
887b8fdfcc6SHarry Wentland 		/* adjust color to the required colorFormat */
888b8fdfcc6SHarry Wentland 		for (index = 0; index < 6; index++) {
889b8fdfcc6SHarry Wentland 			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
890b8fdfcc6SHarry Wentland 			 * (srcBpc - dstBpc);
891b8fdfcc6SHarry Wentland 			 */
892b8fdfcc6SHarry Wentland 			dst_color[index] =
893b8fdfcc6SHarry Wentland 				src_color[index] >> (src_bpc - dst_bpc);
894b8fdfcc6SHarry Wentland 		/* CRTC_TEST_PATTERN_DATA has 16 bits,
895b8fdfcc6SHarry Wentland 		 * lowest 6 are hardwired to ZERO
896b8fdfcc6SHarry Wentland 		 * color bits should be left aligned aligned to MSB
897b8fdfcc6SHarry Wentland 		 * XXXXXXXXXX000000 for 10 bit,
898b8fdfcc6SHarry Wentland 		 * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
899b8fdfcc6SHarry Wentland 		 */
900b8fdfcc6SHarry Wentland 			dst_color[index] <<= (16 - dst_bpc);
901b8fdfcc6SHarry Wentland 		}
902b8fdfcc6SHarry Wentland 
903b8fdfcc6SHarry Wentland 		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
904b8fdfcc6SHarry Wentland 
905b8fdfcc6SHarry Wentland 		/* We have to write the mask before data, similar to pipeline.
906b8fdfcc6SHarry Wentland 		 * For example, for 8 bpc, if we want RGB0 to be magenta,
907b8fdfcc6SHarry Wentland 		 * and RGB1 to be cyan,
908b8fdfcc6SHarry Wentland 		 * we need to make 7 writes:
909b8fdfcc6SHarry Wentland 		 * MASK   DATA
910b8fdfcc6SHarry Wentland 		 * 000001 00000000 00000000                     set mask to R0
911b8fdfcc6SHarry Wentland 		 * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
912b8fdfcc6SHarry Wentland 		 * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
913b8fdfcc6SHarry Wentland 		 * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
914b8fdfcc6SHarry Wentland 		 * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
915b8fdfcc6SHarry Wentland 		 * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
916b8fdfcc6SHarry Wentland 		 * 100000 11111111 00000000     B1 255, 0xFF00
917b8fdfcc6SHarry Wentland 		 *
918b8fdfcc6SHarry Wentland 		 * we will make a loop of 6 in which we prepare the mask,
919b8fdfcc6SHarry Wentland 		 * then write, then prepare the color for next write.
920b8fdfcc6SHarry Wentland 		 * first iteration will write mask only,
921b8fdfcc6SHarry Wentland 		 * but each next iteration color prepared in
922b8fdfcc6SHarry Wentland 		 * previous iteration will be written within new mask,
923b8fdfcc6SHarry Wentland 		 * the last component will written separately,
924b8fdfcc6SHarry Wentland 		 * mask is not changing between 6th and 7th write
925b8fdfcc6SHarry Wentland 		 * and color will be prepared by last iteration
926b8fdfcc6SHarry Wentland 		 */
927b8fdfcc6SHarry Wentland 
928b8fdfcc6SHarry Wentland 		/* write color, color values mask in CRTC_TEST_PATTERN_MASK
929b8fdfcc6SHarry Wentland 		 * is B1, G1, R1, B0, G0, R0
930b8fdfcc6SHarry Wentland 		 */
931b8fdfcc6SHarry Wentland 		value = 0;
932b8fdfcc6SHarry Wentland 		for (index = 0; index < 6; index++) {
933b8fdfcc6SHarry Wentland 			/* prepare color mask, first write PATTERN_DATA
934b8fdfcc6SHarry Wentland 			 * will have all zeros
935b8fdfcc6SHarry Wentland 			 */
936b8fdfcc6SHarry Wentland 			set_reg_field_value(
937b8fdfcc6SHarry Wentland 				value,
938b8fdfcc6SHarry Wentland 				(1 << index),
939b8fdfcc6SHarry Wentland 				CRTC0_CRTC_TEST_PATTERN_COLOR,
940b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_MASK);
941b8fdfcc6SHarry Wentland 			/* write color component */
942b8fdfcc6SHarry Wentland 			dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
943b8fdfcc6SHarry Wentland 			/* prepare next color component,
944b8fdfcc6SHarry Wentland 			 * will be written in the next iteration
945b8fdfcc6SHarry Wentland 			 */
946b8fdfcc6SHarry Wentland 			set_reg_field_value(
947b8fdfcc6SHarry Wentland 				value,
948b8fdfcc6SHarry Wentland 				dst_color[index],
949b8fdfcc6SHarry Wentland 				CRTC0_CRTC_TEST_PATTERN_COLOR,
950b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_DATA);
951b8fdfcc6SHarry Wentland 		}
952b8fdfcc6SHarry Wentland 		/* write last color component,
953b8fdfcc6SHarry Wentland 		 * it's been already prepared in the loop
954b8fdfcc6SHarry Wentland 		 */
955b8fdfcc6SHarry Wentland 		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
956b8fdfcc6SHarry Wentland 
957b8fdfcc6SHarry Wentland 		/* enable test pattern */
958b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
959b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_EN, 1,
960b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_MODE, mode,
961b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
962b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
963b8fdfcc6SHarry Wentland 	}
964b8fdfcc6SHarry Wentland 	break;
965b8fdfcc6SHarry Wentland 
966b8fdfcc6SHarry Wentland 	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
967b8fdfcc6SHarry Wentland 	{
968b8fdfcc6SHarry Wentland 		mode = (bit_depth ==
969b8fdfcc6SHarry Wentland 			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
970b8fdfcc6SHarry Wentland 			TEST_PATTERN_MODE_DUALRAMP_RGB :
971b8fdfcc6SHarry Wentland 			TEST_PATTERN_MODE_SINGLERAMP_RGB);
972b8fdfcc6SHarry Wentland 
973b8fdfcc6SHarry Wentland 		switch (bit_depth) {
974b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
975b8fdfcc6SHarry Wentland 			dst_bpc = 6;
976b8fdfcc6SHarry Wentland 		break;
977b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
978b8fdfcc6SHarry Wentland 			dst_bpc = 8;
979b8fdfcc6SHarry Wentland 		break;
980b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
981b8fdfcc6SHarry Wentland 			dst_bpc = 10;
982b8fdfcc6SHarry Wentland 		break;
983b8fdfcc6SHarry Wentland 		default:
984b8fdfcc6SHarry Wentland 			dst_bpc = 8;
985b8fdfcc6SHarry Wentland 		break;
986b8fdfcc6SHarry Wentland 		}
987b8fdfcc6SHarry Wentland 
988b8fdfcc6SHarry Wentland 		/* increment for the first ramp for one color gradation
989b8fdfcc6SHarry Wentland 		 * 1 gradation for 6-bit color is 2^10
990b8fdfcc6SHarry Wentland 		 * gradations in 16-bit color
991b8fdfcc6SHarry Wentland 		 */
992b8fdfcc6SHarry Wentland 		inc_base = (src_bpc - dst_bpc);
993b8fdfcc6SHarry Wentland 
994b8fdfcc6SHarry Wentland 		switch (bit_depth) {
995b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
996b8fdfcc6SHarry Wentland 		{
997b8fdfcc6SHarry Wentland 			CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
998b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_INC0, inc_base,
999b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_INC1, 0,
1000b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_HRES, 6,
1001b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_VRES, 6,
1002b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1003b8fdfcc6SHarry Wentland 		}
1004b8fdfcc6SHarry Wentland 		break;
1005b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1006b8fdfcc6SHarry Wentland 		{
1007b8fdfcc6SHarry Wentland 			CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1008b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_INC0, inc_base,
1009b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_INC1, 0,
1010b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_HRES, 8,
1011b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_VRES, 6,
1012b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1013b8fdfcc6SHarry Wentland 		}
1014b8fdfcc6SHarry Wentland 		break;
1015b8fdfcc6SHarry Wentland 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1016b8fdfcc6SHarry Wentland 		{
1017b8fdfcc6SHarry Wentland 			CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1018b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_INC0, inc_base,
1019b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_INC1, inc_base + 2,
1020b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_HRES, 8,
1021b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_VRES, 5,
1022b8fdfcc6SHarry Wentland 					CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1023b8fdfcc6SHarry Wentland 		}
1024b8fdfcc6SHarry Wentland 		break;
1025b8fdfcc6SHarry Wentland 		default:
1026b8fdfcc6SHarry Wentland 		break;
1027b8fdfcc6SHarry Wentland 		}
1028b8fdfcc6SHarry Wentland 
1029b8fdfcc6SHarry Wentland 		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1030b8fdfcc6SHarry Wentland 
1031b8fdfcc6SHarry Wentland 		/* enable test pattern */
1032b8fdfcc6SHarry Wentland 		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1033b8fdfcc6SHarry Wentland 
1034b8fdfcc6SHarry Wentland 		CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1035b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_EN, 1,
1036b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_MODE, mode,
1037b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1038b8fdfcc6SHarry Wentland 				CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1039b8fdfcc6SHarry Wentland 	}
1040b8fdfcc6SHarry Wentland 	break;
1041b8fdfcc6SHarry Wentland 	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1042b8fdfcc6SHarry Wentland 	{
1043b8fdfcc6SHarry Wentland 		value = 0;
1044b8fdfcc6SHarry Wentland 		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1045b8fdfcc6SHarry Wentland 		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1046b8fdfcc6SHarry Wentland 		dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1047b8fdfcc6SHarry Wentland 	}
1048b8fdfcc6SHarry Wentland 	break;
1049b8fdfcc6SHarry Wentland 	default:
1050b8fdfcc6SHarry Wentland 	break;
1051b8fdfcc6SHarry Wentland 	}
1052b8fdfcc6SHarry Wentland }
1053b8fdfcc6SHarry Wentland 
dce120_arm_vert_intr(struct timing_generator * tg,uint8_t width)1054667e1498SAndrey Grodzovsky static bool dce120_arm_vert_intr(
1055667e1498SAndrey Grodzovsky 		struct timing_generator *tg,
1056667e1498SAndrey Grodzovsky 		uint8_t width)
1057667e1498SAndrey Grodzovsky {
1058667e1498SAndrey Grodzovsky 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
105981c50963SSylvia Tsai 	uint32_t v_blank_start, v_blank_end, h_position, v_position;
1060667e1498SAndrey Grodzovsky 
1061667e1498SAndrey Grodzovsky 	tg->funcs->get_scanoutpos(
1062667e1498SAndrey Grodzovsky 				tg,
106381c50963SSylvia Tsai 				&v_blank_start,
106481c50963SSylvia Tsai 				&v_blank_end,
106581c50963SSylvia Tsai 				&h_position,
106681c50963SSylvia Tsai 				&v_position);
1067667e1498SAndrey Grodzovsky 
106881c50963SSylvia Tsai 	if (v_blank_start == 0 || v_blank_end == 0)
1069667e1498SAndrey Grodzovsky 		return false;
1070667e1498SAndrey Grodzovsky 
1071667e1498SAndrey Grodzovsky 	CRTC_REG_SET_2(
1072667e1498SAndrey Grodzovsky 			CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
107381c50963SSylvia Tsai 			CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
107481c50963SSylvia Tsai 			CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1075667e1498SAndrey Grodzovsky 
1076667e1498SAndrey Grodzovsky 	return true;
1077667e1498SAndrey Grodzovsky }
1078667e1498SAndrey Grodzovsky 
10790880d9ffSNicholas Kazlauskas 
dce120_is_tg_enabled(struct timing_generator * tg)10800880d9ffSNicholas Kazlauskas static bool dce120_is_tg_enabled(struct timing_generator *tg)
10810880d9ffSNicholas Kazlauskas {
10820880d9ffSNicholas Kazlauskas 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
10830880d9ffSNicholas Kazlauskas 	uint32_t value, field;
10840880d9ffSNicholas Kazlauskas 
10850880d9ffSNicholas Kazlauskas 	value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
10860880d9ffSNicholas Kazlauskas 				  tg110->offsets.crtc);
10870880d9ffSNicholas Kazlauskas 	field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
10880880d9ffSNicholas Kazlauskas 				    CRTC_CURRENT_MASTER_EN_STATE);
10890880d9ffSNicholas Kazlauskas 
10900880d9ffSNicholas Kazlauskas 	return field == 1;
10910880d9ffSNicholas Kazlauskas }
10920880d9ffSNicholas Kazlauskas 
dce120_configure_crc(struct timing_generator * tg,const struct crc_params * params)10930880d9ffSNicholas Kazlauskas static bool dce120_configure_crc(struct timing_generator *tg,
10940880d9ffSNicholas Kazlauskas 				 const struct crc_params *params)
10950880d9ffSNicholas Kazlauskas {
10960880d9ffSNicholas Kazlauskas 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
10970880d9ffSNicholas Kazlauskas 
10980880d9ffSNicholas Kazlauskas 	/* Cannot configure crc on a CRTC that is disabled */
10990880d9ffSNicholas Kazlauskas 	if (!dce120_is_tg_enabled(tg))
11000880d9ffSNicholas Kazlauskas 		return false;
11010880d9ffSNicholas Kazlauskas 
11020880d9ffSNicholas Kazlauskas 	/* First, disable CRC before we configure it. */
11030880d9ffSNicholas Kazlauskas 	dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
11040880d9ffSNicholas Kazlauskas 			   tg110->offsets.crtc, 0);
11050880d9ffSNicholas Kazlauskas 
11060880d9ffSNicholas Kazlauskas 	if (!params->enable)
11070880d9ffSNicholas Kazlauskas 		return true;
11080880d9ffSNicholas Kazlauskas 
11090880d9ffSNicholas Kazlauskas 	/* Program frame boundaries */
11100880d9ffSNicholas Kazlauskas 	/* Window A x axis start and end. */
11110880d9ffSNicholas Kazlauskas 	CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
11120880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
11130880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
11140880d9ffSNicholas Kazlauskas 
11150880d9ffSNicholas Kazlauskas 	/* Window A y axis start and end. */
11160880d9ffSNicholas Kazlauskas 	CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
11170880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
11180880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
11190880d9ffSNicholas Kazlauskas 
11200880d9ffSNicholas Kazlauskas 	/* Window B x axis start and end. */
11210880d9ffSNicholas Kazlauskas 	CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
11220880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
11230880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
11240880d9ffSNicholas Kazlauskas 
11250880d9ffSNicholas Kazlauskas 	/* Window B y axis start and end. */
11260880d9ffSNicholas Kazlauskas 	CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
11270880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
11280880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
11290880d9ffSNicholas Kazlauskas 
11300880d9ffSNicholas Kazlauskas 	/* Set crc mode and selection, and enable. Only using CRC0*/
11310880d9ffSNicholas Kazlauskas 	CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
11320880d9ffSNicholas Kazlauskas 			  CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
11330880d9ffSNicholas Kazlauskas 			  CRTC_CRC0_SELECT, params->selection,
11340880d9ffSNicholas Kazlauskas 			  CRTC_CRC_EN, 1);
11350880d9ffSNicholas Kazlauskas 
11360880d9ffSNicholas Kazlauskas 	return true;
11370880d9ffSNicholas Kazlauskas }
11380880d9ffSNicholas Kazlauskas 
dce120_get_crc(struct timing_generator * tg,uint32_t * r_cr,uint32_t * g_y,uint32_t * b_cb)11390880d9ffSNicholas Kazlauskas static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
11400880d9ffSNicholas Kazlauskas 			   uint32_t *g_y, uint32_t *b_cb)
11410880d9ffSNicholas Kazlauskas {
11420880d9ffSNicholas Kazlauskas 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
11430880d9ffSNicholas Kazlauskas 	uint32_t value, field;
11440880d9ffSNicholas Kazlauskas 
11450880d9ffSNicholas Kazlauskas 	value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
11460880d9ffSNicholas Kazlauskas 				  tg110->offsets.crtc);
11470880d9ffSNicholas Kazlauskas 	field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
11480880d9ffSNicholas Kazlauskas 
11490880d9ffSNicholas Kazlauskas 	/* Early return if CRC is not enabled for this CRTC */
11500880d9ffSNicholas Kazlauskas 	if (!field)
11510880d9ffSNicholas Kazlauskas 		return false;
11520880d9ffSNicholas Kazlauskas 
11530880d9ffSNicholas Kazlauskas 	value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
11540880d9ffSNicholas Kazlauskas 				  tg110->offsets.crtc);
11550880d9ffSNicholas Kazlauskas 	*r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
11560880d9ffSNicholas Kazlauskas 	*g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
11570880d9ffSNicholas Kazlauskas 
11580880d9ffSNicholas Kazlauskas 	value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
11590880d9ffSNicholas Kazlauskas 				  tg110->offsets.crtc);
11600880d9ffSNicholas Kazlauskas 	*b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
11610880d9ffSNicholas Kazlauskas 
11620880d9ffSNicholas Kazlauskas 	return true;
11630880d9ffSNicholas Kazlauskas }
11640880d9ffSNicholas Kazlauskas 
1165395f669eSDave Airlie static const struct timing_generator_funcs dce120_tg_funcs = {
1166b8fdfcc6SHarry Wentland 		.validate_timing = dce120_tg_validate_timing,
1167b8fdfcc6SHarry Wentland 		.program_timing = dce120_tg_program_timing,
1168b8fdfcc6SHarry Wentland 		.enable_crtc = dce120_timing_generator_enable_crtc,
1169b8fdfcc6SHarry Wentland 		.disable_crtc = dce110_timing_generator_disable_crtc,
1170b8fdfcc6SHarry Wentland 		/* used by enable_timing_synchronization. Not need for FPGA */
1171b8fdfcc6SHarry Wentland 		.is_counter_moving = dce110_timing_generator_is_counter_moving,
1172b8fdfcc6SHarry Wentland 		/* never be called */
117372ada5f7SEric Cook 		.get_position = dce120_timing_generator_get_crtc_position,
1174b8fdfcc6SHarry Wentland 		.get_frame_count = dce120_timing_generator_get_vblank_counter,
1175b8fdfcc6SHarry Wentland 		.get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1176b8fdfcc6SHarry Wentland 		.set_early_control = dce120_timing_generator_set_early_control,
1177b8fdfcc6SHarry Wentland 		/* used by enable_timing_synchronization. Not need for FPGA */
1178b8fdfcc6SHarry Wentland 		.wait_for_state = dce120_tg_wait_for_state,
1179b8fdfcc6SHarry Wentland 		.set_blank = dce120_tg_set_blank,
1180b8fdfcc6SHarry Wentland 		.is_blanked = dce120_tg_is_blanked,
1181b8fdfcc6SHarry Wentland 		/* never be called */
1182b8fdfcc6SHarry Wentland 		.set_colors = dce120_tg_set_colors,
1183b8fdfcc6SHarry Wentland 		.set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1184b8fdfcc6SHarry Wentland 		.set_blank_color = dce120_timing_generator_program_blank_color,
1185b8fdfcc6SHarry Wentland 		.disable_vga = dce120_timing_generator_disable_vga,
1186b8fdfcc6SHarry Wentland 		.did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1187b8fdfcc6SHarry Wentland 		.setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1188b8fdfcc6SHarry Wentland 		.enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1189b8fdfcc6SHarry Wentland 		.disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1190b8fdfcc6SHarry Wentland 		.tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1191b8fdfcc6SHarry Wentland 		.enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1192b8fdfcc6SHarry Wentland 		.set_drr = dce120_timing_generator_set_drr,
1193*5c69cc55SJayendran Ramani 		.get_last_used_drr_vtotal = NULL,
1194b8fdfcc6SHarry Wentland 		.set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1195667e1498SAndrey Grodzovsky 		.set_test_pattern = dce120_timing_generator_set_test_pattern,
1196667e1498SAndrey Grodzovsky 		.arm_vert_intr = dce120_arm_vert_intr,
11970880d9ffSNicholas Kazlauskas 		.is_tg_enabled = dce120_is_tg_enabled,
11980880d9ffSNicholas Kazlauskas 		.configure_crc = dce120_configure_crc,
11990880d9ffSNicholas Kazlauskas 		.get_crc = dce120_get_crc,
1200b8fdfcc6SHarry Wentland };
1201b8fdfcc6SHarry Wentland 
1202b8fdfcc6SHarry Wentland 
dce120_timing_generator_construct(struct dce110_timing_generator * tg110,struct dc_context * ctx,uint32_t instance,const struct dce110_timing_generator_offsets * offsets)1203c13b408bSDave Airlie void dce120_timing_generator_construct(
1204b8fdfcc6SHarry Wentland 	struct dce110_timing_generator *tg110,
1205b8fdfcc6SHarry Wentland 	struct dc_context *ctx,
1206b8fdfcc6SHarry Wentland 	uint32_t instance,
1207b8fdfcc6SHarry Wentland 	const struct dce110_timing_generator_offsets *offsets)
1208b8fdfcc6SHarry Wentland {
1209b8fdfcc6SHarry Wentland 	tg110->controller_id = CONTROLLER_ID_D0 + instance;
1210b8fdfcc6SHarry Wentland 	tg110->base.inst = instance;
1211b8fdfcc6SHarry Wentland 
1212b8fdfcc6SHarry Wentland 	tg110->offsets = *offsets;
1213b8fdfcc6SHarry Wentland 
1214b8fdfcc6SHarry Wentland 	tg110->base.funcs = &dce120_tg_funcs;
1215b8fdfcc6SHarry Wentland 
1216b8fdfcc6SHarry Wentland 	tg110->base.ctx = ctx;
1217b8fdfcc6SHarry Wentland 	tg110->base.bp = ctx->dc_bios;
1218b8fdfcc6SHarry Wentland 
1219b8fdfcc6SHarry Wentland 	tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1220b8fdfcc6SHarry Wentland 	tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1221b8fdfcc6SHarry Wentland 
1222b8fdfcc6SHarry Wentland 	/*//CRTC requires a minimum HBLANK = 32 pixels and o
1223b8fdfcc6SHarry Wentland 	 * Minimum HSYNC = 8 pixels*/
1224b8fdfcc6SHarry Wentland 	tg110->min_h_blank = 32;
1225b8fdfcc6SHarry Wentland 	/*DCE12_CRTC_Block_ARch.doc*/
1226b8fdfcc6SHarry Wentland 	tg110->min_h_front_porch = 0;
1227b8fdfcc6SHarry Wentland 	tg110->min_h_back_porch = 0;
1228b8fdfcc6SHarry Wentland 
1229570b302bSAric Cyr 	tg110->min_h_sync_width = 4;
1230b8fdfcc6SHarry Wentland 	tg110->min_v_sync_width = 1;
1231b8fdfcc6SHarry Wentland 	tg110->min_v_blank = 3;
1232b8fdfcc6SHarry Wentland }
1233