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  ciaddrlib.cpp
30* @brief Contains the implementation for the CIAddrLib class.
31***************************************************************************************************
32*/
33
34#include "ciaddrlib.h"
35
36#include "si_gb_reg.h"
37
38#include "si_ci_vi_merged_enum.h"
39
40#if BRAHMA_BUILD
41#include "amdgpu_id.h"
42#else
43#include "ci_id.h"
44#include "kv_id.h"
45#include "vi_id.h"
46#endif
47
48///////////////////////////////////////////////////////////////////////////////////////////////////
49///////////////////////////////////////////////////////////////////////////////////////////////////
50
51/**
52***************************************************************************************************
53*   AddrMask
54*
55*   @brief
56*       Gets a mask of "width"
57*   @return
58*       Bit mask
59***************************************************************************************************
60*/
61static UINT_64 AddrMask(
62    UINT_32 width)  ///< Width of bits
63{
64    UINT_64 ret;
65
66    if (width >= sizeof(UINT_64)*8)
67    {
68        ret = ~((UINT_64) 0);
69    }
70    else
71    {
72        return (((UINT_64) 1) << width) - 1;
73    }
74    return ret;
75}
76
77/**
78***************************************************************************************************
79*   AddrGetBits
80*
81*   @brief
82*       Gets bits within a range of [msb, lsb]
83*   @return
84*       Bits of this range
85***************************************************************************************************
86*/
87static UINT_64 AddrGetBits(
88    UINT_64 bits,   ///< Source bits
89    UINT_32 msb,    ///< Most signicant bit
90    UINT_32 lsb)    ///< Least signicant bit
91{
92    UINT_64 ret = 0;
93
94    if (msb >= lsb)
95    {
96        ret = (bits >> lsb) & (AddrMask(1 + msb - lsb));
97    }
98    return ret;
99}
100
101/**
102***************************************************************************************************
103*   AddrRemoveBits
104*
105*   @brief
106*       Removes bits within the range of [msb, lsb]
107*   @return
108*       Modified bits
109***************************************************************************************************
110*/
111static UINT_64 AddrRemoveBits(
112    UINT_64 bits,   ///< Source bits
113    UINT_32 msb,    ///< Most signicant bit
114    UINT_32 lsb)    ///< Least signicant bit
115{
116    UINT_64 ret = bits;
117
118    if (msb >= lsb)
119    {
120        ret = AddrGetBits(bits, lsb - 1, 0) // low bits
121            | (AddrGetBits(bits, 8 * sizeof(bits) - 1, msb + 1) << lsb); //high bits
122    }
123    return ret;
124}
125
126/**
127***************************************************************************************************
128*   AddrInsertBits
129*
130*   @brief
131*       Inserts new bits into the range of [msb, lsb]
132*   @return
133*       Modified bits
134***************************************************************************************************
135*/
136static UINT_64 AddrInsertBits(
137    UINT_64 bits,       ///< Source bits
138    UINT_64 newBits,    ///< New bits to be inserted
139    UINT_32 msb,        ///< Most signicant bit
140    UINT_32 lsb)        ///< Least signicant bit
141{
142    UINT_64 ret = bits;
143
144    if (msb >= lsb)
145    {
146        ret = AddrGetBits(bits, lsb - 1, 0) // old low bitss
147             | (AddrGetBits(newBits, msb - lsb, 0) << lsb) //new bits
148             | (AddrGetBits(bits, 8 * sizeof(bits) - 1, lsb) << (msb + 1)); //old high bits
149    }
150    return ret;
151}
152
153
154/**
155***************************************************************************************************
156*   AddrCIHwlInit
157*
158*   @brief
159*       Creates an CIAddrLib object.
160*
161*   @return
162*       Returns an CIAddrLib object pointer.
163***************************************************************************************************
164*/
165AddrLib* AddrCIHwlInit(const AddrClient* pClient)
166{
167    return CIAddrLib::CreateObj(pClient);
168}
169
170/**
171***************************************************************************************************
172*   CIAddrLib::CIAddrLib
173*
174*   @brief
175*       Constructor
176*
177***************************************************************************************************
178*/
179CIAddrLib::CIAddrLib(const AddrClient* pClient) :
180    SIAddrLib(pClient),
181    m_noOfMacroEntries(0),
182    m_allowNonDispThickModes(FALSE)
183{
184    m_class = CI_ADDRLIB;
185    memset(&m_settings, 0, sizeof(m_settings));
186}
187
188/**
189***************************************************************************************************
190*   CIAddrLib::~CIAddrLib
191*
192*   @brief
193*       Destructor
194***************************************************************************************************
195*/
196CIAddrLib::~CIAddrLib()
197{
198}
199
200/**
201***************************************************************************************************
202*   CIAddrLib::HwlComputeDccInfo
203*
204*   @brief
205*       Compute DCC key size, base alignment
206*   @return
207*       ADDR_E_RETURNCODE
208***************************************************************************************************
209*/
210ADDR_E_RETURNCODE CIAddrLib::HwlComputeDccInfo(
211    const ADDR_COMPUTE_DCCINFO_INPUT*  pIn,
212    ADDR_COMPUTE_DCCINFO_OUTPUT*       pOut) const
213{
214    ADDR_E_RETURNCODE returnCode = ADDR_OK;
215
216    if (m_settings.isVolcanicIslands && IsMacroTiled(pIn->tileMode))
217    {
218        UINT_64 dccFastClearSize = pIn->colorSurfSize >> 8;
219
220        ADDR_ASSERT(0 == (pIn->colorSurfSize & 0xff));
221
222        if (pIn->numSamples > 1)
223        {
224            UINT_32 tileSizePerSample = BITS_TO_BYTES(pIn->bpp * MicroTileWidth * MicroTileHeight);
225            UINT_32 samplesPerSplit  = pIn->tileInfo.tileSplitBytes / tileSizePerSample;
226
227            if (samplesPerSplit < pIn->numSamples)
228            {
229                UINT_32 numSplits = pIn->numSamples / samplesPerSplit;
230                UINT_32 fastClearBaseAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes;
231
232                ADDR_ASSERT(IsPow2(fastClearBaseAlign));
233
234                dccFastClearSize /= numSplits;
235
236                if (0 != (dccFastClearSize & (fastClearBaseAlign - 1)))
237                {
238                    // Disable dcc fast clear
239                    // if key size of fisrt sample split is not pipe*interleave aligned
240                    dccFastClearSize = 0;
241                }
242            }
243        }
244
245        pOut->dccRamSize          = pIn->colorSurfSize >> 8;
246        pOut->dccRamBaseAlign     = pIn->tileInfo.banks *
247                                    HwlGetPipes(&pIn->tileInfo) *
248                                    m_pipeInterleaveBytes;
249        pOut->dccFastClearSize    = dccFastClearSize;
250
251        ADDR_ASSERT(IsPow2(pOut->dccRamBaseAlign));
252
253        if (0 == (pOut->dccRamSize & (pOut->dccRamBaseAlign - 1)))
254        {
255            pOut->subLvlCompressible = TRUE;
256        }
257        else
258        {
259            UINT_64 dccRamSizeAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes;
260
261            if (pOut->dccRamSize == pOut->dccFastClearSize)
262            {
263                pOut->dccFastClearSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign);
264            }
265            pOut->dccRamSize          = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign);
266            pOut->subLvlCompressible  = FALSE;
267        }
268    }
269    else
270    {
271        returnCode = ADDR_NOTSUPPORTED;
272    }
273
274    return returnCode;
275}
276
277/**
278***************************************************************************************************
279*   CIAddrLib::HwlComputeCmaskAddrFromCoord
280*
281*   @brief
282*       Compute tc compatible Cmask address from fmask ram address
283*
284*   @return
285*       ADDR_E_RETURNCODE
286***************************************************************************************************
287*/
288ADDR_E_RETURNCODE CIAddrLib::HwlComputeCmaskAddrFromCoord(
289    const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT*  pIn,  ///< [in] fmask addr/bpp/tile input
290    ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT*       pOut  ///< [out] cmask address
291    ) const
292{
293    ADDR_E_RETURNCODE returnCode = ADDR_NOTSUPPORTED;
294
295    if ((m_settings.isVolcanicIslands == TRUE) &&
296        (pIn->flags.tcCompatible == TRUE))
297    {
298        UINT_32 numOfPipes   = HwlGetPipes(pIn->pTileInfo);
299        UINT_32 numOfBanks   = pIn->pTileInfo->banks;
300        UINT_64 fmaskAddress = pIn->fmaskAddr;
301        UINT_32 elemBits     = pIn->bpp;
302        UINT_32 blockByte    = 64 * elemBits / 8;
303        UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(fmaskAddress,
304                                                                    0,
305                                                                    0,
306                                                                    4,
307                                                                    elemBits,
308                                                                    blockByte,
309                                                                    m_pipeInterleaveBytes,
310                                                                    numOfPipes,
311                                                                    numOfBanks,
312                                                                    1);
313        pOut->addr = (metaNibbleAddress >> 1);
314        pOut->bitPosition = (metaNibbleAddress % 2) ? 4 : 0;
315        returnCode = ADDR_OK;
316    }
317
318    return returnCode;
319}
320/**
321***************************************************************************************************
322*   CIAddrLib::HwlConvertChipFamily
323*
324*   @brief
325*       Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision
326*   @return
327*       AddrChipFamily
328***************************************************************************************************
329*/
330AddrChipFamily CIAddrLib::HwlConvertChipFamily(
331    UINT_32 uChipFamily,        ///< [in] chip family defined in atiih.h
332    UINT_32 uChipRevision)      ///< [in] chip revision defined in "asic_family"_id.h
333{
334    AddrChipFamily family = ADDR_CHIP_FAMILY_CI;
335
336    switch (uChipFamily)
337    {
338        case FAMILY_CI:
339            m_settings.isSeaIsland  = 1;
340            m_settings.isBonaire    = ASICREV_IS_BONAIRE_M(uChipRevision);
341            m_settings.isHawaii     = ASICREV_IS_HAWAII_P(uChipRevision);
342            break;
343        case FAMILY_KV:
344            m_settings.isKaveri     = 1;
345            m_settings.isSpectre    = ASICREV_IS_SPECTRE(uChipRevision);
346            m_settings.isSpooky     = ASICREV_IS_SPOOKY(uChipRevision);
347            m_settings.isKalindi    = ASICREV_IS_KALINDI(uChipRevision);
348            break;
349        case FAMILY_VI:
350            m_settings.isVolcanicIslands = 1;
351            m_settings.isIceland         = ASICREV_IS_ICELAND_M(uChipRevision);
352            m_settings.isTonga           = ASICREV_IS_TONGA_P(uChipRevision);
353            m_settings.isFiji            = ASICREV_IS_FIJI_P(uChipRevision);
354            m_settings.isPolaris10       = ASICREV_IS_POLARIS10_P(uChipRevision);
355            m_settings.isPolaris11       = ASICREV_IS_POLARIS11_M(uChipRevision);
356            m_settings.isPolaris12       = ASICREV_IS_POLARIS12_V(uChipRevision);
357            break;
358        case FAMILY_CZ:
359            m_settings.isCarrizo         = 1;
360            m_settings.isVolcanicIslands = 1;
361            break;
362        default:
363            ADDR_ASSERT(!"This should be a unexpected Fusion");
364            break;
365    }
366
367    return family;
368}
369
370/**
371***************************************************************************************************
372*   CIAddrLib::HwlInitGlobalParams
373*
374*   @brief
375*       Initializes global parameters
376*
377*   @return
378*       TRUE if all settings are valid
379*
380***************************************************************************************************
381*/
382BOOL_32 CIAddrLib::HwlInitGlobalParams(
383    const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input
384{
385    BOOL_32  valid = TRUE;
386
387    const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue;
388
389    valid = DecodeGbRegs(pRegValue);
390
391    // The following assignments for m_pipes is only for fail-safe, InitTileSettingTable should
392    // read the correct pipes from tile mode table
393    if (m_settings.isHawaii)
394    {
395        // Hawaii has 16-pipe, see GFXIP_Config_Summary.xls
396        m_pipes = 16;
397    }
398    else if (m_settings.isBonaire || m_settings.isSpectre)
399    {
400        m_pipes = 4;
401    }
402    else // Treat other KV asics to be 2-pipe
403    {
404        m_pipes = 2;
405    }
406
407    // @todo: VI
408    // Move this to VI code path once created
409    if (m_settings.isTonga || m_settings.isPolaris10)
410    {
411        m_pipes = 8;
412    }
413    else if (m_settings.isIceland)
414    {
415        m_pipes = 2;
416    }
417    else if (m_settings.isFiji)
418    {
419        m_pipes = 16;
420    }
421    else if (m_settings.isPolaris11 || m_settings.isPolaris12)
422    {
423        m_pipes = 4;
424    }
425
426    if (valid)
427    {
428        valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
429    }
430    if (valid)
431    {
432        valid = InitMacroTileCfgTable(pRegValue->pMacroTileConfig, pRegValue->noOfMacroEntries);
433    }
434
435    return valid;
436}
437
438/**
439***************************************************************************************************
440*   CIAddrLib::HwlPostCheckTileIndex
441*
442*   @brief
443*       Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
444*       tile mode/type/info and change the index if needed
445*   @return
446*       Tile index.
447***************************************************************************************************
448*/
449INT_32 CIAddrLib::HwlPostCheckTileIndex(
450    const ADDR_TILEINFO* pInfo,     ///< [in] Tile Info
451    AddrTileMode         mode,      ///< [in] Tile mode
452    AddrTileType         type,      ///< [in] Tile type
453    INT                  curIndex   ///< [in] Current index assigned in HwlSetupTileInfo
454    ) const
455{
456    INT_32 index = curIndex;
457
458    if (mode == ADDR_TM_LINEAR_GENERAL)
459    {
460        index = TileIndexLinearGeneral;
461    }
462    else
463    {
464        BOOL_32 macroTiled = IsMacroTiled(mode);
465
466        // We need to find a new index if either of them is true
467        // 1. curIndex is invalid
468        // 2. tile mode is changed
469        // 3. tile info does not match for macro tiled
470        if ((index == TileIndexInvalid)         ||
471            (mode != m_tileTable[index].mode)   ||
472            (macroTiled && pInfo->pipeConfig != m_tileTable[index].info.pipeConfig))
473        {
474            for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
475            {
476                if (macroTiled)
477                {
478                    // macro tile modes need all to match
479                    if ((pInfo->pipeConfig == m_tileTable[index].info.pipeConfig) &&
480                        (mode == m_tileTable[index].mode) &&
481                        (type == m_tileTable[index].type))
482                    {
483                        // tileSplitBytes stored in m_tileTable is only valid for depth entries
484                        if (type == ADDR_DEPTH_SAMPLE_ORDER)
485                        {
486                            if (pInfo->tileSplitBytes == m_tileTable[index].info.tileSplitBytes)
487                            {
488                                break;
489                            }
490                        }
491                        else // other entries are determined by other 3 fields
492                        {
493                            break;
494                        }
495                    }
496                }
497                else if (mode == ADDR_TM_LINEAR_ALIGNED)
498                {
499                    // linear mode only needs tile mode to match
500                    if (mode == m_tileTable[index].mode)
501                    {
502                        break;
503                    }
504                }
505                else
506                {
507                    // micro tile modes only need tile mode and tile type to match
508                    if (mode == m_tileTable[index].mode &&
509                        type == m_tileTable[index].type)
510                    {
511                        break;
512                    }
513                }
514            }
515        }
516    }
517
518    ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
519
520    if (index >= static_cast<INT_32>(m_noOfEntries))
521    {
522        index = TileIndexInvalid;
523    }
524
525    return index;
526}
527
528/**
529***************************************************************************************************
530*   CIAddrLib::HwlSetupTileCfg
531*
532*   @brief
533*       Map tile index to tile setting.
534*   @return
535*       ADDR_E_RETURNCODE
536***************************************************************************************************
537*/
538ADDR_E_RETURNCODE CIAddrLib::HwlSetupTileCfg(
539    INT_32          index,          ///< [in] Tile index
540    INT_32          macroModeIndex, ///< [in] Index in macro tile mode table(CI)
541    ADDR_TILEINFO*  pInfo,          ///< [out] Tile Info
542    AddrTileMode*   pMode,          ///< [out] Tile mode
543    AddrTileType*   pType           ///< [out] Tile type
544    ) const
545{
546    ADDR_E_RETURNCODE returnCode = ADDR_OK;
547
548    // Global flag to control usage of tileIndex
549    if (UseTileIndex(index))
550    {
551        if (static_cast<UINT_32>(index) >= m_noOfEntries)
552        {
553            returnCode = ADDR_INVALIDPARAMS;
554        }
555        else
556        {
557            const ADDR_TILECONFIG* pCfgTable = GetTileSetting(index);
558
559            if (pInfo != NULL)
560            {
561                if (IsMacroTiled(pCfgTable->mode))
562                {
563                    ADDR_ASSERT(((macroModeIndex != TileIndexInvalid)
564                        && (macroModeIndex != TileIndexNoMacroIndex)));
565                    // Here we used tile_bytes to replace of tile_split
566                    // According info as below:
567                    // "tile_split_c = MIN(ROW_SIZE, tile_split)
568                    // "tile_bytes = MIN(tile_split_c, num_samples * tile_bytes_1x)
569                    // when using tile_bytes replacing of tile_split, the result of
570                    // alignment and others(such as slicesPerTile) are unaffected -
571                    // since if tile_split_c is larger, split won't happen, otherwise
572                    // (num_samples * tile_bytes_1x is larger), a correct tile_split is
573                    // returned.
574                    *pInfo = m_macroTileTable[macroModeIndex];
575
576                    if (pCfgTable->type == ADDR_DEPTH_SAMPLE_ORDER)
577                    {
578                        pInfo->tileSplitBytes = pCfgTable->info.tileSplitBytes;
579                    }
580                    pInfo->pipeConfig = pCfgTable->info.pipeConfig;
581                }
582                else // 1D and linear modes, we return default value stored in table
583                {
584                    *pInfo = pCfgTable->info;
585                }
586            }
587
588            if (pMode != NULL)
589            {
590                *pMode = pCfgTable->mode;
591            }
592
593            if (pType != NULL)
594            {
595                *pType = pCfgTable->type;
596            }
597        }
598    }
599
600    return returnCode;
601}
602
603/**
604***************************************************************************************************
605*   CIAddrLib::HwlComputeSurfaceInfo
606*
607*   @brief
608*       Entry of ci's ComputeSurfaceInfo
609*   @return
610*       ADDR_E_RETURNCODE
611***************************************************************************************************
612*/
613ADDR_E_RETURNCODE CIAddrLib::HwlComputeSurfaceInfo(
614    const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,    ///< [in] input structure
615    ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [out] output structure
616    ) const
617{
618    // If tileIndex is invalid, force macroModeIndex to be invalid, too
619    if (pIn->tileIndex == TileIndexInvalid)
620    {
621        pOut->macroModeIndex = TileIndexInvalid;
622    }
623
624    ADDR_E_RETURNCODE retCode = SIAddrLib::HwlComputeSurfaceInfo(pIn,pOut);
625
626    if (pOut->macroModeIndex == TileIndexNoMacroIndex)
627    {
628        pOut->macroModeIndex = TileIndexInvalid;
629    }
630
631    return retCode;
632}
633
634/**
635***************************************************************************************************
636*   CIAddrLib::HwlFmaskSurfaceInfo
637*   @brief
638*       Entry of r800's ComputeFmaskInfo
639*   @return
640*       ADDR_E_RETURNCODE
641***************************************************************************************************
642*/
643ADDR_E_RETURNCODE CIAddrLib::HwlComputeFmaskInfo(
644    const ADDR_COMPUTE_FMASK_INFO_INPUT*    pIn,   ///< [in] input structure
645    ADDR_COMPUTE_FMASK_INFO_OUTPUT*         pOut   ///< [out] output structure
646    )
647{
648    ADDR_E_RETURNCODE retCode = ADDR_OK;
649
650    ADDR_TILEINFO tileInfo = {0};
651    ADDR_COMPUTE_FMASK_INFO_INPUT fmaskIn;
652    fmaskIn = *pIn;
653
654    AddrTileMode tileMode = pIn->tileMode;
655
656    // Use internal tile info if pOut does not have a valid pTileInfo
657    if (pOut->pTileInfo == NULL)
658    {
659        pOut->pTileInfo = &tileInfo;
660    }
661
662    ADDR_ASSERT(tileMode == ADDR_TM_2D_TILED_THIN1     ||
663                tileMode == ADDR_TM_3D_TILED_THIN1     ||
664                tileMode == ADDR_TM_PRT_TILED_THIN1    ||
665                tileMode == ADDR_TM_PRT_2D_TILED_THIN1 ||
666                tileMode == ADDR_TM_PRT_3D_TILED_THIN1);
667
668    ADDR_ASSERT(m_tileTable[14].mode == ADDR_TM_2D_TILED_THIN1);
669    ADDR_ASSERT(m_tileTable[15].mode == ADDR_TM_3D_TILED_THIN1);
670
671    // The only valid tile modes for fmask are 2D_THIN1 and 3D_THIN1 plus non-displayable
672    INT_32 tileIndex = tileMode == ADDR_TM_2D_TILED_THIN1 ? 14 : 15;
673    ADDR_SURFACE_FLAGS flags = {{0}};
674    flags.fmask = 1;
675
676    INT_32 macroModeIndex = TileIndexInvalid;
677
678    UINT_32 numSamples = pIn->numSamples;
679    UINT_32 numFrags = pIn->numFrags == 0 ? numSamples : pIn->numFrags;
680
681    UINT_32 bpp = QLog2(numFrags);
682
683    // EQAA needs one more bit
684    if (numSamples > numFrags)
685    {
686        bpp++;
687    }
688
689    if (bpp == 3)
690    {
691        bpp = 4;
692    }
693
694    bpp = Max(8u, bpp * numSamples);
695
696    macroModeIndex = HwlComputeMacroModeIndex(tileIndex, flags, bpp, numSamples, pOut->pTileInfo);
697
698    fmaskIn.tileIndex = tileIndex;
699    fmaskIn.pTileInfo = pOut->pTileInfo;
700    pOut->macroModeIndex = macroModeIndex;
701    pOut->tileIndex = tileIndex;
702
703    retCode = DispatchComputeFmaskInfo(&fmaskIn, pOut);
704
705    if (retCode == ADDR_OK)
706    {
707        pOut->tileIndex =
708            HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE,
709                                  pOut->tileIndex);
710    }
711
712    // Resets pTileInfo to NULL if the internal tile info is used
713    if (pOut->pTileInfo == &tileInfo)
714    {
715        pOut->pTileInfo = NULL;
716    }
717
718    return retCode;
719}
720
721/**
722***************************************************************************************************
723*   CIAddrLib::HwlFmaskPreThunkSurfInfo
724*
725*   @brief
726*       Some preparation before thunking a ComputeSurfaceInfo call for Fmask
727*   @return
728*       ADDR_E_RETURNCODE
729***************************************************************************************************
730*/
731VOID CIAddrLib::HwlFmaskPreThunkSurfInfo(
732    const ADDR_COMPUTE_FMASK_INFO_INPUT*    pFmaskIn,   ///< [in] Input of fmask info
733    const ADDR_COMPUTE_FMASK_INFO_OUTPUT*   pFmaskOut,  ///< [in] Output of fmask info
734    ADDR_COMPUTE_SURFACE_INFO_INPUT*        pSurfIn,    ///< [out] Input of thunked surface info
735    ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pSurfOut    ///< [out] Output of thunked surface info
736    ) const
737{
738    pSurfIn->tileIndex = pFmaskIn->tileIndex;
739    pSurfOut->macroModeIndex  = pFmaskOut->macroModeIndex;
740}
741
742/**
743***************************************************************************************************
744*   CIAddrLib::HwlFmaskPostThunkSurfInfo
745*
746*   @brief
747*       Copy hwl extra field after calling thunked ComputeSurfaceInfo
748*   @return
749*       ADDR_E_RETURNCODE
750***************************************************************************************************
751*/
752VOID CIAddrLib::HwlFmaskPostThunkSurfInfo(
753    const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut,   ///< [in] Output of surface info
754    ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut           ///< [out] Output of fmask info
755    ) const
756{
757    pFmaskOut->tileIndex = pSurfOut->tileIndex;
758    pFmaskOut->macroModeIndex = pSurfOut->macroModeIndex;
759}
760
761/**
762***************************************************************************************************
763*   CIAddrLib::HwlDegradeThickTileMode
764*
765*   @brief
766*       Degrades valid tile mode for thick modes if needed
767*
768*   @return
769*       Suitable tile mode
770***************************************************************************************************
771*/
772AddrTileMode CIAddrLib::HwlDegradeThickTileMode(
773    AddrTileMode        baseTileMode,   ///< [in] base tile mode
774    UINT_32             numSlices,      ///< [in] current number of slices
775    UINT_32*            pBytesPerTile   ///< [in/out] pointer to bytes per slice
776    ) const
777{
778    return baseTileMode;
779}
780
781/**
782***************************************************************************************************
783*   CIAddrLib::HwlOverrideTileMode
784*
785*   @brief
786*       Override THICK to THIN, for specific formats on CI
787*
788*   @return
789*       Suitable tile mode
790*
791***************************************************************************************************
792*/
793BOOL_32 CIAddrLib::HwlOverrideTileMode(
794    const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,       ///< [in] input structure
795    AddrTileMode*                           pTileMode, ///< [in/out] pointer to the tile mode
796    AddrTileType*                           pTileType  ///< [in/out] pointer to the tile type
797    ) const
798{
799    BOOL_32 bOverrided = FALSE;
800    AddrTileMode tileMode = *pTileMode;
801
802    // currently, all CI/VI family do not
803    // support ADDR_TM_PRT_2D_TILED_THICK,ADDR_TM_PRT_3D_TILED_THICK and
804    // ADDR_TM_PRT_2D_TILED_THIN1, ADDR_TM_PRT_3D_TILED_THIN1
805    switch (tileMode)
806    {
807        case ADDR_TM_PRT_2D_TILED_THICK:
808        case ADDR_TM_PRT_3D_TILED_THICK:
809            tileMode = ADDR_TM_PRT_TILED_THICK;
810            break;
811        case ADDR_TM_PRT_2D_TILED_THIN1:
812        case ADDR_TM_PRT_3D_TILED_THIN1:
813            tileMode = ADDR_TM_PRT_TILED_THIN1;
814            break;
815        default:
816            break;
817    }
818
819    // UBTS#404321, we do not need such overriding, as THICK+THICK entries removed from the tile-mode table
820    if (!m_settings.isBonaire)
821    {
822        UINT_32 thickness = ComputeSurfaceThickness(tileMode);
823
824        // tile_thickness = (array_mode == XTHICK) ? 8 : ((array_mode == THICK) ? 4 : 1)
825        if (thickness > 1)
826        {
827            switch (pIn->format)
828            {
829                // see //gfxip/gcB/devel/cds/src/verif/tc/models/csim/tcp.cpp
830                // tcpError("Thick micro tiling is not supported for format...
831                case ADDR_FMT_X24_8_32_FLOAT:
832                case ADDR_FMT_32_AS_8:
833                case ADDR_FMT_32_AS_8_8:
834                case ADDR_FMT_32_AS_32_32_32_32:
835
836                // packed formats
837                case ADDR_FMT_GB_GR:
838                case ADDR_FMT_BG_RG:
839                case ADDR_FMT_1_REVERSED:
840                case ADDR_FMT_1:
841                case ADDR_FMT_BC1:
842                case ADDR_FMT_BC2:
843                case ADDR_FMT_BC3:
844                case ADDR_FMT_BC4:
845                case ADDR_FMT_BC5:
846                case ADDR_FMT_BC6:
847                case ADDR_FMT_BC7:
848                    switch (tileMode)
849                    {
850                        case ADDR_TM_1D_TILED_THICK:
851                            tileMode    = ADDR_TM_1D_TILED_THIN1;
852                            break;
853
854                        case ADDR_TM_2D_TILED_XTHICK:
855                        case ADDR_TM_2D_TILED_THICK:
856                            tileMode    = ADDR_TM_2D_TILED_THIN1;
857                            break;
858
859                        case ADDR_TM_3D_TILED_XTHICK:
860                        case ADDR_TM_3D_TILED_THICK:
861                            tileMode    = ADDR_TM_3D_TILED_THIN1;
862                            break;
863
864                        case ADDR_TM_PRT_TILED_THICK:
865                            tileMode    = ADDR_TM_PRT_TILED_THIN1;
866                            break;
867
868                        case ADDR_TM_PRT_2D_TILED_THICK:
869                            tileMode    = ADDR_TM_PRT_2D_TILED_THIN1;
870                            break;
871
872                        case ADDR_TM_PRT_3D_TILED_THICK:
873                            tileMode    = ADDR_TM_PRT_3D_TILED_THIN1;
874                            break;
875
876                        default:
877                            break;
878
879                    }
880
881                    // Switch tile type from thick to thin
882                    if (tileMode != *pTileMode)
883                    {
884                        // see tileIndex: 13-18
885                        *pTileType = ADDR_NON_DISPLAYABLE;
886                    }
887
888                    break;
889                default:
890                    break;
891            }
892        }
893    }
894
895    if (tileMode != *pTileMode)
896    {
897        *pTileMode = tileMode;
898        bOverrided = TRUE;
899    }
900
901    return bOverrided;
902}
903
904/**
905***************************************************************************************************
906*   CiAddrLib::GetPrtSwitchP4Threshold
907*
908*   @brief
909*       Return the threshold of switching to P4_* instead of P16_* for PRT resources
910***************************************************************************************************
911*/
912UINT_32 CIAddrLib::GetPrtSwitchP4Threshold() const
913{
914    UINT_32 threshold;
915
916    switch (m_pipes)
917    {
918        case 8:
919            threshold = 32;
920            break;
921        case 16:
922            if (m_settings.isFiji)
923            {
924                threshold = 16;
925            }
926            else if (m_settings.isHawaii)
927            {
928                threshold = 8;
929            }
930            else
931            {
932                ///@todo add for possible new ASICs.
933                ADDR_ASSERT_ALWAYS();
934                threshold = 16;
935            }
936            break;
937        default:
938            ///@todo add for possible new ASICs.
939            ADDR_ASSERT_ALWAYS();
940            threshold = 32;
941            break;
942    }
943
944    return threshold;
945}
946
947/**
948***************************************************************************************************
949*   CIAddrLib::HwlSetupTileInfo
950*
951*   @brief
952*       Setup default value of tile info for SI
953***************************************************************************************************
954*/
955VOID CIAddrLib::HwlSetupTileInfo(
956    AddrTileMode                        tileMode,       ///< [in] Tile mode
957    ADDR_SURFACE_FLAGS                  flags,          ///< [in] Surface type flags
958    UINT_32                             bpp,            ///< [in] Bits per pixel
959    UINT_32                             pitch,          ///< [in] Pitch in pixels
960    UINT_32                             height,         ///< [in] Height in pixels
961    UINT_32                             numSamples,     ///< [in] Number of samples
962    ADDR_TILEINFO*                      pTileInfoIn,    ///< [in] Tile info input: NULL for default
963    ADDR_TILEINFO*                      pTileInfoOut,   ///< [out] Tile info output
964    AddrTileType                        inTileType,     ///< [in] Tile type
965    ADDR_COMPUTE_SURFACE_INFO_OUTPUT*   pOut            ///< [out] Output
966    ) const
967{
968    UINT_32 thickness = ComputeSurfaceThickness(tileMode);
969    ADDR_TILEINFO* pTileInfo = pTileInfoOut;
970    INT index = TileIndexInvalid;
971    INT macroModeIndex = TileIndexInvalid;
972
973    // Fail-safe code
974    if (!IsLinear(tileMode))
975    {
976        // Thick tile modes must use thick micro tile mode but Bonaire does not support due to
977        // old derived netlists (UBTS 404321)
978        if (thickness > 1)
979        {
980            if (m_settings.isBonaire)
981            {
982                inTileType = ADDR_NON_DISPLAYABLE;
983            }
984            else if ((m_allowNonDispThickModes == FALSE) || (inTileType != ADDR_NON_DISPLAYABLE))
985            {
986                inTileType = ADDR_THICK;
987            }
988        }
989        // 128 bpp tiling must be non-displayable.
990        // Fmask reuse color buffer's entry but bank-height field can be from another entry
991        // To simplify the logic, fmask entry should be picked from non-displayable ones
992        else if (bpp == 128 || flags.fmask)
993        {
994            inTileType = ADDR_NON_DISPLAYABLE;
995        }
996        // These two modes only have non-disp entries though they can be other micro tile modes
997        else if (tileMode == ADDR_TM_3D_TILED_THIN1 || tileMode == ADDR_TM_PRT_3D_TILED_THIN1)
998        {
999            inTileType = ADDR_NON_DISPLAYABLE;
1000        }
1001
1002        if (flags.depth || flags.stencil)
1003        {
1004            inTileType = ADDR_DEPTH_SAMPLE_ORDER;
1005        }
1006    }
1007
1008    if (IsTileInfoAllZero(pTileInfo))
1009    {
1010        // See table entries 0-4
1011        if (flags.depth || flags.stencil)
1012        {
1013            if (flags.depth && flags.tcCompatible)
1014            {
1015                // tileSize = bpp * numSamples * 8 * 8 / 8
1016                UINT_32 tileSize = bpp * numSamples * 8;
1017
1018                // Texure readable depth surface should not be split
1019                switch (tileSize)
1020                {
1021                    case 128:
1022                        index = 1;
1023                        break;
1024                    case 256:
1025                        index = 2;
1026                        break;
1027                    case 512:
1028                        index = 3;
1029                        break;
1030                    default:
1031                        index = 4;
1032                        break;
1033                }
1034            }
1035            else
1036            {
1037                // Depth and stencil need to use the same index, thus the pre-defined tile_split
1038                // can meet the requirement to choose the same macro mode index
1039                // uncompressed depth/stencil are not supported for now
1040                switch (numSamples)
1041                {
1042                    case 1:
1043                        index = 0;
1044                        break;
1045                    case 2:
1046                    case 4:
1047                        index = 1;
1048                        break;
1049                    case 8:
1050                        index = 2;
1051                        break;
1052                    default:
1053                        break;
1054                }
1055            }
1056        }
1057
1058        // See table entries 5-6
1059        if (inTileType == ADDR_DEPTH_SAMPLE_ORDER)
1060        {
1061            switch (tileMode)
1062            {
1063                case ADDR_TM_1D_TILED_THIN1:
1064                    index = 5;
1065                    break;
1066                case ADDR_TM_PRT_TILED_THIN1:
1067                    index = 6;
1068                    break;
1069                default:
1070                    break;
1071            }
1072        }
1073
1074        // See table entries 8-12
1075        if (inTileType == ADDR_DISPLAYABLE)
1076        {
1077            switch (tileMode)
1078            {
1079                case ADDR_TM_1D_TILED_THIN1:
1080                    index = 9;
1081                    break;
1082                case ADDR_TM_2D_TILED_THIN1:
1083                    index = 10;
1084                    break;
1085                case ADDR_TM_PRT_TILED_THIN1:
1086                    index = 11;
1087                    break;
1088                default:
1089                    break;
1090            }
1091        }
1092
1093        // See table entries 13-18
1094        if (inTileType == ADDR_NON_DISPLAYABLE)
1095        {
1096            switch (tileMode)
1097            {
1098                case ADDR_TM_1D_TILED_THIN1:
1099                    index = 13;
1100                    break;
1101                case ADDR_TM_2D_TILED_THIN1:
1102                    index = 14;
1103                    break;
1104                case ADDR_TM_3D_TILED_THIN1:
1105                    index = 15;
1106                    break;
1107                case ADDR_TM_PRT_TILED_THIN1:
1108                    index = 16;
1109                    break;
1110                default:
1111                    break;
1112            }
1113        }
1114
1115        // See table entries 19-26
1116        if (thickness > 1)
1117        {
1118            switch (tileMode)
1119            {
1120            case ADDR_TM_1D_TILED_THICK:
1121                    //special check for bonaire, for the compatablity between old KMD and new UMD for bonaire
1122                    index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 19 : 18;
1123                    break;
1124            case ADDR_TM_2D_TILED_THICK:
1125                    // special check for bonaire, for the compatablity between old KMD and new UMD for bonaire
1126                    index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 20 : 24;
1127                    break;
1128                case ADDR_TM_3D_TILED_THICK:
1129                    index = 21;
1130                    break;
1131                case ADDR_TM_PRT_TILED_THICK:
1132                    index = 22;
1133                    break;
1134                case ADDR_TM_2D_TILED_XTHICK:
1135                    index = 25;
1136                    break;
1137                case ADDR_TM_3D_TILED_XTHICK:
1138                    index = 26;
1139                    break;
1140                default:
1141                    break;
1142            }
1143        }
1144
1145        // See table entries 27-30
1146        if (inTileType == ADDR_ROTATED)
1147        {
1148            switch (tileMode)
1149            {
1150                case ADDR_TM_1D_TILED_THIN1:
1151                    index = 27;
1152                    break;
1153                case ADDR_TM_2D_TILED_THIN1:
1154                    index = 28;
1155                    break;
1156                case ADDR_TM_PRT_TILED_THIN1:
1157                    index = 29;
1158                    break;
1159                case ADDR_TM_PRT_2D_TILED_THIN1:
1160                    index = 30;
1161                    break;
1162                default:
1163                    break;
1164            }
1165        }
1166
1167        if (m_pipes >= 8)
1168        {
1169            ADDR_ASSERT((index + 1) < static_cast<INT_32>(m_noOfEntries));
1170            // Only do this when tile mode table is updated.
1171            if (((tileMode == ADDR_TM_PRT_TILED_THIN1) || (tileMode == ADDR_TM_PRT_TILED_THICK)) &&
1172                (m_tileTable[index+1].mode == tileMode))
1173            {
1174                UINT_32 bytesXSamples = bpp * numSamples / 8;
1175                UINT_32 bytesXThickness = bpp * thickness / 8;
1176                UINT_32 switchP4Threshold = GetPrtSwitchP4Threshold();
1177
1178                if ((bytesXSamples > switchP4Threshold) || (bytesXThickness > switchP4Threshold))
1179                {
1180                    // Pick next 4 pipe entry
1181                    index += 1;
1182                }
1183            }
1184        }
1185    }
1186    else
1187    {
1188        // A pre-filled tile info is ready
1189        index = pOut->tileIndex;
1190        macroModeIndex = pOut->macroModeIndex;
1191
1192        // pass tile type back for post tile index compute
1193        pOut->tileType = inTileType;
1194    }
1195
1196    // We only need to set up tile info if there is a valid index but macroModeIndex is invalid
1197    if (index != TileIndexInvalid && macroModeIndex == TileIndexInvalid)
1198    {
1199        macroModeIndex = HwlComputeMacroModeIndex(index, flags, bpp, numSamples, pTileInfo);
1200
1201        /// Copy to pOut->tileType/tileIndex/macroModeIndex
1202        pOut->tileIndex = index;
1203        pOut->tileType = m_tileTable[index].type; // Or inTileType, the samea
1204        pOut->macroModeIndex = macroModeIndex;
1205    }
1206    else if (tileMode == ADDR_TM_LINEAR_GENERAL)
1207    {
1208        pOut->tileIndex = TileIndexLinearGeneral;
1209
1210        // Copy linear-aligned entry??
1211        *pTileInfo = m_tileTable[8].info;
1212    }
1213    else if (tileMode == ADDR_TM_LINEAR_ALIGNED)
1214    {
1215        pOut->tileIndex = 8;
1216        *pTileInfo = m_tileTable[8].info;
1217    }
1218}
1219
1220/**
1221***************************************************************************************************
1222*   CIAddrLib::ReadGbTileMode
1223*
1224*   @brief
1225*       Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
1226*   @return
1227*       NA.
1228***************************************************************************************************
1229*/
1230VOID CIAddrLib::ReadGbTileMode(
1231    UINT_32             regValue,   ///< [in] GB_TILE_MODE register
1232    ADDR_TILECONFIG*    pCfg        ///< [out] output structure
1233    ) const
1234{
1235    GB_TILE_MODE gbTileMode;
1236    gbTileMode.val = regValue;
1237
1238    pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode_new);
1239    pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
1240
1241    if (pCfg->type == ADDR_DEPTH_SAMPLE_ORDER)
1242    {
1243        pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
1244    }
1245    else
1246    {
1247        pCfg->info.tileSplitBytes = 1 << gbTileMode.f.sample_split;
1248    }
1249
1250    UINT_32 regArrayMode = gbTileMode.f.array_mode;
1251
1252    pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
1253
1254    switch (regArrayMode)
1255    {
1256        case 5:
1257            pCfg->mode = ADDR_TM_PRT_TILED_THIN1;
1258            break;
1259        case 6:
1260            pCfg->mode = ADDR_TM_PRT_2D_TILED_THIN1;
1261            break;
1262        case 8:
1263            pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
1264            break;
1265        case 9:
1266            pCfg->mode = ADDR_TM_PRT_TILED_THICK;
1267            break;
1268        case 0xa:
1269            pCfg->mode = ADDR_TM_PRT_2D_TILED_THICK;
1270            break;
1271        case 0xb:
1272            pCfg->mode = ADDR_TM_PRT_3D_TILED_THIN1;
1273            break;
1274        case 0xe:
1275            pCfg->mode = ADDR_TM_3D_TILED_XTHICK;
1276            break;
1277        case 0xf:
1278            pCfg->mode = ADDR_TM_PRT_3D_TILED_THICK;
1279            break;
1280        default:
1281            break;
1282    }
1283
1284    // Fail-safe code for these always convert tile info, as the non-macro modes
1285    // return the entry of tile mode table directly without looking up macro mode table
1286    if (!IsMacroTiled(pCfg->mode))
1287    {
1288        pCfg->info.banks = 2;
1289        pCfg->info.bankWidth = 1;
1290        pCfg->info.bankHeight = 1;
1291        pCfg->info.macroAspectRatio = 1;
1292        pCfg->info.tileSplitBytes = 64;
1293    }
1294}
1295
1296/**
1297***************************************************************************************************
1298*   CIAddrLib::InitTileSettingTable
1299*
1300*   @brief
1301*       Initialize the ADDR_TILE_CONFIG table.
1302*   @return
1303*       TRUE if tile table is correctly initialized
1304***************************************************************************************************
1305*/
1306BOOL_32 CIAddrLib::InitTileSettingTable(
1307    const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
1308    UINT_32         noOfEntries     ///< [in] Numbe of entries in the table above
1309    )
1310{
1311    BOOL_32 initOk = TRUE;
1312
1313    ADDR_ASSERT(noOfEntries <= TileTableSize);
1314
1315    memset(m_tileTable, 0, sizeof(m_tileTable));
1316
1317    if (noOfEntries != 0)
1318    {
1319        m_noOfEntries = noOfEntries;
1320    }
1321    else
1322    {
1323        m_noOfEntries = TileTableSize;
1324    }
1325
1326    if (pCfg) // From Client
1327    {
1328        for (UINT_32 i = 0; i < m_noOfEntries; i++)
1329        {
1330            ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
1331        }
1332    }
1333    else
1334    {
1335        ADDR_ASSERT_ALWAYS();
1336        initOk = FALSE;
1337    }
1338
1339    if (initOk)
1340    {
1341        ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
1342
1343        if (m_settings.isBonaire == FALSE)
1344        {
1345            // Check if entry 18 is "thick+thin" combination
1346            if ((m_tileTable[18].mode == ADDR_TM_1D_TILED_THICK) &&
1347                (m_tileTable[18].type == ADDR_NON_DISPLAYABLE))
1348            {
1349                m_allowNonDispThickModes = TRUE;
1350                ADDR_ASSERT(m_tileTable[24].mode == ADDR_TM_2D_TILED_THICK);
1351            }
1352        }
1353        else
1354        {
1355            m_allowNonDispThickModes = TRUE;
1356        }
1357
1358        // Assume the first entry is always programmed with full pipes
1359        m_pipes = HwlGetPipes(&m_tileTable[0].info);
1360    }
1361
1362    return initOk;
1363}
1364
1365/**
1366***************************************************************************************************
1367*   CIAddrLib::ReadGbMacroTileCfg
1368*
1369*   @brief
1370*       Convert GB_MACRO_TILE_CFG HW value to ADDR_TILE_CONFIG.
1371*   @return
1372*       NA.
1373***************************************************************************************************
1374*/
1375VOID CIAddrLib::ReadGbMacroTileCfg(
1376    UINT_32             regValue,   ///< [in] GB_MACRO_TILE_MODE register
1377    ADDR_TILEINFO*      pCfg        ///< [out] output structure
1378    ) const
1379{
1380    GB_MACROTILE_MODE gbTileMode;
1381    gbTileMode.val = regValue;
1382
1383    pCfg->bankHeight = 1 << gbTileMode.f.bank_height;
1384    pCfg->bankWidth = 1 << gbTileMode.f.bank_width;
1385    pCfg->banks = 1 << (gbTileMode.f.num_banks + 1);
1386    pCfg->macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
1387}
1388
1389/**
1390***************************************************************************************************
1391*   CIAddrLib::InitMacroTileCfgTable
1392*
1393*   @brief
1394*       Initialize the ADDR_MACRO_TILE_CONFIG table.
1395*   @return
1396*       TRUE if macro tile table is correctly initialized
1397***************************************************************************************************
1398*/
1399BOOL_32 CIAddrLib::InitMacroTileCfgTable(
1400    const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
1401    UINT_32         noOfMacroEntries     ///< [in] Numbe of entries in the table above
1402    )
1403{
1404    BOOL_32 initOk = TRUE;
1405
1406    ADDR_ASSERT(noOfMacroEntries <= MacroTileTableSize);
1407
1408    memset(m_macroTileTable, 0, sizeof(m_macroTileTable));
1409
1410    if (noOfMacroEntries != 0)
1411    {
1412        m_noOfMacroEntries = noOfMacroEntries;
1413    }
1414    else
1415    {
1416        m_noOfMacroEntries = MacroTileTableSize;
1417    }
1418
1419    if (pCfg) // From Client
1420    {
1421        for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
1422        {
1423            ReadGbMacroTileCfg(*(pCfg + i), &m_macroTileTable[i]);
1424
1425            m_macroTileTable[i].tileSplitBytes = 64 << (i % 8);
1426        }
1427    }
1428    else
1429    {
1430        ADDR_ASSERT_ALWAYS();
1431        initOk = FALSE;
1432    }
1433    return initOk;
1434}
1435
1436/**
1437***************************************************************************************************
1438*   CIAddrLib::HwlComputeMacroModeIndex
1439*
1440*   @brief
1441*       Computes macro tile mode index
1442*   @return
1443*       TRUE if macro tile table is correctly initialized
1444***************************************************************************************************
1445*/
1446INT_32 CIAddrLib::HwlComputeMacroModeIndex(
1447    INT_32              tileIndex,      ///< [in] Tile mode index
1448    ADDR_SURFACE_FLAGS  flags,          ///< [in] Surface flags
1449    UINT_32             bpp,            ///< [in] Bit per pixel
1450    UINT_32             numSamples,     ///< [in] Number of samples
1451    ADDR_TILEINFO*      pTileInfo,      ///< [out] Pointer to ADDR_TILEINFO
1452    AddrTileMode*       pTileMode,      ///< [out] Pointer to AddrTileMode
1453    AddrTileType*       pTileType       ///< [out] Pointer to AddrTileType
1454    ) const
1455{
1456    INT_32 macroModeIndex = TileIndexInvalid;
1457
1458    if (flags.tcCompatible && flags.stencil)
1459    {
1460        // Don't compute macroModeIndex for tc compatible stencil surface
1461        macroModeIndex = TileIndexNoMacroIndex;
1462    }
1463    else
1464    {
1465        AddrTileMode tileMode = m_tileTable[tileIndex].mode;
1466        AddrTileType tileType = m_tileTable[tileIndex].type;
1467        UINT_32 thickness = ComputeSurfaceThickness(tileMode);
1468
1469        if (!IsMacroTiled(tileMode))
1470        {
1471            *pTileInfo = m_tileTable[tileIndex].info;
1472            macroModeIndex = TileIndexNoMacroIndex;
1473        }
1474        else
1475        {
1476            UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
1477            UINT_32 tileSplit;
1478
1479            if (m_tileTable[tileIndex].type == ADDR_DEPTH_SAMPLE_ORDER)
1480            {
1481                // Depth entries store real tileSplitBytes
1482                tileSplit = m_tileTable[tileIndex].info.tileSplitBytes;
1483            }
1484            else
1485            {
1486                // Non-depth entries store a split factor
1487                UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes;
1488                UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x);
1489
1490                tileSplit = colorTileSplit;
1491            }
1492
1493            UINT_32 tileSplitC = Min(m_rowSize, tileSplit);
1494            UINT_32 tileBytes;
1495
1496            if (flags.fmask)
1497            {
1498                tileBytes = Min(tileSplitC, tileBytes1x);
1499            }
1500            else
1501            {
1502                tileBytes = Min(tileSplitC, numSamples * tileBytes1x);
1503            }
1504
1505            if (tileBytes < 64)
1506            {
1507                tileBytes = 64;
1508            }
1509
1510            macroModeIndex = Log2(tileBytes / 64);
1511
1512            if (flags.prt || IsPrtTileMode(tileMode))
1513            {
1514                // Unknown - assume it is 1/2 of table size
1515                const UINT_32 PrtMacroModeOffset = MacroTileTableSize / 2;
1516
1517                macroModeIndex += PrtMacroModeOffset;
1518                *pTileInfo = m_macroTileTable[macroModeIndex];
1519            }
1520            else
1521            {
1522                *pTileInfo = m_macroTileTable[macroModeIndex];
1523            }
1524
1525            pTileInfo->pipeConfig = m_tileTable[tileIndex].info.pipeConfig;
1526
1527            if (m_tileTable[tileIndex].type != ADDR_DEPTH_SAMPLE_ORDER)
1528            {
1529                pTileInfo->tileSplitBytes = tileSplitC;
1530            }
1531            else
1532            {
1533                pTileInfo->tileSplitBytes = m_tileTable[tileIndex].info.tileSplitBytes;
1534            }
1535        }
1536
1537        if (NULL != pTileMode)
1538        {
1539            *pTileMode = tileMode;
1540        }
1541
1542        if (NULL != pTileType)
1543        {
1544            *pTileType = tileType;
1545        }
1546    }
1547
1548    return macroModeIndex;
1549}
1550
1551/**
1552***************************************************************************************************
1553*   CIAddrLib::HwlComputeTileDataWidthAndHeightLinear
1554*
1555*   @brief
1556*       Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1557*
1558*   @return
1559*       N/A
1560*
1561*   @note
1562*       MacroWidth and macroHeight are measured in pixels
1563***************************************************************************************************
1564*/
1565VOID CIAddrLib::HwlComputeTileDataWidthAndHeightLinear(
1566    UINT_32*        pMacroWidth,     ///< [out] macro tile width
1567    UINT_32*        pMacroHeight,    ///< [out] macro tile height
1568    UINT_32         bpp,             ///< [in] bits per pixel
1569    ADDR_TILEINFO*  pTileInfo        ///< [in] tile info
1570    ) const
1571{
1572    ADDR_ASSERT(pTileInfo != NULL);
1573
1574    UINT_32 numTiles;
1575
1576    switch (pTileInfo->pipeConfig)
1577    {
1578        case ADDR_PIPECFG_P16_32x32_8x16:
1579        case ADDR_PIPECFG_P16_32x32_16x16:
1580        case ADDR_PIPECFG_P8_32x64_32x32:
1581        case ADDR_PIPECFG_P8_32x32_16x32:
1582        case ADDR_PIPECFG_P8_32x32_16x16:
1583        case ADDR_PIPECFG_P8_32x32_8x16:
1584        case ADDR_PIPECFG_P4_32x32:
1585            numTiles = 8;
1586            break;
1587        default:
1588            numTiles = 4;
1589            break;
1590    }
1591
1592    *pMacroWidth    = numTiles * MicroTileWidth;
1593    *pMacroHeight   = numTiles * MicroTileHeight;
1594}
1595
1596/**
1597***************************************************************************************************
1598*   CIAddrLib::HwlStereoCheckRightOffsetPadding
1599*
1600*   @brief
1601*       check if the height needs extra padding for stereo right eye offset, to avoid swizzling
1602*
1603*   @return
1604*       TRUE is the extra padding is needed
1605*
1606*   @note
1607*       Kalindi (Kabini) is the only one that needs this padding as there is a uncertain
1608*       possible HW issue where the right eye displays incorrectly with some type of swizzles, if
1609*       the right eye offset is not 64KB aligned - EPR#366461
1610*       Other Kaveri APUs also need the padding according to DXX team's report otherwise
1611*       corruption observed. - EPR#374788
1612***************************************************************************************************
1613*/
1614BOOL_32 CIAddrLib::HwlStereoCheckRightOffsetPadding() const
1615{
1616    BOOL_32 bNeedPadding = FALSE;
1617
1618    if (m_settings.isKaveri)
1619    {
1620        bNeedPadding = TRUE;
1621    }
1622
1623    return bNeedPadding;
1624}
1625
1626/**
1627***************************************************************************************************
1628*   CIAddrLib::HwlComputeMetadataNibbleAddress
1629*
1630*   @brief
1631*        calculate meta data address based on input information
1632*
1633*   &parameter
1634*        uncompressedDataByteAddress - address of a pixel in color surface
1635*        dataBaseByteAddress         - base address of color surface
1636*        metadataBaseByteAddress     - base address of meta ram
1637*        metadataBitSize             - meta key size, 8 for DCC, 4 for cmask
1638*        elementBitSize              - element size of color surface
1639*        blockByteSize               - compression block size, 256 for DCC
1640*        pipeInterleaveBytes         - pipe interleave size
1641*        numOfPipes                  - number of pipes
1642*        numOfBanks                  - number of banks
1643*        numOfSamplesPerSplit        - number of samples per tile split
1644*   @return
1645*        meta data nibble address (nibble address is used to support DCC compatible cmask)
1646*
1647***************************************************************************************************
1648*/
1649UINT_64 CIAddrLib::HwlComputeMetadataNibbleAddress(
1650    UINT_64 uncompressedDataByteAddress,
1651    UINT_64 dataBaseByteAddress,
1652    UINT_64 metadataBaseByteAddress,
1653    UINT_32 metadataBitSize,
1654    UINT_32 elementBitSize,
1655    UINT_32 blockByteSize,
1656    UINT_32 pipeInterleaveBytes,
1657    UINT_32 numOfPipes,
1658    UINT_32 numOfBanks,
1659    UINT_32 numOfSamplesPerSplit) const
1660{
1661    ///--------------------------------------------------------------------------------------------
1662    /// Get pipe interleave, bank and pipe bits
1663    ///--------------------------------------------------------------------------------------------
1664    UINT_32 pipeInterleaveBits  = Log2(pipeInterleaveBytes);
1665    UINT_32 pipeBits            = Log2(numOfPipes);
1666    UINT_32 bankBits            = Log2(numOfBanks);
1667
1668    ///--------------------------------------------------------------------------------------------
1669    /// Clear pipe and bank swizzles
1670    ///--------------------------------------------------------------------------------------------
1671    UINT_32 dataMacrotileBits        = pipeInterleaveBits + pipeBits + bankBits;
1672    UINT_32 metadataMacrotileBits    = pipeInterleaveBits + pipeBits + bankBits;
1673
1674    UINT_64 dataMacrotileClearMask     = ~((1L << dataMacrotileBits) - 1);
1675    UINT_64 metadataMacrotileClearMask = ~((1L << metadataMacrotileBits) - 1);
1676
1677    UINT_64 dataBaseByteAddressNoSwizzle = dataBaseByteAddress & dataMacrotileClearMask;
1678    UINT_64 metadataBaseByteAddressNoSwizzle = metadataBaseByteAddress & metadataMacrotileClearMask;
1679
1680    ///--------------------------------------------------------------------------------------------
1681    /// Modify metadata base before adding in so that when final address is divided by data ratio,
1682    /// the base address returns to where it should be
1683    ///--------------------------------------------------------------------------------------------
1684    ADDR_ASSERT((0 != metadataBitSize));
1685    UINT_64 metadataBaseShifted = metadataBaseByteAddressNoSwizzle * blockByteSize * 8 /
1686                                  metadataBitSize;
1687    UINT_64 offset = uncompressedDataByteAddress -
1688                     dataBaseByteAddressNoSwizzle +
1689                     metadataBaseShifted;
1690
1691    ///--------------------------------------------------------------------------------------------
1692    /// Save bank data bits
1693    ///--------------------------------------------------------------------------------------------
1694    UINT_32 lsb = pipeBits + pipeInterleaveBits;
1695    UINT_32 msb = bankBits - 1 + lsb;
1696
1697    UINT_64 bankDataBits = AddrGetBits(offset, msb, lsb);
1698
1699    ///--------------------------------------------------------------------------------------------
1700    /// Save pipe data bits
1701    ///--------------------------------------------------------------------------------------------
1702    lsb = pipeInterleaveBits;
1703    msb = pipeBits - 1 + lsb;
1704
1705    UINT_64 pipeDataBits = AddrGetBits(offset, msb, lsb);
1706
1707    ///--------------------------------------------------------------------------------------------
1708    /// Remove pipe and bank bits
1709    ///--------------------------------------------------------------------------------------------
1710    lsb = pipeInterleaveBits;
1711    msb = dataMacrotileBits - 1;
1712
1713    UINT_64 offsetWithoutPipeBankBits = AddrRemoveBits(offset, msb, lsb);
1714
1715    ADDR_ASSERT((0 != blockByteSize));
1716    UINT_64 blockInBankpipe = offsetWithoutPipeBankBits / blockByteSize;
1717
1718    UINT_32 tileSize = 8 * 8 * elementBitSize/8 * numOfSamplesPerSplit;
1719    UINT_32 blocksInTile = tileSize / blockByteSize;
1720
1721    if (0 == blocksInTile)
1722    {
1723        lsb = 0;
1724    }
1725    else
1726    {
1727        lsb = Log2(blocksInTile);
1728    }
1729    msb = bankBits - 1 + lsb;
1730
1731    UINT_64 blockInBankpipeWithBankBits = AddrInsertBits(blockInBankpipe, bankDataBits, msb, lsb);
1732
1733    /// NOTE *2 because we are converting to Nibble address in this step
1734    UINT_64 metaAddressInPipe = blockInBankpipeWithBankBits * 2 * metadataBitSize / 8;
1735
1736
1737    ///--------------------------------------------------------------------------------------------
1738    /// Reinsert pipe bits back into the final address
1739    ///--------------------------------------------------------------------------------------------
1740    lsb = pipeInterleaveBits + 1; ///<+1 due to Nibble address now gives interleave bits extra lsb.
1741    msb = pipeBits - 1 + lsb;
1742    UINT_64 metadataAddress = AddrInsertBits(metaAddressInPipe, pipeDataBits, msb, lsb);
1743
1744    return metadataAddress;
1745}
1746
1747/**
1748***************************************************************************************************
1749*   CIAddrLib::HwlPadDimensions
1750*
1751*   @brief
1752*       Helper function to pad dimensions
1753*
1754*   @return
1755*       N/A
1756*
1757***************************************************************************************************
1758*/
1759VOID CIAddrLib::HwlPadDimensions(
1760    AddrTileMode        tileMode,    ///< [in] tile mode
1761    UINT_32             bpp,         ///< [in] bits per pixel
1762    ADDR_SURFACE_FLAGS  flags,       ///< [in] surface flags
1763    UINT_32             numSamples,  ///< [in] number of samples
1764    ADDR_TILEINFO*      pTileInfo,   ///< [in/out] bank structure.
1765    UINT_32             padDims,     ///< [in] Dimensions to pad valid value 1,2,3
1766    UINT_32             mipLevel,    ///< [in] MipLevel
1767    UINT_32*            pPitch,      ///< [in/out] pitch in pixels
1768    UINT_32             pitchAlign,  ///< [in] pitch alignment
1769    UINT_32*            pHeight,     ///< [in/out] height in pixels
1770    UINT_32             heightAlign, ///< [in] height alignment
1771    UINT_32*            pSlices,     ///< [in/out] number of slices
1772    UINT_32             sliceAlign   ///< [in] number of slice alignment
1773    ) const
1774{
1775    if (m_settings.isVolcanicIslands &&
1776        flags.dccCompatible &&
1777        (numSamples > 1) &&
1778        (mipLevel == 0) &&
1779        IsMacroTiled(tileMode))
1780    {
1781        UINT_32 tileSizePerSample = BITS_TO_BYTES(bpp * MicroTileWidth * MicroTileHeight);
1782        UINT_32 samplesPerSplit  = pTileInfo->tileSplitBytes / tileSizePerSample;
1783
1784        if (samplesPerSplit < numSamples)
1785        {
1786            UINT_32 dccFastClearByteAlign = HwlGetPipes(pTileInfo) * m_pipeInterleaveBytes * 256;
1787            UINT_32 bytesPerSplit = BITS_TO_BYTES((*pPitch) * (*pHeight) * bpp * samplesPerSplit);
1788
1789            ADDR_ASSERT(IsPow2(dccFastClearByteAlign));
1790
1791            if (0 != (bytesPerSplit & (dccFastClearByteAlign - 1)))
1792            {
1793                UINT_32 dccFastClearPixelAlign = dccFastClearByteAlign /
1794                                                BITS_TO_BYTES(bpp) /
1795                                                samplesPerSplit;
1796                UINT_32 macroTilePixelAlign = pitchAlign * heightAlign;
1797
1798                if ((dccFastClearPixelAlign >= macroTilePixelAlign) &&
1799                    ((dccFastClearPixelAlign % macroTilePixelAlign) == 0))
1800                {
1801                    UINT_32 dccFastClearPitchAlignInMacroTile =
1802                        dccFastClearPixelAlign / macroTilePixelAlign;
1803                    UINT_32 heightInMacroTile = *pHeight / heightAlign;
1804                    UINT_32 dccFastClearPitchAlignInPixels;
1805
1806                    while ((heightInMacroTile > 1) &&
1807                           ((heightInMacroTile % 2) == 0) &&
1808                           (dccFastClearPitchAlignInMacroTile > 1) &&
1809                           ((dccFastClearPitchAlignInMacroTile % 2) == 0))
1810                    {
1811                        heightInMacroTile >>= 1;
1812                        dccFastClearPitchAlignInMacroTile >>= 1;
1813                    }
1814
1815                    dccFastClearPitchAlignInPixels = pitchAlign * dccFastClearPitchAlignInMacroTile;
1816
1817                    if (IsPow2(dccFastClearPitchAlignInPixels))
1818                    {
1819                        *pPitch = PowTwoAlign((*pPitch), dccFastClearPitchAlignInPixels);
1820                    }
1821                    else
1822                    {
1823                        *pPitch += (dccFastClearPitchAlignInPixels - 1);
1824                        *pPitch /= dccFastClearPitchAlignInPixels;
1825                        *pPitch *= dccFastClearPitchAlignInPixels;
1826                    }
1827                }
1828            }
1829        }
1830    }
1831}
1832
1833