Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dm_services.h"
0027 
0028 #include "dce/dce_11_2_d.h"
0029 #include "dce/dce_11_2_sh_mask.h"
0030 #include "gmc/gmc_8_1_sh_mask.h"
0031 #include "gmc/gmc_8_1_d.h"
0032 
0033 #include "include/logger_interface.h"
0034 
0035 #include "dce112_compressor.h"
0036 #define DC_LOGGER \
0037         cp110->base.ctx->logger
0038 #define DCP_REG(reg)\
0039     (reg + cp110->offsets.dcp_offset)
0040 #define DMIF_REG(reg)\
0041     (reg + cp110->offsets.dmif_offset)
0042 
0043 static const struct dce112_compressor_reg_offsets reg_offsets[] = {
0044 {
0045     .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
0046     .dmif_offset =
0047         (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
0048             - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
0049 },
0050 {
0051     .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
0052     .dmif_offset =
0053         (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
0054             - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
0055 },
0056 {
0057     .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
0058     .dmif_offset =
0059         (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
0060             - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
0061 }
0062 };
0063 
0064 static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;
0065 
0066 enum fbc_idle_force {
0067     /* Bit 0 - Display registers updated */
0068     FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001,
0069 
0070     /* Bit 2 - FBC_GRPH_COMP_EN register updated */
0071     FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002,
0072     /* Bit 3 - FBC_SRC_SEL register updated */
0073     FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004,
0074     /* Bit 4 - FBC_MIN_COMPRESSION register updated */
0075     FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008,
0076     /* Bit 5 - FBC_ALPHA_COMP_EN register updated */
0077     FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010,
0078     /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */
0079     FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020,
0080     /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */
0081     FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040,
0082 
0083     /* Bit 24 - Memory write to region 0 defined by MC registers. */
0084     FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000,
0085     /* Bit 25 - Memory write to region 1 defined by MC registers */
0086     FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000,
0087     /* Bit 26 - Memory write to region 2 defined by MC registers */
0088     FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000,
0089     /* Bit 27 - Memory write to region 3 defined by MC registers. */
0090     FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000,
0091 
0092     /* Bit 28 - Memory write from any client other than MCIF */
0093     FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000,
0094     /* Bit 29 - CG statics screen signal is inactive */
0095     FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000,
0096 };
0097 
0098 static uint32_t lpt_size_alignment(struct dce112_compressor *cp110)
0099 {
0100     /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
0101     return cp110->base.raw_size * cp110->base.banks_num *
0102         cp110->base.dram_channels_num;
0103 }
0104 
0105 static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,
0106     uint32_t lpt_control)
0107 {
0108     /*LPT MC Config */
0109     if (cp110->base.options.bits.LPT_MC_CONFIG == 1) {
0110         /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):
0111          * 00 - 1 CHANNEL
0112          * 01 - 2 CHANNELS
0113          * 02 - 4 OR 6 CHANNELS
0114          * (Only for discrete GPU, N/A for CZ)
0115          * 03 - 8 OR 12 CHANNELS
0116          * (Only for discrete GPU, N/A for CZ) */
0117         switch (cp110->base.dram_channels_num) {
0118         case 2:
0119             set_reg_field_value(
0120                 lpt_control,
0121                 1,
0122                 LOW_POWER_TILING_CONTROL,
0123                 LOW_POWER_TILING_NUM_PIPES);
0124             break;
0125         case 1:
0126             set_reg_field_value(
0127                 lpt_control,
0128                 0,
0129                 LOW_POWER_TILING_CONTROL,
0130                 LOW_POWER_TILING_NUM_PIPES);
0131             break;
0132         default:
0133             DC_LOG_WARNING(
0134                 "%s: Invalid LPT NUM_PIPES!!!",
0135                 __func__);
0136             break;
0137         }
0138 
0139         /* The mapping for LPT NUM_BANKS is in
0140          * GRPH_CONTROL.GRPH_NUM_BANKS register field
0141          * Specifies the number of memory banks for tiling
0142          * purposes. Only applies to 2D and 3D tiling modes.
0143          * POSSIBLE VALUES:
0144          * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK
0145          * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK
0146          * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK
0147          * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */
0148         switch (cp110->base.banks_num) {
0149         case 16:
0150             set_reg_field_value(
0151                 lpt_control,
0152                 3,
0153                 LOW_POWER_TILING_CONTROL,
0154                 LOW_POWER_TILING_NUM_BANKS);
0155             break;
0156         case 8:
0157             set_reg_field_value(
0158                 lpt_control,
0159                 2,
0160                 LOW_POWER_TILING_CONTROL,
0161                 LOW_POWER_TILING_NUM_BANKS);
0162             break;
0163         case 4:
0164             set_reg_field_value(
0165                 lpt_control,
0166                 1,
0167                 LOW_POWER_TILING_CONTROL,
0168                 LOW_POWER_TILING_NUM_BANKS);
0169             break;
0170         case 2:
0171             set_reg_field_value(
0172                 lpt_control,
0173                 0,
0174                 LOW_POWER_TILING_CONTROL,
0175                 LOW_POWER_TILING_NUM_BANKS);
0176             break;
0177         default:
0178             DC_LOG_WARNING(
0179                 "%s: Invalid LPT NUM_BANKS!!!",
0180                 __func__);
0181             break;
0182         }
0183 
0184         /* The mapping is in DMIF_ADDR_CALC.
0185          * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for
0186          * Carrizo specifies the memory interleave per pipe.
0187          * It effectively specifies the location of pipe bits in
0188          * the memory address.
0189          * POSSIBLE VALUES:
0190          * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte
0191          * interleave
0192          * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte
0193          * interleave
0194          */
0195         switch (cp110->base.channel_interleave_size) {
0196         case 256: /*256B */
0197             set_reg_field_value(
0198                 lpt_control,
0199                 0,
0200                 LOW_POWER_TILING_CONTROL,
0201                 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
0202             break;
0203         case 512: /*512B */
0204             set_reg_field_value(
0205                 lpt_control,
0206                 1,
0207                 LOW_POWER_TILING_CONTROL,
0208                 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
0209             break;
0210         default:
0211             DC_LOG_WARNING(
0212                 "%s: Invalid LPT INTERLEAVE_SIZE!!!",
0213                 __func__);
0214             break;
0215         }
0216 
0217         /* The mapping for LOW_POWER_TILING_ROW_SIZE is in
0218          * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field
0219          * for Carrizo. Specifies the size of dram row in bytes.
0220          * This should match up with NOOFCOLS field in
0221          * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).
0222          * This register DMIF_ADDR_CALC is not used by the
0223          * hardware as it is only used for addrlib assertions.
0224          * POSSIBLE VALUES:
0225          * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row
0226          * boundary
0227          * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row
0228          * boundary
0229          * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row
0230          * boundary */
0231         switch (cp110->base.raw_size) {
0232         case 4096: /*4 KB */
0233             set_reg_field_value(
0234                 lpt_control,
0235                 2,
0236                 LOW_POWER_TILING_CONTROL,
0237                 LOW_POWER_TILING_ROW_SIZE);
0238             break;
0239         case 2048:
0240             set_reg_field_value(
0241                 lpt_control,
0242                 1,
0243                 LOW_POWER_TILING_CONTROL,
0244                 LOW_POWER_TILING_ROW_SIZE);
0245             break;
0246         case 1024:
0247             set_reg_field_value(
0248                 lpt_control,
0249                 0,
0250                 LOW_POWER_TILING_CONTROL,
0251                 LOW_POWER_TILING_ROW_SIZE);
0252             break;
0253         default:
0254             DC_LOG_WARNING(
0255                 "%s: Invalid LPT ROW_SIZE!!!",
0256                 __func__);
0257             break;
0258         }
0259     } else {
0260         DC_LOG_WARNING(
0261             "%s: LPT MC Configuration is not provided",
0262             __func__);
0263     }
0264 
0265     return lpt_control;
0266 }
0267 
0268 static bool is_source_bigger_than_epanel_size(
0269     struct dce112_compressor *cp110,
0270     uint32_t source_view_width,
0271     uint32_t source_view_height)
0272 {
0273     if (cp110->base.embedded_panel_h_size != 0 &&
0274         cp110->base.embedded_panel_v_size != 0 &&
0275         ((source_view_width * source_view_height) >
0276         (cp110->base.embedded_panel_h_size *
0277             cp110->base.embedded_panel_v_size)))
0278         return true;
0279 
0280     return false;
0281 }
0282 
0283 static uint32_t align_to_chunks_number_per_line(
0284     struct dce112_compressor *cp110,
0285     uint32_t pixels)
0286 {
0287     return 256 * ((pixels + 255) / 256);
0288 }
0289 
0290 static void wait_for_fbc_state_changed(
0291     struct dce112_compressor *cp110,
0292     bool enabled)
0293 {
0294     uint8_t counter = 0;
0295     uint32_t addr = mmFBC_STATUS;
0296     uint32_t value;
0297 
0298     while (counter < 10) {
0299         value = dm_read_reg(cp110->base.ctx, addr);
0300         if (get_reg_field_value(
0301             value,
0302             FBC_STATUS,
0303             FBC_ENABLE_STATUS) == enabled)
0304             break;
0305         udelay(10);
0306         counter++;
0307     }
0308 
0309     if (counter == 10) {
0310         DC_LOG_WARNING(
0311             "%s: wait counter exceeded, changes to HW not applied",
0312             __func__);
0313     }
0314 }
0315 
0316 void dce112_compressor_power_up_fbc(struct compressor *compressor)
0317 {
0318     uint32_t value;
0319     uint32_t addr;
0320 
0321     addr = mmFBC_CNTL;
0322     value = dm_read_reg(compressor->ctx, addr);
0323     set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
0324     set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);
0325     set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);
0326     if (compressor->options.bits.CLK_GATING_DISABLED == 1) {
0327         /* HW needs to do power measurement comparison. */
0328         set_reg_field_value(
0329             value,
0330             0,
0331             FBC_CNTL,
0332             FBC_COMP_CLK_GATE_EN);
0333     }
0334     dm_write_reg(compressor->ctx, addr, value);
0335 
0336     addr = mmFBC_COMP_MODE;
0337     value = dm_read_reg(compressor->ctx, addr);
0338     set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);
0339     set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);
0340     set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);
0341     dm_write_reg(compressor->ctx, addr, value);
0342 
0343     addr = mmFBC_COMP_CNTL;
0344     value = dm_read_reg(compressor->ctx, addr);
0345     set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);
0346     dm_write_reg(compressor->ctx, addr, value);
0347     /*FBC_MIN_COMPRESSION 0 ==> 2:1 */
0348     /*                    1 ==> 4:1 */
0349     /*                    2 ==> 8:1 */
0350     /*                  0xF ==> 1:1 */
0351     set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);
0352     dm_write_reg(compressor->ctx, addr, value);
0353     compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;
0354 
0355     value = 0;
0356     dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);
0357 
0358     value = 0xFFFFFF;
0359     dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);
0360 }
0361 
0362 void dce112_compressor_enable_fbc(
0363     struct compressor *compressor,
0364     uint32_t paths_num,
0365     struct compr_addr_and_pitch_params *params)
0366 {
0367     struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
0368 
0369     if (compressor->options.bits.FBC_SUPPORT &&
0370         (compressor->options.bits.DUMMY_BACKEND == 0) &&
0371         (!dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) &&
0372         (!is_source_bigger_than_epanel_size(
0373             cp110,
0374             params->source_view_width,
0375             params->source_view_height))) {
0376 
0377         uint32_t addr;
0378         uint32_t value;
0379 
0380         /* Before enabling FBC first need to enable LPT if applicable
0381          * LPT state should always be changed (enable/disable) while FBC
0382          * is disabled */
0383         if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) &&
0384             (params->source_view_width *
0385                 params->source_view_height <=
0386                 dce11_one_lpt_channel_max_resolution)) {
0387             dce112_compressor_enable_lpt(compressor);
0388         }
0389 
0390         addr = mmFBC_CNTL;
0391         value = dm_read_reg(compressor->ctx, addr);
0392         set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
0393         set_reg_field_value(
0394             value,
0395             params->inst,
0396             FBC_CNTL, FBC_SRC_SEL);
0397         dm_write_reg(compressor->ctx, addr, value);
0398 
0399         /* Keep track of enum controller_id FBC is attached to */
0400         compressor->is_enabled = true;
0401         compressor->attached_inst = params->inst;
0402         cp110->offsets = reg_offsets[params->inst];
0403 
0404         /*Toggle it as there is bug in HW */
0405         set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
0406         dm_write_reg(compressor->ctx, addr, value);
0407         set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
0408         dm_write_reg(compressor->ctx, addr, value);
0409 
0410         wait_for_fbc_state_changed(cp110, true);
0411     }
0412 }
0413 
0414 void dce112_compressor_disable_fbc(struct compressor *compressor)
0415 {
0416     struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
0417 
0418     if (compressor->options.bits.FBC_SUPPORT &&
0419         dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
0420         uint32_t reg_data;
0421         /* Turn off compression */
0422         reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
0423         set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
0424         dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
0425 
0426         /* Reset enum controller_id to undefined */
0427         compressor->attached_inst = 0;
0428         compressor->is_enabled = false;
0429 
0430         /* Whenever disabling FBC make sure LPT is disabled if LPT
0431          * supported */
0432         if (compressor->options.bits.LPT_SUPPORT)
0433             dce112_compressor_disable_lpt(compressor);
0434 
0435         wait_for_fbc_state_changed(cp110, false);
0436     }
0437 }
0438 
0439 bool dce112_compressor_is_fbc_enabled_in_hw(
0440     struct compressor *compressor,
0441     uint32_t *inst)
0442 {
0443     /* Check the hardware register */
0444     uint32_t value;
0445 
0446     value = dm_read_reg(compressor->ctx, mmFBC_STATUS);
0447     if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {
0448         if (inst != NULL)
0449             *inst = compressor->attached_inst;
0450         return true;
0451     }
0452 
0453     value = dm_read_reg(compressor->ctx, mmFBC_MISC);
0454     if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {
0455         value = dm_read_reg(compressor->ctx, mmFBC_CNTL);
0456 
0457         if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {
0458             if (inst != NULL)
0459                 *inst =
0460                     compressor->attached_inst;
0461             return true;
0462         }
0463     }
0464     return false;
0465 }
0466 
0467 bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *compressor)
0468 {
0469     /* Check the hardware register */
0470     uint32_t value = dm_read_reg(compressor->ctx,
0471         mmLOW_POWER_TILING_CONTROL);
0472 
0473     return get_reg_field_value(
0474         value,
0475         LOW_POWER_TILING_CONTROL,
0476         LOW_POWER_TILING_ENABLE);
0477 }
0478 
0479 void dce112_compressor_program_compressed_surface_address_and_pitch(
0480     struct compressor *compressor,
0481     struct compr_addr_and_pitch_params *params)
0482 {
0483     struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
0484     uint32_t value = 0;
0485     uint32_t fbc_pitch = 0;
0486     uint32_t compressed_surf_address_low_part =
0487         compressor->compr_surface_address.addr.low_part;
0488 
0489     /* Clear content first. */
0490     dm_write_reg(
0491         compressor->ctx,
0492         DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
0493         0);
0494     dm_write_reg(compressor->ctx,
0495         DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);
0496 
0497     if (compressor->options.bits.LPT_SUPPORT) {
0498         uint32_t lpt_alignment = lpt_size_alignment(cp110);
0499 
0500         if (lpt_alignment != 0) {
0501             compressed_surf_address_low_part =
0502                 ((compressed_surf_address_low_part
0503                     + (lpt_alignment - 1)) / lpt_alignment)
0504                     * lpt_alignment;
0505         }
0506     }
0507 
0508     /* Write address, HIGH has to be first. */
0509     dm_write_reg(compressor->ctx,
0510         DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
0511         compressor->compr_surface_address.addr.high_part);
0512     dm_write_reg(compressor->ctx,
0513         DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),
0514         compressed_surf_address_low_part);
0515 
0516     fbc_pitch = align_to_chunks_number_per_line(
0517         cp110,
0518         params->source_view_width);
0519 
0520     if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
0521         fbc_pitch = fbc_pitch / 8;
0522     else
0523         DC_LOG_WARNING(
0524             "%s: Unexpected DCE11 compression ratio",
0525             __func__);
0526 
0527     /* Clear content first. */
0528     dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);
0529 
0530     /* Write FBC Pitch. */
0531     set_reg_field_value(
0532         value,
0533         fbc_pitch,
0534         GRPH_COMPRESS_PITCH,
0535         GRPH_COMPRESS_PITCH);
0536     dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);
0537 
0538 }
0539 
0540 void dce112_compressor_disable_lpt(struct compressor *compressor)
0541 {
0542     struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
0543     uint32_t value;
0544     uint32_t addr;
0545     uint32_t inx;
0546 
0547     /* Disable all pipes LPT Stutter */
0548     for (inx = 0; inx < 3; inx++) {
0549         value =
0550             dm_read_reg(
0551                 compressor->ctx,
0552                 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
0553         set_reg_field_value(
0554             value,
0555             0,
0556             DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
0557             STUTTER_ENABLE_NONLPTCH);
0558         dm_write_reg(
0559             compressor->ctx,
0560             DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH),
0561             value);
0562     }
0563     /* Disable Underlay pipe LPT Stutter */
0564     addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
0565     value = dm_read_reg(compressor->ctx, addr);
0566     set_reg_field_value(
0567         value,
0568         0,
0569         DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
0570         STUTTER_ENABLE_NONLPTCH);
0571     dm_write_reg(compressor->ctx, addr, value);
0572 
0573     /* Disable LPT */
0574     addr = mmLOW_POWER_TILING_CONTROL;
0575     value = dm_read_reg(compressor->ctx, addr);
0576     set_reg_field_value(
0577         value,
0578         0,
0579         LOW_POWER_TILING_CONTROL,
0580         LOW_POWER_TILING_ENABLE);
0581     dm_write_reg(compressor->ctx, addr, value);
0582 
0583     /* Clear selection of Channel(s) containing Compressed Surface */
0584     addr = mmGMCON_LPT_TARGET;
0585     value = dm_read_reg(compressor->ctx, addr);
0586     set_reg_field_value(
0587         value,
0588         0xFFFFFFFF,
0589         GMCON_LPT_TARGET,
0590         STCTRL_LPT_TARGET);
0591     dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value);
0592 }
0593 
0594 void dce112_compressor_enable_lpt(struct compressor *compressor)
0595 {
0596     struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
0597     uint32_t value;
0598     uint32_t addr;
0599     uint32_t value_control;
0600     uint32_t channels;
0601 
0602     /* Enable LPT Stutter from Display pipe */
0603     value = dm_read_reg(compressor->ctx,
0604         DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
0605     set_reg_field_value(
0606         value,
0607         1,
0608         DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
0609         STUTTER_ENABLE_NONLPTCH);
0610     dm_write_reg(compressor->ctx,
0611         DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value);
0612 
0613     /* Enable Underlay pipe LPT Stutter */
0614     addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
0615     value = dm_read_reg(compressor->ctx, addr);
0616     set_reg_field_value(
0617         value,
0618         1,
0619         DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
0620         STUTTER_ENABLE_NONLPTCH);
0621     dm_write_reg(compressor->ctx, addr, value);
0622 
0623     /* Selection of Channel(s) containing Compressed Surface: 0xfffffff
0624      * will disable LPT.
0625      * STCTRL_LPT_TARGETn corresponds to channel n. */
0626     addr = mmLOW_POWER_TILING_CONTROL;
0627     value_control = dm_read_reg(compressor->ctx, addr);
0628     channels = get_reg_field_value(value_control,
0629             LOW_POWER_TILING_CONTROL,
0630             LOW_POWER_TILING_MODE);
0631 
0632     addr = mmGMCON_LPT_TARGET;
0633     value = dm_read_reg(compressor->ctx, addr);
0634     set_reg_field_value(
0635         value,
0636         channels + 1, /* not mentioned in programming guide,
0637                 but follow DCE8.1 */
0638         GMCON_LPT_TARGET,
0639         STCTRL_LPT_TARGET);
0640     dm_write_reg(compressor->ctx, addr, value);
0641 
0642     /* Enable LPT */
0643     addr = mmLOW_POWER_TILING_CONTROL;
0644     value = dm_read_reg(compressor->ctx, addr);
0645     set_reg_field_value(
0646         value,
0647         1,
0648         LOW_POWER_TILING_CONTROL,
0649         LOW_POWER_TILING_ENABLE);
0650     dm_write_reg(compressor->ctx, addr, value);
0651 }
0652 
0653 void dce112_compressor_program_lpt_control(
0654     struct compressor *compressor,
0655     struct compr_addr_and_pitch_params *params)
0656 {
0657     struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
0658     uint32_t rows_per_channel;
0659     uint32_t lpt_alignment;
0660     uint32_t source_view_width;
0661     uint32_t source_view_height;
0662     uint32_t lpt_control = 0;
0663 
0664     if (!compressor->options.bits.LPT_SUPPORT)
0665         return;
0666 
0667     lpt_control = dm_read_reg(compressor->ctx,
0668         mmLOW_POWER_TILING_CONTROL);
0669 
0670     /* POSSIBLE VALUES for Low Power Tiling Mode:
0671      * 00 - Use channel 0
0672      * 01 - Use Channel 0 and 1
0673      * 02 - Use Channel 0,1,2,3
0674      * 03 - reserved */
0675     switch (compressor->lpt_channels_num) {
0676     /* case 2:
0677      * Use Channel 0 & 1 / Not used for DCE 11 */
0678     case 1:
0679         /*Use Channel 0 for LPT for DCE 11 */
0680         set_reg_field_value(
0681             lpt_control,
0682             0,
0683             LOW_POWER_TILING_CONTROL,
0684             LOW_POWER_TILING_MODE);
0685         break;
0686     default:
0687         DC_LOG_WARNING(
0688             "%s: Invalid selected DRAM channels for LPT!!!",
0689             __func__);
0690         break;
0691     }
0692 
0693     lpt_control = lpt_memory_control_config(cp110, lpt_control);
0694 
0695     /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on
0696      * FBC compressed surface pitch.
0697      * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *
0698      * Surface Pitch) / (Row Size * Number of Channels *
0699      * Number of Banks)). */
0700     rows_per_channel = 0;
0701     lpt_alignment = lpt_size_alignment(cp110);
0702     source_view_width =
0703         align_to_chunks_number_per_line(
0704             cp110,
0705             params->source_view_width);
0706     source_view_height = (params->source_view_height + 1) & (~0x1);
0707 
0708     if (lpt_alignment != 0) {
0709         rows_per_channel = source_view_width * source_view_height * 4;
0710         rows_per_channel =
0711             (rows_per_channel % lpt_alignment) ?
0712                 (rows_per_channel / lpt_alignment + 1) :
0713                 rows_per_channel / lpt_alignment;
0714     }
0715 
0716     set_reg_field_value(
0717         lpt_control,
0718         rows_per_channel,
0719         LOW_POWER_TILING_CONTROL,
0720         LOW_POWER_TILING_ROWS_PER_CHAN);
0721 
0722     dm_write_reg(compressor->ctx,
0723         mmLOW_POWER_TILING_CONTROL, lpt_control);
0724 }
0725 
0726 /*
0727  * DCE 11 Frame Buffer Compression Implementation
0728  */
0729 
0730 void dce112_compressor_set_fbc_invalidation_triggers(
0731     struct compressor *compressor,
0732     uint32_t fbc_trigger)
0733 {
0734     /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
0735      * for DCE 11 regions cannot be used - does not work with S/G
0736      */
0737     uint32_t addr = mmFBC_CLIENT_REGION_MASK;
0738     uint32_t value = dm_read_reg(compressor->ctx, addr);
0739 
0740     set_reg_field_value(
0741         value,
0742         0,
0743         FBC_CLIENT_REGION_MASK,
0744         FBC_MEMORY_REGION_MASK);
0745     dm_write_reg(compressor->ctx, addr, value);
0746 
0747     /* Setup events when to clear all CSM entries (effectively marking
0748      * current compressed data invalid)
0749      * For DCE 11 CSM metadata 11111 means - "Not Compressed"
0750      * Used as the initial value of the metadata sent to the compressor
0751      * after invalidation, to indicate that the compressor should attempt
0752      * to compress all chunks on the current pass.  Also used when the chunk
0753      * is not successfully written to memory.
0754      * When this CSM value is detected, FBC reads from the uncompressed
0755      * buffer. Set events according to passed in value, these events are
0756      * valid for DCE11:
0757      *     - bit  0 - display register updated
0758      *     - bit 28 - memory write from any client except from MCIF
0759      *     - bit 29 - CG static screen signal is inactive
0760      * In addition, DCE11.1 also needs to set new DCE11.1 specific events
0761      * that are used to trigger invalidation on certain register changes,
0762      * for example enabling of Alpha Compression may trigger invalidation of
0763      * FBC once bit is set. These events are as follows:
0764      *      - Bit 2 - FBC_GRPH_COMP_EN register updated
0765      *      - Bit 3 - FBC_SRC_SEL register updated
0766      *      - Bit 4 - FBC_MIN_COMPRESSION register updated
0767      *      - Bit 5 - FBC_ALPHA_COMP_EN register updated
0768      *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
0769      *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
0770      */
0771     addr = mmFBC_IDLE_FORCE_CLEAR_MASK;
0772     value = dm_read_reg(compressor->ctx, addr);
0773     set_reg_field_value(
0774         value,
0775         fbc_trigger |
0776         FBC_IDLE_FORCE_GRPH_COMP_EN |
0777         FBC_IDLE_FORCE_SRC_SEL_CHANGE |
0778         FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE |
0779         FBC_IDLE_FORCE_ALPHA_COMP_EN |
0780         FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN |
0781         FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF,
0782         FBC_IDLE_FORCE_CLEAR_MASK,
0783         FBC_IDLE_FORCE_CLEAR_MASK);
0784     dm_write_reg(compressor->ctx, addr, value);
0785 }
0786 
0787 void dce112_compressor_construct(struct dce112_compressor *compressor,
0788     struct dc_context *ctx)
0789 {
0790     struct dc_bios *bp = ctx->dc_bios;
0791     struct embedded_panel_info panel_info;
0792 
0793     compressor->base.options.raw = 0;
0794     compressor->base.options.bits.FBC_SUPPORT = true;
0795     compressor->base.options.bits.LPT_SUPPORT = true;
0796      /* For DCE 11 always use one DRAM channel for LPT */
0797     compressor->base.lpt_channels_num = 1;
0798     compressor->base.options.bits.DUMMY_BACKEND = false;
0799 
0800     /* Check if this system has more than 1 DRAM channel; if only 1 then LPT
0801      * should not be supported */
0802     if (compressor->base.memory_bus_width == 64)
0803         compressor->base.options.bits.LPT_SUPPORT = false;
0804 
0805     compressor->base.options.bits.CLK_GATING_DISABLED = false;
0806 
0807     compressor->base.ctx = ctx;
0808     compressor->base.embedded_panel_h_size = 0;
0809     compressor->base.embedded_panel_v_size = 0;
0810     compressor->base.memory_bus_width = ctx->asic_id.vram_width;
0811     compressor->base.allocated_size = 0;
0812     compressor->base.preferred_requested_size = 0;
0813     compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;
0814     compressor->base.banks_num = 0;
0815     compressor->base.raw_size = 0;
0816     compressor->base.channel_interleave_size = 0;
0817     compressor->base.dram_channels_num = 0;
0818     compressor->base.lpt_channels_num = 0;
0819     compressor->base.attached_inst = 0;
0820     compressor->base.is_enabled = false;
0821 
0822     if (BP_RESULT_OK ==
0823             bp->funcs->get_embedded_panel_info(bp, &panel_info)) {
0824         compressor->base.embedded_panel_h_size =
0825             panel_info.lcd_timing.horizontal_addressable;
0826         compressor->base.embedded_panel_v_size =
0827             panel_info.lcd_timing.vertical_addressable;
0828     }
0829 }
0830 
0831 struct compressor *dce112_compressor_create(struct dc_context *ctx)
0832 {
0833     struct dce112_compressor *cp110 =
0834         kzalloc(sizeof(struct dce112_compressor), GFP_KERNEL);
0835 
0836     if (!cp110)
0837         return NULL;
0838 
0839     dce112_compressor_construct(cp110, ctx);
0840     return &cp110->base;
0841 }
0842 
0843 void dce112_compressor_destroy(struct compressor **compressor)
0844 {
0845     kfree(TO_DCE112_COMPRESSOR(*compressor));
0846     *compressor = NULL;
0847 }