1 | /* |
2 | * Copyright 2012-16 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 | #include "dm_services.h" |
26 | |
27 | #include "dce/dce_11_0_d.h" |
28 | #include "dce/dce_11_0_sh_mask.h" |
29 | /* TODO: this needs to be looked at, used by Stella's workaround*/ |
30 | #include "gmc/gmc_8_2_d.h" |
31 | #include "gmc/gmc_8_2_sh_mask.h" |
32 | |
33 | #include "include/logger_interface.h" |
34 | #include "inc/dce_calcs.h" |
35 | |
36 | #include "dce/dce_mem_input.h" |
37 | #include "dce110_mem_input_v.h" |
38 | |
39 | static void set_flip_control( |
40 | struct dce_mem_input *mem_input110, |
41 | bool immediate) |
42 | { |
43 | uint32_t value = 0; |
44 | |
45 | value = dm_read_reg( |
46 | mem_input110->base.ctx, |
47 | mmUNP_FLIP_CONTROL); |
48 | |
49 | set_reg_field_value(value, 1, |
50 | UNP_FLIP_CONTROL, |
51 | GRPH_SURFACE_UPDATE_PENDING_MODE); |
52 | |
53 | dm_write_reg( |
54 | mem_input110->base.ctx, |
55 | mmUNP_FLIP_CONTROL, |
56 | value); |
57 | } |
58 | |
59 | /* chroma part */ |
60 | static void program_pri_addr_c( |
61 | struct dce_mem_input *mem_input110, |
62 | PHYSICAL_ADDRESS_LOC address) |
63 | { |
64 | uint32_t value = 0; |
65 | uint32_t temp = 0; |
66 | /*high register MUST be programmed first*/ |
67 | temp = address.high_part & |
68 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MASK; |
69 | |
70 | set_reg_field_value(value, temp, |
71 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C, |
72 | GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C); |
73 | |
74 | dm_write_reg( |
75 | mem_input110->base.ctx, |
76 | mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C, |
77 | value); |
78 | |
79 | temp = 0; |
80 | value = 0; |
81 | temp = address.low_part >> |
82 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT; |
83 | |
84 | set_reg_field_value(value, temp, |
85 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C, |
86 | GRPH_PRIMARY_SURFACE_ADDRESS_C); |
87 | |
88 | dm_write_reg( |
89 | mem_input110->base.ctx, |
90 | mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C, |
91 | value); |
92 | } |
93 | |
94 | /* luma part */ |
95 | static void program_pri_addr_l( |
96 | struct dce_mem_input *mem_input110, |
97 | PHYSICAL_ADDRESS_LOC address) |
98 | { |
99 | uint32_t value = 0; |
100 | uint32_t temp = 0; |
101 | |
102 | /*high register MUST be programmed first*/ |
103 | temp = address.high_part & |
104 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK; |
105 | |
106 | set_reg_field_value(value, temp, |
107 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, |
108 | GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L); |
109 | |
110 | dm_write_reg( |
111 | mem_input110->base.ctx, |
112 | mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, |
113 | value); |
114 | |
115 | temp = 0; |
116 | value = 0; |
117 | temp = address.low_part >> |
118 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT; |
119 | |
120 | set_reg_field_value(value, temp, |
121 | UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, |
122 | GRPH_PRIMARY_SURFACE_ADDRESS_L); |
123 | |
124 | dm_write_reg( |
125 | mem_input110->base.ctx, |
126 | mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, |
127 | value); |
128 | } |
129 | |
130 | static void program_addr( |
131 | struct dce_mem_input *mem_input110, |
132 | const struct dc_plane_address *addr) |
133 | { |
134 | switch (addr->type) { |
135 | case PLN_ADDR_TYPE_GRAPHICS: |
136 | program_pri_addr_l( |
137 | mem_input110, |
138 | address: addr->grph.addr); |
139 | break; |
140 | case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: |
141 | program_pri_addr_c( |
142 | mem_input110, |
143 | address: addr->video_progressive.chroma_addr); |
144 | program_pri_addr_l( |
145 | mem_input110, |
146 | address: addr->video_progressive.luma_addr); |
147 | break; |
148 | default: |
149 | /* not supported */ |
150 | BREAK_TO_DEBUGGER(); |
151 | } |
152 | } |
153 | |
154 | static void enable(struct dce_mem_input *mem_input110) |
155 | { |
156 | uint32_t value = 0; |
157 | |
158 | value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_ENABLE); |
159 | set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE); |
160 | dm_write_reg(mem_input110->base.ctx, |
161 | mmUNP_GRPH_ENABLE, |
162 | value); |
163 | } |
164 | |
165 | static void program_tiling( |
166 | struct dce_mem_input *mem_input110, |
167 | const union dc_tiling_info *info, |
168 | const enum surface_pixel_format pixel_format) |
169 | { |
170 | uint32_t value = 0; |
171 | |
172 | set_reg_field_value(value, info->gfx8.num_banks, |
173 | UNP_GRPH_CONTROL, GRPH_NUM_BANKS); |
174 | |
175 | set_reg_field_value(value, info->gfx8.bank_width, |
176 | UNP_GRPH_CONTROL, GRPH_BANK_WIDTH_L); |
177 | |
178 | set_reg_field_value(value, info->gfx8.bank_height, |
179 | UNP_GRPH_CONTROL, GRPH_BANK_HEIGHT_L); |
180 | |
181 | set_reg_field_value(value, info->gfx8.tile_aspect, |
182 | UNP_GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT_L); |
183 | |
184 | set_reg_field_value(value, info->gfx8.tile_split, |
185 | UNP_GRPH_CONTROL, GRPH_TILE_SPLIT_L); |
186 | |
187 | set_reg_field_value(value, info->gfx8.tile_mode, |
188 | UNP_GRPH_CONTROL, GRPH_MICRO_TILE_MODE_L); |
189 | |
190 | set_reg_field_value(value, info->gfx8.pipe_config, |
191 | UNP_GRPH_CONTROL, GRPH_PIPE_CONFIG); |
192 | |
193 | set_reg_field_value(value, info->gfx8.array_mode, |
194 | UNP_GRPH_CONTROL, GRPH_ARRAY_MODE); |
195 | |
196 | set_reg_field_value(value, 1, |
197 | UNP_GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE); |
198 | |
199 | set_reg_field_value(value, 0, |
200 | UNP_GRPH_CONTROL, GRPH_Z); |
201 | |
202 | dm_write_reg( |
203 | mem_input110->base.ctx, |
204 | mmUNP_GRPH_CONTROL, |
205 | value); |
206 | |
207 | value = 0; |
208 | |
209 | set_reg_field_value(value, info->gfx8.bank_width_c, |
210 | UNP_GRPH_CONTROL_C, GRPH_BANK_WIDTH_C); |
211 | |
212 | set_reg_field_value(value, info->gfx8.bank_height_c, |
213 | UNP_GRPH_CONTROL_C, GRPH_BANK_HEIGHT_C); |
214 | |
215 | set_reg_field_value(value, info->gfx8.tile_aspect_c, |
216 | UNP_GRPH_CONTROL_C, GRPH_MACRO_TILE_ASPECT_C); |
217 | |
218 | set_reg_field_value(value, info->gfx8.tile_split_c, |
219 | UNP_GRPH_CONTROL_C, GRPH_TILE_SPLIT_C); |
220 | |
221 | set_reg_field_value(value, info->gfx8.tile_mode_c, |
222 | UNP_GRPH_CONTROL_C, GRPH_MICRO_TILE_MODE_C); |
223 | |
224 | dm_write_reg( |
225 | mem_input110->base.ctx, |
226 | mmUNP_GRPH_CONTROL_C, |
227 | value); |
228 | } |
229 | |
230 | static void program_size_and_rotation( |
231 | struct dce_mem_input *mem_input110, |
232 | enum dc_rotation_angle rotation, |
233 | const struct plane_size *plane_size) |
234 | { |
235 | uint32_t value = 0; |
236 | struct plane_size local_size = *plane_size; |
237 | |
238 | if (rotation == ROTATION_ANGLE_90 || |
239 | rotation == ROTATION_ANGLE_270) { |
240 | |
241 | swap(local_size.surface_size.x, |
242 | local_size.surface_size.y); |
243 | swap(local_size.surface_size.width, |
244 | local_size.surface_size.height); |
245 | swap(local_size.chroma_size.x, |
246 | local_size.chroma_size.y); |
247 | swap(local_size.chroma_size.width, |
248 | local_size.chroma_size.height); |
249 | } |
250 | |
251 | value = 0; |
252 | set_reg_field_value(value, local_size.surface_pitch, |
253 | UNP_GRPH_PITCH_L, GRPH_PITCH_L); |
254 | |
255 | dm_write_reg( |
256 | mem_input110->base.ctx, |
257 | mmUNP_GRPH_PITCH_L, |
258 | value); |
259 | |
260 | value = 0; |
261 | set_reg_field_value(value, local_size.chroma_pitch, |
262 | UNP_GRPH_PITCH_C, GRPH_PITCH_C); |
263 | dm_write_reg( |
264 | mem_input110->base.ctx, |
265 | mmUNP_GRPH_PITCH_C, |
266 | value); |
267 | |
268 | value = 0; |
269 | set_reg_field_value(value, 0, |
270 | UNP_GRPH_X_START_L, GRPH_X_START_L); |
271 | dm_write_reg( |
272 | mem_input110->base.ctx, |
273 | mmUNP_GRPH_X_START_L, |
274 | value); |
275 | |
276 | value = 0; |
277 | set_reg_field_value(value, 0, |
278 | UNP_GRPH_X_START_C, GRPH_X_START_C); |
279 | dm_write_reg( |
280 | mem_input110->base.ctx, |
281 | mmUNP_GRPH_X_START_C, |
282 | value); |
283 | |
284 | value = 0; |
285 | set_reg_field_value(value, 0, |
286 | UNP_GRPH_Y_START_L, GRPH_Y_START_L); |
287 | dm_write_reg( |
288 | mem_input110->base.ctx, |
289 | mmUNP_GRPH_Y_START_L, |
290 | value); |
291 | |
292 | value = 0; |
293 | set_reg_field_value(value, 0, |
294 | UNP_GRPH_Y_START_C, GRPH_Y_START_C); |
295 | dm_write_reg( |
296 | mem_input110->base.ctx, |
297 | mmUNP_GRPH_Y_START_C, |
298 | value); |
299 | |
300 | value = 0; |
301 | set_reg_field_value(value, local_size.surface_size.x + |
302 | local_size.surface_size.width, |
303 | UNP_GRPH_X_END_L, GRPH_X_END_L); |
304 | dm_write_reg( |
305 | mem_input110->base.ctx, |
306 | mmUNP_GRPH_X_END_L, |
307 | value); |
308 | |
309 | value = 0; |
310 | set_reg_field_value(value, local_size.chroma_size.x + |
311 | local_size.chroma_size.width, |
312 | UNP_GRPH_X_END_C, GRPH_X_END_C); |
313 | dm_write_reg( |
314 | mem_input110->base.ctx, |
315 | mmUNP_GRPH_X_END_C, |
316 | value); |
317 | |
318 | value = 0; |
319 | set_reg_field_value(value, local_size.surface_size.y + |
320 | local_size.surface_size.height, |
321 | UNP_GRPH_Y_END_L, GRPH_Y_END_L); |
322 | dm_write_reg( |
323 | mem_input110->base.ctx, |
324 | mmUNP_GRPH_Y_END_L, |
325 | value); |
326 | |
327 | value = 0; |
328 | set_reg_field_value(value, local_size.chroma_size.y + |
329 | local_size.chroma_size.height, |
330 | UNP_GRPH_Y_END_C, GRPH_Y_END_C); |
331 | dm_write_reg( |
332 | mem_input110->base.ctx, |
333 | mmUNP_GRPH_Y_END_C, |
334 | value); |
335 | |
336 | value = 0; |
337 | switch (rotation) { |
338 | case ROTATION_ANGLE_90: |
339 | set_reg_field_value(value, 3, |
340 | UNP_HW_ROTATION, ROTATION_ANGLE); |
341 | break; |
342 | case ROTATION_ANGLE_180: |
343 | set_reg_field_value(value, 2, |
344 | UNP_HW_ROTATION, ROTATION_ANGLE); |
345 | break; |
346 | case ROTATION_ANGLE_270: |
347 | set_reg_field_value(value, 1, |
348 | UNP_HW_ROTATION, ROTATION_ANGLE); |
349 | break; |
350 | default: |
351 | set_reg_field_value(value, 0, |
352 | UNP_HW_ROTATION, ROTATION_ANGLE); |
353 | break; |
354 | } |
355 | |
356 | dm_write_reg( |
357 | mem_input110->base.ctx, |
358 | mmUNP_HW_ROTATION, |
359 | value); |
360 | } |
361 | |
362 | static void program_pixel_format( |
363 | struct dce_mem_input *mem_input110, |
364 | enum surface_pixel_format format) |
365 | { |
366 | if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { |
367 | uint32_t value; |
368 | uint8_t grph_depth; |
369 | uint8_t grph_format; |
370 | |
371 | value = dm_read_reg( |
372 | mem_input110->base.ctx, |
373 | mmUNP_GRPH_CONTROL); |
374 | |
375 | switch (format) { |
376 | case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: |
377 | grph_depth = 0; |
378 | grph_format = 0; |
379 | break; |
380 | case SURFACE_PIXEL_FORMAT_GRPH_RGB565: |
381 | grph_depth = 1; |
382 | grph_format = 1; |
383 | break; |
384 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: |
385 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: |
386 | grph_depth = 2; |
387 | grph_format = 0; |
388 | break; |
389 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: |
390 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: |
391 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: |
392 | grph_depth = 2; |
393 | grph_format = 1; |
394 | break; |
395 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: |
396 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: |
397 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: |
398 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: |
399 | grph_depth = 3; |
400 | grph_format = 0; |
401 | break; |
402 | default: |
403 | grph_depth = 2; |
404 | grph_format = 0; |
405 | break; |
406 | } |
407 | |
408 | set_reg_field_value( |
409 | value, |
410 | grph_depth, |
411 | UNP_GRPH_CONTROL, |
412 | GRPH_DEPTH); |
413 | set_reg_field_value( |
414 | value, |
415 | grph_format, |
416 | UNP_GRPH_CONTROL, |
417 | GRPH_FORMAT); |
418 | |
419 | dm_write_reg( |
420 | mem_input110->base.ctx, |
421 | mmUNP_GRPH_CONTROL, |
422 | value); |
423 | |
424 | value = dm_read_reg( |
425 | mem_input110->base.ctx, |
426 | mmUNP_GRPH_CONTROL_EXP); |
427 | |
428 | /* VIDEO FORMAT 0 */ |
429 | set_reg_field_value( |
430 | value, |
431 | 0, |
432 | UNP_GRPH_CONTROL_EXP, |
433 | VIDEO_FORMAT); |
434 | dm_write_reg( |
435 | mem_input110->base.ctx, |
436 | mmUNP_GRPH_CONTROL_EXP, |
437 | value); |
438 | |
439 | } else { |
440 | /* Video 422 and 420 needs UNP_GRPH_CONTROL_EXP programmed */ |
441 | uint32_t value; |
442 | uint8_t video_format; |
443 | |
444 | value = dm_read_reg( |
445 | mem_input110->base.ctx, |
446 | mmUNP_GRPH_CONTROL_EXP); |
447 | |
448 | switch (format) { |
449 | case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: |
450 | video_format = 2; |
451 | break; |
452 | case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: |
453 | video_format = 3; |
454 | break; |
455 | default: |
456 | video_format = 0; |
457 | break; |
458 | } |
459 | |
460 | set_reg_field_value( |
461 | value, |
462 | video_format, |
463 | UNP_GRPH_CONTROL_EXP, |
464 | VIDEO_FORMAT); |
465 | |
466 | dm_write_reg( |
467 | mem_input110->base.ctx, |
468 | mmUNP_GRPH_CONTROL_EXP, |
469 | value); |
470 | } |
471 | } |
472 | |
473 | static bool dce_mem_input_v_is_surface_pending(struct mem_input *mem_input) |
474 | { |
475 | struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); |
476 | uint32_t value; |
477 | |
478 | value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_UPDATE); |
479 | |
480 | if (get_reg_field_value(value, UNP_GRPH_UPDATE, |
481 | GRPH_SURFACE_UPDATE_PENDING)) |
482 | return true; |
483 | |
484 | mem_input->current_address = mem_input->request_address; |
485 | return false; |
486 | } |
487 | |
488 | static bool dce_mem_input_v_program_surface_flip_and_addr( |
489 | struct mem_input *mem_input, |
490 | const struct dc_plane_address *address, |
491 | bool flip_immediate) |
492 | { |
493 | struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); |
494 | |
495 | set_flip_control(mem_input110, immediate: flip_immediate); |
496 | program_addr(mem_input110, |
497 | addr: address); |
498 | |
499 | mem_input->request_address = *address; |
500 | |
501 | return true; |
502 | } |
503 | |
504 | /* Scatter Gather param tables */ |
505 | static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = { |
506 | { 8, 64, 64, 8, 8, 1, 4, 0, 0}, |
507 | { 16, 64, 32, 8, 16, 1, 8, 0, 0}, |
508 | { 32, 32, 32, 16, 16, 1, 8, 0, 0}, |
509 | { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ |
510 | }; |
511 | |
512 | static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = { |
513 | { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ |
514 | { 16, 256, 8, 2, 0, 1, 0, 0, 0}, |
515 | { 32, 128, 8, 4, 0, 1, 0, 0, 0}, |
516 | { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ |
517 | }; |
518 | |
519 | static const unsigned int dvmm_Hw_Setting_Linear[4][9] = { |
520 | { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, |
521 | { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, |
522 | { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, |
523 | { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ |
524 | }; |
525 | |
526 | /* Helper to get table entry from surface info */ |
527 | static const unsigned int *get_dvmm_hw_setting( |
528 | union dc_tiling_info *tiling_info, |
529 | enum surface_pixel_format format, |
530 | bool chroma) |
531 | { |
532 | enum bits_per_pixel { |
533 | bpp_8 = 0, |
534 | bpp_16, |
535 | bpp_32, |
536 | bpp_64 |
537 | } bpp; |
538 | |
539 | if (format >= SURFACE_PIXEL_FORMAT_INVALID) |
540 | bpp = bpp_32; |
541 | else if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) |
542 | bpp = chroma ? bpp_16 : bpp_8; |
543 | else |
544 | bpp = bpp_8; |
545 | |
546 | switch (tiling_info->gfx8.array_mode) { |
547 | case DC_ARRAY_1D_TILED_THIN1: |
548 | case DC_ARRAY_1D_TILED_THICK: |
549 | case DC_ARRAY_PRT_TILED_THIN1: |
550 | return dvmm_Hw_Setting_1DTiling[bpp]; |
551 | case DC_ARRAY_2D_TILED_THIN1: |
552 | case DC_ARRAY_2D_TILED_THICK: |
553 | case DC_ARRAY_2D_TILED_X_THICK: |
554 | case DC_ARRAY_PRT_2D_TILED_THIN1: |
555 | case DC_ARRAY_PRT_2D_TILED_THICK: |
556 | return dvmm_Hw_Setting_2DTiling[bpp]; |
557 | case DC_ARRAY_LINEAR_GENERAL: |
558 | case DC_ARRAY_LINEAR_ALLIGNED: |
559 | return dvmm_Hw_Setting_Linear[bpp]; |
560 | default: |
561 | return dvmm_Hw_Setting_2DTiling[bpp]; |
562 | } |
563 | } |
564 | |
565 | static void dce_mem_input_v_program_pte_vm( |
566 | struct mem_input *mem_input, |
567 | enum surface_pixel_format format, |
568 | union dc_tiling_info *tiling_info, |
569 | enum dc_rotation_angle rotation) |
570 | { |
571 | struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); |
572 | const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format, chroma: false); |
573 | const unsigned int *pte_chroma = get_dvmm_hw_setting(tiling_info, format, chroma: true); |
574 | |
575 | unsigned int page_width = 0; |
576 | unsigned int page_height = 0; |
577 | unsigned int page_width_chroma = 0; |
578 | unsigned int page_height_chroma = 0; |
579 | unsigned int temp_page_width = pte[1]; |
580 | unsigned int temp_page_height = pte[2]; |
581 | unsigned int min_pte_before_flip = 0; |
582 | unsigned int min_pte_before_flip_chroma = 0; |
583 | uint32_t value = 0; |
584 | |
585 | while ((temp_page_width >>= 1) != 0) |
586 | page_width++; |
587 | while ((temp_page_height >>= 1) != 0) |
588 | page_height++; |
589 | |
590 | temp_page_width = pte_chroma[1]; |
591 | temp_page_height = pte_chroma[2]; |
592 | while ((temp_page_width >>= 1) != 0) |
593 | page_width_chroma++; |
594 | while ((temp_page_height >>= 1) != 0) |
595 | page_height_chroma++; |
596 | |
597 | switch (rotation) { |
598 | case ROTATION_ANGLE_90: |
599 | case ROTATION_ANGLE_270: |
600 | min_pte_before_flip = pte[4]; |
601 | min_pte_before_flip_chroma = pte_chroma[4]; |
602 | break; |
603 | default: |
604 | min_pte_before_flip = pte[3]; |
605 | min_pte_before_flip_chroma = pte_chroma[3]; |
606 | break; |
607 | } |
608 | |
609 | value = dm_read_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT); |
610 | /* TODO: un-hardcode requestlimit */ |
611 | set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L); |
612 | set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C); |
613 | dm_write_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT, value); |
614 | |
615 | value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL); |
616 | set_reg_field_value(value, page_width, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); |
617 | set_reg_field_value(value, page_height, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); |
618 | set_reg_field_value(value, min_pte_before_flip, UNP_DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); |
619 | dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL, value); |
620 | |
621 | value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL); |
622 | set_reg_field_value(value, pte[5], UNP_DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); |
623 | set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); |
624 | dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL, value); |
625 | |
626 | value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C); |
627 | set_reg_field_value(value, page_width_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_WIDTH_C); |
628 | set_reg_field_value(value, page_height_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_HEIGHT_C); |
629 | set_reg_field_value(value, min_pte_before_flip_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_MIN_PTE_BEFORE_FLIP_C); |
630 | dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C, value); |
631 | |
632 | value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C); |
633 | set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C); |
634 | set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C); |
635 | dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C, value); |
636 | } |
637 | |
638 | static void dce_mem_input_v_program_surface_config( |
639 | struct mem_input *mem_input, |
640 | enum surface_pixel_format format, |
641 | union dc_tiling_info *tiling_info, |
642 | struct plane_size *plane_size, |
643 | enum dc_rotation_angle rotation, |
644 | struct dc_plane_dcc_param *dcc, |
645 | bool horizotal_mirror) |
646 | { |
647 | struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); |
648 | |
649 | enable(mem_input110); |
650 | program_tiling(mem_input110, info: tiling_info, pixel_format: format); |
651 | program_size_and_rotation(mem_input110, rotation, plane_size); |
652 | program_pixel_format(mem_input110, format); |
653 | } |
654 | |
655 | static void program_urgency_watermark( |
656 | const struct dc_context *ctx, |
657 | const uint32_t urgency_addr, |
658 | const uint32_t wm_addr, |
659 | struct dce_watermarks marks_low, |
660 | uint32_t total_dest_line_time_ns) |
661 | { |
662 | /* register value */ |
663 | uint32_t urgency_cntl = 0; |
664 | uint32_t wm_mask_cntl = 0; |
665 | |
666 | /*Write mask to enable reading/writing of watermark set A*/ |
667 | wm_mask_cntl = dm_read_reg(ctx, wm_addr); |
668 | set_reg_field_value(wm_mask_cntl, |
669 | 1, |
670 | DPGV0_WATERMARK_MASK_CONTROL, |
671 | URGENCY_WATERMARK_MASK); |
672 | dm_write_reg(ctx, wm_addr, wm_mask_cntl); |
673 | |
674 | urgency_cntl = dm_read_reg(ctx, urgency_addr); |
675 | |
676 | set_reg_field_value( |
677 | urgency_cntl, |
678 | marks_low.a_mark, |
679 | DPGV0_PIPE_URGENCY_CONTROL, |
680 | URGENCY_LOW_WATERMARK); |
681 | |
682 | set_reg_field_value( |
683 | urgency_cntl, |
684 | total_dest_line_time_ns, |
685 | DPGV0_PIPE_URGENCY_CONTROL, |
686 | URGENCY_HIGH_WATERMARK); |
687 | dm_write_reg(ctx, urgency_addr, urgency_cntl); |
688 | |
689 | /*Write mask to enable reading/writing of watermark set B*/ |
690 | wm_mask_cntl = dm_read_reg(ctx, wm_addr); |
691 | set_reg_field_value(wm_mask_cntl, |
692 | 2, |
693 | DPGV0_WATERMARK_MASK_CONTROL, |
694 | URGENCY_WATERMARK_MASK); |
695 | dm_write_reg(ctx, wm_addr, wm_mask_cntl); |
696 | |
697 | urgency_cntl = dm_read_reg(ctx, urgency_addr); |
698 | |
699 | set_reg_field_value(urgency_cntl, |
700 | marks_low.b_mark, |
701 | DPGV0_PIPE_URGENCY_CONTROL, |
702 | URGENCY_LOW_WATERMARK); |
703 | |
704 | set_reg_field_value(urgency_cntl, |
705 | total_dest_line_time_ns, |
706 | DPGV0_PIPE_URGENCY_CONTROL, |
707 | URGENCY_HIGH_WATERMARK); |
708 | |
709 | dm_write_reg(ctx, urgency_addr, urgency_cntl); |
710 | } |
711 | |
712 | static void program_urgency_watermark_l( |
713 | const struct dc_context *ctx, |
714 | struct dce_watermarks marks_low, |
715 | uint32_t total_dest_line_time_ns) |
716 | { |
717 | program_urgency_watermark( |
718 | ctx, |
719 | mmDPGV0_PIPE_URGENCY_CONTROL, |
720 | mmDPGV0_WATERMARK_MASK_CONTROL, |
721 | marks_low, |
722 | total_dest_line_time_ns); |
723 | } |
724 | |
725 | static void program_urgency_watermark_c( |
726 | const struct dc_context *ctx, |
727 | struct dce_watermarks marks_low, |
728 | uint32_t total_dest_line_time_ns) |
729 | { |
730 | program_urgency_watermark( |
731 | ctx, |
732 | mmDPGV1_PIPE_URGENCY_CONTROL, |
733 | mmDPGV1_WATERMARK_MASK_CONTROL, |
734 | marks_low, |
735 | total_dest_line_time_ns); |
736 | } |
737 | |
738 | static void program_stutter_watermark( |
739 | const struct dc_context *ctx, |
740 | const uint32_t stutter_addr, |
741 | const uint32_t wm_addr, |
742 | struct dce_watermarks marks) |
743 | { |
744 | /* register value */ |
745 | uint32_t stutter_cntl = 0; |
746 | uint32_t wm_mask_cntl = 0; |
747 | |
748 | /*Write mask to enable reading/writing of watermark set A*/ |
749 | |
750 | wm_mask_cntl = dm_read_reg(ctx, wm_addr); |
751 | set_reg_field_value(wm_mask_cntl, |
752 | 1, |
753 | DPGV0_WATERMARK_MASK_CONTROL, |
754 | STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); |
755 | dm_write_reg(ctx, wm_addr, wm_mask_cntl); |
756 | |
757 | stutter_cntl = dm_read_reg(ctx, stutter_addr); |
758 | |
759 | if (ctx->dc->debug.disable_stutter) { |
760 | set_reg_field_value(stutter_cntl, |
761 | 0, |
762 | DPGV0_PIPE_STUTTER_CONTROL, |
763 | STUTTER_ENABLE); |
764 | } else { |
765 | set_reg_field_value(stutter_cntl, |
766 | 1, |
767 | DPGV0_PIPE_STUTTER_CONTROL, |
768 | STUTTER_ENABLE); |
769 | } |
770 | |
771 | set_reg_field_value(stutter_cntl, |
772 | 1, |
773 | DPGV0_PIPE_STUTTER_CONTROL, |
774 | STUTTER_IGNORE_FBC); |
775 | |
776 | /*Write watermark set A*/ |
777 | set_reg_field_value(stutter_cntl, |
778 | marks.a_mark, |
779 | DPGV0_PIPE_STUTTER_CONTROL, |
780 | STUTTER_EXIT_SELF_REFRESH_WATERMARK); |
781 | dm_write_reg(ctx, stutter_addr, stutter_cntl); |
782 | |
783 | /*Write mask to enable reading/writing of watermark set B*/ |
784 | wm_mask_cntl = dm_read_reg(ctx, wm_addr); |
785 | set_reg_field_value(wm_mask_cntl, |
786 | 2, |
787 | DPGV0_WATERMARK_MASK_CONTROL, |
788 | STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); |
789 | dm_write_reg(ctx, wm_addr, wm_mask_cntl); |
790 | |
791 | stutter_cntl = dm_read_reg(ctx, stutter_addr); |
792 | /*Write watermark set B*/ |
793 | set_reg_field_value(stutter_cntl, |
794 | marks.b_mark, |
795 | DPGV0_PIPE_STUTTER_CONTROL, |
796 | STUTTER_EXIT_SELF_REFRESH_WATERMARK); |
797 | dm_write_reg(ctx, stutter_addr, stutter_cntl); |
798 | } |
799 | |
800 | static void program_stutter_watermark_l( |
801 | const struct dc_context *ctx, |
802 | struct dce_watermarks marks) |
803 | { |
804 | program_stutter_watermark(ctx, |
805 | mmDPGV0_PIPE_STUTTER_CONTROL, |
806 | mmDPGV0_WATERMARK_MASK_CONTROL, |
807 | marks); |
808 | } |
809 | |
810 | static void program_stutter_watermark_c( |
811 | const struct dc_context *ctx, |
812 | struct dce_watermarks marks) |
813 | { |
814 | program_stutter_watermark(ctx, |
815 | mmDPGV1_PIPE_STUTTER_CONTROL, |
816 | mmDPGV1_WATERMARK_MASK_CONTROL, |
817 | marks); |
818 | } |
819 | |
820 | static void program_nbp_watermark( |
821 | const struct dc_context *ctx, |
822 | const uint32_t wm_mask_ctrl_addr, |
823 | const uint32_t nbp_pstate_ctrl_addr, |
824 | struct dce_watermarks marks) |
825 | { |
826 | uint32_t value; |
827 | |
828 | /* Write mask to enable reading/writing of watermark set A */ |
829 | |
830 | value = dm_read_reg(ctx, wm_mask_ctrl_addr); |
831 | |
832 | set_reg_field_value( |
833 | value, |
834 | 1, |
835 | DPGV0_WATERMARK_MASK_CONTROL, |
836 | NB_PSTATE_CHANGE_WATERMARK_MASK); |
837 | dm_write_reg(ctx, wm_mask_ctrl_addr, value); |
838 | |
839 | value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); |
840 | |
841 | set_reg_field_value( |
842 | value, |
843 | 1, |
844 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
845 | NB_PSTATE_CHANGE_ENABLE); |
846 | set_reg_field_value( |
847 | value, |
848 | 1, |
849 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
850 | NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); |
851 | set_reg_field_value( |
852 | value, |
853 | 1, |
854 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
855 | NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); |
856 | dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); |
857 | |
858 | /* Write watermark set A */ |
859 | value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); |
860 | set_reg_field_value( |
861 | value, |
862 | marks.a_mark, |
863 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
864 | NB_PSTATE_CHANGE_WATERMARK); |
865 | dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); |
866 | |
867 | /* Write mask to enable reading/writing of watermark set B */ |
868 | value = dm_read_reg(ctx, wm_mask_ctrl_addr); |
869 | set_reg_field_value( |
870 | value, |
871 | 2, |
872 | DPGV0_WATERMARK_MASK_CONTROL, |
873 | NB_PSTATE_CHANGE_WATERMARK_MASK); |
874 | dm_write_reg(ctx, wm_mask_ctrl_addr, value); |
875 | |
876 | value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); |
877 | set_reg_field_value( |
878 | value, |
879 | 1, |
880 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
881 | NB_PSTATE_CHANGE_ENABLE); |
882 | set_reg_field_value( |
883 | value, |
884 | 1, |
885 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
886 | NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); |
887 | set_reg_field_value( |
888 | value, |
889 | 1, |
890 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
891 | NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); |
892 | dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); |
893 | |
894 | /* Write watermark set B */ |
895 | value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); |
896 | set_reg_field_value( |
897 | value, |
898 | marks.b_mark, |
899 | DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
900 | NB_PSTATE_CHANGE_WATERMARK); |
901 | dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); |
902 | } |
903 | |
904 | static void program_nbp_watermark_l( |
905 | const struct dc_context *ctx, |
906 | struct dce_watermarks marks) |
907 | { |
908 | program_nbp_watermark(ctx, |
909 | mmDPGV0_WATERMARK_MASK_CONTROL, |
910 | mmDPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, |
911 | marks); |
912 | } |
913 | |
914 | static void program_nbp_watermark_c( |
915 | const struct dc_context *ctx, |
916 | struct dce_watermarks marks) |
917 | { |
918 | program_nbp_watermark(ctx, |
919 | mmDPGV1_WATERMARK_MASK_CONTROL, |
920 | mmDPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL, |
921 | marks); |
922 | } |
923 | |
924 | static void dce_mem_input_v_program_display_marks( |
925 | struct mem_input *mem_input, |
926 | struct dce_watermarks nbp, |
927 | struct dce_watermarks stutter, |
928 | struct dce_watermarks stutter_enter, |
929 | struct dce_watermarks urgent, |
930 | uint32_t total_dest_line_time_ns) |
931 | { |
932 | program_urgency_watermark_l( |
933 | ctx: mem_input->ctx, |
934 | marks_low: urgent, |
935 | total_dest_line_time_ns); |
936 | |
937 | program_nbp_watermark_l( |
938 | ctx: mem_input->ctx, |
939 | marks: nbp); |
940 | |
941 | program_stutter_watermark_l( |
942 | ctx: mem_input->ctx, |
943 | marks: stutter); |
944 | |
945 | } |
946 | |
947 | static void dce_mem_input_program_chroma_display_marks( |
948 | struct mem_input *mem_input, |
949 | struct dce_watermarks nbp, |
950 | struct dce_watermarks stutter, |
951 | struct dce_watermarks urgent, |
952 | uint32_t total_dest_line_time_ns) |
953 | { |
954 | program_urgency_watermark_c( |
955 | ctx: mem_input->ctx, |
956 | marks_low: urgent, |
957 | total_dest_line_time_ns); |
958 | |
959 | program_nbp_watermark_c( |
960 | ctx: mem_input->ctx, |
961 | marks: nbp); |
962 | |
963 | program_stutter_watermark_c( |
964 | ctx: mem_input->ctx, |
965 | marks: stutter); |
966 | } |
967 | |
968 | static void dce110_allocate_mem_input_v( |
969 | struct mem_input *mi, |
970 | uint32_t h_total,/* for current stream */ |
971 | uint32_t v_total,/* for current stream */ |
972 | uint32_t pix_clk_khz,/* for current stream */ |
973 | uint32_t total_stream_num) |
974 | { |
975 | uint32_t addr; |
976 | uint32_t value; |
977 | uint32_t pix_dur; |
978 | if (pix_clk_khz != 0) { |
979 | addr = mmDPGV0_PIPE_ARBITRATION_CONTROL1; |
980 | value = dm_read_reg(mi->ctx, addr); |
981 | pix_dur = 1000000000ULL / pix_clk_khz; |
982 | set_reg_field_value( |
983 | value, |
984 | pix_dur, |
985 | DPGV0_PIPE_ARBITRATION_CONTROL1, |
986 | PIXEL_DURATION); |
987 | dm_write_reg(mi->ctx, addr, value); |
988 | |
989 | addr = mmDPGV1_PIPE_ARBITRATION_CONTROL1; |
990 | value = dm_read_reg(mi->ctx, addr); |
991 | pix_dur = 1000000000ULL / pix_clk_khz; |
992 | set_reg_field_value( |
993 | value, |
994 | pix_dur, |
995 | DPGV1_PIPE_ARBITRATION_CONTROL1, |
996 | PIXEL_DURATION); |
997 | dm_write_reg(mi->ctx, addr, value); |
998 | |
999 | addr = mmDPGV0_PIPE_ARBITRATION_CONTROL2; |
1000 | value = 0x4000800; |
1001 | dm_write_reg(mi->ctx, addr, value); |
1002 | |
1003 | addr = mmDPGV1_PIPE_ARBITRATION_CONTROL2; |
1004 | value = 0x4000800; |
1005 | dm_write_reg(mi->ctx, addr, value); |
1006 | } |
1007 | |
1008 | } |
1009 | |
1010 | static void dce110_free_mem_input_v( |
1011 | struct mem_input *mi, |
1012 | uint32_t total_stream_num) |
1013 | { |
1014 | } |
1015 | |
1016 | static const struct mem_input_funcs dce110_mem_input_v_funcs = { |
1017 | .mem_input_program_display_marks = |
1018 | dce_mem_input_v_program_display_marks, |
1019 | .mem_input_program_chroma_display_marks = |
1020 | dce_mem_input_program_chroma_display_marks, |
1021 | .allocate_mem_input = dce110_allocate_mem_input_v, |
1022 | .free_mem_input = dce110_free_mem_input_v, |
1023 | .mem_input_program_surface_flip_and_addr = |
1024 | dce_mem_input_v_program_surface_flip_and_addr, |
1025 | .mem_input_program_pte_vm = |
1026 | dce_mem_input_v_program_pte_vm, |
1027 | .mem_input_program_surface_config = |
1028 | dce_mem_input_v_program_surface_config, |
1029 | .mem_input_is_flip_pending = |
1030 | dce_mem_input_v_is_surface_pending |
1031 | }; |
1032 | /*****************************************/ |
1033 | /* Constructor, Destructor */ |
1034 | /*****************************************/ |
1035 | |
1036 | void dce110_mem_input_v_construct( |
1037 | struct dce_mem_input *dce_mi, |
1038 | struct dc_context *ctx) |
1039 | { |
1040 | dce_mi->base.funcs = &dce110_mem_input_v_funcs; |
1041 | dce_mi->base.ctx = ctx; |
1042 | } |
1043 | |
1044 | |