2 * Copyright 2012-15 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
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"
38 #define FN(reg_name, field_name) \
39 hubp1->hubp_shift->field_name, hubp1->hubp_mask->field_name
41 void hubp1_set_blank(struct hubp
*hubp
, bool blank
)
43 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
44 uint32_t blank_en
= blank
? 1 : 0;
46 REG_UPDATE_2(DCHUBP_CNTL
,
47 HUBP_BLANK_EN
, blank_en
,
48 HUBP_TTU_DISABLE
, blank_en
);
52 HUBP_NO_OUTSTANDING_REQ
, 1,
59 static void hubp1_set_hubp_blank_en(struct hubp
*hubp
, bool blank
)
61 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
62 uint32_t blank_en
= blank
? 1 : 0;
64 REG_UPDATE(DCHUBP_CNTL
, HUBP_BLANK_EN
, blank_en
);
67 static void hubp1_vready_workaround(struct hubp
*hubp
,
68 struct _vcs_dpi_display_pipe_dest_params_st
*pipe_dest
)
71 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
73 /* set HBUBREQ_DEBUG_DB[12] = 1 */
74 value
= REG_READ(HUBPREQ_DEBUG_DB
);
76 /* hack mode disable */
80 if ((pipe_dest
->vstartup_start
- 2*(pipe_dest
->vready_offset
+pipe_dest
->vupdate_width
81 + pipe_dest
->vupdate_offset
) / pipe_dest
->htotal
) <= pipe_dest
->vblank_end
) {
82 /* if (eco_fix_needed(otg_global_sync_timing)
83 * set HBUBREQ_DEBUG_DB[12] = 1 */
87 REG_WRITE(HUBPREQ_DEBUG_DB
, value
);
90 void hubp1_program_tiling(
91 struct dcn10_hubp
*hubp1
,
92 const union dc_tiling_info
*info
,
93 const enum surface_pixel_format pixel_format
)
95 REG_UPDATE_6(DCSURF_ADDR_CONFIG
,
96 NUM_PIPES
, log_2(info
->gfx9
.num_pipes
),
97 NUM_BANKS
, log_2(info
->gfx9
.num_banks
),
98 PIPE_INTERLEAVE
, info
->gfx9
.pipe_interleave
,
99 NUM_SE
, log_2(info
->gfx9
.num_shader_engines
),
100 NUM_RB_PER_SE
, log_2(info
->gfx9
.num_rb_per_se
),
101 MAX_COMPRESSED_FRAGS
, log_2(info
->gfx9
.max_compressed_frags
));
103 REG_UPDATE_4(DCSURF_TILING_CONFIG
,
104 SW_MODE
, info
->gfx9
.swizzle
,
105 META_LINEAR
, info
->gfx9
.meta_linear
,
106 RB_ALIGNED
, info
->gfx9
.rb_aligned
,
107 PIPE_ALIGNED
, info
->gfx9
.pipe_aligned
);
110 void hubp1_program_size_and_rotation(
111 struct dcn10_hubp
*hubp1
,
112 enum dc_rotation_angle rotation
,
113 enum surface_pixel_format format
,
114 const union plane_size
*plane_size
,
115 struct dc_plane_dcc_param
*dcc
,
116 bool horizontal_mirror
)
118 uint32_t pitch
, meta_pitch
, pitch_c
, meta_pitch_c
, mirror
;
120 /* Program data and meta surface pitch (calculation from addrlib)
123 if (format
>= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
) {
124 pitch
= plane_size
->video
.luma_pitch
- 1;
125 meta_pitch
= dcc
->video
.meta_pitch_l
- 1;
126 pitch_c
= plane_size
->video
.chroma_pitch
- 1;
127 meta_pitch_c
= dcc
->video
.meta_pitch_c
- 1;
129 pitch
= plane_size
->grph
.surface_pitch
- 1;
130 meta_pitch
= dcc
->grph
.meta_pitch
- 1;
140 REG_UPDATE_2(DCSURF_SURFACE_PITCH
,
141 PITCH
, pitch
, META_PITCH
, meta_pitch
);
143 if (format
>= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
)
144 REG_UPDATE_2(DCSURF_SURFACE_PITCH_C
,
145 PITCH_C
, pitch_c
, META_PITCH_C
, meta_pitch_c
);
147 if (horizontal_mirror
)
153 /* Program rotation angle and horz mirror - no mirror */
154 if (rotation
== ROTATION_ANGLE_0
)
155 REG_UPDATE_2(DCSURF_SURFACE_CONFIG
,
157 H_MIRROR_EN
, mirror
);
158 else if (rotation
== ROTATION_ANGLE_90
)
159 REG_UPDATE_2(DCSURF_SURFACE_CONFIG
,
161 H_MIRROR_EN
, mirror
);
162 else if (rotation
== ROTATION_ANGLE_180
)
163 REG_UPDATE_2(DCSURF_SURFACE_CONFIG
,
165 H_MIRROR_EN
, mirror
);
166 else if (rotation
== ROTATION_ANGLE_270
)
167 REG_UPDATE_2(DCSURF_SURFACE_CONFIG
,
169 H_MIRROR_EN
, mirror
);
172 void hubp1_program_pixel_format(
173 struct dcn10_hubp
*hubp1
,
174 enum surface_pixel_format format
)
176 uint32_t red_bar
= 3;
177 uint32_t blue_bar
= 2;
179 /* swap for ABGR format */
180 if (format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
181 || format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
182 || format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
183 || format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
) {
188 REG_UPDATE_2(HUBPRET_CONTROL
,
189 CROSSBAR_SRC_CB_B
, blue_bar
,
190 CROSSBAR_SRC_CR_R
, red_bar
);
192 /* Mapping is same as ipp programming (cnvc) */
195 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
:
196 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
197 SURFACE_PIXEL_FORMAT
, 1);
199 case SURFACE_PIXEL_FORMAT_GRPH_RGB565
:
200 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
201 SURFACE_PIXEL_FORMAT
, 3);
203 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
:
204 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
:
205 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
206 SURFACE_PIXEL_FORMAT
, 8);
208 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010
:
209 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
:
210 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
:
211 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
212 SURFACE_PIXEL_FORMAT
, 10);
214 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
215 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
216 SURFACE_PIXEL_FORMAT
, 22);
218 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
:
219 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:/*we use crossbar already*/
220 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
221 SURFACE_PIXEL_FORMAT
, 24);
224 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr
:
225 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
226 SURFACE_PIXEL_FORMAT
, 65);
228 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb
:
229 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
230 SURFACE_PIXEL_FORMAT
, 64);
232 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr
:
233 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
234 SURFACE_PIXEL_FORMAT
, 67);
236 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb
:
237 REG_UPDATE(DCSURF_SURFACE_CONFIG
,
238 SURFACE_PIXEL_FORMAT
, 66);
245 /* don't see the need of program the xbar in DCN 1.0 */
248 bool hubp1_program_surface_flip_and_addr(
250 const struct dc_plane_address
*address
,
253 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
255 /* program flip type */
256 REG_SET(DCSURF_FLIP_CONTROL
, 0,
257 SURFACE_FLIP_TYPE
, flip_immediate
);
259 /* HW automatically latch rest of address register on write to
260 * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used
262 * program high first and then the low addr, order matters!
264 switch (address
->type
) {
265 case PLN_ADDR_TYPE_GRAPHICS
:
266 /* DCN1.0 does not support const color
267 * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1
268 * base on address->grph.dcc_const_color
269 * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma
270 * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma
273 if (address
->grph
.addr
.quad_part
== 0)
276 REG_UPDATE(DCSURF_SURFACE_CONTROL
,
277 PRIMARY_SURFACE_TMZ
, address
->tmz_surface
);
279 if (address
->grph
.meta_addr
.quad_part
!= 0) {
280 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH
, 0,
281 PRIMARY_META_SURFACE_ADDRESS_HIGH
,
282 address
->grph
.meta_addr
.high_part
);
284 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS
, 0,
285 PRIMARY_META_SURFACE_ADDRESS
,
286 address
->grph
.meta_addr
.low_part
);
289 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH
, 0,
290 PRIMARY_SURFACE_ADDRESS_HIGH
,
291 address
->grph
.addr
.high_part
);
293 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS
, 0,
294 PRIMARY_SURFACE_ADDRESS
,
295 address
->grph
.addr
.low_part
);
297 case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE
:
298 if (address
->video_progressive
.luma_addr
.quad_part
== 0
299 || address
->video_progressive
.chroma_addr
.quad_part
== 0)
302 REG_UPDATE(DCSURF_SURFACE_CONTROL
,
303 PRIMARY_SURFACE_TMZ
, address
->tmz_surface
);
305 if (address
->video_progressive
.luma_meta_addr
.quad_part
!= 0) {
306 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C
, 0,
307 PRIMARY_META_SURFACE_ADDRESS_HIGH_C
,
308 address
->video_progressive
.chroma_meta_addr
.high_part
);
310 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C
, 0,
311 PRIMARY_META_SURFACE_ADDRESS_C
,
312 address
->video_progressive
.chroma_meta_addr
.low_part
);
314 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH
, 0,
315 PRIMARY_META_SURFACE_ADDRESS_HIGH
,
316 address
->video_progressive
.luma_meta_addr
.high_part
);
318 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS
, 0,
319 PRIMARY_META_SURFACE_ADDRESS
,
320 address
->video_progressive
.luma_meta_addr
.low_part
);
323 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C
, 0,
324 PRIMARY_SURFACE_ADDRESS_HIGH_C
,
325 address
->video_progressive
.chroma_addr
.high_part
);
327 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C
, 0,
328 PRIMARY_SURFACE_ADDRESS_C
,
329 address
->video_progressive
.chroma_addr
.low_part
);
331 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH
, 0,
332 PRIMARY_SURFACE_ADDRESS_HIGH
,
333 address
->video_progressive
.luma_addr
.high_part
);
335 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS
, 0,
336 PRIMARY_SURFACE_ADDRESS
,
337 address
->video_progressive
.luma_addr
.low_part
);
339 case PLN_ADDR_TYPE_GRPH_STEREO
:
340 if (address
->grph_stereo
.left_addr
.quad_part
== 0)
342 if (address
->grph_stereo
.right_addr
.quad_part
== 0)
345 REG_UPDATE(DCSURF_SURFACE_CONTROL
,
346 PRIMARY_SURFACE_TMZ
, address
->tmz_surface
);
348 if (address
->grph_stereo
.right_meta_addr
.quad_part
!= 0) {
350 REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH
, 0,
351 SECONDARY_META_SURFACE_ADDRESS_HIGH
,
352 address
->grph_stereo
.right_meta_addr
.high_part
);
354 REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS
, 0,
355 SECONDARY_META_SURFACE_ADDRESS
,
356 address
->grph_stereo
.right_meta_addr
.low_part
);
358 if (address
->grph_stereo
.left_meta_addr
.quad_part
!= 0) {
360 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH
, 0,
361 PRIMARY_META_SURFACE_ADDRESS_HIGH
,
362 address
->grph_stereo
.left_meta_addr
.high_part
);
364 REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS
, 0,
365 PRIMARY_META_SURFACE_ADDRESS
,
366 address
->grph_stereo
.left_meta_addr
.low_part
);
369 REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH
, 0,
370 SECONDARY_SURFACE_ADDRESS_HIGH
,
371 address
->grph_stereo
.right_addr
.high_part
);
373 REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS
, 0,
374 SECONDARY_SURFACE_ADDRESS
,
375 address
->grph_stereo
.right_addr
.low_part
);
377 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH
, 0,
378 PRIMARY_SURFACE_ADDRESS_HIGH
,
379 address
->grph_stereo
.left_addr
.high_part
);
381 REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS
, 0,
382 PRIMARY_SURFACE_ADDRESS
,
383 address
->grph_stereo
.left_addr
.low_part
);
390 hubp
->request_address
= *address
;
393 hubp
->current_address
= *address
;
398 void hubp1_dcc_control(struct hubp
*hubp
, bool enable
,
399 bool independent_64b_blks
)
401 uint32_t dcc_en
= enable
? 1 : 0;
402 uint32_t dcc_ind_64b_blk
= independent_64b_blks
? 1 : 0;
403 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
405 REG_UPDATE_2(DCSURF_SURFACE_CONTROL
,
406 PRIMARY_SURFACE_DCC_EN
, dcc_en
,
407 PRIMARY_SURFACE_DCC_IND_64B_BLK
, dcc_ind_64b_blk
);
410 void hubp1_program_surface_config(
412 enum surface_pixel_format format
,
413 union dc_tiling_info
*tiling_info
,
414 union plane_size
*plane_size
,
415 enum dc_rotation_angle rotation
,
416 struct dc_plane_dcc_param
*dcc
,
417 bool horizontal_mirror
)
419 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
421 hubp1_dcc_control(hubp
, dcc
->enable
, dcc
->grph
.independent_64b_blks
);
422 hubp1_program_tiling(hubp1
, tiling_info
, format
);
423 hubp1_program_size_and_rotation(
424 hubp1
, rotation
, format
, plane_size
, dcc
, horizontal_mirror
);
425 hubp1_program_pixel_format(hubp1
, format
);
428 void hubp1_program_requestor(
430 struct _vcs_dpi_display_rq_regs_st
*rq_regs
)
432 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
434 REG_UPDATE(HUBPRET_CONTROL
,
435 DET_BUF_PLANE1_BASE_ADDRESS
, rq_regs
->plane1_base_address
);
436 REG_SET_4(DCN_EXPANSION_MODE
, 0,
437 DRQ_EXPANSION_MODE
, rq_regs
->drq_expansion_mode
,
438 PRQ_EXPANSION_MODE
, rq_regs
->prq_expansion_mode
,
439 MRQ_EXPANSION_MODE
, rq_regs
->mrq_expansion_mode
,
440 CRQ_EXPANSION_MODE
, rq_regs
->crq_expansion_mode
);
441 REG_SET_8(DCHUBP_REQ_SIZE_CONFIG
, 0,
442 CHUNK_SIZE
, rq_regs
->rq_regs_l
.chunk_size
,
443 MIN_CHUNK_SIZE
, rq_regs
->rq_regs_l
.min_chunk_size
,
444 META_CHUNK_SIZE
, rq_regs
->rq_regs_l
.meta_chunk_size
,
445 MIN_META_CHUNK_SIZE
, rq_regs
->rq_regs_l
.min_meta_chunk_size
,
446 DPTE_GROUP_SIZE
, rq_regs
->rq_regs_l
.dpte_group_size
,
447 MPTE_GROUP_SIZE
, rq_regs
->rq_regs_l
.mpte_group_size
,
448 SWATH_HEIGHT
, rq_regs
->rq_regs_l
.swath_height
,
449 PTE_ROW_HEIGHT_LINEAR
, rq_regs
->rq_regs_l
.pte_row_height_linear
);
450 REG_SET_8(DCHUBP_REQ_SIZE_CONFIG_C
, 0,
451 CHUNK_SIZE_C
, rq_regs
->rq_regs_c
.chunk_size
,
452 MIN_CHUNK_SIZE_C
, rq_regs
->rq_regs_c
.min_chunk_size
,
453 META_CHUNK_SIZE_C
, rq_regs
->rq_regs_c
.meta_chunk_size
,
454 MIN_META_CHUNK_SIZE_C
, rq_regs
->rq_regs_c
.min_meta_chunk_size
,
455 DPTE_GROUP_SIZE_C
, rq_regs
->rq_regs_c
.dpte_group_size
,
456 MPTE_GROUP_SIZE_C
, rq_regs
->rq_regs_c
.mpte_group_size
,
457 SWATH_HEIGHT_C
, rq_regs
->rq_regs_c
.swath_height
,
458 PTE_ROW_HEIGHT_LINEAR_C
, rq_regs
->rq_regs_c
.pte_row_height_linear
);
462 void hubp1_program_deadline(
464 struct _vcs_dpi_display_dlg_regs_st
*dlg_attr
,
465 struct _vcs_dpi_display_ttu_regs_st
*ttu_attr
)
467 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
470 REG_SET_2(BLANK_OFFSET_0
, 0,
471 REFCYC_H_BLANK_END
, dlg_attr
->refcyc_h_blank_end
,
472 DLG_V_BLANK_END
, dlg_attr
->dlg_vblank_end
);
474 REG_SET(BLANK_OFFSET_1
, 0,
475 MIN_DST_Y_NEXT_START
, dlg_attr
->min_dst_y_next_start
);
477 REG_SET(DST_DIMENSIONS
, 0,
478 REFCYC_PER_HTOTAL
, dlg_attr
->refcyc_per_htotal
);
480 REG_SET_2(DST_AFTER_SCALER
, 0,
481 REFCYC_X_AFTER_SCALER
, dlg_attr
->refcyc_x_after_scaler
,
482 DST_Y_AFTER_SCALER
, dlg_attr
->dst_y_after_scaler
);
484 if (REG(PREFETCH_SETTINS
))
485 REG_SET_2(PREFETCH_SETTINS
, 0,
486 DST_Y_PREFETCH
, dlg_attr
->dst_y_prefetch
,
487 VRATIO_PREFETCH
, dlg_attr
->vratio_prefetch
);
489 REG_SET_2(PREFETCH_SETTINGS
, 0,
490 DST_Y_PREFETCH
, dlg_attr
->dst_y_prefetch
,
491 VRATIO_PREFETCH
, dlg_attr
->vratio_prefetch
);
493 REG_SET_2(VBLANK_PARAMETERS_0
, 0,
494 DST_Y_PER_VM_VBLANK
, dlg_attr
->dst_y_per_vm_vblank
,
495 DST_Y_PER_ROW_VBLANK
, dlg_attr
->dst_y_per_row_vblank
);
497 REG_SET(REF_FREQ_TO_PIX_FREQ
, 0,
498 REF_FREQ_TO_PIX_FREQ
, dlg_attr
->ref_freq_to_pix_freq
);
500 /* DLG - Per luma/chroma */
501 REG_SET(VBLANK_PARAMETERS_1
, 0,
502 REFCYC_PER_PTE_GROUP_VBLANK_L
, dlg_attr
->refcyc_per_pte_group_vblank_l
);
504 REG_SET(VBLANK_PARAMETERS_3
, 0,
505 REFCYC_PER_META_CHUNK_VBLANK_L
, dlg_attr
->refcyc_per_meta_chunk_vblank_l
);
507 REG_SET(NOM_PARAMETERS_0
, 0,
508 DST_Y_PER_PTE_ROW_NOM_L
, dlg_attr
->dst_y_per_pte_row_nom_l
);
510 REG_SET(NOM_PARAMETERS_1
, 0,
511 REFCYC_PER_PTE_GROUP_NOM_L
, dlg_attr
->refcyc_per_pte_group_nom_l
);
513 REG_SET(NOM_PARAMETERS_4
, 0,
514 DST_Y_PER_META_ROW_NOM_L
, dlg_attr
->dst_y_per_meta_row_nom_l
);
516 REG_SET(NOM_PARAMETERS_5
, 0,
517 REFCYC_PER_META_CHUNK_NOM_L
, dlg_attr
->refcyc_per_meta_chunk_nom_l
);
519 REG_SET_2(PER_LINE_DELIVERY_PRE
, 0,
520 REFCYC_PER_LINE_DELIVERY_PRE_L
, dlg_attr
->refcyc_per_line_delivery_pre_l
,
521 REFCYC_PER_LINE_DELIVERY_PRE_C
, dlg_attr
->refcyc_per_line_delivery_pre_c
);
523 REG_SET_2(PER_LINE_DELIVERY
, 0,
524 REFCYC_PER_LINE_DELIVERY_L
, dlg_attr
->refcyc_per_line_delivery_l
,
525 REFCYC_PER_LINE_DELIVERY_C
, dlg_attr
->refcyc_per_line_delivery_c
);
527 if (REG(PREFETCH_SETTINS_C
))
528 REG_SET(PREFETCH_SETTINS_C
, 0,
529 VRATIO_PREFETCH_C
, dlg_attr
->vratio_prefetch_c
);
531 REG_SET(PREFETCH_SETTINGS_C
, 0,
532 VRATIO_PREFETCH_C
, dlg_attr
->vratio_prefetch_c
);
534 REG_SET(VBLANK_PARAMETERS_2
, 0,
535 REFCYC_PER_PTE_GROUP_VBLANK_C
, dlg_attr
->refcyc_per_pte_group_vblank_c
);
537 REG_SET(VBLANK_PARAMETERS_4
, 0,
538 REFCYC_PER_META_CHUNK_VBLANK_C
, dlg_attr
->refcyc_per_meta_chunk_vblank_c
);
540 REG_SET(NOM_PARAMETERS_2
, 0,
541 DST_Y_PER_PTE_ROW_NOM_C
, dlg_attr
->dst_y_per_pte_row_nom_c
);
543 REG_SET(NOM_PARAMETERS_3
, 0,
544 REFCYC_PER_PTE_GROUP_NOM_C
, dlg_attr
->refcyc_per_pte_group_nom_c
);
546 REG_SET(NOM_PARAMETERS_6
, 0,
547 DST_Y_PER_META_ROW_NOM_C
, dlg_attr
->dst_y_per_meta_row_nom_c
);
549 REG_SET(NOM_PARAMETERS_7
, 0,
550 REFCYC_PER_META_CHUNK_NOM_C
, dlg_attr
->refcyc_per_meta_chunk_nom_c
);
553 REG_SET_2(DCN_TTU_QOS_WM
, 0,
554 QoS_LEVEL_LOW_WM
, ttu_attr
->qos_level_low_wm
,
555 QoS_LEVEL_HIGH_WM
, ttu_attr
->qos_level_high_wm
);
557 REG_SET_2(DCN_GLOBAL_TTU_CNTL
, 0,
558 MIN_TTU_VBLANK
, ttu_attr
->min_ttu_vblank
,
559 QoS_LEVEL_FLIP
, ttu_attr
->qos_level_flip
);
561 /* TTU - per luma/chroma */
562 /* Assumed surf0 is luma and 1 is chroma */
564 REG_SET_3(DCN_SURF0_TTU_CNTL0
, 0,
565 REFCYC_PER_REQ_DELIVERY
, ttu_attr
->refcyc_per_req_delivery_l
,
566 QoS_LEVEL_FIXED
, ttu_attr
->qos_level_fixed_l
,
567 QoS_RAMP_DISABLE
, ttu_attr
->qos_ramp_disable_l
);
569 REG_SET(DCN_SURF0_TTU_CNTL1
, 0,
570 REFCYC_PER_REQ_DELIVERY_PRE
,
571 ttu_attr
->refcyc_per_req_delivery_pre_l
);
573 REG_SET_3(DCN_SURF1_TTU_CNTL0
, 0,
574 REFCYC_PER_REQ_DELIVERY
, ttu_attr
->refcyc_per_req_delivery_c
,
575 QoS_LEVEL_FIXED
, ttu_attr
->qos_level_fixed_c
,
576 QoS_RAMP_DISABLE
, ttu_attr
->qos_ramp_disable_c
);
578 REG_SET(DCN_SURF1_TTU_CNTL1
, 0,
579 REFCYC_PER_REQ_DELIVERY_PRE
,
580 ttu_attr
->refcyc_per_req_delivery_pre_c
);
583 static void hubp1_setup(
585 struct _vcs_dpi_display_dlg_regs_st
*dlg_attr
,
586 struct _vcs_dpi_display_ttu_regs_st
*ttu_attr
,
587 struct _vcs_dpi_display_rq_regs_st
*rq_regs
,
588 struct _vcs_dpi_display_pipe_dest_params_st
*pipe_dest
)
590 /* otg is locked when this func is called. Register are double buffered.
591 * disable the requestors is not needed
593 hubp1_program_requestor(hubp
, rq_regs
);
594 hubp1_program_deadline(hubp
, dlg_attr
, ttu_attr
);
595 hubp1_vready_workaround(hubp
, pipe_dest
);
598 bool hubp1_is_flip_pending(struct hubp
*hubp
)
600 uint32_t flip_pending
= 0;
601 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
602 struct dc_plane_address earliest_inuse_address
;
604 REG_GET(DCSURF_FLIP_CONTROL
,
605 SURFACE_FLIP_PENDING
, &flip_pending
);
607 REG_GET(DCSURF_SURFACE_EARLIEST_INUSE
,
608 SURFACE_EARLIEST_INUSE_ADDRESS
, &earliest_inuse_address
.grph
.addr
.low_part
);
610 REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH
,
611 SURFACE_EARLIEST_INUSE_ADDRESS_HIGH
, &earliest_inuse_address
.grph
.addr
.high_part
);
616 if (earliest_inuse_address
.grph
.addr
.quad_part
!= hubp
->request_address
.grph
.addr
.quad_part
)
619 hubp
->current_address
= hubp
->request_address
;
623 uint32_t aperture_default_system
= 1;
624 uint32_t context0_default_system
; /* = 0;*/
626 static void hubp1_set_vm_system_aperture_settings(struct hubp
*hubp
,
627 struct vm_system_aperture_param
*apt
)
629 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
630 PHYSICAL_ADDRESS_LOC mc_vm_apt_default
;
631 PHYSICAL_ADDRESS_LOC mc_vm_apt_low
;
632 PHYSICAL_ADDRESS_LOC mc_vm_apt_high
;
634 mc_vm_apt_default
.quad_part
= apt
->sys_default
.quad_part
>> 12;
635 mc_vm_apt_low
.quad_part
= apt
->sys_low
.quad_part
>> 12;
636 mc_vm_apt_high
.quad_part
= apt
->sys_high
.quad_part
>> 12;
638 REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB
, 0,
639 MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM
, aperture_default_system
, /* 1 = system physical memory */
640 MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB
, mc_vm_apt_default
.high_part
);
641 REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB
, 0,
642 MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB
, mc_vm_apt_default
.low_part
);
644 REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB
, 0,
645 MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB
, mc_vm_apt_low
.high_part
);
646 REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
, 0,
647 MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
, mc_vm_apt_low
.low_part
);
649 REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB
, 0,
650 MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB
, mc_vm_apt_high
.high_part
);
651 REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB
, 0,
652 MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB
, mc_vm_apt_high
.low_part
);
655 static void hubp1_set_vm_context0_settings(struct hubp
*hubp
,
656 const struct vm_context0_param
*vm0
)
658 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
660 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB
, 0,
661 VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB
, vm0
->pte_base
.high_part
);
662 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB
, 0,
663 VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB
, vm0
->pte_base
.low_part
);
666 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB
, 0,
667 VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB
, vm0
->pte_start
.high_part
);
668 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB
, 0,
669 VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB
, vm0
->pte_start
.low_part
);
672 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB
, 0,
673 VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB
, vm0
->pte_end
.high_part
);
674 REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB
, 0,
675 VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB
, vm0
->pte_end
.low_part
);
678 REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB
, 0,
679 VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB
, vm0
->fault_default
.high_part
,
680 VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM
, context0_default_system
);
681 REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB
, 0,
682 VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB
, vm0
->fault_default
.low_part
);
684 /* control: enable VM PTE*/
685 REG_SET_2(DCN_VM_MX_L1_TLB_CNTL
, 0,
687 SYSTEM_ACCESS_MODE
, 3);
690 void min_set_viewport(
692 const struct rect
*viewport
,
693 const struct rect
*viewport_c
)
695 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
697 REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION
, 0,
698 PRI_VIEWPORT_WIDTH
, viewport
->width
,
699 PRI_VIEWPORT_HEIGHT
, viewport
->height
);
701 REG_SET_2(DCSURF_PRI_VIEWPORT_START
, 0,
702 PRI_VIEWPORT_X_START
, viewport
->x
,
703 PRI_VIEWPORT_Y_START
, viewport
->y
);
706 REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION
, 0,
707 SEC_VIEWPORT_WIDTH
, viewport
->width
,
708 SEC_VIEWPORT_HEIGHT
, viewport
->height
);
710 REG_SET_2(DCSURF_SEC_VIEWPORT_START
, 0,
711 SEC_VIEWPORT_X_START
, viewport
->x
,
712 SEC_VIEWPORT_Y_START
, viewport
->y
);
714 /* DC supports NV12 only at the moment */
715 REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C
, 0,
716 PRI_VIEWPORT_WIDTH_C
, viewport_c
->width
,
717 PRI_VIEWPORT_HEIGHT_C
, viewport_c
->height
);
719 REG_SET_2(DCSURF_PRI_VIEWPORT_START_C
, 0,
720 PRI_VIEWPORT_X_START_C
, viewport_c
->x
,
721 PRI_VIEWPORT_Y_START_C
, viewport_c
->y
);
724 void hubp1_read_state(struct dcn10_hubp
*hubp1
,
725 struct dcn_hubp_state
*s
)
727 REG_GET(DCSURF_SURFACE_CONFIG
,
728 SURFACE_PIXEL_FORMAT
, &s
->pixel_format
);
730 REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH
,
731 SURFACE_EARLIEST_INUSE_ADDRESS_HIGH
, &s
->inuse_addr_hi
);
733 REG_GET_2(DCSURF_PRI_VIEWPORT_DIMENSION
,
734 PRI_VIEWPORT_WIDTH
, &s
->viewport_width
,
735 PRI_VIEWPORT_HEIGHT
, &s
->viewport_height
);
737 REG_GET_2(DCSURF_SURFACE_CONFIG
,
738 ROTATION_ANGLE
, &s
->rotation_angle
,
739 H_MIRROR_EN
, &s
->h_mirror_en
);
741 REG_GET(DCSURF_TILING_CONFIG
,
742 SW_MODE
, &s
->sw_mode
);
744 REG_GET(DCSURF_SURFACE_CONTROL
,
745 PRIMARY_SURFACE_DCC_EN
, &s
->dcc_en
);
747 REG_GET_3(DCHUBP_CNTL
,
748 HUBP_BLANK_EN
, &s
->blank_en
,
749 HUBP_TTU_DISABLE
, &s
->ttu_disable
,
750 HUBP_UNDERFLOW_STATUS
, &s
->underflow_status
);
752 REG_GET(DCN_GLOBAL_TTU_CNTL
,
753 MIN_TTU_VBLANK
, &s
->min_ttu_vblank
);
755 REG_GET_2(DCN_TTU_QOS_WM
,
756 QoS_LEVEL_LOW_WM
, &s
->qos_level_low_wm
,
757 QoS_LEVEL_HIGH_WM
, &s
->qos_level_high_wm
);
761 CURSOR_PITCH_64_PIXELS
= 0,
762 CURSOR_PITCH_128_PIXELS
,
763 CURSOR_PITCH_256_PIXELS
766 enum cursor_lines_per_chunk
{
767 CURSOR_LINE_PER_CHUNK_2
= 1,
768 CURSOR_LINE_PER_CHUNK_4
,
769 CURSOR_LINE_PER_CHUNK_8
,
770 CURSOR_LINE_PER_CHUNK_16
773 static bool ippn10_cursor_program_control(
774 struct dcn10_hubp
*hubp1
,
775 bool pixel_data_invert
,
776 enum dc_cursor_color_format color_format
)
778 if (REG(CURSOR_SETTINS
))
779 REG_SET_2(CURSOR_SETTINS
, 0,
780 /* no shift of the cursor HDL schedule */
781 CURSOR0_DST_Y_OFFSET
, 0,
782 /* used to shift the cursor chunk request deadline */
783 CURSOR0_CHUNK_HDL_ADJUST
, 3);
785 REG_SET_2(CURSOR_SETTINGS
, 0,
786 /* no shift of the cursor HDL schedule */
787 CURSOR0_DST_Y_OFFSET
, 0,
788 /* used to shift the cursor chunk request deadline */
789 CURSOR0_CHUNK_HDL_ADJUST
, 3);
794 static enum cursor_pitch
ippn10_get_cursor_pitch(
797 enum cursor_pitch hw_pitch
;
801 hw_pitch
= CURSOR_PITCH_64_PIXELS
;
804 hw_pitch
= CURSOR_PITCH_128_PIXELS
;
807 hw_pitch
= CURSOR_PITCH_256_PIXELS
;
810 DC_ERR("Invalid cursor pitch of %d. "
811 "Only 64/128/256 is supported on DCN.\n", pitch
);
812 hw_pitch
= CURSOR_PITCH_64_PIXELS
;
818 static enum cursor_lines_per_chunk
ippn10_get_lines_per_chunk(
819 unsigned int cur_width
,
820 enum dc_cursor_color_format format
)
822 enum cursor_lines_per_chunk line_per_chunk
;
824 if (format
== CURSOR_MODE_MONO
)
825 /* impl B. expansion in CUR Buffer reader */
826 line_per_chunk
= CURSOR_LINE_PER_CHUNK_16
;
827 else if (cur_width
<= 32)
828 line_per_chunk
= CURSOR_LINE_PER_CHUNK_16
;
829 else if (cur_width
<= 64)
830 line_per_chunk
= CURSOR_LINE_PER_CHUNK_8
;
831 else if (cur_width
<= 128)
832 line_per_chunk
= CURSOR_LINE_PER_CHUNK_4
;
834 line_per_chunk
= CURSOR_LINE_PER_CHUNK_2
;
836 return line_per_chunk
;
839 void hubp1_cursor_set_attributes(
841 const struct dc_cursor_attributes
*attr
)
843 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
844 enum cursor_pitch hw_pitch
= ippn10_get_cursor_pitch(attr
->pitch
);
845 enum cursor_lines_per_chunk lpc
= ippn10_get_lines_per_chunk(
846 attr
->width
, attr
->color_format
);
848 hubp
->curs_attr
= *attr
;
850 REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH
,
851 CURSOR_SURFACE_ADDRESS_HIGH
, attr
->address
.high_part
);
852 REG_UPDATE(CURSOR_SURFACE_ADDRESS
,
853 CURSOR_SURFACE_ADDRESS
, attr
->address
.low_part
);
855 REG_UPDATE_2(CURSOR_SIZE
,
856 CURSOR_WIDTH
, attr
->width
,
857 CURSOR_HEIGHT
, attr
->height
);
858 REG_UPDATE_3(CURSOR_CONTROL
,
859 CURSOR_MODE
, attr
->color_format
,
860 CURSOR_PITCH
, hw_pitch
,
861 CURSOR_LINES_PER_CHUNK
, lpc
);
862 ippn10_cursor_program_control(hubp1
,
863 attr
->attribute_flags
.bits
.INVERT_PIXEL_DATA
,
867 void hubp1_cursor_set_position(
869 const struct dc_cursor_position
*pos
,
870 const struct dc_cursor_mi_param
*param
)
872 struct dcn10_hubp
*hubp1
= TO_DCN10_HUBP(hubp
);
873 int src_x_offset
= pos
->x
- pos
->x_hotspot
- param
->viewport_x_start
;
874 uint32_t cur_en
= pos
->enable
? 1 : 0;
875 uint32_t dst_x_offset
= (src_x_offset
>= 0) ? src_x_offset
: 0;
878 * Guard aganst cursor_set_position() from being called with invalid
881 * TODO: Look at combining cursor_set_position() and
882 * cursor_set_attributes() into cursor_update()
884 if (hubp
->curs_attr
.address
.quad_part
== 0)
887 dst_x_offset
*= param
->ref_clk_khz
;
888 dst_x_offset
/= param
->pixel_clk_khz
;
890 ASSERT(param
->h_scale_ratio
.value
);
892 if (param
->h_scale_ratio
.value
)
893 dst_x_offset
= dal_fixed31_32_floor(dal_fixed31_32_div(
894 dal_fixed31_32_from_int(dst_x_offset
),
895 param
->h_scale_ratio
));
897 if (src_x_offset
>= (int)param
->viewport_width
)
898 cur_en
= 0; /* not visible beyond right edge*/
900 if (src_x_offset
+ (int)hubp
->curs_attr
.width
< 0)
901 cur_en
= 0; /* not visible beyond left edge*/
903 if (cur_en
&& REG_READ(CURSOR_SURFACE_ADDRESS
) == 0)
904 hubp1_cursor_set_attributes(hubp
, &hubp
->curs_attr
);
905 REG_UPDATE(CURSOR_CONTROL
,
906 CURSOR_ENABLE
, cur_en
);
908 REG_SET_2(CURSOR_POSITION
, 0,
909 CURSOR_X_POSITION
, pos
->x
,
910 CURSOR_Y_POSITION
, pos
->y
);
912 REG_SET_2(CURSOR_HOT_SPOT
, 0,
913 CURSOR_HOT_SPOT_X
, pos
->x_hotspot
,
914 CURSOR_HOT_SPOT_Y
, pos
->y_hotspot
);
916 REG_SET(CURSOR_DST_OFFSET
, 0,
917 CURSOR_DST_X_OFFSET
, dst_x_offset
);
918 /* TODO Handle surface pixel formats other than 4:4:4 */
921 static struct hubp_funcs dcn10_hubp_funcs
= {
922 .hubp_program_surface_flip_and_addr
=
923 hubp1_program_surface_flip_and_addr
,
924 .hubp_program_surface_config
=
925 hubp1_program_surface_config
,
926 .hubp_is_flip_pending
= hubp1_is_flip_pending
,
927 .hubp_setup
= hubp1_setup
,
928 .hubp_set_vm_system_aperture_settings
= hubp1_set_vm_system_aperture_settings
,
929 .hubp_set_vm_context0_settings
= hubp1_set_vm_context0_settings
,
930 .set_blank
= hubp1_set_blank
,
931 .dcc_control
= hubp1_dcc_control
,
932 .mem_program_viewport
= min_set_viewport
,
933 .set_hubp_blank_en
= hubp1_set_hubp_blank_en
,
934 .set_cursor_attributes
= hubp1_cursor_set_attributes
,
935 .set_cursor_position
= hubp1_cursor_set_position
,
938 /*****************************************/
939 /* Constructor, Destructor */
940 /*****************************************/
942 void dcn10_hubp_construct(
943 struct dcn10_hubp
*hubp1
,
944 struct dc_context
*ctx
,
946 const struct dcn_mi_registers
*hubp_regs
,
947 const struct dcn_mi_shift
*hubp_shift
,
948 const struct dcn_mi_mask
*hubp_mask
)
950 hubp1
->base
.funcs
= &dcn10_hubp_funcs
;
951 hubp1
->base
.ctx
= ctx
;
952 hubp1
->hubp_regs
= hubp_regs
;
953 hubp1
->hubp_shift
= hubp_shift
;
954 hubp1
->hubp_mask
= hubp_mask
;
955 hubp1
->base
.inst
= inst
;
956 hubp1
->base
.opp_id
= 0xf;
957 hubp1
->base
.mpcc_id
= 0xf;