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 SiLib class.
     31 ****************************************************************************************************
     32 */
     33 
     34 #include "siaddrlib.h"
     35 #include "si_gb_reg.h"
     36 
     37 #include "amdgpu_asic_addr.h"
     38 
     39 ////////////////////////////////////////////////////////////////////////////////////////////////////
     40 ////////////////////////////////////////////////////////////////////////////////////////////////////
     41 namespace Addr
     42 {
     43 
     44 /**
     45 ****************************************************************************************************
     46 *   SiHwlInit
     47 *
     48 *   @brief
     49 *       Creates an SiLib object.
     50 *
     51 *   @return
     52 *       Returns an SiLib object pointer.
     53 ****************************************************************************************************
     54 */
     55 Lib* SiHwlInit(const Client* pClient)
     56 {
     57     return V1::SiLib::CreateObj(pClient);
     58 }
     59 
     60 namespace V1
     61 {
     62 
     63 // We don't support MSAA for equation
     64 const BOOL_32 SiLib::m_EquationSupport[SiLib::TileTableSize][SiLib::MaxNumElementBytes] =
     65 {
     66     {TRUE,  TRUE,  TRUE,  FALSE, FALSE},    //  0, non-AA compressed depth or any stencil
     67     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  1, 2xAA/4xAA compressed depth with or without stencil
     68     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  2, 8xAA compressed depth with or without stencil
     69     {FALSE, TRUE,  FALSE, FALSE, FALSE},    //  3, 16 bpp depth PRT (non-MSAA), don't support uncompressed depth
     70     {TRUE,  TRUE,  TRUE,  FALSE, FALSE},    //  4, 1D depth
     71     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  5, 16 bpp depth PRT (4xMSAA)
     72     {FALSE, FALSE, TRUE,  FALSE, FALSE},    //  6, 32 bpp depth PRT (non-MSAA)
     73     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  7, 32 bpp depth PRT (4xMSAA)
     74     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    //  8, Linear
     75     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    //  9, 1D display
     76     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 10, 8 bpp color (displayable)
     77     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 11, 16 bpp color (displayable)
     78     {FALSE, FALSE, TRUE,  TRUE,  FALSE},    // 12, 32/64 bpp color (displayable)
     79     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    // 13, 1D thin
     80     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 14, 8 bpp color non-displayable
     81     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 15, 16 bpp color non-displayable
     82     {FALSE, FALSE, TRUE,  FALSE, FALSE},    // 16, 32 bpp color non-displayable
     83     {FALSE, FALSE, FALSE, TRUE,  TRUE },    // 17, 64/128 bpp color non-displayable
     84     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    // 18, 1D THICK
     85     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 19, 2D XTHICK
     86     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 20, 2D THICK
     87     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 21, 8 bpp 2D PRTs (non-MSAA)
     88     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 22, 16 bpp 2D PRTs (non-MSAA)
     89     {FALSE, FALSE, TRUE,  FALSE, FALSE},    // 23, 32 bpp 2D PRTs (non-MSAA)
     90     {FALSE, FALSE, FALSE, TRUE,  FALSE},    // 24, 64 bpp 2D PRTs (non-MSAA)
     91     {FALSE, FALSE, FALSE, FALSE, TRUE },    // 25, 128bpp 2D PRTs (non-MSAA)
     92     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 26, none
     93     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 27, none
     94     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 28, none
     95     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 29, none
     96     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 30, 64bpp 2D PRTs (4xMSAA)
     97     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 31, none
     98 };
     99 
    100 /**
    101 ****************************************************************************************************
    102 *   SiLib::SiLib
    103 *
    104 *   @brief
    105 *       Constructor
    106 *
    107 ****************************************************************************************************
    108 */
    109 SiLib::SiLib(const Client* pClient)
    110     :
    111     EgBasedLib(pClient),
    112     m_noOfEntries(0),
    113     m_numEquations(0)
    114 {
    115     m_class = SI_ADDRLIB;
    116     memset(&m_settings, 0, sizeof(m_settings));
    117 }
    118 
    119 /**
    120 ****************************************************************************************************
    121 *   SiLib::~SiLib
    122 *
    123 *   @brief
    124 *       Destructor
    125 ****************************************************************************************************
    126 */
    127 SiLib::~SiLib()
    128 {
    129 }
    130 
    131 /**
    132 ****************************************************************************************************
    133 *   SiLib::HwlGetPipes
    134 *
    135 *   @brief
    136 *       Get number pipes
    137 *   @return
    138 *       num pipes
    139 ****************************************************************************************************
    140 */
    141 UINT_32 SiLib::HwlGetPipes(
    142     const ADDR_TILEINFO* pTileInfo    ///< [in] Tile info
    143     ) const
    144 {
    145     UINT_32 numPipes;
    146 
    147     if (pTileInfo)
    148     {
    149         numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
    150     }
    151     else
    152     {
    153         ADDR_ASSERT_ALWAYS();
    154         numPipes = m_pipes; // Suppose we should still have a global pipes
    155     }
    156 
    157     return numPipes;
    158 }
    159 
    160 /**
    161 ****************************************************************************************************
    162 *   SiLib::GetPipePerSurf
    163 *   @brief
    164 *       get pipe num base on inputing tileinfo->pipeconfig
    165 *   @return
    166 *       pipe number
    167 ****************************************************************************************************
    168 */
    169 UINT_32 SiLib::GetPipePerSurf(
    170     AddrPipeCfg pipeConfig   ///< [in] pipe config
    171     ) const
    172 {
    173     UINT_32 numPipes = 0;
    174 
    175     switch (pipeConfig)
    176     {
    177         case ADDR_PIPECFG_P2:
    178             numPipes = 2;
    179             break;
    180         case ADDR_PIPECFG_P4_8x16:
    181         case ADDR_PIPECFG_P4_16x16:
    182         case ADDR_PIPECFG_P4_16x32:
    183         case ADDR_PIPECFG_P4_32x32:
    184             numPipes = 4;
    185             break;
    186         case ADDR_PIPECFG_P8_16x16_8x16:
    187         case ADDR_PIPECFG_P8_16x32_8x16:
    188         case ADDR_PIPECFG_P8_32x32_8x16:
    189         case ADDR_PIPECFG_P8_16x32_16x16:
    190         case ADDR_PIPECFG_P8_32x32_16x16:
    191         case ADDR_PIPECFG_P8_32x32_16x32:
    192         case ADDR_PIPECFG_P8_32x64_32x32:
    193             numPipes = 8;
    194             break;
    195         case ADDR_PIPECFG_P16_32x32_8x16:
    196         case ADDR_PIPECFG_P16_32x32_16x16:
    197             numPipes = 16;
    198             break;
    199         default:
    200             ADDR_ASSERT(!"Invalid pipe config");
    201             numPipes = m_pipes;
    202     }
    203     return numPipes;
    204 }
    205 
    206 /**
    207 ****************************************************************************************************
    208 *   SiLib::ComputeBankEquation
    209 *
    210 *   @brief
    211 *       Compute bank equation
    212 *
    213 *   @return
    214 *       If equation can be computed
    215 ****************************************************************************************************
    216 */
    217 ADDR_E_RETURNCODE SiLib::ComputeBankEquation(
    218     UINT_32         log2BytesPP,    ///< [in] log2 of bytes per pixel
    219     UINT_32         threshX,        ///< [in] threshold for x channel
    220     UINT_32         threshY,        ///< [in] threshold for y channel
    221     ADDR_TILEINFO*  pTileInfo,      ///< [in] tile info
    222     ADDR_EQUATION*  pEquation       ///< [out] bank equation
    223     ) const
    224 {
    225     ADDR_E_RETURNCODE retCode = ADDR_OK;
    226 
    227     UINT_32 pipes = HwlGetPipes(pTileInfo);
    228     UINT_32 bankXStart = 3 + Log2(pipes) + Log2(pTileInfo->bankWidth);
    229     UINT_32 bankYStart = 3 + Log2(pTileInfo->bankHeight);
    230 
    231     ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, log2BytesPP + bankXStart);
    232     ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, log2BytesPP + bankXStart + 1);
    233     ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, log2BytesPP + bankXStart + 2);
    234     ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, log2BytesPP + bankXStart + 3);
    235     ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, bankYStart);
    236     ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, bankYStart + 1);
    237     ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, bankYStart + 2);
    238     ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, bankYStart + 3);
    239 
    240     x3.value = (threshX > bankXStart)     ? x3.value : 0;
    241     x4.value = (threshX > bankXStart + 1) ? x4.value : 0;
    242     x5.value = (threshX > bankXStart + 2) ? x5.value : 0;
    243     x6.value = (threshX > bankXStart + 3) ? x6.value : 0;
    244     y3.value = (threshY > bankYStart)     ? y3.value : 0;
    245     y4.value = (threshY > bankYStart + 1) ? y4.value : 0;
    246     y5.value = (threshY > bankYStart + 2) ? y5.value : 0;
    247     y6.value = (threshY > bankYStart + 3) ? y6.value : 0;
    248 
    249     switch (pTileInfo->banks)
    250     {
    251         case 16:
    252             if (pTileInfo->macroAspectRatio == 1)
    253             {
    254                 pEquation->addr[0] = y6;
    255                 pEquation->xor1[0] = x3;
    256                 pEquation->addr[1] = y5;
    257                 pEquation->xor1[1] = y6;
    258                 pEquation->xor2[1] = x4;
    259                 pEquation->addr[2] = y4;
    260                 pEquation->xor1[2] = x5;
    261                 pEquation->addr[3] = y3;
    262                 pEquation->xor1[3] = x6;
    263             }
    264             else if (pTileInfo->macroAspectRatio == 2)
    265             {
    266                 pEquation->addr[0] = x3;
    267                 pEquation->xor1[0] = y6;
    268                 pEquation->addr[1] = y5;
    269                 pEquation->xor1[1] = y6;
    270                 pEquation->xor2[1] = x4;
    271                 pEquation->addr[2] = y4;
    272                 pEquation->xor1[2] = x5;
    273                 pEquation->addr[3] = y3;
    274                 pEquation->xor1[3] = x6;
    275             }
    276             else if (pTileInfo->macroAspectRatio == 4)
    277             {
    278                 pEquation->addr[0] = x3;
    279                 pEquation->xor1[0] = y6;
    280                 pEquation->addr[1] = x4;
    281                 pEquation->xor1[1] = y5;
    282                 pEquation->xor2[1] = y6;
    283                 pEquation->addr[2] = y4;
    284                 pEquation->xor1[2] = x5;
    285                 pEquation->addr[3] = y3;
    286                 pEquation->xor1[3] = x6;
    287             }
    288             else if (pTileInfo->macroAspectRatio == 8)
    289             {
    290                 pEquation->addr[0] = x3;
    291                 pEquation->xor1[0] = y6;
    292                 pEquation->addr[1] = x4;
    293                 pEquation->xor1[1] = y5;
    294                 pEquation->xor2[1] = y6;
    295                 pEquation->addr[2] = x5;
    296                 pEquation->xor1[2] = y4;
    297                 pEquation->addr[3] = y3;
    298                 pEquation->xor1[3] = x6;
    299             }
    300             else
    301             {
    302                 ADDR_ASSERT_ALWAYS();
    303             }
    304             pEquation->numBits = 4;
    305             break;
    306         case 8:
    307             if (pTileInfo->macroAspectRatio == 1)
    308             {
    309                 pEquation->addr[0] = y5;
    310                 pEquation->xor1[0] = x3;
    311                 pEquation->addr[1] = y4;
    312                 pEquation->xor1[1] = y5;
    313                 pEquation->xor2[1] = x4;
    314                 pEquation->addr[2] = y3;
    315                 pEquation->xor1[2] = x5;
    316             }
    317             else if (pTileInfo->macroAspectRatio == 2)
    318             {
    319                 pEquation->addr[0] = x3;
    320                 pEquation->xor1[0] = y5;
    321                 pEquation->addr[1] = y4;
    322                 pEquation->xor1[1] = y5;
    323                 pEquation->xor2[1] = x4;
    324                 pEquation->addr[2] = y3;
    325                 pEquation->xor1[2] = x5;
    326             }
    327             else if (pTileInfo->macroAspectRatio == 4)
    328             {
    329                 pEquation->addr[0] = x3;
    330                 pEquation->xor1[0] = y5;
    331                 pEquation->addr[1] = x4;
    332                 pEquation->xor1[1] = y4;
    333                 pEquation->xor2[1] = y5;
    334                 pEquation->addr[2] = y3;
    335                 pEquation->xor1[2] = x5;
    336             }
    337             else
    338             {
    339                 ADDR_ASSERT_ALWAYS();
    340             }
    341             pEquation->numBits = 3;
    342             break;
    343         case 4:
    344             if (pTileInfo->macroAspectRatio == 1)
    345             {
    346                 pEquation->addr[0] = y4;
    347                 pEquation->xor1[0] = x3;
    348                 pEquation->addr[1] = y3;
    349                 pEquation->xor1[1] = x4;
    350             }
    351             else if (pTileInfo->macroAspectRatio == 2)
    352             {
    353                 pEquation->addr[0] = x3;
    354                 pEquation->xor1[0] = y4;
    355                 pEquation->addr[1] = y3;
    356                 pEquation->xor1[1] = x4;
    357             }
    358             else
    359             {
    360                 pEquation->addr[0] = x3;
    361                 pEquation->xor1[0] = y4;
    362                 pEquation->addr[1] = x4;
    363                 pEquation->xor1[1] = y3;
    364             }
    365             pEquation->numBits = 2;
    366             break;
    367         case 2:
    368             if (pTileInfo->macroAspectRatio == 1)
    369             {
    370                 pEquation->addr[0] = y3;
    371                 pEquation->xor1[0] = x3;
    372             }
    373             else
    374             {
    375                 pEquation->addr[0] = x3;
    376                 pEquation->xor1[0] = y3;
    377             }
    378             pEquation->numBits = 1;
    379             break;
    380         default:
    381             pEquation->numBits = 0;
    382             retCode = ADDR_NOTSUPPORTED;
    383             ADDR_ASSERT_ALWAYS();
    384             break;
    385     }
    386 
    387     for (UINT_32 i = 0; i < pEquation->numBits; i++)
    388     {
    389         if (pEquation->addr[i].value == 0)
    390         {
    391             if (pEquation->xor1[i].value == 0)
    392             {
    393                 // 00X -> X00
    394                 pEquation->addr[i].value = pEquation->xor2[i].value;
    395                 pEquation->xor2[i].value = 0;
    396             }
    397             else
    398             {
    399                 pEquation->addr[i].value = pEquation->xor1[i].value;
    400 
    401                 if (pEquation->xor2[i].value != 0)
    402                 {
    403                     // 0XY -> XY0
    404                     pEquation->xor1[i].value = pEquation->xor2[i].value;
    405                     pEquation->xor2[i].value = 0;
    406                 }
    407                 else
    408                 {
    409                     // 0X0 -> X00
    410                     pEquation->xor1[i].value = 0;
    411                 }
    412             }
    413         }
    414         else if (pEquation->xor1[i].value == 0)
    415         {
    416             if (pEquation->xor2[i].value != 0)
    417             {
    418                 // X0Y -> XY0
    419                 pEquation->xor1[i].value = pEquation->xor2[i].value;
    420                 pEquation->xor2[i].value = 0;
    421             }
    422         }
    423     }
    424 
    425     if ((pTileInfo->bankWidth == 1) &&
    426         ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
    427          (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)))
    428     {
    429         retCode = ADDR_NOTSUPPORTED;
    430     }
    431 
    432     return retCode;
    433 }
    434 
    435 /**
    436 ****************************************************************************************************
    437 *   SiLib::ComputePipeEquation
    438 *
    439 *   @brief
    440 *       Compute pipe equation
    441 *
    442 *   @return
    443 *       If equation can be computed
    444 ****************************************************************************************************
    445 */
    446 ADDR_E_RETURNCODE SiLib::ComputePipeEquation(
    447     UINT_32        log2BytesPP, ///< [in] Log2 of bytes per pixel
    448     UINT_32        threshX,     ///< [in] Threshold for X channel
    449     UINT_32        threshY,     ///< [in] Threshold for Y channel
    450     ADDR_TILEINFO* pTileInfo,   ///< [in] Tile info
    451     ADDR_EQUATION* pEquation    ///< [out] Pipe configure
    452     ) const
    453 {
    454     ADDR_E_RETURNCODE retCode = ADDR_OK;
    455 
    456     ADDR_CHANNEL_SETTING* pAddr = pEquation->addr;
    457     ADDR_CHANNEL_SETTING* pXor1 = pEquation->xor1;
    458     ADDR_CHANNEL_SETTING* pXor2 = pEquation->xor2;
    459 
    460     ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, 3 + log2BytesPP);
    461     ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, 4 + log2BytesPP);
    462     ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, 5 + log2BytesPP);
    463     ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, 6 + log2BytesPP);
    464     ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, 3);
    465     ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, 4);
    466     ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, 5);
    467     ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, 6);
    468 
    469     x3.value = (threshX > 3) ? x3.value : 0;
    470     x4.value = (threshX > 4) ? x4.value : 0;
    471     x5.value = (threshX > 5) ? x5.value : 0;
    472     x6.value = (threshX > 6) ? x6.value : 0;
    473     y3.value = (threshY > 3) ? y3.value : 0;
    474     y4.value = (threshY > 4) ? y4.value : 0;
    475     y5.value = (threshY > 5) ? y5.value : 0;
    476     y6.value = (threshY > 6) ? y6.value : 0;
    477 
    478     switch (pTileInfo->pipeConfig)
    479     {
    480         case ADDR_PIPECFG_P2:
    481             pAddr[0] = x3;
    482             pXor1[0] = y3;
    483             pEquation->numBits = 1;
    484             break;
    485         case ADDR_PIPECFG_P4_8x16:
    486             pAddr[0] = x4;
    487             pXor1[0] = y3;
    488             pAddr[1] = x3;
    489             pXor1[1] = y4;
    490             pEquation->numBits = 2;
    491             break;
    492         case ADDR_PIPECFG_P4_16x16:
    493             pAddr[0] = x3;
    494             pXor1[0] = y3;
    495             pXor2[0] = x4;
    496             pAddr[1] = x4;
    497             pXor1[1] = y4;
    498             pEquation->numBits = 2;
    499             break;
    500         case ADDR_PIPECFG_P4_16x32:
    501             pAddr[0] = x3;
    502             pXor1[0] = y3;
    503             pXor2[0] = x4;
    504             pAddr[1] = x4;
    505             pXor1[1] = y5;
    506             pEquation->numBits = 2;
    507             break;
    508         case ADDR_PIPECFG_P4_32x32:
    509             pAddr[0] = x3;
    510             pXor1[0] = y3;
    511             pXor2[0] = x5;
    512             pAddr[1] = x5;
    513             pXor1[1] = y5;
    514             pEquation->numBits = 2;
    515             break;
    516         case ADDR_PIPECFG_P8_16x16_8x16:
    517             pAddr[0] = x4;
    518             pXor1[0] = y3;
    519             pXor2[0] = x5;
    520             pAddr[1] = x3;
    521             pXor1[1] = y5;
    522             pEquation->numBits = 3;
    523             break;
    524         case ADDR_PIPECFG_P8_16x32_8x16:
    525             pAddr[0] = x4;
    526             pXor1[0] = y3;
    527             pXor2[0] = x5;
    528             pAddr[1] = x3;
    529             pXor1[1] = y4;
    530             pAddr[2] = x4;
    531             pXor1[2] = y5;
    532             pEquation->numBits = 3;
    533             break;
    534         case ADDR_PIPECFG_P8_16x32_16x16:
    535             pAddr[0] = x3;
    536             pXor1[0] = y3;
    537             pXor2[0] = x4;
    538             pAddr[1] = x5;
    539             pXor1[1] = y4;
    540             pAddr[2] = x4;
    541             pXor1[2] = y5;
    542             pEquation->numBits = 3;
    543             break;
    544         case ADDR_PIPECFG_P8_32x32_8x16:
    545             pAddr[0] = x4;
    546             pXor1[0] = y3;
    547             pXor2[0] = x5;
    548             pAddr[1] = x3;
    549             pXor1[1] = y4;
    550             pAddr[2] = x5;
    551             pXor1[2] = y5;
    552             pEquation->numBits = 3;
    553             break;
    554         case ADDR_PIPECFG_P8_32x32_16x16:
    555             pAddr[0] = x3;
    556             pXor1[0] = y3;
    557             pXor2[0] = x4;
    558             pAddr[1] = x4;
    559             pXor1[1] = y4;
    560             pAddr[2] = x5;
    561             pXor1[2] = y5;
    562             pEquation->numBits = 3;
    563             break;
    564         case ADDR_PIPECFG_P8_32x32_16x32:
    565             pAddr[0] = x3;
    566             pXor1[0] = y3;
    567             pXor2[0] = x4;
    568             pAddr[1] = x4;
    569             pXor1[1] = y6;
    570             pAddr[2] = x5;
    571             pXor1[2] = y5;
    572             pEquation->numBits = 3;
    573             break;
    574         case ADDR_PIPECFG_P8_32x64_32x32:
    575             pAddr[0] = x3;
    576             pXor1[0] = y3;
    577             pXor2[0] = x5;
    578             pAddr[1] = x6;
    579             pXor1[1] = y5;
    580             pAddr[2] = x5;
    581             pXor1[2] = y6;
    582             pEquation->numBits = 3;
    583             break;
    584         case ADDR_PIPECFG_P16_32x32_8x16:
    585             pAddr[0] = x4;
    586             pXor1[0] = y3;
    587             pAddr[1] = x3;
    588             pXor1[1] = y4;
    589             pAddr[2] = x5;
    590             pXor1[2] = y6;
    591             pAddr[3] = x6;
    592             pXor1[3] = y5;
    593             pEquation->numBits = 4;
    594             break;
    595         case ADDR_PIPECFG_P16_32x32_16x16:
    596             pAddr[0] = x3;
    597             pXor1[0] = y3;
    598             pXor2[0] = x4;
    599             pAddr[1] = x4;
    600             pXor1[1] = y4;
    601             pAddr[2] = x5;
    602             pXor1[2] = y6;
    603             pAddr[3] = x6;
    604             pXor1[3] = y5;
    605             pEquation->numBits = 4;
    606             break;
    607         default:
    608             ADDR_UNHANDLED_CASE();
    609             pEquation->numBits = 0;
    610             retCode = ADDR_NOTSUPPORTED;
    611             break;
    612     }
    613 
    614     for (UINT_32 i = 0; i < pEquation->numBits; i++)
    615     {
    616         if (pAddr[i].value == 0)
    617         {
    618             if (pXor1[i].value == 0)
    619             {
    620                 pAddr[i].value = pXor2[i].value;
    621             }
    622             else
    623             {
    624                 pAddr[i].value = pXor1[i].value;
    625                 pXor1[i].value = 0;
    626             }
    627         }
    628     }
    629 
    630     return retCode;
    631 }
    632 
    633 /**
    634 ****************************************************************************************************
    635 *   SiLib::ComputePipeFromCoord
    636 *
    637 *   @brief
    638 *       Compute pipe number from coordinates
    639 *   @return
    640 *       Pipe number
    641 ****************************************************************************************************
    642 */
    643 UINT_32 SiLib::ComputePipeFromCoord(
    644     UINT_32         x,              ///< [in] x coordinate
    645     UINT_32         y,              ///< [in] y coordinate
    646     UINT_32         slice,          ///< [in] slice index
    647     AddrTileMode    tileMode,       ///< [in] tile mode
    648     UINT_32         pipeSwizzle,    ///< [in] pipe swizzle
    649     BOOL_32         ignoreSE,       ///< [in] TRUE if shader engines are ignored
    650     ADDR_TILEINFO*  pTileInfo       ///< [in] Tile info
    651     ) const
    652 {
    653     UINT_32 pipe;
    654     UINT_32 pipeBit0 = 0;
    655     UINT_32 pipeBit1 = 0;
    656     UINT_32 pipeBit2 = 0;
    657     UINT_32 pipeBit3 = 0;
    658     UINT_32 sliceRotation;
    659     UINT_32 numPipes = 0;
    660 
    661     UINT_32 tx = x / MicroTileWidth;
    662     UINT_32 ty = y / MicroTileHeight;
    663     UINT_32 x3 = _BIT(tx,0);
    664     UINT_32 x4 = _BIT(tx,1);
    665     UINT_32 x5 = _BIT(tx,2);
    666     UINT_32 x6 = _BIT(tx,3);
    667     UINT_32 y3 = _BIT(ty,0);
    668     UINT_32 y4 = _BIT(ty,1);
    669     UINT_32 y5 = _BIT(ty,2);
    670     UINT_32 y6 = _BIT(ty,3);
    671 
    672     switch (pTileInfo->pipeConfig)
    673     {
    674         case ADDR_PIPECFG_P2:
    675             pipeBit0 = x3 ^ y3;
    676             numPipes = 2;
    677             break;
    678         case ADDR_PIPECFG_P4_8x16:
    679             pipeBit0 = x4 ^ y3;
    680             pipeBit1 = x3 ^ y4;
    681             numPipes = 4;
    682             break;
    683         case ADDR_PIPECFG_P4_16x16:
    684             pipeBit0 = x3 ^ y3 ^ x4;
    685             pipeBit1 = x4 ^ y4;
    686             numPipes = 4;
    687             break;
    688         case ADDR_PIPECFG_P4_16x32:
    689             pipeBit0 = x3 ^ y3 ^ x4;
    690             pipeBit1 = x4 ^ y5;
    691             numPipes = 4;
    692             break;
    693         case ADDR_PIPECFG_P4_32x32:
    694             pipeBit0 = x3 ^ y3 ^ x5;
    695             pipeBit1 = x5 ^ y5;
    696             numPipes = 4;
    697             break;
    698         case ADDR_PIPECFG_P8_16x16_8x16:
    699             pipeBit0 = x4 ^ y3 ^ x5;
    700             pipeBit1 = x3 ^ y5;
    701             numPipes = 8;
    702             break;
    703         case ADDR_PIPECFG_P8_16x32_8x16:
    704             pipeBit0 = x4 ^ y3 ^ x5;
    705             pipeBit1 = x3 ^ y4;
    706             pipeBit2 = x4 ^ y5;
    707             numPipes = 8;
    708             break;
    709         case ADDR_PIPECFG_P8_16x32_16x16:
    710             pipeBit0 = x3 ^ y3 ^ x4;
    711             pipeBit1 = x5 ^ y4;
    712             pipeBit2 = x4 ^ y5;
    713             numPipes = 8;
    714             break;
    715         case ADDR_PIPECFG_P8_32x32_8x16:
    716             pipeBit0 = x4 ^ y3 ^ x5;
    717             pipeBit1 = x3 ^ y4;
    718             pipeBit2 = x5 ^ y5;
    719             numPipes = 8;
    720             break;
    721         case ADDR_PIPECFG_P8_32x32_16x16:
    722             pipeBit0 = x3 ^ y3 ^ x4;
    723             pipeBit1 = x4 ^ y4;
    724             pipeBit2 = x5 ^ y5;
    725             numPipes = 8;
    726             break;
    727         case ADDR_PIPECFG_P8_32x32_16x32:
    728             pipeBit0 = x3 ^ y3 ^ x4;
    729             pipeBit1 = x4 ^ y6;
    730             pipeBit2 = x5 ^ y5;
    731             numPipes = 8;
    732             break;
    733         case ADDR_PIPECFG_P8_32x64_32x32:
    734             pipeBit0 = x3 ^ y3 ^ x5;
    735             pipeBit1 = x6 ^ y5;
    736             pipeBit2 = x5 ^ y6;
    737             numPipes = 8;
    738             break;
    739         case ADDR_PIPECFG_P16_32x32_8x16:
    740             pipeBit0 = x4 ^ y3;
    741             pipeBit1 = x3 ^ y4;
    742             pipeBit2 = x5 ^ y6;
    743             pipeBit3 = x6 ^ y5;
    744             numPipes = 16;
    745             break;
    746         case ADDR_PIPECFG_P16_32x32_16x16:
    747             pipeBit0 = x3 ^ y3 ^ x4;
    748             pipeBit1 = x4 ^ y4;
    749             pipeBit2 = x5 ^ y6;
    750             pipeBit3 = x6 ^ y5;
    751             numPipes = 16;
    752             break;
    753         default:
    754             ADDR_UNHANDLED_CASE();
    755             break;
    756     }
    757     pipe = pipeBit0 | (pipeBit1 << 1) | (pipeBit2 << 2) | (pipeBit3 << 3);
    758 
    759     UINT_32 microTileThickness = Thickness(tileMode);
    760 
    761     //
    762     // Apply pipe rotation for the slice.
    763     //
    764     switch (tileMode)
    765     {
    766         case ADDR_TM_3D_TILED_THIN1:    //fall through thin
    767         case ADDR_TM_3D_TILED_THICK:    //fall through thick
    768         case ADDR_TM_3D_TILED_XTHICK:
    769             sliceRotation =
    770                 Max(1, static_cast<INT_32>(numPipes / 2) - 1) * (slice / microTileThickness);
    771             break;
    772         default:
    773             sliceRotation = 0;
    774             break;
    775     }
    776     pipeSwizzle += sliceRotation;
    777     pipeSwizzle &= (numPipes - 1);
    778 
    779     pipe = pipe ^ pipeSwizzle;
    780 
    781     return pipe;
    782 }
    783 
    784 /**
    785 ****************************************************************************************************
    786 *   SiLib::ComputeTileCoordFromPipeAndElemIdx
    787 *
    788 *   @brief
    789 *       Compute (x,y) of a tile within a macro tile from address
    790 *   @return
    791 *       Pipe number
    792 ****************************************************************************************************
    793 */
    794 VOID SiLib::ComputeTileCoordFromPipeAndElemIdx(
    795     UINT_32         elemIdx,          ///< [in] per pipe element index within a macro tile
    796     UINT_32         pipe,             ///< [in] pipe index
    797     AddrPipeCfg     pipeCfg,          ///< [in] pipe config
    798     UINT_32         pitchInMacroTile, ///< [in] surface pitch in macro tile
    799     UINT_32         x,                ///< [in] x coordinate of the (0,0) tile in a macro tile
    800     UINT_32         y,                ///< [in] y coordinate of the (0,0) tile in a macro tile
    801     UINT_32*        pX,               ///< [out] x coordinate
    802     UINT_32*        pY                ///< [out] y coordinate
    803     ) const
    804 {
    805     UINT_32 pipebit0 = _BIT(pipe,0);
    806     UINT_32 pipebit1 = _BIT(pipe,1);
    807     UINT_32 pipebit2 = _BIT(pipe,2);
    808     UINT_32 pipebit3 = _BIT(pipe,3);
    809     UINT_32 elemIdx0 = _BIT(elemIdx,0);
    810     UINT_32 elemIdx1 = _BIT(elemIdx,1);
    811     UINT_32 elemIdx2 = _BIT(elemIdx,2);
    812     UINT_32 x3 = 0;
    813     UINT_32 x4 = 0;
    814     UINT_32 x5 = 0;
    815     UINT_32 x6 = 0;
    816     UINT_32 y3 = 0;
    817     UINT_32 y4 = 0;
    818     UINT_32 y5 = 0;
    819     UINT_32 y6 = 0;
    820 
    821     switch(pipeCfg)
    822     {
    823         case ADDR_PIPECFG_P2:
    824             x4 = elemIdx2;
    825             y4 = elemIdx1 ^ x4;
    826             y3 = elemIdx0 ^ x4;
    827             x3 = pipebit0 ^ y3;
    828             *pY = Bits2Number(2, y4, y3);
    829             *pX = Bits2Number(2, x4, x3);
    830             break;
    831         case ADDR_PIPECFG_P4_8x16:
    832             x4 = elemIdx1;
    833             y4 = elemIdx0 ^ x4;
    834             x3 = pipebit1 ^ y4;
    835             y3 = pipebit0 ^ x4;
    836             *pY = Bits2Number(2, y4, y3);
    837             *pX = Bits2Number(2, x4, x3);
    838             break;
    839         case ADDR_PIPECFG_P4_16x16:
    840             x4 = elemIdx1;
    841             y3 = elemIdx0 ^ x4;
    842             y4 = pipebit1 ^ x4;
    843             x3 = pipebit0 ^ y3 ^ x4;
    844             *pY = Bits2Number(2, y4, y3);
    845             *pX = Bits2Number(2, x4, x3);
    846             break;
    847         case ADDR_PIPECFG_P4_16x32:
    848             x3 = elemIdx0 ^ pipebit0;
    849             y5 = _BIT(y,5);
    850             x4 = pipebit1 ^ y5;
    851             y3 = pipebit0 ^ x3 ^ x4;
    852             y4 = elemIdx1 ^ x4;
    853             *pY = Bits2Number(2, y4, y3);
    854             *pX = Bits2Number(2, x4, x3);
    855             break;
    856         case ADDR_PIPECFG_P4_32x32:
    857             x4 = elemIdx2;
    858             y3 = elemIdx0 ^ x4;
    859             y4 = elemIdx1 ^ x4;
    860             if((pitchInMacroTile % 2) == 0)
    861             {   //even
    862                 y5 = _BIT(y,5);
    863                 x5 = pipebit1 ^ y5;
    864                 x3 = pipebit0 ^ y3 ^ x5;
    865                 *pY = Bits2Number(2, y4, y3);
    866                 *pX = Bits2Number(3, x5, x4, x3);
    867             }
    868             else
    869             {   //odd
    870                 x5 = _BIT(x,5);
    871                 x3 = pipebit0 ^ y3 ^ x5;
    872                 *pY = Bits2Number(2, y4, y3);
    873                 *pX = Bits2Number(2, x4, x3);
    874             }
    875             break;
    876         case ADDR_PIPECFG_P8_16x16_8x16:
    877             x4 = elemIdx0;
    878             y5 = _BIT(y,5);
    879             x5 = _BIT(x,5);
    880             x3 = pipebit1 ^ y5;
    881             y4 = pipebit2 ^ x4;
    882             y3 = pipebit0 ^ x5 ^ x4;
    883             *pY = Bits2Number(2, y4, y3);
    884             *pX = Bits2Number(2, x4, x3);
    885             break;
    886         case ADDR_PIPECFG_P8_16x32_8x16:
    887             x3 = elemIdx0;
    888             y4 = pipebit1 ^ x3;
    889             y5 = _BIT(y,5);
    890             x5 = _BIT(x,5);
    891             x4 = pipebit2 ^ y5;
    892             y3 = pipebit0 ^ x4 ^ x5;
    893             *pY = Bits2Number(2, y4, y3);
    894             *pX = Bits2Number(2, x4, x3);
    895             break;
    896         case ADDR_PIPECFG_P8_32x32_8x16:
    897             x4 = elemIdx1;
    898             y4 = elemIdx0 ^ x4;
    899             x3 = pipebit1 ^ y4;
    900             if((pitchInMacroTile % 2) == 0)
    901             {  //even
    902                 y5 = _BIT(y,5);
    903                 x5 = _BIT(x,5);
    904                 x5 = pipebit2 ^ y5;
    905                 y3 = pipebit0 ^ x4 ^ x5;
    906                 *pY = Bits2Number(2, y4, y3);
    907                 *pX = Bits2Number(3, x5, x4, x3);
    908             }
    909             else
    910             {  //odd
    911                 x5 = _BIT(x,5);
    912                 y3 = pipebit0 ^ x4 ^ x5;
    913                 *pY = Bits2Number(2, y4, y3);
    914                 *pX = Bits2Number(2, x4, x3);
    915             }
    916             break;
    917         case ADDR_PIPECFG_P8_16x32_16x16:
    918             x3 = elemIdx0;
    919             x5 = _BIT(x,5);
    920             y5 = _BIT(y,5);
    921             x4 = pipebit2 ^ y5;
    922             y4 = pipebit1 ^ x5;
    923             y3 = pipebit0 ^ x3 ^ x4;
    924             *pY = Bits2Number(2, y4, y3);
    925             *pX = Bits2Number(2, x4, x3);
    926             break;
    927         case ADDR_PIPECFG_P8_32x32_16x16:
    928             x4 = elemIdx1;
    929             y3 = elemIdx0 ^ x4;
    930             x3 = y3^x4^pipebit0;
    931             y4 = pipebit1 ^ x4;
    932             if((pitchInMacroTile % 2) == 0)
    933             {   //even
    934                 y5 = _BIT(y,5);
    935                 x5 = pipebit2 ^ y5;
    936                 *pY = Bits2Number(2, y4, y3);
    937                 *pX = Bits2Number(3, x5, x4, x3);
    938             }
    939             else
    940             {   //odd
    941                 *pY = Bits2Number(2, y4, y3);
    942                 *pX = Bits2Number(2, x4, x3);
    943             }
    944             break;
    945         case ADDR_PIPECFG_P8_32x32_16x32:
    946             if((pitchInMacroTile % 2) == 0)
    947             {   //even
    948                 y5 = _BIT(y,5);
    949                 y6 = _BIT(y,6);
    950                 x4 = pipebit1 ^ y6;
    951                 y3 = elemIdx0 ^ x4;
    952                 y4 = elemIdx1 ^ x4;
    953                 x3 = pipebit0 ^ y3 ^ x4;
    954                 x5 = pipebit2 ^ y5;
    955                 *pY = Bits2Number(2, y4, y3);
    956                 *pX = Bits2Number(3, x5, x4, x3);
    957             }
    958             else
    959             {   //odd
    960                 y6 = _BIT(y,6);
    961                 x4 = pipebit1 ^ y6;
    962                 y3 = elemIdx0 ^ x4;
    963                 y4 = elemIdx1 ^ x4;
    964                 x3 = pipebit0 ^ y3 ^ x4;
    965                 *pY = Bits2Number(2, y4, y3);
    966                 *pX = Bits2Number(2, x4, x3);
    967             }
    968             break;
    969         case ADDR_PIPECFG_P8_32x64_32x32:
    970             x4 = elemIdx2;
    971             y3 = elemIdx0 ^ x4;
    972             y4 = elemIdx1 ^ x4;
    973             if((pitchInMacroTile % 4) == 0)
    974             {   //multiple of 4
    975                 y5 = _BIT(y,5);
    976                 y6 = _BIT(y,6);
    977                 x5 = pipebit2 ^ y6;
    978                 x6 = pipebit1 ^ y5;
    979                 x3 = pipebit0 ^ y3 ^ x5;
    980                 *pY = Bits2Number(2, y4, y3);
    981                 *pX = Bits2Number(4, x6, x5, x4, x3);
    982             }
    983             else
    984             {
    985                 y6 = _BIT(y,6);
    986                 x5 = pipebit2 ^ y6;
    987                 x3 = pipebit0 ^ y3 ^ x5;
    988                 *pY = Bits2Number(2, y4, y3);
    989                 *pX = Bits2Number(3, x5, x4, x3);
    990             }
    991             break;
    992         case ADDR_PIPECFG_P16_32x32_8x16:
    993             x4 = elemIdx1;
    994             y4 = elemIdx0 ^ x4;
    995             y3 = pipebit0 ^ x4;
    996             x3 = pipebit1 ^ y4;
    997             if((pitchInMacroTile % 4) == 0)
    998             {   //multiple of 4
    999                 y5 = _BIT(y,5);
   1000                 y6 = _BIT(y,6);
   1001                 x5 = pipebit2 ^ y6;
   1002                 x6 = pipebit3 ^ y5;
   1003                 *pY = Bits2Number(2, y4, y3);
   1004                 *pX = Bits2Number(4, x6, x5,x4, x3);
   1005             }
   1006             else
   1007             {
   1008                 y6 = _BIT(y,6);
   1009                 x5 = pipebit2 ^ y6;
   1010                 *pY = Bits2Number(2, y4, y3);
   1011                 *pX = Bits2Number(3, x5, x4, x3);
   1012             }
   1013             break;
   1014         case ADDR_PIPECFG_P16_32x32_16x16:
   1015             x4 = elemIdx1;
   1016             y3 = elemIdx0 ^ x4;
   1017             y4 = pipebit1 ^ x4;
   1018             x3 = pipebit0 ^ y3 ^ x4;
   1019             if((pitchInMacroTile % 4) == 0)
   1020             {   //multiple of 4
   1021                 y5 = _BIT(y,5);
   1022                 y6 = _BIT(y,6);
   1023                 x5 = pipebit2 ^ y6;
   1024                 x6 = pipebit3 ^ y5;
   1025                 *pY = Bits2Number(2, y4, y3);
   1026                 *pX = Bits2Number(4, x6, x5, x4, x3);
   1027             }
   1028             else
   1029             {
   1030                 y6 = _BIT(y,6);
   1031                 x5 = pipebit2 ^ y6;
   1032                 *pY = Bits2Number(2, y4, y3);
   1033                 *pX = Bits2Number(3, x5, x4, x3);
   1034             }
   1035             break;
   1036         default:
   1037             ADDR_UNHANDLED_CASE();
   1038     }
   1039 }
   1040 
   1041 /**
   1042 ****************************************************************************************************
   1043 *   SiLib::TileCoordToMaskElementIndex
   1044 *
   1045 *   @brief
   1046 *       Compute element index from coordinates in tiles
   1047 *   @return
   1048 *       Element index
   1049 ****************************************************************************************************
   1050 */
   1051 UINT_32 SiLib::TileCoordToMaskElementIndex(
   1052     UINT_32         tx,                 ///< [in] x coord, in Tiles
   1053     UINT_32         ty,                 ///< [in] y coord, in Tiles
   1054     AddrPipeCfg     pipeConfig,         ///< [in] pipe config
   1055     UINT_32*        macroShift,         ///< [out] macro shift
   1056     UINT_32*        elemIdxBits         ///< [out] tile offset bits
   1057     ) const
   1058 {
   1059     UINT_32 elemIdx = 0;
   1060     UINT_32 elemIdx0, elemIdx1, elemIdx2;
   1061     UINT_32 tx0, tx1;
   1062     UINT_32 ty0, ty1;
   1063 
   1064     tx0 = _BIT(tx,0);
   1065     tx1 = _BIT(tx,1);
   1066     ty0 = _BIT(ty,0);
   1067     ty1 = _BIT(ty,1);
   1068 
   1069     switch(pipeConfig)
   1070     {
   1071         case ADDR_PIPECFG_P2:
   1072             *macroShift = 3;
   1073             *elemIdxBits =3;
   1074             elemIdx2 = tx1;
   1075             elemIdx1 = tx1 ^ ty1;
   1076             elemIdx0 = tx1 ^ ty0;
   1077             elemIdx = Bits2Number(3,elemIdx2,elemIdx1,elemIdx0);
   1078             break;
   1079         case ADDR_PIPECFG_P4_8x16:
   1080             *macroShift = 2;
   1081             *elemIdxBits =2;
   1082             elemIdx1 = tx1;
   1083             elemIdx0 = tx1 ^ ty1;
   1084             elemIdx = Bits2Number(2,elemIdx1,elemIdx0);
   1085             break;
   1086         case ADDR_PIPECFG_P4_16x16:
   1087             *macroShift = 2;
   1088             *elemIdxBits =2;
   1089             elemIdx0 = tx1^ty0;
   1090             elemIdx1 = tx1;
   1091             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
   1092             break;
   1093         case ADDR_PIPECFG_P4_16x32:
   1094             *macroShift = 2;
   1095             *elemIdxBits =2;
   1096             elemIdx0 = tx1^ty0;
   1097             elemIdx1 = tx1^ty1;
   1098             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
   1099             break;
   1100         case ADDR_PIPECFG_P4_32x32:
   1101             *macroShift = 2;
   1102             *elemIdxBits =3;
   1103             elemIdx0 = tx1^ty0;
   1104             elemIdx1 = tx1^ty1;
   1105             elemIdx2 = tx1;
   1106             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
   1107             break;
   1108         case ADDR_PIPECFG_P8_16x16_8x16:
   1109             *macroShift = 1;
   1110             *elemIdxBits =1;
   1111             elemIdx0 = tx1;
   1112             elemIdx = elemIdx0;
   1113             break;
   1114         case ADDR_PIPECFG_P8_16x32_8x16:
   1115             *macroShift = 1;
   1116             *elemIdxBits =1;
   1117             elemIdx0 = tx0;
   1118             elemIdx = elemIdx0;
   1119             break;
   1120         case ADDR_PIPECFG_P8_32x32_8x16:
   1121             *macroShift = 1;
   1122             *elemIdxBits =2;
   1123             elemIdx1 = tx1;
   1124             elemIdx0 = tx1^ty1;
   1125             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
   1126             break;
   1127         case ADDR_PIPECFG_P8_16x32_16x16:
   1128             *macroShift = 1;
   1129             *elemIdxBits =1;
   1130             elemIdx0 = tx0;
   1131             elemIdx = elemIdx0;
   1132             break;
   1133         case ADDR_PIPECFG_P8_32x32_16x16:
   1134             *macroShift = 1;
   1135             *elemIdxBits =2;
   1136             elemIdx0 = tx1^ty0;
   1137             elemIdx1 = tx1;
   1138             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
   1139             break;
   1140         case ADDR_PIPECFG_P8_32x32_16x32:
   1141             *macroShift = 1;
   1142             *elemIdxBits =2;
   1143             elemIdx0 =  tx1^ty0;
   1144             elemIdx1 = tx1^ty1;
   1145             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
   1146             break;
   1147         case ADDR_PIPECFG_P8_32x64_32x32:
   1148             *macroShift = 1;
   1149             *elemIdxBits =3;
   1150             elemIdx0 = tx1^ty0;
   1151             elemIdx1 = tx1^ty1;
   1152             elemIdx2 = tx1;
   1153             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
   1154             break;
   1155         case ADDR_PIPECFG_P16_32x32_8x16:
   1156             *macroShift = 0;
   1157             *elemIdxBits =2;
   1158             elemIdx0 = tx1^ty1;
   1159             elemIdx1 = tx1;
   1160             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
   1161             break;
   1162         case ADDR_PIPECFG_P16_32x32_16x16:
   1163             *macroShift = 0;
   1164             *elemIdxBits =2;
   1165             elemIdx0 = tx1^ty0;
   1166             elemIdx1 = tx1;
   1167             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
   1168             break;
   1169         default:
   1170             ADDR_UNHANDLED_CASE();
   1171             break;
   1172     }
   1173 
   1174     return elemIdx;
   1175 }
   1176 
   1177 /**
   1178 ****************************************************************************************************
   1179 *   SiLib::HwlComputeTileDataWidthAndHeightLinear
   1180 *
   1181 *   @brief
   1182 *       Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
   1183 *
   1184 *   @return
   1185 *       N/A
   1186 *
   1187 *   @note
   1188 *       MacroWidth and macroHeight are measured in pixels
   1189 ****************************************************************************************************
   1190 */
   1191 VOID SiLib::HwlComputeTileDataWidthAndHeightLinear(
   1192     UINT_32*        pMacroWidth,     ///< [out] macro tile width
   1193     UINT_32*        pMacroHeight,    ///< [out] macro tile height
   1194     UINT_32         bpp,             ///< [in] bits per pixel
   1195     ADDR_TILEINFO*  pTileInfo        ///< [in] tile info
   1196     ) const
   1197 {
   1198     ADDR_ASSERT(pTileInfo != NULL);
   1199     UINT_32 macroWidth;
   1200     UINT_32 macroHeight;
   1201 
   1202     /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles
   1203     /// but for P8_32x64_32x32, it must be padded out to 8 tiles
   1204     /// Actually there are more pipe configs which need 8-tile padding but SI family
   1205     /// has a bug which is fixed in CI family
   1206     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) ||
   1207         (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
   1208         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x32_16x16))
   1209     {
   1210         macroWidth  = 8*MicroTileWidth;
   1211         macroHeight = 8*MicroTileHeight;
   1212     }
   1213     else
   1214     {
   1215         macroWidth  = 4*MicroTileWidth;
   1216         macroHeight = 4*MicroTileHeight;
   1217     }
   1218 
   1219     *pMacroWidth    = macroWidth;
   1220     *pMacroHeight   = macroHeight;
   1221 }
   1222 
   1223 /**
   1224 ****************************************************************************************************
   1225 *   SiLib::HwlComputeHtileBytes
   1226 *
   1227 *   @brief
   1228 *       Compute htile size in bytes
   1229 *
   1230 *   @return
   1231 *       Htile size in bytes
   1232 ****************************************************************************************************
   1233 */
   1234 UINT_64 SiLib::HwlComputeHtileBytes(
   1235     UINT_32     pitch,          ///< [in] pitch
   1236     UINT_32     height,         ///< [in] height
   1237     UINT_32     bpp,            ///< [in] bits per pixel
   1238     BOOL_32     isLinear,       ///< [in] if it is linear mode
   1239     UINT_32     numSlices,      ///< [in] number of slices
   1240     UINT_64*    pSliceBytes,    ///< [out] bytes per slice
   1241     UINT_32     baseAlign       ///< [in] base alignments
   1242     ) const
   1243 {
   1244     return ComputeHtileBytes(pitch, height, bpp, isLinear, numSlices, pSliceBytes, baseAlign);
   1245 }
   1246 
   1247 /**
   1248 ****************************************************************************************************
   1249 *   SiLib::HwlComputeXmaskAddrFromCoord
   1250 *
   1251 *   @brief
   1252 *       Compute address from coordinates for htile/cmask
   1253 *   @return
   1254 *       Byte address
   1255 ****************************************************************************************************
   1256 */
   1257 UINT_64 SiLib::HwlComputeXmaskAddrFromCoord(
   1258     UINT_32        pitch,          ///< [in] pitch
   1259     UINT_32        height,         ///< [in] height
   1260     UINT_32        x,              ///< [in] x coord
   1261     UINT_32        y,              ///< [in] y coord
   1262     UINT_32        slice,          ///< [in] slice/depth index
   1263     UINT_32        numSlices,      ///< [in] number of slices
   1264     UINT_32        factor,         ///< [in] factor that indicates cmask(2) or htile(1)
   1265     BOOL_32        isLinear,       ///< [in] linear or tiled HTILE layout
   1266     BOOL_32        isWidth8,       ///< [in] TRUE if width is 8, FALSE means 4. It's register value
   1267     BOOL_32        isHeight8,      ///< [in] TRUE if width is 8, FALSE means 4. It's register value
   1268     ADDR_TILEINFO* pTileInfo,      ///< [in] Tile info
   1269     UINT_32*       pBitPosition    ///< [out] bit position inside a byte
   1270     ) const
   1271 {
   1272     UINT_32 tx = x / MicroTileWidth;
   1273     UINT_32 ty = y / MicroTileHeight;
   1274     UINT_32 newPitch;
   1275     UINT_32 newHeight;
   1276     UINT_64 totalBytes;
   1277     UINT_32 macroWidth;
   1278     UINT_32 macroHeight;
   1279     UINT_64 pSliceBytes;
   1280     UINT_32 pBaseAlign;
   1281     UINT_32 tileNumPerPipe;
   1282     UINT_32 elemBits;
   1283 
   1284     if (factor == 2) //CMASK
   1285     {
   1286         ADDR_CMASK_FLAGS flags = {{0}};
   1287 
   1288         tileNumPerPipe = 256;
   1289 
   1290         ComputeCmaskInfo(flags,
   1291                          pitch,
   1292                          height,
   1293                          numSlices,
   1294                          isLinear,
   1295                          pTileInfo,
   1296                          &newPitch,
   1297                          &newHeight,
   1298                          &totalBytes,
   1299                          &macroWidth,
   1300                          &macroHeight);
   1301         elemBits = CmaskElemBits;
   1302     }
   1303     else //HTile
   1304     {
   1305         ADDR_HTILE_FLAGS flags = {{0}};
   1306 
   1307         tileNumPerPipe = 512;
   1308 
   1309         ComputeHtileInfo(flags,
   1310                          pitch,
   1311                          height,
   1312                          numSlices,
   1313                          isLinear,
   1314                          TRUE,
   1315                          TRUE,
   1316                          pTileInfo,
   1317                          &newPitch,
   1318                          &newHeight,
   1319                          &totalBytes,
   1320                          &macroWidth,
   1321                          &macroHeight,
   1322                          &pSliceBytes,
   1323                          &pBaseAlign);
   1324         elemBits = 32;
   1325     }
   1326 
   1327     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
   1328     const UINT_32 heightInTile = newHeight / MicroTileWidth;
   1329     UINT_64 macroOffset; // Per pipe starting offset of the macro tile in which this tile lies.
   1330     UINT_64 microNumber; // Per pipe starting offset of the macro tile in which this tile lies.
   1331     UINT_32 microX;
   1332     UINT_32 microY;
   1333     UINT_64 microOffset;
   1334     UINT_32 microShift;
   1335     UINT_64 totalOffset;
   1336     UINT_32 elemIdxBits;
   1337     UINT_32 elemIdx =
   1338         TileCoordToMaskElementIndex(tx, ty, pTileInfo->pipeConfig, &microShift, &elemIdxBits);
   1339 
   1340     UINT_32 numPipes = HwlGetPipes(pTileInfo);
   1341 
   1342     if (isLinear)
   1343     {   //linear addressing
   1344         // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full
   1345         // slice memory foot print instead of divided by numPipes.
   1346         microX = tx / 4; // Macro Tile is 4x4
   1347         microY = ty / 4 ;
   1348         microNumber = static_cast<UINT_64>(microX + microY * (pitchInTile / 4)) << microShift;
   1349 
   1350         UINT_32 sliceBits = pitchInTile * heightInTile;
   1351 
   1352         // do htile single slice alignment if the flag is true
   1353         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
   1354         {
   1355             sliceBits = PowTwoAlign(sliceBits, BITS_TO_BYTES(HtileCacheBits) * numPipes / elemBits);
   1356         }
   1357         macroOffset = slice * (sliceBits / numPipes) * elemBits ;
   1358     }
   1359     else
   1360     {   //tiled addressing
   1361         const UINT_32 macroWidthInTile = macroWidth / MicroTileWidth; // Now in unit of Tiles
   1362         const UINT_32 macroHeightInTile = macroHeight / MicroTileHeight;
   1363         const UINT_32 pitchInCL = pitchInTile / macroWidthInTile;
   1364         const UINT_32 heightInCL = heightInTile / macroHeightInTile;
   1365 
   1366         const UINT_32 macroX = x / macroWidth;
   1367         const UINT_32 macroY = y / macroHeight;
   1368         const UINT_32 macroNumber = macroX + macroY * pitchInCL + slice * pitchInCL * heightInCL;
   1369 
   1370         // Per pipe starting offset of the cache line in which this tile lies.
   1371         microX = (x % macroWidth) / MicroTileWidth / 4; // Macro Tile is 4x4
   1372         microY = (y % macroHeight) / MicroTileHeight / 4 ;
   1373         microNumber = static_cast<UINT_64>(microX + microY * (macroWidth / MicroTileWidth / 4)) << microShift;
   1374 
   1375         macroOffset = macroNumber * tileNumPerPipe * elemBits;
   1376     }
   1377 
   1378     if(elemIdxBits == microShift)
   1379     {
   1380         microNumber += elemIdx;
   1381     }
   1382     else
   1383     {
   1384         microNumber >>= elemIdxBits;
   1385         microNumber <<= elemIdxBits;
   1386         microNumber += elemIdx;
   1387     }
   1388 
   1389     microOffset = elemBits * microNumber;
   1390     totalOffset = microOffset + macroOffset;
   1391 
   1392     UINT_32 pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo);
   1393     UINT_64 addrInBits = totalOffset % (m_pipeInterleaveBytes * 8) +
   1394                    pipe * (m_pipeInterleaveBytes * 8) +
   1395                    totalOffset / (m_pipeInterleaveBytes * 8) * (m_pipeInterleaveBytes * 8) * numPipes;
   1396     *pBitPosition = static_cast<UINT_32>(addrInBits) % 8;
   1397     UINT_64 addr = addrInBits / 8;
   1398 
   1399     return addr;
   1400 }
   1401 
   1402 /**
   1403 ****************************************************************************************************
   1404 *   SiLib::HwlComputeXmaskCoordFromAddr
   1405 *
   1406 *   @brief
   1407 *       Compute the coord from an address of a cmask/htile
   1408 *
   1409 *   @return
   1410 *       N/A
   1411 *
   1412 *   @note
   1413 *       This method is reused by htile, so rename to Xmask
   1414 ****************************************************************************************************
   1415 */
   1416 VOID SiLib::HwlComputeXmaskCoordFromAddr(
   1417     UINT_64         addr,           ///< [in] address
   1418     UINT_32         bitPosition,    ///< [in] bitPosition in a byte
   1419     UINT_32         pitch,          ///< [in] pitch
   1420     UINT_32         height,         ///< [in] height
   1421     UINT_32         numSlices,      ///< [in] number of slices
   1422     UINT_32         factor,         ///< [in] factor that indicates cmask or htile
   1423     BOOL_32         isLinear,       ///< [in] linear or tiled HTILE layout
   1424     BOOL_32         isWidth8,       ///< [in] Not used by SI
   1425     BOOL_32         isHeight8,      ///< [in] Not used by SI
   1426     ADDR_TILEINFO*  pTileInfo,      ///< [in] Tile info
   1427     UINT_32*        pX,             ///< [out] x coord
   1428     UINT_32*        pY,             ///< [out] y coord
   1429     UINT_32*        pSlice          ///< [out] slice index
   1430     ) const
   1431 {
   1432     UINT_32 newPitch;
   1433     UINT_32 newHeight;
   1434     UINT_64 totalBytes;
   1435     UINT_32 clWidth;
   1436     UINT_32 clHeight;
   1437     UINT_32 tileNumPerPipe;
   1438     UINT_64 sliceBytes;
   1439 
   1440     *pX = 0;
   1441     *pY = 0;
   1442     *pSlice = 0;
   1443 
   1444     if (factor == 2) //CMASK
   1445     {
   1446         ADDR_CMASK_FLAGS flags = {{0}};
   1447 
   1448         tileNumPerPipe = 256;
   1449 
   1450         ComputeCmaskInfo(flags,
   1451                          pitch,
   1452                          height,
   1453                          numSlices,
   1454                          isLinear,
   1455                          pTileInfo,
   1456                          &newPitch,
   1457                          &newHeight,
   1458                          &totalBytes,
   1459                          &clWidth,
   1460                          &clHeight);
   1461     }
   1462     else //HTile
   1463     {
   1464         ADDR_HTILE_FLAGS flags = {{0}};
   1465 
   1466         tileNumPerPipe = 512;
   1467 
   1468         ComputeHtileInfo(flags,
   1469                          pitch,
   1470                          height,
   1471                          numSlices,
   1472                          isLinear,
   1473                          TRUE,
   1474                          TRUE,
   1475                          pTileInfo,
   1476                          &newPitch,
   1477                          &newHeight,
   1478                          &totalBytes,
   1479                          &clWidth,
   1480                          &clHeight,
   1481                          &sliceBytes);
   1482     }
   1483 
   1484     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
   1485     const UINT_32 heightInTile = newHeight / MicroTileWidth;
   1486     const UINT_32 pitchInMacroTile = pitchInTile / 4;
   1487     UINT_32 macroShift;
   1488     UINT_32 elemIdxBits;
   1489     // get macroShift and elemIdxBits
   1490     TileCoordToMaskElementIndex(0, 0, pTileInfo->pipeConfig, &macroShift, &elemIdxBits);
   1491 
   1492     const UINT_32 numPipes = HwlGetPipes(pTileInfo);
   1493     const UINT_32 pipe = (UINT_32)((addr / m_pipeInterleaveBytes) % numPipes);
   1494     // per pipe
   1495     UINT_64 localOffset = (addr % m_pipeInterleaveBytes) +
   1496         (addr / m_pipeInterleaveBytes / numPipes)* m_pipeInterleaveBytes;
   1497 
   1498     UINT_32 tileIndex;
   1499     if (factor == 2) //CMASK
   1500     {
   1501         tileIndex = (UINT_32)(localOffset * 2 + (bitPosition != 0));
   1502     }
   1503     else
   1504     {
   1505         tileIndex = (UINT_32)(localOffset / 4);
   1506     }
   1507 
   1508     UINT_32 macroOffset;
   1509     if (isLinear)
   1510     {
   1511         UINT_32 sliceSizeInTile = pitchInTile * heightInTile;
   1512 
   1513         // do htile single slice alignment if the flag is true
   1514         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
   1515         {
   1516             sliceSizeInTile = PowTwoAlign(sliceSizeInTile, static_cast<UINT_32>(sliceBytes) / 64);
   1517         }
   1518         *pSlice = tileIndex / (sliceSizeInTile / numPipes);
   1519         macroOffset = tileIndex % (sliceSizeInTile / numPipes);
   1520     }
   1521     else
   1522     {
   1523         const UINT_32 clWidthInTile = clWidth / MicroTileWidth; // Now in unit of Tiles
   1524         const UINT_32 clHeightInTile = clHeight / MicroTileHeight;
   1525         const UINT_32 pitchInCL = pitchInTile / clWidthInTile;
   1526         const UINT_32 heightInCL = heightInTile / clHeightInTile;
   1527         const UINT_32 clIndex = tileIndex / tileNumPerPipe;
   1528 
   1529         UINT_32 clX = clIndex % pitchInCL;
   1530         UINT_32 clY = (clIndex % (heightInCL * pitchInCL)) / pitchInCL;
   1531 
   1532         *pX = clX * clWidthInTile * MicroTileWidth;
   1533         *pY = clY * clHeightInTile * MicroTileHeight;
   1534         *pSlice = clIndex / (heightInCL * pitchInCL);
   1535 
   1536         macroOffset = tileIndex % tileNumPerPipe;
   1537     }
   1538 
   1539     UINT_32 elemIdx = macroOffset & 7;
   1540     macroOffset >>= elemIdxBits;
   1541 
   1542     if (elemIdxBits != macroShift)
   1543     {
   1544         macroOffset <<= (elemIdxBits - macroShift);
   1545 
   1546         UINT_32 pipebit1 = _BIT(pipe,1);
   1547         UINT_32 pipebit2 = _BIT(pipe,2);
   1548         UINT_32 pipebit3 = _BIT(pipe,3);
   1549         if (pitchInMacroTile % 2)
   1550         {   //odd
   1551             switch (pTileInfo->pipeConfig)
   1552             {
   1553                 case ADDR_PIPECFG_P4_32x32:
   1554                     macroOffset |= pipebit1;
   1555                     break;
   1556                 case ADDR_PIPECFG_P8_32x32_8x16:
   1557                 case ADDR_PIPECFG_P8_32x32_16x16:
   1558                 case ADDR_PIPECFG_P8_32x32_16x32:
   1559                     macroOffset |= pipebit2;
   1560                     break;
   1561                 default:
   1562                     break;
   1563             }
   1564 
   1565         }
   1566 
   1567         if (pitchInMacroTile % 4)
   1568         {
   1569             if (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)
   1570             {
   1571                 macroOffset |= (pipebit1<<1);
   1572             }
   1573             if((pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
   1574                (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_16x16))
   1575             {
   1576                 macroOffset |= (pipebit3<<1);
   1577             }
   1578         }
   1579     }
   1580 
   1581     UINT_32 macroX;
   1582     UINT_32 macroY;
   1583 
   1584     if (isLinear)
   1585     {
   1586         macroX = macroOffset % pitchInMacroTile;
   1587         macroY = macroOffset / pitchInMacroTile;
   1588     }
   1589     else
   1590     {
   1591         const UINT_32 clWidthInMacroTile = clWidth / (MicroTileWidth * 4);
   1592         macroX = macroOffset % clWidthInMacroTile;
   1593         macroY = macroOffset / clWidthInMacroTile;
   1594     }
   1595 
   1596     *pX += macroX * 4 * MicroTileWidth;
   1597     *pY += macroY * 4 * MicroTileHeight;
   1598 
   1599     UINT_32 microX;
   1600     UINT_32 microY;
   1601     ComputeTileCoordFromPipeAndElemIdx(elemIdx, pipe, pTileInfo->pipeConfig, pitchInMacroTile,
   1602                                        *pX, *pY, &microX, &microY);
   1603 
   1604     *pX += microX * MicroTileWidth;
   1605     *pY += microY * MicroTileWidth;
   1606 }
   1607 
   1608 /**
   1609 ****************************************************************************************************
   1610 *   SiLib::HwlGetPitchAlignmentLinear
   1611 *   @brief
   1612 *       Get pitch alignment
   1613 *   @return
   1614 *       pitch alignment
   1615 ****************************************************************************************************
   1616 */
   1617 UINT_32 SiLib::HwlGetPitchAlignmentLinear(
   1618     UINT_32             bpp,    ///< [in] bits per pixel
   1619     ADDR_SURFACE_FLAGS  flags   ///< [in] surface flags
   1620     ) const
   1621 {
   1622     UINT_32 pitchAlign;
   1623 
   1624     // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment
   1625     if (flags.interleaved)
   1626     {
   1627         pitchAlign = Max(64u, m_pipeInterleaveBytes / BITS_TO_BYTES(bpp));
   1628 
   1629     }
   1630     else
   1631     {
   1632         pitchAlign = Max(8u, 64 / BITS_TO_BYTES(bpp));
   1633     }
   1634 
   1635     return pitchAlign;
   1636 }
   1637 
   1638 /**
   1639 ****************************************************************************************************
   1640 *   SiLib::HwlGetSizeAdjustmentLinear
   1641 *
   1642 *   @brief
   1643 *       Adjust linear surface pitch and slice size
   1644 *
   1645 *   @return
   1646 *       Logical slice size in bytes
   1647 ****************************************************************************************************
   1648 */
   1649 UINT_64 SiLib::HwlGetSizeAdjustmentLinear(
   1650     AddrTileMode        tileMode,       ///< [in] tile mode
   1651     UINT_32             bpp,            ///< [in] bits per pixel
   1652     UINT_32             numSamples,     ///< [in] number of samples
   1653     UINT_32             baseAlign,      ///< [in] base alignment
   1654     UINT_32             pitchAlign,     ///< [in] pitch alignment
   1655     UINT_32*            pPitch,         ///< [in,out] pointer to pitch
   1656     UINT_32*            pHeight,        ///< [in,out] pointer to height
   1657     UINT_32*            pHeightAlign    ///< [in,out] pointer to height align
   1658     ) const
   1659 {
   1660     UINT_64 sliceSize;
   1661     if (tileMode == ADDR_TM_LINEAR_GENERAL)
   1662     {
   1663         sliceSize = BITS_TO_BYTES(static_cast<UINT_64>(*pPitch) * (*pHeight) * bpp * numSamples);
   1664     }
   1665     else
   1666     {
   1667         UINT_32 pitch   = *pPitch;
   1668         UINT_32 height  = *pHeight;
   1669 
   1670         UINT_32 pixelsPerPipeInterleave = m_pipeInterleaveBytes / BITS_TO_BYTES(bpp);
   1671         UINT_32 sliceAlignInPixel = pixelsPerPipeInterleave < 64 ? 64 : pixelsPerPipeInterleave;
   1672 
   1673         // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value)
   1674         UINT_64 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
   1675 
   1676         while (pixelPerSlice % sliceAlignInPixel)
   1677         {
   1678             pitch += pitchAlign;
   1679             pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
   1680         }
   1681 
   1682         *pPitch = pitch;
   1683 
   1684         UINT_32 heightAlign = 1;
   1685 
   1686         while ((pitch * heightAlign) % sliceAlignInPixel)
   1687         {
   1688             heightAlign++;
   1689         }
   1690 
   1691         *pHeightAlign = heightAlign;
   1692 
   1693         sliceSize = BITS_TO_BYTES(pixelPerSlice * bpp);
   1694     }
   1695 
   1696     return sliceSize;
   1697 }
   1698 
   1699 /**
   1700 ****************************************************************************************************
   1701 *   SiLib::HwlPreHandleBaseLvl3xPitch
   1702 *
   1703 *   @brief
   1704 *       Pre-handler of 3x pitch (96 bit) adjustment
   1705 *
   1706 *   @return
   1707 *       Expected pitch
   1708 ****************************************************************************************************
   1709 */
   1710 UINT_32 SiLib::HwlPreHandleBaseLvl3xPitch(
   1711     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
   1712     UINT_32                                 expPitch    ///< [in] pitch
   1713     ) const
   1714 {
   1715     ADDR_ASSERT(pIn->width == expPitch);
   1716 
   1717     // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to
   1718     // do here
   1719     if (pIn->flags.pow2Pad == FALSE)
   1720     {
   1721         Addr::V1::Lib::HwlPreHandleBaseLvl3xPitch(pIn, expPitch);
   1722     }
   1723     else
   1724     {
   1725         ADDR_ASSERT(IsPow2(expPitch));
   1726     }
   1727 
   1728     return expPitch;
   1729 }
   1730 
   1731 /**
   1732 ****************************************************************************************************
   1733 *   SiLib::HwlPostHandleBaseLvl3xPitch
   1734 *
   1735 *   @brief
   1736 *       Post-handler of 3x pitch adjustment
   1737 *
   1738 *   @return
   1739 *       Expected pitch
   1740 ****************************************************************************************************
   1741 */
   1742 UINT_32 SiLib::HwlPostHandleBaseLvl3xPitch(
   1743     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
   1744     UINT_32                                 expPitch    ///< [in] pitch
   1745     ) const
   1746 {
   1747     /**
   1748      * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should
   1749      *  be able to compute a correct pitch from it as h/w address library is doing the job.
   1750      */
   1751     // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here
   1752     if (pIn->flags.pow2Pad == FALSE)
   1753     {
   1754         Addr::V1::Lib::HwlPostHandleBaseLvl3xPitch(pIn, expPitch);
   1755     }
   1756 
   1757     return expPitch;
   1758 }
   1759 
   1760 /**
   1761 ****************************************************************************************************
   1762 *   SiLib::HwlGetPitchAlignmentMicroTiled
   1763 *
   1764 *   @brief
   1765 *       Compute 1D tiled surface pitch alignment
   1766 *
   1767 *   @return
   1768 *       pitch alignment
   1769 ****************************************************************************************************
   1770 */
   1771 UINT_32 SiLib::HwlGetPitchAlignmentMicroTiled(
   1772     AddrTileMode        tileMode,          ///< [in] tile mode
   1773     UINT_32             bpp,               ///< [in] bits per pixel
   1774     ADDR_SURFACE_FLAGS  flags,             ///< [in] surface flags
   1775     UINT_32             numSamples         ///< [in] number of samples
   1776     ) const
   1777 {
   1778     UINT_32 pitchAlign;
   1779 
   1780     if (flags.qbStereo)
   1781     {
   1782         pitchAlign = EgBasedLib::HwlGetPitchAlignmentMicroTiled(tileMode,bpp,flags,numSamples);
   1783     }
   1784     else
   1785     {
   1786         pitchAlign = 8;
   1787     }
   1788 
   1789     return pitchAlign;
   1790 }
   1791 
   1792 /**
   1793 ****************************************************************************************************
   1794 *   SiLib::HwlGetSizeAdjustmentMicroTiled
   1795 *
   1796 *   @brief
   1797 *       Adjust 1D tiled surface pitch and slice size
   1798 *
   1799 *   @return
   1800 *       Logical slice size in bytes
   1801 ****************************************************************************************************
   1802 */
   1803 UINT_64 SiLib::HwlGetSizeAdjustmentMicroTiled(
   1804     UINT_32             thickness,      ///< [in] thickness
   1805     UINT_32             bpp,            ///< [in] bits per pixel
   1806     ADDR_SURFACE_FLAGS  flags,          ///< [in] surface flags
   1807     UINT_32             numSamples,     ///< [in] number of samples
   1808     UINT_32             baseAlign,      ///< [in] base alignment
   1809     UINT_32             pitchAlign,     ///< [in] pitch alignment
   1810     UINT_32*            pPitch,         ///< [in,out] pointer to pitch
   1811     UINT_32*            pHeight         ///< [in,out] pointer to height
   1812     ) const
   1813 {
   1814     UINT_64 logicalSliceSize;
   1815     UINT_64 physicalSliceSize;
   1816 
   1817     UINT_32 pitch   = *pPitch;
   1818     UINT_32 height  = *pHeight;
   1819 
   1820     // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1)
   1821     logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
   1822 
   1823     // Physical slice: multiplied by thickness
   1824     physicalSliceSize =  logicalSliceSize * thickness;
   1825 
   1826     // Pitch alignment is always 8, so if slice size is not padded to base alignment
   1827     // (pipe_interleave_size), we need to increase pitch
   1828     while ((physicalSliceSize % baseAlign) != 0)
   1829     {
   1830         pitch += pitchAlign;
   1831 
   1832         logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
   1833 
   1834         physicalSliceSize =  logicalSliceSize * thickness;
   1835     }
   1836 
   1837 #if !ALT_TEST
   1838     //
   1839     // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since
   1840     // the stencil plane may have larger pitch if the slice size is smaller than base alignment.
   1841     //
   1842     // Note: this actually does not work for mipmap but mipmap depth texture is not really
   1843     // sampled with mipmap.
   1844     //
   1845     if (flags.depth && (flags.noStencil == FALSE))
   1846     {
   1847         ADDR_ASSERT(numSamples == 1);
   1848 
   1849         UINT_64 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; // 1 byte stencil
   1850 
   1851         while ((logicalSiceSizeStencil % baseAlign) != 0)
   1852         {
   1853             pitch += pitchAlign; // Stencil plane's pitch alignment is the same as depth plane's
   1854 
   1855             logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height;
   1856         }
   1857 
   1858         if (pitch != *pPitch)
   1859         {
   1860             // If this is a mipmap, this padded one cannot be sampled as a whole mipmap!
   1861             logicalSliceSize = logicalSiceSizeStencil * BITS_TO_BYTES(bpp);
   1862         }
   1863     }
   1864 #endif
   1865     *pPitch = pitch;
   1866 
   1867     // No adjust for pHeight
   1868 
   1869     return logicalSliceSize;
   1870 }
   1871 
   1872 /**
   1873 ****************************************************************************************************
   1874 *   SiLib::HwlConvertChipFamily
   1875 *
   1876 *   @brief
   1877 *       Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
   1878 *   @return
   1879 *       ChipFamily
   1880 ****************************************************************************************************
   1881 */
   1882 ChipFamily SiLib::HwlConvertChipFamily(
   1883     UINT_32 uChipFamily,        ///< [in] chip family defined in atiih.h
   1884     UINT_32 uChipRevision)      ///< [in] chip revision defined in "asic_family"_id.h
   1885 {
   1886     ChipFamily family = ADDR_CHIP_FAMILY_SI;
   1887 
   1888     switch (uChipFamily)
   1889     {
   1890         case FAMILY_SI:
   1891             m_settings.isSouthernIsland = 1;
   1892             m_settings.isTahiti     = ASICREV_IS_TAHITI_P(uChipRevision);
   1893             m_settings.isPitCairn   = ASICREV_IS_PITCAIRN_PM(uChipRevision);
   1894             m_settings.isCapeVerde  = ASICREV_IS_CAPEVERDE_M(uChipRevision);
   1895             m_settings.isOland      = ASICREV_IS_OLAND_M(uChipRevision);
   1896             m_settings.isHainan     = ASICREV_IS_HAINAN_V(uChipRevision);
   1897             break;
   1898         default:
   1899             ADDR_ASSERT(!"This should be a Fusion");
   1900             break;
   1901     }
   1902 
   1903     return family;
   1904 }
   1905 
   1906 /**
   1907 ****************************************************************************************************
   1908 *   SiLib::HwlSetupTileInfo
   1909 *
   1910 *   @brief
   1911 *       Setup default value of tile info for SI
   1912 ****************************************************************************************************
   1913 */
   1914 VOID SiLib::HwlSetupTileInfo(
   1915     AddrTileMode                        tileMode,       ///< [in] Tile mode
   1916     ADDR_SURFACE_FLAGS                  flags,          ///< [in] Surface type flags
   1917     UINT_32                             bpp,            ///< [in] Bits per pixel
   1918     UINT_32                             pitch,          ///< [in] Pitch in pixels
   1919     UINT_32                             height,         ///< [in] Height in pixels
   1920     UINT_32                             numSamples,     ///< [in] Number of samples
   1921     ADDR_TILEINFO*                      pTileInfoIn,    ///< [in] Tile info input: NULL for default
   1922     ADDR_TILEINFO*                      pTileInfoOut,   ///< [out] Tile info output
   1923     AddrTileType                        inTileType,     ///< [in] Tile type
   1924     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*   pOut            ///< [out] Output
   1925     ) const
   1926 {
   1927     UINT_32 thickness = Thickness(tileMode);
   1928     ADDR_TILEINFO* pTileInfo = pTileInfoOut;
   1929     INT index = TileIndexInvalid;
   1930 
   1931     // Fail-safe code
   1932     if (IsLinear(tileMode) == FALSE)
   1933     {
   1934         // 128 bpp/thick tiling must be non-displayable.
   1935         // Fmask reuse color buffer's entry but bank-height field can be from another entry
   1936         // To simplify the logic, fmask entry should be picked from non-displayable ones
   1937         if (bpp == 128 || thickness > 1 || flags.fmask || flags.prt)
   1938         {
   1939             inTileType = ADDR_NON_DISPLAYABLE;
   1940         }
   1941 
   1942         if (flags.depth || flags.stencil)
   1943         {
   1944             inTileType = ADDR_DEPTH_SAMPLE_ORDER;
   1945         }
   1946     }
   1947 
   1948     // Partial valid fields are not allowed for SI.
   1949     if (IsTileInfoAllZero(pTileInfo))
   1950     {
   1951         if (IsMacroTiled(tileMode))
   1952         {
   1953             if (flags.prt)
   1954             {
   1955                 if (numSamples == 1)
   1956                 {
   1957                     if (flags.depth)
   1958                     {
   1959                         switch (bpp)
   1960                         {
   1961                             case 16:
   1962                                 index = 3;
   1963                                 break;
   1964                             case 32:
   1965                                 index = 6;
   1966                                 break;
   1967                             default:
   1968                                 ADDR_ASSERT_ALWAYS();
   1969                                 break;
   1970                         }
   1971                     }
   1972                     else
   1973                     {
   1974                         switch (bpp)
   1975                         {
   1976                             case 8:
   1977                                 index = 21;
   1978                                 break;
   1979                             case 16:
   1980                                 index = 22;
   1981                                 break;
   1982                             case 32:
   1983                                 index = 23;
   1984                                 break;
   1985                             case 64:
   1986                                 index = 24;
   1987                                 break;
   1988                             case 128:
   1989                                 index = 25;
   1990                                 break;
   1991                             default:
   1992                                 break;
   1993                         }
   1994 
   1995                         if (thickness > 1)
   1996                         {
   1997                             ADDR_ASSERT(bpp != 128);
   1998                             index += 5;
   1999                         }
   2000                     }
   2001                 }
   2002                 else
   2003                 {
   2004                     ADDR_ASSERT(numSamples == 4);
   2005 
   2006                     if (flags.depth)
   2007                     {
   2008                         switch (bpp)
   2009                         {
   2010                             case 16:
   2011                                 index = 5;
   2012                                 break;
   2013                             case 32:
   2014                                 index = 7;
   2015                                 break;
   2016                             default:
   2017                                 ADDR_ASSERT_ALWAYS();
   2018                                 break;
   2019                         }
   2020                     }
   2021                     else
   2022                     {
   2023                         switch (bpp)
   2024                         {
   2025                             case 8:
   2026                                 index = 23;
   2027                                 break;
   2028                             case 16:
   2029                                 index = 24;
   2030                                 break;
   2031                             case 32:
   2032                                 index = 25;
   2033                                 break;
   2034                             case 64:
   2035                                 index = 30;
   2036                                 break;
   2037                             default:
   2038                                 ADDR_ASSERT_ALWAYS();
   2039                                 break;
   2040                         }
   2041                     }
   2042                 }
   2043             }//end of PRT part
   2044             // See table entries 0-7
   2045             else if (flags.depth || flags.stencil)
   2046             {
   2047                 if (flags.compressZ)
   2048                 {
   2049                     if (flags.stencil)
   2050                     {
   2051                         index = 0;
   2052                     }
   2053                     else
   2054                     {
   2055                         // optimal tile index for compressed depth/stencil.
   2056                         switch (numSamples)
   2057                         {
   2058                             case 1:
   2059                                 index = 0;
   2060                                 break;
   2061                             case 2:
   2062                             case 4:
   2063                                 index = 1;
   2064                                 break;
   2065                             case 8:
   2066                                 index = 2;
   2067                                 break;
   2068                             default:
   2069                                 break;
   2070                         }
   2071                     }
   2072                 }
   2073                 else // unCompressZ
   2074                 {
   2075                     index = 3;
   2076                 }
   2077             }
   2078             else //non PRT & non Depth & non Stencil
   2079             {
   2080                 // See table entries 9-12
   2081                 if (inTileType == ADDR_DISPLAYABLE)
   2082                 {
   2083                     switch (bpp)
   2084                     {
   2085                         case 8:
   2086                             index = 10;
   2087                             break;
   2088                         case 16:
   2089                             index = 11;
   2090                             break;
   2091                         case 32:
   2092                             index = 12;
   2093                             break;
   2094                         case 64:
   2095                             index = 12;
   2096                             break;
   2097                         default:
   2098                             break;
   2099                     }
   2100                 }
   2101                 else
   2102                 {
   2103                     // See table entries 13-17
   2104                     if (thickness == 1)
   2105                     {
   2106                         if (flags.fmask)
   2107                         {
   2108                             UINT_32 fmaskPixelSize = bpp * numSamples;
   2109 
   2110                             switch (fmaskPixelSize)
   2111                             {
   2112                                 case 8:
   2113                                     index = 14;
   2114                                     break;
   2115                                 case 16:
   2116                                     index = 15;
   2117                                     break;
   2118                                 case 32:
   2119                                     index = 16;
   2120                                     break;
   2121                                 case 64:
   2122                                     index = 17;
   2123                                     break;
   2124                                 default:
   2125                                     ADDR_ASSERT_ALWAYS();
   2126                             }
   2127                         }
   2128                         else
   2129                         {
   2130                             switch (bpp)
   2131                             {
   2132                                 case 8:
   2133                                     index = 14;
   2134                                     break;
   2135                                 case 16:
   2136                                     index = 15;
   2137                                     break;
   2138                                 case 32:
   2139                                     index = 16;
   2140                                     break;
   2141                                 case 64:
   2142                                     index = 17;
   2143                                     break;
   2144                                 case 128:
   2145                                     index = 17;
   2146                                     break;
   2147                                 default:
   2148                                     break;
   2149                             }
   2150                         }
   2151                     }
   2152                     else // thick tiling - entries 18-20
   2153                     {
   2154                         switch (thickness)
   2155                         {
   2156                             case 4:
   2157                                 index = 20;
   2158                                 break;
   2159                             case 8:
   2160                                 index = 19;
   2161                                 break;
   2162                             default:
   2163                                 break;
   2164                         }
   2165                     }
   2166                 }
   2167             }
   2168         }
   2169         else
   2170         {
   2171             if (tileMode == ADDR_TM_LINEAR_ALIGNED)
   2172             {
   2173                 index = 8;
   2174             }
   2175             else if (tileMode == ADDR_TM_LINEAR_GENERAL)
   2176             {
   2177                 index = TileIndexLinearGeneral;
   2178             }
   2179             else
   2180             {
   2181                 if (flags.depth || flags.stencil)
   2182                 {
   2183                     index = 4;
   2184                 }
   2185                 else if (inTileType == ADDR_DISPLAYABLE)
   2186                 {
   2187                     index = 9;
   2188                 }
   2189                 else if (thickness == 1)
   2190                 {
   2191                     index = 13;
   2192                 }
   2193                 else
   2194                 {
   2195                     index = 18;
   2196                 }
   2197             }
   2198         }
   2199 
   2200         if (index >= 0 && index <= 31)
   2201         {
   2202             *pTileInfo      = m_tileTable[index].info;
   2203             pOut->tileType  = m_tileTable[index].type;
   2204         }
   2205 
   2206         if (index == TileIndexLinearGeneral)
   2207         {
   2208             *pTileInfo      = m_tileTable[8].info;
   2209             pOut->tileType  = m_tileTable[8].type;
   2210         }
   2211     }
   2212     else
   2213     {
   2214         if (pTileInfoIn)
   2215         {
   2216             if (flags.stencil && pTileInfoIn->tileSplitBytes == 0)
   2217             {
   2218                 // Stencil always uses index 0
   2219                 *pTileInfo = m_tileTable[0].info;
   2220             }
   2221         }
   2222         // Pass through tile type
   2223         pOut->tileType = inTileType;
   2224     }
   2225 
   2226     pOut->tileIndex = index;
   2227     pOut->prtTileIndex = flags.prt;
   2228 }
   2229 
   2230 /**
   2231 ****************************************************************************************************
   2232 *   SiLib::DecodeGbRegs
   2233 *
   2234 *   @brief
   2235 *       Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks
   2236 *
   2237 *   @return
   2238 *       TRUE if all settings are valid
   2239 *
   2240 ****************************************************************************************************
   2241 */
   2242 BOOL_32 SiLib::DecodeGbRegs(
   2243     const ADDR_REGISTER_VALUE* pRegValue) ///< [in] create input
   2244 {
   2245     GB_ADDR_CONFIG  reg;
   2246     BOOL_32         valid = TRUE;
   2247 
   2248     reg.val = pRegValue->gbAddrConfig;
   2249 
   2250     switch (reg.f.pipe_interleave_size)
   2251     {
   2252         case ADDR_CONFIG_PIPE_INTERLEAVE_256B:
   2253             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_256B;
   2254             break;
   2255         case ADDR_CONFIG_PIPE_INTERLEAVE_512B:
   2256             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_512B;
   2257             break;
   2258         default:
   2259             valid = FALSE;
   2260             ADDR_UNHANDLED_CASE();
   2261             break;
   2262     }
   2263 
   2264     switch (reg.f.row_size)
   2265     {
   2266         case ADDR_CONFIG_1KB_ROW:
   2267             m_rowSize = ADDR_ROWSIZE_1KB;
   2268             break;
   2269         case ADDR_CONFIG_2KB_ROW:
   2270             m_rowSize = ADDR_ROWSIZE_2KB;
   2271             break;
   2272         case ADDR_CONFIG_4KB_ROW:
   2273             m_rowSize = ADDR_ROWSIZE_4KB;
   2274             break;
   2275         default:
   2276             valid = FALSE;
   2277             ADDR_UNHANDLED_CASE();
   2278             break;
   2279     }
   2280 
   2281     switch (pRegValue->noOfBanks)
   2282     {
   2283         case 0:
   2284             m_banks = 4;
   2285             break;
   2286         case 1:
   2287             m_banks = 8;
   2288             break;
   2289         case 2:
   2290             m_banks = 16;
   2291             break;
   2292         default:
   2293             valid = FALSE;
   2294             ADDR_UNHANDLED_CASE();
   2295             break;
   2296     }
   2297 
   2298     switch (pRegValue->noOfRanks)
   2299     {
   2300         case 0:
   2301             m_ranks = 1;
   2302             break;
   2303         case 1:
   2304             m_ranks = 2;
   2305             break;
   2306         default:
   2307             valid = FALSE;
   2308             ADDR_UNHANDLED_CASE();
   2309             break;
   2310     }
   2311 
   2312     m_logicalBanks = m_banks * m_ranks;
   2313 
   2314     ADDR_ASSERT(m_logicalBanks <= 16);
   2315 
   2316     return valid;
   2317 }
   2318 
   2319 /**
   2320 ****************************************************************************************************
   2321 *   SiLib::HwlInitGlobalParams
   2322 *
   2323 *   @brief
   2324 *       Initializes global parameters
   2325 *
   2326 *   @return
   2327 *       TRUE if all settings are valid
   2328 *
   2329 ****************************************************************************************************
   2330 */
   2331 BOOL_32 SiLib::HwlInitGlobalParams(
   2332     const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input
   2333 {
   2334     BOOL_32 valid = TRUE;
   2335     const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue;
   2336 
   2337     valid = DecodeGbRegs(pRegValue);
   2338 
   2339     if (valid)
   2340     {
   2341         if (m_settings.isTahiti || m_settings.isPitCairn)
   2342         {
   2343             m_pipes = 8;
   2344         }
   2345         else if (m_settings.isCapeVerde || m_settings.isOland)
   2346         {
   2347             m_pipes = 4;
   2348         }
   2349         else
   2350         {
   2351             // Hainan is 2-pipe (m_settings.isHainan == 1)
   2352             m_pipes = 2;
   2353         }
   2354 
   2355         valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
   2356 
   2357         if (valid)
   2358         {
   2359             InitEquationTable();
   2360         }
   2361 
   2362         m_maxSamples = 16;
   2363     }
   2364 
   2365     return valid;
   2366 }
   2367 
   2368 /**
   2369 ****************************************************************************************************
   2370 *   SiLib::HwlConvertTileInfoToHW
   2371 *   @brief
   2372 *       Entry of si's ConvertTileInfoToHW
   2373 *   @return
   2374 *       ADDR_E_RETURNCODE
   2375 ****************************************************************************************************
   2376 */
   2377 ADDR_E_RETURNCODE SiLib::HwlConvertTileInfoToHW(
   2378     const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
   2379     ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut      ///< [out] output structure
   2380     ) const
   2381 {
   2382     ADDR_E_RETURNCODE retCode   = ADDR_OK;
   2383 
   2384     retCode = EgBasedLib::HwlConvertTileInfoToHW(pIn, pOut);
   2385 
   2386     if (retCode == ADDR_OK)
   2387     {
   2388         if (pIn->reverse == FALSE)
   2389         {
   2390             if (pIn->pTileInfo->pipeConfig == ADDR_PIPECFG_INVALID)
   2391             {
   2392                 retCode = ADDR_INVALIDPARAMS;
   2393             }
   2394             else
   2395             {
   2396                 pOut->pTileInfo->pipeConfig =
   2397                     static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig - 1);
   2398             }
   2399         }
   2400         else
   2401         {
   2402             pOut->pTileInfo->pipeConfig =
   2403                 static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig + 1);
   2404         }
   2405     }
   2406 
   2407     return retCode;
   2408 }
   2409 
   2410 /**
   2411 ****************************************************************************************************
   2412 *   SiLib::HwlComputeXmaskCoordYFrom8Pipe
   2413 *
   2414 *   @brief
   2415 *       Compute the Y coord which will be added to Xmask Y
   2416 *       coord.
   2417 *   @return
   2418 *       Y coord
   2419 ****************************************************************************************************
   2420 */
   2421 UINT_32 SiLib::HwlComputeXmaskCoordYFrom8Pipe(
   2422     UINT_32         pipe,       ///< [in] pipe id
   2423     UINT_32         x           ///< [in] tile coord x, which is original x coord / 8
   2424     ) const
   2425 {
   2426     // This function should never be called since it is 6xx/8xx specfic.
   2427     // Keep this empty implementation to avoid any mis-use.
   2428     ADDR_ASSERT_ALWAYS();
   2429 
   2430     return 0;
   2431 }
   2432 
   2433 /**
   2434 ****************************************************************************************************
   2435 *   SiLib::HwlComputeSurfaceCoord2DFromBankPipe
   2436 *
   2437 *   @brief
   2438 *       Compute surface x,y coordinates from bank/pipe info
   2439 *   @return
   2440 *       N/A
   2441 ****************************************************************************************************
   2442 */
   2443 VOID SiLib::HwlComputeSurfaceCoord2DFromBankPipe(
   2444     AddrTileMode        tileMode,   ///< [in] tile mode
   2445     UINT_32*            pX,         ///< [in,out] x coordinate
   2446     UINT_32*            pY,         ///< [in,out] y coordinate
   2447     UINT_32             slice,      ///< [in] slice index
   2448     UINT_32             bank,       ///< [in] bank number
   2449     UINT_32             pipe,       ///< [in] pipe number
   2450     UINT_32             bankSwizzle,///< [in] bank swizzle
   2451     UINT_32             pipeSwizzle,///< [in] pipe swizzle
   2452     UINT_32             tileSlices, ///< [in] slices in a micro tile
   2453     BOOL_32             ignoreSE,   ///< [in] TRUE if shader engines are ignored
   2454     ADDR_TILEINFO*      pTileInfo   ///< [in] bank structure. **All fields to be valid on entry**
   2455     ) const
   2456 {
   2457     UINT_32 xBit;
   2458     UINT_32 yBit;
   2459     UINT_32 yBit3 = 0;
   2460     UINT_32 yBit4 = 0;
   2461     UINT_32 yBit5 = 0;
   2462     UINT_32 yBit6 = 0;
   2463 
   2464     UINT_32 xBit3 = 0;
   2465     UINT_32 xBit4 = 0;
   2466     UINT_32 xBit5 = 0;
   2467 
   2468     UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
   2469 
   2470     CoordFromBankPipe xyBits = {0};
   2471     ComputeSurfaceCoord2DFromBankPipe(tileMode, *pX, *pY, slice, bank, pipe,
   2472                                       bankSwizzle, pipeSwizzle, tileSlices, pTileInfo,
   2473                                       &xyBits);
   2474     yBit3 = xyBits.yBit3;
   2475     yBit4 = xyBits.yBit4;
   2476     yBit5 = xyBits.yBit5;
   2477     yBit6 = xyBits.yBit6;
   2478 
   2479     xBit3 = xyBits.xBit3;
   2480     xBit4 = xyBits.xBit4;
   2481     xBit5 = xyBits.xBit5;
   2482 
   2483     yBit = xyBits.yBits;
   2484 
   2485     UINT_32 yBitTemp = 0;
   2486 
   2487     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
   2488         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32))
   2489     {
   2490         ADDR_ASSERT(pTileInfo->bankWidth == 1 && pTileInfo->macroAspectRatio > 1);
   2491         UINT_32 yBitToCheck = QLog2(pTileInfo->banks) - 1;
   2492 
   2493         ADDR_ASSERT(yBitToCheck <= 3);
   2494 
   2495         yBitTemp = _BIT(yBit, yBitToCheck);
   2496 
   2497         xBit3 = 0;
   2498     }
   2499 
   2500     yBit = Bits2Number(4, yBit6, yBit5, yBit4, yBit3);
   2501     xBit = Bits2Number(3, xBit5, xBit4, xBit3);
   2502 
   2503     *pY += yBit * pTileInfo->bankHeight * MicroTileHeight;
   2504     *pX += xBit * numPipes * pTileInfo->bankWidth * MicroTileWidth;
   2505 
   2506     //calculate the bank and pipe bits in x, y
   2507     UINT_32 xTile; //x in micro tile
   2508     UINT_32 x3 = 0;
   2509     UINT_32 x4 = 0;
   2510     UINT_32 x5 = 0;
   2511     UINT_32 x6 = 0;
   2512     UINT_32 y = *pY;
   2513 
   2514     UINT_32 pipeBit0 = _BIT(pipe,0);
   2515     UINT_32 pipeBit1 = _BIT(pipe,1);
   2516     UINT_32 pipeBit2 = _BIT(pipe,2);
   2517 
   2518     UINT_32 y3 = _BIT(y, 3);
   2519     UINT_32 y4 = _BIT(y, 4);
   2520     UINT_32 y5 = _BIT(y, 5);
   2521     UINT_32 y6 = _BIT(y, 6);
   2522 
   2523     // bankbit0 after ^x4^x5
   2524     UINT_32 bankBit00 = _BIT(bank,0);
   2525     UINT_32 bankBit0 = 0;
   2526 
   2527     switch (pTileInfo->pipeConfig)
   2528     {
   2529         case ADDR_PIPECFG_P2:
   2530             x3 = pipeBit0 ^ y3;
   2531             break;
   2532         case ADDR_PIPECFG_P4_8x16:
   2533             x4 = pipeBit0 ^ y3;
   2534             x3 = pipeBit0 ^ y4;
   2535             break;
   2536         case ADDR_PIPECFG_P4_16x16:
   2537             x4 = pipeBit1 ^ y4;
   2538             x3 = pipeBit0 ^ y3 ^ x4;
   2539             break;
   2540         case ADDR_PIPECFG_P4_16x32:
   2541             x4 = pipeBit1 ^ y4;
   2542             x3 = pipeBit0 ^ y3 ^ x4;
   2543             break;
   2544         case ADDR_PIPECFG_P4_32x32:
   2545             x5 = pipeBit1 ^ y5;
   2546             x3 = pipeBit0 ^ y3 ^ x5;
   2547             bankBit0 = yBitTemp ^ x5;
   2548             x4 = bankBit00 ^ x5 ^ bankBit0;
   2549             *pX += x5 * 4 * 1 * 8; // x5 * num_pipes * bank_width * 8;
   2550             break;
   2551         case ADDR_PIPECFG_P8_16x16_8x16:
   2552             x3 = pipeBit1 ^ y5;
   2553             x4 = pipeBit2 ^ y4;
   2554             x5 = pipeBit0 ^ y3 ^ x4;
   2555             break;
   2556         case ADDR_PIPECFG_P8_16x32_8x16:
   2557             x3 = pipeBit1 ^ y4;
   2558             x4 = pipeBit2 ^ y5;
   2559             x5 = pipeBit0 ^ y3 ^ x4;
   2560             break;
   2561         case ADDR_PIPECFG_P8_32x32_8x16:
   2562             x3 = pipeBit1 ^ y4;
   2563             x5 = pipeBit2 ^ y5;
   2564             x4 = pipeBit0 ^ y3 ^ x5;
   2565             break;
   2566         case ADDR_PIPECFG_P8_16x32_16x16:
   2567             x4 = pipeBit2 ^ y5;
   2568             x5 = pipeBit1 ^ y4;
   2569             x3 = pipeBit0 ^ y3 ^ x4;
   2570             break;
   2571         case ADDR_PIPECFG_P8_32x32_16x16:
   2572             x5 = pipeBit2 ^ y5;
   2573             x4 = pipeBit1 ^ y4;
   2574             x3 = pipeBit0 ^ y3 ^ x4;
   2575             break;
   2576         case ADDR_PIPECFG_P8_32x32_16x32:
   2577             x5 = pipeBit2 ^ y5;
   2578             x4 = pipeBit1 ^ y6;
   2579             x3 = pipeBit0 ^ y3 ^ x4;
   2580             break;
   2581         case ADDR_PIPECFG_P8_32x64_32x32:
   2582             x6 = pipeBit1 ^ y5;
   2583             x5 = pipeBit2 ^ y6;
   2584             x3 = pipeBit0 ^ y3 ^ x5;
   2585             bankBit0 = yBitTemp ^ x6;
   2586             x4 = bankBit00 ^ x5 ^ bankBit0;
   2587             *pX += x6 * 8 * 1 * 8; // x6 * num_pipes * bank_width * 8;
   2588             break;
   2589         default:
   2590             ADDR_ASSERT_ALWAYS();
   2591     }
   2592 
   2593     xTile = Bits2Number(3, x5, x4, x3);
   2594 
   2595     *pX += xTile << 3;
   2596 }
   2597 
   2598 /**
   2599 ****************************************************************************************************
   2600 *   SiLib::HwlPreAdjustBank
   2601 *
   2602 *   @brief
   2603 *       Adjust bank before calculating address acoording to bank/pipe
   2604 *   @return
   2605 *       Adjusted bank
   2606 ****************************************************************************************************
   2607 */
   2608 UINT_32 SiLib::HwlPreAdjustBank(
   2609     UINT_32         tileX,      ///< [in] x coordinate in unit of tile
   2610     UINT_32         bank,       ///< [in] bank
   2611     ADDR_TILEINFO*  pTileInfo   ///< [in] tile info
   2612     ) const
   2613 {
   2614     if (((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
   2615         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) && (pTileInfo->bankWidth == 1))
   2616     {
   2617         UINT_32 bankBit0 = _BIT(bank, 0);
   2618         UINT_32 x4 = _BIT(tileX, 1);
   2619         UINT_32 x5 = _BIT(tileX, 2);
   2620 
   2621         bankBit0 = bankBit0 ^ x4 ^ x5;
   2622         bank |= bankBit0;
   2623 
   2624         ADDR_ASSERT(pTileInfo->macroAspectRatio > 1);
   2625     }
   2626 
   2627     return bank;
   2628 }
   2629 
   2630 /**
   2631 ****************************************************************************************************
   2632 *   SiLib::HwlComputeSurfaceInfo
   2633 *
   2634 *   @brief
   2635 *       Entry of si's ComputeSurfaceInfo
   2636 *   @return
   2637 *       ADDR_E_RETURNCODE
   2638 ****************************************************************************************************
   2639 */
   2640 ADDR_E_RETURNCODE SiLib::HwlComputeSurfaceInfo(
   2641     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,    ///< [in] input structure
   2642     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [out] output structure
   2643     ) const
   2644 {
   2645     pOut->tileIndex = pIn->tileIndex;
   2646 
   2647     ADDR_E_RETURNCODE retCode = EgBasedLib::HwlComputeSurfaceInfo(pIn, pOut);
   2648 
   2649     UINT_32 tileIndex = static_cast<UINT_32>(pOut->tileIndex);
   2650 
   2651     if (((pIn->flags.needEquation   == TRUE) ||
   2652          (pIn->flags.preferEquation == TRUE)) &&
   2653         (pIn->numSamples <= 1) &&
   2654         (tileIndex < TileTableSize))
   2655     {
   2656         static const UINT_32 SiUncompressDepthTileIndex = 3;
   2657 
   2658         if ((pIn->numSlices > 1) &&
   2659             (IsMacroTiled(pOut->tileMode) == TRUE) &&
   2660             ((m_chipFamily == ADDR_CHIP_FAMILY_SI) ||
   2661              (IsPrtTileMode(pOut->tileMode) == FALSE)))
   2662         {
   2663             pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX;
   2664         }
   2665         else if ((pIn->flags.prt == FALSE) &&
   2666                  (m_uncompressDepthEqIndex != 0) &&
   2667                  (tileIndex == SiUncompressDepthTileIndex))
   2668         {
   2669             pOut->equationIndex = m_uncompressDepthEqIndex + Log2(pIn->bpp >> 3);
   2670         }
   2671         else
   2672         {
   2673 
   2674             pOut->equationIndex = m_equationLookupTable[Log2(pIn->bpp >> 3)][tileIndex];
   2675         }
   2676 
   2677         if (pOut->equationIndex != ADDR_INVALID_EQUATION_INDEX)
   2678         {
   2679             pOut->blockWidth = m_blockWidth[pOut->equationIndex];
   2680 
   2681             pOut->blockHeight = m_blockHeight[pOut->equationIndex];
   2682 
   2683             pOut->blockSlices = m_blockSlices[pOut->equationIndex];
   2684         }
   2685     }
   2686     else
   2687     {
   2688         pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX;
   2689     }
   2690 
   2691     return retCode;
   2692 }
   2693 
   2694 /**
   2695 ****************************************************************************************************
   2696 *   SiLib::HwlComputeMipLevel
   2697 *   @brief
   2698 *       Compute MipLevel info (including level 0)
   2699 *   @return
   2700 *       TRUE if HWL's handled
   2701 ****************************************************************************************************
   2702 */
   2703 BOOL_32 SiLib::HwlComputeMipLevel(
   2704     ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in,out] Input structure
   2705     ) const
   2706 {
   2707     // basePitch is calculated from level 0 so we only check this for mipLevel > 0
   2708     if (pIn->mipLevel > 0)
   2709     {
   2710         // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if
   2711         // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being
   2712         // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2.
   2713         if (ElemLib::IsExpand3x(pIn->format) == FALSE)
   2714         {
   2715             // Sublevel pitches are generated from base level pitch instead of width on SI
   2716             // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain
   2717             ADDR_ASSERT((pIn->flags.pow2Pad == FALSE) ||
   2718                         ((pIn->basePitch != 0) && IsPow2(pIn->basePitch)));
   2719         }
   2720 
   2721         if (pIn->basePitch != 0)
   2722         {
   2723             pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel);
   2724         }
   2725     }
   2726 
   2727     // pow2Pad is done in PostComputeMipLevel
   2728 
   2729     return TRUE;
   2730 }
   2731 
   2732 /**
   2733 ****************************************************************************************************
   2734 *   SiLib::HwlCheckLastMacroTiledLvl
   2735 *
   2736 *   @brief
   2737 *       Sets pOut->last2DLevel to TRUE if it is
   2738 *   @note
   2739 *
   2740 ****************************************************************************************************
   2741 */
   2742 VOID SiLib::HwlCheckLastMacroTiledLvl(
   2743     const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
   2744     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut      ///< [in,out] Output structure (used as input, too)
   2745     ) const
   2746 {
   2747     // pow2Pad covers all mipmap cases
   2748     if (pIn->flags.pow2Pad)
   2749     {
   2750         ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
   2751 
   2752         UINT_32 nextPitch;
   2753         UINT_32 nextHeight;
   2754         UINT_32 nextSlices;
   2755 
   2756         AddrTileMode nextTileMode;
   2757 
   2758         if (pIn->mipLevel == 0 || pIn->basePitch == 0)
   2759         {
   2760             // Base level or fail-safe case (basePitch == 0)
   2761             nextPitch = pOut->pitch >> 1;
   2762         }
   2763         else
   2764         {
   2765             // Sub levels
   2766             nextPitch = pIn->basePitch >> (pIn->mipLevel + 1);
   2767         }
   2768 
   2769         // nextHeight must be shifted from this level's original height rather than a pow2 padded
   2770         // one but this requires original height stored somewhere (pOut->height)
   2771         ADDR_ASSERT(pOut->height != 0);
   2772 
   2773         // next level's height is just current level's >> 1 in pixels
   2774         nextHeight = pOut->height >> 1;
   2775         // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block
   2776         // compressed foramts
   2777         if (ElemLib::IsBlockCompressed(pIn->format))
   2778         {
   2779             nextHeight = (nextHeight + 3) / 4;
   2780         }
   2781         nextHeight = NextPow2(nextHeight);
   2782 
   2783         // nextSlices may be 0 if this level's is 1
   2784         if (pIn->flags.volume)
   2785         {
   2786             nextSlices = Max(1u, pIn->numSlices >> 1);
   2787         }
   2788         else
   2789         {
   2790             nextSlices = pIn->numSlices;
   2791         }
   2792 
   2793         nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode,
   2794                                                       pIn->bpp,
   2795                                                       nextPitch,
   2796                                                       nextHeight,
   2797                                                       nextSlices,
   2798                                                       pIn->numSamples,
   2799                                                       pOut->blockWidth,
   2800                                                       pOut->blockHeight,
   2801                                                       pOut->pTileInfo);
   2802 
   2803         pOut->last2DLevel = IsMicroTiled(nextTileMode);
   2804     }
   2805 }
   2806 
   2807 /**
   2808 ****************************************************************************************************
   2809 *   SiLib::HwlDegradeThickTileMode
   2810 *
   2811 *   @brief
   2812 *       Degrades valid tile mode for thick modes if needed
   2813 *
   2814 *   @return
   2815 *       Suitable tile mode
   2816 ****************************************************************************************************
   2817 */
   2818 AddrTileMode SiLib::HwlDegradeThickTileMode(
   2819     AddrTileMode        baseTileMode,   ///< base tile mode
   2820     UINT_32             numSlices,      ///< current number of slices
   2821     UINT_32*            pBytesPerTile   ///< [in,out] pointer to bytes per slice
   2822     ) const
   2823 {
   2824     return EgBasedLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile);
   2825 }
   2826 
   2827 /**
   2828 ****************************************************************************************************
   2829 *   SiLib::HwlTileInfoEqual
   2830 *
   2831 *   @brief
   2832 *       Return TRUE if all field are equal
   2833 *   @note
   2834 *       Only takes care of current HWL's data
   2835 ****************************************************************************************************
   2836 */
   2837 BOOL_32 SiLib::HwlTileInfoEqual(
   2838     const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand
   2839     const ADDR_TILEINFO* pRight ///<[in] Right compare operand
   2840     ) const
   2841 {
   2842     BOOL_32 equal = FALSE;
   2843 
   2844     if (pLeft->pipeConfig == pRight->pipeConfig)
   2845     {
   2846         equal =  EgBasedLib::HwlTileInfoEqual(pLeft, pRight);
   2847     }
   2848 
   2849     return equal;
   2850 }
   2851 
   2852 /**
   2853 ****************************************************************************************************
   2854 *   SiLib::GetTileSettings
   2855 *
   2856 *   @brief
   2857 *       Get tile setting infos by index.
   2858 *   @return
   2859 *       Tile setting info.
   2860 ****************************************************************************************************
   2861 */
   2862 const TileConfig* SiLib::GetTileSetting(
   2863     UINT_32 index          ///< [in] Tile index
   2864     ) const
   2865 {
   2866     ADDR_ASSERT(index < m_noOfEntries);
   2867     return &m_tileTable[index];
   2868 }
   2869 
   2870 /**
   2871 ****************************************************************************************************
   2872 *   SiLib::HwlPostCheckTileIndex
   2873 *
   2874 *   @brief
   2875 *       Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
   2876 *       tile mode/type/info and change the index if needed
   2877 *   @return
   2878 *       Tile index.
   2879 ****************************************************************************************************
   2880 */
   2881 INT_32 SiLib::HwlPostCheckTileIndex(
   2882     const ADDR_TILEINFO* pInfo,     ///< [in] Tile Info
   2883     AddrTileMode         mode,      ///< [in] Tile mode
   2884     AddrTileType         type,      ///< [in] Tile type
   2885     INT                  curIndex   ///< [in] Current index assigned in HwlSetupTileInfo
   2886     ) const
   2887 {
   2888     INT_32 index = curIndex;
   2889 
   2890     if (mode == ADDR_TM_LINEAR_GENERAL)
   2891     {
   2892         index = TileIndexLinearGeneral;
   2893     }
   2894     else
   2895     {
   2896         BOOL_32 macroTiled = IsMacroTiled(mode);
   2897 
   2898         // We need to find a new index if either of them is true
   2899         // 1. curIndex is invalid
   2900         // 2. tile mode is changed
   2901         // 3. tile info does not match for macro tiled
   2902         if ((index == TileIndexInvalid         ||
   2903             (mode != m_tileTable[index].mode)  ||
   2904             (macroTiled && (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) == FALSE))))
   2905         {
   2906             for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
   2907             {
   2908                 if (macroTiled)
   2909                 {
   2910                     // macro tile modes need all to match
   2911                     if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) &&
   2912                         (mode == m_tileTable[index].mode)                 &&
   2913                         (type == m_tileTable[index].type))
   2914                     {
   2915                         break;
   2916                     }
   2917                 }
   2918                 else if (mode == ADDR_TM_LINEAR_ALIGNED)
   2919                 {
   2920                     // linear mode only needs tile mode to match
   2921                     if (mode == m_tileTable[index].mode)
   2922                     {
   2923                         break;
   2924                     }
   2925                 }
   2926                 else
   2927                 {
   2928                     // micro tile modes only need tile mode and tile type to match
   2929                     if (mode == m_tileTable[index].mode &&
   2930                         type == m_tileTable[index].type)
   2931                     {
   2932                         break;
   2933                     }
   2934                 }
   2935             }
   2936         }
   2937     }
   2938 
   2939     ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
   2940 
   2941     if (index >= static_cast<INT_32>(m_noOfEntries))
   2942     {
   2943         index = TileIndexInvalid;
   2944     }
   2945 
   2946     return index;
   2947 }
   2948 
   2949 /**
   2950 ****************************************************************************************************
   2951 *   SiLib::HwlSetupTileCfg
   2952 *
   2953 *   @brief
   2954 *       Map tile index to tile setting.
   2955 *   @return
   2956 *       ADDR_E_RETURNCODE
   2957 ****************************************************************************************************
   2958 */
   2959 ADDR_E_RETURNCODE SiLib::HwlSetupTileCfg(
   2960     UINT_32         bpp,            ///< Bits per pixel
   2961     INT_32          index,          ///< Tile index
   2962     INT_32          macroModeIndex, ///< Index in macro tile mode table(CI)
   2963     ADDR_TILEINFO*  pInfo,          ///< [out] Tile Info
   2964     AddrTileMode*   pMode,          ///< [out] Tile mode
   2965     AddrTileType*   pType           ///< [out] Tile type
   2966     ) const
   2967 {
   2968     ADDR_E_RETURNCODE returnCode = ADDR_OK;
   2969 
   2970     // Global flag to control usage of tileIndex
   2971     if (UseTileIndex(index))
   2972     {
   2973         if (index == TileIndexLinearGeneral)
   2974         {
   2975             if (pMode)
   2976             {
   2977                 *pMode = ADDR_TM_LINEAR_GENERAL;
   2978             }
   2979 
   2980             if (pType)
   2981             {
   2982                 *pType = ADDR_DISPLAYABLE;
   2983             }
   2984 
   2985             if (pInfo)
   2986             {
   2987                 pInfo->banks = 2;
   2988                 pInfo->bankWidth = 1;
   2989                 pInfo->bankHeight = 1;
   2990                 pInfo->macroAspectRatio = 1;
   2991                 pInfo->tileSplitBytes = 64;
   2992                 pInfo->pipeConfig = ADDR_PIPECFG_P2;
   2993             }
   2994         }
   2995         else if (static_cast<UINT_32>(index) >= m_noOfEntries)
   2996         {
   2997             returnCode = ADDR_INVALIDPARAMS;
   2998         }
   2999         else
   3000         {
   3001             const TileConfig* pCfgTable = GetTileSetting(index);
   3002 
   3003             if (pInfo)
   3004             {
   3005                 *pInfo = pCfgTable->info;
   3006             }
   3007             else
   3008             {
   3009                 if (IsMacroTiled(pCfgTable->mode))
   3010                 {
   3011                     returnCode = ADDR_INVALIDPARAMS;
   3012                 }
   3013             }
   3014 
   3015             if (pMode)
   3016             {
   3017                 *pMode = pCfgTable->mode;
   3018             }
   3019 
   3020             if (pType)
   3021             {
   3022                 *pType = pCfgTable->type;
   3023             }
   3024         }
   3025     }
   3026 
   3027     return returnCode;
   3028 }
   3029 
   3030 /**
   3031 ****************************************************************************************************
   3032 *   SiLib::ReadGbTileMode
   3033 *
   3034 *   @brief
   3035 *       Convert GB_TILE_MODE HW value to TileConfig.
   3036 *   @return
   3037 *       NA.
   3038 ****************************************************************************************************
   3039 */
   3040 VOID SiLib::ReadGbTileMode(
   3041     UINT_32     regValue,   ///< [in] GB_TILE_MODE register
   3042     TileConfig* pCfg        ///< [out] output structure
   3043     ) const
   3044 {
   3045     GB_TILE_MODE gbTileMode;
   3046     gbTileMode.val = regValue;
   3047 
   3048     pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode);
   3049     pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height;
   3050     pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width;
   3051     pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1);
   3052     pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
   3053     pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
   3054     pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
   3055 
   3056     UINT_32 regArrayMode = gbTileMode.f.array_mode;
   3057 
   3058     pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
   3059 
   3060     if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK
   3061     {
   3062         pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
   3063     }
   3064     else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK
   3065     {
   3066         pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3);
   3067     }
   3068 }
   3069 
   3070 /**
   3071 ****************************************************************************************************
   3072 *   SiLib::InitTileSettingTable
   3073 *
   3074 *   @brief
   3075 *       Initialize the ADDR_TILE_CONFIG table.
   3076 *   @return
   3077 *       TRUE if tile table is correctly initialized
   3078 ****************************************************************************************************
   3079 */
   3080 BOOL_32 SiLib::InitTileSettingTable(
   3081     const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
   3082     UINT_32         noOfEntries     ///< [in] Numbe of entries in the table above
   3083     )
   3084 {
   3085     BOOL_32 initOk = TRUE;
   3086 
   3087     ADDR_ASSERT(noOfEntries <= TileTableSize);
   3088 
   3089     memset(m_tileTable, 0, sizeof(m_tileTable));
   3090 
   3091     if (noOfEntries != 0)
   3092     {
   3093         m_noOfEntries = noOfEntries;
   3094     }
   3095     else
   3096     {
   3097         m_noOfEntries = TileTableSize;
   3098     }
   3099 
   3100     if (pCfg) // From Client
   3101     {
   3102         for (UINT_32 i = 0; i < m_noOfEntries; i++)
   3103         {
   3104             ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
   3105         }
   3106     }
   3107     else
   3108     {
   3109         ADDR_ASSERT_ALWAYS();
   3110         initOk = FALSE;
   3111     }
   3112 
   3113     if (initOk)
   3114     {
   3115         ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
   3116     }
   3117 
   3118     return initOk;
   3119 }
   3120 
   3121 /**
   3122 ****************************************************************************************************
   3123 *   SiLib::HwlGetTileIndex
   3124 *
   3125 *   @brief
   3126 *       Return the virtual/real index for given mode/type/info
   3127 *   @return
   3128 *       ADDR_OK if successful.
   3129 ****************************************************************************************************
   3130 */
   3131 ADDR_E_RETURNCODE SiLib::HwlGetTileIndex(
   3132     const ADDR_GET_TILEINDEX_INPUT* pIn,
   3133     ADDR_GET_TILEINDEX_OUTPUT*      pOut) const
   3134 {
   3135     ADDR_E_RETURNCODE returnCode = ADDR_OK;
   3136 
   3137     pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType);
   3138 
   3139     return returnCode;
   3140 }
   3141 
   3142 /**
   3143 ****************************************************************************************************
   3144 *   SiLib::HwlFmaskPreThunkSurfInfo
   3145 *
   3146 *   @brief
   3147 *       Some preparation before thunking a ComputeSurfaceInfo call for Fmask
   3148 *   @return
   3149 *       ADDR_E_RETURNCODE
   3150 ****************************************************************************************************
   3151 */
   3152 VOID SiLib::HwlFmaskPreThunkSurfInfo(
   3153     const ADDR_COMPUTE_FMASK_INFO_INPUT*    pFmaskIn,   ///< [in] Input of fmask info
   3154     const ADDR_COMPUTE_FMASK_INFO_OUTPUT*   pFmaskOut,  ///< [in] Output of fmask info
   3155     ADDR_COMPUTE_SURFACE_INFO_INPUT*        pSurfIn,    ///< [out] Input of thunked surface info
   3156     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pSurfOut    ///< [out] Output of thunked surface info
   3157     ) const
   3158 {
   3159     pSurfIn->tileIndex = pFmaskIn->tileIndex;
   3160 }
   3161 
   3162 /**
   3163 ****************************************************************************************************
   3164 *   SiLib::HwlFmaskPostThunkSurfInfo
   3165 *
   3166 *   @brief
   3167 *       Copy hwl extra field after calling thunked ComputeSurfaceInfo
   3168 *   @return
   3169 *       ADDR_E_RETURNCODE
   3170 ****************************************************************************************************
   3171 */
   3172 VOID SiLib::HwlFmaskPostThunkSurfInfo(
   3173     const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut,   ///< [in] Output of surface info
   3174     ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut           ///< [out] Output of fmask info
   3175     ) const
   3176 {
   3177     pFmaskOut->macroModeIndex = TileIndexInvalid;
   3178     pFmaskOut->tileIndex = pSurfOut->tileIndex;
   3179 }
   3180 
   3181 /**
   3182 ****************************************************************************************************
   3183 *   SiLib::HwlComputeFmaskBits
   3184 *   @brief
   3185 *       Computes fmask bits
   3186 *   @return
   3187 *       Fmask bits
   3188 ****************************************************************************************************
   3189 */
   3190 UINT_32 SiLib::HwlComputeFmaskBits(
   3191     const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn,
   3192     UINT_32* pNumSamples
   3193     ) const
   3194 {
   3195     UINT_32 numSamples = pIn->numSamples;
   3196     UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags);
   3197     UINT_32 bpp;
   3198 
   3199     if (numFrags != numSamples) // EQAA
   3200     {
   3201         ADDR_ASSERT(numFrags <= 8);
   3202 
   3203         if (pIn->resolved == FALSE)
   3204         {
   3205             if (numFrags == 1)
   3206             {
   3207                 bpp          = 1;
   3208                 numSamples   = numSamples == 16 ? 16 : 8;
   3209             }
   3210             else if (numFrags == 2)
   3211             {
   3212                 ADDR_ASSERT(numSamples >= 4);
   3213 
   3214                 bpp          = 2;
   3215                 numSamples   = numSamples;
   3216             }
   3217             else if (numFrags == 4)
   3218             {
   3219                 ADDR_ASSERT(numSamples >= 4);
   3220 
   3221                 bpp          = 4;
   3222                 numSamples   = numSamples;
   3223             }
   3224             else // numFrags == 8
   3225             {
   3226                 ADDR_ASSERT(numSamples == 16);
   3227 
   3228                 bpp          = 4;
   3229                 numSamples   = numSamples;
   3230             }
   3231         }
   3232         else
   3233         {
   3234             if (numFrags == 1)
   3235             {
   3236                 bpp          = (numSamples == 16) ? 16 : 8;
   3237                 numSamples   = 1;
   3238             }
   3239             else if (numFrags == 2)
   3240             {
   3241                 ADDR_ASSERT(numSamples >= 4);
   3242 
   3243                 bpp          = numSamples*2;
   3244                 numSamples   = 1;
   3245             }
   3246             else if (numFrags == 4)
   3247             {
   3248                 ADDR_ASSERT(numSamples >= 4);
   3249 
   3250                 bpp          = numSamples*4;
   3251                 numSamples   = 1;
   3252             }
   3253             else // numFrags == 8
   3254             {
   3255                 ADDR_ASSERT(numSamples >= 16);
   3256 
   3257                 bpp          = 16*4;
   3258                 numSamples   = 1;
   3259             }
   3260         }
   3261     }
   3262     else // Normal AA
   3263     {
   3264         if (pIn->resolved == FALSE)
   3265         {
   3266             bpp          = ComputeFmaskNumPlanesFromNumSamples(numSamples);
   3267             numSamples   = numSamples == 2 ? 8 : numSamples;
   3268         }
   3269         else
   3270         {
   3271             // The same as 8XX
   3272             bpp          = ComputeFmaskResolvedBppFromNumSamples(numSamples);
   3273             numSamples   = 1; // 1x sample
   3274         }
   3275     }
   3276 
   3277     SafeAssign(pNumSamples, numSamples);
   3278 
   3279     return bpp;
   3280 }
   3281 
   3282 /**
   3283 ****************************************************************************************************
   3284 *   SiLib::HwlOptimizeTileMode
   3285 *
   3286 *   @brief
   3287 *       Optimize tile mode on SI
   3288 *
   3289 *   @return
   3290 *       N/A
   3291 *
   3292 ****************************************************************************************************
   3293 */
   3294 VOID SiLib::HwlOptimizeTileMode(
   3295     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut      ///< [in,out] input output structure
   3296     ) const
   3297 {
   3298     AddrTileMode tileMode = pInOut->tileMode;
   3299 
   3300     if ((pInOut->flags.needEquation == TRUE) &&
   3301         (IsMacroTiled(tileMode) == TRUE) &&
   3302         (pInOut->numSamples <= 1))
   3303     {
   3304         UINT_32 thickness = Thickness(tileMode);
   3305 
   3306         if (thickness > 1)
   3307         {
   3308             tileMode = ADDR_TM_1D_TILED_THICK;
   3309         }
   3310         else if (pInOut->numSlices > 1)
   3311         {
   3312             tileMode = ADDR_TM_1D_TILED_THIN1;
   3313         }
   3314         else
   3315         {
   3316             tileMode = ADDR_TM_2D_TILED_THIN1;
   3317         }
   3318     }
   3319 
   3320     if (tileMode != pInOut->tileMode)
   3321     {
   3322         pInOut->tileMode = tileMode;
   3323     }
   3324 }
   3325 
   3326 /**
   3327 ****************************************************************************************************
   3328 *   SiLib::HwlOverrideTileMode
   3329 *
   3330 *   @brief
   3331 *       Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI.
   3332 *
   3333 *   @return
   3334 *       N/A
   3335 *
   3336 ****************************************************************************************************
   3337 */
   3338 VOID SiLib::HwlOverrideTileMode(
   3339     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut          ///< [in,out] input output structure
   3340     ) const
   3341 {
   3342     AddrTileMode tileMode = pInOut->tileMode;
   3343 
   3344     switch (tileMode)
   3345     {
   3346         case ADDR_TM_PRT_TILED_THIN1:
   3347             tileMode = ADDR_TM_2D_TILED_THIN1;
   3348             break;
   3349 
   3350         case ADDR_TM_PRT_TILED_THICK:
   3351             tileMode = ADDR_TM_2D_TILED_THICK;
   3352             break;
   3353 
   3354         case ADDR_TM_PRT_2D_TILED_THICK:
   3355             tileMode = ADDR_TM_2D_TILED_THICK;
   3356             break;
   3357 
   3358         case ADDR_TM_PRT_3D_TILED_THICK:
   3359             tileMode = ADDR_TM_3D_TILED_THICK;
   3360             break;
   3361 
   3362         default:
   3363             break;
   3364     }
   3365 
   3366     if (tileMode != pInOut->tileMode)
   3367     {
   3368         pInOut->tileMode  = tileMode;
   3369         // Only PRT tile modes are overridden for now. Revisit this once new modes are added above.
   3370         pInOut->flags.prt = TRUE;
   3371     }
   3372 }
   3373 
   3374 /**
   3375 ****************************************************************************************************
   3376 *   SiLib::HwlSetPrtTileMode
   3377 *
   3378 *   @brief
   3379 *       Set prt tile modes.
   3380 *
   3381 *   @return
   3382 *       N/A
   3383 *
   3384 ****************************************************************************************************
   3385 */
   3386 VOID SiLib::HwlSetPrtTileMode(
   3387     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
   3388     ) const
   3389 {
   3390     pInOut->tileMode = ADDR_TM_2D_TILED_THIN1;
   3391     pInOut->tileType = (pInOut->tileType == ADDR_DEPTH_SAMPLE_ORDER) ?
   3392                        ADDR_DEPTH_SAMPLE_ORDER : ADDR_NON_DISPLAYABLE;
   3393     pInOut->flags.prt = TRUE;
   3394 }
   3395 
   3396 /**
   3397 ****************************************************************************************************
   3398 *   SiLib::HwlSelectTileMode
   3399 *
   3400 *   @brief
   3401 *       Select tile modes.
   3402 *
   3403 *   @return
   3404 *       N/A
   3405 *
   3406 ****************************************************************************************************
   3407 */
   3408 VOID SiLib::HwlSelectTileMode(
   3409     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
   3410     ) const
   3411 {
   3412     AddrTileMode tileMode;
   3413     AddrTileType tileType;
   3414 
   3415     if (pInOut->flags.volume)
   3416     {
   3417         if (pInOut->numSlices >= 8)
   3418         {
   3419             tileMode = ADDR_TM_2D_TILED_XTHICK;
   3420         }
   3421         else if (pInOut->numSlices >= 4)
   3422         {
   3423             tileMode = ADDR_TM_2D_TILED_THICK;
   3424         }
   3425         else
   3426         {
   3427             tileMode = ADDR_TM_2D_TILED_THIN1;
   3428         }
   3429         tileType = ADDR_NON_DISPLAYABLE;
   3430     }
   3431     else
   3432     {
   3433         tileMode = ADDR_TM_2D_TILED_THIN1;
   3434 
   3435         if (pInOut->flags.depth || pInOut->flags.stencil)
   3436         {
   3437             tileType = ADDR_DEPTH_SAMPLE_ORDER;
   3438         }
   3439         else if ((pInOut->bpp <= 32) ||
   3440                  (pInOut->flags.display == TRUE) ||
   3441                  (pInOut->flags.overlay == TRUE))
   3442         {
   3443             tileType = ADDR_DISPLAYABLE;
   3444         }
   3445         else
   3446         {
   3447             tileType = ADDR_NON_DISPLAYABLE;
   3448         }
   3449     }
   3450 
   3451     if (pInOut->flags.prt)
   3452     {
   3453         tileMode = ADDR_TM_2D_TILED_THIN1;
   3454         tileType = (tileType == ADDR_DISPLAYABLE) ? ADDR_NON_DISPLAYABLE : tileType;
   3455     }
   3456 
   3457     pInOut->tileMode = tileMode;
   3458     pInOut->tileType = tileType;
   3459 
   3460     // Optimize tile mode if possible
   3461     pInOut->flags.opt4Space = TRUE;
   3462 
   3463     // Optimize tile mode if possible
   3464     OptimizeTileMode(pInOut);
   3465 
   3466     HwlOverrideTileMode(pInOut);
   3467 }
   3468 
   3469 /**
   3470 ****************************************************************************************************
   3471 *   SiLib::HwlGetMaxAlignments
   3472 *
   3473 *   @brief
   3474 *       Gets maximum alignments
   3475 *   @return
   3476 *       ADDR_E_RETURNCODE
   3477 ****************************************************************************************************
   3478 */
   3479 ADDR_E_RETURNCODE SiLib::HwlGetMaxAlignments(
   3480     ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut    ///< [out] output structure
   3481     ) const
   3482 {
   3483     const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info);
   3484 
   3485     // Initial size is 64 KiB for PRT.
   3486     UINT_64 maxBaseAlign = 64 * 1024;
   3487 
   3488     for (UINT_32 i = 0; i < m_noOfEntries; i++)
   3489     {
   3490         if ((IsMacroTiled(m_tileTable[i].mode) == TRUE) &&
   3491             (IsPrtTileMode(m_tileTable[i].mode) == FALSE))
   3492         {
   3493             // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
   3494             UINT_32 tileSize = Min(m_tileTable[i].info.tileSplitBytes,
   3495                                    MicroTilePixels * 8 * 16);
   3496 
   3497             UINT_64 baseAlign = tileSize * pipes * m_tileTable[i].info.banks *
   3498                                 m_tileTable[i].info.bankWidth * m_tileTable[i].info.bankHeight;
   3499 
   3500             if (baseAlign > maxBaseAlign)
   3501             {
   3502                 maxBaseAlign = baseAlign;
   3503             }
   3504         }
   3505     }
   3506 
   3507     if (pOut != NULL)
   3508     {
   3509         pOut->baseAlign = maxBaseAlign;
   3510     }
   3511 
   3512     return ADDR_OK;
   3513 }
   3514 
   3515 /**
   3516 ****************************************************************************************************
   3517 *   SiLib::HwlComputeSurfaceAlignmentsMacroTiled
   3518 *
   3519 *   @brief
   3520 *       Hardware layer function to compute alignment request for macro tile mode
   3521 *
   3522 *   @return
   3523 *       N/A
   3524 *
   3525 ****************************************************************************************************
   3526 */
   3527 VOID SiLib::HwlComputeSurfaceAlignmentsMacroTiled(
   3528     AddrTileMode                      tileMode,           ///< [in] tile mode
   3529     UINT_32                           bpp,                ///< [in] bits per pixel
   3530     ADDR_SURFACE_FLAGS                flags,              ///< [in] surface flags
   3531     UINT_32                           mipLevel,           ///< [in] mip level
   3532     UINT_32                           numSamples,         ///< [in] number of samples
   3533     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut                ///< [in,out] Surface output
   3534     ) const
   3535 {
   3536     if ((mipLevel == 0) && (flags.prt))
   3537     {
   3538         UINT_32 macroTileSize = pOut->blockWidth * pOut->blockHeight * numSamples * bpp / 8;
   3539 
   3540         if (macroTileSize < PrtTileSize)
   3541         {
   3542             UINT_32 numMacroTiles = PrtTileSize / macroTileSize;
   3543 
   3544             ADDR_ASSERT((PrtTileSize % macroTileSize) == 0);
   3545 
   3546             pOut->pitchAlign *= numMacroTiles;
   3547             pOut->baseAlign  *= numMacroTiles;
   3548         }
   3549     }
   3550 }
   3551 
   3552 /**
   3553 ****************************************************************************************************
   3554 *   SiLib::InitEquationTable
   3555 *
   3556 *   @brief
   3557 *       Initialize Equation table.
   3558 *
   3559 *   @return
   3560 *       N/A
   3561 ****************************************************************************************************
   3562 */
   3563 VOID SiLib::InitEquationTable()
   3564 {
   3565     ADDR_EQUATION_KEY equationKeyTable[EquationTableSize];
   3566     memset(equationKeyTable, 0, sizeof(equationKeyTable));
   3567 
   3568     memset(m_equationTable, 0, sizeof(m_equationTable));
   3569 
   3570     memset(m_blockWidth, 0, sizeof(m_blockWidth));
   3571 
   3572     memset(m_blockHeight, 0, sizeof(m_blockHeight));
   3573 
   3574     memset(m_blockSlices, 0, sizeof(m_blockSlices));
   3575 
   3576     // Loop all possible bpp
   3577     for (UINT_32 log2ElementBytes = 0; log2ElementBytes < MaxNumElementBytes; log2ElementBytes++)
   3578     {
   3579         // Get bits per pixel
   3580         UINT_32 bpp = 1 << (log2ElementBytes + 3);
   3581 
   3582         // Loop all possible tile index
   3583         for (INT_32 tileIndex = 0; tileIndex < static_cast<INT_32>(m_noOfEntries); tileIndex++)
   3584         {
   3585             UINT_32 equationIndex = ADDR_INVALID_EQUATION_INDEX;
   3586 
   3587             TileConfig tileConfig = m_tileTable[tileIndex];
   3588 
   3589             ADDR_SURFACE_FLAGS flags = {{0}};
   3590 
   3591             // Compute tile info, hardcode numSamples to 1 because MSAA is not supported
   3592             // in swizzle pattern equation
   3593             HwlComputeMacroModeIndex(tileIndex, flags, bpp, 1, &tileConfig.info, NULL, NULL);
   3594 
   3595             // Check if the input is supported
   3596             if (IsEquationSupported(bpp, tileConfig, tileIndex, log2ElementBytes) == TRUE)
   3597             {
   3598                 ADDR_EQUATION_KEY  key   = {{0}};
   3599 
   3600                 // Generate swizzle equation key from bpp and tile config
   3601                 key.fields.log2ElementBytes = log2ElementBytes;
   3602                 key.fields.tileMode         = tileConfig.mode;
   3603                 // Treat depth micro tile type and non-display micro tile type as the same key
   3604                 // because they have the same equation actually
   3605                 key.fields.microTileType    = (tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) ?
   3606                                               ADDR_NON_DISPLAYABLE : tileConfig.type;
   3607                 key.fields.pipeConfig       = tileConfig.info.pipeConfig;
   3608                 key.fields.numBanksLog2     = Log2(tileConfig.info.banks);
   3609                 key.fields.bankWidth        = tileConfig.info.bankWidth;
   3610                 key.fields.bankHeight       = tileConfig.info.bankHeight;
   3611                 key.fields.macroAspectRatio = tileConfig.info.macroAspectRatio;
   3612                 key.fields.prt              = ((m_chipFamily == ADDR_CHIP_FAMILY_SI) &&
   3613                                                ((1 << tileIndex) & SiPrtTileIndexMask)) ? 1 : 0;
   3614 
   3615                 // Find in the table if the equation has been built based on the key
   3616                 for (UINT_32 i = 0; i < m_numEquations; i++)
   3617                 {
   3618                     if (key.value == equationKeyTable[i].value)
   3619                     {
   3620                         equationIndex = i;
   3621                         break;
   3622                     }
   3623                 }
   3624 
   3625                 // If found, just fill the index into the lookup table and no need
   3626                 // to generate the equation again. Otherwise, generate the equation.
   3627                 if (equationIndex == ADDR_INVALID_EQUATION_INDEX)
   3628                 {
   3629                     ADDR_EQUATION equation;
   3630                     ADDR_E_RETURNCODE retCode;
   3631 
   3632                     memset(&equation, 0, sizeof(ADDR_EQUATION));
   3633 
   3634                     // Generate the equation
   3635                     if (IsMicroTiled(tileConfig.mode))
   3636                     {
   3637                         retCode = ComputeMicroTileEquation(log2ElementBytes,
   3638                                                            tileConfig.mode,
   3639                                                            tileConfig.type,
   3640                                                            &equation);
   3641                     }
   3642                     else
   3643                     {
   3644                         retCode = ComputeMacroTileEquation(log2ElementBytes,
   3645                                                            tileConfig.mode,
   3646                                                            tileConfig.type,
   3647                                                            &tileConfig.info,
   3648                                                            &equation);
   3649                     }
   3650                     // Only fill the equation into the table if the return code is ADDR_OK,
   3651                     // otherwise if the return code is not ADDR_OK, it indicates this is not
   3652                     // a valid input, we do nothing but just fill invalid equation index
   3653                     // into the lookup table.
   3654                     if (retCode == ADDR_OK)
   3655                     {
   3656                         equationIndex = m_numEquations;
   3657                         ADDR_ASSERT(equationIndex < EquationTableSize);
   3658 
   3659                         m_blockSlices[equationIndex] = Thickness(tileConfig.mode);
   3660 
   3661                         if (IsMicroTiled(tileConfig.mode))
   3662                         {
   3663                             m_blockWidth[equationIndex]  = MicroTileWidth;
   3664                             m_blockHeight[equationIndex] = MicroTileHeight;
   3665                         }
   3666                         else
   3667                         {
   3668                             const ADDR_TILEINFO* pTileInfo = &tileConfig.info;
   3669 
   3670                             m_blockWidth[equationIndex]  =
   3671                                 HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth *
   3672                                 pTileInfo->macroAspectRatio;
   3673                             m_blockHeight[equationIndex] =
   3674                                 MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
   3675                                 pTileInfo->macroAspectRatio;
   3676 
   3677                             if (key.fields.prt)
   3678                             {
   3679                                 UINT_32 macroTileSize =
   3680                                     m_blockWidth[equationIndex] * m_blockHeight[equationIndex] *
   3681                                     bpp / 8;
   3682 
   3683                                 if (macroTileSize < PrtTileSize)
   3684                                 {
   3685                                     UINT_32 numMacroTiles = PrtTileSize / macroTileSize;
   3686 
   3687                                     ADDR_ASSERT(macroTileSize == (1u << equation.numBits));
   3688                                     ADDR_ASSERT((PrtTileSize % macroTileSize) == 0);
   3689 
   3690                                     UINT_32 numBits = Log2(numMacroTiles);
   3691 
   3692                                     UINT_32 xStart = Log2(m_blockWidth[equationIndex]) +
   3693                                                      log2ElementBytes;
   3694 
   3695                                     m_blockWidth[equationIndex] *= numMacroTiles;
   3696 
   3697                                     for (UINT_32 i = 0; i < numBits; i++)
   3698                                     {
   3699                                         equation.addr[equation.numBits + i].valid = 1;
   3700                                         equation.addr[equation.numBits + i].index = xStart + i;
   3701                                     }
   3702 
   3703                                     equation.numBits += numBits;
   3704                                 }
   3705                             }
   3706                         }
   3707 
   3708                         equationKeyTable[equationIndex] = key;
   3709                         m_equationTable[equationIndex]  = equation;
   3710 
   3711                         m_numEquations++;
   3712                     }
   3713                 }
   3714             }
   3715 
   3716             // Fill the index into the lookup table, if the combination is not supported
   3717             // fill the invalid equation index
   3718             m_equationLookupTable[log2ElementBytes][tileIndex] = equationIndex;
   3719         }
   3720 
   3721         if (m_chipFamily == ADDR_CHIP_FAMILY_SI)
   3722         {
   3723             // For tile index 3 which is shared between PRT depth and uncompressed depth
   3724             m_uncompressDepthEqIndex = m_numEquations;
   3725 
   3726             for (UINT_32 log2ElemBytes = 0; log2ElemBytes < MaxNumElementBytes; log2ElemBytes++)
   3727             {
   3728                 TileConfig        tileConfig = m_tileTable[3];
   3729                 ADDR_EQUATION     equation;
   3730                 ADDR_E_RETURNCODE retCode;
   3731 
   3732                 memset(&equation, 0, sizeof(ADDR_EQUATION));
   3733 
   3734                 retCode = ComputeMacroTileEquation(log2ElemBytes,
   3735                                                    tileConfig.mode,
   3736                                                    tileConfig.type,
   3737                                                    &tileConfig.info,
   3738                                                    &equation);
   3739 
   3740                 if (retCode == ADDR_OK)
   3741                 {
   3742                     UINT_32 equationIndex = m_numEquations;
   3743                     ADDR_ASSERT(equationIndex < EquationTableSize);
   3744 
   3745                     m_blockSlices[equationIndex] = 1;
   3746 
   3747                     const ADDR_TILEINFO* pTileInfo = &tileConfig.info;
   3748 
   3749                     m_blockWidth[equationIndex]  =
   3750                         HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth *
   3751                         pTileInfo->macroAspectRatio;
   3752                     m_blockHeight[equationIndex] =
   3753                         MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
   3754                         pTileInfo->macroAspectRatio;
   3755 
   3756                     m_equationTable[equationIndex] = equation;
   3757 
   3758                     m_numEquations++;
   3759                 }
   3760             }
   3761         }
   3762     }
   3763 }
   3764 
   3765 /**
   3766 ****************************************************************************************************
   3767 *   SiLib::IsEquationSupported
   3768 *
   3769 *   @brief
   3770 *       Check if it is supported for given bpp and tile config to generate a equation.
   3771 *
   3772 *   @return
   3773 *       TRUE if supported
   3774 ****************************************************************************************************
   3775 */
   3776 BOOL_32 SiLib::IsEquationSupported(
   3777     UINT_32    bpp,             ///< Bits per pixel
   3778     TileConfig tileConfig,      ///< Tile config
   3779     INT_32     tileIndex,       ///< Tile index
   3780     UINT_32    elementBytesLog2 ///< Log2 of element bytes
   3781     ) const
   3782 {
   3783     BOOL_32 supported = TRUE;
   3784 
   3785     // Linear tile mode is not supported in swizzle pattern equation
   3786     if (IsLinear(tileConfig.mode))
   3787     {
   3788         supported = FALSE;
   3789     }
   3790     // These tile modes are for Tex2DArray and Tex3D which has depth (num_slice > 1) use,
   3791     // which is not supported in swizzle pattern equation due to slice rotation
   3792     else if ((tileConfig.mode == ADDR_TM_2D_TILED_THICK)  ||
   3793              (tileConfig.mode == ADDR_TM_2D_TILED_XTHICK) ||
   3794              (tileConfig.mode == ADDR_TM_3D_TILED_THIN1)  ||
   3795              (tileConfig.mode == ADDR_TM_3D_TILED_THICK)  ||
   3796              (tileConfig.mode == ADDR_TM_3D_TILED_XTHICK))
   3797     {
   3798         supported = FALSE;
   3799     }
   3800     // Only 8bpp(stencil), 16bpp and 32bpp is supported for depth
   3801     else if ((tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) && (bpp > 32))
   3802     {
   3803         supported = FALSE;
   3804     }
   3805     // Tile split is not supported in swizzle pattern equation
   3806     else if (IsMacroTiled(tileConfig.mode))
   3807     {
   3808         UINT_32 thickness = Thickness(tileConfig.mode);
   3809         if (((bpp >> 3) * MicroTilePixels * thickness) > tileConfig.info.tileSplitBytes)
   3810         {
   3811             supported = FALSE;
   3812         }
   3813 
   3814         if ((supported == TRUE) && (m_chipFamily == ADDR_CHIP_FAMILY_SI))
   3815         {
   3816             supported = m_EquationSupport[tileIndex][elementBytesLog2];
   3817         }
   3818     }
   3819 
   3820     return supported;
   3821 }
   3822 
   3823 } // V1
   3824 } // Addr
   3825