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