1*b843c749SSergey Zigachev /*
2*b843c749SSergey Zigachev  * Copyright 2016 Advanced Micro Devices, Inc.
3*b843c749SSergey Zigachev  *
4*b843c749SSergey Zigachev  * Permission is hereby granted, free of charge, to any person obtaining a
5*b843c749SSergey Zigachev  * copy of this software and associated documentation files (the "Software"),
6*b843c749SSergey Zigachev  * to deal in the Software without restriction, including without limitation
7*b843c749SSergey Zigachev  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*b843c749SSergey Zigachev  * and/or sell copies of the Software, and to permit persons to whom the
9*b843c749SSergey Zigachev  * Software is furnished to do so, subject to the following conditions:
10*b843c749SSergey Zigachev  *
11*b843c749SSergey Zigachev  * The above copyright notice and this permission notice shall be included in
12*b843c749SSergey Zigachev  * all copies or substantial portions of the Software.
13*b843c749SSergey Zigachev  *
14*b843c749SSergey Zigachev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*b843c749SSergey Zigachev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*b843c749SSergey Zigachev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*b843c749SSergey Zigachev  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*b843c749SSergey Zigachev  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*b843c749SSergey Zigachev  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*b843c749SSergey Zigachev  * OTHER DEALINGS IN THE SOFTWARE.
21*b843c749SSergey Zigachev  *
22*b843c749SSergey Zigachev  * Authors: AMD
23*b843c749SSergey Zigachev  *
24*b843c749SSergey Zigachev  */
25*b843c749SSergey Zigachev 
26*b843c749SSergey Zigachev #include "dce_mem_input.h"
27*b843c749SSergey Zigachev #include "reg_helper.h"
28*b843c749SSergey Zigachev #include "basics/conversion.h"
29*b843c749SSergey Zigachev 
30*b843c749SSergey Zigachev #define CTX \
31*b843c749SSergey Zigachev 	dce_mi->base.ctx
32*b843c749SSergey Zigachev #define REG(reg)\
33*b843c749SSergey Zigachev 	dce_mi->regs->reg
34*b843c749SSergey Zigachev 
35*b843c749SSergey Zigachev #undef FN
36*b843c749SSergey Zigachev #define FN(reg_name, field_name) \
37*b843c749SSergey Zigachev 	dce_mi->shifts->field_name, dce_mi->masks->field_name
38*b843c749SSergey Zigachev 
39*b843c749SSergey Zigachev struct pte_setting {
40*b843c749SSergey Zigachev 	unsigned int bpp;
41*b843c749SSergey Zigachev 	unsigned int page_width;
42*b843c749SSergey Zigachev 	unsigned int page_height;
43*b843c749SSergey Zigachev 	unsigned char min_pte_before_flip_horiz_scan;
44*b843c749SSergey Zigachev 	unsigned char min_pte_before_flip_vert_scan;
45*b843c749SSergey Zigachev 	unsigned char pte_req_per_chunk;
46*b843c749SSergey Zigachev 	unsigned char param_6;
47*b843c749SSergey Zigachev 	unsigned char param_7;
48*b843c749SSergey Zigachev 	unsigned char param_8;
49*b843c749SSergey Zigachev };
50*b843c749SSergey Zigachev 
51*b843c749SSergey Zigachev enum mi_bits_per_pixel {
52*b843c749SSergey Zigachev 	mi_bpp_8 = 0,
53*b843c749SSergey Zigachev 	mi_bpp_16,
54*b843c749SSergey Zigachev 	mi_bpp_32,
55*b843c749SSergey Zigachev 	mi_bpp_64,
56*b843c749SSergey Zigachev 	mi_bpp_count,
57*b843c749SSergey Zigachev };
58*b843c749SSergey Zigachev 
59*b843c749SSergey Zigachev enum mi_tiling_format {
60*b843c749SSergey Zigachev 	mi_tiling_linear = 0,
61*b843c749SSergey Zigachev 	mi_tiling_1D,
62*b843c749SSergey Zigachev 	mi_tiling_2D,
63*b843c749SSergey Zigachev 	mi_tiling_count,
64*b843c749SSergey Zigachev };
65*b843c749SSergey Zigachev 
66*b843c749SSergey Zigachev static const struct pte_setting pte_settings[mi_tiling_count][mi_bpp_count] = {
67*b843c749SSergey Zigachev 	[mi_tiling_linear] = {
68*b843c749SSergey Zigachev 		{  8, 4096, 1, 8, 0, 1, 0, 0, 0},
69*b843c749SSergey Zigachev 		{ 16, 2048, 1, 8, 0, 1, 0, 0, 0},
70*b843c749SSergey Zigachev 		{ 32, 1024, 1, 8, 0, 1, 0, 0, 0},
71*b843c749SSergey Zigachev 		{ 64,  512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
72*b843c749SSergey Zigachev 	},
73*b843c749SSergey Zigachev 	[mi_tiling_1D] = {
74*b843c749SSergey Zigachev 		{  8, 512, 8, 1, 0, 1, 0, 0, 0},  /* 0 for invalid */
75*b843c749SSergey Zigachev 		{ 16, 256, 8, 2, 0, 1, 0, 0, 0},
76*b843c749SSergey Zigachev 		{ 32, 128, 8, 4, 0, 1, 0, 0, 0},
77*b843c749SSergey Zigachev 		{ 64,  64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
78*b843c749SSergey Zigachev 	},
79*b843c749SSergey Zigachev 	[mi_tiling_2D] = {
80*b843c749SSergey Zigachev 		{  8, 64, 64,  8,  8, 1, 4, 0, 0},
81*b843c749SSergey Zigachev 		{ 16, 64, 32,  8, 16, 1, 8, 0, 0},
82*b843c749SSergey Zigachev 		{ 32, 32, 32, 16, 16, 1, 8, 0, 0},
83*b843c749SSergey Zigachev 		{ 64,  8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
84*b843c749SSergey Zigachev 	},
85*b843c749SSergey Zigachev };
86*b843c749SSergey Zigachev 
get_mi_bpp(enum surface_pixel_format format)87*b843c749SSergey Zigachev static enum mi_bits_per_pixel get_mi_bpp(
88*b843c749SSergey Zigachev 		enum surface_pixel_format format)
89*b843c749SSergey Zigachev {
90*b843c749SSergey Zigachev 	if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
91*b843c749SSergey Zigachev 		return mi_bpp_64;
92*b843c749SSergey Zigachev 	else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888)
93*b843c749SSergey Zigachev 		return mi_bpp_32;
94*b843c749SSergey Zigachev 	else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555)
95*b843c749SSergey Zigachev 		return mi_bpp_16;
96*b843c749SSergey Zigachev 	else
97*b843c749SSergey Zigachev 		return mi_bpp_8;
98*b843c749SSergey Zigachev }
99*b843c749SSergey Zigachev 
get_mi_tiling(union dc_tiling_info * tiling_info)100*b843c749SSergey Zigachev static enum mi_tiling_format get_mi_tiling(
101*b843c749SSergey Zigachev 		union dc_tiling_info *tiling_info)
102*b843c749SSergey Zigachev {
103*b843c749SSergey Zigachev 	switch (tiling_info->gfx8.array_mode) {
104*b843c749SSergey Zigachev 	case DC_ARRAY_1D_TILED_THIN1:
105*b843c749SSergey Zigachev 	case DC_ARRAY_1D_TILED_THICK:
106*b843c749SSergey Zigachev 	case DC_ARRAY_PRT_TILED_THIN1:
107*b843c749SSergey Zigachev 		return mi_tiling_1D;
108*b843c749SSergey Zigachev 	case DC_ARRAY_2D_TILED_THIN1:
109*b843c749SSergey Zigachev 	case DC_ARRAY_2D_TILED_THICK:
110*b843c749SSergey Zigachev 	case DC_ARRAY_2D_TILED_X_THICK:
111*b843c749SSergey Zigachev 	case DC_ARRAY_PRT_2D_TILED_THIN1:
112*b843c749SSergey Zigachev 	case DC_ARRAY_PRT_2D_TILED_THICK:
113*b843c749SSergey Zigachev 		return mi_tiling_2D;
114*b843c749SSergey Zigachev 	case DC_ARRAY_LINEAR_GENERAL:
115*b843c749SSergey Zigachev 	case DC_ARRAY_LINEAR_ALLIGNED:
116*b843c749SSergey Zigachev 		return mi_tiling_linear;
117*b843c749SSergey Zigachev 	default:
118*b843c749SSergey Zigachev 		return mi_tiling_2D;
119*b843c749SSergey Zigachev 	}
120*b843c749SSergey Zigachev }
121*b843c749SSergey Zigachev 
is_vert_scan(enum dc_rotation_angle rotation)122*b843c749SSergey Zigachev static bool is_vert_scan(enum dc_rotation_angle rotation)
123*b843c749SSergey Zigachev {
124*b843c749SSergey Zigachev 	switch (rotation) {
125*b843c749SSergey Zigachev 	case ROTATION_ANGLE_90:
126*b843c749SSergey Zigachev 	case ROTATION_ANGLE_270:
127*b843c749SSergey Zigachev 		return true;
128*b843c749SSergey Zigachev 	default:
129*b843c749SSergey Zigachev 		return false;
130*b843c749SSergey Zigachev 	}
131*b843c749SSergey Zigachev }
132*b843c749SSergey Zigachev 
dce_mi_program_pte_vm(struct mem_input * mi,enum surface_pixel_format format,union dc_tiling_info * tiling_info,enum dc_rotation_angle rotation)133*b843c749SSergey Zigachev static void dce_mi_program_pte_vm(
134*b843c749SSergey Zigachev 		struct mem_input *mi,
135*b843c749SSergey Zigachev 		enum surface_pixel_format format,
136*b843c749SSergey Zigachev 		union dc_tiling_info *tiling_info,
137*b843c749SSergey Zigachev 		enum dc_rotation_angle rotation)
138*b843c749SSergey Zigachev {
139*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
140*b843c749SSergey Zigachev 	enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format);
141*b843c749SSergey Zigachev 	enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info);
142*b843c749SSergey Zigachev 	const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp];
143*b843c749SSergey Zigachev 
144*b843c749SSergey Zigachev 	unsigned int page_width = log_2(pte->page_width);
145*b843c749SSergey Zigachev 	unsigned int page_height = log_2(pte->page_height);
146*b843c749SSergey Zigachev 	unsigned int min_pte_before_flip = is_vert_scan(rotation) ?
147*b843c749SSergey Zigachev 			pte->min_pte_before_flip_vert_scan :
148*b843c749SSergey Zigachev 			pte->min_pte_before_flip_horiz_scan;
149*b843c749SSergey Zigachev 
150*b843c749SSergey Zigachev 	REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT,
151*b843c749SSergey Zigachev 			GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0xff);
152*b843c749SSergey Zigachev 
153*b843c749SSergey Zigachev 	REG_UPDATE_3(DVMM_PTE_CONTROL,
154*b843c749SSergey Zigachev 			DVMM_PAGE_WIDTH, page_width,
155*b843c749SSergey Zigachev 			DVMM_PAGE_HEIGHT, page_height,
156*b843c749SSergey Zigachev 			DVMM_MIN_PTE_BEFORE_FLIP, min_pte_before_flip);
157*b843c749SSergey Zigachev 
158*b843c749SSergey Zigachev 	REG_UPDATE_2(DVMM_PTE_ARB_CONTROL,
159*b843c749SSergey Zigachev 			DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk,
160*b843c749SSergey Zigachev 			DVMM_MAX_PTE_REQ_OUTSTANDING, 0xff);
161*b843c749SSergey Zigachev }
162*b843c749SSergey Zigachev 
program_urgency_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t urgency_low_wm,uint32_t urgency_high_wm)163*b843c749SSergey Zigachev static void program_urgency_watermark(
164*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
165*b843c749SSergey Zigachev 	uint32_t wm_select,
166*b843c749SSergey Zigachev 	uint32_t urgency_low_wm,
167*b843c749SSergey Zigachev 	uint32_t urgency_high_wm)
168*b843c749SSergey Zigachev {
169*b843c749SSergey Zigachev 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
170*b843c749SSergey Zigachev 		URGENCY_WATERMARK_MASK, wm_select);
171*b843c749SSergey Zigachev 
172*b843c749SSergey Zigachev 	REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
173*b843c749SSergey Zigachev 		URGENCY_LOW_WATERMARK, urgency_low_wm,
174*b843c749SSergey Zigachev 		URGENCY_HIGH_WATERMARK, urgency_high_wm);
175*b843c749SSergey Zigachev }
176*b843c749SSergey Zigachev 
dce120_program_urgency_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t urgency_low_wm,uint32_t urgency_high_wm)177*b843c749SSergey Zigachev static void dce120_program_urgency_watermark(
178*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
179*b843c749SSergey Zigachev 	uint32_t wm_select,
180*b843c749SSergey Zigachev 	uint32_t urgency_low_wm,
181*b843c749SSergey Zigachev 	uint32_t urgency_high_wm)
182*b843c749SSergey Zigachev {
183*b843c749SSergey Zigachev 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
184*b843c749SSergey Zigachev 		URGENCY_WATERMARK_MASK, wm_select);
185*b843c749SSergey Zigachev 
186*b843c749SSergey Zigachev 	REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
187*b843c749SSergey Zigachev 		URGENCY_LOW_WATERMARK, urgency_low_wm,
188*b843c749SSergey Zigachev 		URGENCY_HIGH_WATERMARK, urgency_high_wm);
189*b843c749SSergey Zigachev 
190*b843c749SSergey Zigachev 	REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0,
191*b843c749SSergey Zigachev 		URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm,
192*b843c749SSergey Zigachev 		URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm);
193*b843c749SSergey Zigachev 
194*b843c749SSergey Zigachev }
195*b843c749SSergey Zigachev 
program_nbp_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t nbp_wm)196*b843c749SSergey Zigachev static void program_nbp_watermark(
197*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
198*b843c749SSergey Zigachev 	uint32_t wm_select,
199*b843c749SSergey Zigachev 	uint32_t nbp_wm)
200*b843c749SSergey Zigachev {
201*b843c749SSergey Zigachev 	if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
202*b843c749SSergey Zigachev 		REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
203*b843c749SSergey Zigachev 				NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
204*b843c749SSergey Zigachev 
205*b843c749SSergey Zigachev 		REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
206*b843c749SSergey Zigachev 				NB_PSTATE_CHANGE_ENABLE, 1,
207*b843c749SSergey Zigachev 				NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
208*b843c749SSergey Zigachev 				NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
209*b843c749SSergey Zigachev 
210*b843c749SSergey Zigachev 		REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
211*b843c749SSergey Zigachev 				NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
212*b843c749SSergey Zigachev 	}
213*b843c749SSergey Zigachev 
214*b843c749SSergey Zigachev 	if (REG(DPG_PIPE_LOW_POWER_CONTROL)) {
215*b843c749SSergey Zigachev 		REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
216*b843c749SSergey Zigachev 				PSTATE_CHANGE_WATERMARK_MASK, wm_select);
217*b843c749SSergey Zigachev 
218*b843c749SSergey Zigachev 		REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL,
219*b843c749SSergey Zigachev 				PSTATE_CHANGE_ENABLE, 1,
220*b843c749SSergey Zigachev 				PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
221*b843c749SSergey Zigachev 				PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
222*b843c749SSergey Zigachev 
223*b843c749SSergey Zigachev 		REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL,
224*b843c749SSergey Zigachev 				PSTATE_CHANGE_WATERMARK, nbp_wm);
225*b843c749SSergey Zigachev 	}
226*b843c749SSergey Zigachev }
227*b843c749SSergey Zigachev 
dce120_program_stutter_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t stutter_mark,uint32_t stutter_entry)228*b843c749SSergey Zigachev static void dce120_program_stutter_watermark(
229*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
230*b843c749SSergey Zigachev 	uint32_t wm_select,
231*b843c749SSergey Zigachev 	uint32_t stutter_mark,
232*b843c749SSergey Zigachev 	uint32_t stutter_entry)
233*b843c749SSergey Zigachev {
234*b843c749SSergey Zigachev 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
235*b843c749SSergey Zigachev 		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
236*b843c749SSergey Zigachev 
237*b843c749SSergey Zigachev 	if (REG(DPG_PIPE_STUTTER_CONTROL2))
238*b843c749SSergey Zigachev 		REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2,
239*b843c749SSergey Zigachev 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
240*b843c749SSergey Zigachev 				STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
241*b843c749SSergey Zigachev 	else
242*b843c749SSergey Zigachev 		REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
243*b843c749SSergey Zigachev 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
244*b843c749SSergey Zigachev 				STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
245*b843c749SSergey Zigachev }
246*b843c749SSergey Zigachev 
program_stutter_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t stutter_mark)247*b843c749SSergey Zigachev static void program_stutter_watermark(
248*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
249*b843c749SSergey Zigachev 	uint32_t wm_select,
250*b843c749SSergey Zigachev 	uint32_t stutter_mark)
251*b843c749SSergey Zigachev {
252*b843c749SSergey Zigachev 	REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
253*b843c749SSergey Zigachev 		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
254*b843c749SSergey Zigachev 
255*b843c749SSergey Zigachev 	if (REG(DPG_PIPE_STUTTER_CONTROL2))
256*b843c749SSergey Zigachev 		REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2,
257*b843c749SSergey Zigachev 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
258*b843c749SSergey Zigachev 	else
259*b843c749SSergey Zigachev 		REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
260*b843c749SSergey Zigachev 				STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
261*b843c749SSergey Zigachev }
262*b843c749SSergey Zigachev 
dce_mi_program_display_marks(struct mem_input * mi,struct dce_watermarks nbp,struct dce_watermarks stutter_exit,struct dce_watermarks stutter_enter,struct dce_watermarks urgent,uint32_t total_dest_line_time_ns)263*b843c749SSergey Zigachev static void dce_mi_program_display_marks(
264*b843c749SSergey Zigachev 	struct mem_input *mi,
265*b843c749SSergey Zigachev 	struct dce_watermarks nbp,
266*b843c749SSergey Zigachev 	struct dce_watermarks stutter_exit,
267*b843c749SSergey Zigachev 	struct dce_watermarks stutter_enter,
268*b843c749SSergey Zigachev 	struct dce_watermarks urgent,
269*b843c749SSergey Zigachev 	uint32_t total_dest_line_time_ns)
270*b843c749SSergey Zigachev {
271*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
272*b843c749SSergey Zigachev 	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
273*b843c749SSergey Zigachev 
274*b843c749SSergey Zigachev 	program_urgency_watermark(dce_mi, 2, /* set a */
275*b843c749SSergey Zigachev 			urgent.a_mark, total_dest_line_time_ns);
276*b843c749SSergey Zigachev 	program_urgency_watermark(dce_mi, 1, /* set d */
277*b843c749SSergey Zigachev 			urgent.d_mark, total_dest_line_time_ns);
278*b843c749SSergey Zigachev 
279*b843c749SSergey Zigachev 	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
280*b843c749SSergey Zigachev 		STUTTER_ENABLE, stutter_en,
281*b843c749SSergey Zigachev 		STUTTER_IGNORE_FBC, 1);
282*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
283*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
284*b843c749SSergey Zigachev 
285*b843c749SSergey Zigachev 	program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
286*b843c749SSergey Zigachev 	program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
287*b843c749SSergey Zigachev }
288*b843c749SSergey Zigachev 
dce112_mi_program_display_marks(struct mem_input * mi,struct dce_watermarks nbp,struct dce_watermarks stutter_exit,struct dce_watermarks stutter_entry,struct dce_watermarks urgent,uint32_t total_dest_line_time_ns)289*b843c749SSergey Zigachev static void dce112_mi_program_display_marks(struct mem_input *mi,
290*b843c749SSergey Zigachev 	struct dce_watermarks nbp,
291*b843c749SSergey Zigachev 	struct dce_watermarks stutter_exit,
292*b843c749SSergey Zigachev 	struct dce_watermarks stutter_entry,
293*b843c749SSergey Zigachev 	struct dce_watermarks urgent,
294*b843c749SSergey Zigachev 	uint32_t total_dest_line_time_ns)
295*b843c749SSergey Zigachev {
296*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
297*b843c749SSergey Zigachev 	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
298*b843c749SSergey Zigachev 
299*b843c749SSergey Zigachev 	program_urgency_watermark(dce_mi, 0, /* set a */
300*b843c749SSergey Zigachev 			urgent.a_mark, total_dest_line_time_ns);
301*b843c749SSergey Zigachev 	program_urgency_watermark(dce_mi, 1, /* set b */
302*b843c749SSergey Zigachev 			urgent.b_mark, total_dest_line_time_ns);
303*b843c749SSergey Zigachev 	program_urgency_watermark(dce_mi, 2, /* set c */
304*b843c749SSergey Zigachev 			urgent.c_mark, total_dest_line_time_ns);
305*b843c749SSergey Zigachev 	program_urgency_watermark(dce_mi, 3, /* set d */
306*b843c749SSergey Zigachev 			urgent.d_mark, total_dest_line_time_ns);
307*b843c749SSergey Zigachev 
308*b843c749SSergey Zigachev 	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
309*b843c749SSergey Zigachev 		STUTTER_ENABLE, stutter_en,
310*b843c749SSergey Zigachev 		STUTTER_IGNORE_FBC, 1);
311*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
312*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
313*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
314*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
315*b843c749SSergey Zigachev 
316*b843c749SSergey Zigachev 	program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */
317*b843c749SSergey Zigachev 	program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */
318*b843c749SSergey Zigachev 	program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */
319*b843c749SSergey Zigachev 	program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */
320*b843c749SSergey Zigachev }
321*b843c749SSergey Zigachev 
dce120_mi_program_display_marks(struct mem_input * mi,struct dce_watermarks nbp,struct dce_watermarks stutter_exit,struct dce_watermarks stutter_entry,struct dce_watermarks urgent,uint32_t total_dest_line_time_ns)322*b843c749SSergey Zigachev static void dce120_mi_program_display_marks(struct mem_input *mi,
323*b843c749SSergey Zigachev 	struct dce_watermarks nbp,
324*b843c749SSergey Zigachev 	struct dce_watermarks stutter_exit,
325*b843c749SSergey Zigachev 	struct dce_watermarks stutter_entry,
326*b843c749SSergey Zigachev 	struct dce_watermarks urgent,
327*b843c749SSergey Zigachev 	uint32_t total_dest_line_time_ns)
328*b843c749SSergey Zigachev {
329*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
330*b843c749SSergey Zigachev 	uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
331*b843c749SSergey Zigachev 
332*b843c749SSergey Zigachev 	dce120_program_urgency_watermark(dce_mi, 0, /* set a */
333*b843c749SSergey Zigachev 			urgent.a_mark, total_dest_line_time_ns);
334*b843c749SSergey Zigachev 	dce120_program_urgency_watermark(dce_mi, 1, /* set b */
335*b843c749SSergey Zigachev 			urgent.b_mark, total_dest_line_time_ns);
336*b843c749SSergey Zigachev 	dce120_program_urgency_watermark(dce_mi, 2, /* set c */
337*b843c749SSergey Zigachev 			urgent.c_mark, total_dest_line_time_ns);
338*b843c749SSergey Zigachev 	dce120_program_urgency_watermark(dce_mi, 3, /* set d */
339*b843c749SSergey Zigachev 			urgent.d_mark, total_dest_line_time_ns);
340*b843c749SSergey Zigachev 
341*b843c749SSergey Zigachev 	REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
342*b843c749SSergey Zigachev 		STUTTER_ENABLE, stutter_en,
343*b843c749SSergey Zigachev 		STUTTER_IGNORE_FBC, 1);
344*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
345*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
346*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
347*b843c749SSergey Zigachev 	program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
348*b843c749SSergey Zigachev 
349*b843c749SSergey Zigachev 	dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */
350*b843c749SSergey Zigachev 	dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */
351*b843c749SSergey Zigachev 	dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */
352*b843c749SSergey Zigachev 	dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */
353*b843c749SSergey Zigachev }
354*b843c749SSergey Zigachev 
program_tiling(struct dce_mem_input * dce_mi,const union dc_tiling_info * info)355*b843c749SSergey Zigachev static void program_tiling(
356*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
357*b843c749SSergey Zigachev {
358*b843c749SSergey Zigachev 	if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */
359*b843c749SSergey Zigachev 		REG_UPDATE_6(GRPH_CONTROL,
360*b843c749SSergey Zigachev 				GRPH_SW_MODE, info->gfx9.swizzle,
361*b843c749SSergey Zigachev 				GRPH_NUM_BANKS, log_2(info->gfx9.num_banks),
362*b843c749SSergey Zigachev 				GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines),
363*b843c749SSergey Zigachev 				GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes),
364*b843c749SSergey Zigachev 				GRPH_COLOR_EXPANSION_MODE, 1,
365*b843c749SSergey Zigachev 				GRPH_SE_ENABLE, info->gfx9.shaderEnable);
366*b843c749SSergey Zigachev 		/* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
367*b843c749SSergey Zigachev 		GRPH_SE_ENABLE, 1,
368*b843c749SSergey Zigachev 		GRPH_Z, 0);
369*b843c749SSergey Zigachev 		 */
370*b843c749SSergey Zigachev 	}
371*b843c749SSergey Zigachev 
372*b843c749SSergey Zigachev 	if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */
373*b843c749SSergey Zigachev 		REG_UPDATE_9(GRPH_CONTROL,
374*b843c749SSergey Zigachev 				GRPH_NUM_BANKS, info->gfx8.num_banks,
375*b843c749SSergey Zigachev 				GRPH_BANK_WIDTH, info->gfx8.bank_width,
376*b843c749SSergey Zigachev 				GRPH_BANK_HEIGHT, info->gfx8.bank_height,
377*b843c749SSergey Zigachev 				GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
378*b843c749SSergey Zigachev 				GRPH_TILE_SPLIT, info->gfx8.tile_split,
379*b843c749SSergey Zigachev 				GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
380*b843c749SSergey Zigachev 				GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
381*b843c749SSergey Zigachev 				GRPH_ARRAY_MODE, info->gfx8.array_mode,
382*b843c749SSergey Zigachev 				GRPH_COLOR_EXPANSION_MODE, 1);
383*b843c749SSergey Zigachev 		/* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
384*b843c749SSergey Zigachev 		/*
385*b843c749SSergey Zigachev 				GRPH_Z, 0);
386*b843c749SSergey Zigachev 				*/
387*b843c749SSergey Zigachev 	}
388*b843c749SSergey Zigachev }
389*b843c749SSergey Zigachev 
390*b843c749SSergey Zigachev 
program_size_and_rotation(struct dce_mem_input * dce_mi,enum dc_rotation_angle rotation,const union plane_size * plane_size)391*b843c749SSergey Zigachev static void program_size_and_rotation(
392*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
393*b843c749SSergey Zigachev 	enum dc_rotation_angle rotation,
394*b843c749SSergey Zigachev 	const union plane_size *plane_size)
395*b843c749SSergey Zigachev {
396*b843c749SSergey Zigachev 	const struct rect *in_rect = &plane_size->grph.surface_size;
397*b843c749SSergey Zigachev 	struct rect hw_rect = plane_size->grph.surface_size;
398*b843c749SSergey Zigachev 	const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
399*b843c749SSergey Zigachev 			[ROTATION_ANGLE_0] = 0,
400*b843c749SSergey Zigachev 			[ROTATION_ANGLE_90] = 1,
401*b843c749SSergey Zigachev 			[ROTATION_ANGLE_180] = 2,
402*b843c749SSergey Zigachev 			[ROTATION_ANGLE_270] = 3,
403*b843c749SSergey Zigachev 	};
404*b843c749SSergey Zigachev 
405*b843c749SSergey Zigachev 	if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
406*b843c749SSergey Zigachev 		hw_rect.x = in_rect->y;
407*b843c749SSergey Zigachev 		hw_rect.y = in_rect->x;
408*b843c749SSergey Zigachev 
409*b843c749SSergey Zigachev 		hw_rect.height = in_rect->width;
410*b843c749SSergey Zigachev 		hw_rect.width = in_rect->height;
411*b843c749SSergey Zigachev 	}
412*b843c749SSergey Zigachev 
413*b843c749SSergey Zigachev 	REG_SET(GRPH_X_START, 0,
414*b843c749SSergey Zigachev 			GRPH_X_START, hw_rect.x);
415*b843c749SSergey Zigachev 
416*b843c749SSergey Zigachev 	REG_SET(GRPH_Y_START, 0,
417*b843c749SSergey Zigachev 			GRPH_Y_START, hw_rect.y);
418*b843c749SSergey Zigachev 
419*b843c749SSergey Zigachev 	REG_SET(GRPH_X_END, 0,
420*b843c749SSergey Zigachev 			GRPH_X_END, hw_rect.width);
421*b843c749SSergey Zigachev 
422*b843c749SSergey Zigachev 	REG_SET(GRPH_Y_END, 0,
423*b843c749SSergey Zigachev 			GRPH_Y_END, hw_rect.height);
424*b843c749SSergey Zigachev 
425*b843c749SSergey Zigachev 	REG_SET(GRPH_PITCH, 0,
426*b843c749SSergey Zigachev 			GRPH_PITCH, plane_size->grph.surface_pitch);
427*b843c749SSergey Zigachev 
428*b843c749SSergey Zigachev 	REG_SET(HW_ROTATION, 0,
429*b843c749SSergey Zigachev 			GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
430*b843c749SSergey Zigachev }
431*b843c749SSergey Zigachev 
program_grph_pixel_format(struct dce_mem_input * dce_mi,enum surface_pixel_format format)432*b843c749SSergey Zigachev static void program_grph_pixel_format(
433*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
434*b843c749SSergey Zigachev 	enum surface_pixel_format format)
435*b843c749SSergey Zigachev {
436*b843c749SSergey Zigachev 	uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
437*b843c749SSergey Zigachev 	uint32_t grph_depth = 0, grph_format = 0;
438*b843c749SSergey Zigachev 	uint32_t sign = 0, floating = 0;
439*b843c749SSergey Zigachev 
440*b843c749SSergey Zigachev 	if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
441*b843c749SSergey Zigachev 			/*todo: doesn't look like we handle BGRA here,
442*b843c749SSergey Zigachev 			 *  should problem swap endian*/
443*b843c749SSergey Zigachev 		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
444*b843c749SSergey Zigachev 		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
445*b843c749SSergey Zigachev 		format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
446*b843c749SSergey Zigachev 		/* ABGR formats */
447*b843c749SSergey Zigachev 		red_xbar = 2;
448*b843c749SSergey Zigachev 		blue_xbar = 2;
449*b843c749SSergey Zigachev 	}
450*b843c749SSergey Zigachev 
451*b843c749SSergey Zigachev 	REG_SET_2(GRPH_SWAP_CNTL, 0,
452*b843c749SSergey Zigachev 			GRPH_RED_CROSSBAR, red_xbar,
453*b843c749SSergey Zigachev 			GRPH_BLUE_CROSSBAR, blue_xbar);
454*b843c749SSergey Zigachev 
455*b843c749SSergey Zigachev 	switch (format) {
456*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
457*b843c749SSergey Zigachev 		grph_depth = 0;
458*b843c749SSergey Zigachev 		grph_format = 0;
459*b843c749SSergey Zigachev 		break;
460*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
461*b843c749SSergey Zigachev 		grph_depth = 1;
462*b843c749SSergey Zigachev 		grph_format = 0;
463*b843c749SSergey Zigachev 		break;
464*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
465*b843c749SSergey Zigachev 		grph_depth = 1;
466*b843c749SSergey Zigachev 		grph_format = 1;
467*b843c749SSergey Zigachev 		break;
468*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
469*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
470*b843c749SSergey Zigachev 		grph_depth = 2;
471*b843c749SSergey Zigachev 		grph_format = 0;
472*b843c749SSergey Zigachev 		break;
473*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
474*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
475*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
476*b843c749SSergey Zigachev 		grph_depth = 2;
477*b843c749SSergey Zigachev 		grph_format = 1;
478*b843c749SSergey Zigachev 		break;
479*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
480*b843c749SSergey Zigachev 		sign = 1;
481*b843c749SSergey Zigachev 		floating = 1;
482*b843c749SSergey Zigachev 		/* no break */
483*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
484*b843c749SSergey Zigachev 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
485*b843c749SSergey Zigachev 		grph_depth = 3;
486*b843c749SSergey Zigachev 		grph_format = 0;
487*b843c749SSergey Zigachev 		break;
488*b843c749SSergey Zigachev 	default:
489*b843c749SSergey Zigachev 		DC_ERR("unsupported grph pixel format");
490*b843c749SSergey Zigachev 		break;
491*b843c749SSergey Zigachev 	}
492*b843c749SSergey Zigachev 
493*b843c749SSergey Zigachev 	REG_UPDATE_2(GRPH_CONTROL,
494*b843c749SSergey Zigachev 			GRPH_DEPTH, grph_depth,
495*b843c749SSergey Zigachev 			GRPH_FORMAT, grph_format);
496*b843c749SSergey Zigachev 
497*b843c749SSergey Zigachev 	REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
498*b843c749SSergey Zigachev 			GRPH_PRESCALE_SELECT, floating,
499*b843c749SSergey Zigachev 			GRPH_PRESCALE_R_SIGN, sign,
500*b843c749SSergey Zigachev 			GRPH_PRESCALE_G_SIGN, sign,
501*b843c749SSergey Zigachev 			GRPH_PRESCALE_B_SIGN, sign);
502*b843c749SSergey Zigachev }
503*b843c749SSergey Zigachev 
dce_mi_program_surface_config(struct mem_input * mi,enum surface_pixel_format format,union dc_tiling_info * tiling_info,union plane_size * plane_size,enum dc_rotation_angle rotation,struct dc_plane_dcc_param * dcc,bool horizontal_mirror)504*b843c749SSergey Zigachev static void dce_mi_program_surface_config(
505*b843c749SSergey Zigachev 	struct mem_input *mi,
506*b843c749SSergey Zigachev 	enum surface_pixel_format format,
507*b843c749SSergey Zigachev 	union dc_tiling_info *tiling_info,
508*b843c749SSergey Zigachev 	union plane_size *plane_size,
509*b843c749SSergey Zigachev 	enum dc_rotation_angle rotation,
510*b843c749SSergey Zigachev 	struct dc_plane_dcc_param *dcc,
511*b843c749SSergey Zigachev 	bool horizontal_mirror)
512*b843c749SSergey Zigachev {
513*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
514*b843c749SSergey Zigachev 	REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
515*b843c749SSergey Zigachev 
516*b843c749SSergey Zigachev 	program_tiling(dce_mi, tiling_info);
517*b843c749SSergey Zigachev 	program_size_and_rotation(dce_mi, rotation, plane_size);
518*b843c749SSergey Zigachev 
519*b843c749SSergey Zigachev 	if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
520*b843c749SSergey Zigachev 		format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
521*b843c749SSergey Zigachev 		program_grph_pixel_format(dce_mi, format);
522*b843c749SSergey Zigachev }
523*b843c749SSergey Zigachev 
get_dmif_switch_time_us(uint32_t h_total,uint32_t v_total,uint32_t pix_clk_khz)524*b843c749SSergey Zigachev static uint32_t get_dmif_switch_time_us(
525*b843c749SSergey Zigachev 	uint32_t h_total,
526*b843c749SSergey Zigachev 	uint32_t v_total,
527*b843c749SSergey Zigachev 	uint32_t pix_clk_khz)
528*b843c749SSergey Zigachev {
529*b843c749SSergey Zigachev 	uint32_t frame_time;
530*b843c749SSergey Zigachev 	uint32_t pixels_per_second;
531*b843c749SSergey Zigachev 	uint32_t pixels_per_frame;
532*b843c749SSergey Zigachev 	uint32_t refresh_rate;
533*b843c749SSergey Zigachev 	const uint32_t us_in_sec = 1000000;
534*b843c749SSergey Zigachev 	const uint32_t min_single_frame_time_us = 30000;
535*b843c749SSergey Zigachev 	/*return double of frame time*/
536*b843c749SSergey Zigachev 	const uint32_t single_frame_time_multiplier = 2;
537*b843c749SSergey Zigachev 
538*b843c749SSergey Zigachev 	if (!h_total || v_total || !pix_clk_khz)
539*b843c749SSergey Zigachev 		return single_frame_time_multiplier * min_single_frame_time_us;
540*b843c749SSergey Zigachev 
541*b843c749SSergey Zigachev 	/*TODO: should we use pixel format normalized pixel clock here?*/
542*b843c749SSergey Zigachev 	pixels_per_second = pix_clk_khz * 1000;
543*b843c749SSergey Zigachev 	pixels_per_frame = h_total * v_total;
544*b843c749SSergey Zigachev 
545*b843c749SSergey Zigachev 	if (!pixels_per_second || !pixels_per_frame) {
546*b843c749SSergey Zigachev 		/* avoid division by zero */
547*b843c749SSergey Zigachev 		ASSERT(pixels_per_frame);
548*b843c749SSergey Zigachev 		ASSERT(pixels_per_second);
549*b843c749SSergey Zigachev 		return single_frame_time_multiplier * min_single_frame_time_us;
550*b843c749SSergey Zigachev 	}
551*b843c749SSergey Zigachev 
552*b843c749SSergey Zigachev 	refresh_rate = pixels_per_second / pixels_per_frame;
553*b843c749SSergey Zigachev 
554*b843c749SSergey Zigachev 	if (!refresh_rate) {
555*b843c749SSergey Zigachev 		/* avoid division by zero*/
556*b843c749SSergey Zigachev 		ASSERT(refresh_rate);
557*b843c749SSergey Zigachev 		return single_frame_time_multiplier * min_single_frame_time_us;
558*b843c749SSergey Zigachev 	}
559*b843c749SSergey Zigachev 
560*b843c749SSergey Zigachev 	frame_time = us_in_sec / refresh_rate;
561*b843c749SSergey Zigachev 
562*b843c749SSergey Zigachev 	if (frame_time < min_single_frame_time_us)
563*b843c749SSergey Zigachev 		frame_time = min_single_frame_time_us;
564*b843c749SSergey Zigachev 
565*b843c749SSergey Zigachev 	frame_time *= single_frame_time_multiplier;
566*b843c749SSergey Zigachev 
567*b843c749SSergey Zigachev 	return frame_time;
568*b843c749SSergey Zigachev }
569*b843c749SSergey Zigachev 
dce_mi_allocate_dmif(struct mem_input * mi,uint32_t h_total,uint32_t v_total,uint32_t pix_clk_khz,uint32_t total_stream_num)570*b843c749SSergey Zigachev static void dce_mi_allocate_dmif(
571*b843c749SSergey Zigachev 	struct mem_input *mi,
572*b843c749SSergey Zigachev 	uint32_t h_total,
573*b843c749SSergey Zigachev 	uint32_t v_total,
574*b843c749SSergey Zigachev 	uint32_t pix_clk_khz,
575*b843c749SSergey Zigachev 	uint32_t total_stream_num)
576*b843c749SSergey Zigachev {
577*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
578*b843c749SSergey Zigachev 	const uint32_t retry_delay = 10;
579*b843c749SSergey Zigachev 	uint32_t retry_count = get_dmif_switch_time_us(
580*b843c749SSergey Zigachev 			h_total,
581*b843c749SSergey Zigachev 			v_total,
582*b843c749SSergey Zigachev 			pix_clk_khz) / retry_delay;
583*b843c749SSergey Zigachev 
584*b843c749SSergey Zigachev 	uint32_t pix_dur;
585*b843c749SSergey Zigachev 	uint32_t buffers_allocated;
586*b843c749SSergey Zigachev 	uint32_t dmif_buffer_control;
587*b843c749SSergey Zigachev 
588*b843c749SSergey Zigachev 	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
589*b843c749SSergey Zigachev 			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
590*b843c749SSergey Zigachev 
591*b843c749SSergey Zigachev 	if (buffers_allocated == 2)
592*b843c749SSergey Zigachev 		return;
593*b843c749SSergey Zigachev 
594*b843c749SSergey Zigachev 	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
595*b843c749SSergey Zigachev 			DMIF_BUFFERS_ALLOCATED, 2);
596*b843c749SSergey Zigachev 
597*b843c749SSergey Zigachev 	REG_WAIT(DMIF_BUFFER_CONTROL,
598*b843c749SSergey Zigachev 			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
599*b843c749SSergey Zigachev 			retry_delay, retry_count);
600*b843c749SSergey Zigachev 
601*b843c749SSergey Zigachev 	if (pix_clk_khz != 0) {
602*b843c749SSergey Zigachev 		pix_dur = 1000000000ULL / pix_clk_khz;
603*b843c749SSergey Zigachev 
604*b843c749SSergey Zigachev 		REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
605*b843c749SSergey Zigachev 			PIXEL_DURATION, pix_dur);
606*b843c749SSergey Zigachev 	}
607*b843c749SSergey Zigachev 
608*b843c749SSergey Zigachev 	if (dce_mi->wa.single_head_rdreq_dmif_limit) {
609*b843c749SSergey Zigachev 		uint32_t eanble =  (total_stream_num > 1) ? 0 :
610*b843c749SSergey Zigachev 				dce_mi->wa.single_head_rdreq_dmif_limit;
611*b843c749SSergey Zigachev 
612*b843c749SSergey Zigachev 		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
613*b843c749SSergey Zigachev 				ENABLE, eanble);
614*b843c749SSergey Zigachev 	}
615*b843c749SSergey Zigachev }
616*b843c749SSergey Zigachev 
dce_mi_free_dmif(struct mem_input * mi,uint32_t total_stream_num)617*b843c749SSergey Zigachev static void dce_mi_free_dmif(
618*b843c749SSergey Zigachev 		struct mem_input *mi,
619*b843c749SSergey Zigachev 		uint32_t total_stream_num)
620*b843c749SSergey Zigachev {
621*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
622*b843c749SSergey Zigachev 	uint32_t buffers_allocated;
623*b843c749SSergey Zigachev 	uint32_t dmif_buffer_control;
624*b843c749SSergey Zigachev 
625*b843c749SSergey Zigachev 	dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
626*b843c749SSergey Zigachev 			DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
627*b843c749SSergey Zigachev 
628*b843c749SSergey Zigachev 	if (buffers_allocated == 0)
629*b843c749SSergey Zigachev 		return;
630*b843c749SSergey Zigachev 
631*b843c749SSergey Zigachev 	REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
632*b843c749SSergey Zigachev 			DMIF_BUFFERS_ALLOCATED, 0);
633*b843c749SSergey Zigachev 
634*b843c749SSergey Zigachev 	REG_WAIT(DMIF_BUFFER_CONTROL,
635*b843c749SSergey Zigachev 			DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
636*b843c749SSergey Zigachev 			10, 3500);
637*b843c749SSergey Zigachev 
638*b843c749SSergey Zigachev 	if (dce_mi->wa.single_head_rdreq_dmif_limit) {
639*b843c749SSergey Zigachev 		uint32_t eanble =  (total_stream_num > 1) ? 0 :
640*b843c749SSergey Zigachev 				dce_mi->wa.single_head_rdreq_dmif_limit;
641*b843c749SSergey Zigachev 
642*b843c749SSergey Zigachev 		REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
643*b843c749SSergey Zigachev 				ENABLE, eanble);
644*b843c749SSergey Zigachev 	}
645*b843c749SSergey Zigachev }
646*b843c749SSergey Zigachev 
647*b843c749SSergey Zigachev 
program_sec_addr(struct dce_mem_input * dce_mi,PHYSICAL_ADDRESS_LOC address)648*b843c749SSergey Zigachev static void program_sec_addr(
649*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
650*b843c749SSergey Zigachev 	PHYSICAL_ADDRESS_LOC address)
651*b843c749SSergey Zigachev {
652*b843c749SSergey Zigachev 	/*high register MUST be programmed first*/
653*b843c749SSergey Zigachev 	REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
654*b843c749SSergey Zigachev 		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
655*b843c749SSergey Zigachev 		address.high_part);
656*b843c749SSergey Zigachev 
657*b843c749SSergey Zigachev 	REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,
658*b843c749SSergey Zigachev 		GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,
659*b843c749SSergey Zigachev 		GRPH_SECONDARY_DFQ_ENABLE, 0);
660*b843c749SSergey Zigachev }
661*b843c749SSergey Zigachev 
program_pri_addr(struct dce_mem_input * dce_mi,PHYSICAL_ADDRESS_LOC address)662*b843c749SSergey Zigachev static void program_pri_addr(
663*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
664*b843c749SSergey Zigachev 	PHYSICAL_ADDRESS_LOC address)
665*b843c749SSergey Zigachev {
666*b843c749SSergey Zigachev 	/*high register MUST be programmed first*/
667*b843c749SSergey Zigachev 	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
668*b843c749SSergey Zigachev 		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
669*b843c749SSergey Zigachev 		address.high_part);
670*b843c749SSergey Zigachev 
671*b843c749SSergey Zigachev 	REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,
672*b843c749SSergey Zigachev 		GRPH_PRIMARY_SURFACE_ADDRESS,
673*b843c749SSergey Zigachev 		address.low_part >> 8);
674*b843c749SSergey Zigachev }
675*b843c749SSergey Zigachev 
676*b843c749SSergey Zigachev 
dce_mi_is_flip_pending(struct mem_input * mem_input)677*b843c749SSergey Zigachev static bool dce_mi_is_flip_pending(struct mem_input *mem_input)
678*b843c749SSergey Zigachev {
679*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
680*b843c749SSergey Zigachev 	uint32_t update_pending;
681*b843c749SSergey Zigachev 
682*b843c749SSergey Zigachev 	REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);
683*b843c749SSergey Zigachev 	if (update_pending)
684*b843c749SSergey Zigachev 		return true;
685*b843c749SSergey Zigachev 
686*b843c749SSergey Zigachev 	mem_input->current_address = mem_input->request_address;
687*b843c749SSergey Zigachev 	return false;
688*b843c749SSergey Zigachev }
689*b843c749SSergey Zigachev 
dce_mi_program_surface_flip_and_addr(struct mem_input * mem_input,const struct dc_plane_address * address,bool flip_immediate)690*b843c749SSergey Zigachev static bool dce_mi_program_surface_flip_and_addr(
691*b843c749SSergey Zigachev 	struct mem_input *mem_input,
692*b843c749SSergey Zigachev 	const struct dc_plane_address *address,
693*b843c749SSergey Zigachev 	bool flip_immediate)
694*b843c749SSergey Zigachev {
695*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
696*b843c749SSergey Zigachev 
697*b843c749SSergey Zigachev 	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
698*b843c749SSergey Zigachev 
699*b843c749SSergey Zigachev 	REG_UPDATE(
700*b843c749SSergey Zigachev 		GRPH_FLIP_CONTROL,
701*b843c749SSergey Zigachev 		GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);
702*b843c749SSergey Zigachev 
703*b843c749SSergey Zigachev 	switch (address->type) {
704*b843c749SSergey Zigachev 	case PLN_ADDR_TYPE_GRAPHICS:
705*b843c749SSergey Zigachev 		if (address->grph.addr.quad_part == 0)
706*b843c749SSergey Zigachev 			break;
707*b843c749SSergey Zigachev 		program_pri_addr(dce_mi, address->grph.addr);
708*b843c749SSergey Zigachev 		break;
709*b843c749SSergey Zigachev 	case PLN_ADDR_TYPE_GRPH_STEREO:
710*b843c749SSergey Zigachev 		if (address->grph_stereo.left_addr.quad_part == 0 ||
711*b843c749SSergey Zigachev 		    address->grph_stereo.right_addr.quad_part == 0)
712*b843c749SSergey Zigachev 			break;
713*b843c749SSergey Zigachev 		program_pri_addr(dce_mi, address->grph_stereo.left_addr);
714*b843c749SSergey Zigachev 		program_sec_addr(dce_mi, address->grph_stereo.right_addr);
715*b843c749SSergey Zigachev 		break;
716*b843c749SSergey Zigachev 	default:
717*b843c749SSergey Zigachev 		/* not supported */
718*b843c749SSergey Zigachev 		BREAK_TO_DEBUGGER();
719*b843c749SSergey Zigachev 		break;
720*b843c749SSergey Zigachev 	}
721*b843c749SSergey Zigachev 
722*b843c749SSergey Zigachev 	mem_input->request_address = *address;
723*b843c749SSergey Zigachev 
724*b843c749SSergey Zigachev 	if (flip_immediate)
725*b843c749SSergey Zigachev 		mem_input->current_address = *address;
726*b843c749SSergey Zigachev 
727*b843c749SSergey Zigachev 	REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
728*b843c749SSergey Zigachev 
729*b843c749SSergey Zigachev 	return true;
730*b843c749SSergey Zigachev }
731*b843c749SSergey Zigachev 
732*b843c749SSergey Zigachev static const struct mem_input_funcs dce_mi_funcs = {
733*b843c749SSergey Zigachev 	.mem_input_program_display_marks = dce_mi_program_display_marks,
734*b843c749SSergey Zigachev 	.allocate_mem_input = dce_mi_allocate_dmif,
735*b843c749SSergey Zigachev 	.free_mem_input = dce_mi_free_dmif,
736*b843c749SSergey Zigachev 	.mem_input_program_surface_flip_and_addr =
737*b843c749SSergey Zigachev 			dce_mi_program_surface_flip_and_addr,
738*b843c749SSergey Zigachev 	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
739*b843c749SSergey Zigachev 	.mem_input_program_surface_config =
740*b843c749SSergey Zigachev 			dce_mi_program_surface_config,
741*b843c749SSergey Zigachev 	.mem_input_is_flip_pending = dce_mi_is_flip_pending
742*b843c749SSergey Zigachev };
743*b843c749SSergey Zigachev 
744*b843c749SSergey Zigachev static const struct mem_input_funcs dce112_mi_funcs = {
745*b843c749SSergey Zigachev 	.mem_input_program_display_marks = dce112_mi_program_display_marks,
746*b843c749SSergey Zigachev 	.allocate_mem_input = dce_mi_allocate_dmif,
747*b843c749SSergey Zigachev 	.free_mem_input = dce_mi_free_dmif,
748*b843c749SSergey Zigachev 	.mem_input_program_surface_flip_and_addr =
749*b843c749SSergey Zigachev 			dce_mi_program_surface_flip_and_addr,
750*b843c749SSergey Zigachev 	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
751*b843c749SSergey Zigachev 	.mem_input_program_surface_config =
752*b843c749SSergey Zigachev 			dce_mi_program_surface_config,
753*b843c749SSergey Zigachev 	.mem_input_is_flip_pending = dce_mi_is_flip_pending
754*b843c749SSergey Zigachev };
755*b843c749SSergey Zigachev 
756*b843c749SSergey Zigachev static const struct mem_input_funcs dce120_mi_funcs = {
757*b843c749SSergey Zigachev 	.mem_input_program_display_marks = dce120_mi_program_display_marks,
758*b843c749SSergey Zigachev 	.allocate_mem_input = dce_mi_allocate_dmif,
759*b843c749SSergey Zigachev 	.free_mem_input = dce_mi_free_dmif,
760*b843c749SSergey Zigachev 	.mem_input_program_surface_flip_and_addr =
761*b843c749SSergey Zigachev 			dce_mi_program_surface_flip_and_addr,
762*b843c749SSergey Zigachev 	.mem_input_program_pte_vm = dce_mi_program_pte_vm,
763*b843c749SSergey Zigachev 	.mem_input_program_surface_config =
764*b843c749SSergey Zigachev 			dce_mi_program_surface_config,
765*b843c749SSergey Zigachev 	.mem_input_is_flip_pending = dce_mi_is_flip_pending
766*b843c749SSergey Zigachev };
767*b843c749SSergey Zigachev 
dce_mem_input_construct(struct dce_mem_input * dce_mi,struct dc_context * ctx,int inst,const struct dce_mem_input_registers * regs,const struct dce_mem_input_shift * mi_shift,const struct dce_mem_input_mask * mi_mask)768*b843c749SSergey Zigachev void dce_mem_input_construct(
769*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
770*b843c749SSergey Zigachev 	struct dc_context *ctx,
771*b843c749SSergey Zigachev 	int inst,
772*b843c749SSergey Zigachev 	const struct dce_mem_input_registers *regs,
773*b843c749SSergey Zigachev 	const struct dce_mem_input_shift *mi_shift,
774*b843c749SSergey Zigachev 	const struct dce_mem_input_mask *mi_mask)
775*b843c749SSergey Zigachev {
776*b843c749SSergey Zigachev 	dce_mi->base.ctx = ctx;
777*b843c749SSergey Zigachev 
778*b843c749SSergey Zigachev 	dce_mi->base.inst = inst;
779*b843c749SSergey Zigachev 	dce_mi->base.funcs = &dce_mi_funcs;
780*b843c749SSergey Zigachev 
781*b843c749SSergey Zigachev 	dce_mi->regs = regs;
782*b843c749SSergey Zigachev 	dce_mi->shifts = mi_shift;
783*b843c749SSergey Zigachev 	dce_mi->masks = mi_mask;
784*b843c749SSergey Zigachev }
785*b843c749SSergey Zigachev 
dce112_mem_input_construct(struct dce_mem_input * dce_mi,struct dc_context * ctx,int inst,const struct dce_mem_input_registers * regs,const struct dce_mem_input_shift * mi_shift,const struct dce_mem_input_mask * mi_mask)786*b843c749SSergey Zigachev void dce112_mem_input_construct(
787*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
788*b843c749SSergey Zigachev 	struct dc_context *ctx,
789*b843c749SSergey Zigachev 	int inst,
790*b843c749SSergey Zigachev 	const struct dce_mem_input_registers *regs,
791*b843c749SSergey Zigachev 	const struct dce_mem_input_shift *mi_shift,
792*b843c749SSergey Zigachev 	const struct dce_mem_input_mask *mi_mask)
793*b843c749SSergey Zigachev {
794*b843c749SSergey Zigachev 	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
795*b843c749SSergey Zigachev 	dce_mi->base.funcs = &dce112_mi_funcs;
796*b843c749SSergey Zigachev }
797*b843c749SSergey Zigachev 
dce120_mem_input_construct(struct dce_mem_input * dce_mi,struct dc_context * ctx,int inst,const struct dce_mem_input_registers * regs,const struct dce_mem_input_shift * mi_shift,const struct dce_mem_input_mask * mi_mask)798*b843c749SSergey Zigachev void dce120_mem_input_construct(
799*b843c749SSergey Zigachev 	struct dce_mem_input *dce_mi,
800*b843c749SSergey Zigachev 	struct dc_context *ctx,
801*b843c749SSergey Zigachev 	int inst,
802*b843c749SSergey Zigachev 	const struct dce_mem_input_registers *regs,
803*b843c749SSergey Zigachev 	const struct dce_mem_input_shift *mi_shift,
804*b843c749SSergey Zigachev 	const struct dce_mem_input_mask *mi_mask)
805*b843c749SSergey Zigachev {
806*b843c749SSergey Zigachev 	dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
807*b843c749SSergey Zigachev 	dce_mi->base.funcs = &dce120_mi_funcs;
808*b843c749SSergey Zigachev }
809