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///////////////////////////////////////////////////////////////////////////////////////////////////
52static const UINT_32 MicroTileWidth      = 8;       ///< Micro tile width, for 1D and 2D tiling
53static const UINT_32 MicroTileHeight     = 8;       ///< Micro tile height, for 1D and 2D tiling
54static const UINT_32 ThickTileThickness  = 4;       ///< Micro tile thickness, for THICK modes
55static const UINT_32 XThickTileThickness = 8;       ///< Extra thick tiling thickness
56static const UINT_32 PowerSaveTileBytes  = 64;      ///< Nuber of bytes per tile for power save 64
57static const UINT_32 CmaskCacheBits      = 1024;    ///< Number of bits for CMASK cache
58static const UINT_32 CmaskElemBits       = 4;       ///< Number of bits for CMASK element
59static const UINT_32 HtileCacheBits      = 16384;   ///< Number of bits for HTILE cache 512*32
60
61static const UINT_32 MicroTilePixels     = MicroTileWidth * MicroTileHeight;
62
63static const INT_32 TileIndexInvalid        = TILEINDEX_INVALID;
64static const INT_32 TileIndexLinearGeneral  = TILEINDEX_LINEAR_GENERAL;
65static 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*/
82enum 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*/
100enum 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*/
120union 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*/
262static 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*/
285static 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*/
300static 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*/
315static 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*/
334static 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*/
353static 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*/
368static 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*/
383static 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*/
398static 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*/
413static 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*/
444static 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*/
472static 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*/
511static 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*/
529static 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*/
547static 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