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.
26 #include "dm_services.h"
28 #include "dce/dce_11_2_d.h"
29 #include "dce/dce_11_2_sh_mask.h"
30 #include "gmc/gmc_8_1_sh_mask.h"
31 #include "gmc/gmc_8_1_d.h"
33 #include "include/logger_interface.h"
35 #include "dce112_compressor.h"
38 (reg + cp110->offsets.dcp_offset)
39 #define DMIF_REG(reg)\
40 (reg + cp110->offsets.dmif_offset)
42 static const struct dce112_compressor_reg_offsets reg_offsets
[] = {
44 .dcp_offset
= (mmDCP0_GRPH_CONTROL
- mmDCP0_GRPH_CONTROL
),
46 (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
47 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
),
50 .dcp_offset
= (mmDCP1_GRPH_CONTROL
- mmDCP0_GRPH_CONTROL
),
52 (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
53 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
),
56 .dcp_offset
= (mmDCP2_GRPH_CONTROL
- mmDCP0_GRPH_CONTROL
),
58 (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
59 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
),
63 static const uint32_t dce11_one_lpt_channel_max_resolution
= 2560 * 1600;
66 /* Bit 0 - Display registers updated */
67 FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE
= 0x00000001,
69 /* Bit 2 - FBC_GRPH_COMP_EN register updated */
70 FBC_IDLE_FORCE_GRPH_COMP_EN
= 0x00000002,
71 /* Bit 3 - FBC_SRC_SEL register updated */
72 FBC_IDLE_FORCE_SRC_SEL_CHANGE
= 0x00000004,
73 /* Bit 4 - FBC_MIN_COMPRESSION register updated */
74 FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE
= 0x00000008,
75 /* Bit 5 - FBC_ALPHA_COMP_EN register updated */
76 FBC_IDLE_FORCE_ALPHA_COMP_EN
= 0x00000010,
77 /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */
78 FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN
= 0x00000020,
79 /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */
80 FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF
= 0x00000040,
82 /* Bit 24 - Memory write to region 0 defined by MC registers. */
83 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0
= 0x01000000,
84 /* Bit 25 - Memory write to region 1 defined by MC registers */
85 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1
= 0x02000000,
86 /* Bit 26 - Memory write to region 2 defined by MC registers */
87 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2
= 0x04000000,
88 /* Bit 27 - Memory write to region 3 defined by MC registers. */
89 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3
= 0x08000000,
91 /* Bit 28 - Memory write from any client other than MCIF */
92 FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF
= 0x10000000,
93 /* Bit 29 - CG statics screen signal is inactive */
94 FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE
= 0x20000000,
97 static uint32_t lpt_size_alignment(struct dce112_compressor
*cp110
)
99 /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
100 return cp110
->base
.raw_size
* cp110
->base
.banks_num
*
101 cp110
->base
.dram_channels_num
;
104 static uint32_t lpt_memory_control_config(struct dce112_compressor
*cp110
,
105 uint32_t lpt_control
)
108 if (cp110
->base
.options
.bits
.LPT_MC_CONFIG
== 1) {
109 /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):
112 * 02 - 4 OR 6 CHANNELS
113 * (Only for discrete GPU, N/A for CZ)
114 * 03 - 8 OR 12 CHANNELS
115 * (Only for discrete GPU, N/A for CZ) */
116 switch (cp110
->base
.dram_channels_num
) {
121 LOW_POWER_TILING_CONTROL
,
122 LOW_POWER_TILING_NUM_PIPES
);
128 LOW_POWER_TILING_CONTROL
,
129 LOW_POWER_TILING_NUM_PIPES
);
133 cp110
->base
.ctx
->logger
, LOG_WARNING
,
134 "%s: Invalid LPT NUM_PIPES!!!",
139 /* The mapping for LPT NUM_BANKS is in
140 * GRPH_CONTROL.GRPH_NUM_BANKS register field
141 * Specifies the number of memory banks for tiling
142 * purposes. Only applies to 2D and 3D tiling modes.
144 * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK
145 * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK
146 * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK
147 * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */
148 switch (cp110
->base
.banks_num
) {
153 LOW_POWER_TILING_CONTROL
,
154 LOW_POWER_TILING_NUM_BANKS
);
160 LOW_POWER_TILING_CONTROL
,
161 LOW_POWER_TILING_NUM_BANKS
);
167 LOW_POWER_TILING_CONTROL
,
168 LOW_POWER_TILING_NUM_BANKS
);
174 LOW_POWER_TILING_CONTROL
,
175 LOW_POWER_TILING_NUM_BANKS
);
179 cp110
->base
.ctx
->logger
, LOG_WARNING
,
180 "%s: Invalid LPT NUM_BANKS!!!",
185 /* The mapping is in DMIF_ADDR_CALC.
186 * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for
187 * Carrizo specifies the memory interleave per pipe.
188 * It effectively specifies the location of pipe bits in
189 * the memory address.
191 * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte
193 * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte
196 switch (cp110
->base
.channel_interleave_size
) {
201 LOW_POWER_TILING_CONTROL
,
202 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE
);
208 LOW_POWER_TILING_CONTROL
,
209 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE
);
213 cp110
->base
.ctx
->logger
, LOG_WARNING
,
214 "%s: Invalid LPT INTERLEAVE_SIZE!!!",
219 /* The mapping for LOW_POWER_TILING_ROW_SIZE is in
220 * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field
221 * for Carrizo. Specifies the size of dram row in bytes.
222 * This should match up with NOOFCOLS field in
223 * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).
224 * This register DMIF_ADDR_CALC is not used by the
225 * hardware as it is only used for addrlib assertions.
227 * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row
229 * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row
231 * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row
233 switch (cp110
->base
.raw_size
) {
238 LOW_POWER_TILING_CONTROL
,
239 LOW_POWER_TILING_ROW_SIZE
);
245 LOW_POWER_TILING_CONTROL
,
246 LOW_POWER_TILING_ROW_SIZE
);
252 LOW_POWER_TILING_CONTROL
,
253 LOW_POWER_TILING_ROW_SIZE
);
257 cp110
->base
.ctx
->logger
, LOG_WARNING
,
258 "%s: Invalid LPT ROW_SIZE!!!",
264 cp110
->base
.ctx
->logger
, LOG_WARNING
,
265 "%s: LPT MC Configuration is not provided",
272 static bool is_source_bigger_than_epanel_size(
273 struct dce112_compressor
*cp110
,
274 uint32_t source_view_width
,
275 uint32_t source_view_height
)
277 if (cp110
->base
.embedded_panel_h_size
!= 0 &&
278 cp110
->base
.embedded_panel_v_size
!= 0 &&
279 ((source_view_width
* source_view_height
) >
280 (cp110
->base
.embedded_panel_h_size
*
281 cp110
->base
.embedded_panel_v_size
)))
287 static uint32_t align_to_chunks_number_per_line(
288 struct dce112_compressor
*cp110
,
291 return 256 * ((pixels
+ 255) / 256);
294 static void wait_for_fbc_state_changed(
295 struct dce112_compressor
*cp110
,
299 uint32_t addr
= mmFBC_STATUS
;
302 while (counter
< 10) {
303 value
= dm_read_reg(cp110
->base
.ctx
, addr
);
304 if (get_reg_field_value(
307 FBC_ENABLE_STATUS
) == enabled
)
315 cp110
->base
.ctx
->logger
, LOG_WARNING
,
316 "%s: wait counter exceeded, changes to HW not applied",
321 void dce112_compressor_power_up_fbc(struct compressor
*compressor
)
327 value
= dm_read_reg(compressor
->ctx
, addr
);
328 set_reg_field_value(value
, 0, FBC_CNTL
, FBC_GRPH_COMP_EN
);
329 set_reg_field_value(value
, 1, FBC_CNTL
, FBC_EN
);
330 set_reg_field_value(value
, 2, FBC_CNTL
, FBC_COHERENCY_MODE
);
331 if (compressor
->options
.bits
.CLK_GATING_DISABLED
== 1) {
332 /* HW needs to do power measurement comparison. */
337 FBC_COMP_CLK_GATE_EN
);
339 dm_write_reg(compressor
->ctx
, addr
, value
);
341 addr
= mmFBC_COMP_MODE
;
342 value
= dm_read_reg(compressor
->ctx
, addr
);
343 set_reg_field_value(value
, 1, FBC_COMP_MODE
, FBC_RLE_EN
);
344 set_reg_field_value(value
, 1, FBC_COMP_MODE
, FBC_DPCM4_RGB_EN
);
345 set_reg_field_value(value
, 1, FBC_COMP_MODE
, FBC_IND_EN
);
346 dm_write_reg(compressor
->ctx
, addr
, value
);
348 addr
= mmFBC_COMP_CNTL
;
349 value
= dm_read_reg(compressor
->ctx
, addr
);
350 set_reg_field_value(value
, 1, FBC_COMP_CNTL
, FBC_DEPTH_RGB08_EN
);
351 dm_write_reg(compressor
->ctx
, addr
, value
);
352 /*FBC_MIN_COMPRESSION 0 ==> 2:1 */
356 set_reg_field_value(value
, 0xF, FBC_COMP_CNTL
, FBC_MIN_COMPRESSION
);
357 dm_write_reg(compressor
->ctx
, addr
, value
);
358 compressor
->min_compress_ratio
= FBC_COMPRESS_RATIO_1TO1
;
361 dm_write_reg(compressor
->ctx
, mmFBC_IND_LUT0
, value
);
364 dm_write_reg(compressor
->ctx
, mmFBC_IND_LUT1
, value
);
367 void dce112_compressor_enable_fbc(
368 struct compressor
*compressor
,
370 struct compr_addr_and_pitch_params
*params
)
372 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
374 if (compressor
->options
.bits
.FBC_SUPPORT
&&
375 (compressor
->options
.bits
.DUMMY_BACKEND
== 0) &&
376 (!dce112_compressor_is_fbc_enabled_in_hw(compressor
, NULL
)) &&
377 (!is_source_bigger_than_epanel_size(
379 params
->source_view_width
,
380 params
->source_view_height
))) {
385 /* Before enabling FBC first need to enable LPT if applicable
386 * LPT state should always be changed (enable/disable) while FBC
388 if (compressor
->options
.bits
.LPT_SUPPORT
&& (paths_num
< 2) &&
389 (params
->source_view_width
*
390 params
->source_view_height
<=
391 dce11_one_lpt_channel_max_resolution
)) {
392 dce112_compressor_enable_lpt(compressor
);
396 value
= dm_read_reg(compressor
->ctx
, addr
);
397 set_reg_field_value(value
, 1, FBC_CNTL
, FBC_GRPH_COMP_EN
);
401 FBC_CNTL
, FBC_SRC_SEL
);
402 dm_write_reg(compressor
->ctx
, addr
, value
);
404 /* Keep track of enum controller_id FBC is attached to */
405 compressor
->is_enabled
= true;
406 compressor
->attached_inst
= params
->inst
;
407 cp110
->offsets
= reg_offsets
[params
->inst
- 1];
409 /*Toggle it as there is bug in HW */
410 set_reg_field_value(value
, 0, FBC_CNTL
, FBC_GRPH_COMP_EN
);
411 dm_write_reg(compressor
->ctx
, addr
, value
);
412 set_reg_field_value(value
, 1, FBC_CNTL
, FBC_GRPH_COMP_EN
);
413 dm_write_reg(compressor
->ctx
, addr
, value
);
415 wait_for_fbc_state_changed(cp110
, true);
419 void dce112_compressor_disable_fbc(struct compressor
*compressor
)
421 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
423 if (compressor
->options
.bits
.FBC_SUPPORT
&&
424 dce112_compressor_is_fbc_enabled_in_hw(compressor
, NULL
)) {
426 /* Turn off compression */
427 reg_data
= dm_read_reg(compressor
->ctx
, mmFBC_CNTL
);
428 set_reg_field_value(reg_data
, 0, FBC_CNTL
, FBC_GRPH_COMP_EN
);
429 dm_write_reg(compressor
->ctx
, mmFBC_CNTL
, reg_data
);
431 /* Reset enum controller_id to undefined */
432 compressor
->attached_inst
= 0;
433 compressor
->is_enabled
= false;
435 /* Whenever disabling FBC make sure LPT is disabled if LPT
437 if (compressor
->options
.bits
.LPT_SUPPORT
)
438 dce112_compressor_disable_lpt(compressor
);
440 wait_for_fbc_state_changed(cp110
, false);
444 bool dce112_compressor_is_fbc_enabled_in_hw(
445 struct compressor
*compressor
,
448 /* Check the hardware register */
451 value
= dm_read_reg(compressor
->ctx
, mmFBC_STATUS
);
452 if (get_reg_field_value(value
, FBC_STATUS
, FBC_ENABLE_STATUS
)) {
454 *inst
= compressor
->attached_inst
;
458 value
= dm_read_reg(compressor
->ctx
, mmFBC_MISC
);
459 if (get_reg_field_value(value
, FBC_MISC
, FBC_STOP_ON_HFLIP_EVENT
)) {
460 value
= dm_read_reg(compressor
->ctx
, mmFBC_CNTL
);
462 if (get_reg_field_value(value
, FBC_CNTL
, FBC_GRPH_COMP_EN
)) {
465 compressor
->attached_inst
;
472 bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor
*compressor
)
474 /* Check the hardware register */
475 uint32_t value
= dm_read_reg(compressor
->ctx
,
476 mmLOW_POWER_TILING_CONTROL
);
478 return get_reg_field_value(
480 LOW_POWER_TILING_CONTROL
,
481 LOW_POWER_TILING_ENABLE
);
484 void dce112_compressor_program_compressed_surface_address_and_pitch(
485 struct compressor
*compressor
,
486 struct compr_addr_and_pitch_params
*params
)
488 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
490 uint32_t fbc_pitch
= 0;
491 uint32_t compressed_surf_address_low_part
=
492 compressor
->compr_surface_address
.addr
.low_part
;
494 /* Clear content first. */
497 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH
),
499 dm_write_reg(compressor
->ctx
,
500 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS
), 0);
502 if (compressor
->options
.bits
.LPT_SUPPORT
) {
503 uint32_t lpt_alignment
= lpt_size_alignment(cp110
);
505 if (lpt_alignment
!= 0) {
506 compressed_surf_address_low_part
=
507 ((compressed_surf_address_low_part
508 + (lpt_alignment
- 1)) / lpt_alignment
)
513 /* Write address, HIGH has to be first. */
514 dm_write_reg(compressor
->ctx
,
515 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH
),
516 compressor
->compr_surface_address
.addr
.high_part
);
517 dm_write_reg(compressor
->ctx
,
518 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS
),
519 compressed_surf_address_low_part
);
521 fbc_pitch
= align_to_chunks_number_per_line(
523 params
->source_view_width
);
525 if (compressor
->min_compress_ratio
== FBC_COMPRESS_RATIO_1TO1
)
526 fbc_pitch
= fbc_pitch
/ 8;
529 compressor
->ctx
->logger
, LOG_WARNING
,
530 "%s: Unexpected DCE11 compression ratio",
533 /* Clear content first. */
534 dm_write_reg(compressor
->ctx
, DCP_REG(mmGRPH_COMPRESS_PITCH
), 0);
536 /* Write FBC Pitch. */
541 GRPH_COMPRESS_PITCH
);
542 dm_write_reg(compressor
->ctx
, DCP_REG(mmGRPH_COMPRESS_PITCH
), value
);
546 void dce112_compressor_disable_lpt(struct compressor
*compressor
)
548 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
553 /* Disable all pipes LPT Stutter */
554 for (inx
= 0; inx
< 3; inx
++) {
558 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
));
562 DPG_PIPE_STUTTER_CONTROL_NONLPTCH
,
563 STUTTER_ENABLE_NONLPTCH
);
566 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
),
569 /* Disable Underlay pipe LPT Stutter */
570 addr
= mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
;
571 value
= dm_read_reg(compressor
->ctx
, addr
);
575 DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
,
576 STUTTER_ENABLE_NONLPTCH
);
577 dm_write_reg(compressor
->ctx
, addr
, value
);
580 addr
= mmLOW_POWER_TILING_CONTROL
;
581 value
= dm_read_reg(compressor
->ctx
, addr
);
585 LOW_POWER_TILING_CONTROL
,
586 LOW_POWER_TILING_ENABLE
);
587 dm_write_reg(compressor
->ctx
, addr
, value
);
589 /* Clear selection of Channel(s) containing Compressed Surface */
590 addr
= mmGMCON_LPT_TARGET
;
591 value
= dm_read_reg(compressor
->ctx
, addr
);
597 dm_write_reg(compressor
->ctx
, mmGMCON_LPT_TARGET
, value
);
600 void dce112_compressor_enable_lpt(struct compressor
*compressor
)
602 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
605 uint32_t value_control
;
608 /* Enable LPT Stutter from Display pipe */
609 value
= dm_read_reg(compressor
->ctx
,
610 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
));
614 DPG_PIPE_STUTTER_CONTROL_NONLPTCH
,
615 STUTTER_ENABLE_NONLPTCH
);
616 dm_write_reg(compressor
->ctx
,
617 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
), value
);
619 /* Enable Underlay pipe LPT Stutter */
620 addr
= mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
;
621 value
= dm_read_reg(compressor
->ctx
, addr
);
625 DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
,
626 STUTTER_ENABLE_NONLPTCH
);
627 dm_write_reg(compressor
->ctx
, addr
, value
);
629 /* Selection of Channel(s) containing Compressed Surface: 0xfffffff
631 * STCTRL_LPT_TARGETn corresponds to channel n. */
632 addr
= mmLOW_POWER_TILING_CONTROL
;
633 value_control
= dm_read_reg(compressor
->ctx
, addr
);
634 channels
= get_reg_field_value(value_control
,
635 LOW_POWER_TILING_CONTROL
,
636 LOW_POWER_TILING_MODE
);
638 addr
= mmGMCON_LPT_TARGET
;
639 value
= dm_read_reg(compressor
->ctx
, addr
);
642 channels
+ 1, /* not mentioned in programming guide,
646 dm_write_reg(compressor
->ctx
, addr
, value
);
649 addr
= mmLOW_POWER_TILING_CONTROL
;
650 value
= dm_read_reg(compressor
->ctx
, addr
);
654 LOW_POWER_TILING_CONTROL
,
655 LOW_POWER_TILING_ENABLE
);
656 dm_write_reg(compressor
->ctx
, addr
, value
);
659 void dce112_compressor_program_lpt_control(
660 struct compressor
*compressor
,
661 struct compr_addr_and_pitch_params
*params
)
663 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
664 uint32_t rows_per_channel
;
665 uint32_t lpt_alignment
;
666 uint32_t source_view_width
;
667 uint32_t source_view_height
;
668 uint32_t lpt_control
= 0;
670 if (!compressor
->options
.bits
.LPT_SUPPORT
)
673 lpt_control
= dm_read_reg(compressor
->ctx
,
674 mmLOW_POWER_TILING_CONTROL
);
676 /* POSSIBLE VALUES for Low Power Tiling Mode:
678 * 01 - Use Channel 0 and 1
679 * 02 - Use Channel 0,1,2,3
681 switch (compressor
->lpt_channels_num
) {
683 * Use Channel 0 & 1 / Not used for DCE 11 */
685 /*Use Channel 0 for LPT for DCE 11 */
689 LOW_POWER_TILING_CONTROL
,
690 LOW_POWER_TILING_MODE
);
694 compressor
->ctx
->logger
, LOG_WARNING
,
695 "%s: Invalid selected DRAM channels for LPT!!!",
700 lpt_control
= lpt_memory_control_config(cp110
, lpt_control
);
702 /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on
703 * FBC compressed surface pitch.
704 * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *
705 * Surface Pitch) / (Row Size * Number of Channels *
706 * Number of Banks)). */
707 rows_per_channel
= 0;
708 lpt_alignment
= lpt_size_alignment(cp110
);
710 align_to_chunks_number_per_line(
712 params
->source_view_width
);
713 source_view_height
= (params
->source_view_height
+ 1) & (~0x1);
715 if (lpt_alignment
!= 0) {
716 rows_per_channel
= source_view_width
* source_view_height
* 4;
718 (rows_per_channel
% lpt_alignment
) ?
719 (rows_per_channel
/ lpt_alignment
+ 1) :
720 rows_per_channel
/ lpt_alignment
;
726 LOW_POWER_TILING_CONTROL
,
727 LOW_POWER_TILING_ROWS_PER_CHAN
);
729 dm_write_reg(compressor
->ctx
,
730 mmLOW_POWER_TILING_CONTROL
, lpt_control
);
734 * DCE 11 Frame Buffer Compression Implementation
737 void dce112_compressor_set_fbc_invalidation_triggers(
738 struct compressor
*compressor
,
739 uint32_t fbc_trigger
)
741 /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
742 * for DCE 11 regions cannot be used - does not work with S/G
744 uint32_t addr
= mmFBC_CLIENT_REGION_MASK
;
745 uint32_t value
= dm_read_reg(compressor
->ctx
, addr
);
750 FBC_CLIENT_REGION_MASK
,
751 FBC_MEMORY_REGION_MASK
);
752 dm_write_reg(compressor
->ctx
, addr
, value
);
754 /* Setup events when to clear all CSM entries (effectively marking
755 * current compressed data invalid)
756 * For DCE 11 CSM metadata 11111 means - "Not Compressed"
757 * Used as the initial value of the metadata sent to the compressor
758 * after invalidation, to indicate that the compressor should attempt
759 * to compress all chunks on the current pass. Also used when the chunk
760 * is not successfully written to memory.
761 * When this CSM value is detected, FBC reads from the uncompressed
762 * buffer. Set events according to passed in value, these events are
764 * - bit 0 - display register updated
765 * - bit 28 - memory write from any client except from MCIF
766 * - bit 29 - CG static screen signal is inactive
767 * In addition, DCE11.1 also needs to set new DCE11.1 specific events
768 * that are used to trigger invalidation on certain register changes,
769 * for example enabling of Alpha Compression may trigger invalidation of
770 * FBC once bit is set. These events are as follows:
771 * - Bit 2 - FBC_GRPH_COMP_EN register updated
772 * - Bit 3 - FBC_SRC_SEL register updated
773 * - Bit 4 - FBC_MIN_COMPRESSION register updated
774 * - Bit 5 - FBC_ALPHA_COMP_EN register updated
775 * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
776 * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
778 addr
= mmFBC_IDLE_FORCE_CLEAR_MASK
;
779 value
= dm_read_reg(compressor
->ctx
, addr
);
783 FBC_IDLE_FORCE_GRPH_COMP_EN
|
784 FBC_IDLE_FORCE_SRC_SEL_CHANGE
|
785 FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE
|
786 FBC_IDLE_FORCE_ALPHA_COMP_EN
|
787 FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN
|
788 FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF
,
789 FBC_IDLE_FORCE_CLEAR_MASK
,
790 FBC_IDLE_FORCE_CLEAR_MASK
);
791 dm_write_reg(compressor
->ctx
, addr
, value
);
794 bool dce112_compressor_construct(struct dce112_compressor
*compressor
,
795 struct dc_context
*ctx
)
797 struct dc_bios
*bp
= ctx
->dc_bios
;
798 struct embedded_panel_info panel_info
;
800 compressor
->base
.options
.bits
.FBC_SUPPORT
= true;
801 compressor
->base
.options
.bits
.LPT_SUPPORT
= true;
802 /* For DCE 11 always use one DRAM channel for LPT */
803 compressor
->base
.lpt_channels_num
= 1;
804 compressor
->base
.options
.bits
.DUMMY_BACKEND
= false;
806 /* Check if this system has more than 1 DRAM channel; if only 1 then LPT
807 * should not be supported */
808 if (compressor
->base
.memory_bus_width
== 64)
809 compressor
->base
.options
.bits
.LPT_SUPPORT
= false;
811 compressor
->base
.options
.bits
.CLK_GATING_DISABLED
= false;
813 compressor
->base
.ctx
= ctx
;
814 compressor
->base
.embedded_panel_h_size
= 0;
815 compressor
->base
.embedded_panel_v_size
= 0;
816 compressor
->base
.memory_bus_width
= ctx
->asic_id
.vram_width
;
817 compressor
->base
.allocated_size
= 0;
818 compressor
->base
.preferred_requested_size
= 0;
819 compressor
->base
.min_compress_ratio
= FBC_COMPRESS_RATIO_INVALID
;
820 compressor
->base
.options
.raw
= 0;
821 compressor
->base
.banks_num
= 0;
822 compressor
->base
.raw_size
= 0;
823 compressor
->base
.channel_interleave_size
= 0;
824 compressor
->base
.dram_channels_num
= 0;
825 compressor
->base
.lpt_channels_num
= 0;
826 compressor
->base
.attached_inst
= 0;
827 compressor
->base
.is_enabled
= false;
830 bp
->funcs
->get_embedded_panel_info(bp
, &panel_info
)) {
831 compressor
->base
.embedded_panel_h_size
=
832 panel_info
.lcd_timing
.horizontal_addressable
;
833 compressor
->base
.embedded_panel_v_size
=
834 panel_info
.lcd_timing
.vertical_addressable
;
839 struct compressor
*dce112_compressor_create(struct dc_context
*ctx
)
841 struct dce112_compressor
*cp110
=
842 dm_alloc(sizeof(struct dce112_compressor
));
847 if (dce112_compressor_construct(cp110
, ctx
))
855 void dce112_compressor_destroy(struct compressor
**compressor
)
857 dm_free(TO_DCE112_COMPRESSOR(*compressor
));