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