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