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 | 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 | |
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 | switch (rotation) { |
125 | case ROTATION_ANGLE_90: |
126 | case ROTATION_ANGLE_270: |
127 | return true; |
128 | default: |
129 | return false; |
130 | } |
131 | } |
132 | |
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(num: pte->page_width); |
145 | unsigned int page_height = log_2(num: 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, 0x7f); |
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, 0x7f); |
161 | } |
162 | |
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 | |
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 | 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 | REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, |
200 | URGENCY_WATERMARK_MASK, wm_select); |
201 | |
202 | REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0, |
203 | URGENCY_LOW_WATERMARK, urgency_low_wm, |
204 | URGENCY_HIGH_WATERMARK, urgency_high_wm); |
205 | |
206 | 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 | } |
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 | static void program_nbp_watermark( |
232 | struct dce_mem_input *dce_mi, |
233 | uint32_t wm_select, |
234 | uint32_t nbp_wm) |
235 | { |
236 | if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) { |
237 | REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, |
238 | NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select); |
239 | |
240 | 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 | REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, |
246 | NB_PSTATE_CHANGE_WATERMARK, nbp_wm); |
247 | } |
248 | |
249 | if (REG(DPG_PIPE_LOW_POWER_CONTROL)) { |
250 | REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, |
251 | PSTATE_CHANGE_WATERMARK_MASK, wm_select); |
252 | |
253 | 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 | REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL, |
259 | PSTATE_CHANGE_WATERMARK, nbp_wm); |
260 | } |
261 | } |
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 | 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 | REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, |
284 | STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); |
285 | |
286 | if (REG(DPG_PIPE_STUTTER_CONTROL2)) |
287 | 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 | REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, |
292 | STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark, |
293 | STUTTER_ENTER_SELF_REFRESH_WATERMARK, stutter_entry); |
294 | } |
295 | |
296 | static void program_stutter_watermark( |
297 | struct dce_mem_input *dce_mi, |
298 | uint32_t wm_select, |
299 | uint32_t stutter_mark) |
300 | { |
301 | REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, |
302 | STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); |
303 | |
304 | if (REG(DPG_PIPE_STUTTER_CONTROL2)) |
305 | REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2, |
306 | STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); |
307 | else |
308 | REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, |
309 | STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); |
310 | } |
311 | |
312 | 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 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); |
321 | uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; |
322 | |
323 | program_urgency_watermark(dce_mi, wm_select: 2, /* set a */ |
324 | urgency_low_wm: urgent.a_mark, urgency_high_wm: total_dest_line_time_ns); |
325 | program_urgency_watermark(dce_mi, wm_select: 1, /* set d */ |
326 | urgency_low_wm: urgent.d_mark, urgency_high_wm: total_dest_line_time_ns); |
327 | |
328 | REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, |
329 | STUTTER_ENABLE, stutter_en, |
330 | STUTTER_IGNORE_FBC, 1); |
331 | program_nbp_watermark(dce_mi, wm_select: 2, nbp_wm: nbp.a_mark); /* set a */ |
332 | program_nbp_watermark(dce_mi, wm_select: 1, nbp_wm: nbp.d_mark); /* set d */ |
333 | |
334 | program_stutter_watermark(dce_mi, wm_select: 2, stutter_mark: stutter_exit.a_mark); /* set a */ |
335 | program_stutter_watermark(dce_mi, wm_select: 1, stutter_mark: stutter_exit.d_mark); /* set d */ |
336 | } |
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, wm_select: 2, /* set a */ |
351 | urgency_low_wm: urgent.a_mark, urgency_high_wm: total_dest_line_time_ns); |
352 | dce60_program_urgency_watermark(dce_mi, wm_select: 1, /* set d */ |
353 | urgency_low_wm: urgent.d_mark, urgency_high_wm: 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, wm_select: 2, nbp_wm: nbp.a_mark); /* set a */ |
359 | dce60_program_nbp_watermark(dce_mi, wm_select: 1, nbp_wm: nbp.d_mark); /* set d */ |
360 | |
361 | dce60_program_stutter_watermark(dce_mi, wm_select: 2, stutter_mark: stutter_exit.a_mark); /* set a */ |
362 | dce60_program_stutter_watermark(dce_mi, wm_select: 1, stutter_mark: stutter_exit.d_mark); /* set d */ |
363 | } |
364 | #endif |
365 | |
366 | 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 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); |
374 | uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; |
375 | |
376 | program_urgency_watermark(dce_mi, wm_select: 0, /* set a */ |
377 | urgency_low_wm: urgent.a_mark, urgency_high_wm: total_dest_line_time_ns); |
378 | program_urgency_watermark(dce_mi, wm_select: 1, /* set b */ |
379 | urgency_low_wm: urgent.b_mark, urgency_high_wm: total_dest_line_time_ns); |
380 | program_urgency_watermark(dce_mi, wm_select: 2, /* set c */ |
381 | urgency_low_wm: urgent.c_mark, urgency_high_wm: total_dest_line_time_ns); |
382 | program_urgency_watermark(dce_mi, wm_select: 3, /* set d */ |
383 | urgency_low_wm: urgent.d_mark, urgency_high_wm: total_dest_line_time_ns); |
384 | |
385 | REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, |
386 | STUTTER_ENABLE, stutter_en, |
387 | STUTTER_IGNORE_FBC, 1); |
388 | program_nbp_watermark(dce_mi, wm_select: 0, nbp_wm: nbp.a_mark); /* set a */ |
389 | program_nbp_watermark(dce_mi, wm_select: 1, nbp_wm: nbp.b_mark); /* set b */ |
390 | program_nbp_watermark(dce_mi, wm_select: 2, nbp_wm: nbp.c_mark); /* set c */ |
391 | program_nbp_watermark(dce_mi, wm_select: 3, nbp_wm: nbp.d_mark); /* set d */ |
392 | |
393 | program_stutter_watermark(dce_mi, wm_select: 0, stutter_mark: stutter_exit.a_mark); /* set a */ |
394 | program_stutter_watermark(dce_mi, wm_select: 1, stutter_mark: stutter_exit.b_mark); /* set b */ |
395 | program_stutter_watermark(dce_mi, wm_select: 2, stutter_mark: stutter_exit.c_mark); /* set c */ |
396 | program_stutter_watermark(dce_mi, wm_select: 3, stutter_mark: stutter_exit.d_mark); /* set d */ |
397 | } |
398 | |
399 | 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 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); |
407 | uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; |
408 | |
409 | dce120_program_urgency_watermark(dce_mi, wm_select: 0, /* set a */ |
410 | urgency_low_wm: urgent.a_mark, urgency_high_wm: total_dest_line_time_ns); |
411 | dce120_program_urgency_watermark(dce_mi, wm_select: 1, /* set b */ |
412 | urgency_low_wm: urgent.b_mark, urgency_high_wm: total_dest_line_time_ns); |
413 | dce120_program_urgency_watermark(dce_mi, wm_select: 2, /* set c */ |
414 | urgency_low_wm: urgent.c_mark, urgency_high_wm: total_dest_line_time_ns); |
415 | dce120_program_urgency_watermark(dce_mi, wm_select: 3, /* set d */ |
416 | urgency_low_wm: urgent.d_mark, urgency_high_wm: total_dest_line_time_ns); |
417 | |
418 | REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, |
419 | STUTTER_ENABLE, stutter_en, |
420 | STUTTER_IGNORE_FBC, 1); |
421 | program_nbp_watermark(dce_mi, wm_select: 0, nbp_wm: nbp.a_mark); /* set a */ |
422 | program_nbp_watermark(dce_mi, wm_select: 1, nbp_wm: nbp.b_mark); /* set b */ |
423 | program_nbp_watermark(dce_mi, wm_select: 2, nbp_wm: nbp.c_mark); /* set c */ |
424 | program_nbp_watermark(dce_mi, wm_select: 3, nbp_wm: nbp.d_mark); /* set d */ |
425 | |
426 | dce120_program_stutter_watermark(dce_mi, wm_select: 0, stutter_mark: stutter_exit.a_mark, stutter_entry: stutter_entry.a_mark); /* set a */ |
427 | dce120_program_stutter_watermark(dce_mi, wm_select: 1, stutter_mark: stutter_exit.b_mark, stutter_entry: stutter_entry.b_mark); /* set b */ |
428 | dce120_program_stutter_watermark(dce_mi, wm_select: 2, stutter_mark: stutter_exit.c_mark, stutter_entry: stutter_entry.c_mark); /* set c */ |
429 | dce120_program_stutter_watermark(dce_mi, wm_select: 3, stutter_mark: stutter_exit.d_mark, stutter_entry: stutter_entry.d_mark); /* set d */ |
430 | } |
431 | |
432 | static void program_tiling( |
433 | struct dce_mem_input *dce_mi, const union dc_tiling_info *info) |
434 | { |
435 | if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */ |
436 | 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 | if (dce_mi->masks->GRPH_MICRO_TILE_MODE) { /* GFX8 */ |
450 | 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 | if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX6 but reuses gfx8 struct */ |
467 | 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 | } |
483 | |
484 | |
485 | 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 | const struct rect *in_rect = &plane_size->surface_size; |
491 | struct rect hw_rect = plane_size->surface_size; |
492 | 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 | if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) { |
500 | hw_rect.x = in_rect->y; |
501 | hw_rect.y = in_rect->x; |
502 | |
503 | hw_rect.height = in_rect->width; |
504 | hw_rect.width = in_rect->height; |
505 | } |
506 | |
507 | REG_SET(GRPH_X_START, 0, |
508 | GRPH_X_START, hw_rect.x); |
509 | |
510 | REG_SET(GRPH_Y_START, 0, |
511 | GRPH_Y_START, hw_rect.y); |
512 | |
513 | REG_SET(GRPH_X_END, 0, |
514 | GRPH_X_END, hw_rect.width); |
515 | |
516 | REG_SET(GRPH_Y_END, 0, |
517 | GRPH_Y_END, hw_rect.height); |
518 | |
519 | REG_SET(GRPH_PITCH, 0, |
520 | GRPH_PITCH, plane_size->surface_pitch); |
521 | |
522 | REG_SET(HW_ROTATION, 0, |
523 | GRPH_ROTATION_ANGLE, rotation_angles[rotation]); |
524 | } |
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 | static void program_grph_pixel_format( |
557 | struct dce_mem_input *dce_mi, |
558 | enum surface_pixel_format format) |
559 | { |
560 | uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ |
561 | uint32_t grph_depth = 0, grph_format = 0; |
562 | uint32_t sign = 0, floating = 0; |
563 | |
564 | if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || |
565 | /*todo: doesn't look like we handle BGRA here, |
566 | * should problem swap endian*/ |
567 | format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || |
568 | format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS || |
569 | format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 || |
570 | format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { |
571 | /* ABGR formats */ |
572 | red_xbar = 2; |
573 | blue_xbar = 2; |
574 | } |
575 | |
576 | REG_SET_2(GRPH_SWAP_CNTL, 0, |
577 | GRPH_RED_CROSSBAR, red_xbar, |
578 | GRPH_BLUE_CROSSBAR, blue_xbar); |
579 | |
580 | 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 | grph_depth = 1; |
587 | grph_format = 0; |
588 | break; |
589 | case SURFACE_PIXEL_FORMAT_GRPH_RGB565: |
590 | grph_depth = 1; |
591 | grph_format = 1; |
592 | break; |
593 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: |
594 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: |
595 | grph_depth = 2; |
596 | grph_format = 0; |
597 | 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 | grph_depth = 2; |
602 | grph_format = 1; |
603 | break; |
604 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: |
605 | sign = 1; |
606 | 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 | DC_ERR("unsupported grph pixel format" ); |
616 | break; |
617 | } |
618 | |
619 | REG_UPDATE_2(GRPH_CONTROL, |
620 | GRPH_DEPTH, grph_depth, |
621 | GRPH_FORMAT, grph_format); |
622 | |
623 | 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 | } |
629 | |
630 | 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 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); |
640 | REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); |
641 | |
642 | program_tiling(dce_mi, info: tiling_info); |
643 | program_size_and_rotation(dce_mi, rotation, plane_size); |
644 | |
645 | if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && |
646 | format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) |
647 | program_grph_pixel_format(dce_mi, format); |
648 | } |
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, info: 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 | 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 | const uint32_t us_in_sec = 1000000; |
682 | const uint32_t min_single_frame_time_us = 30000; |
683 | /*return double of frame time*/ |
684 | const uint32_t single_frame_time_multiplier = 2; |
685 | |
686 | 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 | pixels_per_second = pix_clk_khz * 1000; |
691 | pixels_per_frame = h_total * v_total; |
692 | |
693 | if (!pixels_per_second || !pixels_per_frame) { |
694 | /* avoid division by zero */ |
695 | ASSERT(pixels_per_frame); |
696 | ASSERT(pixels_per_second); |
697 | return single_frame_time_multiplier * min_single_frame_time_us; |
698 | } |
699 | |
700 | refresh_rate = pixels_per_second / pixels_per_frame; |
701 | |
702 | if (!refresh_rate) { |
703 | /* avoid division by zero*/ |
704 | ASSERT(refresh_rate); |
705 | return single_frame_time_multiplier * min_single_frame_time_us; |
706 | } |
707 | |
708 | frame_time = us_in_sec / refresh_rate; |
709 | |
710 | if (frame_time < min_single_frame_time_us) |
711 | frame_time = min_single_frame_time_us; |
712 | |
713 | frame_time *= single_frame_time_multiplier; |
714 | |
715 | return frame_time; |
716 | } |
717 | |
718 | 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 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); |
726 | const uint32_t retry_delay = 10; |
727 | 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 | dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, |
737 | DMIF_BUFFERS_ALLOCATED, &buffers_allocated); |
738 | |
739 | if (buffers_allocated == 2) |
740 | return; |
741 | |
742 | REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, |
743 | DMIF_BUFFERS_ALLOCATED, 2); |
744 | |
745 | REG_WAIT(DMIF_BUFFER_CONTROL, |
746 | DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, |
747 | retry_delay, retry_count); |
748 | |
749 | if (pix_clk_khz != 0) { |
750 | pix_dur = 1000000000ULL / pix_clk_khz; |
751 | |
752 | REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1, |
753 | PIXEL_DURATION, pix_dur); |
754 | } |
755 | |
756 | if (dce_mi->wa.single_head_rdreq_dmif_limit) { |
757 | uint32_t enable = (total_stream_num > 1) ? 0 : |
758 | dce_mi->wa.single_head_rdreq_dmif_limit; |
759 | |
760 | REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, |
761 | ENABLE, enable); |
762 | } |
763 | } |
764 | |
765 | static void dce_mi_free_dmif( |
766 | struct mem_input *mi, |
767 | uint32_t total_stream_num) |
768 | { |
769 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); |
770 | uint32_t buffers_allocated; |
771 | uint32_t dmif_buffer_control; |
772 | |
773 | dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, |
774 | DMIF_BUFFERS_ALLOCATED, &buffers_allocated); |
775 | |
776 | if (buffers_allocated == 0) |
777 | return; |
778 | |
779 | REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, |
780 | DMIF_BUFFERS_ALLOCATED, 0); |
781 | |
782 | REG_WAIT(DMIF_BUFFER_CONTROL, |
783 | DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, |
784 | 10, 3500); |
785 | |
786 | if (dce_mi->wa.single_head_rdreq_dmif_limit) { |
787 | uint32_t enable = (total_stream_num > 1) ? 0 : |
788 | dce_mi->wa.single_head_rdreq_dmif_limit; |
789 | |
790 | REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, |
791 | ENABLE, enable); |
792 | } |
793 | } |
794 | |
795 | |
796 | 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 | REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0, |
802 | GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, |
803 | address.high_part); |
804 | |
805 | REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0, |
806 | GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8, |
807 | GRPH_SECONDARY_DFQ_ENABLE, 0); |
808 | } |
809 | |
810 | 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 | REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0, |
816 | GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, |
817 | address.high_part); |
818 | |
819 | REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0, |
820 | GRPH_PRIMARY_SURFACE_ADDRESS, |
821 | address.low_part >> 8); |
822 | } |
823 | |
824 | |
825 | static bool dce_mi_is_flip_pending(struct mem_input *mem_input) |
826 | { |
827 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); |
828 | uint32_t update_pending; |
829 | |
830 | REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending); |
831 | if (update_pending) |
832 | return true; |
833 | |
834 | mem_input->current_address = mem_input->request_address; |
835 | return false; |
836 | } |
837 | |
838 | 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 | struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); |
844 | |
845 | REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); |
846 | |
847 | REG_UPDATE( |
848 | GRPH_FLIP_CONTROL, |
849 | GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0); |
850 | |
851 | switch (address->type) { |
852 | case PLN_ADDR_TYPE_GRAPHICS: |
853 | if (address->grph.addr.quad_part == 0) |
854 | break; |
855 | program_pri_addr(dce_mi, address: address->grph.addr); |
856 | break; |
857 | case PLN_ADDR_TYPE_GRPH_STEREO: |
858 | if (address->grph_stereo.left_addr.quad_part == 0 || |
859 | address->grph_stereo.right_addr.quad_part == 0) |
860 | break; |
861 | program_pri_addr(dce_mi, address: address->grph_stereo.left_addr); |
862 | program_sec_addr(dce_mi, address: address->grph_stereo.right_addr); |
863 | break; |
864 | default: |
865 | /* not supported */ |
866 | BREAK_TO_DEBUGGER(); |
867 | break; |
868 | } |
869 | |
870 | mem_input->request_address = *address; |
871 | |
872 | if (flip_immediate) |
873 | mem_input->current_address = *address; |
874 | |
875 | REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0); |
876 | |
877 | 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 | 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 | dce_mi->base.ctx = ctx; |
939 | |
940 | dce_mi->base.inst = inst; |
941 | dce_mi->base.funcs = &dce_mi_funcs; |
942 | |
943 | dce_mi->regs = regs; |
944 | dce_mi->shifts = mi_shift; |
945 | dce_mi->masks = mi_mask; |
946 | } |
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 | 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 | dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); |
971 | dce_mi->base.funcs = &dce112_mi_funcs; |
972 | } |
973 | |
974 | 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 | dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); |
983 | dce_mi->base.funcs = &dce120_mi_funcs; |
984 | } |
985 | |