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