Line data Source code
1 : /*
2 : * Copyright 2016 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 "dce_mem_input.h"
27 : #include "reg_helper.h"
28 : #include "basics/conversion.h"
29 :
30 : #define CTX \
31 : dce_mi->base.ctx
32 : #define REG(reg)\
33 : dce_mi->regs->reg
34 :
35 : #undef FN
36 : #define FN(reg_name, field_name) \
37 : dce_mi->shifts->field_name, dce_mi->masks->field_name
38 :
39 : struct pte_setting {
40 : unsigned int bpp;
41 : unsigned int page_width;
42 : unsigned int page_height;
43 : unsigned char min_pte_before_flip_horiz_scan;
44 : unsigned char min_pte_before_flip_vert_scan;
45 : unsigned char pte_req_per_chunk;
46 : unsigned char param_6;
47 : unsigned char param_7;
48 : unsigned char param_8;
49 : };
50 :
51 : enum mi_bits_per_pixel {
52 : mi_bpp_8 = 0,
53 : mi_bpp_16,
54 : mi_bpp_32,
55 : mi_bpp_64,
56 : mi_bpp_count,
57 : };
58 :
59 : enum mi_tiling_format {
60 : mi_tiling_linear = 0,
61 : mi_tiling_1D,
62 : mi_tiling_2D,
63 : mi_tiling_count,
64 : };
65 :
66 : static const struct pte_setting pte_settings[mi_tiling_count][mi_bpp_count] = {
67 : [mi_tiling_linear] = {
68 : { 8, 4096, 1, 8, 0, 1, 0, 0, 0},
69 : { 16, 2048, 1, 8, 0, 1, 0, 0, 0},
70 : { 32, 1024, 1, 8, 0, 1, 0, 0, 0},
71 : { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */
72 : },
73 : [mi_tiling_1D] = {
74 : { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */
75 : { 16, 256, 8, 2, 0, 1, 0, 0, 0},
76 : { 32, 128, 8, 4, 0, 1, 0, 0, 0},
77 : { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */
78 : },
79 : [mi_tiling_2D] = {
80 : { 8, 64, 64, 8, 8, 1, 4, 0, 0},
81 : { 16, 64, 32, 8, 16, 1, 8, 0, 0},
82 : { 32, 32, 32, 16, 16, 1, 8, 0, 0},
83 : { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */
84 : },
85 : };
86 :
87 : static enum mi_bits_per_pixel get_mi_bpp(
88 : enum surface_pixel_format format)
89 : {
90 0 : if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
91 : return mi_bpp_64;
92 0 : else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888)
93 : return mi_bpp_32;
94 0 : else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555)
95 : return mi_bpp_16;
96 : else
97 : return mi_bpp_8;
98 : }
99 :
100 : static enum mi_tiling_format get_mi_tiling(
101 : union dc_tiling_info *tiling_info)
102 : {
103 : switch (tiling_info->gfx8.array_mode) {
104 : case DC_ARRAY_1D_TILED_THIN1:
105 : case DC_ARRAY_1D_TILED_THICK:
106 : case DC_ARRAY_PRT_TILED_THIN1:
107 : return mi_tiling_1D;
108 : case DC_ARRAY_2D_TILED_THIN1:
109 : case DC_ARRAY_2D_TILED_THICK:
110 : case DC_ARRAY_2D_TILED_X_THICK:
111 : case DC_ARRAY_PRT_2D_TILED_THIN1:
112 : case DC_ARRAY_PRT_2D_TILED_THICK:
113 : return mi_tiling_2D;
114 : case DC_ARRAY_LINEAR_GENERAL:
115 : case DC_ARRAY_LINEAR_ALLIGNED:
116 : return mi_tiling_linear;
117 : default:
118 : return mi_tiling_2D;
119 : }
120 : }
121 :
122 : static bool is_vert_scan(enum dc_rotation_angle rotation)
123 : {
124 0 : switch (rotation) {
125 : case ROTATION_ANGLE_90:
126 : case ROTATION_ANGLE_270:
127 : return true;
128 : default:
129 : return false;
130 : }
131 : }
132 :
133 0 : static void dce_mi_program_pte_vm(
134 : struct mem_input *mi,
135 : enum surface_pixel_format format,
136 : union dc_tiling_info *tiling_info,
137 : enum dc_rotation_angle rotation)
138 : {
139 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
140 0 : enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format);
141 0 : enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info);
142 0 : const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp];
143 :
144 0 : unsigned int page_width = log_2(pte->page_width);
145 0 : unsigned int page_height = log_2(pte->page_height);
146 0 : unsigned int min_pte_before_flip = is_vert_scan(rotation) ?
147 0 : pte->min_pte_before_flip_vert_scan :
148 0 : pte->min_pte_before_flip_horiz_scan;
149 :
150 0 : REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT,
151 : GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0x7f);
152 :
153 0 : REG_UPDATE_3(DVMM_PTE_CONTROL,
154 : DVMM_PAGE_WIDTH, page_width,
155 : DVMM_PAGE_HEIGHT, page_height,
156 : DVMM_MIN_PTE_BEFORE_FLIP, min_pte_before_flip);
157 :
158 0 : REG_UPDATE_2(DVMM_PTE_ARB_CONTROL,
159 : DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk,
160 : DVMM_MAX_PTE_REQ_OUTSTANDING, 0x7f);
161 0 : }
162 :
163 0 : static void program_urgency_watermark(
164 : struct dce_mem_input *dce_mi,
165 : uint32_t wm_select,
166 : uint32_t urgency_low_wm,
167 : uint32_t urgency_high_wm)
168 : {
169 0 : REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
170 : URGENCY_WATERMARK_MASK, wm_select);
171 :
172 0 : REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
173 : URGENCY_LOW_WATERMARK, urgency_low_wm,
174 : URGENCY_HIGH_WATERMARK, urgency_high_wm);
175 0 : }
176 :
177 : #if defined(CONFIG_DRM_AMD_DC_SI)
178 : static void dce60_program_urgency_watermark(
179 : struct dce_mem_input *dce_mi,
180 : uint32_t wm_select,
181 : uint32_t urgency_low_wm,
182 : uint32_t urgency_high_wm)
183 : {
184 : REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL3,
185 : URGENCY_WATERMARK_MASK, wm_select);
186 :
187 : REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
188 : URGENCY_LOW_WATERMARK, urgency_low_wm,
189 : URGENCY_HIGH_WATERMARK, urgency_high_wm);
190 : }
191 : #endif
192 :
193 0 : static void dce120_program_urgency_watermark(
194 : struct dce_mem_input *dce_mi,
195 : uint32_t wm_select,
196 : uint32_t urgency_low_wm,
197 : uint32_t urgency_high_wm)
198 : {
199 0 : REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
200 : URGENCY_WATERMARK_MASK, wm_select);
201 :
202 0 : REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
203 : URGENCY_LOW_WATERMARK, urgency_low_wm,
204 : URGENCY_HIGH_WATERMARK, urgency_high_wm);
205 :
206 0 : REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0,
207 : URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm,
208 : URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm);
209 :
210 0 : }
211 :
212 : #if defined(CONFIG_DRM_AMD_DC_SI)
213 : static void dce60_program_nbp_watermark(
214 : struct dce_mem_input *dce_mi,
215 : uint32_t wm_select,
216 : uint32_t nbp_wm)
217 : {
218 : REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
219 : NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
220 :
221 : REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
222 : NB_PSTATE_CHANGE_ENABLE, 1,
223 : NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
224 : NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
225 :
226 : REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
227 : NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
228 : }
229 : #endif
230 :
231 0 : static void program_nbp_watermark(
232 : struct dce_mem_input *dce_mi,
233 : uint32_t wm_select,
234 : uint32_t nbp_wm)
235 : {
236 0 : if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
237 0 : REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
238 : NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
239 :
240 0 : REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
241 : NB_PSTATE_CHANGE_ENABLE, 1,
242 : NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
243 : NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
244 :
245 0 : REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
246 : NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
247 : }
248 :
249 0 : if (REG(DPG_PIPE_LOW_POWER_CONTROL)) {
250 0 : REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
251 : PSTATE_CHANGE_WATERMARK_MASK, wm_select);
252 :
253 0 : REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL,
254 : PSTATE_CHANGE_ENABLE, 1,
255 : PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
256 : PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
257 :
258 0 : REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL,
259 : PSTATE_CHANGE_WATERMARK, nbp_wm);
260 : }
261 0 : }
262 :
263 : #if defined(CONFIG_DRM_AMD_DC_SI)
264 : static void dce60_program_stutter_watermark(
265 : struct dce_mem_input *dce_mi,
266 : uint32_t wm_select,
267 : uint32_t stutter_mark)
268 : {
269 : REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
270 : STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
271 :
272 : REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
273 : STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
274 : }
275 : #endif
276 :
277 0 : static void dce120_program_stutter_watermark(
278 : struct dce_mem_input *dce_mi,
279 : uint32_t wm_select,
280 : uint32_t stutter_mark,
281 : uint32_t stutter_entry)
282 : {
283 0 : REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
284 : STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
285 :
286 0 : if (REG(DPG_PIPE_STUTTER_CONTROL2))
287 0 : REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2,
288 : STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
289 : STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
290 : else
291 0 : REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
292 : STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
293 : STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
294 0 : }
295 :
296 0 : static void program_stutter_watermark(
297 : struct dce_mem_input *dce_mi,
298 : uint32_t wm_select,
299 : uint32_t stutter_mark)
300 : {
301 0 : REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
302 : STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
303 :
304 0 : if (REG(DPG_PIPE_STUTTER_CONTROL2))
305 0 : REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2,
306 : STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
307 : else
308 0 : REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
309 : STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
310 0 : }
311 :
312 0 : static void dce_mi_program_display_marks(
313 : struct mem_input *mi,
314 : struct dce_watermarks nbp,
315 : struct dce_watermarks stutter_exit,
316 : struct dce_watermarks stutter_enter,
317 : struct dce_watermarks urgent,
318 : uint32_t total_dest_line_time_ns)
319 : {
320 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
321 0 : uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
322 :
323 0 : program_urgency_watermark(dce_mi, 2, /* set a */
324 0 : urgent.a_mark, total_dest_line_time_ns);
325 0 : program_urgency_watermark(dce_mi, 1, /* set d */
326 0 : urgent.d_mark, total_dest_line_time_ns);
327 :
328 0 : REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
329 : STUTTER_ENABLE, stutter_en,
330 : STUTTER_IGNORE_FBC, 1);
331 0 : program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
332 0 : program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
333 :
334 0 : program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
335 0 : program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
336 0 : }
337 :
338 : #if defined(CONFIG_DRM_AMD_DC_SI)
339 : static void dce60_mi_program_display_marks(
340 : struct mem_input *mi,
341 : struct dce_watermarks nbp,
342 : struct dce_watermarks stutter_exit,
343 : struct dce_watermarks stutter_enter,
344 : struct dce_watermarks urgent,
345 : uint32_t total_dest_line_time_ns)
346 : {
347 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
348 : uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
349 :
350 : dce60_program_urgency_watermark(dce_mi, 2, /* set a */
351 : urgent.a_mark, total_dest_line_time_ns);
352 : dce60_program_urgency_watermark(dce_mi, 1, /* set d */
353 : urgent.d_mark, total_dest_line_time_ns);
354 :
355 : REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
356 : STUTTER_ENABLE, stutter_en,
357 : STUTTER_IGNORE_FBC, 1);
358 : dce60_program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */
359 : dce60_program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
360 :
361 : dce60_program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
362 : dce60_program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
363 : }
364 : #endif
365 :
366 0 : static void dce112_mi_program_display_marks(struct mem_input *mi,
367 : struct dce_watermarks nbp,
368 : struct dce_watermarks stutter_exit,
369 : struct dce_watermarks stutter_entry,
370 : struct dce_watermarks urgent,
371 : uint32_t total_dest_line_time_ns)
372 : {
373 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
374 0 : uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
375 :
376 0 : program_urgency_watermark(dce_mi, 0, /* set a */
377 0 : urgent.a_mark, total_dest_line_time_ns);
378 0 : program_urgency_watermark(dce_mi, 1, /* set b */
379 0 : urgent.b_mark, total_dest_line_time_ns);
380 0 : program_urgency_watermark(dce_mi, 2, /* set c */
381 0 : urgent.c_mark, total_dest_line_time_ns);
382 0 : program_urgency_watermark(dce_mi, 3, /* set d */
383 0 : urgent.d_mark, total_dest_line_time_ns);
384 :
385 0 : REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
386 : STUTTER_ENABLE, stutter_en,
387 : STUTTER_IGNORE_FBC, 1);
388 0 : program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
389 0 : program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
390 0 : program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
391 0 : program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
392 :
393 0 : program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */
394 0 : program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */
395 0 : program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */
396 0 : program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */
397 0 : }
398 :
399 0 : static void dce120_mi_program_display_marks(struct mem_input *mi,
400 : struct dce_watermarks nbp,
401 : struct dce_watermarks stutter_exit,
402 : struct dce_watermarks stutter_entry,
403 : struct dce_watermarks urgent,
404 : uint32_t total_dest_line_time_ns)
405 : {
406 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
407 0 : uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
408 :
409 0 : dce120_program_urgency_watermark(dce_mi, 0, /* set a */
410 0 : urgent.a_mark, total_dest_line_time_ns);
411 0 : dce120_program_urgency_watermark(dce_mi, 1, /* set b */
412 0 : urgent.b_mark, total_dest_line_time_ns);
413 0 : dce120_program_urgency_watermark(dce_mi, 2, /* set c */
414 0 : urgent.c_mark, total_dest_line_time_ns);
415 0 : dce120_program_urgency_watermark(dce_mi, 3, /* set d */
416 0 : urgent.d_mark, total_dest_line_time_ns);
417 :
418 0 : REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
419 : STUTTER_ENABLE, stutter_en,
420 : STUTTER_IGNORE_FBC, 1);
421 0 : program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */
422 0 : program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
423 0 : program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
424 0 : program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
425 :
426 0 : dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */
427 0 : dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */
428 0 : dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */
429 0 : dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */
430 0 : }
431 :
432 0 : static void program_tiling(
433 : struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
434 : {
435 0 : if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */
436 0 : REG_UPDATE_6(GRPH_CONTROL,
437 : GRPH_SW_MODE, info->gfx9.swizzle,
438 : GRPH_NUM_BANKS, log_2(info->gfx9.num_banks),
439 : GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines),
440 : GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes),
441 : GRPH_COLOR_EXPANSION_MODE, 1,
442 : GRPH_SE_ENABLE, info->gfx9.shaderEnable);
443 : /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
444 : GRPH_SE_ENABLE, 1,
445 : GRPH_Z, 0);
446 : */
447 : }
448 :
449 0 : if (dce_mi->masks->GRPH_MICRO_TILE_MODE) { /* GFX8 */
450 0 : REG_UPDATE_9(GRPH_CONTROL,
451 : GRPH_NUM_BANKS, info->gfx8.num_banks,
452 : GRPH_BANK_WIDTH, info->gfx8.bank_width,
453 : GRPH_BANK_HEIGHT, info->gfx8.bank_height,
454 : GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
455 : GRPH_TILE_SPLIT, info->gfx8.tile_split,
456 : GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
457 : GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
458 : GRPH_ARRAY_MODE, info->gfx8.array_mode,
459 : GRPH_COLOR_EXPANSION_MODE, 1);
460 : /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
461 : /*
462 : GRPH_Z, 0);
463 : */
464 : }
465 :
466 0 : if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX6 but reuses gfx8 struct */
467 0 : REG_UPDATE_8(GRPH_CONTROL,
468 : GRPH_NUM_BANKS, info->gfx8.num_banks,
469 : GRPH_BANK_WIDTH, info->gfx8.bank_width,
470 : GRPH_BANK_HEIGHT, info->gfx8.bank_height,
471 : GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
472 : GRPH_TILE_SPLIT, info->gfx8.tile_split,
473 : /* DCE6 has no GRPH_MICRO_TILE_MODE mask */
474 : GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
475 : GRPH_ARRAY_MODE, info->gfx8.array_mode,
476 : GRPH_COLOR_EXPANSION_MODE, 1);
477 : /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
478 : /*
479 : GRPH_Z, 0);
480 : */
481 : }
482 0 : }
483 :
484 :
485 0 : static void program_size_and_rotation(
486 : struct dce_mem_input *dce_mi,
487 : enum dc_rotation_angle rotation,
488 : const struct plane_size *plane_size)
489 : {
490 0 : const struct rect *in_rect = &plane_size->surface_size;
491 0 : struct rect hw_rect = plane_size->surface_size;
492 0 : const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
493 : [ROTATION_ANGLE_0] = 0,
494 : [ROTATION_ANGLE_90] = 1,
495 : [ROTATION_ANGLE_180] = 2,
496 : [ROTATION_ANGLE_270] = 3,
497 : };
498 :
499 0 : if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
500 0 : hw_rect.x = in_rect->y;
501 0 : hw_rect.y = in_rect->x;
502 :
503 0 : hw_rect.height = in_rect->width;
504 0 : hw_rect.width = in_rect->height;
505 : }
506 :
507 0 : REG_SET(GRPH_X_START, 0,
508 : GRPH_X_START, hw_rect.x);
509 :
510 0 : REG_SET(GRPH_Y_START, 0,
511 : GRPH_Y_START, hw_rect.y);
512 :
513 0 : REG_SET(GRPH_X_END, 0,
514 : GRPH_X_END, hw_rect.width);
515 :
516 0 : REG_SET(GRPH_Y_END, 0,
517 : GRPH_Y_END, hw_rect.height);
518 :
519 0 : REG_SET(GRPH_PITCH, 0,
520 : GRPH_PITCH, plane_size->surface_pitch);
521 :
522 0 : REG_SET(HW_ROTATION, 0,
523 : GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
524 0 : }
525 :
526 : #if defined(CONFIG_DRM_AMD_DC_SI)
527 : static void dce60_program_size(
528 : struct dce_mem_input *dce_mi,
529 : enum dc_rotation_angle rotation, /* not used in DCE6 */
530 : const struct plane_size *plane_size)
531 : {
532 : struct rect hw_rect = plane_size->surface_size;
533 : /* DCE6 has no HW rotation, skip rotation_angles declaration */
534 :
535 : /* DCE6 has no HW rotation, skip ROTATION_ANGLE_* processing */
536 :
537 : REG_SET(GRPH_X_START, 0,
538 : GRPH_X_START, hw_rect.x);
539 :
540 : REG_SET(GRPH_Y_START, 0,
541 : GRPH_Y_START, hw_rect.y);
542 :
543 : REG_SET(GRPH_X_END, 0,
544 : GRPH_X_END, hw_rect.width);
545 :
546 : REG_SET(GRPH_Y_END, 0,
547 : GRPH_Y_END, hw_rect.height);
548 :
549 : REG_SET(GRPH_PITCH, 0,
550 : GRPH_PITCH, plane_size->surface_pitch);
551 :
552 : /* DCE6 has no HW_ROTATION register, skip setting rotation_angles */
553 : }
554 : #endif
555 :
556 0 : static void program_grph_pixel_format(
557 : struct dce_mem_input *dce_mi,
558 : enum surface_pixel_format format)
559 : {
560 0 : uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
561 0 : uint32_t grph_depth = 0, grph_format = 0;
562 0 : uint32_t sign = 0, floating = 0;
563 :
564 0 : if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
565 : /*todo: doesn't look like we handle BGRA here,
566 : * should problem swap endian*/
567 0 : format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
568 0 : format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
569 0 : format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 ||
570 : format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
571 : /* ABGR formats */
572 0 : red_xbar = 2;
573 0 : blue_xbar = 2;
574 : }
575 :
576 0 : REG_SET_2(GRPH_SWAP_CNTL, 0,
577 : GRPH_RED_CROSSBAR, red_xbar,
578 : GRPH_BLUE_CROSSBAR, blue_xbar);
579 :
580 0 : switch (format) {
581 : case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
582 : grph_depth = 0;
583 : grph_format = 0;
584 : break;
585 : case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
586 0 : grph_depth = 1;
587 0 : grph_format = 0;
588 0 : break;
589 : case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
590 0 : grph_depth = 1;
591 0 : grph_format = 1;
592 0 : break;
593 : case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
594 : case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
595 0 : grph_depth = 2;
596 0 : grph_format = 0;
597 0 : break;
598 : case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
599 : case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
600 : case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
601 0 : grph_depth = 2;
602 0 : grph_format = 1;
603 0 : break;
604 : case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
605 0 : sign = 1;
606 0 : floating = 1;
607 : fallthrough;
608 : case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
609 : case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
610 : case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
611 : grph_depth = 3;
612 : grph_format = 0;
613 : break;
614 : default:
615 0 : DC_ERR("unsupported grph pixel format");
616 0 : break;
617 : }
618 :
619 0 : REG_UPDATE_2(GRPH_CONTROL,
620 : GRPH_DEPTH, grph_depth,
621 : GRPH_FORMAT, grph_format);
622 :
623 0 : REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
624 : GRPH_PRESCALE_SELECT, floating,
625 : GRPH_PRESCALE_R_SIGN, sign,
626 : GRPH_PRESCALE_G_SIGN, sign,
627 : GRPH_PRESCALE_B_SIGN, sign);
628 0 : }
629 :
630 0 : static void dce_mi_program_surface_config(
631 : struct mem_input *mi,
632 : enum surface_pixel_format format,
633 : union dc_tiling_info *tiling_info,
634 : struct plane_size *plane_size,
635 : enum dc_rotation_angle rotation,
636 : struct dc_plane_dcc_param *dcc,
637 : bool horizontal_mirror)
638 : {
639 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
640 0 : REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
641 :
642 0 : program_tiling(dce_mi, tiling_info);
643 0 : program_size_and_rotation(dce_mi, rotation, plane_size);
644 :
645 0 : if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
646 : format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
647 0 : program_grph_pixel_format(dce_mi, format);
648 0 : }
649 :
650 : #if defined(CONFIG_DRM_AMD_DC_SI)
651 : static void dce60_mi_program_surface_config(
652 : struct mem_input *mi,
653 : enum surface_pixel_format format,
654 : union dc_tiling_info *tiling_info,
655 : struct plane_size *plane_size,
656 : enum dc_rotation_angle rotation, /* not used in DCE6 */
657 : struct dc_plane_dcc_param *dcc,
658 : bool horizontal_mirror)
659 : {
660 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
661 : REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
662 :
663 : program_tiling(dce_mi, tiling_info);
664 : dce60_program_size(dce_mi, rotation, plane_size);
665 :
666 : if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
667 : format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
668 : program_grph_pixel_format(dce_mi, format);
669 : }
670 : #endif
671 :
672 0 : static uint32_t get_dmif_switch_time_us(
673 : uint32_t h_total,
674 : uint32_t v_total,
675 : uint32_t pix_clk_khz)
676 : {
677 : uint32_t frame_time;
678 : uint32_t pixels_per_second;
679 : uint32_t pixels_per_frame;
680 : uint32_t refresh_rate;
681 0 : const uint32_t us_in_sec = 1000000;
682 0 : const uint32_t min_single_frame_time_us = 30000;
683 : /*return double of frame time*/
684 0 : const uint32_t single_frame_time_multiplier = 2;
685 :
686 0 : if (!h_total || v_total || !pix_clk_khz)
687 : return single_frame_time_multiplier * min_single_frame_time_us;
688 :
689 : /*TODO: should we use pixel format normalized pixel clock here?*/
690 0 : pixels_per_second = pix_clk_khz * 1000;
691 0 : pixels_per_frame = h_total * v_total;
692 :
693 0 : if (!pixels_per_second || !pixels_per_frame) {
694 : /* avoid division by zero */
695 0 : ASSERT(pixels_per_frame);
696 0 : ASSERT(pixels_per_second);
697 : return single_frame_time_multiplier * min_single_frame_time_us;
698 : }
699 :
700 0 : refresh_rate = pixels_per_second / pixels_per_frame;
701 :
702 0 : if (!refresh_rate) {
703 : /* avoid division by zero*/
704 0 : ASSERT(refresh_rate);
705 : return single_frame_time_multiplier * min_single_frame_time_us;
706 : }
707 :
708 0 : frame_time = us_in_sec / refresh_rate;
709 :
710 0 : if (frame_time < min_single_frame_time_us)
711 0 : frame_time = min_single_frame_time_us;
712 :
713 0 : frame_time *= single_frame_time_multiplier;
714 :
715 0 : return frame_time;
716 : }
717 :
718 0 : static void dce_mi_allocate_dmif(
719 : struct mem_input *mi,
720 : uint32_t h_total,
721 : uint32_t v_total,
722 : uint32_t pix_clk_khz,
723 : uint32_t total_stream_num)
724 : {
725 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
726 0 : const uint32_t retry_delay = 10;
727 0 : uint32_t retry_count = get_dmif_switch_time_us(
728 : h_total,
729 : v_total,
730 : pix_clk_khz) / retry_delay;
731 :
732 : uint32_t pix_dur;
733 : uint32_t buffers_allocated;
734 : uint32_t dmif_buffer_control;
735 :
736 0 : dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
737 : DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
738 :
739 0 : if (buffers_allocated == 2)
740 0 : return;
741 :
742 0 : REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
743 : DMIF_BUFFERS_ALLOCATED, 2);
744 :
745 0 : REG_WAIT(DMIF_BUFFER_CONTROL,
746 : DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
747 : retry_delay, retry_count);
748 :
749 0 : if (pix_clk_khz != 0) {
750 0 : pix_dur = 1000000000ULL / pix_clk_khz;
751 :
752 0 : REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
753 : PIXEL_DURATION, pix_dur);
754 : }
755 :
756 0 : if (dce_mi->wa.single_head_rdreq_dmif_limit) {
757 0 : uint32_t enable = (total_stream_num > 1) ? 0 :
758 : dce_mi->wa.single_head_rdreq_dmif_limit;
759 :
760 0 : REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
761 : ENABLE, enable);
762 : }
763 : }
764 :
765 0 : static void dce_mi_free_dmif(
766 : struct mem_input *mi,
767 : uint32_t total_stream_num)
768 : {
769 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
770 : uint32_t buffers_allocated;
771 : uint32_t dmif_buffer_control;
772 :
773 0 : dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
774 : DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
775 :
776 0 : if (buffers_allocated == 0)
777 0 : return;
778 :
779 0 : REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
780 : DMIF_BUFFERS_ALLOCATED, 0);
781 :
782 0 : REG_WAIT(DMIF_BUFFER_CONTROL,
783 : DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
784 : 10, 3500);
785 :
786 0 : if (dce_mi->wa.single_head_rdreq_dmif_limit) {
787 0 : uint32_t enable = (total_stream_num > 1) ? 0 :
788 : dce_mi->wa.single_head_rdreq_dmif_limit;
789 :
790 0 : REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
791 : ENABLE, enable);
792 : }
793 : }
794 :
795 :
796 0 : static void program_sec_addr(
797 : struct dce_mem_input *dce_mi,
798 : PHYSICAL_ADDRESS_LOC address)
799 : {
800 : /*high register MUST be programmed first*/
801 0 : REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
802 : GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
803 : address.high_part);
804 :
805 0 : REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,
806 : GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,
807 : GRPH_SECONDARY_DFQ_ENABLE, 0);
808 0 : }
809 :
810 0 : static void program_pri_addr(
811 : struct dce_mem_input *dce_mi,
812 : PHYSICAL_ADDRESS_LOC address)
813 : {
814 : /*high register MUST be programmed first*/
815 0 : REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
816 : GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
817 : address.high_part);
818 :
819 0 : REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,
820 : GRPH_PRIMARY_SURFACE_ADDRESS,
821 : address.low_part >> 8);
822 0 : }
823 :
824 :
825 0 : static bool dce_mi_is_flip_pending(struct mem_input *mem_input)
826 : {
827 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
828 : uint32_t update_pending;
829 :
830 0 : REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);
831 0 : if (update_pending)
832 : return true;
833 :
834 0 : mem_input->current_address = mem_input->request_address;
835 0 : return false;
836 : }
837 :
838 0 : static bool dce_mi_program_surface_flip_and_addr(
839 : struct mem_input *mem_input,
840 : const struct dc_plane_address *address,
841 : bool flip_immediate)
842 : {
843 0 : struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
844 :
845 0 : REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
846 :
847 0 : REG_UPDATE(
848 : GRPH_FLIP_CONTROL,
849 : GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);
850 :
851 0 : switch (address->type) {
852 : case PLN_ADDR_TYPE_GRAPHICS:
853 0 : if (address->grph.addr.quad_part == 0)
854 : break;
855 0 : program_pri_addr(dce_mi, address->grph.addr);
856 0 : break;
857 : case PLN_ADDR_TYPE_GRPH_STEREO:
858 0 : if (address->grph_stereo.left_addr.quad_part == 0 ||
859 0 : address->grph_stereo.right_addr.quad_part == 0)
860 : break;
861 0 : program_pri_addr(dce_mi, address->grph_stereo.left_addr);
862 0 : program_sec_addr(dce_mi, address->grph_stereo.right_addr);
863 0 : break;
864 : default:
865 : /* not supported */
866 0 : BREAK_TO_DEBUGGER();
867 0 : break;
868 : }
869 :
870 0 : mem_input->request_address = *address;
871 :
872 0 : if (flip_immediate)
873 0 : mem_input->current_address = *address;
874 :
875 0 : REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
876 :
877 0 : return true;
878 : }
879 :
880 : static const struct mem_input_funcs dce_mi_funcs = {
881 : .mem_input_program_display_marks = dce_mi_program_display_marks,
882 : .allocate_mem_input = dce_mi_allocate_dmif,
883 : .free_mem_input = dce_mi_free_dmif,
884 : .mem_input_program_surface_flip_and_addr =
885 : dce_mi_program_surface_flip_and_addr,
886 : .mem_input_program_pte_vm = dce_mi_program_pte_vm,
887 : .mem_input_program_surface_config =
888 : dce_mi_program_surface_config,
889 : .mem_input_is_flip_pending = dce_mi_is_flip_pending
890 : };
891 :
892 : #if defined(CONFIG_DRM_AMD_DC_SI)
893 : static const struct mem_input_funcs dce60_mi_funcs = {
894 : .mem_input_program_display_marks = dce60_mi_program_display_marks,
895 : .allocate_mem_input = dce_mi_allocate_dmif,
896 : .free_mem_input = dce_mi_free_dmif,
897 : .mem_input_program_surface_flip_and_addr =
898 : dce_mi_program_surface_flip_and_addr,
899 : .mem_input_program_pte_vm = dce_mi_program_pte_vm,
900 : .mem_input_program_surface_config =
901 : dce60_mi_program_surface_config,
902 : .mem_input_is_flip_pending = dce_mi_is_flip_pending
903 : };
904 : #endif
905 :
906 : static const struct mem_input_funcs dce112_mi_funcs = {
907 : .mem_input_program_display_marks = dce112_mi_program_display_marks,
908 : .allocate_mem_input = dce_mi_allocate_dmif,
909 : .free_mem_input = dce_mi_free_dmif,
910 : .mem_input_program_surface_flip_and_addr =
911 : dce_mi_program_surface_flip_and_addr,
912 : .mem_input_program_pte_vm = dce_mi_program_pte_vm,
913 : .mem_input_program_surface_config =
914 : dce_mi_program_surface_config,
915 : .mem_input_is_flip_pending = dce_mi_is_flip_pending
916 : };
917 :
918 : static const struct mem_input_funcs dce120_mi_funcs = {
919 : .mem_input_program_display_marks = dce120_mi_program_display_marks,
920 : .allocate_mem_input = dce_mi_allocate_dmif,
921 : .free_mem_input = dce_mi_free_dmif,
922 : .mem_input_program_surface_flip_and_addr =
923 : dce_mi_program_surface_flip_and_addr,
924 : .mem_input_program_pte_vm = dce_mi_program_pte_vm,
925 : .mem_input_program_surface_config =
926 : dce_mi_program_surface_config,
927 : .mem_input_is_flip_pending = dce_mi_is_flip_pending
928 : };
929 :
930 0 : void dce_mem_input_construct(
931 : struct dce_mem_input *dce_mi,
932 : struct dc_context *ctx,
933 : int inst,
934 : const struct dce_mem_input_registers *regs,
935 : const struct dce_mem_input_shift *mi_shift,
936 : const struct dce_mem_input_mask *mi_mask)
937 : {
938 0 : dce_mi->base.ctx = ctx;
939 :
940 0 : dce_mi->base.inst = inst;
941 0 : dce_mi->base.funcs = &dce_mi_funcs;
942 :
943 0 : dce_mi->regs = regs;
944 0 : dce_mi->shifts = mi_shift;
945 0 : dce_mi->masks = mi_mask;
946 0 : }
947 :
948 : #if defined(CONFIG_DRM_AMD_DC_SI)
949 : void dce60_mem_input_construct(
950 : struct dce_mem_input *dce_mi,
951 : struct dc_context *ctx,
952 : int inst,
953 : const struct dce_mem_input_registers *regs,
954 : const struct dce_mem_input_shift *mi_shift,
955 : const struct dce_mem_input_mask *mi_mask)
956 : {
957 : dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
958 : dce_mi->base.funcs = &dce60_mi_funcs;
959 : }
960 : #endif
961 :
962 0 : void dce112_mem_input_construct(
963 : struct dce_mem_input *dce_mi,
964 : struct dc_context *ctx,
965 : int inst,
966 : const struct dce_mem_input_registers *regs,
967 : const struct dce_mem_input_shift *mi_shift,
968 : const struct dce_mem_input_mask *mi_mask)
969 : {
970 0 : dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
971 0 : dce_mi->base.funcs = &dce112_mi_funcs;
972 0 : }
973 :
974 0 : void dce120_mem_input_construct(
975 : struct dce_mem_input *dce_mi,
976 : struct dc_context *ctx,
977 : int inst,
978 : const struct dce_mem_input_registers *regs,
979 : const struct dce_mem_input_shift *mi_shift,
980 : const struct dce_mem_input_mask *mi_mask)
981 : {
982 0 : dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
983 0 : dce_mi->base.funcs = &dce120_mi_funcs;
984 0 : }
|