Home | History | Annotate | Download | only in r800
      1 /*
      2  * Copyright  2014 Advanced Micro Devices, Inc.
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sub license, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     14  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     15  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     16  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
     17  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     20  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * The above copyright notice and this permission notice (including the
     23  * next paragraph) shall be included in all copies or substantial portions
     24  * of the Software.
     25  */
     26 
     27 /**
     28 ***************************************************************************************************
     29 * @file  siaddrlib.cpp
     30 * @brief Contains the implementation for the SIAddrLib class.
     31 ***************************************************************************************************
     32 */
     33 
     34 #include "siaddrlib.h"
     35 
     36 #include "si_gb_reg.h"
     37 
     38 #include "si_ci_vi_merged_enum.h"
     39 
     40 #if BRAHMA_BUILD
     41 #include "amdgpu_id.h"
     42 #else
     43 #include "si_id.h"
     44 #endif
     45 
     46 ///////////////////////////////////////////////////////////////////////////////////////////////////
     47 ///////////////////////////////////////////////////////////////////////////////////////////////////
     48 
     49 /**
     50 ***************************************************************************************************
     51 *   AddrSIHwlInit
     52 *
     53 *   @brief
     54 *       Creates an SIAddrLib object.
     55 *
     56 *   @return
     57 *       Returns an SIAddrLib object pointer.
     58 ***************************************************************************************************
     59 */
     60 AddrLib* AddrSIHwlInit(const AddrClient* pClient)
     61 {
     62     return SIAddrLib::CreateObj(pClient);
     63 }
     64 
     65 /**
     66 ***************************************************************************************************
     67 *   SIAddrLib::SIAddrLib
     68 *
     69 *   @brief
     70 *       Constructor
     71 *
     72 ***************************************************************************************************
     73 */
     74 SIAddrLib::SIAddrLib(const AddrClient* pClient) :
     75     EgBasedAddrLib(pClient),
     76     m_noOfEntries(0)
     77 {
     78     m_class = SI_ADDRLIB;
     79     memset(&m_settings, 0, sizeof(m_settings));
     80 }
     81 
     82 /**
     83 ***************************************************************************************************
     84 *   SIAddrLib::~SIAddrLib
     85 *
     86 *   @brief
     87 *       Destructor
     88 ***************************************************************************************************
     89 */
     90 SIAddrLib::~SIAddrLib()
     91 {
     92 }
     93 
     94 /**
     95 ***************************************************************************************************
     96 *   SIAddrLib::HwlGetPipes
     97 *
     98 *   @brief
     99 *       Get number pipes
    100 *   @return
    101 *       num pipes
    102 ***************************************************************************************************
    103 */
    104 UINT_32 SIAddrLib::HwlGetPipes(
    105     const ADDR_TILEINFO* pTileInfo    ///< [in] Tile info
    106     ) const
    107 {
    108     UINT_32 numPipes;
    109 
    110     if (pTileInfo)
    111     {
    112         numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
    113     }
    114     else
    115     {
    116         ADDR_ASSERT_ALWAYS();
    117         numPipes = m_pipes; // Suppose we should still have a global pipes
    118     }
    119 
    120     return numPipes;
    121 }
    122 
    123 /**
    124 ***************************************************************************************************
    125 *   SIAddrLib::GetPipePerSurf
    126 *   @brief
    127 *       get pipe num base on inputing tileinfo->pipeconfig
    128 *   @return
    129 *       pipe number
    130 ***************************************************************************************************
    131 */
    132 UINT_32 SIAddrLib::GetPipePerSurf(
    133     AddrPipeCfg pipeConfig   ///< [in] pipe config
    134     ) const
    135 {
    136     UINT_32 numPipes = 0;
    137 
    138     switch (pipeConfig)
    139     {
    140         case ADDR_PIPECFG_P2:
    141             numPipes = 2;
    142             break;
    143         case ADDR_PIPECFG_P4_8x16:
    144         case ADDR_PIPECFG_P4_16x16:
    145         case ADDR_PIPECFG_P4_16x32:
    146         case ADDR_PIPECFG_P4_32x32:
    147             numPipes = 4;
    148             break;
    149         case ADDR_PIPECFG_P8_16x16_8x16:
    150         case ADDR_PIPECFG_P8_16x32_8x16:
    151         case ADDR_PIPECFG_P8_32x32_8x16:
    152         case ADDR_PIPECFG_P8_16x32_16x16:
    153         case ADDR_PIPECFG_P8_32x32_16x16:
    154         case ADDR_PIPECFG_P8_32x32_16x32:
    155         case ADDR_PIPECFG_P8_32x64_32x32:
    156             numPipes = 8;
    157             break;
    158         case ADDR_PIPECFG_P16_32x32_8x16:
    159         case ADDR_PIPECFG_P16_32x32_16x16:
    160             numPipes = 16;
    161             break;
    162         default:
    163             ADDR_ASSERT(!"Invalid pipe config");
    164             numPipes = m_pipes;
    165     }
    166     return numPipes;
    167 }
    168 
    169 /**
    170 ***************************************************************************************************
    171 *   SIAddrLib::ComputePipeFromCoord
    172 *
    173 *   @brief
    174 *       Compute pipe number from coordinates
    175 *   @return
    176 *       Pipe number
    177 ***************************************************************************************************
    178 */
    179 UINT_32 SIAddrLib::ComputePipeFromCoord(
    180     UINT_32         x,              ///< [in] x coordinate
    181     UINT_32         y,              ///< [in] y coordinate
    182     UINT_32         slice,          ///< [in] slice index
    183     AddrTileMode    tileMode,       ///< [in] tile mode
    184     UINT_32         pipeSwizzle,    ///< [in] pipe swizzle
    185     BOOL_32         ignoreSE,       ///< [in] TRUE if shader engines are ignored
    186     ADDR_TILEINFO*  pTileInfo       ///< [in] Tile info
    187     ) const
    188 {
    189     UINT_32 pipe;
    190     UINT_32 pipeBit0 = 0;
    191     UINT_32 pipeBit1 = 0;
    192     UINT_32 pipeBit2 = 0;
    193     UINT_32 pipeBit3 = 0;
    194     UINT_32 sliceRotation;
    195     UINT_32 numPipes = 0;
    196 
    197     UINT_32 tx = x / MicroTileWidth;
    198     UINT_32 ty = y / MicroTileHeight;
    199     UINT_32 x3 = _BIT(tx,0);
    200     UINT_32 x4 = _BIT(tx,1);
    201     UINT_32 x5 = _BIT(tx,2);
    202     UINT_32 x6 = _BIT(tx,3);
    203     UINT_32 y3 = _BIT(ty,0);
    204     UINT_32 y4 = _BIT(ty,1);
    205     UINT_32 y5 = _BIT(ty,2);
    206     UINT_32 y6 = _BIT(ty,3);
    207 
    208     switch (pTileInfo->pipeConfig)
    209     {
    210         case ADDR_PIPECFG_P2:
    211             pipeBit0 = x3 ^ y3;
    212             numPipes = 2;
    213             break;
    214         case ADDR_PIPECFG_P4_8x16:
    215             pipeBit0 = x4 ^ y3;
    216             pipeBit1 = x3 ^ y4;
    217             numPipes = 4;
    218             break;
    219         case ADDR_PIPECFG_P4_16x16:
    220             pipeBit0 = x3 ^ y3 ^ x4;
    221             pipeBit1 = x4 ^ y4;
    222             numPipes = 4;
    223             break;
    224         case ADDR_PIPECFG_P4_16x32:
    225             pipeBit0 = x3 ^ y3 ^ x4;
    226             pipeBit1 = x4 ^ y5;
    227             numPipes = 4;
    228             break;
    229         case ADDR_PIPECFG_P4_32x32:
    230             pipeBit0 = x3 ^ y3 ^ x5;
    231             pipeBit1 = x5 ^ y5;
    232             numPipes = 4;
    233             break;
    234         case ADDR_PIPECFG_P8_16x16_8x16:
    235             pipeBit0 = x4 ^ y3 ^ x5;
    236             pipeBit1 = x3 ^ y5;
    237             numPipes = 8;
    238             break;
    239         case ADDR_PIPECFG_P8_16x32_8x16:
    240             pipeBit0 = x4 ^ y3 ^ x5;
    241             pipeBit1 = x3 ^ y4;
    242             pipeBit2 = x4 ^ y5;
    243             numPipes = 8;
    244             break;
    245         case ADDR_PIPECFG_P8_16x32_16x16:
    246             pipeBit0 = x3 ^ y3 ^ x4;
    247             pipeBit1 = x5 ^ y4;
    248             pipeBit2 = x4 ^ y5;
    249             numPipes = 8;
    250             break;
    251         case ADDR_PIPECFG_P8_32x32_8x16:
    252             pipeBit0 = x4 ^ y3 ^ x5;
    253             pipeBit1 = x3 ^ y4;
    254             pipeBit2 = x5 ^ y5;
    255             numPipes = 8;
    256             break;
    257         case ADDR_PIPECFG_P8_32x32_16x16:
    258             pipeBit0 = x3 ^ y3 ^ x4;
    259             pipeBit1 = x4 ^ y4;
    260             pipeBit2 = x5 ^ y5;
    261             numPipes = 8;
    262             break;
    263         case ADDR_PIPECFG_P8_32x32_16x32:
    264             pipeBit0 = x3 ^ y3 ^ x4;
    265             pipeBit1 = x4 ^ y6;
    266             pipeBit2 = x5 ^ y5;
    267             numPipes = 8;
    268             break;
    269         case ADDR_PIPECFG_P8_32x64_32x32:
    270             pipeBit0 = x3 ^ y3 ^ x5;
    271             pipeBit1 = x6 ^ y5;
    272             pipeBit2 = x5 ^ y6;
    273             numPipes = 8;
    274             break;
    275         case ADDR_PIPECFG_P16_32x32_8x16:
    276             pipeBit0 = x4 ^ y3;
    277             pipeBit1 = x3 ^ y4;
    278             pipeBit2 = x5 ^ y6;
    279             pipeBit3 = x6 ^ y5;
    280             numPipes = 16;
    281             break;
    282         case ADDR_PIPECFG_P16_32x32_16x16:
    283             pipeBit0 = x3 ^ y3 ^ x4;
    284             pipeBit1 = x4 ^ y4;
    285             pipeBit2 = x5 ^ y6;
    286             pipeBit3 = x6 ^ y5;
    287             numPipes = 16;
    288             break;
    289         default:
    290             ADDR_UNHANDLED_CASE();
    291             break;
    292     }
    293     pipe = pipeBit0 | (pipeBit1 << 1) | (pipeBit2 << 2) | (pipeBit3 << 3);
    294 
    295     UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode);
    296 
    297     //
    298     // Apply pipe rotation for the slice.
    299     //
    300     switch (tileMode)
    301     {
    302         case ADDR_TM_3D_TILED_THIN1:    //fall through thin
    303         case ADDR_TM_3D_TILED_THICK:    //fall through thick
    304         case ADDR_TM_3D_TILED_XTHICK:
    305             sliceRotation =
    306                 Max(1, static_cast<INT_32>(numPipes / 2) - 1) * (slice / microTileThickness);
    307             break;
    308         default:
    309             sliceRotation = 0;
    310             break;
    311     }
    312     pipeSwizzle += sliceRotation;
    313     pipeSwizzle &= (numPipes - 1);
    314 
    315     pipe = pipe ^ pipeSwizzle;
    316 
    317     return pipe;
    318 }
    319 
    320 /**
    321 ***************************************************************************************************
    322 *   SIAddrLib::ComputeTileCoordFromPipeAndElemIdx
    323 *
    324 *   @brief
    325 *       Compute (x,y) of a tile within a macro tile from address
    326 *   @return
    327 *       Pipe number
    328 ***************************************************************************************************
    329 */
    330 VOID SIAddrLib::ComputeTileCoordFromPipeAndElemIdx(
    331     UINT_32         elemIdx,          ///< [in] per pipe element index within a macro tile
    332     UINT_32         pipe,             ///< [in] pipe index
    333     AddrPipeCfg     pipeCfg,          ///< [in] pipe config
    334     UINT_32         pitchInMacroTile, ///< [in] surface pitch in macro tile
    335     UINT_32         x,                ///< [in] x coordinate of the (0,0) tile in a macro tile
    336     UINT_32         y,                ///< [in] y coordinate of the (0,0) tile in a macro tile
    337     UINT_32*        pX,               ///< [out] x coordinate
    338     UINT_32*        pY                ///< [out] y coordinate
    339     ) const
    340 {
    341     UINT_32 pipebit0 = _BIT(pipe,0);
    342     UINT_32 pipebit1 = _BIT(pipe,1);
    343     UINT_32 pipebit2 = _BIT(pipe,2);
    344     UINT_32 pipebit3 = _BIT(pipe,3);
    345     UINT_32 elemIdx0 = _BIT(elemIdx,0);
    346     UINT_32 elemIdx1 = _BIT(elemIdx,1);
    347     UINT_32 elemIdx2 = _BIT(elemIdx,2);
    348     UINT_32 x3 = 0;
    349     UINT_32 x4 = 0;
    350     UINT_32 x5 = 0;
    351     UINT_32 x6 = 0;
    352     UINT_32 y3 = 0;
    353     UINT_32 y4 = 0;
    354     UINT_32 y5 = 0;
    355     UINT_32 y6 = 0;
    356 
    357     switch(pipeCfg)
    358     {
    359         case ADDR_PIPECFG_P2:
    360             x4 = elemIdx2;
    361             y4 = elemIdx1 ^ x4;
    362             y3 = elemIdx0 ^ x4;
    363             x3 = pipebit0 ^ y3;
    364             *pY = Bits2Number(2, y4, y3);
    365             *pX = Bits2Number(2, x4, x3);
    366             break;
    367         case ADDR_PIPECFG_P4_8x16:
    368             x4 = elemIdx1;
    369             y4 = elemIdx0 ^ x4;
    370             x3 = pipebit1 ^ y4;
    371             y3 = pipebit0 ^ x4;
    372             *pY = Bits2Number(2, y4, y3);
    373             *pX = Bits2Number(2, x4, x3);
    374             break;
    375         case ADDR_PIPECFG_P4_16x16:
    376             x4 = elemIdx1;
    377             y3 = elemIdx0 ^ x4;
    378             y4 = pipebit1 ^ x4;
    379             x3 = pipebit0 ^ y3 ^ x4;
    380             *pY = Bits2Number(2, y4, y3);
    381             *pX = Bits2Number(2, x4, x3);
    382             break;
    383         case ADDR_PIPECFG_P4_16x32:
    384             x3 = elemIdx0 ^ pipebit0;
    385             y5 = _BIT(y,5);
    386             x4 = pipebit1 ^ y5;
    387             y3 = pipebit0 ^ x3 ^ x4;
    388             y4 = elemIdx1 ^ x4;
    389             *pY = Bits2Number(2, y4, y3);
    390             *pX = Bits2Number(2, x4, x3);
    391             break;
    392         case ADDR_PIPECFG_P4_32x32:
    393             x4 = elemIdx2;
    394             y3 = elemIdx0 ^ x4;
    395             y4 = elemIdx1 ^ x4;
    396             if((pitchInMacroTile % 2) == 0)
    397             {   //even
    398                 y5 = _BIT(y,5);
    399                 x5 = pipebit1 ^ y5;
    400                 x3 = pipebit0 ^ y3 ^ x5;
    401                 *pY = Bits2Number(2, y4, y3);
    402                 *pX = Bits2Number(3, x5, x4, x3);
    403             }
    404             else
    405             {   //odd
    406                 x5 = _BIT(x,5);
    407                 x3 = pipebit0 ^ y3 ^ x5;
    408                 *pY = Bits2Number(2, y4, y3);
    409                 *pX = Bits2Number(2, x4, x3);
    410             }
    411             break;
    412         case ADDR_PIPECFG_P8_16x16_8x16:
    413             x4 = elemIdx0;
    414             y5 = _BIT(y,5);
    415             x5 = _BIT(x,5);
    416             x3 = pipebit1 ^ y5;
    417             y4 = pipebit2 ^ x4;
    418             y3 = pipebit0 ^ x5 ^ x4;
    419             *pY = Bits2Number(2, y4, y3);
    420             *pX = Bits2Number(2, x4, x3);
    421             break;
    422         case ADDR_PIPECFG_P8_16x32_8x16:
    423             x3 = elemIdx0;
    424             y4 = pipebit1 ^ x3;
    425             y5 = _BIT(y,5);
    426             x5 = _BIT(x,5);
    427             x4 = pipebit2 ^ y5;
    428             y3 = pipebit0 ^ x4 ^ x5;
    429             *pY = Bits2Number(2, y4, y3);
    430             *pX = Bits2Number(2, x4, x3);
    431             break;
    432         case ADDR_PIPECFG_P8_32x32_8x16:
    433             x4 = elemIdx1;
    434             y4 = elemIdx0 ^ x4;
    435             x3 = pipebit1 ^ y4;
    436             if((pitchInMacroTile % 2) == 0)
    437             {  //even
    438                 y5 = _BIT(y,5);
    439                 x5 = _BIT(x,5);
    440                 x5 = pipebit2 ^ y5;
    441                 y3 = pipebit0 ^ x4 ^ x5;
    442                 *pY = Bits2Number(2, y4, y3);
    443                 *pX = Bits2Number(3, x5, x4, x3);
    444             }
    445             else
    446             {  //odd
    447                 x5 = _BIT(x,5);
    448                 y3 = pipebit0 ^ x4 ^ x5;
    449                 *pY = Bits2Number(2, y4, y3);
    450                 *pX = Bits2Number(2, x4, x3);
    451             }
    452             break;
    453         case ADDR_PIPECFG_P8_16x32_16x16:
    454             x3 = elemIdx0;
    455             x5 = _BIT(x,5);
    456             y5 = _BIT(y,5);
    457             x4 = pipebit2 ^ y5;
    458             y4 = pipebit1 ^ x5;
    459             y3 = pipebit0 ^ x3 ^ x4;
    460             *pY = Bits2Number(2, y4, y3);
    461             *pX = Bits2Number(2, x4, x3);
    462             break;
    463         case ADDR_PIPECFG_P8_32x32_16x16:
    464             x4 = elemIdx1;
    465             y3 = elemIdx0 ^ x4;
    466             x3 = y3^x4^pipebit0;
    467             y4 = pipebit1 ^ x4;
    468             if((pitchInMacroTile % 2) == 0)
    469             {   //even
    470                 y5 = _BIT(y,5);
    471                 x5 = pipebit2 ^ y5;
    472                 *pY = Bits2Number(2, y4, y3);
    473                 *pX = Bits2Number(3, x5, x4, x3);
    474             }
    475             else
    476             {   //odd
    477                 *pY = Bits2Number(2, y4, y3);
    478                 *pX = Bits2Number(2, x4, x3);
    479             }
    480             break;
    481         case ADDR_PIPECFG_P8_32x32_16x32:
    482             if((pitchInMacroTile % 2) == 0)
    483             {   //even
    484                 y5 = _BIT(y,5);
    485                 y6 = _BIT(y,6);
    486                 x4 = pipebit1 ^ y6;
    487                 y3 = elemIdx0 ^ x4;
    488                 y4 = elemIdx1 ^ x4;
    489                 x3 = pipebit0 ^ y3 ^ x4;
    490                 x5 = pipebit2 ^ y5;
    491                 *pY = Bits2Number(2, y4, y3);
    492                 *pX = Bits2Number(3, x5, x4, x3);
    493             }
    494             else
    495             {   //odd
    496                 y6 = _BIT(y,6);
    497                 x4 = pipebit1 ^ y6;
    498                 y3 = elemIdx0 ^ x4;
    499                 y4 = elemIdx1 ^ x4;
    500                 x3 = pipebit0 ^ y3 ^ x4;
    501                 *pY = Bits2Number(2, y4, y3);
    502                 *pX = Bits2Number(2, x4, x3);
    503             }
    504             break;
    505         case ADDR_PIPECFG_P8_32x64_32x32:
    506             x4 = elemIdx2;
    507             y3 = elemIdx0 ^ x4;
    508             y4 = elemIdx1 ^ x4;
    509             if((pitchInMacroTile % 4) == 0)
    510             {   //multiple of 4
    511                 y5 = _BIT(y,5);
    512                 y6 = _BIT(y,6);
    513                 x5 = pipebit2 ^ y6;
    514                 x6 = pipebit1 ^ y5;
    515                 x3 = pipebit0 ^ y3 ^ x5;
    516                 *pY = Bits2Number(2, y4, y3);
    517                 *pX = Bits2Number(4, x6, x5, x4, x3);
    518             }
    519             else
    520             {
    521                 y6 = _BIT(y,6);
    522                 x5 = pipebit2 ^ y6;
    523                 x3 = pipebit0 ^ y3 ^ x5;
    524                 *pY = Bits2Number(2, y4, y3);
    525                 *pX = Bits2Number(3, x5, x4, x3);
    526             }
    527             break;
    528         case ADDR_PIPECFG_P16_32x32_8x16:
    529             x4 = elemIdx1;
    530             y4 = elemIdx0 ^ x4;
    531             y3 = pipebit0 ^ x4;
    532             x3 = pipebit1 ^ y4;
    533             if((pitchInMacroTile % 4) == 0)
    534             {   //multiple of 4
    535                 y5 = _BIT(y,5);
    536                 y6 = _BIT(y,6);
    537                 x5 = pipebit2 ^ y6;
    538                 x6 = pipebit3 ^ y5;
    539                 *pY = Bits2Number(2, y4, y3);
    540                 *pX = Bits2Number(4, x6, x5,x4, x3);
    541             }
    542             else
    543             {
    544                 y6 = _BIT(y,6);
    545                 x5 = pipebit2 ^ y6;
    546                 *pY = Bits2Number(2, y4, y3);
    547                 *pX = Bits2Number(3, x5, x4, x3);
    548             }
    549             break;
    550         case ADDR_PIPECFG_P16_32x32_16x16:
    551             x4 = elemIdx1;
    552             y3 = elemIdx0 ^ x4;
    553             y4 = pipebit1 ^ x4;
    554             x3 = pipebit0 ^ y3 ^ x4;
    555             if((pitchInMacroTile % 4) == 0)
    556             {   //multiple of 4
    557                 y5 = _BIT(y,5);
    558                 y6 = _BIT(y,6);
    559                 x5 = pipebit2 ^ y6;
    560                 x6 = pipebit3 ^ y5;
    561                 *pY = Bits2Number(2, y4, y3);
    562                 *pX = Bits2Number(4, x6, x5, x4, x3);
    563             }
    564             else
    565             {
    566                 y6 = _BIT(y,6);
    567                 x5 = pipebit2 ^ y6;
    568                 *pY = Bits2Number(2, y4, y3);
    569                 *pX = Bits2Number(3, x5, x4, x3);
    570             }
    571             break;
    572         default:
    573             ADDR_UNHANDLED_CASE();
    574     }
    575 }
    576 
    577 /**
    578 ***************************************************************************************************
    579 *   SIAddrLib::TileCoordToMaskElementIndex
    580 *
    581 *   @brief
    582 *       Compute element index from coordinates in tiles
    583 *   @return
    584 *       Element index
    585 ***************************************************************************************************
    586 */
    587 UINT_32 SIAddrLib::TileCoordToMaskElementIndex(
    588     UINT_32         tx,                 ///< [in] x coord, in Tiles
    589     UINT_32         ty,                 ///< [in] y coord, in Tiles
    590     AddrPipeCfg     pipeConfig,         ///< [in] pipe config
    591     UINT_32*        macroShift,         ///< [out] macro shift
    592     UINT_32*        elemIdxBits         ///< [out] tile offset bits
    593     ) const
    594 {
    595     UINT_32 elemIdx = 0;
    596     UINT_32 elemIdx0, elemIdx1, elemIdx2;
    597     UINT_32 tx0, tx1;
    598     UINT_32 ty0, ty1;
    599 
    600     tx0 = _BIT(tx,0);
    601     tx1 = _BIT(tx,1);
    602     ty0 = _BIT(ty,0);
    603     ty1 = _BIT(ty,1);
    604 
    605     switch(pipeConfig)
    606     {
    607         case ADDR_PIPECFG_P2:
    608             *macroShift = 3;
    609             *elemIdxBits =3;
    610             elemIdx2 = tx1;
    611             elemIdx1 = tx1 ^ ty1;
    612             elemIdx0 = tx1 ^ ty0;
    613             elemIdx = Bits2Number(3,elemIdx2,elemIdx1,elemIdx0);
    614             break;
    615         case ADDR_PIPECFG_P4_8x16:
    616             *macroShift = 2;
    617             *elemIdxBits =2;
    618             elemIdx1 = tx1;
    619             elemIdx0 = tx1 ^ ty1;
    620             elemIdx = Bits2Number(2,elemIdx1,elemIdx0);
    621             break;
    622         case ADDR_PIPECFG_P4_16x16:
    623             *macroShift = 2;
    624             *elemIdxBits =2;
    625             elemIdx0 = tx1^ty0;
    626             elemIdx1 = tx1;
    627             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
    628             break;
    629         case ADDR_PIPECFG_P4_16x32:
    630             *macroShift = 2;
    631             *elemIdxBits =2;
    632             elemIdx0 = tx1^ty0;
    633             elemIdx1 = tx1^ty1;
    634             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
    635             break;
    636         case ADDR_PIPECFG_P4_32x32:
    637             *macroShift = 2;
    638             *elemIdxBits =3;
    639             elemIdx0 = tx1^ty0;
    640             elemIdx1 = tx1^ty1;
    641             elemIdx2 = tx1;
    642             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
    643             break;
    644         case ADDR_PIPECFG_P8_16x16_8x16:
    645             *macroShift = 1;
    646             *elemIdxBits =1;
    647             elemIdx0 = tx1;
    648             elemIdx = elemIdx0;
    649             break;
    650         case ADDR_PIPECFG_P8_16x32_8x16:
    651             *macroShift = 1;
    652             *elemIdxBits =1;
    653             elemIdx0 = tx0;
    654             elemIdx = elemIdx0;
    655             break;
    656         case ADDR_PIPECFG_P8_32x32_8x16:
    657             *macroShift = 1;
    658             *elemIdxBits =2;
    659             elemIdx1 = tx1;
    660             elemIdx0 = tx1^ty1;
    661             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
    662             break;
    663         case ADDR_PIPECFG_P8_16x32_16x16:
    664             *macroShift = 1;
    665             *elemIdxBits =1;
    666             elemIdx0 = tx0;
    667             elemIdx = elemIdx0;
    668             break;
    669         case ADDR_PIPECFG_P8_32x32_16x16:
    670             *macroShift = 1;
    671             *elemIdxBits =2;
    672             elemIdx0 = tx1^ty0;
    673             elemIdx1 = tx1;
    674             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
    675             break;
    676         case ADDR_PIPECFG_P8_32x32_16x32:
    677             *macroShift = 1;
    678             *elemIdxBits =2;
    679             elemIdx0 =  tx1^ty0;
    680             elemIdx1 = tx1^ty1;
    681             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
    682             break;
    683         case ADDR_PIPECFG_P8_32x64_32x32:
    684             *macroShift = 1;
    685             *elemIdxBits =3;
    686             elemIdx0 = tx1^ty0;
    687             elemIdx1 = tx1^ty1;
    688             elemIdx2 = tx1;
    689             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
    690             break;
    691         case ADDR_PIPECFG_P16_32x32_8x16:
    692             *macroShift = 0;
    693             *elemIdxBits =2;
    694             elemIdx0 = tx1^ty1;
    695             elemIdx1 = tx1;
    696             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
    697             break;
    698         case ADDR_PIPECFG_P16_32x32_16x16:
    699             *macroShift = 0;
    700             *elemIdxBits =2;
    701             elemIdx0 = tx1^ty0;
    702             elemIdx1 = tx1;
    703             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
    704             break;
    705         default:
    706             ADDR_UNHANDLED_CASE();
    707             break;
    708     }
    709 
    710     return elemIdx;
    711 }
    712 
    713 /**
    714 ***************************************************************************************************
    715 *   SIAddrLib::HwlComputeTileDataWidthAndHeightLinear
    716 *
    717 *   @brief
    718 *       Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
    719 *
    720 *   @return
    721 *       N/A
    722 *
    723 *   @note
    724 *       MacroWidth and macroHeight are measured in pixels
    725 ***************************************************************************************************
    726 */
    727 VOID SIAddrLib::HwlComputeTileDataWidthAndHeightLinear(
    728     UINT_32*        pMacroWidth,     ///< [out] macro tile width
    729     UINT_32*        pMacroHeight,    ///< [out] macro tile height
    730     UINT_32         bpp,             ///< [in] bits per pixel
    731     ADDR_TILEINFO*  pTileInfo        ///< [in] tile info
    732     ) const
    733 {
    734     ADDR_ASSERT(pTileInfo != NULL);
    735     UINT_32 macroWidth;
    736     UINT_32 macroHeight;
    737 
    738     /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles
    739     /// but for P8_32x64_32x32, it must be padded out to 8 tiles
    740     /// Actually there are more pipe configs which need 8-tile padding but SI family
    741     /// has a bug which is fixed in CI family
    742     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) ||
    743         (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
    744         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x32_16x16))
    745     {
    746         macroWidth  = 8*MicroTileWidth;
    747         macroHeight = 8*MicroTileHeight;
    748     }
    749     else
    750     {
    751         macroWidth  = 4*MicroTileWidth;
    752         macroHeight = 4*MicroTileHeight;
    753     }
    754 
    755     *pMacroWidth    = macroWidth;
    756     *pMacroHeight   = macroHeight;
    757 }
    758 
    759 /**
    760 ***************************************************************************************************
    761 *   SIAddrLib::HwlComputeHtileBytes
    762 *
    763 *   @brief
    764 *       Compute htile size in bytes
    765 *
    766 *   @return
    767 *       Htile size in bytes
    768 ***************************************************************************************************
    769 */
    770 UINT_64 SIAddrLib::HwlComputeHtileBytes(
    771     UINT_32     pitch,          ///< [in] pitch
    772     UINT_32     height,         ///< [in] height
    773     UINT_32     bpp,            ///< [in] bits per pixel
    774     BOOL_32     isLinear,       ///< [in] if it is linear mode
    775     UINT_32     numSlices,      ///< [in] number of slices
    776     UINT_64*    pSliceBytes,    ///< [out] bytes per slice
    777     UINT_32     baseAlign       ///< [in] base alignments
    778     ) const
    779 {
    780     return ComputeHtileBytes(pitch, height, bpp, isLinear, numSlices, pSliceBytes, baseAlign);
    781 }
    782 
    783 /**
    784 ***************************************************************************************************
    785 *   SIAddrLib::HwlComputeXmaskAddrFromCoord
    786 *
    787 *   @brief
    788 *       Compute address from coordinates for htile/cmask
    789 *   @return
    790 *       Byte address
    791 ***************************************************************************************************
    792 */
    793 UINT_64 SIAddrLib::HwlComputeXmaskAddrFromCoord(
    794     UINT_32        pitch,          ///< [in] pitch
    795     UINT_32        height,         ///< [in] height
    796     UINT_32        x,              ///< [in] x coord
    797     UINT_32        y,              ///< [in] y coord
    798     UINT_32        slice,          ///< [in] slice/depth index
    799     UINT_32        numSlices,      ///< [in] number of slices
    800     UINT_32        factor,         ///< [in] factor that indicates cmask(2) or htile(1)
    801     BOOL_32        isLinear,       ///< [in] linear or tiled HTILE layout
    802     BOOL_32        isWidth8,       ///< [in] TRUE if width is 8, FALSE means 4. It's register value
    803     BOOL_32        isHeight8,      ///< [in] TRUE if width is 8, FALSE means 4. It's register value
    804     ADDR_TILEINFO* pTileInfo,      ///< [in] Tile info
    805     UINT_32*       pBitPosition    ///< [out] bit position inside a byte
    806     ) const
    807 {
    808     UINT_32 tx = x / MicroTileWidth;
    809     UINT_32 ty = y / MicroTileHeight;
    810     UINT_32 newPitch;
    811     UINT_32 newHeight;
    812     UINT_64 totalBytes;
    813     UINT_32 macroWidth;
    814     UINT_32 macroHeight;
    815     UINT_64 pSliceBytes;
    816     UINT_32 pBaseAlign;
    817     UINT_32 tileNumPerPipe;
    818     UINT_32 elemBits;
    819 
    820     if (factor == 2) //CMASK
    821     {
    822         ADDR_CMASK_FLAGS flags = {{0}};
    823 
    824         tileNumPerPipe = 256;
    825 
    826         ComputeCmaskInfo(flags,
    827                          pitch,
    828                          height,
    829                          numSlices,
    830                          isLinear,
    831                          pTileInfo,
    832                          &newPitch,
    833                          &newHeight,
    834                          &totalBytes,
    835                          &macroWidth,
    836                          &macroHeight);
    837         elemBits = CmaskElemBits;
    838     }
    839     else //HTile
    840     {
    841         ADDR_HTILE_FLAGS flags = {{0}};
    842 
    843         tileNumPerPipe = 512;
    844 
    845         ComputeHtileInfo(flags,
    846                          pitch,
    847                          height,
    848                          numSlices,
    849                          isLinear,
    850                          TRUE,
    851                          TRUE,
    852                          pTileInfo,
    853                          &newPitch,
    854                          &newHeight,
    855                          &totalBytes,
    856                          &macroWidth,
    857                          &macroHeight,
    858                          &pSliceBytes,
    859                          &pBaseAlign);
    860         elemBits = 32;
    861     }
    862 
    863     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
    864     const UINT_32 heightInTile = newHeight / MicroTileWidth;
    865     UINT_64 macroOffset; // Per pipe starting offset of the macro tile in which this tile lies.
    866     UINT_64 microNumber; // Per pipe starting offset of the macro tile in which this tile lies.
    867     UINT_32 microX;
    868     UINT_32 microY;
    869     UINT_64 microOffset;
    870     UINT_32 microShift;
    871     UINT_64 totalOffset;
    872     UINT_32 elemIdxBits;
    873     UINT_32 elemIdx =
    874         TileCoordToMaskElementIndex(tx, ty, pTileInfo->pipeConfig, &microShift, &elemIdxBits);
    875 
    876     UINT_32 numPipes = HwlGetPipes(pTileInfo);
    877 
    878     if (isLinear)
    879     {   //linear addressing
    880         // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full
    881         // slice memory foot print instead of divided by numPipes.
    882         microX = tx / 4; // Macro Tile is 4x4
    883         microY = ty / 4 ;
    884         microNumber = static_cast<UINT_64>(microX + microY * (pitchInTile / 4)) << microShift;
    885 
    886         UINT_32 sliceBits = pitchInTile * heightInTile;
    887 
    888         // do htile single slice alignment if the flag is true
    889         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
    890         {
    891             sliceBits = PowTwoAlign(sliceBits, BITS_TO_BYTES(HtileCacheBits) * numPipes / elemBits);
    892         }
    893         macroOffset = slice * (sliceBits / numPipes) * elemBits ;
    894     }
    895     else
    896     {   //tiled addressing
    897         const UINT_32 macroWidthInTile = macroWidth / MicroTileWidth; // Now in unit of Tiles
    898         const UINT_32 macroHeightInTile = macroHeight / MicroTileHeight;
    899         const UINT_32 pitchInCL = pitchInTile / macroWidthInTile;
    900         const UINT_32 heightInCL = heightInTile / macroHeightInTile;
    901 
    902         const UINT_32 macroX = x / macroWidth;
    903         const UINT_32 macroY = y / macroHeight;
    904         const UINT_32 macroNumber = macroX + macroY * pitchInCL + slice * pitchInCL * heightInCL;
    905 
    906         // Per pipe starting offset of the cache line in which this tile lies.
    907         microX = (x % macroWidth) / MicroTileWidth / 4; // Macro Tile is 4x4
    908         microY = (y % macroHeight) / MicroTileHeight / 4 ;
    909         microNumber = static_cast<UINT_64>(microX + microY * (macroWidth / MicroTileWidth / 4)) << microShift;
    910 
    911         macroOffset = macroNumber * tileNumPerPipe * elemBits;
    912     }
    913 
    914     if(elemIdxBits == microShift)
    915     {
    916         microNumber += elemIdx;
    917     }
    918     else
    919     {
    920         microNumber >>= elemIdxBits;
    921         microNumber <<= elemIdxBits;
    922         microNumber += elemIdx;
    923     }
    924 
    925     microOffset = elemBits * microNumber;
    926     totalOffset = microOffset + macroOffset;
    927 
    928     UINT_32 pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo);
    929     UINT_64 addrInBits = totalOffset % (m_pipeInterleaveBytes * 8) +
    930                    pipe * (m_pipeInterleaveBytes * 8) +
    931                    totalOffset / (m_pipeInterleaveBytes * 8) * (m_pipeInterleaveBytes * 8) * numPipes;
    932     *pBitPosition = static_cast<UINT_32>(addrInBits) % 8;
    933     UINT_64 addr = addrInBits / 8;
    934 
    935     return addr;
    936 }
    937 
    938 /**
    939 ***************************************************************************************************
    940 *   SIAddrLib::HwlComputeXmaskCoordFromAddr
    941 *
    942 *   @brief
    943 *       Compute the coord from an address of a cmask/htile
    944 *
    945 *   @return
    946 *       N/A
    947 *
    948 *   @note
    949 *       This method is reused by htile, so rename to Xmask
    950 ***************************************************************************************************
    951 */
    952 VOID SIAddrLib::HwlComputeXmaskCoordFromAddr(
    953     UINT_64         addr,           ///< [in] address
    954     UINT_32         bitPosition,    ///< [in] bitPosition in a byte
    955     UINT_32         pitch,          ///< [in] pitch
    956     UINT_32         height,         ///< [in] height
    957     UINT_32         numSlices,      ///< [in] number of slices
    958     UINT_32         factor,         ///< [in] factor that indicates cmask or htile
    959     BOOL_32         isLinear,       ///< [in] linear or tiled HTILE layout
    960     BOOL_32         isWidth8,       ///< [in] Not used by SI
    961     BOOL_32         isHeight8,      ///< [in] Not used by SI
    962     ADDR_TILEINFO*  pTileInfo,      ///< [in] Tile info
    963     UINT_32*        pX,             ///< [out] x coord
    964     UINT_32*        pY,             ///< [out] y coord
    965     UINT_32*        pSlice          ///< [out] slice index
    966     ) const
    967 {
    968     UINT_32 newPitch;
    969     UINT_32 newHeight;
    970     UINT_64 totalBytes;
    971     UINT_32 clWidth;
    972     UINT_32 clHeight;
    973     UINT_32 tileNumPerPipe;
    974     UINT_64 sliceBytes;
    975 
    976     *pX = 0;
    977     *pY = 0;
    978     *pSlice = 0;
    979 
    980     if (factor == 2) //CMASK
    981     {
    982         ADDR_CMASK_FLAGS flags = {{0}};
    983 
    984         tileNumPerPipe = 256;
    985 
    986         ComputeCmaskInfo(flags,
    987                          pitch,
    988                          height,
    989                          numSlices,
    990                          isLinear,
    991                          pTileInfo,
    992                          &newPitch,
    993                          &newHeight,
    994                          &totalBytes,
    995                          &clWidth,
    996                          &clHeight);
    997     }
    998     else //HTile
    999     {
   1000         ADDR_HTILE_FLAGS flags = {{0}};
   1001 
   1002         tileNumPerPipe = 512;
   1003 
   1004         ComputeHtileInfo(flags,
   1005                          pitch,
   1006                          height,
   1007                          numSlices,
   1008                          isLinear,
   1009                          TRUE,
   1010                          TRUE,
   1011                          pTileInfo,
   1012                          &newPitch,
   1013                          &newHeight,
   1014                          &totalBytes,
   1015                          &clWidth,
   1016                          &clHeight,
   1017                          &sliceBytes);
   1018     }
   1019 
   1020     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
   1021     const UINT_32 heightInTile = newHeight / MicroTileWidth;
   1022     const UINT_32 pitchInMacroTile = pitchInTile / 4;
   1023     UINT_32 macroShift;
   1024     UINT_32 elemIdxBits;
   1025     // get macroShift and elemIdxBits
   1026     TileCoordToMaskElementIndex(0, 0, pTileInfo->pipeConfig, &macroShift, &elemIdxBits);
   1027 
   1028     const UINT_32 numPipes = HwlGetPipes(pTileInfo);
   1029     const UINT_32 pipe = (UINT_32)((addr / m_pipeInterleaveBytes) % numPipes);
   1030     // per pipe
   1031     UINT_64 localOffset = (addr % m_pipeInterleaveBytes) +
   1032         (addr / m_pipeInterleaveBytes / numPipes)* m_pipeInterleaveBytes;
   1033 
   1034     UINT_32 tileIndex;
   1035     if (factor == 2) //CMASK
   1036     {
   1037         tileIndex = (UINT_32)(localOffset * 2 + (bitPosition != 0));
   1038     }
   1039     else
   1040     {
   1041         tileIndex = (UINT_32)(localOffset / 4);
   1042     }
   1043 
   1044     UINT_32 macroOffset;
   1045     if (isLinear)
   1046     {
   1047         UINT_32 sliceSizeInTile = pitchInTile * heightInTile;
   1048 
   1049         // do htile single slice alignment if the flag is true
   1050         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
   1051         {
   1052             sliceSizeInTile = PowTwoAlign(sliceSizeInTile, static_cast<UINT_32>(sliceBytes) / 64);
   1053         }
   1054         *pSlice = tileIndex / (sliceSizeInTile / numPipes);
   1055         macroOffset = tileIndex % (sliceSizeInTile / numPipes);
   1056     }
   1057     else
   1058     {
   1059         const UINT_32 clWidthInTile = clWidth / MicroTileWidth; // Now in unit of Tiles
   1060         const UINT_32 clHeightInTile = clHeight / MicroTileHeight;
   1061         const UINT_32 pitchInCL = pitchInTile / clWidthInTile;
   1062         const UINT_32 heightInCL = heightInTile / clHeightInTile;
   1063         const UINT_32 clIndex = tileIndex / tileNumPerPipe;
   1064 
   1065         UINT_32 clX = clIndex % pitchInCL;
   1066         UINT_32 clY = (clIndex % (heightInCL * pitchInCL)) / pitchInCL;
   1067 
   1068         *pX = clX * clWidthInTile * MicroTileWidth;
   1069         *pY = clY * clHeightInTile * MicroTileHeight;
   1070         *pSlice = clIndex / (heightInCL * pitchInCL);
   1071 
   1072         macroOffset = tileIndex % tileNumPerPipe;
   1073     }
   1074 
   1075     UINT_32 elemIdx = macroOffset & 7;
   1076     macroOffset >>= elemIdxBits;
   1077 
   1078     if (elemIdxBits != macroShift)
   1079     {
   1080         macroOffset <<= (elemIdxBits - macroShift);
   1081 
   1082         UINT_32 pipebit1 = _BIT(pipe,1);
   1083         UINT_32 pipebit2 = _BIT(pipe,2);
   1084         UINT_32 pipebit3 = _BIT(pipe,3);
   1085         if (pitchInMacroTile % 2)
   1086         {   //odd
   1087             switch (pTileInfo->pipeConfig)
   1088             {
   1089                 case ADDR_PIPECFG_P4_32x32:
   1090                     macroOffset |= pipebit1;
   1091                     break;
   1092                 case ADDR_PIPECFG_P8_32x32_8x16:
   1093                 case ADDR_PIPECFG_P8_32x32_16x16:
   1094                 case ADDR_PIPECFG_P8_32x32_16x32:
   1095                     macroOffset |= pipebit2;
   1096                     break;
   1097                 default:
   1098                     break;
   1099             }
   1100 
   1101         }
   1102 
   1103         if (pitchInMacroTile % 4)
   1104         {
   1105             if (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)
   1106             {
   1107                 macroOffset |= (pipebit1<<1);
   1108             }
   1109             if((pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
   1110                (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_16x16))
   1111             {
   1112                 macroOffset |= (pipebit3<<1);
   1113             }
   1114         }
   1115     }
   1116 
   1117     UINT_32 macroX;
   1118     UINT_32 macroY;
   1119 
   1120     if (isLinear)
   1121     {
   1122         macroX = macroOffset % pitchInMacroTile;
   1123         macroY = macroOffset / pitchInMacroTile;
   1124     }
   1125     else
   1126     {
   1127         const UINT_32 clWidthInMacroTile = clWidth / (MicroTileWidth * 4);
   1128         macroX = macroOffset % clWidthInMacroTile;
   1129         macroY = macroOffset / clWidthInMacroTile;
   1130     }
   1131 
   1132     *pX += macroX * 4 * MicroTileWidth;
   1133     *pY += macroY * 4 * MicroTileHeight;
   1134 
   1135     UINT_32 microX;
   1136     UINT_32 microY;
   1137     ComputeTileCoordFromPipeAndElemIdx(elemIdx, pipe, pTileInfo->pipeConfig, pitchInMacroTile,
   1138                                        *pX, *pY, &microX, &microY);
   1139 
   1140     *pX += microX * MicroTileWidth;
   1141     *pY += microY * MicroTileWidth;
   1142 }
   1143 
   1144 /**
   1145 ***************************************************************************************************
   1146 *   SIAddrLib::HwlGetPitchAlignmentLinear
   1147 *   @brief
   1148 *       Get pitch alignment
   1149 *   @return
   1150 *       pitch alignment
   1151 ***************************************************************************************************
   1152 */
   1153 UINT_32 SIAddrLib::HwlGetPitchAlignmentLinear(
   1154     UINT_32             bpp,    ///< [in] bits per pixel
   1155     ADDR_SURFACE_FLAGS  flags   ///< [in] surface flags
   1156     ) const
   1157 {
   1158     UINT_32 pitchAlign;
   1159 
   1160     // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment
   1161     if (flags.interleaved)
   1162     {
   1163         pitchAlign = Max(64u, m_pipeInterleaveBytes / BITS_TO_BYTES(bpp));
   1164 
   1165     }
   1166     else
   1167     {
   1168         pitchAlign = Max(8u, 64 / BITS_TO_BYTES(bpp));
   1169     }
   1170 
   1171     return pitchAlign;
   1172 }
   1173 
   1174 /**
   1175 ***************************************************************************************************
   1176 *   SIAddrLib::HwlGetSizeAdjustmentLinear
   1177 *
   1178 *   @brief
   1179 *       Adjust linear surface pitch and slice size
   1180 *
   1181 *   @return
   1182 *       Logical slice size in bytes
   1183 ***************************************************************************************************
   1184 */
   1185 UINT_64 SIAddrLib::HwlGetSizeAdjustmentLinear(
   1186     AddrTileMode        tileMode,       ///< [in] tile mode
   1187     UINT_32             bpp,            ///< [in] bits per pixel
   1188     UINT_32             numSamples,     ///< [in] number of samples
   1189     UINT_32             baseAlign,      ///< [in] base alignment
   1190     UINT_32             pitchAlign,     ///< [in] pitch alignment
   1191     UINT_32*            pPitch,         ///< [in/out] pointer to pitch
   1192     UINT_32*            pHeight,        ///< [in/out] pointer to height
   1193     UINT_32*            pHeightAlign    ///< [in/out] pointer to height align
   1194     ) const
   1195 {
   1196     UINT_64 sliceSize;
   1197     if (tileMode == ADDR_TM_LINEAR_GENERAL)
   1198     {
   1199         sliceSize = BITS_TO_BYTES(static_cast<UINT_64>(*pPitch) * (*pHeight) * bpp * numSamples);
   1200     }
   1201     else
   1202     {
   1203         UINT_32 pitch   = *pPitch;
   1204         UINT_32 height  = *pHeight;
   1205 
   1206         UINT_32 pixelsPerPipeInterleave = m_pipeInterleaveBytes / BITS_TO_BYTES(bpp);
   1207         UINT_32 sliceAlignInPixel = pixelsPerPipeInterleave < 64 ? 64 : pixelsPerPipeInterleave;
   1208 
   1209         // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value)
   1210         UINT_64 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
   1211 
   1212         while (pixelPerSlice % sliceAlignInPixel)
   1213         {
   1214             pitch += pitchAlign;
   1215             pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
   1216         }
   1217 
   1218         *pPitch = pitch;
   1219 
   1220         UINT_32 heightAlign = 1;
   1221 
   1222         while ((pitch * heightAlign) % sliceAlignInPixel)
   1223         {
   1224             heightAlign++;
   1225         }
   1226 
   1227         *pHeightAlign = heightAlign;
   1228 
   1229         sliceSize = BITS_TO_BYTES(pixelPerSlice * bpp);
   1230     }
   1231 
   1232     return sliceSize;
   1233 }
   1234 
   1235 /**
   1236 ***************************************************************************************************
   1237 *   SIAddrLib::HwlPreHandleBaseLvl3xPitch
   1238 *
   1239 *   @brief
   1240 *       Pre-handler of 3x pitch (96 bit) adjustment
   1241 *
   1242 *   @return
   1243 *       Expected pitch
   1244 ***************************************************************************************************
   1245 */
   1246 UINT_32 SIAddrLib::HwlPreHandleBaseLvl3xPitch(
   1247     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
   1248     UINT_32                                 expPitch    ///< [in] pitch
   1249     ) const
   1250 {
   1251     ADDR_ASSERT(pIn->width == expPitch);
   1252 
   1253     // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to
   1254     // do here
   1255     if (!pIn->flags.pow2Pad)
   1256     {
   1257         AddrLib::HwlPreHandleBaseLvl3xPitch(pIn, expPitch);
   1258     }
   1259     else
   1260     {
   1261         ADDR_ASSERT(IsPow2(expPitch));
   1262     }
   1263 
   1264     return expPitch;
   1265 }
   1266 
   1267 /**
   1268 ***************************************************************************************************
   1269 *   SIAddrLib::HwlPostHandleBaseLvl3xPitch
   1270 *
   1271 *   @brief
   1272 *       Post-handler of 3x pitch adjustment
   1273 *
   1274 *   @return
   1275 *       Expected pitch
   1276 ***************************************************************************************************
   1277 */
   1278 UINT_32 SIAddrLib::HwlPostHandleBaseLvl3xPitch(
   1279     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
   1280     UINT_32                                 expPitch    ///< [in] pitch
   1281     ) const
   1282 {
   1283     /**
   1284      * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should
   1285      *  be able to compute a correct pitch from it as h/w address library is doing the job.
   1286      */
   1287     // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here
   1288     if (!pIn->flags.pow2Pad)
   1289     {
   1290         AddrLib::HwlPostHandleBaseLvl3xPitch(pIn, expPitch);
   1291     }
   1292 
   1293     return expPitch;
   1294 }
   1295 
   1296 /**
   1297 ***************************************************************************************************
   1298 *   SIAddrLib::HwlGetPitchAlignmentMicroTiled
   1299 *
   1300 *   @brief
   1301 *       Compute 1D tiled surface pitch alignment
   1302 *
   1303 *   @return
   1304 *       pitch alignment
   1305 ***************************************************************************************************
   1306 */
   1307 UINT_32 SIAddrLib::HwlGetPitchAlignmentMicroTiled(
   1308     AddrTileMode        tileMode,          ///< [in] tile mode
   1309     UINT_32             bpp,               ///< [in] bits per pixel
   1310     ADDR_SURFACE_FLAGS  flags,             ///< [in] surface flags
   1311     UINT_32             numSamples         ///< [in] number of samples
   1312     ) const
   1313 {
   1314     UINT_32 pitchAlign;
   1315 
   1316     if (flags.qbStereo)
   1317     {
   1318         pitchAlign = EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled(tileMode,bpp,flags,numSamples);
   1319     }
   1320     else
   1321     {
   1322         pitchAlign = 8;
   1323     }
   1324 
   1325     return pitchAlign;
   1326 }
   1327 
   1328 /**
   1329 ***************************************************************************************************
   1330 *   SIAddrLib::HwlGetSizeAdjustmentMicroTiled
   1331 *
   1332 *   @brief
   1333 *       Adjust 1D tiled surface pitch and slice size
   1334 *
   1335 *   @return
   1336 *       Logical slice size in bytes
   1337 ***************************************************************************************************
   1338 */
   1339 UINT_64 SIAddrLib::HwlGetSizeAdjustmentMicroTiled(
   1340     UINT_32             thickness,      ///< [in] thickness
   1341     UINT_32             bpp,            ///< [in] bits per pixel
   1342     ADDR_SURFACE_FLAGS  flags,          ///< [in] surface flags
   1343     UINT_32             numSamples,     ///< [in] number of samples
   1344     UINT_32             baseAlign,      ///< [in] base alignment
   1345     UINT_32             pitchAlign,     ///< [in] pitch alignment
   1346     UINT_32*            pPitch,         ///< [in/out] pointer to pitch
   1347     UINT_32*            pHeight         ///< [in/out] pointer to height
   1348     ) const
   1349 {
   1350     UINT_64 logicalSliceSize;
   1351     UINT_64 physicalSliceSize;
   1352 
   1353     UINT_32 pitch   = *pPitch;
   1354     UINT_32 height  = *pHeight;
   1355 
   1356     // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1)
   1357     logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
   1358 
   1359     // Physical slice: multiplied by thickness
   1360     physicalSliceSize =  logicalSliceSize * thickness;
   1361 
   1362     // Pitch alignment is always 8, so if slice size is not padded to base alignment
   1363     // (pipe_interleave_size), we need to increase pitch
   1364     while ((physicalSliceSize % baseAlign) != 0)
   1365     {
   1366         pitch += pitchAlign;
   1367 
   1368         logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
   1369 
   1370         physicalSliceSize =  logicalSliceSize * thickness;
   1371     }
   1372 
   1373 #if !ALT_TEST
   1374     //
   1375     // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since
   1376     // the stencil plane may have larger pitch if the slice size is smaller than base alignment.
   1377     //
   1378     // Note: this actually does not work for mipmap but mipmap depth texture is not really
   1379     // sampled with mipmap.
   1380     //
   1381     if (flags.depth && !flags.noStencil)
   1382     {
   1383         ADDR_ASSERT(numSamples == 1);
   1384 
   1385         UINT_64 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; // 1 byte stencil
   1386 
   1387         while ((logicalSiceSizeStencil % baseAlign) != 0)
   1388         {
   1389             pitch += pitchAlign; // Stencil plane's pitch alignment is the same as depth plane's
   1390 
   1391             logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height;
   1392         }
   1393 
   1394         if (pitch != *pPitch)
   1395         {
   1396             // If this is a mipmap, this padded one cannot be sampled as a whole mipmap!
   1397             logicalSliceSize = logicalSiceSizeStencil * BITS_TO_BYTES(bpp);
   1398         }
   1399     }
   1400 #endif
   1401     *pPitch = pitch;
   1402 
   1403     // No adjust for pHeight
   1404 
   1405     return logicalSliceSize;
   1406 }
   1407 
   1408 /**
   1409 ***************************************************************************************************
   1410 *   SIAddrLib::HwlConvertChipFamily
   1411 *
   1412 *   @brief
   1413 *       Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision
   1414 *   @return
   1415 *       AddrChipFamily
   1416 ***************************************************************************************************
   1417 */
   1418 AddrChipFamily SIAddrLib::HwlConvertChipFamily(
   1419     UINT_32 uChipFamily,        ///< [in] chip family defined in atiih.h
   1420     UINT_32 uChipRevision)      ///< [in] chip revision defined in "asic_family"_id.h
   1421 {
   1422     AddrChipFamily family = ADDR_CHIP_FAMILY_SI;
   1423 
   1424     switch (uChipFamily)
   1425     {
   1426         case FAMILY_SI:
   1427             m_settings.isSouthernIsland = 1;
   1428             m_settings.isTahiti     = ASICREV_IS_TAHITI_P(uChipRevision);
   1429             m_settings.isPitCairn   = ASICREV_IS_PITCAIRN_PM(uChipRevision);
   1430             m_settings.isCapeVerde  = ASICREV_IS_CAPEVERDE_M(uChipRevision);
   1431             m_settings.isOland      = ASICREV_IS_OLAND_M(uChipRevision);
   1432             m_settings.isHainan     = ASICREV_IS_HAINAN_V(uChipRevision);
   1433             break;
   1434         default:
   1435             ADDR_ASSERT(!"This should be a Fusion");
   1436             break;
   1437     }
   1438 
   1439     return family;
   1440 }
   1441 
   1442 /**
   1443 ***************************************************************************************************
   1444 *   SIAddrLib::HwlSetupTileInfo
   1445 *
   1446 *   @brief
   1447 *       Setup default value of tile info for SI
   1448 ***************************************************************************************************
   1449 */
   1450 VOID SIAddrLib::HwlSetupTileInfo(
   1451     AddrTileMode                        tileMode,       ///< [in] Tile mode
   1452     ADDR_SURFACE_FLAGS                  flags,          ///< [in] Surface type flags
   1453     UINT_32                             bpp,            ///< [in] Bits per pixel
   1454     UINT_32                             pitch,          ///< [in] Pitch in pixels
   1455     UINT_32                             height,         ///< [in] Height in pixels
   1456     UINT_32                             numSamples,     ///< [in] Number of samples
   1457     ADDR_TILEINFO*                      pTileInfoIn,    ///< [in] Tile info input: NULL for default
   1458     ADDR_TILEINFO*                      pTileInfoOut,   ///< [out] Tile info output
   1459     AddrTileType                        inTileType,     ///< [in] Tile type
   1460     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*   pOut            ///< [out] Output
   1461     ) const
   1462 {
   1463     UINT_32 thickness = ComputeSurfaceThickness(tileMode);
   1464     ADDR_TILEINFO* pTileInfo = pTileInfoOut;
   1465     INT index = TileIndexInvalid;
   1466 
   1467     // Fail-safe code
   1468     if (!IsLinear(tileMode))
   1469     {
   1470         // 128 bpp/thick tiling must be non-displayable.
   1471         // Fmask reuse color buffer's entry but bank-height field can be from another entry
   1472         // To simplify the logic, fmask entry should be picked from non-displayable ones
   1473         if (bpp == 128 || thickness > 1 || flags.fmask || flags.prt)
   1474         {
   1475             inTileType = ADDR_NON_DISPLAYABLE;
   1476         }
   1477 
   1478         if (flags.depth || flags.stencil)
   1479         {
   1480             inTileType = ADDR_DEPTH_SAMPLE_ORDER;
   1481         }
   1482     }
   1483 
   1484     // Partial valid fields are not allowed for SI.
   1485     if (IsTileInfoAllZero(pTileInfo))
   1486     {
   1487         if (IsMacroTiled(tileMode))
   1488         {
   1489             if (flags.prt)
   1490             {
   1491                 if (numSamples == 1)
   1492                 {
   1493                     if (flags.depth)
   1494                     {
   1495                         switch (bpp)
   1496                         {
   1497                             case 16:
   1498                                 index = 3;
   1499                                 break;
   1500                             case 32:
   1501                                 index = 6;
   1502                                 break;
   1503                             default:
   1504                                 ADDR_ASSERT_ALWAYS();
   1505                                 break;
   1506                         }
   1507                     }
   1508                     else
   1509                     {
   1510                         switch (bpp)
   1511                         {
   1512                             case 8:
   1513                                 index = 21;
   1514                                 break;
   1515                             case 16:
   1516                                 index = 22;
   1517                                 break;
   1518                             case 32:
   1519                                 index = 23;
   1520                                 break;
   1521                             case 64:
   1522                                 index = 24;
   1523                                 break;
   1524                             case 128:
   1525                                 index = 25;
   1526                                 break;
   1527                             default:
   1528                                 break;
   1529                         }
   1530 
   1531                         if (thickness > 1)
   1532                         {
   1533                             ADDR_ASSERT(bpp != 128);
   1534                             index += 5;
   1535                         }
   1536                     }
   1537                 }
   1538                 else
   1539                 {
   1540                     ADDR_ASSERT(numSamples == 4);
   1541 
   1542                     if (flags.depth)
   1543                     {
   1544                         switch (bpp)
   1545                         {
   1546                             case 16:
   1547                                 index = 5;
   1548                                 break;
   1549                             case 32:
   1550                                 index = 7;
   1551                                 break;
   1552                             default:
   1553                                 ADDR_ASSERT_ALWAYS();
   1554                                 break;
   1555                         }
   1556                     }
   1557                     else
   1558                     {
   1559                         switch (bpp)
   1560                         {
   1561                             case 8:
   1562                                 index = 23;
   1563                                 break;
   1564                             case 16:
   1565                                 index = 24;
   1566                                 break;
   1567                             case 32:
   1568                                 index = 25;
   1569                                 break;
   1570                             case 64:
   1571                                 index = 30;
   1572                                 break;
   1573                             default:
   1574                                 ADDR_ASSERT_ALWAYS();
   1575                                 break;
   1576                         }
   1577                     }
   1578                 }
   1579             }//end of PRT part
   1580             // See table entries 0-7
   1581             else if (flags.depth || flags.stencil)
   1582             {
   1583                 if (flags.compressZ)
   1584                 {
   1585                     if (flags.stencil)
   1586                     {
   1587                         index = 0;
   1588                     }
   1589                     else
   1590                     {
   1591                         // optimal tile index for compressed depth/stencil.
   1592                         switch (numSamples)
   1593                         {
   1594                             case 1:
   1595                                 index = 0;
   1596                                 break;
   1597                             case 2:
   1598                             case 4:
   1599                                 index = 1;
   1600                                 break;
   1601                             case 8:
   1602                                 index = 2;
   1603                                 break;
   1604                             default:
   1605                                 break;
   1606                         }
   1607                     }
   1608                 }
   1609                 else // unCompressZ
   1610                 {
   1611                     index = 3;
   1612                 }
   1613             }
   1614             else //non PRT & non Depth & non Stencil
   1615             {
   1616                 // See table entries 9-12
   1617                 if (inTileType == ADDR_DISPLAYABLE)
   1618                 {
   1619                     switch (bpp)
   1620                     {
   1621                         case 8:
   1622                             index = 10;
   1623                             break;
   1624                         case 16:
   1625                             index = 11;
   1626                             break;
   1627                         case 32:
   1628                             index = 12;
   1629                             break;
   1630                         case 64:
   1631                             index = 12;
   1632                             break;
   1633                         default:
   1634                             break;
   1635                     }
   1636                 }
   1637                 else
   1638                 {
   1639                     // See table entries 13-17
   1640                     if (thickness == 1)
   1641                     {
   1642                         if (flags.fmask)
   1643                         {
   1644                             UINT_32 fmaskPixelSize = bpp * numSamples;
   1645 
   1646                             switch (fmaskPixelSize)
   1647                             {
   1648                                 case 8:
   1649                                     index = 14;
   1650                                     break;
   1651                                 case 16:
   1652                                     index = 15;
   1653                                     break;
   1654                                 case 32:
   1655                                     index = 16;
   1656                                     break;
   1657                                 case 64:
   1658                                     index = 17;
   1659                                     break;
   1660                                 default:
   1661                                     ADDR_ASSERT_ALWAYS();
   1662                             }
   1663                         }
   1664                         else
   1665                         {
   1666                             switch (bpp)
   1667                             {
   1668                                 case 8:
   1669                                     index = 14;
   1670                                     break;
   1671                                 case 16:
   1672                                     index = 15;
   1673                                     break;
   1674                                 case 32:
   1675                                     index = 16;
   1676                                     break;
   1677                                 case 64:
   1678                                     index = 17;
   1679                                     break;
   1680                                 case 128:
   1681                                     index = 17;
   1682                                     break;
   1683                                 default:
   1684                                     break;
   1685                             }
   1686                         }
   1687                     }
   1688                     else // thick tiling - entries 18-20
   1689                     {
   1690                         switch (thickness)
   1691                         {
   1692                             case 4:
   1693                                 index = 20;
   1694                                 break;
   1695                             case 8:
   1696                                 index = 19;
   1697                                 break;
   1698                             default:
   1699                                 break;
   1700                         }
   1701                     }
   1702                 }
   1703             }
   1704         }
   1705         else
   1706         {
   1707             if (tileMode == ADDR_TM_LINEAR_ALIGNED)
   1708             {
   1709                 index = 8;
   1710             }
   1711             else if (tileMode == ADDR_TM_LINEAR_GENERAL)
   1712             {
   1713                 index = TileIndexLinearGeneral;
   1714             }
   1715             else
   1716             {
   1717                 if (flags.depth || flags.stencil)
   1718                 {
   1719                     index = 4;
   1720                 }
   1721                 else if (inTileType == ADDR_DISPLAYABLE)
   1722                 {
   1723                     index = 9;
   1724                 }
   1725                 else if (thickness == 1)
   1726                 {
   1727                     index = 13;
   1728                 }
   1729                 else
   1730                 {
   1731                     index = 18;
   1732                 }
   1733             }
   1734         }
   1735 
   1736         if (index >= 0 && index <= 31)
   1737         {
   1738             *pTileInfo      = m_tileTable[index].info;
   1739             pOut->tileType  = m_tileTable[index].type;
   1740         }
   1741 
   1742         if (index == TileIndexLinearGeneral)
   1743         {
   1744             *pTileInfo      = m_tileTable[8].info;
   1745             pOut->tileType  = m_tileTable[8].type;
   1746         }
   1747     }
   1748     else
   1749     {
   1750         if (pTileInfoIn)
   1751         {
   1752             if (flags.stencil && pTileInfoIn->tileSplitBytes == 0)
   1753             {
   1754                 // Stencil always uses index 0
   1755                 *pTileInfo = m_tileTable[0].info;
   1756             }
   1757         }
   1758         // Pass through tile type
   1759         pOut->tileType = inTileType;
   1760     }
   1761 
   1762     pOut->tileIndex = index;
   1763 }
   1764 
   1765 /**
   1766 ***************************************************************************************************
   1767 *   SIAddrLib::DecodeGbRegs
   1768 *
   1769 *   @brief
   1770 *       Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks
   1771 *
   1772 *   @return
   1773 *       TRUE if all settings are valid
   1774 *
   1775 ***************************************************************************************************
   1776 */
   1777 BOOL_32 SIAddrLib::DecodeGbRegs(
   1778     const ADDR_REGISTER_VALUE* pRegValue) ///< [in] create input
   1779 {
   1780     GB_ADDR_CONFIG  reg;
   1781     BOOL_32         valid = TRUE;
   1782 
   1783     reg.val = pRegValue->gbAddrConfig;
   1784 
   1785     switch (reg.f.pipe_interleave_size)
   1786     {
   1787         case ADDR_CONFIG_PIPE_INTERLEAVE_256B:
   1788             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_256B;
   1789             break;
   1790         case ADDR_CONFIG_PIPE_INTERLEAVE_512B:
   1791             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_512B;
   1792             break;
   1793         default:
   1794             valid = FALSE;
   1795             ADDR_UNHANDLED_CASE();
   1796             break;
   1797     }
   1798 
   1799     switch (reg.f.row_size)
   1800     {
   1801         case ADDR_CONFIG_1KB_ROW:
   1802             m_rowSize = ADDR_ROWSIZE_1KB;
   1803             break;
   1804         case ADDR_CONFIG_2KB_ROW:
   1805             m_rowSize = ADDR_ROWSIZE_2KB;
   1806             break;
   1807         case ADDR_CONFIG_4KB_ROW:
   1808             m_rowSize = ADDR_ROWSIZE_4KB;
   1809             break;
   1810         default:
   1811             valid = FALSE;
   1812             ADDR_UNHANDLED_CASE();
   1813             break;
   1814     }
   1815 
   1816     switch (pRegValue->noOfBanks)
   1817     {
   1818         case 0:
   1819             m_banks = 4;
   1820             break;
   1821         case 1:
   1822             m_banks = 8;
   1823             break;
   1824         case 2:
   1825             m_banks = 16;
   1826             break;
   1827         default:
   1828             valid = FALSE;
   1829             ADDR_UNHANDLED_CASE();
   1830             break;
   1831     }
   1832 
   1833     switch (pRegValue->noOfRanks)
   1834     {
   1835         case 0:
   1836             m_ranks = 1;
   1837             break;
   1838         case 1:
   1839             m_ranks = 2;
   1840             break;
   1841         default:
   1842             valid = FALSE;
   1843             ADDR_UNHANDLED_CASE();
   1844             break;
   1845     }
   1846 
   1847     m_logicalBanks = m_banks * m_ranks;
   1848 
   1849     ADDR_ASSERT(m_logicalBanks <= 16);
   1850 
   1851     return valid;
   1852 }
   1853 
   1854 /**
   1855 ***************************************************************************************************
   1856 *   SIAddrLib::HwlInitGlobalParams
   1857 *
   1858 *   @brief
   1859 *       Initializes global parameters
   1860 *
   1861 *   @return
   1862 *       TRUE if all settings are valid
   1863 *
   1864 ***************************************************************************************************
   1865 */
   1866 BOOL_32 SIAddrLib::HwlInitGlobalParams(
   1867     const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input
   1868 {
   1869     BOOL_32 valid = TRUE;
   1870     const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue;
   1871 
   1872     valid = DecodeGbRegs(pRegValue);
   1873 
   1874     if (valid)
   1875     {
   1876         if (m_settings.isTahiti || m_settings.isPitCairn)
   1877         {
   1878             m_pipes = 8;
   1879         }
   1880         else if (m_settings.isCapeVerde || m_settings.isOland)
   1881         {
   1882             m_pipes = 4;
   1883         }
   1884         else
   1885         {
   1886             // Hainan is 2-pipe (m_settings.isHainan == 1)
   1887             m_pipes = 2;
   1888         }
   1889 
   1890         valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
   1891 
   1892         m_maxSamples = 16;
   1893     }
   1894 
   1895     return valid;
   1896 }
   1897 
   1898 /**
   1899 ***************************************************************************************************
   1900 *   SIAddrLib::HwlConvertTileInfoToHW
   1901 *   @brief
   1902 *       Entry of si's ConvertTileInfoToHW
   1903 *   @return
   1904 *       ADDR_E_RETURNCODE
   1905 ***************************************************************************************************
   1906 */
   1907 ADDR_E_RETURNCODE SIAddrLib::HwlConvertTileInfoToHW(
   1908     const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
   1909     ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut      ///< [out] output structure
   1910     ) const
   1911 {
   1912     ADDR_E_RETURNCODE retCode   = ADDR_OK;
   1913 
   1914     retCode = EgBasedAddrLib::HwlConvertTileInfoToHW(pIn, pOut);
   1915 
   1916     if (retCode == ADDR_OK)
   1917     {
   1918         if (pIn->reverse == FALSE)
   1919         {
   1920             if (pIn->pTileInfo->pipeConfig == ADDR_PIPECFG_INVALID)
   1921             {
   1922                 retCode = ADDR_INVALIDPARAMS;
   1923             }
   1924             else
   1925             {
   1926                 pOut->pTileInfo->pipeConfig =
   1927                     static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig - 1);
   1928             }
   1929         }
   1930         else
   1931         {
   1932             pOut->pTileInfo->pipeConfig =
   1933                 static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig + 1);
   1934         }
   1935     }
   1936 
   1937     return retCode;
   1938 }
   1939 
   1940 /**
   1941 ***************************************************************************************************
   1942 *   SIAddrLib::HwlComputeXmaskCoordYFrom8Pipe
   1943 *
   1944 *   @brief
   1945 *       Compute the Y coord which will be added to Xmask Y
   1946 *       coord.
   1947 *   @return
   1948 *       Y coord
   1949 ***************************************************************************************************
   1950 */
   1951 UINT_32 SIAddrLib::HwlComputeXmaskCoordYFrom8Pipe(
   1952     UINT_32         pipe,       ///< [in] pipe id
   1953     UINT_32         x           ///< [in] tile coord x, which is original x coord / 8
   1954     ) const
   1955 {
   1956     // This function should never be called since it is 6xx/8xx specfic.
   1957     // Keep this empty implementation to avoid any mis-use.
   1958     ADDR_ASSERT_ALWAYS();
   1959 
   1960     return 0;
   1961 }
   1962 
   1963 /**
   1964 ***************************************************************************************************
   1965 *   SIAddrLib::HwlComputeSurfaceCoord2DFromBankPipe
   1966 *
   1967 *   @brief
   1968 *       Compute surface x,y coordinates from bank/pipe info
   1969 *   @return
   1970 *       N/A
   1971 ***************************************************************************************************
   1972 */
   1973 VOID SIAddrLib::HwlComputeSurfaceCoord2DFromBankPipe(
   1974     AddrTileMode        tileMode,   ///< [in] tile mode
   1975     UINT_32*            pX,         ///< [in/out] x coordinate
   1976     UINT_32*            pY,         ///< [in/out] y coordinate
   1977     UINT_32             slice,      ///< [in] slice index
   1978     UINT_32             bank,       ///< [in] bank number
   1979     UINT_32             pipe,       ///< [in] pipe number
   1980     UINT_32             bankSwizzle,///< [in] bank swizzle
   1981     UINT_32             pipeSwizzle,///< [in] pipe swizzle
   1982     UINT_32             tileSlices, ///< [in] slices in a micro tile
   1983     BOOL_32             ignoreSE,   ///< [in] TRUE if shader engines are ignored
   1984     ADDR_TILEINFO*      pTileInfo   ///< [in] bank structure. **All fields to be valid on entry**
   1985     ) const
   1986 {
   1987     UINT_32 xBit;
   1988     UINT_32 yBit;
   1989     UINT_32 yBit3 = 0;
   1990     UINT_32 yBit4 = 0;
   1991     UINT_32 yBit5 = 0;
   1992     UINT_32 yBit6 = 0;
   1993 
   1994     UINT_32 xBit3 = 0;
   1995     UINT_32 xBit4 = 0;
   1996     UINT_32 xBit5 = 0;
   1997 
   1998     UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
   1999 
   2000     CoordFromBankPipe xyBits = {0};
   2001     ComputeSurfaceCoord2DFromBankPipe(tileMode, *pX, *pY, slice, bank, pipe,
   2002                                       bankSwizzle, pipeSwizzle, tileSlices, pTileInfo,
   2003                                       &xyBits);
   2004     yBit3 = xyBits.yBit3;
   2005     yBit4 = xyBits.yBit4;
   2006     yBit5 = xyBits.yBit5;
   2007     yBit6 = xyBits.yBit6;
   2008 
   2009     xBit3 = xyBits.xBit3;
   2010     xBit4 = xyBits.xBit4;
   2011     xBit5 = xyBits.xBit5;
   2012 
   2013     yBit = xyBits.yBits;
   2014 
   2015     UINT_32 yBitTemp = 0;
   2016 
   2017     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
   2018         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32))
   2019     {
   2020         ADDR_ASSERT(pTileInfo->bankWidth == 1 && pTileInfo->macroAspectRatio > 1);
   2021         UINT_32 yBitToCheck = QLog2(pTileInfo->banks) - 1;
   2022 
   2023         ADDR_ASSERT(yBitToCheck <= 3);
   2024 
   2025         yBitTemp = _BIT(yBit, yBitToCheck);
   2026 
   2027         xBit3 = 0;
   2028     }
   2029 
   2030     yBit = Bits2Number(4, yBit6, yBit5, yBit4, yBit3);
   2031     xBit = Bits2Number(3, xBit5, xBit4, xBit3);
   2032 
   2033     *pY += yBit * pTileInfo->bankHeight * MicroTileHeight;
   2034     *pX += xBit * numPipes * pTileInfo->bankWidth * MicroTileWidth;
   2035 
   2036     //calculate the bank and pipe bits in x, y
   2037     UINT_32 xTile; //x in micro tile
   2038     UINT_32 x3 = 0;
   2039     UINT_32 x4 = 0;
   2040     UINT_32 x5 = 0;
   2041     UINT_32 x6 = 0;
   2042     UINT_32 y = *pY;
   2043 
   2044     UINT_32 pipeBit0 = _BIT(pipe,0);
   2045     UINT_32 pipeBit1 = _BIT(pipe,1);
   2046     UINT_32 pipeBit2 = _BIT(pipe,2);
   2047 
   2048     UINT_32 y3 = _BIT(y, 3);
   2049     UINT_32 y4 = _BIT(y, 4);
   2050     UINT_32 y5 = _BIT(y, 5);
   2051     UINT_32 y6 = _BIT(y, 6);
   2052 
   2053     // bankbit0 after ^x4^x5
   2054     UINT_32 bankBit00 = _BIT(bank,0);
   2055     UINT_32 bankBit0 = 0;
   2056 
   2057     switch (pTileInfo->pipeConfig)
   2058     {
   2059         case ADDR_PIPECFG_P2:
   2060             x3 = pipeBit0 ^ y3;
   2061             break;
   2062         case ADDR_PIPECFG_P4_8x16:
   2063             x4 = pipeBit0 ^ y3;
   2064             x3 = pipeBit0 ^ y4;
   2065             break;
   2066         case ADDR_PIPECFG_P4_16x16:
   2067             x4 = pipeBit1 ^ y4;
   2068             x3 = pipeBit0 ^ y3 ^ x4;
   2069             break;
   2070         case ADDR_PIPECFG_P4_16x32:
   2071             x4 = pipeBit1 ^ y4;
   2072             x3 = pipeBit0 ^ y3 ^ x4;
   2073             break;
   2074         case ADDR_PIPECFG_P4_32x32:
   2075             x5 = pipeBit1 ^ y5;
   2076             x3 = pipeBit0 ^ y3 ^ x5;
   2077             bankBit0 = yBitTemp ^ x5;
   2078             x4 = bankBit00 ^ x5 ^ bankBit0;
   2079             *pX += x5 * 4 * 1 * 8; // x5 * num_pipes * bank_width * 8;
   2080             break;
   2081         case ADDR_PIPECFG_P8_16x16_8x16:
   2082             x3 = pipeBit1 ^ y5;
   2083             x4 = pipeBit2 ^ y4;
   2084             x5 = pipeBit0 ^ y3 ^ x4;
   2085             break;
   2086         case ADDR_PIPECFG_P8_16x32_8x16:
   2087             x3 = pipeBit1 ^ y4;
   2088             x4 = pipeBit2 ^ y5;
   2089             x5 = pipeBit0 ^ y3 ^ x4;
   2090             break;
   2091         case ADDR_PIPECFG_P8_32x32_8x16:
   2092             x3 = pipeBit1 ^ y4;
   2093             x5 = pipeBit2 ^ y5;
   2094             x4 = pipeBit0 ^ y3 ^ x5;
   2095             break;
   2096         case ADDR_PIPECFG_P8_16x32_16x16:
   2097             x4 = pipeBit2 ^ y5;
   2098             x5 = pipeBit1 ^ y4;
   2099             x3 = pipeBit0 ^ y3 ^ x4;
   2100             break;
   2101         case ADDR_PIPECFG_P8_32x32_16x16:
   2102             x5 = pipeBit2 ^ y5;
   2103             x4 = pipeBit1 ^ y4;
   2104             x3 = pipeBit0 ^ y3 ^ x4;
   2105             break;
   2106         case ADDR_PIPECFG_P8_32x32_16x32:
   2107             x5 = pipeBit2 ^ y5;
   2108             x4 = pipeBit1 ^ y6;
   2109             x3 = pipeBit0 ^ y3 ^ x4;
   2110             break;
   2111         case ADDR_PIPECFG_P8_32x64_32x32:
   2112             x6 = pipeBit1 ^ y5;
   2113             x5 = pipeBit2 ^ y6;
   2114             x3 = pipeBit0 ^ y3 ^ x5;
   2115             bankBit0 = yBitTemp ^ x6;
   2116             x4 = bankBit00 ^ x5 ^ bankBit0;
   2117             *pX += x6 * 8 * 1 * 8; // x6 * num_pipes * bank_width * 8;
   2118             break;
   2119         default:
   2120             ADDR_ASSERT_ALWAYS();
   2121     }
   2122 
   2123     xTile = Bits2Number(3, x5, x4, x3);
   2124 
   2125     *pX += xTile << 3;
   2126 }
   2127 
   2128 /**
   2129 ***************************************************************************************************
   2130 *   SIAddrLib::HwlPreAdjustBank
   2131 *
   2132 *   @brief
   2133 *       Adjust bank before calculating address acoording to bank/pipe
   2134 *   @return
   2135 *       Adjusted bank
   2136 ***************************************************************************************************
   2137 */
   2138 UINT_32 SIAddrLib::HwlPreAdjustBank(
   2139     UINT_32         tileX,      ///< [in] x coordinate in unit of tile
   2140     UINT_32         bank,       ///< [in] bank
   2141     ADDR_TILEINFO*  pTileInfo   ///< [in] tile info
   2142     ) const
   2143 {
   2144     if (((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
   2145         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) && (pTileInfo->bankWidth == 1))
   2146     {
   2147         UINT_32 bankBit0 = _BIT(bank, 0);
   2148         UINT_32 x4 = _BIT(tileX, 1);
   2149         UINT_32 x5 = _BIT(tileX, 2);
   2150 
   2151         bankBit0 = bankBit0 ^ x4 ^ x5;
   2152         bank |= bankBit0;
   2153 
   2154         ADDR_ASSERT(pTileInfo->macroAspectRatio > 1)
   2155     }
   2156 
   2157     return bank;
   2158 }
   2159 
   2160 /**
   2161 ***************************************************************************************************
   2162 *   SIAddrLib::HwlComputeSurfaceInfo
   2163 *
   2164 *   @brief
   2165 *       Entry of si's ComputeSurfaceInfo
   2166 *   @return
   2167 *       ADDR_E_RETURNCODE
   2168 ***************************************************************************************************
   2169 */
   2170 ADDR_E_RETURNCODE SIAddrLib::HwlComputeSurfaceInfo(
   2171     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,    ///< [in] input structure
   2172     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [out] output structure
   2173     ) const
   2174 {
   2175     pOut->tileIndex = pIn->tileIndex;
   2176 
   2177     return EgBasedAddrLib::HwlComputeSurfaceInfo(pIn,pOut);
   2178 }
   2179 
   2180 /**
   2181 ***************************************************************************************************
   2182 *   SIAddrLib::HwlComputeMipLevel
   2183 *   @brief
   2184 *       Compute MipLevel info (including level 0)
   2185 *   @return
   2186 *       TRUE if HWL's handled
   2187 ***************************************************************************************************
   2188 */
   2189 BOOL_32 SIAddrLib::HwlComputeMipLevel(
   2190     ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in/out] Input structure
   2191     ) const
   2192 {
   2193     // basePitch is calculated from level 0 so we only check this for mipLevel > 0
   2194     if (pIn->mipLevel > 0)
   2195     {
   2196         // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if
   2197         // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being
   2198         // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2.
   2199         if (!AddrElemLib::IsExpand3x(pIn->format))
   2200         {
   2201             // Sublevel pitches are generated from base level pitch instead of width on SI
   2202             // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain
   2203             ADDR_ASSERT(!pIn->flags.pow2Pad || ((pIn->basePitch != 0) && IsPow2(pIn->basePitch)));
   2204         }
   2205 
   2206         if (pIn->basePitch != 0)
   2207         {
   2208             pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel);
   2209         }
   2210     }
   2211 
   2212     // pow2Pad is done in PostComputeMipLevel
   2213 
   2214     return TRUE;
   2215 }
   2216 
   2217 /**
   2218 ***************************************************************************************************
   2219 *   SIAddrLib::HwlCheckLastMacroTiledLvl
   2220 *
   2221 *   @brief
   2222 *       Sets pOut->last2DLevel to TRUE if it is
   2223 *   @note
   2224 *
   2225 ***************************************************************************************************
   2226 */
   2227 VOID SIAddrLib::HwlCheckLastMacroTiledLvl(
   2228     const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
   2229     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut      ///< [in/out] Output structure (used as input, too)
   2230     ) const
   2231 {
   2232     // pow2Pad covers all mipmap cases
   2233     if (pIn->flags.pow2Pad)
   2234     {
   2235         ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
   2236 
   2237         UINT_32 nextPitch;
   2238         UINT_32 nextHeight;
   2239         UINT_32 nextSlices;
   2240 
   2241         AddrTileMode nextTileMode;
   2242 
   2243         if (pIn->mipLevel == 0 || pIn->basePitch == 0)
   2244         {
   2245             // Base level or fail-safe case (basePitch == 0)
   2246             nextPitch = pOut->pitch >> 1;
   2247         }
   2248         else
   2249         {
   2250             // Sub levels
   2251             nextPitch = pIn->basePitch >> (pIn->mipLevel + 1);
   2252         }
   2253 
   2254         // nextHeight must be shifted from this level's original height rather than a pow2 padded
   2255         // one but this requires original height stored somewhere (pOut->height)
   2256         ADDR_ASSERT(pOut->height != 0);
   2257 
   2258         // next level's height is just current level's >> 1 in pixels
   2259         nextHeight = pOut->height >> 1;
   2260         // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block
   2261         // compressed foramts
   2262         if (AddrElemLib::IsBlockCompressed(pIn->format))
   2263         {
   2264             nextHeight = (nextHeight + 3) / 4;
   2265         }
   2266         nextHeight = NextPow2(nextHeight);
   2267 
   2268         // nextSlices may be 0 if this level's is 1
   2269         if (pIn->flags.volume)
   2270         {
   2271             nextSlices = Max(1u, pIn->numSlices >> 1);
   2272         }
   2273         else
   2274         {
   2275             nextSlices = pIn->numSlices;
   2276         }
   2277 
   2278         nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode,
   2279                                                       pIn->bpp,
   2280                                                       nextPitch,
   2281                                                       nextHeight,
   2282                                                       nextSlices,
   2283                                                       pIn->numSamples,
   2284                                                       pOut->pitchAlign,
   2285                                                       pOut->heightAlign,
   2286                                                       pOut->pTileInfo);
   2287 
   2288         pOut->last2DLevel = IsMicroTiled(nextTileMode);
   2289     }
   2290 }
   2291 
   2292 /**
   2293 ***************************************************************************************************
   2294 *   SIAddrLib::HwlDegradeThickTileMode
   2295 *
   2296 *   @brief
   2297 *       Degrades valid tile mode for thick modes if needed
   2298 *
   2299 *   @return
   2300 *       Suitable tile mode
   2301 ***************************************************************************************************
   2302 */
   2303 AddrTileMode SIAddrLib::HwlDegradeThickTileMode(
   2304     AddrTileMode        baseTileMode,   ///< [in] base tile mode
   2305     UINT_32             numSlices,      ///< [in] current number of slices
   2306     UINT_32*            pBytesPerTile   ///< [in/out] pointer to bytes per slice
   2307     ) const
   2308 {
   2309     return EgBasedAddrLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile);
   2310 }
   2311 
   2312 /**
   2313 ***************************************************************************************************
   2314 *   SIAddrLib::HwlTileInfoEqual
   2315 *
   2316 *   @brief
   2317 *       Return TRUE if all field are equal
   2318 *   @note
   2319 *       Only takes care of current HWL's data
   2320 ***************************************************************************************************
   2321 */
   2322 BOOL_32 SIAddrLib::HwlTileInfoEqual(
   2323     const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand
   2324     const ADDR_TILEINFO* pRight ///<[in] Right compare operand
   2325     ) const
   2326 {
   2327     BOOL_32 equal = FALSE;
   2328 
   2329     if (pLeft->pipeConfig == pRight->pipeConfig)
   2330     {
   2331         equal =  EgBasedAddrLib::HwlTileInfoEqual(pLeft, pRight);
   2332     }
   2333 
   2334     return equal;
   2335 }
   2336 
   2337 /**
   2338 ***************************************************************************************************
   2339 *   SIAddrLib::GetTileSettings
   2340 *
   2341 *   @brief
   2342 *       Get tile setting infos by index.
   2343 *   @return
   2344 *       Tile setting info.
   2345 ***************************************************************************************************
   2346 */
   2347 const ADDR_TILECONFIG* SIAddrLib::GetTileSetting(
   2348     UINT_32 index          ///< [in] Tile index
   2349     ) const
   2350 {
   2351     ADDR_ASSERT(index < m_noOfEntries);
   2352     return &m_tileTable[index];
   2353 }
   2354 
   2355 /**
   2356 ***************************************************************************************************
   2357 *   SIAddrLib::HwlPostCheckTileIndex
   2358 *
   2359 *   @brief
   2360 *       Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
   2361 *       tile mode/type/info and change the index if needed
   2362 *   @return
   2363 *       Tile index.
   2364 ***************************************************************************************************
   2365 */
   2366 INT_32 SIAddrLib::HwlPostCheckTileIndex(
   2367     const ADDR_TILEINFO* pInfo,     ///< [in] Tile Info
   2368     AddrTileMode         mode,      ///< [in] Tile mode
   2369     AddrTileType         type,      ///< [in] Tile type
   2370     INT                  curIndex   ///< [in] Current index assigned in HwlSetupTileInfo
   2371     ) const
   2372 {
   2373     INT_32 index = curIndex;
   2374 
   2375     if (mode == ADDR_TM_LINEAR_GENERAL)
   2376     {
   2377         index = TileIndexLinearGeneral;
   2378     }
   2379     else
   2380     {
   2381         BOOL_32 macroTiled = IsMacroTiled(mode);
   2382 
   2383         // We need to find a new index if either of them is true
   2384         // 1. curIndex is invalid
   2385         // 2. tile mode is changed
   2386         // 3. tile info does not match for macro tiled
   2387         if ((index == TileIndexInvalid         ||
   2388             (mode != m_tileTable[index].mode)  ||
   2389             (macroTiled && !HwlTileInfoEqual(pInfo, &m_tileTable[index].info))))
   2390         {
   2391             for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
   2392             {
   2393                 if (macroTiled)
   2394                 {
   2395                     // macro tile modes need all to match
   2396                     if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) &&
   2397                         (mode == m_tileTable[index].mode)                 &&
   2398                         (type == m_tileTable[index].type))
   2399                     {
   2400                         break;
   2401                     }
   2402                 }
   2403                 else if (mode == ADDR_TM_LINEAR_ALIGNED)
   2404                 {
   2405                     // linear mode only needs tile mode to match
   2406                     if (mode == m_tileTable[index].mode)
   2407                     {
   2408                         break;
   2409                     }
   2410                 }
   2411                 else
   2412                 {
   2413                     // micro tile modes only need tile mode and tile type to match
   2414                     if (mode == m_tileTable[index].mode &&
   2415                         type == m_tileTable[index].type)
   2416                     {
   2417                         break;
   2418                     }
   2419                 }
   2420             }
   2421         }
   2422     }
   2423 
   2424     ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
   2425 
   2426     if (index >= static_cast<INT_32>(m_noOfEntries))
   2427     {
   2428         index = TileIndexInvalid;
   2429     }
   2430 
   2431     return index;
   2432 }
   2433 
   2434 /**
   2435 ***************************************************************************************************
   2436 *   SIAddrLib::HwlSetupTileCfg
   2437 *
   2438 *   @brief
   2439 *       Map tile index to tile setting.
   2440 *   @return
   2441 *       ADDR_E_RETURNCODE
   2442 ***************************************************************************************************
   2443 */
   2444 ADDR_E_RETURNCODE SIAddrLib::HwlSetupTileCfg(
   2445     INT_32          index,          ///< [in] Tile index
   2446     INT_32          macroModeIndex, ///< [in] Index in macro tile mode table(CI)
   2447     ADDR_TILEINFO*  pInfo,          ///< [out] Tile Info
   2448     AddrTileMode*   pMode,          ///< [out] Tile mode
   2449     AddrTileType*   pType          ///< [out] Tile type
   2450     ) const
   2451 {
   2452     ADDR_E_RETURNCODE returnCode = ADDR_OK;
   2453 
   2454     // Global flag to control usage of tileIndex
   2455     if (UseTileIndex(index))
   2456     {
   2457         if (index == TileIndexLinearGeneral)
   2458         {
   2459             if (pMode)
   2460             {
   2461                 *pMode = ADDR_TM_LINEAR_GENERAL;
   2462             }
   2463 
   2464             if (pType)
   2465             {
   2466                 *pType = ADDR_DISPLAYABLE;
   2467             }
   2468 
   2469             if (pInfo)
   2470             {
   2471                 pInfo->banks = 2;
   2472                 pInfo->bankWidth = 1;
   2473                 pInfo->bankHeight = 1;
   2474                 pInfo->macroAspectRatio = 1;
   2475                 pInfo->tileSplitBytes = 64;
   2476                 pInfo->pipeConfig = ADDR_PIPECFG_P2;
   2477             }
   2478         }
   2479         else if (static_cast<UINT_32>(index) >= m_noOfEntries)
   2480         {
   2481             returnCode = ADDR_INVALIDPARAMS;
   2482         }
   2483         else
   2484         {
   2485             const ADDR_TILECONFIG* pCfgTable = GetTileSetting(index);
   2486 
   2487             if (pInfo)
   2488             {
   2489                 *pInfo = pCfgTable->info;
   2490             }
   2491             else
   2492             {
   2493                 if (IsMacroTiled(pCfgTable->mode))
   2494                 {
   2495                     returnCode = ADDR_INVALIDPARAMS;
   2496                 }
   2497             }
   2498 
   2499             if (pMode)
   2500             {
   2501                 *pMode = pCfgTable->mode;
   2502             }
   2503 
   2504             if (pType)
   2505             {
   2506                 *pType = pCfgTable->type;
   2507             }
   2508         }
   2509     }
   2510 
   2511     return returnCode;
   2512 }
   2513 
   2514 /**
   2515 ***************************************************************************************************
   2516 *   SIAddrLib::ReadGbTileMode
   2517 *
   2518 *   @brief
   2519 *       Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
   2520 *   @return
   2521 *       NA.
   2522 ***************************************************************************************************
   2523 */
   2524 VOID SIAddrLib::ReadGbTileMode(
   2525     UINT_32             regValue,   ///< [in] GB_TILE_MODE register
   2526     ADDR_TILECONFIG*    pCfg        ///< [out] output structure
   2527     ) const
   2528 {
   2529     GB_TILE_MODE gbTileMode;
   2530     gbTileMode.val = regValue;
   2531 
   2532     pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode);
   2533     pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height;
   2534     pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width;
   2535     pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1);
   2536     pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
   2537     pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
   2538     pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
   2539 
   2540     UINT_32 regArrayMode = gbTileMode.f.array_mode;
   2541 
   2542     pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
   2543 
   2544     if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK
   2545     {
   2546         pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
   2547     }
   2548     else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK
   2549     {
   2550         pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3);
   2551     }
   2552 }
   2553 
   2554 /**
   2555 ***************************************************************************************************
   2556 *   SIAddrLib::InitTileSettingTable
   2557 *
   2558 *   @brief
   2559 *       Initialize the ADDR_TILE_CONFIG table.
   2560 *   @return
   2561 *       TRUE if tile table is correctly initialized
   2562 ***************************************************************************************************
   2563 */
   2564 BOOL_32 SIAddrLib::InitTileSettingTable(
   2565     const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
   2566     UINT_32         noOfEntries     ///< [in] Numbe of entries in the table above
   2567     )
   2568 {
   2569     BOOL_32 initOk = TRUE;
   2570 
   2571     ADDR_ASSERT(noOfEntries <= TileTableSize);
   2572 
   2573     memset(m_tileTable, 0, sizeof(m_tileTable));
   2574 
   2575     if (noOfEntries != 0)
   2576     {
   2577         m_noOfEntries = noOfEntries;
   2578     }
   2579     else
   2580     {
   2581         m_noOfEntries = TileTableSize;
   2582     }
   2583 
   2584     if (pCfg) // From Client
   2585     {
   2586         for (UINT_32 i = 0; i < m_noOfEntries; i++)
   2587         {
   2588             ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
   2589         }
   2590     }
   2591     else
   2592     {
   2593         ADDR_ASSERT_ALWAYS();
   2594         initOk = FALSE;
   2595     }
   2596 
   2597     if (initOk)
   2598     {
   2599         ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
   2600     }
   2601 
   2602     return initOk;
   2603 }
   2604 
   2605 /**
   2606 ***************************************************************************************************
   2607 *   SIAddrLib::HwlGetTileIndex
   2608 *
   2609 *   @brief
   2610 *       Return the virtual/real index for given mode/type/info
   2611 *   @return
   2612 *       ADDR_OK if successful.
   2613 ***************************************************************************************************
   2614 */
   2615 ADDR_E_RETURNCODE SIAddrLib::HwlGetTileIndex(
   2616     const ADDR_GET_TILEINDEX_INPUT* pIn,
   2617     ADDR_GET_TILEINDEX_OUTPUT*      pOut) const
   2618 {
   2619     ADDR_E_RETURNCODE returnCode = ADDR_OK;
   2620 
   2621     pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType);
   2622 
   2623     return returnCode;
   2624 }
   2625 
   2626 /**
   2627 ***************************************************************************************************
   2628 *   SIAddrLib::HwlFmaskPreThunkSurfInfo
   2629 *
   2630 *   @brief
   2631 *       Some preparation before thunking a ComputeSurfaceInfo call for Fmask
   2632 *   @return
   2633 *       ADDR_E_RETURNCODE
   2634 ***************************************************************************************************
   2635 */
   2636 VOID SIAddrLib::HwlFmaskPreThunkSurfInfo(
   2637     const ADDR_COMPUTE_FMASK_INFO_INPUT*    pFmaskIn,   ///< [in] Input of fmask info
   2638     const ADDR_COMPUTE_FMASK_INFO_OUTPUT*   pFmaskOut,  ///< [in] Output of fmask info
   2639     ADDR_COMPUTE_SURFACE_INFO_INPUT*        pSurfIn,    ///< [out] Input of thunked surface info
   2640     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pSurfOut    ///< [out] Output of thunked surface info
   2641     ) const
   2642 {
   2643     pSurfIn->tileIndex = pFmaskIn->tileIndex;
   2644 }
   2645 
   2646 /**
   2647 ***************************************************************************************************
   2648 *   SIAddrLib::HwlFmaskPostThunkSurfInfo
   2649 *
   2650 *   @brief
   2651 *       Copy hwl extra field after calling thunked ComputeSurfaceInfo
   2652 *   @return
   2653 *       ADDR_E_RETURNCODE
   2654 ***************************************************************************************************
   2655 */
   2656 VOID SIAddrLib::HwlFmaskPostThunkSurfInfo(
   2657     const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut,   ///< [in] Output of surface info
   2658     ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut           ///< [out] Output of fmask info
   2659     ) const
   2660 {
   2661     pFmaskOut->macroModeIndex = TileIndexInvalid;
   2662     pFmaskOut->tileIndex = pSurfOut->tileIndex;
   2663 }
   2664 
   2665 /**
   2666 ***************************************************************************************************
   2667 *   SIAddrLib::HwlComputeFmaskBits
   2668 *   @brief
   2669 *       Computes fmask bits
   2670 *   @return
   2671 *       Fmask bits
   2672 ***************************************************************************************************
   2673 */
   2674 UINT_32 SIAddrLib::HwlComputeFmaskBits(
   2675     const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn,
   2676     UINT_32* pNumSamples
   2677     ) const
   2678 {
   2679     UINT_32 numSamples = pIn->numSamples;
   2680     UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags);
   2681     UINT_32 bpp;
   2682 
   2683     if (numFrags != numSamples) // EQAA
   2684     {
   2685         ADDR_ASSERT(numFrags <= 8);
   2686 
   2687         if (!pIn->resolved)
   2688         {
   2689             if (numFrags == 1)
   2690             {
   2691                 bpp          = 1;
   2692                 numSamples   = numSamples == 16 ? 16 : 8;
   2693             }
   2694             else if (numFrags == 2)
   2695             {
   2696                 ADDR_ASSERT(numSamples >= 4);
   2697 
   2698                 bpp          = 2;
   2699                 numSamples   = numSamples;
   2700             }
   2701             else if (numFrags == 4)
   2702             {
   2703                 ADDR_ASSERT(numSamples >= 4);
   2704 
   2705                 bpp          = 4;
   2706                 numSamples   = numSamples;
   2707             }
   2708             else // numFrags == 8
   2709             {
   2710                 ADDR_ASSERT(numSamples == 16);
   2711 
   2712                 bpp          = 4;
   2713                 numSamples   = numSamples;
   2714             }
   2715         }
   2716         else
   2717         {
   2718             if (numFrags == 1)
   2719             {
   2720                 bpp          = (numSamples == 16) ? 16 : 8;
   2721                 numSamples   = 1;
   2722             }
   2723             else if (numFrags == 2)
   2724             {
   2725                 ADDR_ASSERT(numSamples >= 4);
   2726 
   2727                 bpp          = numSamples*2;
   2728                 numSamples   = 1;
   2729             }
   2730             else if (numFrags == 4)
   2731             {
   2732                 ADDR_ASSERT(numSamples >= 4);
   2733 
   2734                 bpp          = numSamples*4;
   2735                 numSamples   = 1;
   2736             }
   2737             else // numFrags == 8
   2738             {
   2739                 ADDR_ASSERT(numSamples >= 16);
   2740 
   2741                 bpp          = 16*4;
   2742                 numSamples   = 1;
   2743             }
   2744         }
   2745     }
   2746     else // Normal AA
   2747     {
   2748         if (!pIn->resolved)
   2749         {
   2750             bpp          = ComputeFmaskNumPlanesFromNumSamples(numSamples);
   2751             numSamples   = numSamples == 2 ? 8 : numSamples;
   2752         }
   2753         else
   2754         {
   2755             // The same as 8XX
   2756             bpp          = ComputeFmaskResolvedBppFromNumSamples(numSamples);
   2757             numSamples   = 1; // 1x sample
   2758         }
   2759     }
   2760 
   2761     SafeAssign(pNumSamples, numSamples);
   2762 
   2763     return bpp;
   2764 }
   2765 
   2766 /**
   2767 ***************************************************************************************************
   2768 *   SIAddrLib::HwlOverrideTileMode
   2769 *
   2770 *   @brief
   2771 *       Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI.
   2772 *
   2773 *   @return
   2774 *       Suitable tile mode
   2775 *
   2776 ***************************************************************************************************
   2777 */
   2778 BOOL_32 SIAddrLib::HwlOverrideTileMode(
   2779     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,       ///< [in] input structure
   2780     AddrTileMode*                           pTileMode, ///< [in/out] pointer to the tile mode
   2781     AddrTileType*                           pTileType  ///< [in/out] pointer to the tile type
   2782     ) const
   2783 {
   2784     BOOL_32 bOverrided = FALSE;
   2785     AddrTileMode tileMode = *pTileMode;
   2786 
   2787     switch (tileMode)
   2788     {
   2789         case ADDR_TM_PRT_TILED_THIN1:
   2790             tileMode    = ADDR_TM_2D_TILED_THIN1;
   2791             break;
   2792 
   2793         case ADDR_TM_PRT_TILED_THICK:
   2794             tileMode    = ADDR_TM_2D_TILED_THICK;
   2795             break;
   2796 
   2797         case ADDR_TM_PRT_2D_TILED_THICK:
   2798             tileMode    = ADDR_TM_2D_TILED_THICK;
   2799             break;
   2800 
   2801         case ADDR_TM_PRT_3D_TILED_THICK:
   2802             tileMode    = ADDR_TM_3D_TILED_THICK;
   2803             break;
   2804 
   2805         default:
   2806             break;
   2807     }
   2808 
   2809     if (tileMode != *pTileMode)
   2810     {
   2811         *pTileMode = tileMode;
   2812         bOverrided = TRUE;
   2813         ADDR_ASSERT(pIn->flags.prt == TRUE);
   2814     }
   2815 
   2816     return bOverrided;
   2817 }
   2818 
   2819