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 <linux/delay.h>
27 #include <linux/slab.h>
29 #include "dm_services.h"
31 #include "dce/dce_11_2_d.h"
32 #include "dce/dce_11_2_sh_mask.h"
33 #include "gmc/gmc_8_1_sh_mask.h"
34 #include "gmc/gmc_8_1_d.h"
36 #include "include/logger_interface.h"
38 #include "dce112_compressor.h"
40 cp110->base.ctx->logger
42 (reg + cp110->offsets.dcp_offset)
43 #define DMIF_REG(reg)\
44 (reg + cp110->offsets.dmif_offset)
46 static const struct dce112_compressor_reg_offsets reg_offsets
[] = {
48 .dcp_offset
= (mmDCP0_GRPH_CONTROL
- mmDCP0_GRPH_CONTROL
),
50 (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
51 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
),
54 .dcp_offset
= (mmDCP1_GRPH_CONTROL
- mmDCP0_GRPH_CONTROL
),
56 (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
57 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
),
60 .dcp_offset
= (mmDCP2_GRPH_CONTROL
- mmDCP0_GRPH_CONTROL
),
62 (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
63 - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
),
67 static const uint32_t dce11_one_lpt_channel_max_resolution
= 2560 * 1600;
70 /* Bit 0 - Display registers updated */
71 FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE
= 0x00000001,
73 /* Bit 2 - FBC_GRPH_COMP_EN register updated */
74 FBC_IDLE_FORCE_GRPH_COMP_EN
= 0x00000002,
75 /* Bit 3 - FBC_SRC_SEL register updated */
76 FBC_IDLE_FORCE_SRC_SEL_CHANGE
= 0x00000004,
77 /* Bit 4 - FBC_MIN_COMPRESSION register updated */
78 FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE
= 0x00000008,
79 /* Bit 5 - FBC_ALPHA_COMP_EN register updated */
80 FBC_IDLE_FORCE_ALPHA_COMP_EN
= 0x00000010,
81 /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */
82 FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN
= 0x00000020,
83 /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */
84 FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF
= 0x00000040,
86 /* Bit 24 - Memory write to region 0 defined by MC registers. */
87 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0
= 0x01000000,
88 /* Bit 25 - Memory write to region 1 defined by MC registers */
89 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1
= 0x02000000,
90 /* Bit 26 - Memory write to region 2 defined by MC registers */
91 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2
= 0x04000000,
92 /* Bit 27 - Memory write to region 3 defined by MC registers. */
93 FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3
= 0x08000000,
95 /* Bit 28 - Memory write from any client other than MCIF */
96 FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF
= 0x10000000,
97 /* Bit 29 - CG statics screen signal is inactive */
98 FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE
= 0x20000000,
101 static uint32_t lpt_size_alignment(struct dce112_compressor
*cp110
)
103 /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
104 return cp110
->base
.raw_size
* cp110
->base
.banks_num
*
105 cp110
->base
.dram_channels_num
;
108 static uint32_t lpt_memory_control_config(struct dce112_compressor
*cp110
,
109 uint32_t lpt_control
)
112 if (cp110
->base
.options
.bits
.LPT_MC_CONFIG
== 1) {
113 /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):
116 * 02 - 4 OR 6 CHANNELS
117 * (Only for discrete GPU, N/A for CZ)
118 * 03 - 8 OR 12 CHANNELS
119 * (Only for discrete GPU, N/A for CZ) */
120 switch (cp110
->base
.dram_channels_num
) {
125 LOW_POWER_TILING_CONTROL
,
126 LOW_POWER_TILING_NUM_PIPES
);
132 LOW_POWER_TILING_CONTROL
,
133 LOW_POWER_TILING_NUM_PIPES
);
137 "%s: Invalid LPT NUM_PIPES!!!",
142 /* The mapping for LPT NUM_BANKS is in
143 * GRPH_CONTROL.GRPH_NUM_BANKS register field
144 * Specifies the number of memory banks for tiling
145 * purposes. Only applies to 2D and 3D tiling modes.
147 * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK
148 * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK
149 * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK
150 * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */
151 switch (cp110
->base
.banks_num
) {
156 LOW_POWER_TILING_CONTROL
,
157 LOW_POWER_TILING_NUM_BANKS
);
163 LOW_POWER_TILING_CONTROL
,
164 LOW_POWER_TILING_NUM_BANKS
);
170 LOW_POWER_TILING_CONTROL
,
171 LOW_POWER_TILING_NUM_BANKS
);
177 LOW_POWER_TILING_CONTROL
,
178 LOW_POWER_TILING_NUM_BANKS
);
182 "%s: Invalid LPT NUM_BANKS!!!",
187 /* The mapping is in DMIF_ADDR_CALC.
188 * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for
189 * Carrizo specifies the memory interleave per pipe.
190 * It effectively specifies the location of pipe bits in
191 * the memory address.
193 * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte
195 * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte
198 switch (cp110
->base
.channel_interleave_size
) {
203 LOW_POWER_TILING_CONTROL
,
204 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE
);
210 LOW_POWER_TILING_CONTROL
,
211 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE
);
215 "%s: Invalid LPT INTERLEAVE_SIZE!!!",
220 /* The mapping for LOW_POWER_TILING_ROW_SIZE is in
221 * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field
222 * for Carrizo. Specifies the size of dram row in bytes.
223 * This should match up with NOOFCOLS field in
224 * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).
225 * This register DMIF_ADDR_CALC is not used by the
226 * hardware as it is only used for addrlib assertions.
228 * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row
230 * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row
232 * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row
234 switch (cp110
->base
.raw_size
) {
239 LOW_POWER_TILING_CONTROL
,
240 LOW_POWER_TILING_ROW_SIZE
);
246 LOW_POWER_TILING_CONTROL
,
247 LOW_POWER_TILING_ROW_SIZE
);
253 LOW_POWER_TILING_CONTROL
,
254 LOW_POWER_TILING_ROW_SIZE
);
258 "%s: Invalid LPT ROW_SIZE!!!",
264 "%s: LPT MC Configuration is not provided",
271 static bool is_source_bigger_than_epanel_size(
272 struct dce112_compressor
*cp110
,
273 uint32_t source_view_width
,
274 uint32_t source_view_height
)
276 if (cp110
->base
.embedded_panel_h_size
!= 0 &&
277 cp110
->base
.embedded_panel_v_size
!= 0 &&
278 ((source_view_width
* source_view_height
) >
279 (cp110
->base
.embedded_panel_h_size
*
280 cp110
->base
.embedded_panel_v_size
)))
286 static uint32_t align_to_chunks_number_per_line(
287 struct dce112_compressor
*cp110
,
290 return 256 * ((pixels
+ 255) / 256);
293 static void wait_for_fbc_state_changed(
294 struct dce112_compressor
*cp110
,
298 uint32_t addr
= mmFBC_STATUS
;
301 while (counter
< 10) {
302 value
= dm_read_reg(cp110
->base
.ctx
, addr
);
303 if (get_reg_field_value(
306 FBC_ENABLE_STATUS
) == enabled
)
314 "%s: wait counter exceeded, changes to HW not applied",
319 void dce112_compressor_power_up_fbc(struct compressor
*compressor
)
325 value
= dm_read_reg(compressor
->ctx
, addr
);
326 set_reg_field_value(value
, 0, FBC_CNTL
, FBC_GRPH_COMP_EN
);
327 set_reg_field_value(value
, 1, FBC_CNTL
, FBC_EN
);
328 set_reg_field_value(value
, 2, FBC_CNTL
, FBC_COHERENCY_MODE
);
329 if (compressor
->options
.bits
.CLK_GATING_DISABLED
== 1) {
330 /* HW needs to do power measurement comparison. */
335 FBC_COMP_CLK_GATE_EN
);
337 dm_write_reg(compressor
->ctx
, addr
, value
);
339 addr
= mmFBC_COMP_MODE
;
340 value
= dm_read_reg(compressor
->ctx
, addr
);
341 set_reg_field_value(value
, 1, FBC_COMP_MODE
, FBC_RLE_EN
);
342 set_reg_field_value(value
, 1, FBC_COMP_MODE
, FBC_DPCM4_RGB_EN
);
343 set_reg_field_value(value
, 1, FBC_COMP_MODE
, FBC_IND_EN
);
344 dm_write_reg(compressor
->ctx
, addr
, value
);
346 addr
= mmFBC_COMP_CNTL
;
347 value
= dm_read_reg(compressor
->ctx
, addr
);
348 set_reg_field_value(value
, 1, FBC_COMP_CNTL
, FBC_DEPTH_RGB08_EN
);
349 dm_write_reg(compressor
->ctx
, addr
, value
);
350 /*FBC_MIN_COMPRESSION 0 ==> 2:1 */
354 set_reg_field_value(value
, 0xF, FBC_COMP_CNTL
, FBC_MIN_COMPRESSION
);
355 dm_write_reg(compressor
->ctx
, addr
, value
);
356 compressor
->min_compress_ratio
= FBC_COMPRESS_RATIO_1TO1
;
359 dm_write_reg(compressor
->ctx
, mmFBC_IND_LUT0
, value
);
362 dm_write_reg(compressor
->ctx
, mmFBC_IND_LUT1
, value
);
365 void dce112_compressor_enable_fbc(
366 struct compressor
*compressor
,
368 struct compr_addr_and_pitch_params
*params
)
370 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
372 if (compressor
->options
.bits
.FBC_SUPPORT
&&
373 (compressor
->options
.bits
.DUMMY_BACKEND
== 0) &&
374 (!dce112_compressor_is_fbc_enabled_in_hw(compressor
, NULL
)) &&
375 (!is_source_bigger_than_epanel_size(
377 params
->source_view_width
,
378 params
->source_view_height
))) {
383 /* Before enabling FBC first need to enable LPT if applicable
384 * LPT state should always be changed (enable/disable) while FBC
386 if (compressor
->options
.bits
.LPT_SUPPORT
&& (paths_num
< 2) &&
387 (params
->source_view_width
*
388 params
->source_view_height
<=
389 dce11_one_lpt_channel_max_resolution
)) {
390 dce112_compressor_enable_lpt(compressor
);
394 value
= dm_read_reg(compressor
->ctx
, addr
);
395 set_reg_field_value(value
, 1, FBC_CNTL
, FBC_GRPH_COMP_EN
);
399 FBC_CNTL
, FBC_SRC_SEL
);
400 dm_write_reg(compressor
->ctx
, addr
, value
);
402 /* Keep track of enum controller_id FBC is attached to */
403 compressor
->is_enabled
= true;
404 compressor
->attached_inst
= params
->inst
;
405 cp110
->offsets
= reg_offsets
[params
->inst
];
407 /*Toggle it as there is bug in HW */
408 set_reg_field_value(value
, 0, FBC_CNTL
, FBC_GRPH_COMP_EN
);
409 dm_write_reg(compressor
->ctx
, addr
, value
);
410 set_reg_field_value(value
, 1, FBC_CNTL
, FBC_GRPH_COMP_EN
);
411 dm_write_reg(compressor
->ctx
, addr
, value
);
413 wait_for_fbc_state_changed(cp110
, true);
417 void dce112_compressor_disable_fbc(struct compressor
*compressor
)
419 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
421 if (compressor
->options
.bits
.FBC_SUPPORT
&&
422 dce112_compressor_is_fbc_enabled_in_hw(compressor
, NULL
)) {
424 /* Turn off compression */
425 reg_data
= dm_read_reg(compressor
->ctx
, mmFBC_CNTL
);
426 set_reg_field_value(reg_data
, 0, FBC_CNTL
, FBC_GRPH_COMP_EN
);
427 dm_write_reg(compressor
->ctx
, mmFBC_CNTL
, reg_data
);
429 /* Reset enum controller_id to undefined */
430 compressor
->attached_inst
= 0;
431 compressor
->is_enabled
= false;
433 /* Whenever disabling FBC make sure LPT is disabled if LPT
435 if (compressor
->options
.bits
.LPT_SUPPORT
)
436 dce112_compressor_disable_lpt(compressor
);
438 wait_for_fbc_state_changed(cp110
, false);
442 bool dce112_compressor_is_fbc_enabled_in_hw(
443 struct compressor
*compressor
,
446 /* Check the hardware register */
449 value
= dm_read_reg(compressor
->ctx
, mmFBC_STATUS
);
450 if (get_reg_field_value(value
, FBC_STATUS
, FBC_ENABLE_STATUS
)) {
452 *inst
= compressor
->attached_inst
;
456 value
= dm_read_reg(compressor
->ctx
, mmFBC_MISC
);
457 if (get_reg_field_value(value
, FBC_MISC
, FBC_STOP_ON_HFLIP_EVENT
)) {
458 value
= dm_read_reg(compressor
->ctx
, mmFBC_CNTL
);
460 if (get_reg_field_value(value
, FBC_CNTL
, FBC_GRPH_COMP_EN
)) {
463 compressor
->attached_inst
;
470 bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor
*compressor
)
472 /* Check the hardware register */
473 uint32_t value
= dm_read_reg(compressor
->ctx
,
474 mmLOW_POWER_TILING_CONTROL
);
476 return get_reg_field_value(
478 LOW_POWER_TILING_CONTROL
,
479 LOW_POWER_TILING_ENABLE
);
482 void dce112_compressor_program_compressed_surface_address_and_pitch(
483 struct compressor
*compressor
,
484 struct compr_addr_and_pitch_params
*params
)
486 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
488 uint32_t fbc_pitch
= 0;
489 uint32_t compressed_surf_address_low_part
=
490 compressor
->compr_surface_address
.addr
.low_part
;
492 /* Clear content first. */
495 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH
),
497 dm_write_reg(compressor
->ctx
,
498 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS
), 0);
500 if (compressor
->options
.bits
.LPT_SUPPORT
) {
501 uint32_t lpt_alignment
= lpt_size_alignment(cp110
);
503 if (lpt_alignment
!= 0) {
504 compressed_surf_address_low_part
=
505 ((compressed_surf_address_low_part
506 + (lpt_alignment
- 1)) / lpt_alignment
)
511 /* Write address, HIGH has to be first. */
512 dm_write_reg(compressor
->ctx
,
513 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH
),
514 compressor
->compr_surface_address
.addr
.high_part
);
515 dm_write_reg(compressor
->ctx
,
516 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS
),
517 compressed_surf_address_low_part
);
519 fbc_pitch
= align_to_chunks_number_per_line(
521 params
->source_view_width
);
523 if (compressor
->min_compress_ratio
== FBC_COMPRESS_RATIO_1TO1
)
524 fbc_pitch
= fbc_pitch
/ 8;
527 "%s: Unexpected DCE11 compression ratio",
530 /* Clear content first. */
531 dm_write_reg(compressor
->ctx
, DCP_REG(mmGRPH_COMPRESS_PITCH
), 0);
533 /* Write FBC Pitch. */
538 GRPH_COMPRESS_PITCH
);
539 dm_write_reg(compressor
->ctx
, DCP_REG(mmGRPH_COMPRESS_PITCH
), value
);
543 void dce112_compressor_disable_lpt(struct compressor
*compressor
)
545 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
550 /* Disable all pipes LPT Stutter */
551 for (inx
= 0; inx
< 3; inx
++) {
555 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
));
559 DPG_PIPE_STUTTER_CONTROL_NONLPTCH
,
560 STUTTER_ENABLE_NONLPTCH
);
563 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
),
566 /* Disable Underlay pipe LPT Stutter */
567 addr
= mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
;
568 value
= dm_read_reg(compressor
->ctx
, addr
);
572 DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
,
573 STUTTER_ENABLE_NONLPTCH
);
574 dm_write_reg(compressor
->ctx
, addr
, value
);
577 addr
= mmLOW_POWER_TILING_CONTROL
;
578 value
= dm_read_reg(compressor
->ctx
, addr
);
582 LOW_POWER_TILING_CONTROL
,
583 LOW_POWER_TILING_ENABLE
);
584 dm_write_reg(compressor
->ctx
, addr
, value
);
586 /* Clear selection of Channel(s) containing Compressed Surface */
587 addr
= mmGMCON_LPT_TARGET
;
588 value
= dm_read_reg(compressor
->ctx
, addr
);
594 dm_write_reg(compressor
->ctx
, mmGMCON_LPT_TARGET
, value
);
597 void dce112_compressor_enable_lpt(struct compressor
*compressor
)
599 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
602 uint32_t value_control
;
605 /* Enable LPT Stutter from Display pipe */
606 value
= dm_read_reg(compressor
->ctx
,
607 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
));
611 DPG_PIPE_STUTTER_CONTROL_NONLPTCH
,
612 STUTTER_ENABLE_NONLPTCH
);
613 dm_write_reg(compressor
->ctx
,
614 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH
), value
);
616 /* Enable Underlay pipe LPT Stutter */
617 addr
= mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
;
618 value
= dm_read_reg(compressor
->ctx
, addr
);
622 DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH
,
623 STUTTER_ENABLE_NONLPTCH
);
624 dm_write_reg(compressor
->ctx
, addr
, value
);
626 /* Selection of Channel(s) containing Compressed Surface: 0xfffffff
628 * STCTRL_LPT_TARGETn corresponds to channel n. */
629 addr
= mmLOW_POWER_TILING_CONTROL
;
630 value_control
= dm_read_reg(compressor
->ctx
, addr
);
631 channels
= get_reg_field_value(value_control
,
632 LOW_POWER_TILING_CONTROL
,
633 LOW_POWER_TILING_MODE
);
635 addr
= mmGMCON_LPT_TARGET
;
636 value
= dm_read_reg(compressor
->ctx
, addr
);
639 channels
+ 1, /* not mentioned in programming guide,
643 dm_write_reg(compressor
->ctx
, addr
, value
);
646 addr
= mmLOW_POWER_TILING_CONTROL
;
647 value
= dm_read_reg(compressor
->ctx
, addr
);
651 LOW_POWER_TILING_CONTROL
,
652 LOW_POWER_TILING_ENABLE
);
653 dm_write_reg(compressor
->ctx
, addr
, value
);
656 void dce112_compressor_program_lpt_control(
657 struct compressor
*compressor
,
658 struct compr_addr_and_pitch_params
*params
)
660 struct dce112_compressor
*cp110
= TO_DCE112_COMPRESSOR(compressor
);
661 uint32_t rows_per_channel
;
662 uint32_t lpt_alignment
;
663 uint32_t source_view_width
;
664 uint32_t source_view_height
;
665 uint32_t lpt_control
= 0;
667 if (!compressor
->options
.bits
.LPT_SUPPORT
)
670 lpt_control
= dm_read_reg(compressor
->ctx
,
671 mmLOW_POWER_TILING_CONTROL
);
673 /* POSSIBLE VALUES for Low Power Tiling Mode:
675 * 01 - Use Channel 0 and 1
676 * 02 - Use Channel 0,1,2,3
678 switch (compressor
->lpt_channels_num
) {
680 * Use Channel 0 & 1 / Not used for DCE 11 */
682 /*Use Channel 0 for LPT for DCE 11 */
686 LOW_POWER_TILING_CONTROL
,
687 LOW_POWER_TILING_MODE
);
691 "%s: Invalid selected DRAM channels for LPT!!!",
696 lpt_control
= lpt_memory_control_config(cp110
, lpt_control
);
698 /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on
699 * FBC compressed surface pitch.
700 * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *
701 * Surface Pitch) / (Row Size * Number of Channels *
702 * Number of Banks)). */
703 rows_per_channel
= 0;
704 lpt_alignment
= lpt_size_alignment(cp110
);
706 align_to_chunks_number_per_line(
708 params
->source_view_width
);
709 source_view_height
= (params
->source_view_height
+ 1) & (~0x1);
711 if (lpt_alignment
!= 0) {
712 rows_per_channel
= source_view_width
* source_view_height
* 4;
714 (rows_per_channel
% lpt_alignment
) ?
715 (rows_per_channel
/ lpt_alignment
+ 1) :
716 rows_per_channel
/ lpt_alignment
;
722 LOW_POWER_TILING_CONTROL
,
723 LOW_POWER_TILING_ROWS_PER_CHAN
);
725 dm_write_reg(compressor
->ctx
,
726 mmLOW_POWER_TILING_CONTROL
, lpt_control
);
730 * DCE 11 Frame Buffer Compression Implementation
733 void dce112_compressor_set_fbc_invalidation_triggers(
734 struct compressor
*compressor
,
735 uint32_t fbc_trigger
)
737 /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
738 * for DCE 11 regions cannot be used - does not work with S/G
740 uint32_t addr
= mmFBC_CLIENT_REGION_MASK
;
741 uint32_t value
= dm_read_reg(compressor
->ctx
, addr
);
746 FBC_CLIENT_REGION_MASK
,
747 FBC_MEMORY_REGION_MASK
);
748 dm_write_reg(compressor
->ctx
, addr
, value
);
750 /* Setup events when to clear all CSM entries (effectively marking
751 * current compressed data invalid)
752 * For DCE 11 CSM metadata 11111 means - "Not Compressed"
753 * Used as the initial value of the metadata sent to the compressor
754 * after invalidation, to indicate that the compressor should attempt
755 * to compress all chunks on the current pass. Also used when the chunk
756 * is not successfully written to memory.
757 * When this CSM value is detected, FBC reads from the uncompressed
758 * buffer. Set events according to passed in value, these events are
760 * - bit 0 - display register updated
761 * - bit 28 - memory write from any client except from MCIF
762 * - bit 29 - CG static screen signal is inactive
763 * In addition, DCE11.1 also needs to set new DCE11.1 specific events
764 * that are used to trigger invalidation on certain register changes,
765 * for example enabling of Alpha Compression may trigger invalidation of
766 * FBC once bit is set. These events are as follows:
767 * - Bit 2 - FBC_GRPH_COMP_EN register updated
768 * - Bit 3 - FBC_SRC_SEL register updated
769 * - Bit 4 - FBC_MIN_COMPRESSION register updated
770 * - Bit 5 - FBC_ALPHA_COMP_EN register updated
771 * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
772 * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
774 addr
= mmFBC_IDLE_FORCE_CLEAR_MASK
;
775 value
= dm_read_reg(compressor
->ctx
, addr
);
779 FBC_IDLE_FORCE_GRPH_COMP_EN
|
780 FBC_IDLE_FORCE_SRC_SEL_CHANGE
|
781 FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE
|
782 FBC_IDLE_FORCE_ALPHA_COMP_EN
|
783 FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN
|
784 FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF
,
785 FBC_IDLE_FORCE_CLEAR_MASK
,
786 FBC_IDLE_FORCE_CLEAR_MASK
);
787 dm_write_reg(compressor
->ctx
, addr
, value
);
790 void dce112_compressor_construct(struct dce112_compressor
*compressor
,
791 struct dc_context
*ctx
)
793 struct dc_bios
*bp
= ctx
->dc_bios
;
794 struct embedded_panel_info panel_info
;
796 compressor
->base
.options
.raw
= 0;
797 compressor
->base
.options
.bits
.FBC_SUPPORT
= true;
798 compressor
->base
.options
.bits
.LPT_SUPPORT
= true;
799 /* For DCE 11 always use one DRAM channel for LPT */
800 compressor
->base
.lpt_channels_num
= 1;
801 compressor
->base
.options
.bits
.DUMMY_BACKEND
= false;
803 /* Check if this system has more than 1 DRAM channel; if only 1 then LPT
804 * should not be supported */
805 if (compressor
->base
.memory_bus_width
== 64)
806 compressor
->base
.options
.bits
.LPT_SUPPORT
= false;
808 compressor
->base
.options
.bits
.CLK_GATING_DISABLED
= false;
810 compressor
->base
.ctx
= ctx
;
811 compressor
->base
.embedded_panel_h_size
= 0;
812 compressor
->base
.embedded_panel_v_size
= 0;
813 compressor
->base
.memory_bus_width
= ctx
->asic_id
.vram_width
;
814 compressor
->base
.allocated_size
= 0;
815 compressor
->base
.preferred_requested_size
= 0;
816 compressor
->base
.min_compress_ratio
= FBC_COMPRESS_RATIO_INVALID
;
817 compressor
->base
.banks_num
= 0;
818 compressor
->base
.raw_size
= 0;
819 compressor
->base
.channel_interleave_size
= 0;
820 compressor
->base
.dram_channels_num
= 0;
821 compressor
->base
.lpt_channels_num
= 0;
822 compressor
->base
.attached_inst
= 0;
823 compressor
->base
.is_enabled
= false;
826 bp
->funcs
->get_embedded_panel_info(bp
, &panel_info
)) {
827 compressor
->base
.embedded_panel_h_size
=
828 panel_info
.lcd_timing
.horizontal_addressable
;
829 compressor
->base
.embedded_panel_v_size
=
830 panel_info
.lcd_timing
.vertical_addressable
;
834 struct compressor
*dce112_compressor_create(struct dc_context
*ctx
)
836 struct dce112_compressor
*cp110
=
837 kzalloc(sizeof(struct dce112_compressor
), GFP_KERNEL
);
842 dce112_compressor_construct(cp110
, ctx
);
846 void dce112_compressor_destroy(struct compressor
**compressor
)
848 kfree(TO_DCE112_COMPRESSOR(*compressor
));