1 /*
2  * Copyright © 2007-2019 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 CiLib class.
31 ****************************************************************************************************
32 */
33 
34 #include "ciaddrlib.h"
35 
36 #include "si_gb_reg.h"
37 
38 #include "amdgpu_asic_addr.h"
39 
40 ////////////////////////////////////////////////////////////////////////////////////////////////////
41 ////////////////////////////////////////////////////////////////////////////////////////////////////
42 
43 namespace Addr
44 {
45 
46 /**
47 ****************************************************************************************************
48 *   CiHwlInit
49 *
50 *   @brief
51 *       Creates an CiLib object.
52 *
53 *   @return
54 *       Returns an CiLib object pointer.
55 ****************************************************************************************************
56 */
CiHwlInit(const Client * pClient)57 Lib* CiHwlInit(const Client* pClient)
58 {
59     return V1::CiLib::CreateObj(pClient);
60 }
61 
62 namespace V1
63 {
64 
65 /**
66 ****************************************************************************************************
67 *   Mask
68 *
69 *   @brief
70 *       Gets a mask of "width"
71 *   @return
72 *       Bit mask
73 ****************************************************************************************************
74 */
Mask(UINT_32 width)75 static UINT_64 Mask(
76     UINT_32 width)  ///< Width of bits
77 {
78     UINT_64 ret;
79 
80     if (width >= sizeof(UINT_64)*8)
81     {
82         ret = ~((UINT_64) 0);
83     }
84     else
85     {
86         return (((UINT_64) 1) << width) - 1;
87     }
88     return ret;
89 }
90 
91 /**
92 ****************************************************************************************************
93 *   GetBits
94 *
95 *   @brief
96 *       Gets bits within a range of [msb, lsb]
97 *   @return
98 *       Bits of this range
99 ****************************************************************************************************
100 */
GetBits(UINT_64 bits,UINT_32 msb,UINT_32 lsb)101 static UINT_64 GetBits(
102     UINT_64 bits,   ///< Source bits
103     UINT_32 msb,    ///< Most signicant bit
104     UINT_32 lsb)    ///< Least signicant bit
105 {
106     UINT_64 ret = 0;
107 
108     if (msb >= lsb)
109     {
110         ret = (bits >> lsb) & (Mask(1 + msb - lsb));
111     }
112     return ret;
113 }
114 
115 /**
116 ****************************************************************************************************
117 *   RemoveBits
118 *
119 *   @brief
120 *       Removes bits within the range of [msb, lsb]
121 *   @return
122 *       Modified bits
123 ****************************************************************************************************
124 */
RemoveBits(UINT_64 bits,UINT_32 msb,UINT_32 lsb)125 static UINT_64 RemoveBits(
126     UINT_64 bits,   ///< Source bits
127     UINT_32 msb,    ///< Most signicant bit
128     UINT_32 lsb)    ///< Least signicant bit
129 {
130     UINT_64 ret = bits;
131 
132     if (msb >= lsb)
133     {
134         ret = GetBits(bits, lsb - 1, 0) // low bits
135             | (GetBits(bits, 8 * sizeof(bits) - 1, msb + 1) << lsb); //high bits
136     }
137     return ret;
138 }
139 
140 /**
141 ****************************************************************************************************
142 *   InsertBits
143 *
144 *   @brief
145 *       Inserts new bits into the range of [msb, lsb]
146 *   @return
147 *       Modified bits
148 ****************************************************************************************************
149 */
InsertBits(UINT_64 bits,UINT_64 newBits,UINT_32 msb,UINT_32 lsb)150 static UINT_64 InsertBits(
151     UINT_64 bits,       ///< Source bits
152     UINT_64 newBits,    ///< New bits to be inserted
153     UINT_32 msb,        ///< Most signicant bit
154     UINT_32 lsb)        ///< Least signicant bit
155 {
156     UINT_64 ret = bits;
157 
158     if (msb >= lsb)
159     {
160         ret = GetBits(bits, lsb - 1, 0) // old low bitss
161              | (GetBits(newBits, msb - lsb, 0) << lsb) //new bits
162              | (GetBits(bits, 8 * sizeof(bits) - 1, lsb) << (msb + 1)); //old high bits
163     }
164     return ret;
165 }
166 
167 /**
168 ****************************************************************************************************
169 *   CiLib::CiLib
170 *
171 *   @brief
172 *       Constructor
173 *
174 ****************************************************************************************************
175 */
CiLib(const Client * pClient)176 CiLib::CiLib(const Client* pClient)
177     :
178     SiLib(pClient),
179     m_noOfMacroEntries(0),
180     m_allowNonDispThickModes(FALSE)
181 {
182 }
183 
184 /**
185 ****************************************************************************************************
186 *   CiLib::~CiLib
187 *
188 *   @brief
189 *       Destructor
190 ****************************************************************************************************
191 */
~CiLib()192 CiLib::~CiLib()
193 {
194 }
195 
196 /**
197 ****************************************************************************************************
198 *   CiLib::HwlComputeDccInfo
199 *
200 *   @brief
201 *       Compute DCC key size, base alignment
202 *   @return
203 *       ADDR_E_RETURNCODE
204 ****************************************************************************************************
205 */
HwlComputeDccInfo(const ADDR_COMPUTE_DCCINFO_INPUT * pIn,ADDR_COMPUTE_DCCINFO_OUTPUT * pOut) const206 ADDR_E_RETURNCODE CiLib::HwlComputeDccInfo(
207     const ADDR_COMPUTE_DCCINFO_INPUT*  pIn,
208     ADDR_COMPUTE_DCCINFO_OUTPUT*       pOut) const
209 {
210     ADDR_E_RETURNCODE returnCode = ADDR_OK;
211 
212     if (SupportDccAndTcCompatibility() && IsMacroTiled(pIn->tileMode))
213     {
214         UINT_64 dccFastClearSize = pIn->colorSurfSize >> 8;
215 
216         ADDR_ASSERT(0 == (pIn->colorSurfSize & 0xff));
217 
218         if (pIn->numSamples > 1)
219         {
220             UINT_32 tileSizePerSample = BITS_TO_BYTES(pIn->bpp * MicroTileWidth * MicroTileHeight);
221             UINT_32 samplesPerSplit  = pIn->tileInfo.tileSplitBytes / tileSizePerSample;
222 
223             if (samplesPerSplit < pIn->numSamples)
224             {
225                 UINT_32 numSplits = pIn->numSamples / samplesPerSplit;
226                 UINT_32 fastClearBaseAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes;
227 
228                 ADDR_ASSERT(IsPow2(fastClearBaseAlign));
229 
230                 dccFastClearSize /= numSplits;
231 
232                 if (0 != (dccFastClearSize & (fastClearBaseAlign - 1)))
233                 {
234                     // Disable dcc fast clear
235                     // if key size of fisrt sample split is not pipe*interleave aligned
236                     dccFastClearSize = 0;
237                 }
238             }
239         }
240 
241         pOut->dccRamSize          = pIn->colorSurfSize >> 8;
242         pOut->dccRamBaseAlign     = pIn->tileInfo.banks *
243                                     HwlGetPipes(&pIn->tileInfo) *
244                                     m_pipeInterleaveBytes;
245         pOut->dccFastClearSize    = dccFastClearSize;
246         pOut->dccRamSizeAligned   = TRUE;
247 
248         ADDR_ASSERT(IsPow2(pOut->dccRamBaseAlign));
249 
250         if (0 == (pOut->dccRamSize & (pOut->dccRamBaseAlign - 1)))
251         {
252             pOut->subLvlCompressible = TRUE;
253         }
254         else
255         {
256             UINT_64 dccRamSizeAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes;
257 
258             if (pOut->dccRamSize == pOut->dccFastClearSize)
259             {
260                 pOut->dccFastClearSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign);
261             }
262             if ((pOut->dccRamSize & (dccRamSizeAlign - 1)) != 0)
263             {
264                 pOut->dccRamSizeAligned = FALSE;
265             }
266             pOut->dccRamSize          = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign);
267             pOut->subLvlCompressible  = FALSE;
268         }
269     }
270     else
271     {
272         returnCode = ADDR_NOTSUPPORTED;
273     }
274 
275     return returnCode;
276 }
277 
278 /**
279 ****************************************************************************************************
280 *   CiLib::HwlComputeCmaskAddrFromCoord
281 *
282 *   @brief
283 *       Compute tc compatible Cmask address from fmask ram address
284 *
285 *   @return
286 *       ADDR_E_RETURNCODE
287 ****************************************************************************************************
288 */
HwlComputeCmaskAddrFromCoord(const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT * pOut) const289 ADDR_E_RETURNCODE CiLib::HwlComputeCmaskAddrFromCoord(
290     const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT*  pIn,  ///< [in] fmask addr/bpp/tile input
291     ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT*       pOut  ///< [out] cmask address
292     ) const
293 {
294     ADDR_E_RETURNCODE returnCode = ADDR_NOTSUPPORTED;
295 
296     if ((SupportDccAndTcCompatibility() == TRUE) &&
297         (pIn->flags.tcCompatible == TRUE))
298     {
299         UINT_32 numOfPipes   = HwlGetPipes(pIn->pTileInfo);
300         UINT_32 numOfBanks   = pIn->pTileInfo->banks;
301         UINT_64 fmaskAddress = pIn->fmaskAddr;
302         UINT_32 elemBits     = pIn->bpp;
303         UINT_32 blockByte    = 64 * elemBits / 8;
304         UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(fmaskAddress,
305                                                                     0,
306                                                                     0,
307                                                                     4,   // cmask 4 bits
308                                                                     elemBits,
309                                                                     blockByte,
310                                                                     m_pipeInterleaveBytes,
311                                                                     numOfPipes,
312                                                                     numOfBanks,
313                                                                     1);
314         pOut->addr = (metaNibbleAddress >> 1);
315         pOut->bitPosition = (metaNibbleAddress % 2) ? 4 : 0;
316         returnCode = ADDR_OK;
317     }
318 
319     return returnCode;
320 }
321 
322 /**
323 ****************************************************************************************************
324 *   CiLib::HwlComputeHtileAddrFromCoord
325 *
326 *   @brief
327 *       Compute tc compatible Htile address from depth/stencil address
328 *
329 *   @return
330 *       ADDR_E_RETURNCODE
331 ****************************************************************************************************
332 */
HwlComputeHtileAddrFromCoord(const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT * pOut) const333 ADDR_E_RETURNCODE CiLib::HwlComputeHtileAddrFromCoord(
334     const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT*  pIn,  ///< [in] depth/stencil addr/bpp/tile input
335     ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT*       pOut  ///< [out] htile address
336     ) const
337 {
338     ADDR_E_RETURNCODE returnCode = ADDR_NOTSUPPORTED;
339 
340     if ((SupportDccAndTcCompatibility() == TRUE) &&
341         (pIn->flags.tcCompatible == TRUE))
342     {
343         UINT_32 numOfPipes   = HwlGetPipes(pIn->pTileInfo);
344         UINT_32 numOfBanks   = pIn->pTileInfo->banks;
345         UINT_64 zStencilAddr = pIn->zStencilAddr;
346         UINT_32 elemBits     = pIn->bpp;
347         UINT_32 blockByte    = 64 * elemBits / 8;
348         UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(zStencilAddr,
349                                                                     0,
350                                                                     0,
351                                                                     32,  // htile 32 bits
352                                                                     elemBits,
353                                                                     blockByte,
354                                                                     m_pipeInterleaveBytes,
355                                                                     numOfPipes,
356                                                                     numOfBanks,
357                                                                     1);
358         pOut->addr = (metaNibbleAddress >> 1);
359         pOut->bitPosition = 0;
360         returnCode = ADDR_OK;
361     }
362 
363     return returnCode;
364 }
365 
366 /**
367 ****************************************************************************************************
368 *   CiLib::HwlConvertChipFamily
369 *
370 *   @brief
371 *       Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
372 *   @return
373 *       ChipFamily
374 ****************************************************************************************************
375 */
HwlConvertChipFamily(UINT_32 uChipFamily,UINT_32 uChipRevision)376 ChipFamily CiLib::HwlConvertChipFamily(
377     UINT_32 uChipFamily,        ///< [in] chip family defined in atiih.h
378     UINT_32 uChipRevision)      ///< [in] chip revision defined in "asic_family"_id.h
379 {
380     ChipFamily family = ADDR_CHIP_FAMILY_CI;
381 
382     switch (uChipFamily)
383     {
384         case FAMILY_CI:
385             m_settings.isSeaIsland  = 1;
386             m_settings.isBonaire    = ASICREV_IS_BONAIRE_M(uChipRevision);
387             m_settings.isHawaii     = ASICREV_IS_HAWAII_P(uChipRevision);
388             break;
389         case FAMILY_KV:
390             m_settings.isKaveri     = 1;
391             m_settings.isSpectre    = ASICREV_IS_SPECTRE(uChipRevision);
392             m_settings.isSpooky     = ASICREV_IS_SPOOKY(uChipRevision);
393             m_settings.isKalindi    = ASICREV_IS_KALINDI(uChipRevision);
394             break;
395         case FAMILY_VI:
396             m_settings.isVolcanicIslands = 1;
397             m_settings.isIceland         = ASICREV_IS_ICELAND_M(uChipRevision);
398             m_settings.isTonga           = ASICREV_IS_TONGA_P(uChipRevision);
399             m_settings.isFiji            = ASICREV_IS_FIJI_P(uChipRevision);
400             m_settings.isPolaris10       = ASICREV_IS_POLARIS10_P(uChipRevision);
401             m_settings.isPolaris11       = ASICREV_IS_POLARIS11_M(uChipRevision);
402             m_settings.isPolaris12       = ASICREV_IS_POLARIS12_V(uChipRevision);
403             m_settings.isVegaM           = ASICREV_IS_VEGAM_P(uChipRevision);
404             family = ADDR_CHIP_FAMILY_VI;
405             break;
406         case FAMILY_CZ:
407             m_settings.isCarrizo         = 1;
408             m_settings.isVolcanicIslands = 1;
409             family = ADDR_CHIP_FAMILY_VI;
410             break;
411         default:
412             ADDR_ASSERT(!"No Chip found");
413             break;
414     }
415 
416     return family;
417 }
418 
419 /**
420 ****************************************************************************************************
421 *   CiLib::HwlInitGlobalParams
422 *
423 *   @brief
424 *       Initializes global parameters
425 *
426 *   @return
427 *       TRUE if all settings are valid
428 *
429 ****************************************************************************************************
430 */
HwlInitGlobalParams(const ADDR_CREATE_INPUT * pCreateIn)431 BOOL_32 CiLib::HwlInitGlobalParams(
432     const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input
433 {
434     BOOL_32  valid = TRUE;
435 
436     const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue;
437 
438     valid = DecodeGbRegs(pRegValue);
439 
440     // The following assignments for m_pipes is only for fail-safe, InitTileSettingTable should
441     // read the correct pipes from tile mode table
442     if (m_settings.isHawaii)
443     {
444         m_pipes = 16;
445     }
446     else if (m_settings.isBonaire || m_settings.isSpectre)
447     {
448         m_pipes = 4;
449     }
450     else // Treat other KV asics to be 2-pipe
451     {
452         m_pipes = 2;
453     }
454 
455     // @todo: VI
456     // Move this to VI code path once created
457     if (m_settings.isTonga || m_settings.isPolaris10)
458     {
459         m_pipes = 8;
460     }
461     else if (m_settings.isIceland)
462     {
463         m_pipes = 2;
464     }
465     else if (m_settings.isFiji)
466     {
467         m_pipes = 16;
468     }
469     else if (m_settings.isPolaris11 || m_settings.isPolaris12)
470     {
471         m_pipes = 4;
472     }
473     else if (m_settings.isVegaM)
474     {
475         m_pipes = 16;
476     }
477 
478     if (valid)
479     {
480         valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
481     }
482     if (valid)
483     {
484         valid = InitMacroTileCfgTable(pRegValue->pMacroTileConfig, pRegValue->noOfMacroEntries);
485     }
486 
487     if (valid)
488     {
489         InitEquationTable();
490     }
491 
492     return valid;
493 }
494 
495 /**
496 ****************************************************************************************************
497 *   CiLib::HwlPostCheckTileIndex
498 *
499 *   @brief
500 *       Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
501 *       tile mode/type/info and change the index if needed
502 *   @return
503 *       Tile index.
504 ****************************************************************************************************
505 */
HwlPostCheckTileIndex(const ADDR_TILEINFO * pInfo,AddrTileMode mode,AddrTileType type,INT curIndex) const506 INT_32 CiLib::HwlPostCheckTileIndex(
507     const ADDR_TILEINFO* pInfo,     ///< [in] Tile Info
508     AddrTileMode         mode,      ///< [in] Tile mode
509     AddrTileType         type,      ///< [in] Tile type
510     INT                  curIndex   ///< [in] Current index assigned in HwlSetupTileInfo
511     ) const
512 {
513     INT_32 index = curIndex;
514 
515     if (mode == ADDR_TM_LINEAR_GENERAL)
516     {
517         index = TileIndexLinearGeneral;
518     }
519     else
520     {
521         BOOL_32 macroTiled = IsMacroTiled(mode);
522 
523         // We need to find a new index if either of them is true
524         // 1. curIndex is invalid
525         // 2. tile mode is changed
526         // 3. tile info does not match for macro tiled
527         if ((index == TileIndexInvalid)         ||
528             (mode != m_tileTable[index].mode)   ||
529             (macroTiled && pInfo->pipeConfig != m_tileTable[index].info.pipeConfig))
530         {
531             for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
532             {
533                 if (macroTiled)
534                 {
535                     // macro tile modes need all to match
536                     if ((pInfo->pipeConfig == m_tileTable[index].info.pipeConfig) &&
537                         (mode == m_tileTable[index].mode) &&
538                         (type == m_tileTable[index].type))
539                     {
540                         // tileSplitBytes stored in m_tileTable is only valid for depth entries
541                         if (type == ADDR_DEPTH_SAMPLE_ORDER)
542                         {
543                             if (Min(m_tileTable[index].info.tileSplitBytes,
544                                     m_rowSize) == pInfo->tileSplitBytes)
545                             {
546                                 break;
547                             }
548                         }
549                         else // other entries are determined by other 3 fields
550                         {
551                             break;
552                         }
553                     }
554                 }
555                 else if (mode == ADDR_TM_LINEAR_ALIGNED)
556                 {
557                     // linear mode only needs tile mode to match
558                     if (mode == m_tileTable[index].mode)
559                     {
560                         break;
561                     }
562                 }
563                 else
564                 {
565                     // micro tile modes only need tile mode and tile type to match
566                     if (mode == m_tileTable[index].mode &&
567                         type == m_tileTable[index].type)
568                     {
569                         break;
570                     }
571                 }
572             }
573         }
574     }
575 
576     ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
577 
578     if (index >= static_cast<INT_32>(m_noOfEntries))
579     {
580         index = TileIndexInvalid;
581     }
582 
583     return index;
584 }
585 
586 /**
587 ****************************************************************************************************
588 *   CiLib::HwlSetupTileCfg
589 *
590 *   @brief
591 *       Map tile index to tile setting.
592 *   @return
593 *       ADDR_E_RETURNCODE
594 ****************************************************************************************************
595 */
HwlSetupTileCfg(UINT_32 bpp,INT_32 index,INT_32 macroModeIndex,ADDR_TILEINFO * pInfo,AddrTileMode * pMode,AddrTileType * pType) const596 ADDR_E_RETURNCODE CiLib::HwlSetupTileCfg(
597     UINT_32         bpp,            ///< Bits per pixel
598     INT_32          index,          ///< Tile index
599     INT_32          macroModeIndex, ///< Index in macro tile mode table(CI)
600     ADDR_TILEINFO*  pInfo,          ///< [out] Tile Info
601     AddrTileMode*   pMode,          ///< [out] Tile mode
602     AddrTileType*   pType           ///< [out] Tile type
603     ) const
604 {
605     ADDR_E_RETURNCODE returnCode = ADDR_OK;
606 
607     // Global flag to control usage of tileIndex
608     if (UseTileIndex(index))
609     {
610         if (index == TileIndexLinearGeneral)
611         {
612             pInfo->banks = 2;
613             pInfo->bankWidth = 1;
614             pInfo->bankHeight = 1;
615             pInfo->macroAspectRatio = 1;
616             pInfo->tileSplitBytes = 64;
617             pInfo->pipeConfig = ADDR_PIPECFG_P2;
618         }
619         else if (static_cast<UINT_32>(index) >= m_noOfEntries)
620         {
621             returnCode = ADDR_INVALIDPARAMS;
622         }
623         else
624         {
625             const TileConfig* pCfgTable = GetTileSetting(index);
626 
627             if (pInfo != NULL)
628             {
629                 if (IsMacroTiled(pCfgTable->mode))
630                 {
631                     ADDR_ASSERT((macroModeIndex != TileIndexInvalid) &&
632                                 (macroModeIndex != TileIndexNoMacroIndex));
633 
634                     UINT_32 tileSplit;
635 
636                     *pInfo = m_macroTileTable[macroModeIndex];
637 
638                     if (pCfgTable->type == ADDR_DEPTH_SAMPLE_ORDER)
639                     {
640                         tileSplit = pCfgTable->info.tileSplitBytes;
641                     }
642                     else
643                     {
644                         if (bpp > 0)
645                         {
646                             UINT_32 thickness = Thickness(pCfgTable->mode);
647                             UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
648                             // Non-depth entries store a split factor
649                             UINT_32 sampleSplit = m_tileTable[index].info.tileSplitBytes;
650                             tileSplit = Max(256u, sampleSplit * tileBytes1x);
651                         }
652                         else
653                         {
654                             // Return tileBytes instead if not enough info
655                             tileSplit = pInfo->tileSplitBytes;
656                         }
657                     }
658 
659                     // Clamp to row_size
660                     pInfo->tileSplitBytes = Min(m_rowSize, tileSplit);
661 
662                     pInfo->pipeConfig = pCfgTable->info.pipeConfig;
663                 }
664                 else // 1D and linear modes, we return default value stored in table
665                 {
666                     *pInfo = pCfgTable->info;
667                 }
668             }
669 
670             if (pMode != NULL)
671             {
672                 *pMode = pCfgTable->mode;
673             }
674 
675             if (pType != NULL)
676             {
677                 *pType = pCfgTable->type;
678             }
679         }
680     }
681 
682     return returnCode;
683 }
684 
685 /**
686 ****************************************************************************************************
687 *   CiLib::HwlComputeSurfaceInfo
688 *
689 *   @brief
690 *       Entry of CI's ComputeSurfaceInfo
691 *   @return
692 *       ADDR_E_RETURNCODE
693 ****************************************************************************************************
694 */
HwlComputeSurfaceInfo(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const695 ADDR_E_RETURNCODE CiLib::HwlComputeSurfaceInfo(
696     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,    ///< [in] input structure
697     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [out] output structure
698     ) const
699 {
700     // If tileIndex is invalid, force macroModeIndex to be invalid, too
701     if (pIn->tileIndex == TileIndexInvalid)
702     {
703         pOut->macroModeIndex = TileIndexInvalid;
704     }
705 
706     ADDR_E_RETURNCODE retCode = SiLib::HwlComputeSurfaceInfo(pIn, pOut);
707 
708     if ((pIn->mipLevel > 0) &&
709         (pOut->tcCompatible == TRUE) &&
710         (pOut->tileMode != pIn->tileMode) &&
711         (SupportDccAndTcCompatibility() == TRUE))
712     {
713         pOut->tcCompatible = CheckTcCompatibility(pOut->pTileInfo, pIn->bpp, pOut->tileMode, pOut->tileType, pOut);
714     }
715 
716     if (pOut->macroModeIndex == TileIndexNoMacroIndex)
717     {
718         pOut->macroModeIndex = TileIndexInvalid;
719     }
720 
721     if ((pIn->flags.matchStencilTileCfg == TRUE) &&
722         (pIn->flags.depth == TRUE))
723     {
724         pOut->stencilTileIdx = TileIndexInvalid;
725 
726         if ((MinDepth2DThinIndex <= pOut->tileIndex) &&
727             (MaxDepth2DThinIndex >= pOut->tileIndex))
728         {
729             BOOL_32 depthStencil2DTileConfigMatch = DepthStencilTileCfgMatch(pIn, pOut);
730 
731             if ((depthStencil2DTileConfigMatch == FALSE) &&
732                 (pOut->tcCompatible == TRUE))
733             {
734                 pOut->macroModeIndex = TileIndexInvalid;
735 
736                 ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
737                 localIn.tileIndex = TileIndexInvalid;
738                 localIn.pTileInfo = NULL;
739                 localIn.flags.tcCompatible = FALSE;
740 
741                 SiLib::HwlComputeSurfaceInfo(&localIn, pOut);
742 
743                 ADDR_ASSERT((MinDepth2DThinIndex <= pOut->tileIndex) && (MaxDepth2DThinIndex >= pOut->tileIndex));
744 
745                 depthStencil2DTileConfigMatch = DepthStencilTileCfgMatch(pIn, pOut);
746             }
747 
748             if ((depthStencil2DTileConfigMatch == FALSE) &&
749                 (pIn->numSamples <= 1))
750             {
751                 pOut->macroModeIndex = TileIndexInvalid;
752 
753                 ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
754                 localIn.tileMode = ADDR_TM_1D_TILED_THIN1;
755                 localIn.tileIndex = TileIndexInvalid;
756                 localIn.pTileInfo = NULL;
757 
758                 retCode = SiLib::HwlComputeSurfaceInfo(&localIn, pOut);
759             }
760         }
761 
762         if (pOut->tileIndex == Depth1DThinIndex)
763         {
764             pOut->stencilTileIdx = Depth1DThinIndex;
765         }
766     }
767 
768     return retCode;
769 }
770 
771 /**
772 ****************************************************************************************************
773 *   CiLib::HwlFmaskSurfaceInfo
774 *   @brief
775 *       Entry of r800's ComputeFmaskInfo
776 *   @return
777 *       ADDR_E_RETURNCODE
778 ****************************************************************************************************
779 */
HwlComputeFmaskInfo(const ADDR_COMPUTE_FMASK_INFO_INPUT * pIn,ADDR_COMPUTE_FMASK_INFO_OUTPUT * pOut)780 ADDR_E_RETURNCODE CiLib::HwlComputeFmaskInfo(
781     const ADDR_COMPUTE_FMASK_INFO_INPUT*    pIn,   ///< [in] input structure
782     ADDR_COMPUTE_FMASK_INFO_OUTPUT*         pOut   ///< [out] output structure
783     )
784 {
785     ADDR_E_RETURNCODE retCode = ADDR_OK;
786 
787     ADDR_TILEINFO tileInfo = {0};
788     ADDR_COMPUTE_FMASK_INFO_INPUT fmaskIn;
789     fmaskIn = *pIn;
790 
791     AddrTileMode tileMode = pIn->tileMode;
792 
793     // Use internal tile info if pOut does not have a valid pTileInfo
794     if (pOut->pTileInfo == NULL)
795     {
796         pOut->pTileInfo = &tileInfo;
797     }
798 
799     ADDR_ASSERT(tileMode == ADDR_TM_2D_TILED_THIN1     ||
800                 tileMode == ADDR_TM_3D_TILED_THIN1     ||
801                 tileMode == ADDR_TM_PRT_TILED_THIN1    ||
802                 tileMode == ADDR_TM_PRT_2D_TILED_THIN1 ||
803                 tileMode == ADDR_TM_PRT_3D_TILED_THIN1);
804 
805     ADDR_ASSERT(m_tileTable[14].mode == ADDR_TM_2D_TILED_THIN1);
806     ADDR_ASSERT(m_tileTable[15].mode == ADDR_TM_3D_TILED_THIN1);
807 
808     // The only valid tile modes for fmask are 2D_THIN1 and 3D_THIN1 plus non-displayable
809     INT_32 tileIndex = tileMode == ADDR_TM_2D_TILED_THIN1 ? 14 : 15;
810     ADDR_SURFACE_FLAGS flags = {{0}};
811     flags.fmask = 1;
812 
813     INT_32 macroModeIndex = TileIndexInvalid;
814 
815     UINT_32 numSamples = pIn->numSamples;
816     UINT_32 numFrags = pIn->numFrags == 0 ? numSamples : pIn->numFrags;
817 
818     UINT_32 bpp = QLog2(numFrags);
819 
820     // EQAA needs one more bit
821     if (numSamples > numFrags)
822     {
823         bpp++;
824     }
825 
826     if (bpp == 3)
827     {
828         bpp = 4;
829     }
830 
831     bpp = Max(8u, bpp * numSamples);
832 
833     macroModeIndex = HwlComputeMacroModeIndex(tileIndex, flags, bpp, numSamples, pOut->pTileInfo);
834 
835     fmaskIn.tileIndex = tileIndex;
836     fmaskIn.pTileInfo = pOut->pTileInfo;
837     pOut->macroModeIndex = macroModeIndex;
838     pOut->tileIndex = tileIndex;
839 
840     retCode = DispatchComputeFmaskInfo(&fmaskIn, pOut);
841 
842     if (retCode == ADDR_OK)
843     {
844         pOut->tileIndex =
845             HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE,
846                                   pOut->tileIndex);
847     }
848 
849     // Resets pTileInfo to NULL if the internal tile info is used
850     if (pOut->pTileInfo == &tileInfo)
851     {
852         pOut->pTileInfo = NULL;
853     }
854 
855     return retCode;
856 }
857 
858 /**
859 ****************************************************************************************************
860 *   CiLib::HwlFmaskPreThunkSurfInfo
861 *
862 *   @brief
863 *       Some preparation before thunking a ComputeSurfaceInfo call for Fmask
864 *   @return
865 *       ADDR_E_RETURNCODE
866 ****************************************************************************************************
867 */
HwlFmaskPreThunkSurfInfo(const ADDR_COMPUTE_FMASK_INFO_INPUT * pFmaskIn,const ADDR_COMPUTE_FMASK_INFO_OUTPUT * pFmaskOut,ADDR_COMPUTE_SURFACE_INFO_INPUT * pSurfIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pSurfOut) const868 VOID CiLib::HwlFmaskPreThunkSurfInfo(
869     const ADDR_COMPUTE_FMASK_INFO_INPUT*    pFmaskIn,   ///< [in] Input of fmask info
870     const ADDR_COMPUTE_FMASK_INFO_OUTPUT*   pFmaskOut,  ///< [in] Output of fmask info
871     ADDR_COMPUTE_SURFACE_INFO_INPUT*        pSurfIn,    ///< [out] Input of thunked surface info
872     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pSurfOut    ///< [out] Output of thunked surface info
873     ) const
874 {
875     pSurfIn->tileIndex = pFmaskIn->tileIndex;
876     pSurfOut->macroModeIndex  = pFmaskOut->macroModeIndex;
877 }
878 
879 /**
880 ****************************************************************************************************
881 *   CiLib::HwlFmaskPostThunkSurfInfo
882 *
883 *   @brief
884 *       Copy hwl extra field after calling thunked ComputeSurfaceInfo
885 *   @return
886 *       ADDR_E_RETURNCODE
887 ****************************************************************************************************
888 */
HwlFmaskPostThunkSurfInfo(const ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pSurfOut,ADDR_COMPUTE_FMASK_INFO_OUTPUT * pFmaskOut) const889 VOID CiLib::HwlFmaskPostThunkSurfInfo(
890     const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut,   ///< [in] Output of surface info
891     ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut           ///< [out] Output of fmask info
892     ) const
893 {
894     pFmaskOut->tileIndex = pSurfOut->tileIndex;
895     pFmaskOut->macroModeIndex = pSurfOut->macroModeIndex;
896 }
897 
898 /**
899 ****************************************************************************************************
900 *   CiLib::HwlDegradeThickTileMode
901 *
902 *   @brief
903 *       Degrades valid tile mode for thick modes if needed
904 *
905 *   @return
906 *       Suitable tile mode
907 ****************************************************************************************************
908 */
HwlDegradeThickTileMode(AddrTileMode baseTileMode,UINT_32 numSlices,UINT_32 * pBytesPerTile) const909 AddrTileMode CiLib::HwlDegradeThickTileMode(
910     AddrTileMode        baseTileMode,   ///< [in] base tile mode
911     UINT_32             numSlices,      ///< [in] current number of slices
912     UINT_32*            pBytesPerTile   ///< [in,out] pointer to bytes per slice
913     ) const
914 {
915     return baseTileMode;
916 }
917 
918 /**
919 ****************************************************************************************************
920 *   CiLib::HwlOptimizeTileMode
921 *
922 *   @brief
923 *       Optimize tile mode on CI
924 *
925 *   @return
926 *       N/A
927 *
928 ****************************************************************************************************
929 */
HwlOptimizeTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const930 VOID CiLib::HwlOptimizeTileMode(
931     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut      ///< [in,out] input output structure
932     ) const
933 {
934     AddrTileMode tileMode = pInOut->tileMode;
935 
936     // Override 2D/3D macro tile mode to PRT_* tile mode if
937     // client driver requests this surface is equation compatible
938     if (IsMacroTiled(tileMode) == TRUE)
939     {
940         if ((pInOut->flags.needEquation == TRUE) &&
941             (pInOut->numSamples <= 1) &&
942             (IsPrtTileMode(tileMode) == FALSE))
943         {
944             if ((pInOut->numSlices > 1) && ((pInOut->maxBaseAlign == 0) || (pInOut->maxBaseAlign >= Block64K)))
945             {
946                 UINT_32 thickness = Thickness(tileMode);
947 
948                 if (thickness == 1)
949                 {
950                     tileMode = ADDR_TM_PRT_TILED_THIN1;
951                 }
952                 else
953                 {
954                     static const UINT_32 PrtTileBytes = 0x10000;
955                     // First prt thick tile index in the tile mode table
956                     static const UINT_32 PrtThickTileIndex = 22;
957                     ADDR_TILEINFO tileInfo = {0};
958 
959                     HwlComputeMacroModeIndex(PrtThickTileIndex,
960                                              pInOut->flags,
961                                              pInOut->bpp,
962                                              pInOut->numSamples,
963                                              &tileInfo);
964 
965                     UINT_32 macroTileBytes = ((pInOut->bpp) >> 3) * 64 * pInOut->numSamples *
966                                              thickness * HwlGetPipes(&tileInfo) *
967                                              tileInfo.banks * tileInfo.bankWidth *
968                                              tileInfo.bankHeight;
969 
970                     if (macroTileBytes <= PrtTileBytes)
971                     {
972                         tileMode = ADDR_TM_PRT_TILED_THICK;
973                     }
974                     else
975                     {
976                         tileMode = ADDR_TM_PRT_TILED_THIN1;
977                     }
978                 }
979             }
980         }
981 
982         if (pInOut->maxBaseAlign != 0)
983         {
984             pInOut->flags.dccPipeWorkaround = FALSE;
985         }
986     }
987 
988     if (tileMode != pInOut->tileMode)
989     {
990         pInOut->tileMode = tileMode;
991     }
992 }
993 
994 /**
995 ****************************************************************************************************
996 *   CiLib::HwlOverrideTileMode
997 *
998 *   @brief
999 *       Override THICK to THIN, for specific formats on CI
1000 *
1001 *   @return
1002 *       N/A
1003 *
1004 ****************************************************************************************************
1005 */
HwlOverrideTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const1006 VOID CiLib::HwlOverrideTileMode(
1007     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut      ///< [in,out] input output structure
1008     ) const
1009 {
1010     AddrTileMode tileMode = pInOut->tileMode;
1011     AddrTileType tileType = pInOut->tileType;
1012 
1013     // currently, all CI/VI family do not
1014     // support ADDR_TM_PRT_2D_TILED_THICK,ADDR_TM_PRT_3D_TILED_THICK and
1015     // ADDR_TM_PRT_2D_TILED_THIN1, ADDR_TM_PRT_3D_TILED_THIN1
1016     switch (tileMode)
1017     {
1018         case ADDR_TM_PRT_2D_TILED_THICK:
1019         case ADDR_TM_PRT_3D_TILED_THICK:
1020             tileMode = ADDR_TM_PRT_TILED_THICK;
1021             break;
1022         case ADDR_TM_PRT_2D_TILED_THIN1:
1023         case ADDR_TM_PRT_3D_TILED_THIN1:
1024             tileMode = ADDR_TM_PRT_TILED_THIN1;
1025             break;
1026         default:
1027             break;
1028     }
1029 
1030     // UBTS#404321, we do not need such overriding, as THICK+THICK entries removed from the tile-mode table
1031     if (!m_settings.isBonaire)
1032     {
1033         UINT_32 thickness = Thickness(tileMode);
1034 
1035         // tile_thickness = (array_mode == XTHICK) ? 8 : ((array_mode == THICK) ? 4 : 1)
1036         if (thickness > 1)
1037         {
1038             switch (pInOut->format)
1039             {
1040                 // tcpError("Thick micro tiling is not supported for format...
1041                 case ADDR_FMT_X24_8_32_FLOAT:
1042                 case ADDR_FMT_32_AS_8:
1043                 case ADDR_FMT_32_AS_8_8:
1044                 case ADDR_FMT_32_AS_32_32_32_32:
1045 
1046                 // packed formats
1047                 case ADDR_FMT_GB_GR:
1048                 case ADDR_FMT_BG_RG:
1049                 case ADDR_FMT_1_REVERSED:
1050                 case ADDR_FMT_1:
1051                 case ADDR_FMT_BC1:
1052                 case ADDR_FMT_BC2:
1053                 case ADDR_FMT_BC3:
1054                 case ADDR_FMT_BC4:
1055                 case ADDR_FMT_BC5:
1056                 case ADDR_FMT_BC6:
1057                 case ADDR_FMT_BC7:
1058                     switch (tileMode)
1059                     {
1060                         case ADDR_TM_1D_TILED_THICK:
1061                             tileMode = ADDR_TM_1D_TILED_THIN1;
1062                             break;
1063 
1064                         case ADDR_TM_2D_TILED_XTHICK:
1065                         case ADDR_TM_2D_TILED_THICK:
1066                             tileMode = ADDR_TM_2D_TILED_THIN1;
1067                             break;
1068 
1069                         case ADDR_TM_3D_TILED_XTHICK:
1070                         case ADDR_TM_3D_TILED_THICK:
1071                             tileMode = ADDR_TM_3D_TILED_THIN1;
1072                             break;
1073 
1074                         case ADDR_TM_PRT_TILED_THICK:
1075                             tileMode = ADDR_TM_PRT_TILED_THIN1;
1076                             break;
1077 
1078                         case ADDR_TM_PRT_2D_TILED_THICK:
1079                             tileMode = ADDR_TM_PRT_2D_TILED_THIN1;
1080                             break;
1081 
1082                         case ADDR_TM_PRT_3D_TILED_THICK:
1083                             tileMode = ADDR_TM_PRT_3D_TILED_THIN1;
1084                             break;
1085 
1086                         default:
1087                             break;
1088 
1089                     }
1090 
1091                     // Switch tile type from thick to thin
1092                     if (tileMode != pInOut->tileMode)
1093                     {
1094                         // see tileIndex: 13-18
1095                         tileType = ADDR_NON_DISPLAYABLE;
1096                     }
1097 
1098                     break;
1099                 default:
1100                     break;
1101             }
1102         }
1103     }
1104 
1105     if (tileMode != pInOut->tileMode)
1106     {
1107         pInOut->tileMode = tileMode;
1108         pInOut->tileType = tileType;
1109     }
1110 }
1111 
1112 /**
1113 ****************************************************************************************************
1114 *   CiLib::HwlSelectTileMode
1115 *
1116 *   @brief
1117 *       Select tile modes.
1118 *
1119 *   @return
1120 *       N/A
1121 *
1122 ****************************************************************************************************
1123 */
HwlSelectTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const1124 VOID CiLib::HwlSelectTileMode(
1125     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
1126     ) const
1127 {
1128     AddrTileMode tileMode;
1129     AddrTileType tileType;
1130 
1131     if (pInOut->flags.rotateDisplay)
1132     {
1133         tileMode = ADDR_TM_2D_TILED_THIN1;
1134         tileType = ADDR_ROTATED;
1135     }
1136     else if (pInOut->flags.volume)
1137     {
1138         BOOL_32 bThin = (m_settings.isBonaire == TRUE) ||
1139                         ((m_allowNonDispThickModes == TRUE) && (pInOut->flags.color == TRUE));
1140 
1141         if (pInOut->numSlices >= 8)
1142         {
1143             tileMode = ADDR_TM_2D_TILED_XTHICK;
1144             tileType = (bThin == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1145         }
1146         else if (pInOut->numSlices >= 4)
1147         {
1148             tileMode = ADDR_TM_2D_TILED_THICK;
1149             tileType = (bThin == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1150         }
1151         else
1152         {
1153             tileMode = ADDR_TM_2D_TILED_THIN1;
1154             tileType = ADDR_NON_DISPLAYABLE;
1155         }
1156     }
1157     else
1158     {
1159         tileMode = ADDR_TM_2D_TILED_THIN1;
1160 
1161         if (pInOut->flags.depth || pInOut->flags.stencil)
1162         {
1163             tileType = ADDR_DEPTH_SAMPLE_ORDER;
1164         }
1165         else if ((pInOut->bpp <= 32) ||
1166                  (pInOut->flags.display == TRUE) ||
1167                  (pInOut->flags.overlay == TRUE))
1168         {
1169             tileType = ADDR_DISPLAYABLE;
1170         }
1171         else
1172         {
1173             tileType = ADDR_NON_DISPLAYABLE;
1174         }
1175     }
1176 
1177     if (pInOut->flags.prt)
1178     {
1179         if (Thickness(tileMode) > 1)
1180         {
1181             tileMode = ADDR_TM_PRT_TILED_THICK;
1182             tileType = (m_settings.isBonaire == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1183         }
1184         else
1185         {
1186             tileMode = ADDR_TM_PRT_TILED_THIN1;
1187         }
1188     }
1189 
1190     pInOut->tileMode = tileMode;
1191     pInOut->tileType = tileType;
1192 
1193     if ((pInOut->flags.dccCompatible == FALSE) &&
1194         (pInOut->flags.tcCompatible == FALSE))
1195     {
1196         pInOut->flags.opt4Space = TRUE;
1197         pInOut->maxBaseAlign = Block64K;
1198     }
1199 
1200     // Optimize tile mode if possible
1201     OptimizeTileMode(pInOut);
1202 
1203     HwlOverrideTileMode(pInOut);
1204 }
1205 
1206 /**
1207 ****************************************************************************************************
1208 *   CiLib::HwlSetPrtTileMode
1209 *
1210 *   @brief
1211 *       Set PRT tile mode.
1212 *
1213 *   @return
1214 *       N/A
1215 *
1216 ****************************************************************************************************
1217 */
HwlSetPrtTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const1218 VOID CiLib::HwlSetPrtTileMode(
1219     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
1220     ) const
1221 {
1222     AddrTileMode tileMode = pInOut->tileMode;
1223     AddrTileType tileType = pInOut->tileType;
1224 
1225     if (Thickness(tileMode) > 1)
1226     {
1227         tileMode = ADDR_TM_PRT_TILED_THICK;
1228         tileType = (m_settings.isBonaire == TRUE) ? ADDR_NON_DISPLAYABLE : ADDR_THICK;
1229     }
1230     else
1231     {
1232         tileMode = ADDR_TM_PRT_TILED_THIN1;
1233         tileType = (tileType == ADDR_THICK) ? ADDR_NON_DISPLAYABLE : tileType;
1234     }
1235 
1236     pInOut->tileMode = tileMode;
1237     pInOut->tileType = tileType;
1238 }
1239 
1240 /**
1241 ****************************************************************************************************
1242 *   CiLib::HwlSetupTileInfo
1243 *
1244 *   @brief
1245 *       Setup default value of tile info for SI
1246 ****************************************************************************************************
1247 */
HwlSetupTileInfo(AddrTileMode tileMode,ADDR_SURFACE_FLAGS flags,UINT_32 bpp,UINT_32 pitch,UINT_32 height,UINT_32 numSamples,ADDR_TILEINFO * pTileInfoIn,ADDR_TILEINFO * pTileInfoOut,AddrTileType inTileType,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1248 VOID CiLib::HwlSetupTileInfo(
1249     AddrTileMode                        tileMode,       ///< [in] Tile mode
1250     ADDR_SURFACE_FLAGS                  flags,          ///< [in] Surface type flags
1251     UINT_32                             bpp,            ///< [in] Bits per pixel
1252     UINT_32                             pitch,          ///< [in] Pitch in pixels
1253     UINT_32                             height,         ///< [in] Height in pixels
1254     UINT_32                             numSamples,     ///< [in] Number of samples
1255     ADDR_TILEINFO*                      pTileInfoIn,    ///< [in] Tile info input: NULL for default
1256     ADDR_TILEINFO*                      pTileInfoOut,   ///< [out] Tile info output
1257     AddrTileType                        inTileType,     ///< [in] Tile type
1258     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*   pOut            ///< [out] Output
1259     ) const
1260 {
1261     UINT_32 thickness = Thickness(tileMode);
1262     ADDR_TILEINFO* pTileInfo = pTileInfoOut;
1263     INT index = TileIndexInvalid;
1264     INT macroModeIndex = TileIndexInvalid;
1265 
1266     // Fail-safe code
1267     if (IsLinear(tileMode) == FALSE)
1268     {
1269         // Thick tile modes must use thick micro tile mode but Bonaire does not support due to
1270         // old derived netlists (UBTS 404321)
1271         if (thickness > 1)
1272         {
1273             if (m_settings.isBonaire)
1274             {
1275                 inTileType = ADDR_NON_DISPLAYABLE;
1276             }
1277             else if ((m_allowNonDispThickModes == FALSE) ||
1278                      (inTileType != ADDR_NON_DISPLAYABLE) ||
1279                      // There is no PRT_THICK + THIN entry in tile mode table except Bonaire
1280                      (IsPrtTileMode(tileMode) == TRUE))
1281             {
1282                 inTileType = ADDR_THICK;
1283             }
1284         }
1285         // 128 bpp tiling must be non-displayable.
1286         // Fmask reuse color buffer's entry but bank-height field can be from another entry
1287         // To simplify the logic, fmask entry should be picked from non-displayable ones
1288         else if (bpp == 128 || flags.fmask)
1289         {
1290             inTileType = ADDR_NON_DISPLAYABLE;
1291         }
1292         // These two modes only have non-disp entries though they can be other micro tile modes
1293         else if (tileMode == ADDR_TM_3D_TILED_THIN1 || tileMode == ADDR_TM_PRT_3D_TILED_THIN1)
1294         {
1295             inTileType = ADDR_NON_DISPLAYABLE;
1296         }
1297 
1298         if (flags.depth || flags.stencil)
1299         {
1300             inTileType = ADDR_DEPTH_SAMPLE_ORDER;
1301         }
1302     }
1303 
1304     // tcCompatible flag is only meaningful for gfx8.
1305     if (SupportDccAndTcCompatibility() == FALSE)
1306     {
1307         flags.tcCompatible = FALSE;
1308     }
1309 
1310     if (IsTileInfoAllZero(pTileInfo))
1311     {
1312         // See table entries 0-4
1313         if (flags.depth || flags.stencil)
1314         {
1315             // tileSize = thickness * bpp * numSamples * 8 * 8 / 8
1316             UINT_32 tileSize = thickness * bpp * numSamples * 8;
1317 
1318             // Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
1319             if (m_rowSize < tileSize)
1320             {
1321                 flags.tcCompatible = FALSE;
1322             }
1323 
1324             if (flags.nonSplit | flags.tcCompatible | flags.needEquation)
1325             {
1326                 // Texture readable depth surface should not be split
1327                 switch (tileSize)
1328                 {
1329                     case 64:
1330                         index = 0;
1331                         break;
1332                     case 128:
1333                         index = 1;
1334                         break;
1335                     case 256:
1336                         index = 2;
1337                         break;
1338                     case 512:
1339                         index = 3;
1340                         break;
1341                     default:
1342                         index = 4;
1343                         break;
1344                 }
1345             }
1346             else
1347             {
1348                 // Depth and stencil need to use the same index, thus the pre-defined tile_split
1349                 // can meet the requirement to choose the same macro mode index
1350                 // uncompressed depth/stencil are not supported for now
1351                 switch (numSamples)
1352                 {
1353                     case 1:
1354                         index = 0;
1355                         break;
1356                     case 2:
1357                     case 4:
1358                         index = 1;
1359                         break;
1360                     case 8:
1361                         index = 2;
1362                         break;
1363                     default:
1364                         break;
1365                 }
1366             }
1367         }
1368 
1369         // See table entries 5-6
1370         if (inTileType == ADDR_DEPTH_SAMPLE_ORDER)
1371         {
1372             switch (tileMode)
1373             {
1374                 case ADDR_TM_1D_TILED_THIN1:
1375                     index = 5;
1376                     break;
1377                 case ADDR_TM_PRT_TILED_THIN1:
1378                     index = 6;
1379                     break;
1380                 default:
1381                     break;
1382             }
1383         }
1384 
1385         // See table entries 8-12
1386         if (inTileType == ADDR_DISPLAYABLE)
1387         {
1388             switch (tileMode)
1389             {
1390                 case ADDR_TM_1D_TILED_THIN1:
1391                     index = 9;
1392                     break;
1393                 case ADDR_TM_2D_TILED_THIN1:
1394                     index = 10;
1395                     break;
1396                 case ADDR_TM_PRT_TILED_THIN1:
1397                     index = 11;
1398                     break;
1399                 default:
1400                     break;
1401             }
1402         }
1403 
1404         // See table entries 13-18
1405         if (inTileType == ADDR_NON_DISPLAYABLE)
1406         {
1407             switch (tileMode)
1408             {
1409                 case ADDR_TM_1D_TILED_THIN1:
1410                     index = 13;
1411                     break;
1412                 case ADDR_TM_2D_TILED_THIN1:
1413                     index = 14;
1414                     break;
1415                 case ADDR_TM_3D_TILED_THIN1:
1416                     index = 15;
1417                     break;
1418                 case ADDR_TM_PRT_TILED_THIN1:
1419                     index = 16;
1420                     break;
1421                 default:
1422                     break;
1423             }
1424         }
1425 
1426         // See table entries 19-26
1427         if (thickness > 1)
1428         {
1429             switch (tileMode)
1430             {
1431                 case ADDR_TM_1D_TILED_THICK:
1432                     // special check for bonaire, for the compatablity between old KMD and new UMD
1433                     index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 19 : 18;
1434                     break;
1435                 case ADDR_TM_2D_TILED_THICK:
1436                     // special check for bonaire, for the compatablity between old KMD and new UMD
1437                     index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 20 : 24;
1438                     break;
1439                 case ADDR_TM_3D_TILED_THICK:
1440                     index = 21;
1441                     break;
1442                 case ADDR_TM_PRT_TILED_THICK:
1443                     index = 22;
1444                     break;
1445                 case ADDR_TM_2D_TILED_XTHICK:
1446                     index = 25;
1447                     break;
1448                 case ADDR_TM_3D_TILED_XTHICK:
1449                     index = 26;
1450                     break;
1451                 default:
1452                     break;
1453             }
1454         }
1455 
1456         // See table entries 27-30
1457         if (inTileType == ADDR_ROTATED)
1458         {
1459             switch (tileMode)
1460             {
1461                 case ADDR_TM_1D_TILED_THIN1:
1462                     index = 27;
1463                     break;
1464                 case ADDR_TM_2D_TILED_THIN1:
1465                     index = 28;
1466                     break;
1467                 case ADDR_TM_PRT_TILED_THIN1:
1468                     index = 29;
1469                     break;
1470                 case ADDR_TM_PRT_2D_TILED_THIN1:
1471                     index = 30;
1472                     break;
1473                 default:
1474                     break;
1475             }
1476         }
1477 
1478         if (m_pipes >= 8)
1479         {
1480             ADDR_ASSERT((index + 1) < static_cast<INT_32>(m_noOfEntries));
1481             // Only do this when tile mode table is updated.
1482             if (((tileMode == ADDR_TM_PRT_TILED_THIN1) || (tileMode == ADDR_TM_PRT_TILED_THICK)) &&
1483                 (m_tileTable[index + 1].mode == tileMode))
1484             {
1485                 static const UINT_32 PrtTileBytes = 0x10000;
1486                 ADDR_TILEINFO tileInfo = {0};
1487 
1488                 HwlComputeMacroModeIndex(index, flags, bpp, numSamples, &tileInfo);
1489 
1490                 UINT_32 macroTileBytes = (bpp >> 3) * 64 * numSamples * thickness *
1491                                          HwlGetPipes(&tileInfo) * tileInfo.banks *
1492                                          tileInfo.bankWidth * tileInfo.bankHeight;
1493 
1494                 if (macroTileBytes != PrtTileBytes)
1495                 {
1496                     // Switching to next tile mode entry to make sure macro tile size is 64KB
1497                     index += 1;
1498 
1499                     tileInfo.pipeConfig = m_tileTable[index].info.pipeConfig;
1500 
1501                     macroTileBytes = (bpp >> 3) * 64 * numSamples * thickness *
1502                                      HwlGetPipes(&tileInfo) * tileInfo.banks *
1503                                      tileInfo.bankWidth * tileInfo.bankHeight;
1504 
1505                     ADDR_ASSERT(macroTileBytes == PrtTileBytes);
1506 
1507                     flags.tcCompatible = FALSE;
1508                     pOut->dccUnsupport = TRUE;
1509                 }
1510             }
1511         }
1512     }
1513     else
1514     {
1515         // A pre-filled tile info is ready
1516         index = pOut->tileIndex;
1517         macroModeIndex = pOut->macroModeIndex;
1518 
1519         // pass tile type back for post tile index compute
1520         pOut->tileType = inTileType;
1521 
1522         if (flags.depth || flags.stencil)
1523         {
1524             // tileSize = thickness * bpp * numSamples * 8 * 8 / 8
1525             UINT_32 tileSize = thickness * bpp * numSamples * 8;
1526 
1527             // Turn off tc compatible if row_size is smaller than tile size (tile split occurs).
1528             if (m_rowSize < tileSize)
1529             {
1530                 flags.tcCompatible = FALSE;
1531             }
1532         }
1533 
1534         UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
1535 
1536         if (m_pipes != numPipes)
1537         {
1538             pOut->dccUnsupport = TRUE;
1539         }
1540     }
1541 
1542     // We only need to set up tile info if there is a valid index but macroModeIndex is invalid
1543     if ((index != TileIndexInvalid) && (macroModeIndex == TileIndexInvalid))
1544     {
1545         macroModeIndex = HwlComputeMacroModeIndex(index, flags, bpp, numSamples, pTileInfo);
1546 
1547         // Copy to pOut->tileType/tileIndex/macroModeIndex
1548         pOut->tileIndex = index;
1549         pOut->tileType = m_tileTable[index].type; // Or inTileType, the samea
1550         pOut->macroModeIndex = macroModeIndex;
1551     }
1552     else if (tileMode == ADDR_TM_LINEAR_GENERAL)
1553     {
1554         pOut->tileIndex = TileIndexLinearGeneral;
1555 
1556         // Copy linear-aligned entry??
1557         *pTileInfo = m_tileTable[8].info;
1558     }
1559     else if (tileMode == ADDR_TM_LINEAR_ALIGNED)
1560     {
1561         pOut->tileIndex = 8;
1562         *pTileInfo = m_tileTable[8].info;
1563     }
1564 
1565     if (flags.tcCompatible)
1566     {
1567         flags.tcCompatible = CheckTcCompatibility(pTileInfo, bpp, tileMode, inTileType, pOut);
1568     }
1569 
1570     pOut->tcCompatible = flags.tcCompatible;
1571 }
1572 
1573 /**
1574 ****************************************************************************************************
1575 *   CiLib::ReadGbTileMode
1576 *
1577 *   @brief
1578 *       Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG.
1579 ****************************************************************************************************
1580 */
ReadGbTileMode(UINT_32 regValue,TileConfig * pCfg) const1581 VOID CiLib::ReadGbTileMode(
1582     UINT_32       regValue,   ///< [in] GB_TILE_MODE register
1583     TileConfig*   pCfg        ///< [out] output structure
1584     ) const
1585 {
1586     GB_TILE_MODE gbTileMode;
1587     gbTileMode.val = regValue;
1588 
1589     pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode_new);
1590     if (AltTilingEnabled() == TRUE)
1591     {
1592         pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.alt_pipe_config + 1);
1593     }
1594     else
1595     {
1596         pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
1597     }
1598 
1599     if (pCfg->type == ADDR_DEPTH_SAMPLE_ORDER)
1600     {
1601         pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
1602     }
1603     else
1604     {
1605         pCfg->info.tileSplitBytes = 1 << gbTileMode.f.sample_split;
1606     }
1607 
1608     UINT_32 regArrayMode = gbTileMode.f.array_mode;
1609 
1610     pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
1611 
1612     switch (regArrayMode)
1613     {
1614         case 5:
1615             pCfg->mode = ADDR_TM_PRT_TILED_THIN1;
1616             break;
1617         case 6:
1618             pCfg->mode = ADDR_TM_PRT_2D_TILED_THIN1;
1619             break;
1620         case 8:
1621             pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
1622             break;
1623         case 9:
1624             pCfg->mode = ADDR_TM_PRT_TILED_THICK;
1625             break;
1626         case 0xa:
1627             pCfg->mode = ADDR_TM_PRT_2D_TILED_THICK;
1628             break;
1629         case 0xb:
1630             pCfg->mode = ADDR_TM_PRT_3D_TILED_THIN1;
1631             break;
1632         case 0xe:
1633             pCfg->mode = ADDR_TM_3D_TILED_XTHICK;
1634             break;
1635         case 0xf:
1636             pCfg->mode = ADDR_TM_PRT_3D_TILED_THICK;
1637             break;
1638         default:
1639             break;
1640     }
1641 
1642     // Fail-safe code for these always convert tile info, as the non-macro modes
1643     // return the entry of tile mode table directly without looking up macro mode table
1644     if (!IsMacroTiled(pCfg->mode))
1645     {
1646         pCfg->info.banks = 2;
1647         pCfg->info.bankWidth = 1;
1648         pCfg->info.bankHeight = 1;
1649         pCfg->info.macroAspectRatio = 1;
1650         pCfg->info.tileSplitBytes = 64;
1651     }
1652 }
1653 
1654 /**
1655 ****************************************************************************************************
1656 *   CiLib::InitTileSettingTable
1657 *
1658 *   @brief
1659 *       Initialize the ADDR_TILE_CONFIG table.
1660 *   @return
1661 *       TRUE if tile table is correctly initialized
1662 ****************************************************************************************************
1663 */
InitTileSettingTable(const UINT_32 * pCfg,UINT_32 noOfEntries)1664 BOOL_32 CiLib::InitTileSettingTable(
1665     const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
1666     UINT_32         noOfEntries     ///< [in] Numbe of entries in the table above
1667     )
1668 {
1669     BOOL_32 initOk = TRUE;
1670 
1671     ADDR_ASSERT(noOfEntries <= TileTableSize);
1672 
1673     memset(m_tileTable, 0, sizeof(m_tileTable));
1674 
1675     if (noOfEntries != 0)
1676     {
1677         m_noOfEntries = noOfEntries;
1678     }
1679     else
1680     {
1681         m_noOfEntries = TileTableSize;
1682     }
1683 
1684     if (pCfg) // From Client
1685     {
1686         for (UINT_32 i = 0; i < m_noOfEntries; i++)
1687         {
1688             ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
1689         }
1690     }
1691     else
1692     {
1693         ADDR_ASSERT_ALWAYS();
1694         initOk = FALSE;
1695     }
1696 
1697     if (initOk)
1698     {
1699         ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
1700 
1701         if (m_settings.isBonaire == FALSE)
1702         {
1703             // Check if entry 18 is "thick+thin" combination
1704             if ((m_tileTable[18].mode == ADDR_TM_1D_TILED_THICK) &&
1705                 (m_tileTable[18].type == ADDR_NON_DISPLAYABLE))
1706             {
1707                 m_allowNonDispThickModes = TRUE;
1708                 ADDR_ASSERT(m_tileTable[24].mode == ADDR_TM_2D_TILED_THICK);
1709             }
1710         }
1711         else
1712         {
1713             m_allowNonDispThickModes = TRUE;
1714         }
1715 
1716         // Assume the first entry is always programmed with full pipes
1717         m_pipes = HwlGetPipes(&m_tileTable[0].info);
1718     }
1719 
1720     return initOk;
1721 }
1722 
1723 /**
1724 ****************************************************************************************************
1725 *   CiLib::ReadGbMacroTileCfg
1726 *
1727 *   @brief
1728 *       Convert GB_MACRO_TILE_CFG HW value to ADDR_TILE_CONFIG.
1729 ****************************************************************************************************
1730 */
ReadGbMacroTileCfg(UINT_32 regValue,ADDR_TILEINFO * pCfg) const1731 VOID CiLib::ReadGbMacroTileCfg(
1732     UINT_32             regValue,   ///< [in] GB_MACRO_TILE_MODE register
1733     ADDR_TILEINFO*      pCfg        ///< [out] output structure
1734     ) const
1735 {
1736     GB_MACROTILE_MODE gbTileMode;
1737     gbTileMode.val = regValue;
1738 
1739     if (AltTilingEnabled() == TRUE)
1740     {
1741         pCfg->bankHeight       = 1 << gbTileMode.f.alt_bank_height;
1742         pCfg->banks            = 1 << (gbTileMode.f.alt_num_banks + 1);
1743         pCfg->macroAspectRatio = 1 << gbTileMode.f.alt_macro_tile_aspect;
1744     }
1745     else
1746     {
1747         pCfg->bankHeight       = 1 << gbTileMode.f.bank_height;
1748         pCfg->banks            = 1 << (gbTileMode.f.num_banks + 1);
1749         pCfg->macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
1750     }
1751     pCfg->bankWidth = 1 << gbTileMode.f.bank_width;
1752 }
1753 
1754 /**
1755 ****************************************************************************************************
1756 *   CiLib::InitMacroTileCfgTable
1757 *
1758 *   @brief
1759 *       Initialize the ADDR_MACRO_TILE_CONFIG table.
1760 *   @return
1761 *       TRUE if macro tile table is correctly initialized
1762 ****************************************************************************************************
1763 */
InitMacroTileCfgTable(const UINT_32 * pCfg,UINT_32 noOfMacroEntries)1764 BOOL_32 CiLib::InitMacroTileCfgTable(
1765     const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
1766     UINT_32         noOfMacroEntries     ///< [in] Numbe of entries in the table above
1767     )
1768 {
1769     BOOL_32 initOk = TRUE;
1770 
1771     ADDR_ASSERT(noOfMacroEntries <= MacroTileTableSize);
1772 
1773     memset(m_macroTileTable, 0, sizeof(m_macroTileTable));
1774 
1775     if (noOfMacroEntries != 0)
1776     {
1777         m_noOfMacroEntries = noOfMacroEntries;
1778     }
1779     else
1780     {
1781         m_noOfMacroEntries = MacroTileTableSize;
1782     }
1783 
1784     if (pCfg) // From Client
1785     {
1786         for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
1787         {
1788             ReadGbMacroTileCfg(*(pCfg + i), &m_macroTileTable[i]);
1789 
1790             m_macroTileTable[i].tileSplitBytes = 64 << (i % 8);
1791         }
1792     }
1793     else
1794     {
1795         ADDR_ASSERT_ALWAYS();
1796         initOk = FALSE;
1797     }
1798     return initOk;
1799 }
1800 
1801 /**
1802 ****************************************************************************************************
1803 *   CiLib::HwlComputeMacroModeIndex
1804 *
1805 *   @brief
1806 *       Computes macro tile mode index
1807 *   @return
1808 *       TRUE if macro tile table is correctly initialized
1809 ****************************************************************************************************
1810 */
HwlComputeMacroModeIndex(INT_32 tileIndex,ADDR_SURFACE_FLAGS flags,UINT_32 bpp,UINT_32 numSamples,ADDR_TILEINFO * pTileInfo,AddrTileMode * pTileMode,AddrTileType * pTileType) const1811 INT_32 CiLib::HwlComputeMacroModeIndex(
1812     INT_32              tileIndex,      ///< [in] Tile mode index
1813     ADDR_SURFACE_FLAGS  flags,          ///< [in] Surface flags
1814     UINT_32             bpp,            ///< [in] Bit per pixel
1815     UINT_32             numSamples,     ///< [in] Number of samples
1816     ADDR_TILEINFO*      pTileInfo,      ///< [out] Pointer to ADDR_TILEINFO
1817     AddrTileMode*       pTileMode,      ///< [out] Pointer to AddrTileMode
1818     AddrTileType*       pTileType       ///< [out] Pointer to AddrTileType
1819     ) const
1820 {
1821     INT_32 macroModeIndex = TileIndexInvalid;
1822 
1823     AddrTileMode tileMode = m_tileTable[tileIndex].mode;
1824     AddrTileType tileType = m_tileTable[tileIndex].type;
1825     UINT_32 thickness = Thickness(tileMode);
1826 
1827     if (!IsMacroTiled(tileMode))
1828     {
1829         *pTileInfo = m_tileTable[tileIndex].info;
1830         macroModeIndex = TileIndexNoMacroIndex;
1831     }
1832     else
1833     {
1834         UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
1835         UINT_32 tileSplit;
1836 
1837         if (m_tileTable[tileIndex].type == ADDR_DEPTH_SAMPLE_ORDER)
1838         {
1839             // Depth entries store real tileSplitBytes
1840             tileSplit = m_tileTable[tileIndex].info.tileSplitBytes;
1841         }
1842         else
1843         {
1844             // Non-depth entries store a split factor
1845             UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes;
1846             UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x);
1847 
1848             tileSplit = colorTileSplit;
1849         }
1850 
1851         UINT_32 tileSplitC = Min(m_rowSize, tileSplit);
1852         UINT_32 tileBytes;
1853 
1854         if (flags.fmask)
1855         {
1856             tileBytes = Min(tileSplitC, tileBytes1x);
1857         }
1858         else
1859         {
1860             tileBytes = Min(tileSplitC, numSamples * tileBytes1x);
1861         }
1862 
1863         if (tileBytes < 64)
1864         {
1865             tileBytes = 64;
1866         }
1867 
1868         macroModeIndex = Log2(tileBytes / 64);
1869 
1870         if (flags.prt || IsPrtTileMode(tileMode))
1871         {
1872             macroModeIndex += PrtMacroModeOffset;
1873             *pTileInfo = m_macroTileTable[macroModeIndex];
1874         }
1875         else
1876         {
1877             *pTileInfo = m_macroTileTable[macroModeIndex];
1878         }
1879 
1880         pTileInfo->pipeConfig = m_tileTable[tileIndex].info.pipeConfig;
1881 
1882         pTileInfo->tileSplitBytes = tileSplitC;
1883     }
1884 
1885     if (NULL != pTileMode)
1886     {
1887         *pTileMode = tileMode;
1888     }
1889 
1890     if (NULL != pTileType)
1891     {
1892         *pTileType = tileType;
1893     }
1894 
1895     return macroModeIndex;
1896 }
1897 
1898 /**
1899 ****************************************************************************************************
1900 *   CiLib::HwlComputeTileDataWidthAndHeightLinear
1901 *
1902 *   @brief
1903 *       Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1904 *
1905 *   @note
1906 *       MacroWidth and macroHeight are measured in pixels
1907 ****************************************************************************************************
1908 */
HwlComputeTileDataWidthAndHeightLinear(UINT_32 * pMacroWidth,UINT_32 * pMacroHeight,UINT_32 bpp,ADDR_TILEINFO * pTileInfo) const1909 VOID CiLib::HwlComputeTileDataWidthAndHeightLinear(
1910     UINT_32*        pMacroWidth,     ///< [out] macro tile width
1911     UINT_32*        pMacroHeight,    ///< [out] macro tile height
1912     UINT_32         bpp,             ///< [in] bits per pixel
1913     ADDR_TILEINFO*  pTileInfo        ///< [in] tile info
1914     ) const
1915 {
1916     ADDR_ASSERT(pTileInfo != NULL);
1917 
1918     UINT_32 numTiles;
1919 
1920     switch (pTileInfo->pipeConfig)
1921     {
1922         case ADDR_PIPECFG_P16_32x32_8x16:
1923         case ADDR_PIPECFG_P16_32x32_16x16:
1924         case ADDR_PIPECFG_P8_32x64_32x32:
1925         case ADDR_PIPECFG_P8_32x32_16x32:
1926         case ADDR_PIPECFG_P8_32x32_16x16:
1927         case ADDR_PIPECFG_P8_32x32_8x16:
1928         case ADDR_PIPECFG_P4_32x32:
1929             numTiles = 8;
1930             break;
1931         default:
1932             numTiles = 4;
1933             break;
1934     }
1935 
1936     *pMacroWidth    = numTiles * MicroTileWidth;
1937     *pMacroHeight   = numTiles * MicroTileHeight;
1938 }
1939 
1940 /**
1941 ****************************************************************************************************
1942 *   CiLib::HwlComputeMetadataNibbleAddress
1943 *
1944 *   @brief
1945 *        calculate meta data address based on input information
1946 *
1947 *   &parameter
1948 *        uncompressedDataByteAddress - address of a pixel in color surface
1949 *        dataBaseByteAddress         - base address of color surface
1950 *        metadataBaseByteAddress     - base address of meta ram
1951 *        metadataBitSize             - meta key size, 8 for DCC, 4 for cmask
1952 *        elementBitSize              - element size of color surface
1953 *        blockByteSize               - compression block size, 256 for DCC
1954 *        pipeInterleaveBytes         - pipe interleave size
1955 *        numOfPipes                  - number of pipes
1956 *        numOfBanks                  - number of banks
1957 *        numOfSamplesPerSplit        - number of samples per tile split
1958 *   @return
1959 *        meta data nibble address (nibble address is used to support DCC compatible cmask)
1960 *
1961 ****************************************************************************************************
1962 */
HwlComputeMetadataNibbleAddress(UINT_64 uncompressedDataByteAddress,UINT_64 dataBaseByteAddress,UINT_64 metadataBaseByteAddress,UINT_32 metadataBitSize,UINT_32 elementBitSize,UINT_32 blockByteSize,UINT_32 pipeInterleaveBytes,UINT_32 numOfPipes,UINT_32 numOfBanks,UINT_32 numOfSamplesPerSplit) const1963 UINT_64 CiLib::HwlComputeMetadataNibbleAddress(
1964     UINT_64 uncompressedDataByteAddress,
1965     UINT_64 dataBaseByteAddress,
1966     UINT_64 metadataBaseByteAddress,
1967     UINT_32 metadataBitSize,
1968     UINT_32 elementBitSize,
1969     UINT_32 blockByteSize,
1970     UINT_32 pipeInterleaveBytes,
1971     UINT_32 numOfPipes,
1972     UINT_32 numOfBanks,
1973     UINT_32 numOfSamplesPerSplit) const
1974 {
1975     ///--------------------------------------------------------------------------------------------
1976     /// Get pipe interleave, bank and pipe bits
1977     ///--------------------------------------------------------------------------------------------
1978     UINT_32 pipeInterleaveBits  = Log2(pipeInterleaveBytes);
1979     UINT_32 pipeBits            = Log2(numOfPipes);
1980     UINT_32 bankBits            = Log2(numOfBanks);
1981 
1982     ///--------------------------------------------------------------------------------------------
1983     /// Clear pipe and bank swizzles
1984     ///--------------------------------------------------------------------------------------------
1985     UINT_32 dataMacrotileBits        = pipeInterleaveBits + pipeBits + bankBits;
1986     UINT_32 metadataMacrotileBits    = pipeInterleaveBits + pipeBits + bankBits;
1987 
1988     UINT_64 dataMacrotileClearMask     = ~((1L << dataMacrotileBits) - 1);
1989     UINT_64 metadataMacrotileClearMask = ~((1L << metadataMacrotileBits) - 1);
1990 
1991     UINT_64 dataBaseByteAddressNoSwizzle = dataBaseByteAddress & dataMacrotileClearMask;
1992     UINT_64 metadataBaseByteAddressNoSwizzle = metadataBaseByteAddress & metadataMacrotileClearMask;
1993 
1994     ///--------------------------------------------------------------------------------------------
1995     /// Modify metadata base before adding in so that when final address is divided by data ratio,
1996     /// the base address returns to where it should be
1997     ///--------------------------------------------------------------------------------------------
1998     ADDR_ASSERT((0 != metadataBitSize));
1999     UINT_64 metadataBaseShifted = metadataBaseByteAddressNoSwizzle * blockByteSize * 8 /
2000                                   metadataBitSize;
2001     UINT_64 offset = uncompressedDataByteAddress -
2002                      dataBaseByteAddressNoSwizzle +
2003                      metadataBaseShifted;
2004 
2005     ///--------------------------------------------------------------------------------------------
2006     /// Save bank data bits
2007     ///--------------------------------------------------------------------------------------------
2008     UINT_32 lsb = pipeBits + pipeInterleaveBits;
2009     UINT_32 msb = bankBits - 1 + lsb;
2010 
2011     UINT_64 bankDataBits = GetBits(offset, msb, lsb);
2012 
2013     ///--------------------------------------------------------------------------------------------
2014     /// Save pipe data bits
2015     ///--------------------------------------------------------------------------------------------
2016     lsb = pipeInterleaveBits;
2017     msb = pipeBits - 1 + lsb;
2018 
2019     UINT_64 pipeDataBits = GetBits(offset, msb, lsb);
2020 
2021     ///--------------------------------------------------------------------------------------------
2022     /// Remove pipe and bank bits
2023     ///--------------------------------------------------------------------------------------------
2024     lsb = pipeInterleaveBits;
2025     msb = dataMacrotileBits - 1;
2026 
2027     UINT_64 offsetWithoutPipeBankBits = RemoveBits(offset, msb, lsb);
2028 
2029     ADDR_ASSERT((0 != blockByteSize));
2030     UINT_64 blockInBankpipe = offsetWithoutPipeBankBits / blockByteSize;
2031 
2032     UINT_32 tileSize = 8 * 8 * elementBitSize/8 * numOfSamplesPerSplit;
2033     UINT_32 blocksInTile = tileSize / blockByteSize;
2034 
2035     if (0 == blocksInTile)
2036     {
2037         lsb = 0;
2038     }
2039     else
2040     {
2041         lsb = Log2(blocksInTile);
2042     }
2043     msb = bankBits - 1 + lsb;
2044 
2045     UINT_64 blockInBankpipeWithBankBits = InsertBits(blockInBankpipe, bankDataBits, msb, lsb);
2046 
2047     /// NOTE *2 because we are converting to Nibble address in this step
2048     UINT_64 metaAddressInPipe = blockInBankpipeWithBankBits * 2 * metadataBitSize / 8;
2049 
2050 
2051     ///--------------------------------------------------------------------------------------------
2052     /// Reinsert pipe bits back into the final address
2053     ///--------------------------------------------------------------------------------------------
2054     lsb = pipeInterleaveBits + 1; ///<+1 due to Nibble address now gives interleave bits extra lsb.
2055     msb = pipeBits - 1 + lsb;
2056     UINT_64 metadataAddress = InsertBits(metaAddressInPipe, pipeDataBits, msb, lsb);
2057 
2058     return metadataAddress;
2059 }
2060 
2061 /**
2062 ****************************************************************************************************
2063 *   CiLib::HwlComputeSurfaceAlignmentsMacroTiled
2064 *
2065 *   @brief
2066 *       Hardware layer function to compute alignment request for macro tile mode
2067 *
2068 ****************************************************************************************************
2069 */
HwlComputeSurfaceAlignmentsMacroTiled(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 mipLevel,UINT_32 numSamples,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2070 VOID CiLib::HwlComputeSurfaceAlignmentsMacroTiled(
2071     AddrTileMode                      tileMode,           ///< [in] tile mode
2072     UINT_32                           bpp,                ///< [in] bits per pixel
2073     ADDR_SURFACE_FLAGS                flags,              ///< [in] surface flags
2074     UINT_32                           mipLevel,           ///< [in] mip level
2075     UINT_32                           numSamples,         ///< [in] number of samples
2076     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut                ///< [in,out] Surface output
2077     ) const
2078 {
2079     // This is to workaround a H/W limitation that DCC doesn't work when pipe config is switched to
2080     // P4. In theory, all asics that have such switching should be patched but we now only know what
2081     // to pad for Fiji.
2082     if ((m_settings.isFiji == TRUE) &&
2083         (flags.dccPipeWorkaround == TRUE) &&
2084         (flags.prt == FALSE) &&
2085         (mipLevel == 0) &&
2086         (tileMode == ADDR_TM_PRT_TILED_THIN1) &&
2087         (pOut->dccUnsupport == TRUE))
2088     {
2089         pOut->pitchAlign   = PowTwoAlign(pOut->pitchAlign, 256);
2090         // In case the client still requests DCC usage.
2091         pOut->dccUnsupport = FALSE;
2092     }
2093 }
2094 
2095 /**
2096 ****************************************************************************************************
2097 *   CiLib::HwlPadDimensions
2098 *
2099 *   @brief
2100 *       Helper function to pad dimensions
2101 *
2102 ****************************************************************************************************
2103 */
HwlPadDimensions(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 numSamples,ADDR_TILEINFO * pTileInfo,UINT_32 mipLevel,UINT_32 * pPitch,UINT_32 * pPitchAlign,UINT_32 height,UINT_32 heightAlign) const2104 VOID CiLib::HwlPadDimensions(
2105     AddrTileMode        tileMode,    ///< [in] tile mode
2106     UINT_32             bpp,         ///< [in] bits per pixel
2107     ADDR_SURFACE_FLAGS  flags,       ///< [in] surface flags
2108     UINT_32             numSamples,  ///< [in] number of samples
2109     ADDR_TILEINFO*      pTileInfo,   ///< [in] tile info
2110     UINT_32             mipLevel,    ///< [in] mip level
2111     UINT_32*            pPitch,      ///< [in,out] pitch in pixels
2112     UINT_32*            pPitchAlign, ///< [in,out] pitch alignment
2113     UINT_32             height,      ///< [in] height in pixels
2114     UINT_32             heightAlign  ///< [in] height alignment
2115     ) const
2116 {
2117     if ((SupportDccAndTcCompatibility() == TRUE) &&
2118         (flags.dccCompatible == TRUE) &&
2119         (numSamples > 1) &&
2120         (mipLevel == 0) &&
2121         (IsMacroTiled(tileMode) == TRUE))
2122     {
2123         UINT_32 tileSizePerSample = BITS_TO_BYTES(bpp * MicroTileWidth * MicroTileHeight);
2124         UINT_32 samplesPerSplit  = pTileInfo->tileSplitBytes / tileSizePerSample;
2125 
2126         if (samplesPerSplit < numSamples)
2127         {
2128             UINT_32 dccFastClearByteAlign = HwlGetPipes(pTileInfo) * m_pipeInterleaveBytes * 256;
2129             UINT_32 bytesPerSplit = BITS_TO_BYTES((*pPitch) * height * bpp * samplesPerSplit);
2130 
2131             ADDR_ASSERT(IsPow2(dccFastClearByteAlign));
2132 
2133             if (0 != (bytesPerSplit & (dccFastClearByteAlign - 1)))
2134             {
2135                 UINT_32 dccFastClearPixelAlign = dccFastClearByteAlign /
2136                                                 BITS_TO_BYTES(bpp) /
2137                                                 samplesPerSplit;
2138                 UINT_32 macroTilePixelAlign = (*pPitchAlign) * heightAlign;
2139 
2140                 if ((dccFastClearPixelAlign >= macroTilePixelAlign) &&
2141                     ((dccFastClearPixelAlign % macroTilePixelAlign) == 0))
2142                 {
2143                     UINT_32 dccFastClearPitchAlignInMacroTile =
2144                         dccFastClearPixelAlign / macroTilePixelAlign;
2145                     UINT_32 heightInMacroTile = height / heightAlign;
2146 
2147                     while ((heightInMacroTile > 1) &&
2148                            ((heightInMacroTile % 2) == 0) &&
2149                            (dccFastClearPitchAlignInMacroTile > 1) &&
2150                            ((dccFastClearPitchAlignInMacroTile % 2) == 0))
2151                     {
2152                         heightInMacroTile >>= 1;
2153                         dccFastClearPitchAlignInMacroTile >>= 1;
2154                     }
2155 
2156                     UINT_32 dccFastClearPitchAlignInPixels =
2157                         (*pPitchAlign) * dccFastClearPitchAlignInMacroTile;
2158 
2159                     if (IsPow2(dccFastClearPitchAlignInPixels))
2160                     {
2161                         *pPitch = PowTwoAlign((*pPitch), dccFastClearPitchAlignInPixels);
2162                     }
2163                     else
2164                     {
2165                         *pPitch += (dccFastClearPitchAlignInPixels - 1);
2166                         *pPitch /= dccFastClearPitchAlignInPixels;
2167                         *pPitch *= dccFastClearPitchAlignInPixels;
2168                     }
2169 
2170                     *pPitchAlign = dccFastClearPitchAlignInPixels;
2171                 }
2172             }
2173         }
2174     }
2175 }
2176 
2177 /**
2178 ****************************************************************************************************
2179 *   CiLib::HwlComputeMaxBaseAlignments
2180 *
2181 *   @brief
2182 *       Gets maximum alignments
2183 *   @return
2184 *       maximum alignments
2185 ****************************************************************************************************
2186 */
HwlComputeMaxBaseAlignments() const2187 UINT_32 CiLib::HwlComputeMaxBaseAlignments() const
2188 {
2189     const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info);
2190 
2191     // Initial size is 64 KiB for PRT.
2192     UINT_32 maxBaseAlign = 64 * 1024;
2193 
2194     for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
2195     {
2196         // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
2197         UINT_32 tileSize = m_macroTileTable[i].tileSplitBytes;
2198 
2199         UINT_32 baseAlign = tileSize * pipes * m_macroTileTable[i].banks *
2200                             m_macroTileTable[i].bankWidth * m_macroTileTable[i].bankHeight;
2201 
2202         if (baseAlign > maxBaseAlign)
2203         {
2204             maxBaseAlign = baseAlign;
2205         }
2206     }
2207 
2208     return maxBaseAlign;
2209 }
2210 
2211 /**
2212 ****************************************************************************************************
2213 *   CiLib::HwlComputeMaxMetaBaseAlignments
2214 *
2215 *   @brief
2216 *       Gets maximum alignments for metadata
2217 *   @return
2218 *       maximum alignments for metadata
2219 ****************************************************************************************************
2220 */
HwlComputeMaxMetaBaseAlignments() const2221 UINT_32 CiLib::HwlComputeMaxMetaBaseAlignments() const
2222 {
2223     UINT_32 maxBank = 1;
2224 
2225     for (UINT_32 i = 0; i < m_noOfMacroEntries; i++)
2226     {
2227         if (SupportDccAndTcCompatibility() && IsMacroTiled(m_tileTable[i].mode))
2228         {
2229             maxBank = Max(maxBank, m_macroTileTable[i].banks);
2230         }
2231     }
2232 
2233     return SiLib::HwlComputeMaxMetaBaseAlignments() * maxBank;
2234 }
2235 
2236 /**
2237 ****************************************************************************************************
2238 *   CiLib::DepthStencilTileCfgMatch
2239 *
2240 *   @brief
2241 *       Try to find a tile index for stencil which makes its tile config parameters matches to depth
2242 *   @return
2243 *       TRUE if such tile index for stencil can be found
2244 ****************************************************************************************************
2245 */
DepthStencilTileCfgMatch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2246 BOOL_32 CiLib::DepthStencilTileCfgMatch(
2247     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,    ///< [in] input structure
2248     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [out] output structure
2249     ) const
2250 {
2251     BOOL_32 depthStencil2DTileConfigMatch = FALSE;
2252 
2253     for (INT_32 stencilTileIndex = MinDepth2DThinIndex;
2254          stencilTileIndex <= MaxDepth2DThinIndex;
2255          stencilTileIndex++)
2256     {
2257         ADDR_TILEINFO tileInfo = {0};
2258         INT_32 stencilMacroIndex = HwlComputeMacroModeIndex(stencilTileIndex,
2259                                                             pIn->flags,
2260                                                             8,
2261                                                             pIn->numSamples,
2262                                                             &tileInfo);
2263 
2264         if (stencilMacroIndex != TileIndexNoMacroIndex)
2265         {
2266             if ((m_macroTileTable[stencilMacroIndex].banks ==
2267                  m_macroTileTable[pOut->macroModeIndex].banks) &&
2268                 (m_macroTileTable[stencilMacroIndex].bankWidth ==
2269                  m_macroTileTable[pOut->macroModeIndex].bankWidth) &&
2270                 (m_macroTileTable[stencilMacroIndex].bankHeight ==
2271                  m_macroTileTable[pOut->macroModeIndex].bankHeight) &&
2272                 (m_macroTileTable[stencilMacroIndex].macroAspectRatio ==
2273                  m_macroTileTable[pOut->macroModeIndex].macroAspectRatio) &&
2274                 (m_macroTileTable[stencilMacroIndex].pipeConfig ==
2275                  m_macroTileTable[pOut->macroModeIndex].pipeConfig))
2276             {
2277                 if ((pOut->tcCompatible == FALSE) ||
2278                     (tileInfo.tileSplitBytes >= MicroTileWidth * MicroTileHeight * pIn->numSamples))
2279                 {
2280                     depthStencil2DTileConfigMatch = TRUE;
2281                     pOut->stencilTileIdx = stencilTileIndex;
2282                     break;
2283                 }
2284             }
2285         }
2286         else
2287         {
2288             ADDR_ASSERT_ALWAYS();
2289         }
2290     }
2291 
2292     return depthStencil2DTileConfigMatch;
2293 }
2294 
2295 /**
2296 ****************************************************************************************************
2297 *   CiLib::DepthStencilTileCfgMatch
2298 *
2299 *   @brief
2300 *       Check if tc compatibility is available
2301 *   @return
2302 *       If tc compatibility is not available
2303 ****************************************************************************************************
2304 */
CheckTcCompatibility(const ADDR_TILEINFO * pTileInfo,UINT_32 bpp,AddrTileMode tileMode,AddrTileType tileType,const ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2305 BOOL_32 CiLib::CheckTcCompatibility(
2306     const ADDR_TILEINFO*                    pTileInfo,    ///< [in] input tile info
2307     UINT_32                                 bpp,          ///< [in] Bits per pixel
2308     AddrTileMode                            tileMode,     ///< [in] input tile mode
2309     AddrTileType                            tileType,     ///< [in] input tile type
2310     const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut          ///< [in] output surf info
2311     ) const
2312 {
2313     BOOL_32 tcCompatible = TRUE;
2314 
2315     if (IsMacroTiled(tileMode))
2316     {
2317         if (tileType != ADDR_DEPTH_SAMPLE_ORDER)
2318         {
2319             // Turn off tcCompatible for color surface if tileSplit happens. Depth/stencil
2320             // tileSplit case was handled at tileIndex selecting time.
2321             INT_32 tileIndex = pOut->tileIndex;
2322 
2323             if ((tileIndex == TileIndexInvalid) && (IsTileInfoAllZero(pTileInfo) == FALSE))
2324             {
2325                 tileIndex = HwlPostCheckTileIndex(pTileInfo, tileMode, tileType, tileIndex);
2326             }
2327 
2328             if (tileIndex != TileIndexInvalid)
2329             {
2330                 UINT_32 thickness = Thickness(tileMode);
2331 
2332                 ADDR_ASSERT(static_cast<UINT_32>(tileIndex) < TileTableSize);
2333                 // Non-depth entries store a split factor
2334                 UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes;
2335                 UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness);
2336                 UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x);
2337 
2338                 if (m_rowSize < colorTileSplit)
2339                 {
2340                     tcCompatible = FALSE;
2341                 }
2342             }
2343         }
2344     }
2345     else
2346     {
2347         // Client should not enable tc compatible for linear and 1D tile modes.
2348         tcCompatible = FALSE;
2349     }
2350 
2351     return tcCompatible;
2352 }
2353 
2354 } // V1
2355 } // Addr
2356