1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
39struct 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
51enum 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
59enum mi_tiling_format {
60 mi_tiling_linear = 0,
61 mi_tiling_1D,
62 mi_tiling_2D,
63 mi_tiling_count,
64};
65
66static 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},
72 },
73 [mi_tiling_1D] = {
74 { 8, 512, 8, 1, 0, 1, 0, 0, 0},
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},
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},
84 },
85};
86
87static enum mi_bits_per_pixel get_mi_bpp(
88 enum surface_pixel_format format)
89{
90 if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
91 return mi_bpp_64;
92 else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888)
93 return mi_bpp_32;
94 else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555)
95 return mi_bpp_16;
96 else
97 return mi_bpp_8;
98}
99
100static 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
122static bool is_vert_scan(enum dc_rotation_angle rotation)
123{
124 switch (rotation) {
125 case ROTATION_ANGLE_90:
126 case ROTATION_ANGLE_270:
127 return true;
128 default:
129 return false;
130 }
131}
132
133static 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 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
140 enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format);
141 enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info);
142 const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp];
143
144 unsigned int page_width = log_2(pte->page_width);
145 unsigned int page_height = log_2(pte->page_height);
146 unsigned int min_pte_before_flip = is_vert_scan(rotation) ?
147 pte->min_pte_before_flip_vert_scan :
148 pte->min_pte_before_flip_horiz_scan;
149
150 REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT,
151 GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0xff);
152
153 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 REG_UPDATE_2(DVMM_PTE_ARB_CONTROL,
159 DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk,
160 DVMM_MAX_PTE_REQ_OUTSTANDING, 0xff);
161}
162
163static 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 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
170 URGENCY_WATERMARK_MASK, wm_select);
171
172 REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
173 URGENCY_LOW_WATERMARK, urgency_low_wm,
174 URGENCY_HIGH_WATERMARK, urgency_high_wm);
175}
176
177static void dce120_program_urgency_watermark(
178 struct dce_mem_input *dce_mi,
179 uint32_t wm_select,
180 uint32_t urgency_low_wm,
181 uint32_t urgency_high_wm)
182{
183 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
184 URGENCY_WATERMARK_MASK, wm_select);
185
186 REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
187 URGENCY_LOW_WATERMARK, urgency_low_wm,
188 URGENCY_HIGH_WATERMARK, urgency_high_wm);
189
190 REG_SET_2(DPG_PIPE_URGENT_LEVEL_CONTROL, 0,
191 URGENT_LEVEL_LOW_WATERMARK, urgency_low_wm,
192 URGENT_LEVEL_HIGH_WATERMARK, urgency_high_wm);
193
194}
195
196static void program_nbp_watermark(
197 struct dce_mem_input *dce_mi,
198 uint32_t wm_select,
199 uint32_t nbp_wm)
200{
201 if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
202 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
203 NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
204
205 REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
206 NB_PSTATE_CHANGE_ENABLE, 1,
207 NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
208 NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
209
210 REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
211 NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
212 }
213
214 if (REG(DPG_PIPE_LOW_POWER_CONTROL)) {
215 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
216 PSTATE_CHANGE_WATERMARK_MASK, wm_select);
217
218 REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL,
219 PSTATE_CHANGE_ENABLE, 1,
220 PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
221 PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
222
223 REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL,
224 PSTATE_CHANGE_WATERMARK, nbp_wm);
225 }
226}
227
228static void dce120_program_stutter_watermark(
229 struct dce_mem_input *dce_mi,
230 uint32_t wm_select,
231 uint32_t stutter_mark,
232 uint32_t stutter_entry)
233{
234 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
235 STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
236
237 if (REG(DPG_PIPE_STUTTER_CONTROL2))
238 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL2,
239 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
240 STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
241 else
242 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
243 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark,
244 STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry);
245}
246
247static void program_stutter_watermark(
248 struct dce_mem_input *dce_mi,
249 uint32_t wm_select,
250 uint32_t stutter_mark)
251{
252 REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
253 STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
254
255 if (REG(DPG_PIPE_STUTTER_CONTROL2))
256 REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2,
257 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
258 else
259 REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
260 STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
261}
262
263static void dce_mi_program_display_marks(
264 struct mem_input *mi,
265 struct dce_watermarks nbp,
266 struct dce_watermarks stutter_exit,
267 struct dce_watermarks stutter_enter,
268 struct dce_watermarks urgent,
269 uint32_t total_dest_line_time_ns)
270{
271 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
272 uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
273
274 program_urgency_watermark(dce_mi, 2,
275 urgent.a_mark, total_dest_line_time_ns);
276 program_urgency_watermark(dce_mi, 1,
277 urgent.d_mark, total_dest_line_time_ns);
278
279 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
280 STUTTER_ENABLE, stutter_en,
281 STUTTER_IGNORE_FBC, 1);
282 program_nbp_watermark(dce_mi, 2, nbp.a_mark);
283 program_nbp_watermark(dce_mi, 1, nbp.d_mark);
284
285 program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark);
286 program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark);
287}
288
289static void dce112_mi_program_display_marks(struct mem_input *mi,
290 struct dce_watermarks nbp,
291 struct dce_watermarks stutter_exit,
292 struct dce_watermarks stutter_entry,
293 struct dce_watermarks urgent,
294 uint32_t total_dest_line_time_ns)
295{
296 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
297 uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
298
299 program_urgency_watermark(dce_mi, 0,
300 urgent.a_mark, total_dest_line_time_ns);
301 program_urgency_watermark(dce_mi, 1,
302 urgent.b_mark, total_dest_line_time_ns);
303 program_urgency_watermark(dce_mi, 2,
304 urgent.c_mark, total_dest_line_time_ns);
305 program_urgency_watermark(dce_mi, 3,
306 urgent.d_mark, total_dest_line_time_ns);
307
308 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
309 STUTTER_ENABLE, stutter_en,
310 STUTTER_IGNORE_FBC, 1);
311 program_nbp_watermark(dce_mi, 0, nbp.a_mark);
312 program_nbp_watermark(dce_mi, 1, nbp.b_mark);
313 program_nbp_watermark(dce_mi, 2, nbp.c_mark);
314 program_nbp_watermark(dce_mi, 3, nbp.d_mark);
315
316 program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark);
317 program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark);
318 program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark);
319 program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark);
320}
321
322static void dce120_mi_program_display_marks(struct mem_input *mi,
323 struct dce_watermarks nbp,
324 struct dce_watermarks stutter_exit,
325 struct dce_watermarks stutter_entry,
326 struct dce_watermarks urgent,
327 uint32_t total_dest_line_time_ns)
328{
329 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
330 uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
331
332 dce120_program_urgency_watermark(dce_mi, 0,
333 urgent.a_mark, total_dest_line_time_ns);
334 dce120_program_urgency_watermark(dce_mi, 1,
335 urgent.b_mark, total_dest_line_time_ns);
336 dce120_program_urgency_watermark(dce_mi, 2,
337 urgent.c_mark, total_dest_line_time_ns);
338 dce120_program_urgency_watermark(dce_mi, 3,
339 urgent.d_mark, total_dest_line_time_ns);
340
341 REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
342 STUTTER_ENABLE, stutter_en,
343 STUTTER_IGNORE_FBC, 1);
344 program_nbp_watermark(dce_mi, 0, nbp.a_mark);
345 program_nbp_watermark(dce_mi, 1, nbp.b_mark);
346 program_nbp_watermark(dce_mi, 2, nbp.c_mark);
347 program_nbp_watermark(dce_mi, 3, nbp.d_mark);
348
349 dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark);
350 dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark);
351 dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark);
352 dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark);
353}
354
355static void program_tiling(
356 struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
357{
358 if (dce_mi->masks->GRPH_SW_MODE) {
359 REG_UPDATE_6(GRPH_CONTROL,
360 GRPH_SW_MODE, info->gfx9.swizzle,
361 GRPH_NUM_BANKS, log_2(info->gfx9.num_banks),
362 GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines),
363 GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes),
364 GRPH_COLOR_EXPANSION_MODE, 1,
365 GRPH_SE_ENABLE, info->gfx9.shaderEnable);
366
367
368
369
370 }
371
372 if (dce_mi->masks->GRPH_ARRAY_MODE) {
373 REG_UPDATE_9(GRPH_CONTROL,
374 GRPH_NUM_BANKS, info->gfx8.num_banks,
375 GRPH_BANK_WIDTH, info->gfx8.bank_width,
376 GRPH_BANK_HEIGHT, info->gfx8.bank_height,
377 GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
378 GRPH_TILE_SPLIT, info->gfx8.tile_split,
379 GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
380 GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
381 GRPH_ARRAY_MODE, info->gfx8.array_mode,
382 GRPH_COLOR_EXPANSION_MODE, 1);
383
384
385
386
387 }
388}
389
390
391static void program_size_and_rotation(
392 struct dce_mem_input *dce_mi,
393 enum dc_rotation_angle rotation,
394 const union plane_size *plane_size)
395{
396 const struct rect *in_rect = &plane_size->grph.surface_size;
397 struct rect hw_rect = plane_size->grph.surface_size;
398 const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
399 [ROTATION_ANGLE_0] = 0,
400 [ROTATION_ANGLE_90] = 1,
401 [ROTATION_ANGLE_180] = 2,
402 [ROTATION_ANGLE_270] = 3,
403 };
404
405 if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
406 hw_rect.x = in_rect->y;
407 hw_rect.y = in_rect->x;
408
409 hw_rect.height = in_rect->width;
410 hw_rect.width = in_rect->height;
411 }
412
413 REG_SET(GRPH_X_START, 0,
414 GRPH_X_START, hw_rect.x);
415
416 REG_SET(GRPH_Y_START, 0,
417 GRPH_Y_START, hw_rect.y);
418
419 REG_SET(GRPH_X_END, 0,
420 GRPH_X_END, hw_rect.width);
421
422 REG_SET(GRPH_Y_END, 0,
423 GRPH_Y_END, hw_rect.height);
424
425 REG_SET(GRPH_PITCH, 0,
426 GRPH_PITCH, plane_size->grph.surface_pitch);
427
428 REG_SET(HW_ROTATION, 0,
429 GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
430}
431
432static void program_grph_pixel_format(
433 struct dce_mem_input *dce_mi,
434 enum surface_pixel_format format)
435{
436 uint32_t red_xbar = 0, blue_xbar = 0;
437 uint32_t grph_depth = 0, grph_format = 0;
438 uint32_t sign = 0, floating = 0;
439
440 if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
441
442
443 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
444 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
445 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
446
447 red_xbar = 2;
448 blue_xbar = 2;
449 }
450
451 REG_SET_2(GRPH_SWAP_CNTL, 0,
452 GRPH_RED_CROSSBAR, red_xbar,
453 GRPH_BLUE_CROSSBAR, blue_xbar);
454
455 switch (format) {
456 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
457 grph_depth = 0;
458 grph_format = 0;
459 break;
460 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
461 grph_depth = 1;
462 grph_format = 0;
463 break;
464 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
465 grph_depth = 1;
466 grph_format = 1;
467 break;
468 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
469 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
470 grph_depth = 2;
471 grph_format = 0;
472 break;
473 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
474 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
475 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
476 grph_depth = 2;
477 grph_format = 1;
478 break;
479 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
480 sign = 1;
481 floating = 1;
482
483 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
484 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
485 grph_depth = 3;
486 grph_format = 0;
487 break;
488 default:
489 DC_ERR("unsupported grph pixel format");
490 break;
491 }
492
493 REG_UPDATE_2(GRPH_CONTROL,
494 GRPH_DEPTH, grph_depth,
495 GRPH_FORMAT, grph_format);
496
497 REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
498 GRPH_PRESCALE_SELECT, floating,
499 GRPH_PRESCALE_R_SIGN, sign,
500 GRPH_PRESCALE_G_SIGN, sign,
501 GRPH_PRESCALE_B_SIGN, sign);
502}
503
504static void dce_mi_program_surface_config(
505 struct mem_input *mi,
506 enum surface_pixel_format format,
507 union dc_tiling_info *tiling_info,
508 union plane_size *plane_size,
509 enum dc_rotation_angle rotation,
510 struct dc_plane_dcc_param *dcc,
511 bool horizontal_mirror)
512{
513 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
514 REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
515
516 program_tiling(dce_mi, tiling_info);
517 program_size_and_rotation(dce_mi, rotation, plane_size);
518
519 if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
520 format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
521 program_grph_pixel_format(dce_mi, format);
522}
523
524static uint32_t get_dmif_switch_time_us(
525 uint32_t h_total,
526 uint32_t v_total,
527 uint32_t pix_clk_khz)
528{
529 uint32_t frame_time;
530 uint32_t pixels_per_second;
531 uint32_t pixels_per_frame;
532 uint32_t refresh_rate;
533 const uint32_t us_in_sec = 1000000;
534 const uint32_t min_single_frame_time_us = 30000;
535
536 const uint32_t single_frame_time_multiplier = 2;
537
538 if (!h_total || v_total || !pix_clk_khz)
539 return single_frame_time_multiplier * min_single_frame_time_us;
540
541
542 pixels_per_second = pix_clk_khz * 1000;
543 pixels_per_frame = h_total * v_total;
544
545 if (!pixels_per_second || !pixels_per_frame) {
546
547 ASSERT(pixels_per_frame);
548 ASSERT(pixels_per_second);
549 return single_frame_time_multiplier * min_single_frame_time_us;
550 }
551
552 refresh_rate = pixels_per_second / pixels_per_frame;
553
554 if (!refresh_rate) {
555
556 ASSERT(refresh_rate);
557 return single_frame_time_multiplier * min_single_frame_time_us;
558 }
559
560 frame_time = us_in_sec / refresh_rate;
561
562 if (frame_time < min_single_frame_time_us)
563 frame_time = min_single_frame_time_us;
564
565 frame_time *= single_frame_time_multiplier;
566
567 return frame_time;
568}
569
570static void dce_mi_allocate_dmif(
571 struct mem_input *mi,
572 uint32_t h_total,
573 uint32_t v_total,
574 uint32_t pix_clk_khz,
575 uint32_t total_stream_num)
576{
577 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
578 const uint32_t retry_delay = 10;
579 uint32_t retry_count = get_dmif_switch_time_us(
580 h_total,
581 v_total,
582 pix_clk_khz) / retry_delay;
583
584 uint32_t pix_dur;
585 uint32_t buffers_allocated;
586 uint32_t dmif_buffer_control;
587
588 dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
589 DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
590
591 if (buffers_allocated == 2)
592 return;
593
594 REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
595 DMIF_BUFFERS_ALLOCATED, 2);
596
597 REG_WAIT(DMIF_BUFFER_CONTROL,
598 DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
599 retry_delay, retry_count);
600
601 if (pix_clk_khz != 0) {
602 pix_dur = 1000000000ULL / pix_clk_khz;
603
604 REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
605 PIXEL_DURATION, pix_dur);
606 }
607
608 if (dce_mi->wa.single_head_rdreq_dmif_limit) {
609 uint32_t eanble = (total_stream_num > 1) ? 0 :
610 dce_mi->wa.single_head_rdreq_dmif_limit;
611
612 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
613 ENABLE, eanble);
614 }
615}
616
617static void dce_mi_free_dmif(
618 struct mem_input *mi,
619 uint32_t total_stream_num)
620{
621 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
622 uint32_t buffers_allocated;
623 uint32_t dmif_buffer_control;
624
625 dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
626 DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
627
628 if (buffers_allocated == 0)
629 return;
630
631 REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
632 DMIF_BUFFERS_ALLOCATED, 0);
633
634 REG_WAIT(DMIF_BUFFER_CONTROL,
635 DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
636 10, 3500);
637
638 if (dce_mi->wa.single_head_rdreq_dmif_limit) {
639 uint32_t eanble = (total_stream_num > 1) ? 0 :
640 dce_mi->wa.single_head_rdreq_dmif_limit;
641
642 REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
643 ENABLE, eanble);
644 }
645}
646
647
648static void program_sec_addr(
649 struct dce_mem_input *dce_mi,
650 PHYSICAL_ADDRESS_LOC address)
651{
652
653 REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
654 GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
655 address.high_part);
656
657 REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0,
658 GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8,
659 GRPH_SECONDARY_DFQ_ENABLE, 0);
660}
661
662static void program_pri_addr(
663 struct dce_mem_input *dce_mi,
664 PHYSICAL_ADDRESS_LOC address)
665{
666
667 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
668 GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
669 address.high_part);
670
671 REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0,
672 GRPH_PRIMARY_SURFACE_ADDRESS,
673 address.low_part >> 8);
674}
675
676
677static bool dce_mi_is_flip_pending(struct mem_input *mem_input)
678{
679 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
680 uint32_t update_pending;
681
682 REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending);
683 if (update_pending)
684 return true;
685
686 mem_input->current_address = mem_input->request_address;
687 return false;
688}
689
690static bool dce_mi_program_surface_flip_and_addr(
691 struct mem_input *mem_input,
692 const struct dc_plane_address *address,
693 bool flip_immediate)
694{
695 struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input);
696
697 REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
698
699 REG_UPDATE(
700 GRPH_FLIP_CONTROL,
701 GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0);
702
703 switch (address->type) {
704 case PLN_ADDR_TYPE_GRAPHICS:
705 if (address->grph.addr.quad_part == 0)
706 break;
707 program_pri_addr(dce_mi, address->grph.addr);
708 break;
709 case PLN_ADDR_TYPE_GRPH_STEREO:
710 if (address->grph_stereo.left_addr.quad_part == 0 ||
711 address->grph_stereo.right_addr.quad_part == 0)
712 break;
713 program_pri_addr(dce_mi, address->grph_stereo.left_addr);
714 program_sec_addr(dce_mi, address->grph_stereo.right_addr);
715 break;
716 default:
717
718 BREAK_TO_DEBUGGER();
719 break;
720 }
721
722 mem_input->request_address = *address;
723
724 if (flip_immediate)
725 mem_input->current_address = *address;
726
727 REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
728
729 return true;
730}
731
732static struct mem_input_funcs dce_mi_funcs = {
733 .mem_input_program_display_marks = dce_mi_program_display_marks,
734 .allocate_mem_input = dce_mi_allocate_dmif,
735 .free_mem_input = dce_mi_free_dmif,
736 .mem_input_program_surface_flip_and_addr =
737 dce_mi_program_surface_flip_and_addr,
738 .mem_input_program_pte_vm = dce_mi_program_pte_vm,
739 .mem_input_program_surface_config =
740 dce_mi_program_surface_config,
741 .mem_input_is_flip_pending = dce_mi_is_flip_pending
742};
743
744static struct mem_input_funcs dce112_mi_funcs = {
745 .mem_input_program_display_marks = dce112_mi_program_display_marks,
746 .allocate_mem_input = dce_mi_allocate_dmif,
747 .free_mem_input = dce_mi_free_dmif,
748 .mem_input_program_surface_flip_and_addr =
749 dce_mi_program_surface_flip_and_addr,
750 .mem_input_program_pte_vm = dce_mi_program_pte_vm,
751 .mem_input_program_surface_config =
752 dce_mi_program_surface_config,
753 .mem_input_is_flip_pending = dce_mi_is_flip_pending
754};
755
756static struct mem_input_funcs dce120_mi_funcs = {
757 .mem_input_program_display_marks = dce120_mi_program_display_marks,
758 .allocate_mem_input = dce_mi_allocate_dmif,
759 .free_mem_input = dce_mi_free_dmif,
760 .mem_input_program_surface_flip_and_addr =
761 dce_mi_program_surface_flip_and_addr,
762 .mem_input_program_pte_vm = dce_mi_program_pte_vm,
763 .mem_input_program_surface_config =
764 dce_mi_program_surface_config,
765 .mem_input_is_flip_pending = dce_mi_is_flip_pending
766};
767
768void dce_mem_input_construct(
769 struct dce_mem_input *dce_mi,
770 struct dc_context *ctx,
771 int inst,
772 const struct dce_mem_input_registers *regs,
773 const struct dce_mem_input_shift *mi_shift,
774 const struct dce_mem_input_mask *mi_mask)
775{
776 dce_mi->base.ctx = ctx;
777
778 dce_mi->base.inst = inst;
779 dce_mi->base.funcs = &dce_mi_funcs;
780
781 dce_mi->regs = regs;
782 dce_mi->shifts = mi_shift;
783 dce_mi->masks = mi_mask;
784}
785
786void dce112_mem_input_construct(
787 struct dce_mem_input *dce_mi,
788 struct dc_context *ctx,
789 int inst,
790 const struct dce_mem_input_registers *regs,
791 const struct dce_mem_input_shift *mi_shift,
792 const struct dce_mem_input_mask *mi_mask)
793{
794 dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
795 dce_mi->base.funcs = &dce112_mi_funcs;
796}
797
798void dce120_mem_input_construct(
799 struct dce_mem_input *dce_mi,
800 struct dc_context *ctx,
801 int inst,
802 const struct dce_mem_input_registers *regs,
803 const struct dce_mem_input_shift *mi_shift,
804 const struct dce_mem_input_mask *mi_mask)
805{
806 dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask);
807 dce_mi->base.funcs = &dce120_mi_funcs;
808}
809