1 | /* |
2 | * Copyright 2012-15 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 | #include "dce_calcs.h" |
27 | #include "reg_helper.h" |
28 | #include "basics/conversion.h" |
29 | #include "dcn10_hubp.h" |
30 | |
31 | #define REG(reg)\ |
32 | hubp1->hubp_regs->reg |
33 | |
34 | #define CTX \ |
35 | hubp1->base.ctx |
36 | |
37 | #undef FN |
38 | #define FN(reg_name, field_name) \ |
39 | hubp1->hubp_shift->field_name, hubp1->hubp_mask->field_name |
40 | |
41 | void hubp1_set_blank(struct hubp *hubp, bool blank) |
42 | { |
43 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
44 | uint32_t blank_en = blank ? 1 : 0; |
45 | |
46 | REG_UPDATE_2(DCHUBP_CNTL, |
47 | HUBP_BLANK_EN, blank_en, |
48 | HUBP_TTU_DISABLE, blank_en); |
49 | |
50 | if (blank) { |
51 | uint32_t reg_val = REG_READ(DCHUBP_CNTL); |
52 | |
53 | if (reg_val) { |
54 | /* init sequence workaround: in case HUBP is |
55 | * power gated, this wait would timeout. |
56 | * |
57 | * we just wrote reg_val to non-0, if it stay 0 |
58 | * it means HUBP is gated |
59 | */ |
60 | REG_WAIT(DCHUBP_CNTL, |
61 | HUBP_NO_OUTSTANDING_REQ, 1, |
62 | 1, 200); |
63 | } |
64 | |
65 | hubp->mpcc_id = 0xf; |
66 | hubp->opp_id = OPP_ID_INVALID; |
67 | } |
68 | } |
69 | |
70 | static void hubp1_disconnect(struct hubp *hubp) |
71 | { |
72 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
73 | |
74 | REG_UPDATE(DCHUBP_CNTL, |
75 | HUBP_TTU_DISABLE, 1); |
76 | |
77 | REG_UPDATE(CURSOR_CONTROL, |
78 | CURSOR_ENABLE, 0); |
79 | } |
80 | |
81 | static void hubp1_disable_control(struct hubp *hubp, bool disable_hubp) |
82 | { |
83 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
84 | uint32_t disable = disable_hubp ? 1 : 0; |
85 | |
86 | REG_UPDATE(DCHUBP_CNTL, |
87 | HUBP_DISABLE, disable); |
88 | } |
89 | |
90 | static unsigned int hubp1_get_underflow_status(struct hubp *hubp) |
91 | { |
92 | uint32_t hubp_underflow = 0; |
93 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
94 | |
95 | REG_GET(DCHUBP_CNTL, |
96 | HUBP_UNDERFLOW_STATUS, |
97 | &hubp_underflow); |
98 | |
99 | return hubp_underflow; |
100 | } |
101 | |
102 | |
103 | void hubp1_clear_underflow(struct hubp *hubp) |
104 | { |
105 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
106 | |
107 | REG_UPDATE(DCHUBP_CNTL, HUBP_UNDERFLOW_CLEAR, 1); |
108 | } |
109 | |
110 | static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) |
111 | { |
112 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
113 | uint32_t blank_en = blank ? 1 : 0; |
114 | |
115 | REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); |
116 | } |
117 | |
118 | void hubp1_vready_workaround(struct hubp *hubp, |
119 | struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) |
120 | { |
121 | uint32_t value = 0; |
122 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
123 | |
124 | /* set HBUBREQ_DEBUG_DB[12] = 1 */ |
125 | value = REG_READ(HUBPREQ_DEBUG_DB); |
126 | |
127 | /* hack mode disable */ |
128 | value |= 0x100; |
129 | value &= ~0x1000; |
130 | |
131 | if ((pipe_dest->vstartup_start - 2*(pipe_dest->vready_offset+pipe_dest->vupdate_width |
132 | + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { |
133 | /* if (eco_fix_needed(otg_global_sync_timing) |
134 | * set HBUBREQ_DEBUG_DB[12] = 1 */ |
135 | value |= 0x1000; |
136 | } |
137 | |
138 | REG_WRITE(HUBPREQ_DEBUG_DB, value); |
139 | } |
140 | |
141 | void hubp1_program_tiling( |
142 | struct hubp *hubp, |
143 | const union dc_tiling_info *info, |
144 | const enum surface_pixel_format pixel_format) |
145 | { |
146 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
147 | |
148 | REG_UPDATE_6(DCSURF_ADDR_CONFIG, |
149 | NUM_PIPES, log_2(info->gfx9.num_pipes), |
150 | NUM_BANKS, log_2(info->gfx9.num_banks), |
151 | PIPE_INTERLEAVE, info->gfx9.pipe_interleave, |
152 | NUM_SE, log_2(info->gfx9.num_shader_engines), |
153 | NUM_RB_PER_SE, log_2(info->gfx9.num_rb_per_se), |
154 | MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags)); |
155 | |
156 | REG_UPDATE_4(DCSURF_TILING_CONFIG, |
157 | SW_MODE, info->gfx9.swizzle, |
158 | META_LINEAR, info->gfx9.meta_linear, |
159 | RB_ALIGNED, info->gfx9.rb_aligned, |
160 | PIPE_ALIGNED, info->gfx9.pipe_aligned); |
161 | } |
162 | |
163 | void hubp1_program_size( |
164 | struct hubp *hubp, |
165 | enum surface_pixel_format format, |
166 | const struct plane_size *plane_size, |
167 | struct dc_plane_dcc_param *dcc) |
168 | { |
169 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
170 | uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c; |
171 | |
172 | /* Program data and meta surface pitch (calculation from addrlib) |
173 | * 444 or 420 luma |
174 | */ |
175 | if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END) { |
176 | ASSERT(plane_size->chroma_pitch != 0); |
177 | /* Chroma pitch zero can cause system hang! */ |
178 | |
179 | pitch = plane_size->surface_pitch - 1; |
180 | meta_pitch = dcc->meta_pitch - 1; |
181 | pitch_c = plane_size->chroma_pitch - 1; |
182 | meta_pitch_c = dcc->meta_pitch_c - 1; |
183 | } else { |
184 | pitch = plane_size->surface_pitch - 1; |
185 | meta_pitch = dcc->meta_pitch - 1; |
186 | pitch_c = 0; |
187 | meta_pitch_c = 0; |
188 | } |
189 | |
190 | if (!dcc->enable) { |
191 | meta_pitch = 0; |
192 | meta_pitch_c = 0; |
193 | } |
194 | |
195 | REG_UPDATE_2(DCSURF_SURFACE_PITCH, |
196 | PITCH, pitch, META_PITCH, meta_pitch); |
197 | |
198 | if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) |
199 | REG_UPDATE_2(DCSURF_SURFACE_PITCH_C, |
200 | PITCH_C, pitch_c, META_PITCH_C, meta_pitch_c); |
201 | } |
202 | |
203 | void hubp1_program_rotation( |
204 | struct hubp *hubp, |
205 | enum dc_rotation_angle rotation, |
206 | bool horizontal_mirror) |
207 | { |
208 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
209 | uint32_t mirror; |
210 | |
211 | |
212 | if (horizontal_mirror) |
213 | mirror = 1; |
214 | else |
215 | mirror = 0; |
216 | |
217 | /* Program rotation angle and horz mirror - no mirror */ |
218 | if (rotation == ROTATION_ANGLE_0) |
219 | REG_UPDATE_2(DCSURF_SURFACE_CONFIG, |
220 | ROTATION_ANGLE, 0, |
221 | H_MIRROR_EN, mirror); |
222 | else if (rotation == ROTATION_ANGLE_90) |
223 | REG_UPDATE_2(DCSURF_SURFACE_CONFIG, |
224 | ROTATION_ANGLE, 1, |
225 | H_MIRROR_EN, mirror); |
226 | else if (rotation == ROTATION_ANGLE_180) |
227 | REG_UPDATE_2(DCSURF_SURFACE_CONFIG, |
228 | ROTATION_ANGLE, 2, |
229 | H_MIRROR_EN, mirror); |
230 | else if (rotation == ROTATION_ANGLE_270) |
231 | REG_UPDATE_2(DCSURF_SURFACE_CONFIG, |
232 | ROTATION_ANGLE, 3, |
233 | H_MIRROR_EN, mirror); |
234 | } |
235 | |
236 | void hubp1_program_pixel_format( |
237 | struct hubp *hubp, |
238 | enum surface_pixel_format format) |
239 | { |
240 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
241 | uint32_t red_bar = 3; |
242 | uint32_t blue_bar = 2; |
243 | |
244 | /* swap for ABGR format */ |
245 | if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 |
246 | || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 |
247 | || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS |
248 | || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 |
249 | || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { |
250 | red_bar = 2; |
251 | blue_bar = 3; |
252 | } |
253 | |
254 | REG_UPDATE_2(HUBPRET_CONTROL, |
255 | CROSSBAR_SRC_CB_B, blue_bar, |
256 | CROSSBAR_SRC_CR_R, red_bar); |
257 | |
258 | /* Mapping is same as ipp programming (cnvc) */ |
259 | |
260 | switch (format) { |
261 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: |
262 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
263 | SURFACE_PIXEL_FORMAT, 1); |
264 | break; |
265 | case SURFACE_PIXEL_FORMAT_GRPH_RGB565: |
266 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
267 | SURFACE_PIXEL_FORMAT, 3); |
268 | break; |
269 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: |
270 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: |
271 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
272 | SURFACE_PIXEL_FORMAT, 8); |
273 | break; |
274 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: |
275 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: |
276 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: |
277 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
278 | SURFACE_PIXEL_FORMAT, 10); |
279 | break; |
280 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: |
281 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /*we use crossbar already*/ |
282 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
283 | SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */ |
284 | break; |
285 | case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: |
286 | case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ |
287 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
288 | SURFACE_PIXEL_FORMAT, 24); |
289 | break; |
290 | |
291 | case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: |
292 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
293 | SURFACE_PIXEL_FORMAT, 65); |
294 | break; |
295 | case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: |
296 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
297 | SURFACE_PIXEL_FORMAT, 64); |
298 | break; |
299 | case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: |
300 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
301 | SURFACE_PIXEL_FORMAT, 67); |
302 | break; |
303 | case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: |
304 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
305 | SURFACE_PIXEL_FORMAT, 66); |
306 | break; |
307 | case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888: |
308 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
309 | SURFACE_PIXEL_FORMAT, 12); |
310 | break; |
311 | case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: |
312 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
313 | SURFACE_PIXEL_FORMAT, 112); |
314 | break; |
315 | case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: |
316 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
317 | SURFACE_PIXEL_FORMAT, 113); |
318 | break; |
319 | case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: |
320 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
321 | SURFACE_PIXEL_FORMAT, 114); |
322 | break; |
323 | case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: |
324 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
325 | SURFACE_PIXEL_FORMAT, 118); |
326 | break; |
327 | case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: |
328 | REG_UPDATE(DCSURF_SURFACE_CONFIG, |
329 | SURFACE_PIXEL_FORMAT, 119); |
330 | break; |
331 | case SURFACE_PIXEL_FORMAT_GRPH_RGBE: |
332 | REG_UPDATE_2(DCSURF_SURFACE_CONFIG, |
333 | SURFACE_PIXEL_FORMAT, 116, |
334 | ALPHA_PLANE_EN, 0); |
335 | break; |
336 | case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: |
337 | REG_UPDATE_2(DCSURF_SURFACE_CONFIG, |
338 | SURFACE_PIXEL_FORMAT, 116, |
339 | ALPHA_PLANE_EN, 1); |
340 | break; |
341 | default: |
342 | BREAK_TO_DEBUGGER(); |
343 | break; |
344 | } |
345 | |
346 | /* don't see the need of program the xbar in DCN 1.0 */ |
347 | } |
348 | |
349 | bool hubp1_program_surface_flip_and_addr( |
350 | struct hubp *hubp, |
351 | const struct dc_plane_address *address, |
352 | bool flip_immediate) |
353 | { |
354 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
355 | |
356 | |
357 | //program flip type |
358 | REG_UPDATE(DCSURF_FLIP_CONTROL, |
359 | SURFACE_FLIP_TYPE, flip_immediate); |
360 | |
361 | |
362 | if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) { |
363 | REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x1); |
364 | REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1); |
365 | |
366 | } else { |
367 | // turn off stereo if not in stereo |
368 | REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0); |
369 | REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0); |
370 | } |
371 | |
372 | |
373 | |
374 | /* HW automatically latch rest of address register on write to |
375 | * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used |
376 | * |
377 | * program high first and then the low addr, order matters! |
378 | */ |
379 | switch (address->type) { |
380 | case PLN_ADDR_TYPE_GRAPHICS: |
381 | /* DCN1.0 does not support const color |
382 | * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 |
383 | * base on address->grph.dcc_const_color |
384 | * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma |
385 | * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma |
386 | */ |
387 | |
388 | if (address->grph.addr.quad_part == 0) |
389 | break; |
390 | |
391 | REG_UPDATE_2(DCSURF_SURFACE_CONTROL, |
392 | PRIMARY_SURFACE_TMZ, address->tmz_surface, |
393 | PRIMARY_META_SURFACE_TMZ, address->tmz_surface); |
394 | |
395 | if (address->grph.meta_addr.quad_part != 0) { |
396 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, |
397 | PRIMARY_META_SURFACE_ADDRESS_HIGH, |
398 | address->grph.meta_addr.high_part); |
399 | |
400 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, |
401 | PRIMARY_META_SURFACE_ADDRESS, |
402 | address->grph.meta_addr.low_part); |
403 | } |
404 | |
405 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, |
406 | PRIMARY_SURFACE_ADDRESS_HIGH, |
407 | address->grph.addr.high_part); |
408 | |
409 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, |
410 | PRIMARY_SURFACE_ADDRESS, |
411 | address->grph.addr.low_part); |
412 | break; |
413 | case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: |
414 | if (address->video_progressive.luma_addr.quad_part == 0 |
415 | || address->video_progressive.chroma_addr.quad_part == 0) |
416 | break; |
417 | |
418 | REG_UPDATE_4(DCSURF_SURFACE_CONTROL, |
419 | PRIMARY_SURFACE_TMZ, address->tmz_surface, |
420 | PRIMARY_SURFACE_TMZ_C, address->tmz_surface, |
421 | PRIMARY_META_SURFACE_TMZ, address->tmz_surface, |
422 | PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); |
423 | |
424 | if (address->video_progressive.luma_meta_addr.quad_part != 0) { |
425 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, |
426 | PRIMARY_META_SURFACE_ADDRESS_HIGH_C, |
427 | address->video_progressive.chroma_meta_addr.high_part); |
428 | |
429 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, |
430 | PRIMARY_META_SURFACE_ADDRESS_C, |
431 | address->video_progressive.chroma_meta_addr.low_part); |
432 | |
433 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, |
434 | PRIMARY_META_SURFACE_ADDRESS_HIGH, |
435 | address->video_progressive.luma_meta_addr.high_part); |
436 | |
437 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, |
438 | PRIMARY_META_SURFACE_ADDRESS, |
439 | address->video_progressive.luma_meta_addr.low_part); |
440 | } |
441 | |
442 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, |
443 | PRIMARY_SURFACE_ADDRESS_HIGH_C, |
444 | address->video_progressive.chroma_addr.high_part); |
445 | |
446 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, |
447 | PRIMARY_SURFACE_ADDRESS_C, |
448 | address->video_progressive.chroma_addr.low_part); |
449 | |
450 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, |
451 | PRIMARY_SURFACE_ADDRESS_HIGH, |
452 | address->video_progressive.luma_addr.high_part); |
453 | |
454 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, |
455 | PRIMARY_SURFACE_ADDRESS, |
456 | address->video_progressive.luma_addr.low_part); |
457 | break; |
458 | case PLN_ADDR_TYPE_GRPH_STEREO: |
459 | if (address->grph_stereo.left_addr.quad_part == 0) |
460 | break; |
461 | if (address->grph_stereo.right_addr.quad_part == 0) |
462 | break; |
463 | |
464 | REG_UPDATE_8(DCSURF_SURFACE_CONTROL, |
465 | PRIMARY_SURFACE_TMZ, address->tmz_surface, |
466 | PRIMARY_SURFACE_TMZ_C, address->tmz_surface, |
467 | PRIMARY_META_SURFACE_TMZ, address->tmz_surface, |
468 | PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface, |
469 | SECONDARY_SURFACE_TMZ, address->tmz_surface, |
470 | SECONDARY_SURFACE_TMZ_C, address->tmz_surface, |
471 | SECONDARY_META_SURFACE_TMZ, address->tmz_surface, |
472 | SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface); |
473 | |
474 | if (address->grph_stereo.right_meta_addr.quad_part != 0) { |
475 | |
476 | REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, |
477 | SECONDARY_META_SURFACE_ADDRESS_HIGH, |
478 | address->grph_stereo.right_meta_addr.high_part); |
479 | |
480 | REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, |
481 | SECONDARY_META_SURFACE_ADDRESS, |
482 | address->grph_stereo.right_meta_addr.low_part); |
483 | } |
484 | if (address->grph_stereo.left_meta_addr.quad_part != 0) { |
485 | |
486 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, |
487 | PRIMARY_META_SURFACE_ADDRESS_HIGH, |
488 | address->grph_stereo.left_meta_addr.high_part); |
489 | |
490 | REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, |
491 | PRIMARY_META_SURFACE_ADDRESS, |
492 | address->grph_stereo.left_meta_addr.low_part); |
493 | } |
494 | |
495 | REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, |
496 | SECONDARY_SURFACE_ADDRESS_HIGH, |
497 | address->grph_stereo.right_addr.high_part); |
498 | |
499 | REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, |
500 | SECONDARY_SURFACE_ADDRESS, |
501 | address->grph_stereo.right_addr.low_part); |
502 | |
503 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, |
504 | PRIMARY_SURFACE_ADDRESS_HIGH, |
505 | address->grph_stereo.left_addr.high_part); |
506 | |
507 | REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, |
508 | PRIMARY_SURFACE_ADDRESS, |
509 | address->grph_stereo.left_addr.low_part); |
510 | break; |
511 | default: |
512 | BREAK_TO_DEBUGGER(); |
513 | break; |
514 | } |
515 | |
516 | hubp->request_address = *address; |
517 | |
518 | return true; |
519 | } |
520 | |
521 | void hubp1_dcc_control(struct hubp *hubp, bool enable, |
522 | enum hubp_ind_block_size independent_64b_blks) |
523 | { |
524 | uint32_t dcc_en = enable ? 1 : 0; |
525 | uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; |
526 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
527 | |
528 | REG_UPDATE_4(DCSURF_SURFACE_CONTROL, |
529 | PRIMARY_SURFACE_DCC_EN, dcc_en, |
530 | PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk, |
531 | SECONDARY_SURFACE_DCC_EN, dcc_en, |
532 | SECONDARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); |
533 | } |
534 | |
535 | void hubp1_program_surface_config( |
536 | struct hubp *hubp, |
537 | enum surface_pixel_format format, |
538 | union dc_tiling_info *tiling_info, |
539 | struct plane_size *plane_size, |
540 | enum dc_rotation_angle rotation, |
541 | struct dc_plane_dcc_param *dcc, |
542 | bool horizontal_mirror, |
543 | unsigned int compat_level) |
544 | { |
545 | hubp1_dcc_control(hubp, enable: dcc->enable, independent_64b_blks: dcc->independent_64b_blks); |
546 | hubp1_program_tiling(hubp, info: tiling_info, pixel_format: format); |
547 | hubp1_program_size(hubp, format, plane_size, dcc); |
548 | hubp1_program_rotation(hubp, rotation, horizontal_mirror); |
549 | hubp1_program_pixel_format(hubp, format); |
550 | } |
551 | |
552 | void hubp1_program_requestor( |
553 | struct hubp *hubp, |
554 | struct _vcs_dpi_display_rq_regs_st *rq_regs) |
555 | { |
556 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
557 | |
558 | REG_UPDATE(HUBPRET_CONTROL, |
559 | DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); |
560 | REG_SET_4(DCN_EXPANSION_MODE, 0, |
561 | DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode, |
562 | PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode, |
563 | MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, |
564 | CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); |
565 | REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0, |
566 | CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, |
567 | MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, |
568 | META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size, |
569 | MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size, |
570 | DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size, |
571 | MPTE_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size, |
572 | SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height, |
573 | PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear); |
574 | REG_SET_8(DCHUBP_REQ_SIZE_CONFIG_C, 0, |
575 | CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size, |
576 | MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size, |
577 | META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size, |
578 | MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size, |
579 | DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size, |
580 | MPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.mpte_group_size, |
581 | SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height, |
582 | PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear); |
583 | } |
584 | |
585 | |
586 | void hubp1_program_deadline( |
587 | struct hubp *hubp, |
588 | struct _vcs_dpi_display_dlg_regs_st *dlg_attr, |
589 | struct _vcs_dpi_display_ttu_regs_st *ttu_attr) |
590 | { |
591 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
592 | |
593 | /* DLG - Per hubp */ |
594 | REG_SET_2(BLANK_OFFSET_0, 0, |
595 | REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, |
596 | DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); |
597 | |
598 | REG_SET(BLANK_OFFSET_1, 0, |
599 | MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); |
600 | |
601 | REG_SET(DST_DIMENSIONS, 0, |
602 | REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); |
603 | |
604 | REG_SET_2(DST_AFTER_SCALER, 0, |
605 | REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, |
606 | DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); |
607 | |
608 | REG_SET(REF_FREQ_TO_PIX_FREQ, 0, |
609 | REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); |
610 | |
611 | /* DLG - Per luma/chroma */ |
612 | REG_SET(VBLANK_PARAMETERS_1, 0, |
613 | REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); |
614 | |
615 | if (REG(NOM_PARAMETERS_0)) |
616 | REG_SET(NOM_PARAMETERS_0, 0, |
617 | DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); |
618 | |
619 | if (REG(NOM_PARAMETERS_1)) |
620 | REG_SET(NOM_PARAMETERS_1, 0, |
621 | REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); |
622 | |
623 | REG_SET(NOM_PARAMETERS_4, 0, |
624 | DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); |
625 | |
626 | REG_SET(NOM_PARAMETERS_5, 0, |
627 | REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); |
628 | |
629 | REG_SET_2(PER_LINE_DELIVERY, 0, |
630 | REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, |
631 | REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); |
632 | |
633 | REG_SET(VBLANK_PARAMETERS_2, 0, |
634 | REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); |
635 | |
636 | if (REG(NOM_PARAMETERS_2)) |
637 | REG_SET(NOM_PARAMETERS_2, 0, |
638 | DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); |
639 | |
640 | if (REG(NOM_PARAMETERS_3)) |
641 | REG_SET(NOM_PARAMETERS_3, 0, |
642 | REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); |
643 | |
644 | REG_SET(NOM_PARAMETERS_6, 0, |
645 | DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); |
646 | |
647 | REG_SET(NOM_PARAMETERS_7, 0, |
648 | REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); |
649 | |
650 | /* TTU - per hubp */ |
651 | REG_SET_2(DCN_TTU_QOS_WM, 0, |
652 | QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, |
653 | QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); |
654 | |
655 | /* TTU - per luma/chroma */ |
656 | /* Assumed surf0 is luma and 1 is chroma */ |
657 | |
658 | REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, |
659 | REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, |
660 | QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, |
661 | QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); |
662 | |
663 | REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, |
664 | REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, |
665 | QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, |
666 | QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); |
667 | |
668 | REG_SET_3(DCN_CUR0_TTU_CNTL0, 0, |
669 | REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_cur0, |
670 | QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_cur0, |
671 | QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_cur0); |
672 | } |
673 | |
674 | static void hubp1_setup( |
675 | struct hubp *hubp, |
676 | struct _vcs_dpi_display_dlg_regs_st *dlg_attr, |
677 | struct _vcs_dpi_display_ttu_regs_st *ttu_attr, |
678 | struct _vcs_dpi_display_rq_regs_st *rq_regs, |
679 | struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) |
680 | { |
681 | /* otg is locked when this func is called. Register are double buffered. |
682 | * disable the requestors is not needed |
683 | */ |
684 | hubp1_program_requestor(hubp, rq_regs); |
685 | hubp1_program_deadline(hubp, dlg_attr, ttu_attr); |
686 | hubp1_vready_workaround(hubp, pipe_dest); |
687 | } |
688 | |
689 | static void hubp1_setup_interdependent( |
690 | struct hubp *hubp, |
691 | struct _vcs_dpi_display_dlg_regs_st *dlg_attr, |
692 | struct _vcs_dpi_display_ttu_regs_st *ttu_attr) |
693 | { |
694 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
695 | |
696 | REG_SET_2(PREFETCH_SETTINS, 0, |
697 | DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, |
698 | VRATIO_PREFETCH, dlg_attr->vratio_prefetch); |
699 | |
700 | REG_SET(PREFETCH_SETTINS_C, 0, |
701 | VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); |
702 | |
703 | REG_SET_2(VBLANK_PARAMETERS_0, 0, |
704 | DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, |
705 | DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); |
706 | |
707 | REG_SET(VBLANK_PARAMETERS_3, 0, |
708 | REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); |
709 | |
710 | REG_SET(VBLANK_PARAMETERS_4, 0, |
711 | REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); |
712 | |
713 | REG_SET_2(PER_LINE_DELIVERY_PRE, 0, |
714 | REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, |
715 | REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); |
716 | |
717 | REG_SET(DCN_SURF0_TTU_CNTL1, 0, |
718 | REFCYC_PER_REQ_DELIVERY_PRE, |
719 | ttu_attr->refcyc_per_req_delivery_pre_l); |
720 | REG_SET(DCN_SURF1_TTU_CNTL1, 0, |
721 | REFCYC_PER_REQ_DELIVERY_PRE, |
722 | ttu_attr->refcyc_per_req_delivery_pre_c); |
723 | REG_SET(DCN_CUR0_TTU_CNTL1, 0, |
724 | REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur0); |
725 | |
726 | REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, |
727 | MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, |
728 | QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); |
729 | } |
730 | |
731 | bool hubp1_is_flip_pending(struct hubp *hubp) |
732 | { |
733 | uint32_t flip_pending = 0; |
734 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
735 | struct dc_plane_address earliest_inuse_address; |
736 | |
737 | if (hubp && hubp->power_gated) |
738 | return false; |
739 | |
740 | REG_GET(DCSURF_FLIP_CONTROL, |
741 | SURFACE_FLIP_PENDING, &flip_pending); |
742 | |
743 | REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, |
744 | SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); |
745 | |
746 | REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, |
747 | SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); |
748 | |
749 | if (flip_pending) |
750 | return true; |
751 | |
752 | if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) |
753 | return true; |
754 | |
755 | return false; |
756 | } |
757 | |
758 | static uint32_t aperture_default_system = 1; |
759 | static uint32_t context0_default_system; /* = 0;*/ |
760 | |
761 | static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp, |
762 | struct vm_system_aperture_param *apt) |
763 | { |
764 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
765 | PHYSICAL_ADDRESS_LOC mc_vm_apt_default; |
766 | PHYSICAL_ADDRESS_LOC mc_vm_apt_low; |
767 | PHYSICAL_ADDRESS_LOC mc_vm_apt_high; |
768 | |
769 | mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; |
770 | mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 12; |
771 | mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; |
772 | |
773 | REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, |
774 | MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */ |
775 | MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); |
776 | REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, |
777 | MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); |
778 | |
779 | REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, |
780 | MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mc_vm_apt_low.high_part); |
781 | REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, |
782 | MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mc_vm_apt_low.low_part); |
783 | |
784 | REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, |
785 | MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mc_vm_apt_high.high_part); |
786 | REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, |
787 | MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); |
788 | } |
789 | |
790 | static void hubp1_set_vm_context0_settings(struct hubp *hubp, |
791 | const struct vm_context0_param *vm0) |
792 | { |
793 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
794 | /* pte base */ |
795 | REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, |
796 | VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); |
797 | REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, 0, |
798 | VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, vm0->pte_base.low_part); |
799 | |
800 | /* pte start */ |
801 | REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, 0, |
802 | VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, vm0->pte_start.high_part); |
803 | REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, 0, |
804 | VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, vm0->pte_start.low_part); |
805 | |
806 | /* pte end */ |
807 | REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, 0, |
808 | VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->pte_end.high_part); |
809 | REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, 0, |
810 | VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); |
811 | |
812 | /* fault handling */ |
813 | REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, |
814 | VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part, |
815 | VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system); |
816 | REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, |
817 | VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); |
818 | |
819 | /* control: enable VM PTE*/ |
820 | REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, |
821 | ENABLE_L1_TLB, 1, |
822 | SYSTEM_ACCESS_MODE, 3); |
823 | } |
824 | |
825 | void min_set_viewport( |
826 | struct hubp *hubp, |
827 | const struct rect *viewport, |
828 | const struct rect *viewport_c) |
829 | { |
830 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
831 | |
832 | REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, |
833 | PRI_VIEWPORT_WIDTH, viewport->width, |
834 | PRI_VIEWPORT_HEIGHT, viewport->height); |
835 | |
836 | REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, |
837 | PRI_VIEWPORT_X_START, viewport->x, |
838 | PRI_VIEWPORT_Y_START, viewport->y); |
839 | |
840 | /*for stereo*/ |
841 | REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, |
842 | SEC_VIEWPORT_WIDTH, viewport->width, |
843 | SEC_VIEWPORT_HEIGHT, viewport->height); |
844 | |
845 | REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, |
846 | SEC_VIEWPORT_X_START, viewport->x, |
847 | SEC_VIEWPORT_Y_START, viewport->y); |
848 | |
849 | /* DC supports NV12 only at the moment */ |
850 | REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, |
851 | PRI_VIEWPORT_WIDTH_C, viewport_c->width, |
852 | PRI_VIEWPORT_HEIGHT_C, viewport_c->height); |
853 | |
854 | REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, |
855 | PRI_VIEWPORT_X_START_C, viewport_c->x, |
856 | PRI_VIEWPORT_Y_START_C, viewport_c->y); |
857 | |
858 | REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION_C, 0, |
859 | SEC_VIEWPORT_WIDTH_C, viewport_c->width, |
860 | SEC_VIEWPORT_HEIGHT_C, viewport_c->height); |
861 | |
862 | REG_SET_2(DCSURF_SEC_VIEWPORT_START_C, 0, |
863 | SEC_VIEWPORT_X_START_C, viewport_c->x, |
864 | SEC_VIEWPORT_Y_START_C, viewport_c->y); |
865 | } |
866 | |
867 | void hubp1_read_state_common(struct hubp *hubp) |
868 | { |
869 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
870 | struct dcn_hubp_state *s = &hubp1->state; |
871 | struct _vcs_dpi_display_dlg_regs_st *dlg_attr = &s->dlg_attr; |
872 | struct _vcs_dpi_display_ttu_regs_st *ttu_attr = &s->ttu_attr; |
873 | struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs; |
874 | uint32_t aperture_low_msb, aperture_low_lsb; |
875 | uint32_t aperture_high_msb, aperture_high_lsb; |
876 | |
877 | /* Requester */ |
878 | REG_GET(HUBPRET_CONTROL, |
879 | DET_BUF_PLANE1_BASE_ADDRESS, &rq_regs->plane1_base_address); |
880 | REG_GET_4(DCN_EXPANSION_MODE, |
881 | DRQ_EXPANSION_MODE, &rq_regs->drq_expansion_mode, |
882 | PRQ_EXPANSION_MODE, &rq_regs->prq_expansion_mode, |
883 | MRQ_EXPANSION_MODE, &rq_regs->mrq_expansion_mode, |
884 | CRQ_EXPANSION_MODE, &rq_regs->crq_expansion_mode); |
885 | |
886 | REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, |
887 | MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, &aperture_low_msb); |
888 | |
889 | REG_GET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, |
890 | MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, &aperture_low_lsb); |
891 | |
892 | REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, |
893 | MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, &aperture_high_msb); |
894 | |
895 | REG_GET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, |
896 | MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, &aperture_high_lsb); |
897 | |
898 | // On DCN1, aperture is broken down into MSB and LSB; only keep bits [47:18] to match later DCN format |
899 | rq_regs->aperture_low_addr = (aperture_low_msb << 26) | (aperture_low_lsb >> 6); |
900 | rq_regs->aperture_high_addr = (aperture_high_msb << 26) | (aperture_high_lsb >> 6); |
901 | |
902 | /* DLG - Per hubp */ |
903 | REG_GET_2(BLANK_OFFSET_0, |
904 | REFCYC_H_BLANK_END, &dlg_attr->refcyc_h_blank_end, |
905 | DLG_V_BLANK_END, &dlg_attr->dlg_vblank_end); |
906 | |
907 | REG_GET(BLANK_OFFSET_1, |
908 | MIN_DST_Y_NEXT_START, &dlg_attr->min_dst_y_next_start); |
909 | |
910 | REG_GET(DST_DIMENSIONS, |
911 | REFCYC_PER_HTOTAL, &dlg_attr->refcyc_per_htotal); |
912 | |
913 | REG_GET_2(DST_AFTER_SCALER, |
914 | REFCYC_X_AFTER_SCALER, &dlg_attr->refcyc_x_after_scaler, |
915 | DST_Y_AFTER_SCALER, &dlg_attr->dst_y_after_scaler); |
916 | |
917 | if (REG(PREFETCH_SETTINS)) |
918 | REG_GET_2(PREFETCH_SETTINS, |
919 | DST_Y_PREFETCH, &dlg_attr->dst_y_prefetch, |
920 | VRATIO_PREFETCH, &dlg_attr->vratio_prefetch); |
921 | else |
922 | REG_GET_2(PREFETCH_SETTINGS, |
923 | DST_Y_PREFETCH, &dlg_attr->dst_y_prefetch, |
924 | VRATIO_PREFETCH, &dlg_attr->vratio_prefetch); |
925 | |
926 | REG_GET_2(VBLANK_PARAMETERS_0, |
927 | DST_Y_PER_VM_VBLANK, &dlg_attr->dst_y_per_vm_vblank, |
928 | DST_Y_PER_ROW_VBLANK, &dlg_attr->dst_y_per_row_vblank); |
929 | |
930 | REG_GET(REF_FREQ_TO_PIX_FREQ, |
931 | REF_FREQ_TO_PIX_FREQ, &dlg_attr->ref_freq_to_pix_freq); |
932 | |
933 | /* DLG - Per luma/chroma */ |
934 | REG_GET(VBLANK_PARAMETERS_1, |
935 | REFCYC_PER_PTE_GROUP_VBLANK_L, &dlg_attr->refcyc_per_pte_group_vblank_l); |
936 | |
937 | REG_GET(VBLANK_PARAMETERS_3, |
938 | REFCYC_PER_META_CHUNK_VBLANK_L, &dlg_attr->refcyc_per_meta_chunk_vblank_l); |
939 | |
940 | if (REG(NOM_PARAMETERS_0)) |
941 | REG_GET(NOM_PARAMETERS_0, |
942 | DST_Y_PER_PTE_ROW_NOM_L, &dlg_attr->dst_y_per_pte_row_nom_l); |
943 | |
944 | if (REG(NOM_PARAMETERS_1)) |
945 | REG_GET(NOM_PARAMETERS_1, |
946 | REFCYC_PER_PTE_GROUP_NOM_L, &dlg_attr->refcyc_per_pte_group_nom_l); |
947 | |
948 | REG_GET(NOM_PARAMETERS_4, |
949 | DST_Y_PER_META_ROW_NOM_L, &dlg_attr->dst_y_per_meta_row_nom_l); |
950 | |
951 | REG_GET(NOM_PARAMETERS_5, |
952 | REFCYC_PER_META_CHUNK_NOM_L, &dlg_attr->refcyc_per_meta_chunk_nom_l); |
953 | |
954 | REG_GET_2(PER_LINE_DELIVERY_PRE, |
955 | REFCYC_PER_LINE_DELIVERY_PRE_L, &dlg_attr->refcyc_per_line_delivery_pre_l, |
956 | REFCYC_PER_LINE_DELIVERY_PRE_C, &dlg_attr->refcyc_per_line_delivery_pre_c); |
957 | |
958 | REG_GET_2(PER_LINE_DELIVERY, |
959 | REFCYC_PER_LINE_DELIVERY_L, &dlg_attr->refcyc_per_line_delivery_l, |
960 | REFCYC_PER_LINE_DELIVERY_C, &dlg_attr->refcyc_per_line_delivery_c); |
961 | |
962 | if (REG(PREFETCH_SETTINS_C)) |
963 | REG_GET(PREFETCH_SETTINS_C, |
964 | VRATIO_PREFETCH_C, &dlg_attr->vratio_prefetch_c); |
965 | else |
966 | REG_GET(PREFETCH_SETTINGS_C, |
967 | VRATIO_PREFETCH_C, &dlg_attr->vratio_prefetch_c); |
968 | |
969 | REG_GET(VBLANK_PARAMETERS_2, |
970 | REFCYC_PER_PTE_GROUP_VBLANK_C, &dlg_attr->refcyc_per_pte_group_vblank_c); |
971 | |
972 | REG_GET(VBLANK_PARAMETERS_4, |
973 | REFCYC_PER_META_CHUNK_VBLANK_C, &dlg_attr->refcyc_per_meta_chunk_vblank_c); |
974 | |
975 | if (REG(NOM_PARAMETERS_2)) |
976 | REG_GET(NOM_PARAMETERS_2, |
977 | DST_Y_PER_PTE_ROW_NOM_C, &dlg_attr->dst_y_per_pte_row_nom_c); |
978 | |
979 | if (REG(NOM_PARAMETERS_3)) |
980 | REG_GET(NOM_PARAMETERS_3, |
981 | REFCYC_PER_PTE_GROUP_NOM_C, &dlg_attr->refcyc_per_pte_group_nom_c); |
982 | |
983 | REG_GET(NOM_PARAMETERS_6, |
984 | DST_Y_PER_META_ROW_NOM_C, &dlg_attr->dst_y_per_meta_row_nom_c); |
985 | |
986 | REG_GET(NOM_PARAMETERS_7, |
987 | REFCYC_PER_META_CHUNK_NOM_C, &dlg_attr->refcyc_per_meta_chunk_nom_c); |
988 | |
989 | /* TTU - per hubp */ |
990 | REG_GET_2(DCN_TTU_QOS_WM, |
991 | QoS_LEVEL_LOW_WM, &ttu_attr->qos_level_low_wm, |
992 | QoS_LEVEL_HIGH_WM, &ttu_attr->qos_level_high_wm); |
993 | |
994 | REG_GET_2(DCN_GLOBAL_TTU_CNTL, |
995 | MIN_TTU_VBLANK, &ttu_attr->min_ttu_vblank, |
996 | QoS_LEVEL_FLIP, &ttu_attr->qos_level_flip); |
997 | |
998 | /* TTU - per luma/chroma */ |
999 | /* Assumed surf0 is luma and 1 is chroma */ |
1000 | |
1001 | REG_GET_3(DCN_SURF0_TTU_CNTL0, |
1002 | REFCYC_PER_REQ_DELIVERY, &ttu_attr->refcyc_per_req_delivery_l, |
1003 | QoS_LEVEL_FIXED, &ttu_attr->qos_level_fixed_l, |
1004 | QoS_RAMP_DISABLE, &ttu_attr->qos_ramp_disable_l); |
1005 | |
1006 | REG_GET(DCN_SURF0_TTU_CNTL1, |
1007 | REFCYC_PER_REQ_DELIVERY_PRE, |
1008 | &ttu_attr->refcyc_per_req_delivery_pre_l); |
1009 | |
1010 | REG_GET_3(DCN_SURF1_TTU_CNTL0, |
1011 | REFCYC_PER_REQ_DELIVERY, &ttu_attr->refcyc_per_req_delivery_c, |
1012 | QoS_LEVEL_FIXED, &ttu_attr->qos_level_fixed_c, |
1013 | QoS_RAMP_DISABLE, &ttu_attr->qos_ramp_disable_c); |
1014 | |
1015 | REG_GET(DCN_SURF1_TTU_CNTL1, |
1016 | REFCYC_PER_REQ_DELIVERY_PRE, |
1017 | &ttu_attr->refcyc_per_req_delivery_pre_c); |
1018 | |
1019 | /* Rest of hubp */ |
1020 | REG_GET(DCSURF_SURFACE_CONFIG, |
1021 | SURFACE_PIXEL_FORMAT, &s->pixel_format); |
1022 | |
1023 | REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, |
1024 | SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &s->inuse_addr_hi); |
1025 | |
1026 | REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, |
1027 | SURFACE_EARLIEST_INUSE_ADDRESS, &s->inuse_addr_lo); |
1028 | |
1029 | REG_GET_2(DCSURF_PRI_VIEWPORT_DIMENSION, |
1030 | PRI_VIEWPORT_WIDTH, &s->viewport_width, |
1031 | PRI_VIEWPORT_HEIGHT, &s->viewport_height); |
1032 | |
1033 | REG_GET_2(DCSURF_SURFACE_CONFIG, |
1034 | ROTATION_ANGLE, &s->rotation_angle, |
1035 | H_MIRROR_EN, &s->h_mirror_en); |
1036 | |
1037 | REG_GET(DCSURF_TILING_CONFIG, |
1038 | SW_MODE, &s->sw_mode); |
1039 | |
1040 | REG_GET(DCSURF_SURFACE_CONTROL, |
1041 | PRIMARY_SURFACE_DCC_EN, &s->dcc_en); |
1042 | |
1043 | REG_GET_3(DCHUBP_CNTL, |
1044 | HUBP_BLANK_EN, &s->blank_en, |
1045 | HUBP_TTU_DISABLE, &s->ttu_disable, |
1046 | HUBP_UNDERFLOW_STATUS, &s->underflow_status); |
1047 | |
1048 | REG_GET(HUBP_CLK_CNTL, |
1049 | HUBP_CLOCK_ENABLE, &s->clock_en); |
1050 | |
1051 | REG_GET(DCN_GLOBAL_TTU_CNTL, |
1052 | MIN_TTU_VBLANK, &s->min_ttu_vblank); |
1053 | |
1054 | REG_GET_2(DCN_TTU_QOS_WM, |
1055 | QoS_LEVEL_LOW_WM, &s->qos_level_low_wm, |
1056 | QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); |
1057 | |
1058 | REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS, |
1059 | PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_lo); |
1060 | |
1061 | REG_GET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, |
1062 | PRIMARY_SURFACE_ADDRESS, &s->primary_surface_addr_hi); |
1063 | |
1064 | REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, |
1065 | PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_lo); |
1066 | |
1067 | REG_GET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, |
1068 | PRIMARY_META_SURFACE_ADDRESS, &s->primary_meta_addr_hi); |
1069 | } |
1070 | |
1071 | void hubp1_read_state(struct hubp *hubp) |
1072 | { |
1073 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1074 | struct dcn_hubp_state *s = &hubp1->state; |
1075 | struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs; |
1076 | |
1077 | hubp1_read_state_common(hubp); |
1078 | |
1079 | REG_GET_8(DCHUBP_REQ_SIZE_CONFIG, |
1080 | CHUNK_SIZE, &rq_regs->rq_regs_l.chunk_size, |
1081 | MIN_CHUNK_SIZE, &rq_regs->rq_regs_l.min_chunk_size, |
1082 | META_CHUNK_SIZE, &rq_regs->rq_regs_l.meta_chunk_size, |
1083 | MIN_META_CHUNK_SIZE, &rq_regs->rq_regs_l.min_meta_chunk_size, |
1084 | DPTE_GROUP_SIZE, &rq_regs->rq_regs_l.dpte_group_size, |
1085 | MPTE_GROUP_SIZE, &rq_regs->rq_regs_l.mpte_group_size, |
1086 | SWATH_HEIGHT, &rq_regs->rq_regs_l.swath_height, |
1087 | PTE_ROW_HEIGHT_LINEAR, &rq_regs->rq_regs_l.pte_row_height_linear); |
1088 | |
1089 | REG_GET_8(DCHUBP_REQ_SIZE_CONFIG_C, |
1090 | CHUNK_SIZE_C, &rq_regs->rq_regs_c.chunk_size, |
1091 | MIN_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_chunk_size, |
1092 | META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.meta_chunk_size, |
1093 | MIN_META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_meta_chunk_size, |
1094 | DPTE_GROUP_SIZE_C, &rq_regs->rq_regs_c.dpte_group_size, |
1095 | MPTE_GROUP_SIZE_C, &rq_regs->rq_regs_c.mpte_group_size, |
1096 | SWATH_HEIGHT_C, &rq_regs->rq_regs_c.swath_height, |
1097 | PTE_ROW_HEIGHT_LINEAR_C, &rq_regs->rq_regs_c.pte_row_height_linear); |
1098 | |
1099 | } |
1100 | enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch) |
1101 | { |
1102 | enum cursor_pitch hw_pitch; |
1103 | |
1104 | switch (pitch) { |
1105 | case 64: |
1106 | hw_pitch = CURSOR_PITCH_64_PIXELS; |
1107 | break; |
1108 | case 128: |
1109 | hw_pitch = CURSOR_PITCH_128_PIXELS; |
1110 | break; |
1111 | case 256: |
1112 | hw_pitch = CURSOR_PITCH_256_PIXELS; |
1113 | break; |
1114 | default: |
1115 | DC_ERR("Invalid cursor pitch of %d. " |
1116 | "Only 64/128/256 is supported on DCN.\n" , pitch); |
1117 | hw_pitch = CURSOR_PITCH_64_PIXELS; |
1118 | break; |
1119 | } |
1120 | return hw_pitch; |
1121 | } |
1122 | |
1123 | static enum cursor_lines_per_chunk hubp1_get_lines_per_chunk( |
1124 | unsigned int cur_width, |
1125 | enum dc_cursor_color_format format) |
1126 | { |
1127 | enum cursor_lines_per_chunk line_per_chunk; |
1128 | |
1129 | if (format == CURSOR_MODE_MONO) |
1130 | /* impl B. expansion in CUR Buffer reader */ |
1131 | line_per_chunk = CURSOR_LINE_PER_CHUNK_16; |
1132 | else if (cur_width <= 32) |
1133 | line_per_chunk = CURSOR_LINE_PER_CHUNK_16; |
1134 | else if (cur_width <= 64) |
1135 | line_per_chunk = CURSOR_LINE_PER_CHUNK_8; |
1136 | else if (cur_width <= 128) |
1137 | line_per_chunk = CURSOR_LINE_PER_CHUNK_4; |
1138 | else |
1139 | line_per_chunk = CURSOR_LINE_PER_CHUNK_2; |
1140 | |
1141 | return line_per_chunk; |
1142 | } |
1143 | |
1144 | void hubp1_cursor_set_attributes( |
1145 | struct hubp *hubp, |
1146 | const struct dc_cursor_attributes *attr) |
1147 | { |
1148 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1149 | enum cursor_pitch hw_pitch = hubp1_get_cursor_pitch(pitch: attr->pitch); |
1150 | enum cursor_lines_per_chunk lpc = hubp1_get_lines_per_chunk( |
1151 | cur_width: attr->width, format: attr->color_format); |
1152 | |
1153 | hubp->curs_attr = *attr; |
1154 | |
1155 | REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, |
1156 | CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); |
1157 | REG_UPDATE(CURSOR_SURFACE_ADDRESS, |
1158 | CURSOR_SURFACE_ADDRESS, attr->address.low_part); |
1159 | |
1160 | REG_UPDATE_2(CURSOR_SIZE, |
1161 | CURSOR_WIDTH, attr->width, |
1162 | CURSOR_HEIGHT, attr->height); |
1163 | |
1164 | REG_UPDATE_3(CURSOR_CONTROL, |
1165 | CURSOR_MODE, attr->color_format, |
1166 | CURSOR_PITCH, hw_pitch, |
1167 | CURSOR_LINES_PER_CHUNK, lpc); |
1168 | |
1169 | REG_SET_2(CURSOR_SETTINS, 0, |
1170 | /* no shift of the cursor HDL schedule */ |
1171 | CURSOR0_DST_Y_OFFSET, 0, |
1172 | /* used to shift the cursor chunk request deadline */ |
1173 | CURSOR0_CHUNK_HDL_ADJUST, 3); |
1174 | } |
1175 | |
1176 | void hubp1_cursor_set_position( |
1177 | struct hubp *hubp, |
1178 | const struct dc_cursor_position *pos, |
1179 | const struct dc_cursor_mi_param *param) |
1180 | { |
1181 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1182 | int x_pos = pos->x - param->viewport.x; |
1183 | int y_pos = pos->y - param->viewport.y; |
1184 | int x_hotspot = pos->x_hotspot; |
1185 | int y_hotspot = pos->y_hotspot; |
1186 | int src_x_offset = x_pos - pos->x_hotspot; |
1187 | int src_y_offset = y_pos - pos->y_hotspot; |
1188 | int cursor_height = (int)hubp->curs_attr.height; |
1189 | int cursor_width = (int)hubp->curs_attr.width; |
1190 | uint32_t dst_x_offset; |
1191 | uint32_t cur_en = pos->enable ? 1 : 0; |
1192 | |
1193 | hubp->curs_pos = *pos; |
1194 | |
1195 | /* |
1196 | * Guard aganst cursor_set_position() from being called with invalid |
1197 | * attributes |
1198 | * |
1199 | * TODO: Look at combining cursor_set_position() and |
1200 | * cursor_set_attributes() into cursor_update() |
1201 | */ |
1202 | if (hubp->curs_attr.address.quad_part == 0) |
1203 | return; |
1204 | |
1205 | // Transform cursor width / height and hotspots for offset calculations |
1206 | if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) { |
1207 | swap(cursor_height, cursor_width); |
1208 | swap(x_hotspot, y_hotspot); |
1209 | |
1210 | if (param->rotation == ROTATION_ANGLE_90) { |
1211 | // hotspot = (-y, x) |
1212 | src_x_offset = x_pos - (cursor_width - x_hotspot); |
1213 | src_y_offset = y_pos - y_hotspot; |
1214 | } else if (param->rotation == ROTATION_ANGLE_270) { |
1215 | // hotspot = (y, -x) |
1216 | src_x_offset = x_pos - x_hotspot; |
1217 | src_y_offset = y_pos - (cursor_height - y_hotspot); |
1218 | } |
1219 | } else if (param->rotation == ROTATION_ANGLE_180) { |
1220 | // hotspot = (-x, -y) |
1221 | if (!param->mirror) |
1222 | src_x_offset = x_pos - (cursor_width - x_hotspot); |
1223 | |
1224 | src_y_offset = y_pos - (cursor_height - y_hotspot); |
1225 | } |
1226 | |
1227 | dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; |
1228 | dst_x_offset *= param->ref_clk_khz; |
1229 | dst_x_offset /= param->pixel_clk_khz; |
1230 | |
1231 | ASSERT(param->h_scale_ratio.value); |
1232 | |
1233 | if (param->h_scale_ratio.value) |
1234 | dst_x_offset = dc_fixpt_floor(arg: dc_fixpt_div( |
1235 | arg1: dc_fixpt_from_int(arg: dst_x_offset), |
1236 | arg2: param->h_scale_ratio)); |
1237 | |
1238 | if (src_x_offset >= (int)param->viewport.width) |
1239 | cur_en = 0; /* not visible beyond right edge*/ |
1240 | |
1241 | if (src_x_offset + cursor_width <= 0) |
1242 | cur_en = 0; /* not visible beyond left edge*/ |
1243 | |
1244 | if (src_y_offset >= (int)param->viewport.height) |
1245 | cur_en = 0; /* not visible beyond bottom edge*/ |
1246 | |
1247 | if (src_y_offset + cursor_height <= 0) |
1248 | cur_en = 0; /* not visible beyond top edge*/ |
1249 | |
1250 | if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) |
1251 | hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr); |
1252 | |
1253 | REG_UPDATE(CURSOR_CONTROL, |
1254 | CURSOR_ENABLE, cur_en); |
1255 | |
1256 | REG_SET_2(CURSOR_POSITION, 0, |
1257 | CURSOR_X_POSITION, pos->x, |
1258 | CURSOR_Y_POSITION, pos->y); |
1259 | |
1260 | REG_SET_2(CURSOR_HOT_SPOT, 0, |
1261 | CURSOR_HOT_SPOT_X, pos->x_hotspot, |
1262 | CURSOR_HOT_SPOT_Y, pos->y_hotspot); |
1263 | |
1264 | REG_SET(CURSOR_DST_OFFSET, 0, |
1265 | CURSOR_DST_X_OFFSET, dst_x_offset); |
1266 | /* TODO Handle surface pixel formats other than 4:4:4 */ |
1267 | } |
1268 | |
1269 | /** |
1270 | * hubp1_clk_cntl - Disable or enable clocks for DCHUBP |
1271 | * |
1272 | * @hubp: hubp struct reference. |
1273 | * @enable: Set true for enabling gate clock. |
1274 | * |
1275 | * When enabling/disabling DCHUBP clock, we affect dcfclk/dppclk. |
1276 | */ |
1277 | void hubp1_clk_cntl(struct hubp *hubp, bool enable) |
1278 | { |
1279 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1280 | uint32_t clk_enable = enable ? 1 : 0; |
1281 | |
1282 | REG_UPDATE(HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, clk_enable); |
1283 | } |
1284 | |
1285 | void hubp1_vtg_sel(struct hubp *hubp, uint32_t otg_inst) |
1286 | { |
1287 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1288 | |
1289 | REG_UPDATE(DCHUBP_CNTL, HUBP_VTG_SEL, otg_inst); |
1290 | } |
1291 | |
1292 | bool hubp1_in_blank(struct hubp *hubp) |
1293 | { |
1294 | uint32_t in_blank; |
1295 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1296 | |
1297 | REG_GET(DCHUBP_CNTL, HUBP_IN_BLANK, &in_blank); |
1298 | return in_blank ? true : false; |
1299 | } |
1300 | |
1301 | void hubp1_soft_reset(struct hubp *hubp, bool reset) |
1302 | { |
1303 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1304 | |
1305 | REG_UPDATE(DCHUBP_CNTL, HUBP_DISABLE, reset ? 1 : 0); |
1306 | } |
1307 | |
1308 | /** |
1309 | * hubp1_set_flip_int - Enable surface flip interrupt |
1310 | * |
1311 | * @hubp: hubp struct reference. |
1312 | */ |
1313 | void hubp1_set_flip_int(struct hubp *hubp) |
1314 | { |
1315 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1316 | |
1317 | REG_UPDATE(DCSURF_SURFACE_FLIP_INTERRUPT, |
1318 | SURFACE_FLIP_INT_MASK, 1); |
1319 | |
1320 | return; |
1321 | } |
1322 | |
1323 | /** |
1324 | * hubp1_wait_pipe_read_start - wait for hubp ret path starting read. |
1325 | * |
1326 | * @hubp: hubp struct reference. |
1327 | */ |
1328 | static void hubp1_wait_pipe_read_start(struct hubp *hubp) |
1329 | { |
1330 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
1331 | |
1332 | REG_WAIT(HUBPRET_READ_LINE_STATUS, |
1333 | PIPE_READ_VBLANK, 0, |
1334 | 1, 1000); |
1335 | } |
1336 | |
1337 | void hubp1_init(struct hubp *hubp) |
1338 | { |
1339 | //do nothing |
1340 | } |
1341 | static const struct hubp_funcs dcn10_hubp_funcs = { |
1342 | .hubp_program_surface_flip_and_addr = |
1343 | hubp1_program_surface_flip_and_addr, |
1344 | .hubp_program_surface_config = |
1345 | hubp1_program_surface_config, |
1346 | .hubp_is_flip_pending = hubp1_is_flip_pending, |
1347 | .hubp_setup = hubp1_setup, |
1348 | .hubp_setup_interdependent = hubp1_setup_interdependent, |
1349 | .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, |
1350 | .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, |
1351 | .set_blank = hubp1_set_blank, |
1352 | .dcc_control = hubp1_dcc_control, |
1353 | .mem_program_viewport = min_set_viewport, |
1354 | .set_hubp_blank_en = hubp1_set_hubp_blank_en, |
1355 | .set_cursor_attributes = hubp1_cursor_set_attributes, |
1356 | .set_cursor_position = hubp1_cursor_set_position, |
1357 | .hubp_disconnect = hubp1_disconnect, |
1358 | .hubp_clk_cntl = hubp1_clk_cntl, |
1359 | .hubp_vtg_sel = hubp1_vtg_sel, |
1360 | .hubp_read_state = hubp1_read_state, |
1361 | .hubp_clear_underflow = hubp1_clear_underflow, |
1362 | .hubp_disable_control = hubp1_disable_control, |
1363 | .hubp_get_underflow_status = hubp1_get_underflow_status, |
1364 | .hubp_init = hubp1_init, |
1365 | |
1366 | .dmdata_set_attributes = NULL, |
1367 | .dmdata_load = NULL, |
1368 | .hubp_soft_reset = hubp1_soft_reset, |
1369 | .hubp_in_blank = hubp1_in_blank, |
1370 | .hubp_set_flip_int = hubp1_set_flip_int, |
1371 | .hubp_wait_pipe_read_start = hubp1_wait_pipe_read_start, |
1372 | }; |
1373 | |
1374 | /*****************************************/ |
1375 | /* Constructor, Destructor */ |
1376 | /*****************************************/ |
1377 | |
1378 | void dcn10_hubp_construct( |
1379 | struct dcn10_hubp *hubp1, |
1380 | struct dc_context *ctx, |
1381 | uint32_t inst, |
1382 | const struct dcn_mi_registers *hubp_regs, |
1383 | const struct dcn_mi_shift *hubp_shift, |
1384 | const struct dcn_mi_mask *hubp_mask) |
1385 | { |
1386 | hubp1->base.funcs = &dcn10_hubp_funcs; |
1387 | hubp1->base.ctx = ctx; |
1388 | hubp1->hubp_regs = hubp_regs; |
1389 | hubp1->hubp_shift = hubp_shift; |
1390 | hubp1->hubp_mask = hubp_mask; |
1391 | hubp1->base.inst = inst; |
1392 | hubp1->base.opp_id = OPP_ID_INVALID; |
1393 | hubp1->base.mpcc_id = 0xf; |
1394 | } |
1395 | |
1396 | |
1397 | |