LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dce112 - dce112_compressor.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 269 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012-15 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  * Authors: AMD
      23             :  *
      24             :  */
      25             : 
      26             : #include "dm_services.h"
      27             : 
      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"
      32             : 
      33             : #include "include/logger_interface.h"
      34             : 
      35             : #include "dce112_compressor.h"
      36             : #define DC_LOGGER \
      37             :                 cp110->base.ctx->logger
      38             : #define DCP_REG(reg)\
      39             :         (reg + cp110->offsets.dcp_offset)
      40             : #define DMIF_REG(reg)\
      41             :         (reg + cp110->offsets.dmif_offset)
      42             : 
      43             : static const struct dce112_compressor_reg_offsets reg_offsets[] = {
      44             : {
      45             :         .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
      46             :         .dmif_offset =
      47             :                 (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
      48             :                         - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
      49             : },
      50             : {
      51             :         .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
      52             :         .dmif_offset =
      53             :                 (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
      54             :                         - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
      55             : },
      56             : {
      57             :         .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
      58             :         .dmif_offset =
      59             :                 (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
      60             :                         - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
      61             : }
      62             : };
      63             : 
      64             : static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;
      65             : 
      66             : enum fbc_idle_force {
      67             :         /* Bit 0 - Display registers updated */
      68             :         FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001,
      69             : 
      70             :         /* Bit 2 - FBC_GRPH_COMP_EN register updated */
      71             :         FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002,
      72             :         /* Bit 3 - FBC_SRC_SEL register updated */
      73             :         FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004,
      74             :         /* Bit 4 - FBC_MIN_COMPRESSION register updated */
      75             :         FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008,
      76             :         /* Bit 5 - FBC_ALPHA_COMP_EN register updated */
      77             :         FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010,
      78             :         /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */
      79             :         FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020,
      80             :         /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */
      81             :         FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040,
      82             : 
      83             :         /* Bit 24 - Memory write to region 0 defined by MC registers. */
      84             :         FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000,
      85             :         /* Bit 25 - Memory write to region 1 defined by MC registers */
      86             :         FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000,
      87             :         /* Bit 26 - Memory write to region 2 defined by MC registers */
      88             :         FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000,
      89             :         /* Bit 27 - Memory write to region 3 defined by MC registers. */
      90             :         FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000,
      91             : 
      92             :         /* Bit 28 - Memory write from any client other than MCIF */
      93             :         FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000,
      94             :         /* Bit 29 - CG statics screen signal is inactive */
      95             :         FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000,
      96             : };
      97             : 
      98             : static uint32_t lpt_size_alignment(struct dce112_compressor *cp110)
      99             : {
     100             :         /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
     101           0 :         return cp110->base.raw_size * cp110->base.banks_num *
     102             :                 cp110->base.dram_channels_num;
     103             : }
     104             : 
     105           0 : static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,
     106             :         uint32_t lpt_control)
     107             : {
     108             :         /*LPT MC Config */
     109           0 :         if (cp110->base.options.bits.LPT_MC_CONFIG == 1) {
     110             :                 /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):
     111             :                  * 00 - 1 CHANNEL
     112             :                  * 01 - 2 CHANNELS
     113             :                  * 02 - 4 OR 6 CHANNELS
     114             :                  * (Only for discrete GPU, N/A for CZ)
     115             :                  * 03 - 8 OR 12 CHANNELS
     116             :                  * (Only for discrete GPU, N/A for CZ) */
     117           0 :                 switch (cp110->base.dram_channels_num) {
     118             :                 case 2:
     119           0 :                         set_reg_field_value(
     120             :                                 lpt_control,
     121             :                                 1,
     122             :                                 LOW_POWER_TILING_CONTROL,
     123             :                                 LOW_POWER_TILING_NUM_PIPES);
     124           0 :                         break;
     125             :                 case 1:
     126           0 :                         set_reg_field_value(
     127             :                                 lpt_control,
     128             :                                 0,
     129             :                                 LOW_POWER_TILING_CONTROL,
     130             :                                 LOW_POWER_TILING_NUM_PIPES);
     131           0 :                         break;
     132             :                 default:
     133           0 :                         DC_LOG_WARNING(
     134             :                                 "%s: Invalid LPT NUM_PIPES!!!",
     135             :                                 __func__);
     136           0 :                         break;
     137             :                 }
     138             : 
     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.
     143             :                  * POSSIBLE VALUES:
     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           0 :                 switch (cp110->base.banks_num) {
     149             :                 case 16:
     150           0 :                         set_reg_field_value(
     151             :                                 lpt_control,
     152             :                                 3,
     153             :                                 LOW_POWER_TILING_CONTROL,
     154             :                                 LOW_POWER_TILING_NUM_BANKS);
     155           0 :                         break;
     156             :                 case 8:
     157           0 :                         set_reg_field_value(
     158             :                                 lpt_control,
     159             :                                 2,
     160             :                                 LOW_POWER_TILING_CONTROL,
     161             :                                 LOW_POWER_TILING_NUM_BANKS);
     162           0 :                         break;
     163             :                 case 4:
     164           0 :                         set_reg_field_value(
     165             :                                 lpt_control,
     166             :                                 1,
     167             :                                 LOW_POWER_TILING_CONTROL,
     168             :                                 LOW_POWER_TILING_NUM_BANKS);
     169           0 :                         break;
     170             :                 case 2:
     171           0 :                         set_reg_field_value(
     172             :                                 lpt_control,
     173             :                                 0,
     174             :                                 LOW_POWER_TILING_CONTROL,
     175             :                                 LOW_POWER_TILING_NUM_BANKS);
     176           0 :                         break;
     177             :                 default:
     178           0 :                         DC_LOG_WARNING(
     179             :                                 "%s: Invalid LPT NUM_BANKS!!!",
     180             :                                 __func__);
     181           0 :                         break;
     182             :                 }
     183             : 
     184             :                 /* The mapping is in DMIF_ADDR_CALC.
     185             :                  * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for
     186             :                  * Carrizo specifies the memory interleave per pipe.
     187             :                  * It effectively specifies the location of pipe bits in
     188             :                  * the memory address.
     189             :                  * POSSIBLE VALUES:
     190             :                  * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte
     191             :                  * interleave
     192             :                  * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte
     193             :                  * interleave
     194             :                  */
     195           0 :                 switch (cp110->base.channel_interleave_size) {
     196             :                 case 256: /*256B */
     197           0 :                         set_reg_field_value(
     198             :                                 lpt_control,
     199             :                                 0,
     200             :                                 LOW_POWER_TILING_CONTROL,
     201             :                                 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
     202           0 :                         break;
     203             :                 case 512: /*512B */
     204           0 :                         set_reg_field_value(
     205             :                                 lpt_control,
     206             :                                 1,
     207             :                                 LOW_POWER_TILING_CONTROL,
     208             :                                 LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
     209           0 :                         break;
     210             :                 default:
     211           0 :                         DC_LOG_WARNING(
     212             :                                 "%s: Invalid LPT INTERLEAVE_SIZE!!!",
     213             :                                 __func__);
     214           0 :                         break;
     215             :                 }
     216             : 
     217             :                 /* The mapping for LOW_POWER_TILING_ROW_SIZE is in
     218             :                  * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field
     219             :                  * for Carrizo. Specifies the size of dram row in bytes.
     220             :                  * This should match up with NOOFCOLS field in
     221             :                  * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).
     222             :                  * This register DMIF_ADDR_CALC is not used by the
     223             :                  * hardware as it is only used for addrlib assertions.
     224             :                  * POSSIBLE VALUES:
     225             :                  * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row
     226             :                  * boundary
     227             :                  * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row
     228             :                  * boundary
     229             :                  * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row
     230             :                  * boundary */
     231           0 :                 switch (cp110->base.raw_size) {
     232             :                 case 4096: /*4 KB */
     233           0 :                         set_reg_field_value(
     234             :                                 lpt_control,
     235             :                                 2,
     236             :                                 LOW_POWER_TILING_CONTROL,
     237             :                                 LOW_POWER_TILING_ROW_SIZE);
     238           0 :                         break;
     239             :                 case 2048:
     240           0 :                         set_reg_field_value(
     241             :                                 lpt_control,
     242             :                                 1,
     243             :                                 LOW_POWER_TILING_CONTROL,
     244             :                                 LOW_POWER_TILING_ROW_SIZE);
     245           0 :                         break;
     246             :                 case 1024:
     247           0 :                         set_reg_field_value(
     248             :                                 lpt_control,
     249             :                                 0,
     250             :                                 LOW_POWER_TILING_CONTROL,
     251             :                                 LOW_POWER_TILING_ROW_SIZE);
     252           0 :                         break;
     253             :                 default:
     254           0 :                         DC_LOG_WARNING(
     255             :                                 "%s: Invalid LPT ROW_SIZE!!!",
     256             :                                 __func__);
     257           0 :                         break;
     258             :                 }
     259             :         } else {
     260           0 :                 DC_LOG_WARNING(
     261             :                         "%s: LPT MC Configuration is not provided",
     262             :                         __func__);
     263             :         }
     264             : 
     265           0 :         return lpt_control;
     266             : }
     267             : 
     268             : static bool is_source_bigger_than_epanel_size(
     269             :         struct dce112_compressor *cp110,
     270             :         uint32_t source_view_width,
     271             :         uint32_t source_view_height)
     272             : {
     273           0 :         if (cp110->base.embedded_panel_h_size != 0 &&
     274           0 :                 cp110->base.embedded_panel_v_size != 0 &&
     275           0 :                 ((source_view_width * source_view_height) >
     276           0 :                 (cp110->base.embedded_panel_h_size *
     277             :                         cp110->base.embedded_panel_v_size)))
     278             :                 return true;
     279             : 
     280             :         return false;
     281             : }
     282             : 
     283             : static uint32_t align_to_chunks_number_per_line(
     284             :         struct dce112_compressor *cp110,
     285             :         uint32_t pixels)
     286             : {
     287           0 :         return 256 * ((pixels + 255) / 256);
     288             : }
     289             : 
     290           0 : static void wait_for_fbc_state_changed(
     291             :         struct dce112_compressor *cp110,
     292             :         bool enabled)
     293             : {
     294           0 :         uint8_t counter = 0;
     295           0 :         uint32_t addr = mmFBC_STATUS;
     296             :         uint32_t value;
     297             : 
     298           0 :         while (counter < 10) {
     299           0 :                 value = dm_read_reg(cp110->base.ctx, addr);
     300           0 :                 if (get_reg_field_value(
     301             :                         value,
     302             :                         FBC_STATUS,
     303           0 :                         FBC_ENABLE_STATUS) == enabled)
     304             :                         break;
     305           0 :                 udelay(10);
     306           0 :                 counter++;
     307             :         }
     308             : 
     309           0 :         if (counter == 10) {
     310           0 :                 DC_LOG_WARNING(
     311             :                         "%s: wait counter exceeded, changes to HW not applied",
     312             :                         __func__);
     313             :         }
     314           0 : }
     315             : 
     316           0 : void dce112_compressor_power_up_fbc(struct compressor *compressor)
     317             : {
     318             :         uint32_t value;
     319             :         uint32_t addr;
     320             : 
     321           0 :         addr = mmFBC_CNTL;
     322           0 :         value = dm_read_reg(compressor->ctx, addr);
     323           0 :         set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
     324           0 :         set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);
     325           0 :         set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);
     326           0 :         if (compressor->options.bits.CLK_GATING_DISABLED == 1) {
     327             :                 /* HW needs to do power measurement comparison. */
     328           0 :                 set_reg_field_value(
     329             :                         value,
     330             :                         0,
     331             :                         FBC_CNTL,
     332             :                         FBC_COMP_CLK_GATE_EN);
     333             :         }
     334           0 :         dm_write_reg(compressor->ctx, addr, value);
     335             : 
     336           0 :         addr = mmFBC_COMP_MODE;
     337           0 :         value = dm_read_reg(compressor->ctx, addr);
     338           0 :         set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);
     339           0 :         set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);
     340           0 :         set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);
     341           0 :         dm_write_reg(compressor->ctx, addr, value);
     342             : 
     343           0 :         addr = mmFBC_COMP_CNTL;
     344           0 :         value = dm_read_reg(compressor->ctx, addr);
     345           0 :         set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);
     346           0 :         dm_write_reg(compressor->ctx, addr, value);
     347             :         /*FBC_MIN_COMPRESSION 0 ==> 2:1 */
     348             :         /*                    1 ==> 4:1 */
     349             :         /*                    2 ==> 8:1 */
     350             :         /*                  0xF ==> 1:1 */
     351           0 :         set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);
     352           0 :         dm_write_reg(compressor->ctx, addr, value);
     353           0 :         compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;
     354             : 
     355           0 :         value = 0;
     356           0 :         dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);
     357             : 
     358           0 :         value = 0xFFFFFF;
     359           0 :         dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);
     360           0 : }
     361             : 
     362           0 : void dce112_compressor_enable_fbc(
     363             :         struct compressor *compressor,
     364             :         uint32_t paths_num,
     365             :         struct compr_addr_and_pitch_params *params)
     366             : {
     367           0 :         struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
     368             : 
     369           0 :         if (compressor->options.bits.FBC_SUPPORT &&
     370           0 :                 (compressor->options.bits.DUMMY_BACKEND == 0) &&
     371           0 :                 (!dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) &&
     372           0 :                 (!is_source_bigger_than_epanel_size(
     373             :                         cp110,
     374             :                         params->source_view_width,
     375             :                         params->source_view_height))) {
     376             : 
     377             :                 uint32_t addr;
     378             :                 uint32_t value;
     379             : 
     380             :                 /* Before enabling FBC first need to enable LPT if applicable
     381             :                  * LPT state should always be changed (enable/disable) while FBC
     382             :                  * is disabled */
     383           0 :                 if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) &&
     384           0 :                         (params->source_view_width *
     385             :                                 params->source_view_height <=
     386             :                                 dce11_one_lpt_channel_max_resolution)) {
     387           0 :                         dce112_compressor_enable_lpt(compressor);
     388             :                 }
     389             : 
     390           0 :                 addr = mmFBC_CNTL;
     391           0 :                 value = dm_read_reg(compressor->ctx, addr);
     392           0 :                 set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
     393           0 :                 set_reg_field_value(
     394             :                         value,
     395             :                         params->inst,
     396             :                         FBC_CNTL, FBC_SRC_SEL);
     397           0 :                 dm_write_reg(compressor->ctx, addr, value);
     398             : 
     399             :                 /* Keep track of enum controller_id FBC is attached to */
     400           0 :                 compressor->is_enabled = true;
     401           0 :                 compressor->attached_inst = params->inst;
     402           0 :                 cp110->offsets = reg_offsets[params->inst];
     403             : 
     404             :                 /*Toggle it as there is bug in HW */
     405           0 :                 set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
     406           0 :                 dm_write_reg(compressor->ctx, addr, value);
     407           0 :                 set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
     408           0 :                 dm_write_reg(compressor->ctx, addr, value);
     409             : 
     410           0 :                 wait_for_fbc_state_changed(cp110, true);
     411             :         }
     412           0 : }
     413             : 
     414           0 : void dce112_compressor_disable_fbc(struct compressor *compressor)
     415             : {
     416           0 :         struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
     417             : 
     418           0 :         if (compressor->options.bits.FBC_SUPPORT &&
     419           0 :                 dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
     420             :                 uint32_t reg_data;
     421             :                 /* Turn off compression */
     422           0 :                 reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
     423           0 :                 set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
     424           0 :                 dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
     425             : 
     426             :                 /* Reset enum controller_id to undefined */
     427           0 :                 compressor->attached_inst = 0;
     428           0 :                 compressor->is_enabled = false;
     429             : 
     430             :                 /* Whenever disabling FBC make sure LPT is disabled if LPT
     431             :                  * supported */
     432           0 :                 if (compressor->options.bits.LPT_SUPPORT)
     433           0 :                         dce112_compressor_disable_lpt(compressor);
     434             : 
     435           0 :                 wait_for_fbc_state_changed(cp110, false);
     436             :         }
     437           0 : }
     438             : 
     439           0 : bool dce112_compressor_is_fbc_enabled_in_hw(
     440             :         struct compressor *compressor,
     441             :         uint32_t *inst)
     442             : {
     443             :         /* Check the hardware register */
     444             :         uint32_t value;
     445             : 
     446           0 :         value = dm_read_reg(compressor->ctx, mmFBC_STATUS);
     447           0 :         if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {
     448           0 :                 if (inst != NULL)
     449           0 :                         *inst = compressor->attached_inst;
     450             :                 return true;
     451             :         }
     452             : 
     453           0 :         value = dm_read_reg(compressor->ctx, mmFBC_MISC);
     454           0 :         if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {
     455           0 :                 value = dm_read_reg(compressor->ctx, mmFBC_CNTL);
     456             : 
     457           0 :                 if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {
     458           0 :                         if (inst != NULL)
     459           0 :                                 *inst =
     460           0 :                                         compressor->attached_inst;
     461             :                         return true;
     462             :                 }
     463             :         }
     464             :         return false;
     465             : }
     466             : 
     467           0 : bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *compressor)
     468             : {
     469             :         /* Check the hardware register */
     470           0 :         uint32_t value = dm_read_reg(compressor->ctx,
     471             :                 mmLOW_POWER_TILING_CONTROL);
     472             : 
     473           0 :         return get_reg_field_value(
     474             :                 value,
     475             :                 LOW_POWER_TILING_CONTROL,
     476             :                 LOW_POWER_TILING_ENABLE);
     477             : }
     478             : 
     479           0 : void dce112_compressor_program_compressed_surface_address_and_pitch(
     480             :         struct compressor *compressor,
     481             :         struct compr_addr_and_pitch_params *params)
     482             : {
     483           0 :         struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
     484           0 :         uint32_t value = 0;
     485           0 :         uint32_t fbc_pitch = 0;
     486           0 :         uint32_t compressed_surf_address_low_part =
     487             :                 compressor->compr_surface_address.addr.low_part;
     488             : 
     489             :         /* Clear content first. */
     490           0 :         dm_write_reg(
     491             :                 compressor->ctx,
     492             :                 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
     493             :                 0);
     494           0 :         dm_write_reg(compressor->ctx,
     495             :                 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);
     496             : 
     497           0 :         if (compressor->options.bits.LPT_SUPPORT) {
     498           0 :                 uint32_t lpt_alignment = lpt_size_alignment(cp110);
     499             : 
     500           0 :                 if (lpt_alignment != 0) {
     501           0 :                         compressed_surf_address_low_part =
     502             :                                 ((compressed_surf_address_low_part
     503           0 :                                         + (lpt_alignment - 1)) / lpt_alignment)
     504             :                                         * lpt_alignment;
     505             :                 }
     506             :         }
     507             : 
     508             :         /* Write address, HIGH has to be first. */
     509           0 :         dm_write_reg(compressor->ctx,
     510             :                 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
     511             :                 compressor->compr_surface_address.addr.high_part);
     512           0 :         dm_write_reg(compressor->ctx,
     513             :                 DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),
     514             :                 compressed_surf_address_low_part);
     515             : 
     516           0 :         fbc_pitch = align_to_chunks_number_per_line(
     517             :                 cp110,
     518             :                 params->source_view_width);
     519             : 
     520           0 :         if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
     521           0 :                 fbc_pitch = fbc_pitch / 8;
     522             :         else
     523           0 :                 DC_LOG_WARNING(
     524             :                         "%s: Unexpected DCE11 compression ratio",
     525             :                         __func__);
     526             : 
     527             :         /* Clear content first. */
     528           0 :         dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);
     529             : 
     530             :         /* Write FBC Pitch. */
     531           0 :         set_reg_field_value(
     532             :                 value,
     533             :                 fbc_pitch,
     534             :                 GRPH_COMPRESS_PITCH,
     535             :                 GRPH_COMPRESS_PITCH);
     536           0 :         dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);
     537             : 
     538           0 : }
     539             : 
     540           0 : void dce112_compressor_disable_lpt(struct compressor *compressor)
     541             : {
     542           0 :         struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
     543             :         uint32_t value;
     544             :         uint32_t addr;
     545             :         uint32_t inx;
     546             : 
     547             :         /* Disable all pipes LPT Stutter */
     548           0 :         for (inx = 0; inx < 3; inx++) {
     549           0 :                 value =
     550           0 :                         dm_read_reg(
     551             :                                 compressor->ctx,
     552             :                                 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
     553           0 :                 set_reg_field_value(
     554             :                         value,
     555             :                         0,
     556             :                         DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
     557             :                         STUTTER_ENABLE_NONLPTCH);
     558           0 :                 dm_write_reg(
     559             :                         compressor->ctx,
     560             :                         DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH),
     561             :                         value);
     562             :         }
     563             :         /* Disable Underlay pipe LPT Stutter */
     564           0 :         addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
     565           0 :         value = dm_read_reg(compressor->ctx, addr);
     566           0 :         set_reg_field_value(
     567             :                 value,
     568             :                 0,
     569             :                 DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
     570             :                 STUTTER_ENABLE_NONLPTCH);
     571           0 :         dm_write_reg(compressor->ctx, addr, value);
     572             : 
     573             :         /* Disable LPT */
     574           0 :         addr = mmLOW_POWER_TILING_CONTROL;
     575           0 :         value = dm_read_reg(compressor->ctx, addr);
     576           0 :         set_reg_field_value(
     577             :                 value,
     578             :                 0,
     579             :                 LOW_POWER_TILING_CONTROL,
     580             :                 LOW_POWER_TILING_ENABLE);
     581           0 :         dm_write_reg(compressor->ctx, addr, value);
     582             : 
     583             :         /* Clear selection of Channel(s) containing Compressed Surface */
     584           0 :         addr = mmGMCON_LPT_TARGET;
     585           0 :         value = dm_read_reg(compressor->ctx, addr);
     586           0 :         set_reg_field_value(
     587             :                 value,
     588             :                 0xFFFFFFFF,
     589             :                 GMCON_LPT_TARGET,
     590             :                 STCTRL_LPT_TARGET);
     591           0 :         dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value);
     592           0 : }
     593             : 
     594           0 : void dce112_compressor_enable_lpt(struct compressor *compressor)
     595             : {
     596           0 :         struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
     597             :         uint32_t value;
     598             :         uint32_t addr;
     599             :         uint32_t value_control;
     600             :         uint32_t channels;
     601             : 
     602             :         /* Enable LPT Stutter from Display pipe */
     603           0 :         value = dm_read_reg(compressor->ctx,
     604             :                 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
     605           0 :         set_reg_field_value(
     606             :                 value,
     607             :                 1,
     608             :                 DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
     609             :                 STUTTER_ENABLE_NONLPTCH);
     610           0 :         dm_write_reg(compressor->ctx,
     611             :                 DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value);
     612             : 
     613             :         /* Enable Underlay pipe LPT Stutter */
     614           0 :         addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
     615           0 :         value = dm_read_reg(compressor->ctx, addr);
     616           0 :         set_reg_field_value(
     617             :                 value,
     618             :                 1,
     619             :                 DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
     620             :                 STUTTER_ENABLE_NONLPTCH);
     621           0 :         dm_write_reg(compressor->ctx, addr, value);
     622             : 
     623             :         /* Selection of Channel(s) containing Compressed Surface: 0xfffffff
     624             :          * will disable LPT.
     625             :          * STCTRL_LPT_TARGETn corresponds to channel n. */
     626           0 :         addr = mmLOW_POWER_TILING_CONTROL;
     627           0 :         value_control = dm_read_reg(compressor->ctx, addr);
     628           0 :         channels = get_reg_field_value(value_control,
     629             :                         LOW_POWER_TILING_CONTROL,
     630             :                         LOW_POWER_TILING_MODE);
     631             : 
     632           0 :         addr = mmGMCON_LPT_TARGET;
     633           0 :         value = dm_read_reg(compressor->ctx, addr);
     634           0 :         set_reg_field_value(
     635             :                 value,
     636             :                 channels + 1, /* not mentioned in programming guide,
     637             :                                 but follow DCE8.1 */
     638             :                 GMCON_LPT_TARGET,
     639             :                 STCTRL_LPT_TARGET);
     640           0 :         dm_write_reg(compressor->ctx, addr, value);
     641             : 
     642             :         /* Enable LPT */
     643           0 :         addr = mmLOW_POWER_TILING_CONTROL;
     644           0 :         value = dm_read_reg(compressor->ctx, addr);
     645           0 :         set_reg_field_value(
     646             :                 value,
     647             :                 1,
     648             :                 LOW_POWER_TILING_CONTROL,
     649             :                 LOW_POWER_TILING_ENABLE);
     650           0 :         dm_write_reg(compressor->ctx, addr, value);
     651           0 : }
     652             : 
     653           0 : void dce112_compressor_program_lpt_control(
     654             :         struct compressor *compressor,
     655             :         struct compr_addr_and_pitch_params *params)
     656             : {
     657           0 :         struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);
     658             :         uint32_t rows_per_channel;
     659             :         uint32_t lpt_alignment;
     660             :         uint32_t source_view_width;
     661             :         uint32_t source_view_height;
     662           0 :         uint32_t lpt_control = 0;
     663             : 
     664           0 :         if (!compressor->options.bits.LPT_SUPPORT)
     665             :                 return;
     666             : 
     667           0 :         lpt_control = dm_read_reg(compressor->ctx,
     668             :                 mmLOW_POWER_TILING_CONTROL);
     669             : 
     670             :         /* POSSIBLE VALUES for Low Power Tiling Mode:
     671             :          * 00 - Use channel 0
     672             :          * 01 - Use Channel 0 and 1
     673             :          * 02 - Use Channel 0,1,2,3
     674             :          * 03 - reserved */
     675           0 :         switch (compressor->lpt_channels_num) {
     676             :         /* case 2:
     677             :          * Use Channel 0 & 1 / Not used for DCE 11 */
     678             :         case 1:
     679             :                 /*Use Channel 0 for LPT for DCE 11 */
     680           0 :                 set_reg_field_value(
     681             :                         lpt_control,
     682             :                         0,
     683             :                         LOW_POWER_TILING_CONTROL,
     684             :                         LOW_POWER_TILING_MODE);
     685           0 :                 break;
     686             :         default:
     687           0 :                 DC_LOG_WARNING(
     688             :                         "%s: Invalid selected DRAM channels for LPT!!!",
     689             :                         __func__);
     690           0 :                 break;
     691             :         }
     692             : 
     693           0 :         lpt_control = lpt_memory_control_config(cp110, lpt_control);
     694             : 
     695             :         /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on
     696             :          * FBC compressed surface pitch.
     697             :          * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *
     698             :          * Surface Pitch) / (Row Size * Number of Channels *
     699             :          * Number of Banks)). */
     700           0 :         rows_per_channel = 0;
     701           0 :         lpt_alignment = lpt_size_alignment(cp110);
     702           0 :         source_view_width =
     703           0 :                 align_to_chunks_number_per_line(
     704             :                         cp110,
     705             :                         params->source_view_width);
     706           0 :         source_view_height = (params->source_view_height + 1) & (~0x1);
     707             : 
     708           0 :         if (lpt_alignment != 0) {
     709           0 :                 rows_per_channel = source_view_width * source_view_height * 4;
     710             :                 rows_per_channel =
     711           0 :                         (rows_per_channel % lpt_alignment) ?
     712           0 :                                 (rows_per_channel / lpt_alignment + 1) :
     713             :                                 rows_per_channel / lpt_alignment;
     714             :         }
     715             : 
     716           0 :         set_reg_field_value(
     717             :                 lpt_control,
     718             :                 rows_per_channel,
     719             :                 LOW_POWER_TILING_CONTROL,
     720             :                 LOW_POWER_TILING_ROWS_PER_CHAN);
     721             : 
     722           0 :         dm_write_reg(compressor->ctx,
     723             :                 mmLOW_POWER_TILING_CONTROL, lpt_control);
     724             : }
     725             : 
     726             : /*
     727             :  * DCE 11 Frame Buffer Compression Implementation
     728             :  */
     729             : 
     730           0 : void dce112_compressor_set_fbc_invalidation_triggers(
     731             :         struct compressor *compressor,
     732             :         uint32_t fbc_trigger)
     733             : {
     734             :         /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
     735             :          * for DCE 11 regions cannot be used - does not work with S/G
     736             :          */
     737           0 :         uint32_t addr = mmFBC_CLIENT_REGION_MASK;
     738           0 :         uint32_t value = dm_read_reg(compressor->ctx, addr);
     739             : 
     740           0 :         set_reg_field_value(
     741             :                 value,
     742             :                 0,
     743             :                 FBC_CLIENT_REGION_MASK,
     744             :                 FBC_MEMORY_REGION_MASK);
     745           0 :         dm_write_reg(compressor->ctx, addr, value);
     746             : 
     747             :         /* Setup events when to clear all CSM entries (effectively marking
     748             :          * current compressed data invalid)
     749             :          * For DCE 11 CSM metadata 11111 means - "Not Compressed"
     750             :          * Used as the initial value of the metadata sent to the compressor
     751             :          * after invalidation, to indicate that the compressor should attempt
     752             :          * to compress all chunks on the current pass.  Also used when the chunk
     753             :          * is not successfully written to memory.
     754             :          * When this CSM value is detected, FBC reads from the uncompressed
     755             :          * buffer. Set events according to passed in value, these events are
     756             :          * valid for DCE11:
     757             :          *     - bit  0 - display register updated
     758             :          *     - bit 28 - memory write from any client except from MCIF
     759             :          *     - bit 29 - CG static screen signal is inactive
     760             :          * In addition, DCE11.1 also needs to set new DCE11.1 specific events
     761             :          * that are used to trigger invalidation on certain register changes,
     762             :          * for example enabling of Alpha Compression may trigger invalidation of
     763             :          * FBC once bit is set. These events are as follows:
     764             :          *      - Bit 2 - FBC_GRPH_COMP_EN register updated
     765             :          *      - Bit 3 - FBC_SRC_SEL register updated
     766             :          *      - Bit 4 - FBC_MIN_COMPRESSION register updated
     767             :          *      - Bit 5 - FBC_ALPHA_COMP_EN register updated
     768             :          *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
     769             :          *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
     770             :          */
     771           0 :         addr = mmFBC_IDLE_FORCE_CLEAR_MASK;
     772           0 :         value = dm_read_reg(compressor->ctx, addr);
     773           0 :         set_reg_field_value(
     774             :                 value,
     775             :                 fbc_trigger |
     776             :                 FBC_IDLE_FORCE_GRPH_COMP_EN |
     777             :                 FBC_IDLE_FORCE_SRC_SEL_CHANGE |
     778             :                 FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE |
     779             :                 FBC_IDLE_FORCE_ALPHA_COMP_EN |
     780             :                 FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN |
     781             :                 FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF,
     782             :                 FBC_IDLE_FORCE_CLEAR_MASK,
     783             :                 FBC_IDLE_FORCE_CLEAR_MASK);
     784           0 :         dm_write_reg(compressor->ctx, addr, value);
     785           0 : }
     786             : 
     787           0 : void dce112_compressor_construct(struct dce112_compressor *compressor,
     788             :         struct dc_context *ctx)
     789             : {
     790           0 :         struct dc_bios *bp = ctx->dc_bios;
     791             :         struct embedded_panel_info panel_info;
     792             : 
     793           0 :         compressor->base.options.raw = 0;
     794           0 :         compressor->base.options.bits.FBC_SUPPORT = true;
     795           0 :         compressor->base.options.bits.LPT_SUPPORT = true;
     796             :          /* For DCE 11 always use one DRAM channel for LPT */
     797           0 :         compressor->base.lpt_channels_num = 1;
     798           0 :         compressor->base.options.bits.DUMMY_BACKEND = false;
     799             : 
     800             :         /* Check if this system has more than 1 DRAM channel; if only 1 then LPT
     801             :          * should not be supported */
     802           0 :         if (compressor->base.memory_bus_width == 64)
     803           0 :                 compressor->base.options.bits.LPT_SUPPORT = false;
     804             : 
     805           0 :         compressor->base.options.bits.CLK_GATING_DISABLED = false;
     806             : 
     807           0 :         compressor->base.ctx = ctx;
     808           0 :         compressor->base.embedded_panel_h_size = 0;
     809           0 :         compressor->base.embedded_panel_v_size = 0;
     810           0 :         compressor->base.memory_bus_width = ctx->asic_id.vram_width;
     811           0 :         compressor->base.allocated_size = 0;
     812           0 :         compressor->base.preferred_requested_size = 0;
     813           0 :         compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;
     814           0 :         compressor->base.banks_num = 0;
     815           0 :         compressor->base.raw_size = 0;
     816           0 :         compressor->base.channel_interleave_size = 0;
     817           0 :         compressor->base.dram_channels_num = 0;
     818           0 :         compressor->base.lpt_channels_num = 0;
     819           0 :         compressor->base.attached_inst = 0;
     820           0 :         compressor->base.is_enabled = false;
     821             : 
     822           0 :         if (BP_RESULT_OK ==
     823           0 :                         bp->funcs->get_embedded_panel_info(bp, &panel_info)) {
     824           0 :                 compressor->base.embedded_panel_h_size =
     825           0 :                         panel_info.lcd_timing.horizontal_addressable;
     826           0 :                 compressor->base.embedded_panel_v_size =
     827           0 :                         panel_info.lcd_timing.vertical_addressable;
     828             :         }
     829           0 : }
     830             : 
     831           0 : struct compressor *dce112_compressor_create(struct dc_context *ctx)
     832             : {
     833           0 :         struct dce112_compressor *cp110 =
     834             :                 kzalloc(sizeof(struct dce112_compressor), GFP_KERNEL);
     835             : 
     836           0 :         if (!cp110)
     837             :                 return NULL;
     838             : 
     839           0 :         dce112_compressor_construct(cp110, ctx);
     840           0 :         return &cp110->base;
     841             : }
     842             : 
     843           0 : void dce112_compressor_destroy(struct compressor **compressor)
     844             : {
     845           0 :         kfree(TO_DCE112_COMPRESSOR(*compressor));
     846           0 :         *compressor = NULL;
     847           0 : }

Generated by: LCOV version 1.14