xref: /dragonfly/sys/dev/drm/amd/display/dc/dce/dce_mem_input.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
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 
get_mi_bpp(enum surface_pixel_format format)87 static 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 
get_mi_tiling(union dc_tiling_info * tiling_info)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 
is_vert_scan(enum dc_rotation_angle rotation)122 static 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 
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 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           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 
program_urgency_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t urgency_low_wm,uint32_t urgency_high_wm)163 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           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 
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 static 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 
program_nbp_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t nbp_wm)196 static 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 
dce120_program_stutter_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t stutter_mark,uint32_t stutter_entry)228 static 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 
program_stutter_watermark(struct dce_mem_input * dce_mi,uint32_t wm_select,uint32_t stutter_mark)247 static 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 
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 static 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, /* set a */
275                               urgent.a_mark, total_dest_line_time_ns);
276           program_urgency_watermark(dce_mi, 1, /* set d */
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); /* set a */
283           program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */
284 
285           program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */
286           program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */
287 }
288 
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 static 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, /* set a */
300                               urgent.a_mark, total_dest_line_time_ns);
301           program_urgency_watermark(dce_mi, 1, /* set b */
302                               urgent.b_mark, total_dest_line_time_ns);
303           program_urgency_watermark(dce_mi, 2, /* set c */
304                               urgent.c_mark, total_dest_line_time_ns);
305           program_urgency_watermark(dce_mi, 3, /* set d */
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); /* set a */
312           program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
313           program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
314           program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
315 
316           program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark); /* set a */
317           program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark); /* set b */
318           program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark); /* set c */
319           program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark); /* set d */
320 }
321 
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 static 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, /* set a */
333                               urgent.a_mark, total_dest_line_time_ns);
334           dce120_program_urgency_watermark(dce_mi, 1, /* set b */
335                               urgent.b_mark, total_dest_line_time_ns);
336           dce120_program_urgency_watermark(dce_mi, 2, /* set c */
337                               urgent.c_mark, total_dest_line_time_ns);
338           dce120_program_urgency_watermark(dce_mi, 3, /* set d */
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); /* set a */
345           program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */
346           program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */
347           program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */
348 
349           dce120_program_stutter_watermark(dce_mi, 0, stutter_exit.a_mark, stutter_entry.a_mark); /* set a */
350           dce120_program_stutter_watermark(dce_mi, 1, stutter_exit.b_mark, stutter_entry.b_mark); /* set b */
351           dce120_program_stutter_watermark(dce_mi, 2, stutter_exit.c_mark, stutter_entry.c_mark); /* set c */
352           dce120_program_stutter_watermark(dce_mi, 3, stutter_exit.d_mark, stutter_entry.d_mark); /* set d */
353 }
354 
program_tiling(struct dce_mem_input * dce_mi,const union dc_tiling_info * info)355 static 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) { /* GFX9 */
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                     /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info
367                     GRPH_SE_ENABLE, 1,
368                     GRPH_Z, 0);
369                      */
370           }
371 
372           if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */
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                     /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
384                     /*
385                                         GRPH_Z, 0);
386                                         */
387           }
388 }
389 
390 
program_size_and_rotation(struct dce_mem_input * dce_mi,enum dc_rotation_angle rotation,const union plane_size * plane_size)391 static 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 
program_grph_pixel_format(struct dce_mem_input * dce_mi,enum surface_pixel_format format)432 static 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; /* no swap */
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                               /*todo: doesn't look like we handle BGRA here,
442                                *  should problem swap endian*/
443                     format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
444                     format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
445                     format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
446                     /* ABGR formats */
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                     /* no break */
483           case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
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 
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 static 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 
get_dmif_switch_time_us(uint32_t h_total,uint32_t v_total,uint32_t pix_clk_khz)524 static 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           /*return double of frame time*/
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           /*TODO: should we use pixel format normalized pixel clock here?*/
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                     /* avoid division by zero */
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                     /* avoid division by zero*/
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 
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 static 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 
dce_mi_free_dmif(struct mem_input * mi,uint32_t total_stream_num)617 static 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 
program_sec_addr(struct dce_mem_input * dce_mi,PHYSICAL_ADDRESS_LOC address)648 static void program_sec_addr(
649           struct dce_mem_input *dce_mi,
650           PHYSICAL_ADDRESS_LOC address)
651 {
652           /*high register MUST be programmed first*/
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 
program_pri_addr(struct dce_mem_input * dce_mi,PHYSICAL_ADDRESS_LOC address)662 static void program_pri_addr(
663           struct dce_mem_input *dce_mi,
664           PHYSICAL_ADDRESS_LOC address)
665 {
666           /*high register MUST be programmed first*/
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 
dce_mi_is_flip_pending(struct mem_input * mem_input)677 static 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 
dce_mi_program_surface_flip_and_addr(struct mem_input * mem_input,const struct dc_plane_address * address,bool flip_immediate)690 static 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                     /* not supported */
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 
732 static const 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 
744 static const 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 
756 static const 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 
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 void 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 
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 void 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 
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 void 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