Home | History | Annotate | Download | only in core
      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  addrcommon.h
     30 * @brief Contains the helper function and constants
     31 ***************************************************************************************************
     32 */
     33 
     34 #ifndef __ADDR_COMMON_H__
     35 #define __ADDR_COMMON_H__
     36 
     37 #include "addrinterface.h"
     38 
     39 
     40 // ADDR_LNX_KERNEL_BUILD is for internal build
     41 // Moved from addrinterface.h so __KERNEL__ is not needed any more
     42 #if ADDR_LNX_KERNEL_BUILD // || (defined(__GNUC__) && defined(__KERNEL__))
     43     #include "lnx_common_defs.h" // ported from cmmqs
     44 #elif !defined(__APPLE__)
     45     #include <stdlib.h>
     46     #include <string.h>
     47 #endif
     48 
     49 ///////////////////////////////////////////////////////////////////////////////////////////////////
     50 // Common constants
     51 ///////////////////////////////////////////////////////////////////////////////////////////////////
     52 static const UINT_32 MicroTileWidth      = 8;       ///< Micro tile width, for 1D and 2D tiling
     53 static const UINT_32 MicroTileHeight     = 8;       ///< Micro tile height, for 1D and 2D tiling
     54 static const UINT_32 ThickTileThickness  = 4;       ///< Micro tile thickness, for THICK modes
     55 static const UINT_32 XThickTileThickness = 8;       ///< Extra thick tiling thickness
     56 static const UINT_32 PowerSaveTileBytes  = 64;      ///< Nuber of bytes per tile for power save 64
     57 static const UINT_32 CmaskCacheBits      = 1024;    ///< Number of bits for CMASK cache
     58 static const UINT_32 CmaskElemBits       = 4;       ///< Number of bits for CMASK element
     59 static const UINT_32 HtileCacheBits      = 16384;   ///< Number of bits for HTILE cache 512*32
     60 
     61 static const UINT_32 MicroTilePixels     = MicroTileWidth * MicroTileHeight;
     62 
     63 static const INT_32 TileIndexInvalid        = TILEINDEX_INVALID;
     64 static const INT_32 TileIndexLinearGeneral  = TILEINDEX_LINEAR_GENERAL;
     65 static const INT_32 TileIndexNoMacroIndex   = -3;
     66 
     67 ///////////////////////////////////////////////////////////////////////////////////////////////////
     68 // Common macros
     69 ///////////////////////////////////////////////////////////////////////////////////////////////////
     70 #define BITS_PER_BYTE 8
     71 #define BITS_TO_BYTES(x) ( ((x) + (BITS_PER_BYTE-1)) / BITS_PER_BYTE )
     72 #define BYTES_TO_BITS(x) ( (x) * BITS_PER_BYTE )
     73 
     74 /// Helper macros to select a single bit from an int (undefined later in section)
     75 #define _BIT(v,b)      (((v) >> (b) ) & 1)
     76 
     77 /**
     78 ***************************************************************************************************
     79 * @brief Enums to identify AddrLib type
     80 ***************************************************************************************************
     81 */
     82 enum AddrLibClass
     83 {
     84     BASE_ADDRLIB = 0x0,
     85     R600_ADDRLIB = 0x6,
     86     R800_ADDRLIB = 0x8,
     87     SI_ADDRLIB   = 0xa,
     88     CI_ADDRLIB   = 0xb,
     89 };
     90 
     91 /**
     92 ***************************************************************************************************
     93 * AddrChipFamily
     94 *
     95 *   @brief
     96 *       Neutral enums that specifies chip family.
     97 *
     98 ***************************************************************************************************
     99 */
    100 enum AddrChipFamily
    101 {
    102     ADDR_CHIP_FAMILY_IVLD,    ///< Invalid family
    103     ADDR_CHIP_FAMILY_R6XX,
    104     ADDR_CHIP_FAMILY_R7XX,
    105     ADDR_CHIP_FAMILY_R8XX,
    106     ADDR_CHIP_FAMILY_NI,
    107     ADDR_CHIP_FAMILY_SI,
    108     ADDR_CHIP_FAMILY_CI,
    109     ADDR_CHIP_FAMILY_VI,
    110 };
    111 
    112 /**
    113 ***************************************************************************************************
    114 * ADDR_CONFIG_FLAGS
    115 *
    116 *   @brief
    117 *       This structure is used to set addr configuration flags.
    118 ***************************************************************************************************
    119 */
    120 union ADDR_CONFIG_FLAGS
    121 {
    122     struct
    123     {
    124         /// Clients do not need to set these flags except forceLinearAligned.
    125         /// There flags are set up by AddrLib inside thru AddrInitGlobalParamsFromRegister
    126         UINT_32 optimalBankSwap        : 1;    ///< New bank tiling for RV770 only
    127         UINT_32 noCubeMipSlicesPad     : 1;    ///< Disables faces padding for cubemap mipmaps
    128         UINT_32 fillSizeFields         : 1;    ///< If clients fill size fields in all input and
    129                                                ///  output structure
    130         UINT_32 ignoreTileInfo         : 1;    ///< Don't use tile info structure
    131         UINT_32 useTileIndex           : 1;    ///< Make tileIndex field in input valid
    132         UINT_32 useCombinedSwizzle     : 1;    ///< Use combined swizzle
    133         UINT_32 checkLast2DLevel       : 1;    ///< Check the last 2D mip sub level
    134         UINT_32 useHtileSliceAlign     : 1;    ///< Do htile single slice alignment
    135         UINT_32 degradeBaseLevel       : 1;    ///< Degrade to 1D modes automatically for base level
    136         UINT_32 allowLargeThickTile    : 1;    ///< Allow 64*thickness*bytesPerPixel > rowSize
    137         UINT_32 reserved               : 22;   ///< Reserved bits for future use
    138     };
    139 
    140     UINT_32 value;
    141 };
    142 
    143 ///////////////////////////////////////////////////////////////////////////////////////////////////
    144 // Platform specific debug break defines
    145 ///////////////////////////////////////////////////////////////////////////////////////////////////
    146 #if DEBUG
    147     #if defined(__GNUC__)
    148         #define ADDR_DBG_BREAK()
    149     #elif defined(__APPLE__)
    150         #define ADDR_DBG_BREAK()    { IOPanic("");}
    151     #else
    152         #define ADDR_DBG_BREAK()    { __debugbreak(); }
    153     #endif
    154 #else
    155     #define ADDR_DBG_BREAK()
    156 #endif
    157 ///////////////////////////////////////////////////////////////////////////////////////////////////
    158 
    159 ///////////////////////////////////////////////////////////////////////////////////////////////////
    160 // Debug assertions used in AddrLib
    161 ///////////////////////////////////////////////////////////////////////////////////////////////////
    162 #if DEBUG
    163 #define ADDR_ASSERT(__e) if ( !((__e) ? TRUE : FALSE)) { ADDR_DBG_BREAK(); }
    164 #define ADDR_ASSERT_ALWAYS() ADDR_DBG_BREAK()
    165 #define ADDR_UNHANDLED_CASE() ADDR_ASSERT(!"Unhandled case")
    166 #define ADDR_NOT_IMPLEMENTED() ADDR_ASSERT(!"Not implemented");
    167 #else //DEBUG
    168 #define ADDR_ASSERT(__e)
    169 #define ADDR_ASSERT_ALWAYS()
    170 #define ADDR_UNHANDLED_CASE()
    171 #define ADDR_NOT_IMPLEMENTED()
    172 #endif //DEBUG
    173 ///////////////////////////////////////////////////////////////////////////////////////////////////
    174 
    175 ///////////////////////////////////////////////////////////////////////////////////////////////////
    176 // Debug print macro from legacy address library
    177 ///////////////////////////////////////////////////////////////////////////////////////////////////
    178 #if DEBUG
    179 
    180 #define ADDR_PRNT(a)    AddrObject::DebugPrint a
    181 
    182 /// @brief Macro for reporting informational messages
    183 /// @ingroup util
    184 ///
    185 /// This macro optionally prints an informational message to stdout.
    186 /// The first parameter is a condition -- if it is true, nothing is done.
    187 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
    188 /// starting with a string. This is passed to printf() or an equivalent
    189 /// in order to format the informational message. For example,
    190 /// ADDR_INFO(0, ("test %d",3) ); prints out "test 3".
    191 ///
    192 #define ADDR_INFO(cond, a)         \
    193 { if (!(cond)) { ADDR_PRNT(a); } }
    194 
    195 
    196 /// @brief Macro for reporting error warning messages
    197 /// @ingroup util
    198 ///
    199 /// This macro optionally prints an error warning message to stdout,
    200 /// followed by the file name and line number where the macro was called.
    201 /// The first parameter is a condition -- if it is true, nothing is done.
    202 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
    203 /// starting with a string. This is passed to printf() or an equivalent
    204 /// in order to format the informational message. For example,
    205 /// ADDR_WARN(0, ("test %d",3) ); prints out "test 3" followed by
    206 /// a second line with the file name and line number.
    207 ///
    208 #define ADDR_WARN(cond, a)         \
    209 { if (!(cond))                     \
    210   { ADDR_PRNT(a);                  \
    211     ADDR_PRNT(("  WARNING in file %s, line %d\n", __FILE__, __LINE__)); \
    212 } }
    213 
    214 
    215 /// @brief Macro for reporting fatal error conditions
    216 /// @ingroup util
    217 ///
    218 /// This macro optionally stops execution of the current routine
    219 /// after printing an error warning message to stdout,
    220 /// followed by the file name and line number where the macro was called.
    221 /// The first parameter is a condition -- if it is true, nothing is done.
    222 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
    223 /// starting with a string. This is passed to printf() or an equivalent
    224 /// in order to format the informational message. For example,
    225 /// ADDR_EXIT(0, ("test %d",3) ); prints out "test 3" followed by
    226 /// a second line with the file name and line number, then stops execution.
    227 ///
    228 #define ADDR_EXIT(cond, a)         \
    229 { if (!(cond))                     \
    230   { ADDR_PRNT(a); ADDR_DBG_BREAK();\
    231 } }
    232 
    233 #else // DEBUG
    234 
    235 #define ADDRDPF 1 ? (void)0 : (void)
    236 
    237 #define ADDR_PRNT(a)
    238 
    239 #define ADDR_DBG_BREAK()
    240 
    241 #define ADDR_INFO(cond, a)
    242 
    243 #define ADDR_WARN(cond, a)
    244 
    245 #define ADDR_EXIT(cond, a)
    246 
    247 #endif // DEBUG
    248 ///////////////////////////////////////////////////////////////////////////////////////////////////
    249 
    250 ///////////////////////////////////////////////////////////////////////////////////////////////////
    251 // Misc helper functions
    252 ////////////////////////////////////////////////////////////////////////////////////////////////////
    253 
    254 /**
    255 ***************************************************************************************************
    256 *   AddrXorReduce
    257 *
    258 *   @brief
    259 *       Xor the right-side numberOfBits bits of x.
    260 ***************************************************************************************************
    261 */
    262 static inline UINT_32 XorReduce(
    263     UINT_32 x,
    264     UINT_32 numberOfBits)
    265 {
    266     UINT_32 i;
    267     UINT_32 result = x & 1;
    268 
    269     for (i=1; i<numberOfBits; i++)
    270     {
    271         result ^= ((x>>i) & 1);
    272     }
    273 
    274     return result;
    275 }
    276 
    277 /**
    278 ***************************************************************************************************
    279 *   IsPow2
    280 *
    281 *   @brief
    282 *       Check if the size (UINT_32) is pow 2
    283 ***************************************************************************************************
    284 */
    285 static inline UINT_32 IsPow2(
    286     UINT_32 dim)        ///< [in] dimension of miplevel
    287 {
    288     ADDR_ASSERT(dim > 0);
    289     return !(dim & (dim - 1));
    290 }
    291 
    292 /**
    293 ***************************************************************************************************
    294 *   IsPow2
    295 *
    296 *   @brief
    297 *       Check if the size (UINT_64) is pow 2
    298 ***************************************************************************************************
    299 */
    300 static inline UINT_64 IsPow2(
    301     UINT_64 dim)        ///< [in] dimension of miplevel
    302 {
    303     ADDR_ASSERT(dim > 0);
    304     return !(dim & (dim - 1));
    305 }
    306 
    307 /**
    308 ***************************************************************************************************
    309 *   ByteAlign
    310 *
    311 *   @brief
    312 *       Align UINT_32 "x" to "align" alignment, "align" should be power of 2
    313 ***************************************************************************************************
    314 */
    315 static inline UINT_32 PowTwoAlign(
    316     UINT_32 x,
    317     UINT_32 align)
    318 {
    319     //
    320     // Assert that x is a power of two.
    321     //
    322     ADDR_ASSERT(IsPow2(align));
    323     return (x + (align - 1)) & (~(align - 1));
    324 }
    325 
    326 /**
    327 ***************************************************************************************************
    328 *   ByteAlign
    329 *
    330 *   @brief
    331 *       Align UINT_64 "x" to "align" alignment, "align" should be power of 2
    332 ***************************************************************************************************
    333 */
    334 static inline UINT_64 PowTwoAlign(
    335     UINT_64 x,
    336     UINT_64 align)
    337 {
    338     //
    339     // Assert that x is a power of two.
    340     //
    341     ADDR_ASSERT(IsPow2(align));
    342     return (x + (align - 1)) & (~(align - 1));
    343 }
    344 
    345 /**
    346 ***************************************************************************************************
    347 *   Min
    348 *
    349 *   @brief
    350 *       Get the min value between two unsigned values
    351 ***************************************************************************************************
    352 */
    353 static inline UINT_32 Min(
    354     UINT_32 value1,
    355     UINT_32 value2)
    356 {
    357     return ((value1 < (value2)) ? (value1) : value2);
    358 }
    359 
    360 /**
    361 ***************************************************************************************************
    362 *   Min
    363 *
    364 *   @brief
    365 *       Get the min value between two signed values
    366 ***************************************************************************************************
    367 */
    368 static inline INT_32 Min(
    369     INT_32 value1,
    370     INT_32 value2)
    371 {
    372     return ((value1 < (value2)) ? (value1) : value2);
    373 }
    374 
    375 /**
    376 ***************************************************************************************************
    377 *   Max
    378 *
    379 *   @brief
    380 *       Get the max value between two unsigned values
    381 ***************************************************************************************************
    382 */
    383 static inline UINT_32 Max(
    384     UINT_32 value1,
    385     UINT_32 value2)
    386 {
    387     return ((value1 > (value2)) ? (value1) : value2);
    388 }
    389 
    390 /**
    391 ***************************************************************************************************
    392 *   Max
    393 *
    394 *   @brief
    395 *       Get the max value between two signed values
    396 ***************************************************************************************************
    397 */
    398 static inline INT_32 Max(
    399     INT_32 value1,
    400     INT_32 value2)
    401 {
    402     return ((value1 > (value2)) ? (value1) : value2);
    403 }
    404 
    405 /**
    406 ***************************************************************************************************
    407 *   NextPow2
    408 *
    409 *   @brief
    410 *       Compute the mipmap's next level dim size
    411 ***************************************************************************************************
    412 */
    413 static inline UINT_32 NextPow2(
    414     UINT_32 dim)        ///< [in] dimension of miplevel
    415 {
    416     UINT_32 newDim;
    417 
    418     newDim = 1;
    419 
    420     if (dim > 0x7fffffff)
    421     {
    422         ADDR_ASSERT_ALWAYS();
    423         newDim = 0x80000000;
    424     }
    425     else
    426     {
    427         while (newDim < dim)
    428         {
    429             newDim <<= 1;
    430         }
    431     }
    432 
    433     return newDim;
    434 }
    435 
    436 /**
    437 ***************************************************************************************************
    438 *   Log2
    439 *
    440 *   @brief
    441 *       Compute log of base 2
    442 ***************************************************************************************************
    443 */
    444 static inline UINT_32 Log2(
    445     UINT_32 x)      ///< [in] the value should calculate log based 2
    446 {
    447     UINT_32 y;
    448 
    449     //
    450     // Assert that x is a power of two.
    451     //
    452     ADDR_ASSERT(IsPow2(x));
    453 
    454     y = 0;
    455     while (x > 1)
    456     {
    457         x >>= 1;
    458         y++;
    459     }
    460 
    461     return y;
    462 }
    463 
    464 /**
    465 ***************************************************************************************************
    466 *   QLog2
    467 *
    468 *   @brief
    469 *       Compute log of base 2 quickly (<= 16)
    470 ***************************************************************************************************
    471 */
    472 static inline UINT_32 QLog2(
    473     UINT_32 x)      ///< [in] the value should calculate log based 2
    474 {
    475     ADDR_ASSERT(x <= 16);
    476 
    477     UINT_32 y = 0;
    478 
    479     switch (x)
    480     {
    481         case 1:
    482             y = 0;
    483             break;
    484         case 2:
    485             y = 1;
    486             break;
    487         case 4:
    488             y = 2;
    489             break;
    490         case 8:
    491             y = 3;
    492             break;
    493         case 16:
    494             y = 4;
    495             break;
    496         default:
    497             ADDR_ASSERT_ALWAYS();
    498     }
    499 
    500     return y;
    501 }
    502 
    503 /**
    504 ***************************************************************************************************
    505 *   SafeAssign
    506 *
    507 *   @brief
    508 *       NULL pointer safe assignment
    509 ***************************************************************************************************
    510 */
    511 static inline VOID SafeAssign(
    512     UINT_32*    pLVal,  ///< [in] Pointer to left val
    513     UINT_32     rVal)   ///< [in] Right value
    514 {
    515     if (pLVal)
    516     {
    517         *pLVal = rVal;
    518     }
    519 }
    520 
    521 /**
    522 ***************************************************************************************************
    523 *   SafeAssign
    524 *
    525 *   @brief
    526 *       NULL pointer safe assignment for 64bit values
    527 ***************************************************************************************************
    528 */
    529 static inline VOID SafeAssign(
    530     UINT_64*    pLVal,  ///< [in] Pointer to left val
    531     UINT_64     rVal)   ///< [in] Right value
    532 {
    533     if (pLVal)
    534     {
    535         *pLVal = rVal;
    536     }
    537 }
    538 
    539 /**
    540 ***************************************************************************************************
    541 *   SafeAssign
    542 *
    543 *   @brief
    544 *       NULL pointer safe assignment for AddrTileMode
    545 ***************************************************************************************************
    546 */
    547 static inline VOID SafeAssign(
    548     AddrTileMode*    pLVal, ///< [in] Pointer to left val
    549     AddrTileMode     rVal)  ///< [in] Right value
    550 {
    551     if (pLVal)
    552     {
    553         *pLVal = rVal;
    554     }
    555 }
    556 
    557 #endif // __ADDR_COMMON_H__
    558 
    559