1 /*
2  * Copyright © 2007-2019 Advanced Micro Devices, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
17  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20  * USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  */
26 
27 /**
28 ****************************************************************************************************
29 * @file  siaddrlib.cpp
30 * @brief Contains the implementation for the SiLib class.
31 ****************************************************************************************************
32 */
33 
34 #include "siaddrlib.h"
35 #include "si_gb_reg.h"
36 
37 #include "amdgpu_asic_addr.h"
38 
39 ////////////////////////////////////////////////////////////////////////////////////////////////////
40 ////////////////////////////////////////////////////////////////////////////////////////////////////
41 namespace Addr
42 {
43 
44 /**
45 ****************************************************************************************************
46 *   SiHwlInit
47 *
48 *   @brief
49 *       Creates an SiLib object.
50 *
51 *   @return
52 *       Returns an SiLib object pointer.
53 ****************************************************************************************************
54 */
SiHwlInit(const Client * pClient)55 Lib* SiHwlInit(const Client* pClient)
56 {
57     return V1::SiLib::CreateObj(pClient);
58 }
59 
60 namespace V1
61 {
62 
63 // We don't support MSAA for equation
64 const BOOL_32 SiLib::m_EquationSupport[SiLib::TileTableSize][SiLib::MaxNumElementBytes] =
65 {
66     {TRUE,  TRUE,  TRUE,  FALSE, FALSE},    //  0, non-AA compressed depth or any stencil
67     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  1, 2xAA/4xAA compressed depth with or without stencil
68     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  2, 8xAA compressed depth with or without stencil
69     {FALSE, TRUE,  FALSE, FALSE, FALSE},    //  3, 16 bpp depth PRT (non-MSAA), don't support uncompressed depth
70     {TRUE,  TRUE,  TRUE,  FALSE, FALSE},    //  4, 1D depth
71     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  5, 16 bpp depth PRT (4xMSAA)
72     {FALSE, FALSE, TRUE,  FALSE, FALSE},    //  6, 32 bpp depth PRT (non-MSAA)
73     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  7, 32 bpp depth PRT (4xMSAA)
74     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    //  8, Linear
75     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    //  9, 1D display
76     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 10, 8 bpp color (displayable)
77     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 11, 16 bpp color (displayable)
78     {FALSE, FALSE, TRUE,  TRUE,  FALSE},    // 12, 32/64 bpp color (displayable)
79     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    // 13, 1D thin
80     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 14, 8 bpp color non-displayable
81     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 15, 16 bpp color non-displayable
82     {FALSE, FALSE, TRUE,  FALSE, FALSE},    // 16, 32 bpp color non-displayable
83     {FALSE, FALSE, FALSE, TRUE,  TRUE },    // 17, 64/128 bpp color non-displayable
84     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    // 18, 1D THICK
85     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 19, 2D XTHICK
86     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 20, 2D THICK
87     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 21, 8 bpp 2D PRTs (non-MSAA)
88     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 22, 16 bpp 2D PRTs (non-MSAA)
89     {FALSE, FALSE, TRUE,  FALSE, FALSE},    // 23, 32 bpp 2D PRTs (non-MSAA)
90     {FALSE, FALSE, FALSE, TRUE,  FALSE},    // 24, 64 bpp 2D PRTs (non-MSAA)
91     {FALSE, FALSE, FALSE, FALSE, TRUE },    // 25, 128bpp 2D PRTs (non-MSAA)
92     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 26, none
93     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 27, none
94     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 28, none
95     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 29, none
96     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 30, 64bpp 2D PRTs (4xMSAA)
97     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 31, none
98 };
99 
100 /**
101 ****************************************************************************************************
102 *   SiLib::SiLib
103 *
104 *   @brief
105 *       Constructor
106 *
107 ****************************************************************************************************
108 */
SiLib(const Client * pClient)109 SiLib::SiLib(const Client* pClient)
110     :
111     EgBasedLib(pClient),
112     m_noOfEntries(0),
113     m_numEquations(0)
114 {
115     memset(&m_settings, 0, sizeof(m_settings));
116 }
117 
118 /**
119 ****************************************************************************************************
120 *   SiLib::~SiLib
121 *
122 *   @brief
123 *       Destructor
124 ****************************************************************************************************
125 */
~SiLib()126 SiLib::~SiLib()
127 {
128 }
129 
130 /**
131 ****************************************************************************************************
132 *   SiLib::HwlGetPipes
133 *
134 *   @brief
135 *       Get number pipes
136 *   @return
137 *       num pipes
138 ****************************************************************************************************
139 */
HwlGetPipes(const ADDR_TILEINFO * pTileInfo) const140 UINT_32 SiLib::HwlGetPipes(
141     const ADDR_TILEINFO* pTileInfo    ///< [in] Tile info
142     ) const
143 {
144     UINT_32 numPipes;
145 
146     if (pTileInfo)
147     {
148         numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
149     }
150     else
151     {
152         ADDR_ASSERT_ALWAYS();
153         numPipes = m_pipes; // Suppose we should still have a global pipes
154     }
155 
156     return numPipes;
157 }
158 
159 /**
160 ****************************************************************************************************
161 *   SiLib::GetPipePerSurf
162 *   @brief
163 *       get pipe num base on inputing tileinfo->pipeconfig
164 *   @return
165 *       pipe number
166 ****************************************************************************************************
167 */
GetPipePerSurf(AddrPipeCfg pipeConfig) const168 UINT_32 SiLib::GetPipePerSurf(
169     AddrPipeCfg pipeConfig   ///< [in] pipe config
170     ) const
171 {
172     UINT_32 numPipes = 0;
173 
174     switch (pipeConfig)
175     {
176         case ADDR_PIPECFG_P2:
177             numPipes = 2;
178             break;
179         case ADDR_PIPECFG_P4_8x16:
180         case ADDR_PIPECFG_P4_16x16:
181         case ADDR_PIPECFG_P4_16x32:
182         case ADDR_PIPECFG_P4_32x32:
183             numPipes = 4;
184             break;
185         case ADDR_PIPECFG_P8_16x16_8x16:
186         case ADDR_PIPECFG_P8_16x32_8x16:
187         case ADDR_PIPECFG_P8_32x32_8x16:
188         case ADDR_PIPECFG_P8_16x32_16x16:
189         case ADDR_PIPECFG_P8_32x32_16x16:
190         case ADDR_PIPECFG_P8_32x32_16x32:
191         case ADDR_PIPECFG_P8_32x64_32x32:
192             numPipes = 8;
193             break;
194         case ADDR_PIPECFG_P16_32x32_8x16:
195         case ADDR_PIPECFG_P16_32x32_16x16:
196             numPipes = 16;
197             break;
198         default:
199             ADDR_ASSERT(!"Invalid pipe config");
200             numPipes = m_pipes;
201     }
202     return numPipes;
203 }
204 
205 /**
206 ****************************************************************************************************
207 *   SiLib::ComputeBankEquation
208 *
209 *   @brief
210 *       Compute bank equation
211 *
212 *   @return
213 *       If equation can be computed
214 ****************************************************************************************************
215 */
ComputeBankEquation(UINT_32 log2BytesPP,UINT_32 threshX,UINT_32 threshY,ADDR_TILEINFO * pTileInfo,ADDR_EQUATION * pEquation) const216 ADDR_E_RETURNCODE SiLib::ComputeBankEquation(
217     UINT_32         log2BytesPP,    ///< [in] log2 of bytes per pixel
218     UINT_32         threshX,        ///< [in] threshold for x channel
219     UINT_32         threshY,        ///< [in] threshold for y channel
220     ADDR_TILEINFO*  pTileInfo,      ///< [in] tile info
221     ADDR_EQUATION*  pEquation       ///< [out] bank equation
222     ) const
223 {
224     ADDR_E_RETURNCODE retCode = ADDR_OK;
225 
226     UINT_32 pipes = HwlGetPipes(pTileInfo);
227     UINT_32 bankXStart = 3 + Log2(pipes) + Log2(pTileInfo->bankWidth);
228     UINT_32 bankYStart = 3 + Log2(pTileInfo->bankHeight);
229 
230     ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, log2BytesPP + bankXStart);
231     ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, log2BytesPP + bankXStart + 1);
232     ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, log2BytesPP + bankXStart + 2);
233     ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, log2BytesPP + bankXStart + 3);
234     ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, bankYStart);
235     ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, bankYStart + 1);
236     ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, bankYStart + 2);
237     ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, bankYStart + 3);
238 
239     x3.value = (threshX > bankXStart)     ? x3.value : 0;
240     x4.value = (threshX > bankXStart + 1) ? x4.value : 0;
241     x5.value = (threshX > bankXStart + 2) ? x5.value : 0;
242     x6.value = (threshX > bankXStart + 3) ? x6.value : 0;
243     y3.value = (threshY > bankYStart)     ? y3.value : 0;
244     y4.value = (threshY > bankYStart + 1) ? y4.value : 0;
245     y5.value = (threshY > bankYStart + 2) ? y5.value : 0;
246     y6.value = (threshY > bankYStart + 3) ? y6.value : 0;
247 
248     switch (pTileInfo->banks)
249     {
250         case 16:
251             if (pTileInfo->macroAspectRatio == 1)
252             {
253                 pEquation->addr[0] = y6;
254                 pEquation->xor1[0] = x3;
255                 pEquation->addr[1] = y5;
256                 pEquation->xor1[1] = y6;
257                 pEquation->xor2[1] = x4;
258                 pEquation->addr[2] = y4;
259                 pEquation->xor1[2] = x5;
260                 pEquation->addr[3] = y3;
261                 pEquation->xor1[3] = x6;
262             }
263             else if (pTileInfo->macroAspectRatio == 2)
264             {
265                 pEquation->addr[0] = x3;
266                 pEquation->xor1[0] = y6;
267                 pEquation->addr[1] = y5;
268                 pEquation->xor1[1] = y6;
269                 pEquation->xor2[1] = x4;
270                 pEquation->addr[2] = y4;
271                 pEquation->xor1[2] = x5;
272                 pEquation->addr[3] = y3;
273                 pEquation->xor1[3] = x6;
274             }
275             else if (pTileInfo->macroAspectRatio == 4)
276             {
277                 pEquation->addr[0] = x3;
278                 pEquation->xor1[0] = y6;
279                 pEquation->addr[1] = x4;
280                 pEquation->xor1[1] = y5;
281                 pEquation->xor2[1] = y6;
282                 pEquation->addr[2] = y4;
283                 pEquation->xor1[2] = x5;
284                 pEquation->addr[3] = y3;
285                 pEquation->xor1[3] = x6;
286             }
287             else if (pTileInfo->macroAspectRatio == 8)
288             {
289                 pEquation->addr[0] = x3;
290                 pEquation->xor1[0] = y6;
291                 pEquation->addr[1] = x4;
292                 pEquation->xor1[1] = y5;
293                 pEquation->xor2[1] = y6;
294                 pEquation->addr[2] = x5;
295                 pEquation->xor1[2] = y4;
296                 pEquation->addr[3] = y3;
297                 pEquation->xor1[3] = x6;
298             }
299             else
300             {
301                 ADDR_ASSERT_ALWAYS();
302             }
303             pEquation->numBits = 4;
304             break;
305         case 8:
306             if (pTileInfo->macroAspectRatio == 1)
307             {
308                 pEquation->addr[0] = y5;
309                 pEquation->xor1[0] = x3;
310                 pEquation->addr[1] = y4;
311                 pEquation->xor1[1] = y5;
312                 pEquation->xor2[1] = x4;
313                 pEquation->addr[2] = y3;
314                 pEquation->xor1[2] = x5;
315             }
316             else if (pTileInfo->macroAspectRatio == 2)
317             {
318                 pEquation->addr[0] = x3;
319                 pEquation->xor1[0] = y5;
320                 pEquation->addr[1] = y4;
321                 pEquation->xor1[1] = y5;
322                 pEquation->xor2[1] = x4;
323                 pEquation->addr[2] = y3;
324                 pEquation->xor1[2] = x5;
325             }
326             else if (pTileInfo->macroAspectRatio == 4)
327             {
328                 pEquation->addr[0] = x3;
329                 pEquation->xor1[0] = y5;
330                 pEquation->addr[1] = x4;
331                 pEquation->xor1[1] = y4;
332                 pEquation->xor2[1] = y5;
333                 pEquation->addr[2] = y3;
334                 pEquation->xor1[2] = x5;
335             }
336             else
337             {
338                 ADDR_ASSERT_ALWAYS();
339             }
340             pEquation->numBits = 3;
341             break;
342         case 4:
343             if (pTileInfo->macroAspectRatio == 1)
344             {
345                 pEquation->addr[0] = y4;
346                 pEquation->xor1[0] = x3;
347                 pEquation->addr[1] = y3;
348                 pEquation->xor1[1] = x4;
349             }
350             else if (pTileInfo->macroAspectRatio == 2)
351             {
352                 pEquation->addr[0] = x3;
353                 pEquation->xor1[0] = y4;
354                 pEquation->addr[1] = y3;
355                 pEquation->xor1[1] = x4;
356             }
357             else
358             {
359                 pEquation->addr[0] = x3;
360                 pEquation->xor1[0] = y4;
361                 pEquation->addr[1] = x4;
362                 pEquation->xor1[1] = y3;
363             }
364             pEquation->numBits = 2;
365             break;
366         case 2:
367             if (pTileInfo->macroAspectRatio == 1)
368             {
369                 pEquation->addr[0] = y3;
370                 pEquation->xor1[0] = x3;
371             }
372             else
373             {
374                 pEquation->addr[0] = x3;
375                 pEquation->xor1[0] = y3;
376             }
377             pEquation->numBits = 1;
378             break;
379         default:
380             pEquation->numBits = 0;
381             retCode = ADDR_NOTSUPPORTED;
382             ADDR_ASSERT_ALWAYS();
383             break;
384     }
385 
386     for (UINT_32 i = 0; i < pEquation->numBits; i++)
387     {
388         if (pEquation->addr[i].value == 0)
389         {
390             if (pEquation->xor1[i].value == 0)
391             {
392                 // 00X -> X00
393                 pEquation->addr[i].value = pEquation->xor2[i].value;
394                 pEquation->xor2[i].value = 0;
395             }
396             else
397             {
398                 pEquation->addr[i].value = pEquation->xor1[i].value;
399 
400                 if (pEquation->xor2[i].value != 0)
401                 {
402                     // 0XY -> XY0
403                     pEquation->xor1[i].value = pEquation->xor2[i].value;
404                     pEquation->xor2[i].value = 0;
405                 }
406                 else
407                 {
408                     // 0X0 -> X00
409                     pEquation->xor1[i].value = 0;
410                 }
411             }
412         }
413         else if (pEquation->xor1[i].value == 0)
414         {
415             if (pEquation->xor2[i].value != 0)
416             {
417                 // X0Y -> XY0
418                 pEquation->xor1[i].value = pEquation->xor2[i].value;
419                 pEquation->xor2[i].value = 0;
420             }
421         }
422     }
423 
424     if ((pTileInfo->bankWidth == 1) &&
425         ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
426          (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)))
427     {
428         retCode = ADDR_NOTSUPPORTED;
429     }
430 
431     return retCode;
432 }
433 
434 /**
435 ****************************************************************************************************
436 *   SiLib::ComputePipeEquation
437 *
438 *   @brief
439 *       Compute pipe equation
440 *
441 *   @return
442 *       If equation can be computed
443 ****************************************************************************************************
444 */
ComputePipeEquation(UINT_32 log2BytesPP,UINT_32 threshX,UINT_32 threshY,ADDR_TILEINFO * pTileInfo,ADDR_EQUATION * pEquation) const445 ADDR_E_RETURNCODE SiLib::ComputePipeEquation(
446     UINT_32        log2BytesPP, ///< [in] Log2 of bytes per pixel
447     UINT_32        threshX,     ///< [in] Threshold for X channel
448     UINT_32        threshY,     ///< [in] Threshold for Y channel
449     ADDR_TILEINFO* pTileInfo,   ///< [in] Tile info
450     ADDR_EQUATION* pEquation    ///< [out] Pipe configure
451     ) const
452 {
453     ADDR_E_RETURNCODE retCode = ADDR_OK;
454 
455     ADDR_CHANNEL_SETTING* pAddr = pEquation->addr;
456     ADDR_CHANNEL_SETTING* pXor1 = pEquation->xor1;
457     ADDR_CHANNEL_SETTING* pXor2 = pEquation->xor2;
458 
459     ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, 3 + log2BytesPP);
460     ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, 4 + log2BytesPP);
461     ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, 5 + log2BytesPP);
462     ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, 6 + log2BytesPP);
463     ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, 3);
464     ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, 4);
465     ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, 5);
466     ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, 6);
467 
468     x3.value = (threshX > 3) ? x3.value : 0;
469     x4.value = (threshX > 4) ? x4.value : 0;
470     x5.value = (threshX > 5) ? x5.value : 0;
471     x6.value = (threshX > 6) ? x6.value : 0;
472     y3.value = (threshY > 3) ? y3.value : 0;
473     y4.value = (threshY > 4) ? y4.value : 0;
474     y5.value = (threshY > 5) ? y5.value : 0;
475     y6.value = (threshY > 6) ? y6.value : 0;
476 
477     switch (pTileInfo->pipeConfig)
478     {
479         case ADDR_PIPECFG_P2:
480             pAddr[0] = x3;
481             pXor1[0] = y3;
482             pEquation->numBits = 1;
483             break;
484         case ADDR_PIPECFG_P4_8x16:
485             pAddr[0] = x4;
486             pXor1[0] = y3;
487             pAddr[1] = x3;
488             pXor1[1] = y4;
489             pEquation->numBits = 2;
490             break;
491         case ADDR_PIPECFG_P4_16x16:
492             pAddr[0] = x3;
493             pXor1[0] = y3;
494             pXor2[0] = x4;
495             pAddr[1] = x4;
496             pXor1[1] = y4;
497             pEquation->numBits = 2;
498             break;
499         case ADDR_PIPECFG_P4_16x32:
500             pAddr[0] = x3;
501             pXor1[0] = y3;
502             pXor2[0] = x4;
503             pAddr[1] = x4;
504             pXor1[1] = y5;
505             pEquation->numBits = 2;
506             break;
507         case ADDR_PIPECFG_P4_32x32:
508             pAddr[0] = x3;
509             pXor1[0] = y3;
510             pXor2[0] = x5;
511             pAddr[1] = x5;
512             pXor1[1] = y5;
513             pEquation->numBits = 2;
514             break;
515         case ADDR_PIPECFG_P8_16x16_8x16:
516             pAddr[0] = x4;
517             pXor1[0] = y3;
518             pXor2[0] = x5;
519             pAddr[1] = x3;
520             pXor1[1] = y5;
521             pEquation->numBits = 3;
522             break;
523         case ADDR_PIPECFG_P8_16x32_8x16:
524             pAddr[0] = x4;
525             pXor1[0] = y3;
526             pXor2[0] = x5;
527             pAddr[1] = x3;
528             pXor1[1] = y4;
529             pAddr[2] = x4;
530             pXor1[2] = y5;
531             pEquation->numBits = 3;
532             break;
533         case ADDR_PIPECFG_P8_16x32_16x16:
534             pAddr[0] = x3;
535             pXor1[0] = y3;
536             pXor2[0] = x4;
537             pAddr[1] = x5;
538             pXor1[1] = y4;
539             pAddr[2] = x4;
540             pXor1[2] = y5;
541             pEquation->numBits = 3;
542             break;
543         case ADDR_PIPECFG_P8_32x32_8x16:
544             pAddr[0] = x4;
545             pXor1[0] = y3;
546             pXor2[0] = x5;
547             pAddr[1] = x3;
548             pXor1[1] = y4;
549             pAddr[2] = x5;
550             pXor1[2] = y5;
551             pEquation->numBits = 3;
552             break;
553         case ADDR_PIPECFG_P8_32x32_16x16:
554             pAddr[0] = x3;
555             pXor1[0] = y3;
556             pXor2[0] = x4;
557             pAddr[1] = x4;
558             pXor1[1] = y4;
559             pAddr[2] = x5;
560             pXor1[2] = y5;
561             pEquation->numBits = 3;
562             break;
563         case ADDR_PIPECFG_P8_32x32_16x32:
564             pAddr[0] = x3;
565             pXor1[0] = y3;
566             pXor2[0] = x4;
567             pAddr[1] = x4;
568             pXor1[1] = y6;
569             pAddr[2] = x5;
570             pXor1[2] = y5;
571             pEquation->numBits = 3;
572             break;
573         case ADDR_PIPECFG_P8_32x64_32x32:
574             pAddr[0] = x3;
575             pXor1[0] = y3;
576             pXor2[0] = x5;
577             pAddr[1] = x6;
578             pXor1[1] = y5;
579             pAddr[2] = x5;
580             pXor1[2] = y6;
581             pEquation->numBits = 3;
582             break;
583         case ADDR_PIPECFG_P16_32x32_8x16:
584             pAddr[0] = x4;
585             pXor1[0] = y3;
586             pAddr[1] = x3;
587             pXor1[1] = y4;
588             pAddr[2] = x5;
589             pXor1[2] = y6;
590             pAddr[3] = x6;
591             pXor1[3] = y5;
592             pEquation->numBits = 4;
593             break;
594         case ADDR_PIPECFG_P16_32x32_16x16:
595             pAddr[0] = x3;
596             pXor1[0] = y3;
597             pXor2[0] = x4;
598             pAddr[1] = x4;
599             pXor1[1] = y4;
600             pAddr[2] = x5;
601             pXor1[2] = y6;
602             pAddr[3] = x6;
603             pXor1[3] = y5;
604             pEquation->numBits = 4;
605             break;
606         default:
607             ADDR_UNHANDLED_CASE();
608             pEquation->numBits = 0;
609             retCode = ADDR_NOTSUPPORTED;
610             break;
611     }
612 
613     if (m_settings.isVegaM && (pEquation->numBits == 4))
614     {
615         ADDR_CHANNEL_SETTING addeMsb = pAddr[0];
616         ADDR_CHANNEL_SETTING xor1Msb = pXor1[0];
617         ADDR_CHANNEL_SETTING xor2Msb = pXor2[0];
618 
619         pAddr[0] = pAddr[1];
620         pXor1[0] = pXor1[1];
621         pXor2[0] = pXor2[1];
622 
623         pAddr[1] = pAddr[2];
624         pXor1[1] = pXor1[2];
625         pXor2[1] = pXor2[2];
626 
627         pAddr[2] = pAddr[3];
628         pXor1[2] = pXor1[3];
629         pXor2[2] = pXor2[3];
630 
631         pAddr[3] = addeMsb;
632         pXor1[3] = xor1Msb;
633         pXor2[3] = xor2Msb;
634     }
635 
636     for (UINT_32 i = 0; i < pEquation->numBits; i++)
637     {
638         if (pAddr[i].value == 0)
639         {
640             if (pXor1[i].value == 0)
641             {
642                 pAddr[i].value = pXor2[i].value;
643             }
644             else
645             {
646                 pAddr[i].value = pXor1[i].value;
647                 pXor1[i].value = 0;
648             }
649         }
650     }
651 
652     return retCode;
653 }
654 
655 /**
656 ****************************************************************************************************
657 *   SiLib::ComputePipeFromCoord
658 *
659 *   @brief
660 *       Compute pipe number from coordinates
661 *   @return
662 *       Pipe number
663 ****************************************************************************************************
664 */
ComputePipeFromCoord(UINT_32 x,UINT_32 y,UINT_32 slice,AddrTileMode tileMode,UINT_32 pipeSwizzle,BOOL_32 ignoreSE,ADDR_TILEINFO * pTileInfo) const665 UINT_32 SiLib::ComputePipeFromCoord(
666     UINT_32         x,              ///< [in] x coordinate
667     UINT_32         y,              ///< [in] y coordinate
668     UINT_32         slice,          ///< [in] slice index
669     AddrTileMode    tileMode,       ///< [in] tile mode
670     UINT_32         pipeSwizzle,    ///< [in] pipe swizzle
671     BOOL_32         ignoreSE,       ///< [in] TRUE if shader engines are ignored
672     ADDR_TILEINFO*  pTileInfo       ///< [in] Tile info
673     ) const
674 {
675     UINT_32 pipe;
676     UINT_32 pipeBit0 = 0;
677     UINT_32 pipeBit1 = 0;
678     UINT_32 pipeBit2 = 0;
679     UINT_32 pipeBit3 = 0;
680     UINT_32 sliceRotation;
681     UINT_32 numPipes = 0;
682 
683     UINT_32 tx = x / MicroTileWidth;
684     UINT_32 ty = y / MicroTileHeight;
685     UINT_32 x3 = _BIT(tx,0);
686     UINT_32 x4 = _BIT(tx,1);
687     UINT_32 x5 = _BIT(tx,2);
688     UINT_32 x6 = _BIT(tx,3);
689     UINT_32 y3 = _BIT(ty,0);
690     UINT_32 y4 = _BIT(ty,1);
691     UINT_32 y5 = _BIT(ty,2);
692     UINT_32 y6 = _BIT(ty,3);
693 
694     switch (pTileInfo->pipeConfig)
695     {
696         case ADDR_PIPECFG_P2:
697             pipeBit0 = x3 ^ y3;
698             numPipes = 2;
699             break;
700         case ADDR_PIPECFG_P4_8x16:
701             pipeBit0 = x4 ^ y3;
702             pipeBit1 = x3 ^ y4;
703             numPipes = 4;
704             break;
705         case ADDR_PIPECFG_P4_16x16:
706             pipeBit0 = x3 ^ y3 ^ x4;
707             pipeBit1 = x4 ^ y4;
708             numPipes = 4;
709             break;
710         case ADDR_PIPECFG_P4_16x32:
711             pipeBit0 = x3 ^ y3 ^ x4;
712             pipeBit1 = x4 ^ y5;
713             numPipes = 4;
714             break;
715         case ADDR_PIPECFG_P4_32x32:
716             pipeBit0 = x3 ^ y3 ^ x5;
717             pipeBit1 = x5 ^ y5;
718             numPipes = 4;
719             break;
720         case ADDR_PIPECFG_P8_16x16_8x16:
721             pipeBit0 = x4 ^ y3 ^ x5;
722             pipeBit1 = x3 ^ y5;
723             numPipes = 8;
724             break;
725         case ADDR_PIPECFG_P8_16x32_8x16:
726             pipeBit0 = x4 ^ y3 ^ x5;
727             pipeBit1 = x3 ^ y4;
728             pipeBit2 = x4 ^ y5;
729             numPipes = 8;
730             break;
731         case ADDR_PIPECFG_P8_16x32_16x16:
732             pipeBit0 = x3 ^ y3 ^ x4;
733             pipeBit1 = x5 ^ y4;
734             pipeBit2 = x4 ^ y5;
735             numPipes = 8;
736             break;
737         case ADDR_PIPECFG_P8_32x32_8x16:
738             pipeBit0 = x4 ^ y3 ^ x5;
739             pipeBit1 = x3 ^ y4;
740             pipeBit2 = x5 ^ y5;
741             numPipes = 8;
742             break;
743         case ADDR_PIPECFG_P8_32x32_16x16:
744             pipeBit0 = x3 ^ y3 ^ x4;
745             pipeBit1 = x4 ^ y4;
746             pipeBit2 = x5 ^ y5;
747             numPipes = 8;
748             break;
749         case ADDR_PIPECFG_P8_32x32_16x32:
750             pipeBit0 = x3 ^ y3 ^ x4;
751             pipeBit1 = x4 ^ y6;
752             pipeBit2 = x5 ^ y5;
753             numPipes = 8;
754             break;
755         case ADDR_PIPECFG_P8_32x64_32x32:
756             pipeBit0 = x3 ^ y3 ^ x5;
757             pipeBit1 = x6 ^ y5;
758             pipeBit2 = x5 ^ y6;
759             numPipes = 8;
760             break;
761         case ADDR_PIPECFG_P16_32x32_8x16:
762             pipeBit0 = x4 ^ y3;
763             pipeBit1 = x3 ^ y4;
764             pipeBit2 = x5 ^ y6;
765             pipeBit3 = x6 ^ y5;
766             numPipes = 16;
767             break;
768         case ADDR_PIPECFG_P16_32x32_16x16:
769             pipeBit0 = x3 ^ y3 ^ x4;
770             pipeBit1 = x4 ^ y4;
771             pipeBit2 = x5 ^ y6;
772             pipeBit3 = x6 ^ y5;
773             numPipes = 16;
774             break;
775         default:
776             ADDR_UNHANDLED_CASE();
777             break;
778     }
779 
780     if (m_settings.isVegaM && (numPipes == 16))
781     {
782         UINT_32 pipeMsb = pipeBit0;
783         pipeBit0 = pipeBit1;
784         pipeBit1 = pipeBit2;
785         pipeBit2 = pipeBit3;
786         pipeBit3 = pipeMsb;
787     }
788 
789     pipe = pipeBit0 | (pipeBit1 << 1) | (pipeBit2 << 2) | (pipeBit3 << 3);
790 
791     UINT_32 microTileThickness = Thickness(tileMode);
792 
793     //
794     // Apply pipe rotation for the slice.
795     //
796     switch (tileMode)
797     {
798         case ADDR_TM_3D_TILED_THIN1:    //fall through thin
799         case ADDR_TM_3D_TILED_THICK:    //fall through thick
800         case ADDR_TM_3D_TILED_XTHICK:
801             sliceRotation =
802                 Max(1, static_cast<INT_32>(numPipes / 2) - 1) * (slice / microTileThickness);
803             break;
804         default:
805             sliceRotation = 0;
806             break;
807     }
808     pipeSwizzle += sliceRotation;
809     pipeSwizzle &= (numPipes - 1);
810 
811     pipe = pipe ^ pipeSwizzle;
812 
813     return pipe;
814 }
815 
816 /**
817 ****************************************************************************************************
818 *   SiLib::ComputeTileCoordFromPipeAndElemIdx
819 *
820 *   @brief
821 *       Compute (x,y) of a tile within a macro tile from address
822 *   @return
823 *       Pipe number
824 ****************************************************************************************************
825 */
ComputeTileCoordFromPipeAndElemIdx(UINT_32 elemIdx,UINT_32 pipe,AddrPipeCfg pipeCfg,UINT_32 pitchInMacroTile,UINT_32 x,UINT_32 y,UINT_32 * pX,UINT_32 * pY) const826 VOID SiLib::ComputeTileCoordFromPipeAndElemIdx(
827     UINT_32         elemIdx,          ///< [in] per pipe element index within a macro tile
828     UINT_32         pipe,             ///< [in] pipe index
829     AddrPipeCfg     pipeCfg,          ///< [in] pipe config
830     UINT_32         pitchInMacroTile, ///< [in] surface pitch in macro tile
831     UINT_32         x,                ///< [in] x coordinate of the (0,0) tile in a macro tile
832     UINT_32         y,                ///< [in] y coordinate of the (0,0) tile in a macro tile
833     UINT_32*        pX,               ///< [out] x coordinate
834     UINT_32*        pY                ///< [out] y coordinate
835     ) const
836 {
837     UINT_32 pipebit0 = _BIT(pipe,0);
838     UINT_32 pipebit1 = _BIT(pipe,1);
839     UINT_32 pipebit2 = _BIT(pipe,2);
840     UINT_32 pipebit3 = _BIT(pipe,3);
841     UINT_32 elemIdx0 = _BIT(elemIdx,0);
842     UINT_32 elemIdx1 = _BIT(elemIdx,1);
843     UINT_32 elemIdx2 = _BIT(elemIdx,2);
844     UINT_32 x3 = 0;
845     UINT_32 x4 = 0;
846     UINT_32 x5 = 0;
847     UINT_32 x6 = 0;
848     UINT_32 y3 = 0;
849     UINT_32 y4 = 0;
850     UINT_32 y5 = 0;
851     UINT_32 y6 = 0;
852 
853     switch(pipeCfg)
854     {
855         case ADDR_PIPECFG_P2:
856             x4 = elemIdx2;
857             y4 = elemIdx1 ^ x4;
858             y3 = elemIdx0 ^ x4;
859             x3 = pipebit0 ^ y3;
860             *pY = Bits2Number(2, y4, y3);
861             *pX = Bits2Number(2, x4, x3);
862             break;
863         case ADDR_PIPECFG_P4_8x16:
864             x4 = elemIdx1;
865             y4 = elemIdx0 ^ x4;
866             x3 = pipebit1 ^ y4;
867             y3 = pipebit0 ^ x4;
868             *pY = Bits2Number(2, y4, y3);
869             *pX = Bits2Number(2, x4, x3);
870             break;
871         case ADDR_PIPECFG_P4_16x16:
872             x4 = elemIdx1;
873             y3 = elemIdx0 ^ x4;
874             y4 = pipebit1 ^ x4;
875             x3 = pipebit0 ^ y3 ^ x4;
876             *pY = Bits2Number(2, y4, y3);
877             *pX = Bits2Number(2, x4, x3);
878             break;
879         case ADDR_PIPECFG_P4_16x32:
880             x3 = elemIdx0 ^ pipebit0;
881             y5 = _BIT(y,5);
882             x4 = pipebit1 ^ y5;
883             y3 = pipebit0 ^ x3 ^ x4;
884             y4 = elemIdx1 ^ x4;
885             *pY = Bits2Number(2, y4, y3);
886             *pX = Bits2Number(2, x4, x3);
887             break;
888         case ADDR_PIPECFG_P4_32x32:
889             x4 = elemIdx2;
890             y3 = elemIdx0 ^ x4;
891             y4 = elemIdx1 ^ x4;
892             if((pitchInMacroTile % 2) == 0)
893             {   //even
894                 y5 = _BIT(y,5);
895                 x5 = pipebit1 ^ y5;
896                 x3 = pipebit0 ^ y3 ^ x5;
897                 *pY = Bits2Number(2, y4, y3);
898                 *pX = Bits2Number(3, x5, x4, x3);
899             }
900             else
901             {   //odd
902                 x5 = _BIT(x,5);
903                 x3 = pipebit0 ^ y3 ^ x5;
904                 *pY = Bits2Number(2, y4, y3);
905                 *pX = Bits2Number(2, x4, x3);
906             }
907             break;
908         case ADDR_PIPECFG_P8_16x16_8x16:
909             x4 = elemIdx0;
910             y5 = _BIT(y,5);
911             x5 = _BIT(x,5);
912             x3 = pipebit1 ^ y5;
913             y4 = pipebit2 ^ x4;
914             y3 = pipebit0 ^ x5 ^ x4;
915             *pY = Bits2Number(2, y4, y3);
916             *pX = Bits2Number(2, x4, x3);
917             break;
918         case ADDR_PIPECFG_P8_16x32_8x16:
919             x3 = elemIdx0;
920             y4 = pipebit1 ^ x3;
921             y5 = _BIT(y,5);
922             x5 = _BIT(x,5);
923             x4 = pipebit2 ^ y5;
924             y3 = pipebit0 ^ x4 ^ x5;
925             *pY = Bits2Number(2, y4, y3);
926             *pX = Bits2Number(2, x4, x3);
927             break;
928         case ADDR_PIPECFG_P8_32x32_8x16:
929             x4 = elemIdx1;
930             y4 = elemIdx0 ^ x4;
931             x3 = pipebit1 ^ y4;
932             if((pitchInMacroTile % 2) == 0)
933             {  //even
934                 y5 = _BIT(y,5);
935                 x5 = _BIT(x,5);
936                 x5 = pipebit2 ^ y5;
937                 y3 = pipebit0 ^ x4 ^ x5;
938                 *pY = Bits2Number(2, y4, y3);
939                 *pX = Bits2Number(3, x5, x4, x3);
940             }
941             else
942             {  //odd
943                 x5 = _BIT(x,5);
944                 y3 = pipebit0 ^ x4 ^ x5;
945                 *pY = Bits2Number(2, y4, y3);
946                 *pX = Bits2Number(2, x4, x3);
947             }
948             break;
949         case ADDR_PIPECFG_P8_16x32_16x16:
950             x3 = elemIdx0;
951             x5 = _BIT(x,5);
952             y5 = _BIT(y,5);
953             x4 = pipebit2 ^ y5;
954             y4 = pipebit1 ^ x5;
955             y3 = pipebit0 ^ x3 ^ x4;
956             *pY = Bits2Number(2, y4, y3);
957             *pX = Bits2Number(2, x4, x3);
958             break;
959         case ADDR_PIPECFG_P8_32x32_16x16:
960             x4 = elemIdx1;
961             y3 = elemIdx0 ^ x4;
962             x3 = y3^x4^pipebit0;
963             y4 = pipebit1 ^ x4;
964             if((pitchInMacroTile % 2) == 0)
965             {   //even
966                 y5 = _BIT(y,5);
967                 x5 = pipebit2 ^ y5;
968                 *pY = Bits2Number(2, y4, y3);
969                 *pX = Bits2Number(3, x5, x4, x3);
970             }
971             else
972             {   //odd
973                 *pY = Bits2Number(2, y4, y3);
974                 *pX = Bits2Number(2, x4, x3);
975             }
976             break;
977         case ADDR_PIPECFG_P8_32x32_16x32:
978             if((pitchInMacroTile % 2) == 0)
979             {   //even
980                 y5 = _BIT(y,5);
981                 y6 = _BIT(y,6);
982                 x4 = pipebit1 ^ y6;
983                 y3 = elemIdx0 ^ x4;
984                 y4 = elemIdx1 ^ x4;
985                 x3 = pipebit0 ^ y3 ^ x4;
986                 x5 = pipebit2 ^ y5;
987                 *pY = Bits2Number(2, y4, y3);
988                 *pX = Bits2Number(3, x5, x4, x3);
989             }
990             else
991             {   //odd
992                 y6 = _BIT(y,6);
993                 x4 = pipebit1 ^ y6;
994                 y3 = elemIdx0 ^ x4;
995                 y4 = elemIdx1 ^ x4;
996                 x3 = pipebit0 ^ y3 ^ x4;
997                 *pY = Bits2Number(2, y4, y3);
998                 *pX = Bits2Number(2, x4, x3);
999             }
1000             break;
1001         case ADDR_PIPECFG_P8_32x64_32x32:
1002             x4 = elemIdx2;
1003             y3 = elemIdx0 ^ x4;
1004             y4 = elemIdx1 ^ x4;
1005             if((pitchInMacroTile % 4) == 0)
1006             {   //multiple of 4
1007                 y5 = _BIT(y,5);
1008                 y6 = _BIT(y,6);
1009                 x5 = pipebit2 ^ y6;
1010                 x6 = pipebit1 ^ y5;
1011                 x3 = pipebit0 ^ y3 ^ x5;
1012                 *pY = Bits2Number(2, y4, y3);
1013                 *pX = Bits2Number(4, x6, x5, x4, x3);
1014             }
1015             else
1016             {
1017                 y6 = _BIT(y,6);
1018                 x5 = pipebit2 ^ y6;
1019                 x3 = pipebit0 ^ y3 ^ x5;
1020                 *pY = Bits2Number(2, y4, y3);
1021                 *pX = Bits2Number(3, x5, x4, x3);
1022             }
1023             break;
1024         case ADDR_PIPECFG_P16_32x32_8x16:
1025             x4 = elemIdx1;
1026             y4 = elemIdx0 ^ x4;
1027             y3 = pipebit0 ^ x4;
1028             x3 = pipebit1 ^ y4;
1029             if((pitchInMacroTile % 4) == 0)
1030             {   //multiple of 4
1031                 y5 = _BIT(y,5);
1032                 y6 = _BIT(y,6);
1033                 x5 = pipebit2 ^ y6;
1034                 x6 = pipebit3 ^ y5;
1035                 *pY = Bits2Number(2, y4, y3);
1036                 *pX = Bits2Number(4, x6, x5,x4, x3);
1037             }
1038             else
1039             {
1040                 y6 = _BIT(y,6);
1041                 x5 = pipebit2 ^ y6;
1042                 *pY = Bits2Number(2, y4, y3);
1043                 *pX = Bits2Number(3, x5, x4, x3);
1044             }
1045             break;
1046         case ADDR_PIPECFG_P16_32x32_16x16:
1047             x4 = elemIdx1;
1048             y3 = elemIdx0 ^ x4;
1049             y4 = pipebit1 ^ x4;
1050             x3 = pipebit0 ^ y3 ^ x4;
1051             if((pitchInMacroTile % 4) == 0)
1052             {   //multiple of 4
1053                 y5 = _BIT(y,5);
1054                 y6 = _BIT(y,6);
1055                 x5 = pipebit2 ^ y6;
1056                 x6 = pipebit3 ^ y5;
1057                 *pY = Bits2Number(2, y4, y3);
1058                 *pX = Bits2Number(4, x6, x5, x4, x3);
1059             }
1060             else
1061             {
1062                 y6 = _BIT(y,6);
1063                 x5 = pipebit2 ^ y6;
1064                 *pY = Bits2Number(2, y4, y3);
1065                 *pX = Bits2Number(3, x5, x4, x3);
1066             }
1067             break;
1068         default:
1069             ADDR_UNHANDLED_CASE();
1070     }
1071 }
1072 
1073 /**
1074 ****************************************************************************************************
1075 *   SiLib::TileCoordToMaskElementIndex
1076 *
1077 *   @brief
1078 *       Compute element index from coordinates in tiles
1079 *   @return
1080 *       Element index
1081 ****************************************************************************************************
1082 */
TileCoordToMaskElementIndex(UINT_32 tx,UINT_32 ty,AddrPipeCfg pipeConfig,UINT_32 * macroShift,UINT_32 * elemIdxBits) const1083 UINT_32 SiLib::TileCoordToMaskElementIndex(
1084     UINT_32         tx,                 ///< [in] x coord, in Tiles
1085     UINT_32         ty,                 ///< [in] y coord, in Tiles
1086     AddrPipeCfg     pipeConfig,         ///< [in] pipe config
1087     UINT_32*        macroShift,         ///< [out] macro shift
1088     UINT_32*        elemIdxBits         ///< [out] tile offset bits
1089     ) const
1090 {
1091     UINT_32 elemIdx = 0;
1092     UINT_32 elemIdx0, elemIdx1, elemIdx2;
1093     UINT_32 tx0, tx1;
1094     UINT_32 ty0, ty1;
1095 
1096     tx0 = _BIT(tx,0);
1097     tx1 = _BIT(tx,1);
1098     ty0 = _BIT(ty,0);
1099     ty1 = _BIT(ty,1);
1100 
1101     switch(pipeConfig)
1102     {
1103         case ADDR_PIPECFG_P2:
1104             *macroShift = 3;
1105             *elemIdxBits =3;
1106             elemIdx2 = tx1;
1107             elemIdx1 = tx1 ^ ty1;
1108             elemIdx0 = tx1 ^ ty0;
1109             elemIdx = Bits2Number(3,elemIdx2,elemIdx1,elemIdx0);
1110             break;
1111         case ADDR_PIPECFG_P4_8x16:
1112             *macroShift = 2;
1113             *elemIdxBits =2;
1114             elemIdx1 = tx1;
1115             elemIdx0 = tx1 ^ ty1;
1116             elemIdx = Bits2Number(2,elemIdx1,elemIdx0);
1117             break;
1118         case ADDR_PIPECFG_P4_16x16:
1119             *macroShift = 2;
1120             *elemIdxBits =2;
1121             elemIdx0 = tx1^ty0;
1122             elemIdx1 = tx1;
1123             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1124             break;
1125         case ADDR_PIPECFG_P4_16x32:
1126             *macroShift = 2;
1127             *elemIdxBits =2;
1128             elemIdx0 = tx1^ty0;
1129             elemIdx1 = tx1^ty1;
1130             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1131             break;
1132         case ADDR_PIPECFG_P4_32x32:
1133             *macroShift = 2;
1134             *elemIdxBits =3;
1135             elemIdx0 = tx1^ty0;
1136             elemIdx1 = tx1^ty1;
1137             elemIdx2 = tx1;
1138             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
1139             break;
1140         case ADDR_PIPECFG_P8_16x16_8x16:
1141             *macroShift = 1;
1142             *elemIdxBits =1;
1143             elemIdx0 = tx1;
1144             elemIdx = elemIdx0;
1145             break;
1146         case ADDR_PIPECFG_P8_16x32_8x16:
1147             *macroShift = 1;
1148             *elemIdxBits =1;
1149             elemIdx0 = tx0;
1150             elemIdx = elemIdx0;
1151             break;
1152         case ADDR_PIPECFG_P8_32x32_8x16:
1153             *macroShift = 1;
1154             *elemIdxBits =2;
1155             elemIdx1 = tx1;
1156             elemIdx0 = tx1^ty1;
1157             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1158             break;
1159         case ADDR_PIPECFG_P8_16x32_16x16:
1160             *macroShift = 1;
1161             *elemIdxBits =1;
1162             elemIdx0 = tx0;
1163             elemIdx = elemIdx0;
1164             break;
1165         case ADDR_PIPECFG_P8_32x32_16x16:
1166             *macroShift = 1;
1167             *elemIdxBits =2;
1168             elemIdx0 = tx1^ty0;
1169             elemIdx1 = tx1;
1170             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1171             break;
1172         case ADDR_PIPECFG_P8_32x32_16x32:
1173             *macroShift = 1;
1174             *elemIdxBits =2;
1175             elemIdx0 =  tx1^ty0;
1176             elemIdx1 = tx1^ty1;
1177             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1178             break;
1179         case ADDR_PIPECFG_P8_32x64_32x32:
1180             *macroShift = 1;
1181             *elemIdxBits =3;
1182             elemIdx0 = tx1^ty0;
1183             elemIdx1 = tx1^ty1;
1184             elemIdx2 = tx1;
1185             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
1186             break;
1187         case ADDR_PIPECFG_P16_32x32_8x16:
1188             *macroShift = 0;
1189             *elemIdxBits =2;
1190             elemIdx0 = tx1^ty1;
1191             elemIdx1 = tx1;
1192             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1193             break;
1194         case ADDR_PIPECFG_P16_32x32_16x16:
1195             *macroShift = 0;
1196             *elemIdxBits =2;
1197             elemIdx0 = tx1^ty0;
1198             elemIdx1 = tx1;
1199             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1200             break;
1201         default:
1202             ADDR_UNHANDLED_CASE();
1203             break;
1204     }
1205 
1206     return elemIdx;
1207 }
1208 
1209 /**
1210 ****************************************************************************************************
1211 *   SiLib::HwlComputeTileDataWidthAndHeightLinear
1212 *
1213 *   @brief
1214 *       Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1215 *
1216 *   @return
1217 *       N/A
1218 *
1219 *   @note
1220 *       MacroWidth and macroHeight are measured in pixels
1221 ****************************************************************************************************
1222 */
HwlComputeTileDataWidthAndHeightLinear(UINT_32 * pMacroWidth,UINT_32 * pMacroHeight,UINT_32 bpp,ADDR_TILEINFO * pTileInfo) const1223 VOID SiLib::HwlComputeTileDataWidthAndHeightLinear(
1224     UINT_32*        pMacroWidth,     ///< [out] macro tile width
1225     UINT_32*        pMacroHeight,    ///< [out] macro tile height
1226     UINT_32         bpp,             ///< [in] bits per pixel
1227     ADDR_TILEINFO*  pTileInfo        ///< [in] tile info
1228     ) const
1229 {
1230     ADDR_ASSERT(pTileInfo != NULL);
1231     UINT_32 macroWidth;
1232     UINT_32 macroHeight;
1233 
1234     /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles
1235     /// but for P8_32x64_32x32, it must be padded out to 8 tiles
1236     /// Actually there are more pipe configs which need 8-tile padding but SI family
1237     /// has a bug which is fixed in CI family
1238     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) ||
1239         (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
1240         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x32_16x16))
1241     {
1242         macroWidth  = 8*MicroTileWidth;
1243         macroHeight = 8*MicroTileHeight;
1244     }
1245     else
1246     {
1247         macroWidth  = 4*MicroTileWidth;
1248         macroHeight = 4*MicroTileHeight;
1249     }
1250 
1251     *pMacroWidth    = macroWidth;
1252     *pMacroHeight   = macroHeight;
1253 }
1254 
1255 /**
1256 ****************************************************************************************************
1257 *   SiLib::HwlComputeHtileBytes
1258 *
1259 *   @brief
1260 *       Compute htile size in bytes
1261 *
1262 *   @return
1263 *       Htile size in bytes
1264 ****************************************************************************************************
1265 */
HwlComputeHtileBytes(UINT_32 pitch,UINT_32 height,UINT_32 bpp,BOOL_32 isLinear,UINT_32 numSlices,UINT_64 * pSliceBytes,UINT_32 baseAlign) const1266 UINT_64 SiLib::HwlComputeHtileBytes(
1267     UINT_32     pitch,          ///< [in] pitch
1268     UINT_32     height,         ///< [in] height
1269     UINT_32     bpp,            ///< [in] bits per pixel
1270     BOOL_32     isLinear,       ///< [in] if it is linear mode
1271     UINT_32     numSlices,      ///< [in] number of slices
1272     UINT_64*    pSliceBytes,    ///< [out] bytes per slice
1273     UINT_32     baseAlign       ///< [in] base alignments
1274     ) const
1275 {
1276     return ComputeHtileBytes(pitch, height, bpp, isLinear, numSlices, pSliceBytes, baseAlign);
1277 }
1278 
1279 /**
1280 ****************************************************************************************************
1281 *   SiLib::HwlComputeXmaskAddrFromCoord
1282 *
1283 *   @brief
1284 *       Compute address from coordinates for htile/cmask
1285 *   @return
1286 *       Byte address
1287 ****************************************************************************************************
1288 */
HwlComputeXmaskAddrFromCoord(UINT_32 pitch,UINT_32 height,UINT_32 x,UINT_32 y,UINT_32 slice,UINT_32 numSlices,UINT_32 factor,BOOL_32 isLinear,BOOL_32 isWidth8,BOOL_32 isHeight8,ADDR_TILEINFO * pTileInfo,UINT_32 * pBitPosition) const1289 UINT_64 SiLib::HwlComputeXmaskAddrFromCoord(
1290     UINT_32        pitch,          ///< [in] pitch
1291     UINT_32        height,         ///< [in] height
1292     UINT_32        x,              ///< [in] x coord
1293     UINT_32        y,              ///< [in] y coord
1294     UINT_32        slice,          ///< [in] slice/depth index
1295     UINT_32        numSlices,      ///< [in] number of slices
1296     UINT_32        factor,         ///< [in] factor that indicates cmask(2) or htile(1)
1297     BOOL_32        isLinear,       ///< [in] linear or tiled HTILE layout
1298     BOOL_32        isWidth8,       ///< [in] TRUE if width is 8, FALSE means 4. It's register value
1299     BOOL_32        isHeight8,      ///< [in] TRUE if width is 8, FALSE means 4. It's register value
1300     ADDR_TILEINFO* pTileInfo,      ///< [in] Tile info
1301     UINT_32*       pBitPosition    ///< [out] bit position inside a byte
1302     ) const
1303 {
1304     UINT_32 tx = x / MicroTileWidth;
1305     UINT_32 ty = y / MicroTileHeight;
1306     UINT_32 newPitch;
1307     UINT_32 newHeight;
1308     UINT_64 totalBytes;
1309     UINT_32 macroWidth;
1310     UINT_32 macroHeight;
1311     UINT_64 pSliceBytes;
1312     UINT_32 pBaseAlign;
1313     UINT_32 tileNumPerPipe;
1314     UINT_32 elemBits;
1315 
1316     if (factor == 2) //CMASK
1317     {
1318         ADDR_CMASK_FLAGS flags = {{0}};
1319 
1320         tileNumPerPipe = 256;
1321 
1322         ComputeCmaskInfo(flags,
1323                          pitch,
1324                          height,
1325                          numSlices,
1326                          isLinear,
1327                          pTileInfo,
1328                          &newPitch,
1329                          &newHeight,
1330                          &totalBytes,
1331                          &macroWidth,
1332                          &macroHeight);
1333         elemBits = CmaskElemBits;
1334     }
1335     else //HTile
1336     {
1337         ADDR_HTILE_FLAGS flags = {{0}};
1338 
1339         tileNumPerPipe = 512;
1340 
1341         ComputeHtileInfo(flags,
1342                          pitch,
1343                          height,
1344                          numSlices,
1345                          isLinear,
1346                          TRUE,
1347                          TRUE,
1348                          pTileInfo,
1349                          &newPitch,
1350                          &newHeight,
1351                          &totalBytes,
1352                          &macroWidth,
1353                          &macroHeight,
1354                          &pSliceBytes,
1355                          &pBaseAlign);
1356         elemBits = 32;
1357     }
1358 
1359     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
1360     const UINT_32 heightInTile = newHeight / MicroTileWidth;
1361     UINT_64 macroOffset; // Per pipe starting offset of the macro tile in which this tile lies.
1362     UINT_64 microNumber; // Per pipe starting offset of the macro tile in which this tile lies.
1363     UINT_32 microX;
1364     UINT_32 microY;
1365     UINT_64 microOffset;
1366     UINT_32 microShift;
1367     UINT_64 totalOffset;
1368     UINT_32 elemIdxBits;
1369     UINT_32 elemIdx =
1370         TileCoordToMaskElementIndex(tx, ty, pTileInfo->pipeConfig, &microShift, &elemIdxBits);
1371 
1372     UINT_32 numPipes = HwlGetPipes(pTileInfo);
1373 
1374     if (isLinear)
1375     {   //linear addressing
1376         // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full
1377         // slice memory foot print instead of divided by numPipes.
1378         microX = tx / 4; // Macro Tile is 4x4
1379         microY = ty / 4 ;
1380         microNumber = static_cast<UINT_64>(microX + microY * (pitchInTile / 4)) << microShift;
1381 
1382         UINT_32 sliceBits = pitchInTile * heightInTile;
1383 
1384         // do htile single slice alignment if the flag is true
1385         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
1386         {
1387             sliceBits = PowTwoAlign(sliceBits, BITS_TO_BYTES(HtileCacheBits) * numPipes / elemBits);
1388         }
1389         macroOffset = slice * (sliceBits / numPipes) * elemBits ;
1390     }
1391     else
1392     {   //tiled addressing
1393         const UINT_32 macroWidthInTile = macroWidth / MicroTileWidth; // Now in unit of Tiles
1394         const UINT_32 macroHeightInTile = macroHeight / MicroTileHeight;
1395         const UINT_32 pitchInCL = pitchInTile / macroWidthInTile;
1396         const UINT_32 heightInCL = heightInTile / macroHeightInTile;
1397 
1398         const UINT_32 macroX = x / macroWidth;
1399         const UINT_32 macroY = y / macroHeight;
1400         const UINT_32 macroNumber = macroX + macroY * pitchInCL + slice * pitchInCL * heightInCL;
1401 
1402         // Per pipe starting offset of the cache line in which this tile lies.
1403         microX = (x % macroWidth) / MicroTileWidth / 4; // Macro Tile is 4x4
1404         microY = (y % macroHeight) / MicroTileHeight / 4 ;
1405         microNumber = static_cast<UINT_64>(microX + microY * (macroWidth / MicroTileWidth / 4)) << microShift;
1406 
1407         macroOffset = macroNumber * tileNumPerPipe * elemBits;
1408     }
1409 
1410     if(elemIdxBits == microShift)
1411     {
1412         microNumber += elemIdx;
1413     }
1414     else
1415     {
1416         microNumber >>= elemIdxBits;
1417         microNumber <<= elemIdxBits;
1418         microNumber += elemIdx;
1419     }
1420 
1421     microOffset = elemBits * microNumber;
1422     totalOffset = microOffset + macroOffset;
1423 
1424     UINT_32 pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo);
1425     UINT_64 addrInBits = totalOffset % (m_pipeInterleaveBytes * 8) +
1426                    pipe * (m_pipeInterleaveBytes * 8) +
1427                    totalOffset / (m_pipeInterleaveBytes * 8) * (m_pipeInterleaveBytes * 8) * numPipes;
1428     *pBitPosition = static_cast<UINT_32>(addrInBits) % 8;
1429     UINT_64 addr = addrInBits / 8;
1430 
1431     return addr;
1432 }
1433 
1434 /**
1435 ****************************************************************************************************
1436 *   SiLib::HwlComputeXmaskCoordFromAddr
1437 *
1438 *   @brief
1439 *       Compute the coord from an address of a cmask/htile
1440 *
1441 *   @return
1442 *       N/A
1443 *
1444 *   @note
1445 *       This method is reused by htile, so rename to Xmask
1446 ****************************************************************************************************
1447 */
HwlComputeXmaskCoordFromAddr(UINT_64 addr,UINT_32 bitPosition,UINT_32 pitch,UINT_32 height,UINT_32 numSlices,UINT_32 factor,BOOL_32 isLinear,BOOL_32 isWidth8,BOOL_32 isHeight8,ADDR_TILEINFO * pTileInfo,UINT_32 * pX,UINT_32 * pY,UINT_32 * pSlice) const1448 VOID SiLib::HwlComputeXmaskCoordFromAddr(
1449     UINT_64         addr,           ///< [in] address
1450     UINT_32         bitPosition,    ///< [in] bitPosition in a byte
1451     UINT_32         pitch,          ///< [in] pitch
1452     UINT_32         height,         ///< [in] height
1453     UINT_32         numSlices,      ///< [in] number of slices
1454     UINT_32         factor,         ///< [in] factor that indicates cmask or htile
1455     BOOL_32         isLinear,       ///< [in] linear or tiled HTILE layout
1456     BOOL_32         isWidth8,       ///< [in] Not used by SI
1457     BOOL_32         isHeight8,      ///< [in] Not used by SI
1458     ADDR_TILEINFO*  pTileInfo,      ///< [in] Tile info
1459     UINT_32*        pX,             ///< [out] x coord
1460     UINT_32*        pY,             ///< [out] y coord
1461     UINT_32*        pSlice          ///< [out] slice index
1462     ) const
1463 {
1464     UINT_32 newPitch;
1465     UINT_32 newHeight;
1466     UINT_64 totalBytes;
1467     UINT_32 clWidth;
1468     UINT_32 clHeight;
1469     UINT_32 tileNumPerPipe;
1470     UINT_64 sliceBytes;
1471 
1472     *pX = 0;
1473     *pY = 0;
1474     *pSlice = 0;
1475 
1476     if (factor == 2) //CMASK
1477     {
1478         ADDR_CMASK_FLAGS flags = {{0}};
1479 
1480         tileNumPerPipe = 256;
1481 
1482         ComputeCmaskInfo(flags,
1483                          pitch,
1484                          height,
1485                          numSlices,
1486                          isLinear,
1487                          pTileInfo,
1488                          &newPitch,
1489                          &newHeight,
1490                          &totalBytes,
1491                          &clWidth,
1492                          &clHeight);
1493     }
1494     else //HTile
1495     {
1496         ADDR_HTILE_FLAGS flags = {{0}};
1497 
1498         tileNumPerPipe = 512;
1499 
1500         ComputeHtileInfo(flags,
1501                          pitch,
1502                          height,
1503                          numSlices,
1504                          isLinear,
1505                          TRUE,
1506                          TRUE,
1507                          pTileInfo,
1508                          &newPitch,
1509                          &newHeight,
1510                          &totalBytes,
1511                          &clWidth,
1512                          &clHeight,
1513                          &sliceBytes);
1514     }
1515 
1516     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
1517     const UINT_32 heightInTile = newHeight / MicroTileWidth;
1518     const UINT_32 pitchInMacroTile = pitchInTile / 4;
1519     UINT_32 macroShift;
1520     UINT_32 elemIdxBits;
1521     // get macroShift and elemIdxBits
1522     TileCoordToMaskElementIndex(0, 0, pTileInfo->pipeConfig, &macroShift, &elemIdxBits);
1523 
1524     const UINT_32 numPipes = HwlGetPipes(pTileInfo);
1525     const UINT_32 pipe = (UINT_32)((addr / m_pipeInterleaveBytes) % numPipes);
1526     // per pipe
1527     UINT_64 localOffset = (addr % m_pipeInterleaveBytes) +
1528         (addr / m_pipeInterleaveBytes / numPipes)* m_pipeInterleaveBytes;
1529 
1530     UINT_32 tileIndex;
1531     if (factor == 2) //CMASK
1532     {
1533         tileIndex = (UINT_32)(localOffset * 2 + (bitPosition != 0));
1534     }
1535     else
1536     {
1537         tileIndex = (UINT_32)(localOffset / 4);
1538     }
1539 
1540     UINT_32 macroOffset;
1541     if (isLinear)
1542     {
1543         UINT_32 sliceSizeInTile = pitchInTile * heightInTile;
1544 
1545         // do htile single slice alignment if the flag is true
1546         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
1547         {
1548             sliceSizeInTile = PowTwoAlign(sliceSizeInTile, static_cast<UINT_32>(sliceBytes) / 64);
1549         }
1550         *pSlice = tileIndex / (sliceSizeInTile / numPipes);
1551         macroOffset = tileIndex % (sliceSizeInTile / numPipes);
1552     }
1553     else
1554     {
1555         const UINT_32 clWidthInTile = clWidth / MicroTileWidth; // Now in unit of Tiles
1556         const UINT_32 clHeightInTile = clHeight / MicroTileHeight;
1557         const UINT_32 pitchInCL = pitchInTile / clWidthInTile;
1558         const UINT_32 heightInCL = heightInTile / clHeightInTile;
1559         const UINT_32 clIndex = tileIndex / tileNumPerPipe;
1560 
1561         UINT_32 clX = clIndex % pitchInCL;
1562         UINT_32 clY = (clIndex % (heightInCL * pitchInCL)) / pitchInCL;
1563 
1564         *pX = clX * clWidthInTile * MicroTileWidth;
1565         *pY = clY * clHeightInTile * MicroTileHeight;
1566         *pSlice = clIndex / (heightInCL * pitchInCL);
1567 
1568         macroOffset = tileIndex % tileNumPerPipe;
1569     }
1570 
1571     UINT_32 elemIdx = macroOffset & 7;
1572     macroOffset >>= elemIdxBits;
1573 
1574     if (elemIdxBits != macroShift)
1575     {
1576         macroOffset <<= (elemIdxBits - macroShift);
1577 
1578         UINT_32 pipebit1 = _BIT(pipe,1);
1579         UINT_32 pipebit2 = _BIT(pipe,2);
1580         UINT_32 pipebit3 = _BIT(pipe,3);
1581         if (pitchInMacroTile % 2)
1582         {   //odd
1583             switch (pTileInfo->pipeConfig)
1584             {
1585                 case ADDR_PIPECFG_P4_32x32:
1586                     macroOffset |= pipebit1;
1587                     break;
1588                 case ADDR_PIPECFG_P8_32x32_8x16:
1589                 case ADDR_PIPECFG_P8_32x32_16x16:
1590                 case ADDR_PIPECFG_P8_32x32_16x32:
1591                     macroOffset |= pipebit2;
1592                     break;
1593                 default:
1594                     break;
1595             }
1596 
1597         }
1598 
1599         if (pitchInMacroTile % 4)
1600         {
1601             if (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)
1602             {
1603                 macroOffset |= (pipebit1<<1);
1604             }
1605             if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
1606                 (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_16x16)
1607                )
1608             {
1609                 macroOffset |= (pipebit3<<1);
1610             }
1611         }
1612     }
1613 
1614     UINT_32 macroX;
1615     UINT_32 macroY;
1616 
1617     if (isLinear)
1618     {
1619         macroX = macroOffset % pitchInMacroTile;
1620         macroY = macroOffset / pitchInMacroTile;
1621     }
1622     else
1623     {
1624         const UINT_32 clWidthInMacroTile = clWidth / (MicroTileWidth * 4);
1625         macroX = macroOffset % clWidthInMacroTile;
1626         macroY = macroOffset / clWidthInMacroTile;
1627     }
1628 
1629     *pX += macroX * 4 * MicroTileWidth;
1630     *pY += macroY * 4 * MicroTileHeight;
1631 
1632     UINT_32 microX;
1633     UINT_32 microY;
1634     ComputeTileCoordFromPipeAndElemIdx(elemIdx, pipe, pTileInfo->pipeConfig, pitchInMacroTile,
1635                                        *pX, *pY, &microX, &microY);
1636 
1637     *pX += microX * MicroTileWidth;
1638     *pY += microY * MicroTileWidth;
1639 }
1640 
1641 /**
1642 ****************************************************************************************************
1643 *   SiLib::HwlGetPitchAlignmentLinear
1644 *   @brief
1645 *       Get pitch alignment
1646 *   @return
1647 *       pitch alignment
1648 ****************************************************************************************************
1649 */
HwlGetPitchAlignmentLinear(UINT_32 bpp,ADDR_SURFACE_FLAGS flags) const1650 UINT_32 SiLib::HwlGetPitchAlignmentLinear(
1651     UINT_32             bpp,    ///< [in] bits per pixel
1652     ADDR_SURFACE_FLAGS  flags   ///< [in] surface flags
1653     ) const
1654 {
1655     UINT_32 pitchAlign;
1656 
1657     // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment
1658     if (flags.interleaved)
1659     {
1660         pitchAlign = Max(64u, m_pipeInterleaveBytes / BITS_TO_BYTES(bpp));
1661 
1662     }
1663     else
1664     {
1665         pitchAlign = Max(8u, 64 / BITS_TO_BYTES(bpp));
1666     }
1667 
1668     return pitchAlign;
1669 }
1670 
1671 /**
1672 ****************************************************************************************************
1673 *   SiLib::HwlGetSizeAdjustmentLinear
1674 *
1675 *   @brief
1676 *       Adjust linear surface pitch and slice size
1677 *
1678 *   @return
1679 *       Logical slice size in bytes
1680 ****************************************************************************************************
1681 */
HwlGetSizeAdjustmentLinear(AddrTileMode tileMode,UINT_32 bpp,UINT_32 numSamples,UINT_32 baseAlign,UINT_32 pitchAlign,UINT_32 * pPitch,UINT_32 * pHeight,UINT_32 * pHeightAlign) const1682 UINT_64 SiLib::HwlGetSizeAdjustmentLinear(
1683     AddrTileMode        tileMode,       ///< [in] tile mode
1684     UINT_32             bpp,            ///< [in] bits per pixel
1685     UINT_32             numSamples,     ///< [in] number of samples
1686     UINT_32             baseAlign,      ///< [in] base alignment
1687     UINT_32             pitchAlign,     ///< [in] pitch alignment
1688     UINT_32*            pPitch,         ///< [in,out] pointer to pitch
1689     UINT_32*            pHeight,        ///< [in,out] pointer to height
1690     UINT_32*            pHeightAlign    ///< [in,out] pointer to height align
1691     ) const
1692 {
1693     UINT_64 sliceSize;
1694     if (tileMode == ADDR_TM_LINEAR_GENERAL)
1695     {
1696         sliceSize = BITS_TO_BYTES(static_cast<UINT_64>(*pPitch) * (*pHeight) * bpp * numSamples);
1697     }
1698     else
1699     {
1700         UINT_32 pitch   = *pPitch;
1701         UINT_32 height  = *pHeight;
1702 
1703         UINT_32 pixelsPerPipeInterleave = m_pipeInterleaveBytes / BITS_TO_BYTES(bpp);
1704         UINT_32 sliceAlignInPixel = pixelsPerPipeInterleave < 64 ? 64 : pixelsPerPipeInterleave;
1705 
1706         // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value)
1707         UINT_64 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
1708 
1709         while (pixelPerSlice % sliceAlignInPixel)
1710         {
1711             pitch += pitchAlign;
1712             pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
1713         }
1714 
1715         *pPitch = pitch;
1716 
1717         UINT_32 heightAlign = 1;
1718 
1719         while ((pitch * heightAlign) % sliceAlignInPixel)
1720         {
1721             heightAlign++;
1722         }
1723 
1724         *pHeightAlign = heightAlign;
1725 
1726         sliceSize = BITS_TO_BYTES(pixelPerSlice * bpp);
1727     }
1728 
1729     return sliceSize;
1730 }
1731 
1732 /**
1733 ****************************************************************************************************
1734 *   SiLib::HwlPreHandleBaseLvl3xPitch
1735 *
1736 *   @brief
1737 *       Pre-handler of 3x pitch (96 bit) adjustment
1738 *
1739 *   @return
1740 *       Expected pitch
1741 ****************************************************************************************************
1742 */
HwlPreHandleBaseLvl3xPitch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 expPitch) const1743 UINT_32 SiLib::HwlPreHandleBaseLvl3xPitch(
1744     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
1745     UINT_32                                 expPitch    ///< [in] pitch
1746     ) const
1747 {
1748     ADDR_ASSERT(pIn->width == expPitch);
1749 
1750     // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to
1751     // do here
1752     if (pIn->flags.pow2Pad == FALSE)
1753     {
1754         Addr::V1::Lib::HwlPreHandleBaseLvl3xPitch(pIn, expPitch);
1755     }
1756     else
1757     {
1758         ADDR_ASSERT(IsPow2(expPitch));
1759     }
1760 
1761     return expPitch;
1762 }
1763 
1764 /**
1765 ****************************************************************************************************
1766 *   SiLib::HwlPostHandleBaseLvl3xPitch
1767 *
1768 *   @brief
1769 *       Post-handler of 3x pitch adjustment
1770 *
1771 *   @return
1772 *       Expected pitch
1773 ****************************************************************************************************
1774 */
HwlPostHandleBaseLvl3xPitch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 expPitch) const1775 UINT_32 SiLib::HwlPostHandleBaseLvl3xPitch(
1776     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
1777     UINT_32                                 expPitch    ///< [in] pitch
1778     ) const
1779 {
1780     /**
1781      * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should
1782      *  be able to compute a correct pitch from it as h/w address library is doing the job.
1783      */
1784     // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here
1785     if (pIn->flags.pow2Pad == FALSE)
1786     {
1787         Addr::V1::Lib::HwlPostHandleBaseLvl3xPitch(pIn, expPitch);
1788     }
1789 
1790     return expPitch;
1791 }
1792 
1793 /**
1794 ****************************************************************************************************
1795 *   SiLib::HwlGetPitchAlignmentMicroTiled
1796 *
1797 *   @brief
1798 *       Compute 1D tiled surface pitch alignment
1799 *
1800 *   @return
1801 *       pitch alignment
1802 ****************************************************************************************************
1803 */
HwlGetPitchAlignmentMicroTiled(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 numSamples) const1804 UINT_32 SiLib::HwlGetPitchAlignmentMicroTiled(
1805     AddrTileMode        tileMode,          ///< [in] tile mode
1806     UINT_32             bpp,               ///< [in] bits per pixel
1807     ADDR_SURFACE_FLAGS  flags,             ///< [in] surface flags
1808     UINT_32             numSamples         ///< [in] number of samples
1809     ) const
1810 {
1811     UINT_32 pitchAlign;
1812 
1813     if (flags.qbStereo)
1814     {
1815         pitchAlign = EgBasedLib::HwlGetPitchAlignmentMicroTiled(tileMode,bpp,flags,numSamples);
1816     }
1817     else
1818     {
1819         pitchAlign = 8;
1820     }
1821 
1822     return pitchAlign;
1823 }
1824 
1825 /**
1826 ****************************************************************************************************
1827 *   SiLib::HwlGetSizeAdjustmentMicroTiled
1828 *
1829 *   @brief
1830 *       Adjust 1D tiled surface pitch and slice size
1831 *
1832 *   @return
1833 *       Logical slice size in bytes
1834 ****************************************************************************************************
1835 */
HwlGetSizeAdjustmentMicroTiled(UINT_32 thickness,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 numSamples,UINT_32 baseAlign,UINT_32 pitchAlign,UINT_32 * pPitch,UINT_32 * pHeight) const1836 UINT_64 SiLib::HwlGetSizeAdjustmentMicroTiled(
1837     UINT_32             thickness,      ///< [in] thickness
1838     UINT_32             bpp,            ///< [in] bits per pixel
1839     ADDR_SURFACE_FLAGS  flags,          ///< [in] surface flags
1840     UINT_32             numSamples,     ///< [in] number of samples
1841     UINT_32             baseAlign,      ///< [in] base alignment
1842     UINT_32             pitchAlign,     ///< [in] pitch alignment
1843     UINT_32*            pPitch,         ///< [in,out] pointer to pitch
1844     UINT_32*            pHeight         ///< [in,out] pointer to height
1845     ) const
1846 {
1847     UINT_64 logicalSliceSize;
1848     UINT_64 physicalSliceSize;
1849 
1850     UINT_32 pitch   = *pPitch;
1851     UINT_32 height  = *pHeight;
1852 
1853     // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1)
1854     logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
1855 
1856     // Physical slice: multiplied by thickness
1857     physicalSliceSize =  logicalSliceSize * thickness;
1858 
1859     // Pitch alignment is always 8, so if slice size is not padded to base alignment
1860     // (pipe_interleave_size), we need to increase pitch
1861     while ((physicalSliceSize % baseAlign) != 0)
1862     {
1863         pitch += pitchAlign;
1864 
1865         logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
1866 
1867         physicalSliceSize =  logicalSliceSize * thickness;
1868     }
1869 
1870 #if !ALT_TEST
1871     //
1872     // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since
1873     // the stencil plane may have larger pitch if the slice size is smaller than base alignment.
1874     //
1875     // Note: this actually does not work for mipmap but mipmap depth texture is not really
1876     // sampled with mipmap.
1877     //
1878     if (flags.depth && (flags.noStencil == FALSE))
1879     {
1880         ADDR_ASSERT(numSamples == 1);
1881 
1882         UINT_64 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; // 1 byte stencil
1883 
1884         while ((logicalSiceSizeStencil % baseAlign) != 0)
1885         {
1886             pitch += pitchAlign; // Stencil plane's pitch alignment is the same as depth plane's
1887 
1888             logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height;
1889         }
1890 
1891         if (pitch != *pPitch)
1892         {
1893             // If this is a mipmap, this padded one cannot be sampled as a whole mipmap!
1894             logicalSliceSize = logicalSiceSizeStencil * BITS_TO_BYTES(bpp);
1895         }
1896     }
1897 #endif
1898     *pPitch = pitch;
1899 
1900     // No adjust for pHeight
1901 
1902     return logicalSliceSize;
1903 }
1904 
1905 /**
1906 ****************************************************************************************************
1907 *   SiLib::HwlConvertChipFamily
1908 *
1909 *   @brief
1910 *       Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
1911 *   @return
1912 *       ChipFamily
1913 ****************************************************************************************************
1914 */
HwlConvertChipFamily(UINT_32 uChipFamily,UINT_32 uChipRevision)1915 ChipFamily SiLib::HwlConvertChipFamily(
1916     UINT_32 uChipFamily,        ///< [in] chip family defined in atiih.h
1917     UINT_32 uChipRevision)      ///< [in] chip revision defined in "asic_family"_id.h
1918 {
1919     ChipFamily family = ADDR_CHIP_FAMILY_SI;
1920 
1921     switch (uChipFamily)
1922     {
1923         case FAMILY_SI:
1924             m_settings.isSouthernIsland = 1;
1925             m_settings.isTahiti     = ASICREV_IS_TAHITI_P(uChipRevision);
1926             m_settings.isPitCairn   = ASICREV_IS_PITCAIRN_PM(uChipRevision);
1927             m_settings.isCapeVerde  = ASICREV_IS_CAPEVERDE_M(uChipRevision);
1928             m_settings.isOland      = ASICREV_IS_OLAND_M(uChipRevision);
1929             m_settings.isHainan     = ASICREV_IS_HAINAN_V(uChipRevision);
1930             break;
1931         default:
1932             ADDR_ASSERT(!"No Chip found");
1933             break;
1934     }
1935 
1936     return family;
1937 }
1938 
1939 /**
1940 ****************************************************************************************************
1941 *   SiLib::HwlSetupTileInfo
1942 *
1943 *   @brief
1944 *       Setup default value of tile info for SI
1945 ****************************************************************************************************
1946 */
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) const1947 VOID SiLib::HwlSetupTileInfo(
1948     AddrTileMode                        tileMode,       ///< [in] Tile mode
1949     ADDR_SURFACE_FLAGS                  flags,          ///< [in] Surface type flags
1950     UINT_32                             bpp,            ///< [in] Bits per pixel
1951     UINT_32                             pitch,          ///< [in] Pitch in pixels
1952     UINT_32                             height,         ///< [in] Height in pixels
1953     UINT_32                             numSamples,     ///< [in] Number of samples
1954     ADDR_TILEINFO*                      pTileInfoIn,    ///< [in] Tile info input: NULL for default
1955     ADDR_TILEINFO*                      pTileInfoOut,   ///< [out] Tile info output
1956     AddrTileType                        inTileType,     ///< [in] Tile type
1957     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*   pOut            ///< [out] Output
1958     ) const
1959 {
1960     UINT_32 thickness = Thickness(tileMode);
1961     ADDR_TILEINFO* pTileInfo = pTileInfoOut;
1962     INT index = TileIndexInvalid;
1963 
1964     // Fail-safe code
1965     if (IsLinear(tileMode) == FALSE)
1966     {
1967         // 128 bpp/thick tiling must be non-displayable.
1968         // Fmask reuse color buffer's entry but bank-height field can be from another entry
1969         // To simplify the logic, fmask entry should be picked from non-displayable ones
1970         if (bpp == 128 || thickness > 1 || flags.fmask || flags.prt)
1971         {
1972             inTileType = ADDR_NON_DISPLAYABLE;
1973         }
1974 
1975         if (flags.depth || flags.stencil)
1976         {
1977             inTileType = ADDR_DEPTH_SAMPLE_ORDER;
1978         }
1979     }
1980 
1981     // Partial valid fields are not allowed for SI.
1982     if (IsTileInfoAllZero(pTileInfo))
1983     {
1984         if (IsMacroTiled(tileMode))
1985         {
1986             if (flags.prt)
1987             {
1988                 if (numSamples == 1)
1989                 {
1990                     if (flags.depth)
1991                     {
1992                         switch (bpp)
1993                         {
1994                             case 16:
1995                                 index = 3;
1996                                 break;
1997                             case 32:
1998                                 index = 6;
1999                                 break;
2000                             default:
2001                                 ADDR_ASSERT_ALWAYS();
2002                                 break;
2003                         }
2004                     }
2005                     else
2006                     {
2007                         switch (bpp)
2008                         {
2009                             case 8:
2010                                 index = 21;
2011                                 break;
2012                             case 16:
2013                                 index = 22;
2014                                 break;
2015                             case 32:
2016                                 index = 23;
2017                                 break;
2018                             case 64:
2019                                 index = 24;
2020                                 break;
2021                             case 128:
2022                                 index = 25;
2023                                 break;
2024                             default:
2025                                 break;
2026                         }
2027 
2028                         if (thickness > 1)
2029                         {
2030                             ADDR_ASSERT(bpp != 128);
2031                             index += 5;
2032                         }
2033                     }
2034                 }
2035                 else
2036                 {
2037                     ADDR_ASSERT(numSamples == 4);
2038 
2039                     if (flags.depth)
2040                     {
2041                         switch (bpp)
2042                         {
2043                             case 16:
2044                                 index = 5;
2045                                 break;
2046                             case 32:
2047                                 index = 7;
2048                                 break;
2049                             default:
2050                                 ADDR_ASSERT_ALWAYS();
2051                                 break;
2052                         }
2053                     }
2054                     else
2055                     {
2056                         switch (bpp)
2057                         {
2058                             case 8:
2059                                 index = 23;
2060                                 break;
2061                             case 16:
2062                                 index = 24;
2063                                 break;
2064                             case 32:
2065                                 index = 25;
2066                                 break;
2067                             case 64:
2068                                 index = 30;
2069                                 break;
2070                             default:
2071                                 ADDR_ASSERT_ALWAYS();
2072                                 break;
2073                         }
2074                     }
2075                 }
2076             }//end of PRT part
2077             // See table entries 0-7
2078             else if (flags.depth || flags.stencil)
2079             {
2080                 if (flags.compressZ)
2081                 {
2082                     if (flags.stencil)
2083                     {
2084                         index = 0;
2085                     }
2086                     else
2087                     {
2088                         // optimal tile index for compressed depth/stencil.
2089                         switch (numSamples)
2090                         {
2091                             case 1:
2092                                 index = 0;
2093                                 break;
2094                             case 2:
2095                             case 4:
2096                                 index = 1;
2097                                 break;
2098                             case 8:
2099                                 index = 2;
2100                                 break;
2101                             default:
2102                                 break;
2103                         }
2104                     }
2105                 }
2106                 else // unCompressZ
2107                 {
2108                     index = 3;
2109                 }
2110             }
2111             else //non PRT & non Depth & non Stencil
2112             {
2113                 // See table entries 9-12
2114                 if (inTileType == ADDR_DISPLAYABLE)
2115                 {
2116                     switch (bpp)
2117                     {
2118                         case 8:
2119                             index = 10;
2120                             break;
2121                         case 16:
2122                             index = 11;
2123                             break;
2124                         case 32:
2125                             index = 12;
2126                             break;
2127                         case 64:
2128                             index = 12;
2129                             break;
2130                         default:
2131                             break;
2132                     }
2133                 }
2134                 else
2135                 {
2136                     // See table entries 13-17
2137                     if (thickness == 1)
2138                     {
2139                         if (flags.fmask)
2140                         {
2141                             UINT_32 fmaskPixelSize = bpp * numSamples;
2142 
2143                             switch (fmaskPixelSize)
2144                             {
2145                                 case 8:
2146                                     index = 14;
2147                                     break;
2148                                 case 16:
2149                                     index = 15;
2150                                     break;
2151                                 case 32:
2152                                     index = 16;
2153                                     break;
2154                                 case 64:
2155                                     index = 17;
2156                                     break;
2157                                 default:
2158                                     ADDR_ASSERT_ALWAYS();
2159                             }
2160                         }
2161                         else
2162                         {
2163                             switch (bpp)
2164                             {
2165                                 case 8:
2166                                     index = 14;
2167                                     break;
2168                                 case 16:
2169                                     index = 15;
2170                                     break;
2171                                 case 32:
2172                                     index = 16;
2173                                     break;
2174                                 case 64:
2175                                     index = 17;
2176                                     break;
2177                                 case 128:
2178                                     index = 17;
2179                                     break;
2180                                 default:
2181                                     break;
2182                             }
2183                         }
2184                     }
2185                     else // thick tiling - entries 18-20
2186                     {
2187                         switch (thickness)
2188                         {
2189                             case 4:
2190                                 index = 20;
2191                                 break;
2192                             case 8:
2193                                 index = 19;
2194                                 break;
2195                             default:
2196                                 break;
2197                         }
2198                     }
2199                 }
2200             }
2201         }
2202         else
2203         {
2204             if (tileMode == ADDR_TM_LINEAR_ALIGNED)
2205             {
2206                 index = 8;
2207             }
2208             else if (tileMode == ADDR_TM_LINEAR_GENERAL)
2209             {
2210                 index = TileIndexLinearGeneral;
2211             }
2212             else
2213             {
2214                 if (flags.depth || flags.stencil)
2215                 {
2216                     index = 4;
2217                 }
2218                 else if (inTileType == ADDR_DISPLAYABLE)
2219                 {
2220                     index = 9;
2221                 }
2222                 else if (thickness == 1)
2223                 {
2224                     index = 13;
2225                 }
2226                 else
2227                 {
2228                     index = 18;
2229                 }
2230             }
2231         }
2232 
2233         if (index >= 0 && index <= 31)
2234         {
2235             *pTileInfo      = m_tileTable[index].info;
2236             pOut->tileType  = m_tileTable[index].type;
2237         }
2238 
2239         if (index == TileIndexLinearGeneral)
2240         {
2241             *pTileInfo      = m_tileTable[8].info;
2242             pOut->tileType  = m_tileTable[8].type;
2243         }
2244     }
2245     else
2246     {
2247         if (pTileInfoIn)
2248         {
2249             if (flags.stencil && pTileInfoIn->tileSplitBytes == 0)
2250             {
2251                 // Stencil always uses index 0
2252                 *pTileInfo = m_tileTable[0].info;
2253             }
2254         }
2255         // Pass through tile type
2256         pOut->tileType = inTileType;
2257     }
2258 
2259     pOut->tileIndex = index;
2260     pOut->prtTileIndex = flags.prt;
2261 }
2262 
2263 /**
2264 ****************************************************************************************************
2265 *   SiLib::DecodeGbRegs
2266 *
2267 *   @brief
2268 *       Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks
2269 *
2270 *   @return
2271 *       TRUE if all settings are valid
2272 *
2273 ****************************************************************************************************
2274 */
DecodeGbRegs(const ADDR_REGISTER_VALUE * pRegValue)2275 BOOL_32 SiLib::DecodeGbRegs(
2276     const ADDR_REGISTER_VALUE* pRegValue) ///< [in] create input
2277 {
2278     GB_ADDR_CONFIG  reg;
2279     BOOL_32         valid = TRUE;
2280 
2281     reg.val = pRegValue->gbAddrConfig;
2282 
2283     switch (reg.f.pipe_interleave_size)
2284     {
2285         case ADDR_CONFIG_PIPE_INTERLEAVE_256B:
2286             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_256B;
2287             break;
2288         case ADDR_CONFIG_PIPE_INTERLEAVE_512B:
2289             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_512B;
2290             break;
2291         default:
2292             valid = FALSE;
2293             ADDR_UNHANDLED_CASE();
2294             break;
2295     }
2296 
2297     switch (reg.f.row_size)
2298     {
2299         case ADDR_CONFIG_1KB_ROW:
2300             m_rowSize = ADDR_ROWSIZE_1KB;
2301             break;
2302         case ADDR_CONFIG_2KB_ROW:
2303             m_rowSize = ADDR_ROWSIZE_2KB;
2304             break;
2305         case ADDR_CONFIG_4KB_ROW:
2306             m_rowSize = ADDR_ROWSIZE_4KB;
2307             break;
2308         default:
2309             valid = FALSE;
2310             ADDR_UNHANDLED_CASE();
2311             break;
2312     }
2313 
2314     switch (pRegValue->noOfBanks)
2315     {
2316         case 0:
2317             m_banks = 4;
2318             break;
2319         case 1:
2320             m_banks = 8;
2321             break;
2322         case 2:
2323             m_banks = 16;
2324             break;
2325         default:
2326             valid = FALSE;
2327             ADDR_UNHANDLED_CASE();
2328             break;
2329     }
2330 
2331     switch (pRegValue->noOfRanks)
2332     {
2333         case 0:
2334             m_ranks = 1;
2335             break;
2336         case 1:
2337             m_ranks = 2;
2338             break;
2339         default:
2340             valid = FALSE;
2341             ADDR_UNHANDLED_CASE();
2342             break;
2343     }
2344 
2345     m_logicalBanks = m_banks * m_ranks;
2346 
2347     ADDR_ASSERT(m_logicalBanks <= 16);
2348 
2349     return valid;
2350 }
2351 
2352 /**
2353 ****************************************************************************************************
2354 *   SiLib::HwlInitGlobalParams
2355 *
2356 *   @brief
2357 *       Initializes global parameters
2358 *
2359 *   @return
2360 *       TRUE if all settings are valid
2361 *
2362 ****************************************************************************************************
2363 */
HwlInitGlobalParams(const ADDR_CREATE_INPUT * pCreateIn)2364 BOOL_32 SiLib::HwlInitGlobalParams(
2365     const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input
2366 {
2367     BOOL_32 valid = TRUE;
2368     const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue;
2369 
2370     valid = DecodeGbRegs(pRegValue);
2371 
2372     if (valid)
2373     {
2374         if (m_settings.isTahiti || m_settings.isPitCairn)
2375         {
2376             m_pipes = 8;
2377         }
2378         else if (m_settings.isCapeVerde || m_settings.isOland)
2379         {
2380             m_pipes = 4;
2381         }
2382         else
2383         {
2384             // Hainan is 2-pipe (m_settings.isHainan == 1)
2385             m_pipes = 2;
2386         }
2387 
2388         valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
2389 
2390         if (valid)
2391         {
2392             InitEquationTable();
2393         }
2394 
2395         m_maxSamples = 16;
2396     }
2397 
2398     return valid;
2399 }
2400 
2401 /**
2402 ****************************************************************************************************
2403 *   SiLib::HwlConvertTileInfoToHW
2404 *   @brief
2405 *       Entry of si's ConvertTileInfoToHW
2406 *   @return
2407 *       ADDR_E_RETURNCODE
2408 ****************************************************************************************************
2409 */
HwlConvertTileInfoToHW(const ADDR_CONVERT_TILEINFOTOHW_INPUT * pIn,ADDR_CONVERT_TILEINFOTOHW_OUTPUT * pOut) const2410 ADDR_E_RETURNCODE SiLib::HwlConvertTileInfoToHW(
2411     const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
2412     ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut      ///< [out] output structure
2413     ) const
2414 {
2415     ADDR_E_RETURNCODE retCode   = ADDR_OK;
2416 
2417     retCode = EgBasedLib::HwlConvertTileInfoToHW(pIn, pOut);
2418 
2419     if (retCode == ADDR_OK)
2420     {
2421         if (pIn->reverse == FALSE)
2422         {
2423             if (pIn->pTileInfo->pipeConfig == ADDR_PIPECFG_INVALID)
2424             {
2425                 retCode = ADDR_INVALIDPARAMS;
2426             }
2427             else
2428             {
2429                 pOut->pTileInfo->pipeConfig =
2430                     static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig - 1);
2431             }
2432         }
2433         else
2434         {
2435             pOut->pTileInfo->pipeConfig =
2436                 static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig + 1);
2437         }
2438     }
2439 
2440     return retCode;
2441 }
2442 
2443 /**
2444 ****************************************************************************************************
2445 *   SiLib::HwlComputeXmaskCoordYFrom8Pipe
2446 *
2447 *   @brief
2448 *       Compute the Y coord which will be added to Xmask Y
2449 *       coord.
2450 *   @return
2451 *       Y coord
2452 ****************************************************************************************************
2453 */
HwlComputeXmaskCoordYFrom8Pipe(UINT_32 pipe,UINT_32 x) const2454 UINT_32 SiLib::HwlComputeXmaskCoordYFrom8Pipe(
2455     UINT_32         pipe,       ///< [in] pipe id
2456     UINT_32         x           ///< [in] tile coord x, which is original x coord / 8
2457     ) const
2458 {
2459     // This function should never be called since it is 6xx/8xx specfic.
2460     // Keep this empty implementation to avoid any mis-use.
2461     ADDR_ASSERT_ALWAYS();
2462 
2463     return 0;
2464 }
2465 
2466 /**
2467 ****************************************************************************************************
2468 *   SiLib::HwlComputeSurfaceCoord2DFromBankPipe
2469 *
2470 *   @brief
2471 *       Compute surface x,y coordinates from bank/pipe info
2472 *   @return
2473 *       N/A
2474 ****************************************************************************************************
2475 */
HwlComputeSurfaceCoord2DFromBankPipe(AddrTileMode tileMode,UINT_32 * pX,UINT_32 * pY,UINT_32 slice,UINT_32 bank,UINT_32 pipe,UINT_32 bankSwizzle,UINT_32 pipeSwizzle,UINT_32 tileSlices,BOOL_32 ignoreSE,ADDR_TILEINFO * pTileInfo) const2476 VOID SiLib::HwlComputeSurfaceCoord2DFromBankPipe(
2477     AddrTileMode        tileMode,   ///< [in] tile mode
2478     UINT_32*            pX,         ///< [in,out] x coordinate
2479     UINT_32*            pY,         ///< [in,out] y coordinate
2480     UINT_32             slice,      ///< [in] slice index
2481     UINT_32             bank,       ///< [in] bank number
2482     UINT_32             pipe,       ///< [in] pipe number
2483     UINT_32             bankSwizzle,///< [in] bank swizzle
2484     UINT_32             pipeSwizzle,///< [in] pipe swizzle
2485     UINT_32             tileSlices, ///< [in] slices in a micro tile
2486     BOOL_32             ignoreSE,   ///< [in] TRUE if shader engines are ignored
2487     ADDR_TILEINFO*      pTileInfo   ///< [in] bank structure. **All fields to be valid on entry**
2488     ) const
2489 {
2490     UINT_32 xBit;
2491     UINT_32 yBit;
2492     UINT_32 yBit3 = 0;
2493     UINT_32 yBit4 = 0;
2494     UINT_32 yBit5 = 0;
2495     UINT_32 yBit6 = 0;
2496 
2497     UINT_32 xBit3 = 0;
2498     UINT_32 xBit4 = 0;
2499     UINT_32 xBit5 = 0;
2500 
2501     UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
2502 
2503     CoordFromBankPipe xyBits = {0};
2504     ComputeSurfaceCoord2DFromBankPipe(tileMode, *pX, *pY, slice, bank, pipe,
2505                                       bankSwizzle, pipeSwizzle, tileSlices, pTileInfo,
2506                                       &xyBits);
2507     yBit3 = xyBits.yBit3;
2508     yBit4 = xyBits.yBit4;
2509     yBit5 = xyBits.yBit5;
2510     yBit6 = xyBits.yBit6;
2511 
2512     xBit3 = xyBits.xBit3;
2513     xBit4 = xyBits.xBit4;
2514     xBit5 = xyBits.xBit5;
2515 
2516     yBit = xyBits.yBits;
2517 
2518     UINT_32 yBitTemp = 0;
2519 
2520     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
2521         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32))
2522     {
2523         ADDR_ASSERT(pTileInfo->bankWidth == 1 && pTileInfo->macroAspectRatio > 1);
2524         UINT_32 yBitToCheck = QLog2(pTileInfo->banks) - 1;
2525 
2526         ADDR_ASSERT(yBitToCheck <= 3);
2527 
2528         yBitTemp = _BIT(yBit, yBitToCheck);
2529 
2530         xBit3 = 0;
2531     }
2532 
2533     yBit = Bits2Number(4, yBit6, yBit5, yBit4, yBit3);
2534     xBit = Bits2Number(3, xBit5, xBit4, xBit3);
2535 
2536     *pY += yBit * pTileInfo->bankHeight * MicroTileHeight;
2537     *pX += xBit * numPipes * pTileInfo->bankWidth * MicroTileWidth;
2538 
2539     //calculate the bank and pipe bits in x, y
2540     UINT_32 xTile; //x in micro tile
2541     UINT_32 x3 = 0;
2542     UINT_32 x4 = 0;
2543     UINT_32 x5 = 0;
2544     UINT_32 x6 = 0;
2545     UINT_32 y = *pY;
2546 
2547     UINT_32 pipeBit0 = _BIT(pipe,0);
2548     UINT_32 pipeBit1 = _BIT(pipe,1);
2549     UINT_32 pipeBit2 = _BIT(pipe,2);
2550 
2551     UINT_32 y3 = _BIT(y, 3);
2552     UINT_32 y4 = _BIT(y, 4);
2553     UINT_32 y5 = _BIT(y, 5);
2554     UINT_32 y6 = _BIT(y, 6);
2555 
2556     // bankbit0 after ^x4^x5
2557     UINT_32 bankBit00 = _BIT(bank,0);
2558     UINT_32 bankBit0 = 0;
2559 
2560     switch (pTileInfo->pipeConfig)
2561     {
2562         case ADDR_PIPECFG_P2:
2563             x3 = pipeBit0 ^ y3;
2564             break;
2565         case ADDR_PIPECFG_P4_8x16:
2566             x4 = pipeBit0 ^ y3;
2567             x3 = pipeBit0 ^ y4;
2568             break;
2569         case ADDR_PIPECFG_P4_16x16:
2570             x4 = pipeBit1 ^ y4;
2571             x3 = pipeBit0 ^ y3 ^ x4;
2572             break;
2573         case ADDR_PIPECFG_P4_16x32:
2574             x4 = pipeBit1 ^ y4;
2575             x3 = pipeBit0 ^ y3 ^ x4;
2576             break;
2577         case ADDR_PIPECFG_P4_32x32:
2578             x5 = pipeBit1 ^ y5;
2579             x3 = pipeBit0 ^ y3 ^ x5;
2580             bankBit0 = yBitTemp ^ x5;
2581             x4 = bankBit00 ^ x5 ^ bankBit0;
2582             *pX += x5 * 4 * 1 * 8; // x5 * num_pipes * bank_width * 8;
2583             break;
2584         case ADDR_PIPECFG_P8_16x16_8x16:
2585             x3 = pipeBit1 ^ y5;
2586             x4 = pipeBit2 ^ y4;
2587             x5 = pipeBit0 ^ y3 ^ x4;
2588             break;
2589         case ADDR_PIPECFG_P8_16x32_8x16:
2590             x3 = pipeBit1 ^ y4;
2591             x4 = pipeBit2 ^ y5;
2592             x5 = pipeBit0 ^ y3 ^ x4;
2593             break;
2594         case ADDR_PIPECFG_P8_32x32_8x16:
2595             x3 = pipeBit1 ^ y4;
2596             x5 = pipeBit2 ^ y5;
2597             x4 = pipeBit0 ^ y3 ^ x5;
2598             break;
2599         case ADDR_PIPECFG_P8_16x32_16x16:
2600             x4 = pipeBit2 ^ y5;
2601             x5 = pipeBit1 ^ y4;
2602             x3 = pipeBit0 ^ y3 ^ x4;
2603             break;
2604         case ADDR_PIPECFG_P8_32x32_16x16:
2605             x5 = pipeBit2 ^ y5;
2606             x4 = pipeBit1 ^ y4;
2607             x3 = pipeBit0 ^ y3 ^ x4;
2608             break;
2609         case ADDR_PIPECFG_P8_32x32_16x32:
2610             x5 = pipeBit2 ^ y5;
2611             x4 = pipeBit1 ^ y6;
2612             x3 = pipeBit0 ^ y3 ^ x4;
2613             break;
2614         case ADDR_PIPECFG_P8_32x64_32x32:
2615             x6 = pipeBit1 ^ y5;
2616             x5 = pipeBit2 ^ y6;
2617             x3 = pipeBit0 ^ y3 ^ x5;
2618             bankBit0 = yBitTemp ^ x6;
2619             x4 = bankBit00 ^ x5 ^ bankBit0;
2620             *pX += x6 * 8 * 1 * 8; // x6 * num_pipes * bank_width * 8;
2621             break;
2622         default:
2623             ADDR_ASSERT_ALWAYS();
2624     }
2625 
2626     xTile = Bits2Number(3, x5, x4, x3);
2627 
2628     *pX += xTile << 3;
2629 }
2630 
2631 /**
2632 ****************************************************************************************************
2633 *   SiLib::HwlPreAdjustBank
2634 *
2635 *   @brief
2636 *       Adjust bank before calculating address acoording to bank/pipe
2637 *   @return
2638 *       Adjusted bank
2639 ****************************************************************************************************
2640 */
HwlPreAdjustBank(UINT_32 tileX,UINT_32 bank,ADDR_TILEINFO * pTileInfo) const2641 UINT_32 SiLib::HwlPreAdjustBank(
2642     UINT_32         tileX,      ///< [in] x coordinate in unit of tile
2643     UINT_32         bank,       ///< [in] bank
2644     ADDR_TILEINFO*  pTileInfo   ///< [in] tile info
2645     ) const
2646 {
2647     if (((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
2648         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) && (pTileInfo->bankWidth == 1))
2649     {
2650         UINT_32 bankBit0 = _BIT(bank, 0);
2651         UINT_32 x4 = _BIT(tileX, 1);
2652         UINT_32 x5 = _BIT(tileX, 2);
2653 
2654         bankBit0 = bankBit0 ^ x4 ^ x5;
2655         bank |= bankBit0;
2656 
2657         ADDR_ASSERT(pTileInfo->macroAspectRatio > 1);
2658     }
2659 
2660     return bank;
2661 }
2662 
2663 /**
2664 ****************************************************************************************************
2665 *   SiLib::HwlComputeSurfaceInfo
2666 *
2667 *   @brief
2668 *       Entry of si's ComputeSurfaceInfo
2669 *   @return
2670 *       ADDR_E_RETURNCODE
2671 ****************************************************************************************************
2672 */
HwlComputeSurfaceInfo(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2673 ADDR_E_RETURNCODE SiLib::HwlComputeSurfaceInfo(
2674     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,    ///< [in] input structure
2675     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [out] output structure
2676     ) const
2677 {
2678     pOut->tileIndex = pIn->tileIndex;
2679 
2680     ADDR_E_RETURNCODE retCode = EgBasedLib::HwlComputeSurfaceInfo(pIn, pOut);
2681 
2682     UINT_32 tileIndex = static_cast<UINT_32>(pOut->tileIndex);
2683 
2684     if (((pIn->flags.needEquation   == TRUE) ||
2685          (pIn->flags.preferEquation == TRUE)) &&
2686         (pIn->numSamples <= 1) &&
2687         (tileIndex < TileTableSize))
2688     {
2689         static const UINT_32 SiUncompressDepthTileIndex = 3;
2690 
2691         if ((pIn->numSlices > 1) &&
2692             (IsMacroTiled(pOut->tileMode) == TRUE) &&
2693             ((m_chipFamily == ADDR_CHIP_FAMILY_SI) ||
2694              (IsPrtTileMode(pOut->tileMode) == FALSE)))
2695         {
2696             pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX;
2697         }
2698         else if ((pIn->flags.prt == FALSE) &&
2699                  (m_uncompressDepthEqIndex != 0) &&
2700                  (tileIndex == SiUncompressDepthTileIndex))
2701         {
2702             pOut->equationIndex = m_uncompressDepthEqIndex + Log2(pIn->bpp >> 3);
2703         }
2704         else
2705         {
2706 
2707             pOut->equationIndex = m_equationLookupTable[Log2(pIn->bpp >> 3)][tileIndex];
2708         }
2709 
2710         if (pOut->equationIndex != ADDR_INVALID_EQUATION_INDEX)
2711         {
2712             pOut->blockWidth = m_blockWidth[pOut->equationIndex];
2713 
2714             pOut->blockHeight = m_blockHeight[pOut->equationIndex];
2715 
2716             pOut->blockSlices = m_blockSlices[pOut->equationIndex];
2717         }
2718     }
2719     else
2720     {
2721         pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX;
2722     }
2723 
2724     return retCode;
2725 }
2726 
2727 /**
2728 ****************************************************************************************************
2729 *   SiLib::HwlComputeMipLevel
2730 *   @brief
2731 *       Compute MipLevel info (including level 0)
2732 *   @return
2733 *       TRUE if HWL's handled
2734 ****************************************************************************************************
2735 */
HwlComputeMipLevel(ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn) const2736 BOOL_32 SiLib::HwlComputeMipLevel(
2737     ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in,out] Input structure
2738     ) const
2739 {
2740     // basePitch is calculated from level 0 so we only check this for mipLevel > 0
2741     if (pIn->mipLevel > 0)
2742     {
2743         // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if
2744         // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being
2745         // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2.
2746         if (ElemLib::IsExpand3x(pIn->format) == FALSE)
2747         {
2748             // Sublevel pitches are generated from base level pitch instead of width on SI
2749             // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain
2750             ADDR_ASSERT((pIn->flags.pow2Pad == FALSE) ||
2751                         ((pIn->basePitch != 0) && IsPow2(pIn->basePitch)));
2752         }
2753 
2754         if (pIn->basePitch != 0)
2755         {
2756             pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel);
2757         }
2758     }
2759 
2760     // pow2Pad is done in PostComputeMipLevel
2761 
2762     return TRUE;
2763 }
2764 
2765 /**
2766 ****************************************************************************************************
2767 *   SiLib::HwlCheckLastMacroTiledLvl
2768 *
2769 *   @brief
2770 *       Sets pOut->last2DLevel to TRUE if it is
2771 *   @note
2772 *
2773 ****************************************************************************************************
2774 */
HwlCheckLastMacroTiledLvl(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2775 VOID SiLib::HwlCheckLastMacroTiledLvl(
2776     const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
2777     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut      ///< [in,out] Output structure (used as input, too)
2778     ) const
2779 {
2780     // pow2Pad covers all mipmap cases
2781     if (pIn->flags.pow2Pad)
2782     {
2783         ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
2784 
2785         UINT_32 nextPitch;
2786         UINT_32 nextHeight;
2787         UINT_32 nextSlices;
2788 
2789         AddrTileMode nextTileMode;
2790 
2791         if (pIn->mipLevel == 0 || pIn->basePitch == 0)
2792         {
2793             // Base level or fail-safe case (basePitch == 0)
2794             nextPitch = pOut->pitch >> 1;
2795         }
2796         else
2797         {
2798             // Sub levels
2799             nextPitch = pIn->basePitch >> (pIn->mipLevel + 1);
2800         }
2801 
2802         // nextHeight must be shifted from this level's original height rather than a pow2 padded
2803         // one but this requires original height stored somewhere (pOut->height)
2804         ADDR_ASSERT(pOut->height != 0);
2805 
2806         // next level's height is just current level's >> 1 in pixels
2807         nextHeight = pOut->height >> 1;
2808         // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block
2809         // compressed foramts
2810         if (ElemLib::IsBlockCompressed(pIn->format))
2811         {
2812             nextHeight = (nextHeight + 3) / 4;
2813         }
2814         nextHeight = NextPow2(nextHeight);
2815 
2816         // nextSlices may be 0 if this level's is 1
2817         if (pIn->flags.volume)
2818         {
2819             nextSlices = Max(1u, pIn->numSlices >> 1);
2820         }
2821         else
2822         {
2823             nextSlices = pIn->numSlices;
2824         }
2825 
2826         nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode,
2827                                                       pIn->bpp,
2828                                                       nextPitch,
2829                                                       nextHeight,
2830                                                       nextSlices,
2831                                                       pIn->numSamples,
2832                                                       pOut->blockWidth,
2833                                                       pOut->blockHeight,
2834                                                       pOut->pTileInfo);
2835 
2836         pOut->last2DLevel = IsMicroTiled(nextTileMode);
2837     }
2838 }
2839 
2840 /**
2841 ****************************************************************************************************
2842 *   SiLib::HwlDegradeThickTileMode
2843 *
2844 *   @brief
2845 *       Degrades valid tile mode for thick modes if needed
2846 *
2847 *   @return
2848 *       Suitable tile mode
2849 ****************************************************************************************************
2850 */
HwlDegradeThickTileMode(AddrTileMode baseTileMode,UINT_32 numSlices,UINT_32 * pBytesPerTile) const2851 AddrTileMode SiLib::HwlDegradeThickTileMode(
2852     AddrTileMode        baseTileMode,   ///< base tile mode
2853     UINT_32             numSlices,      ///< current number of slices
2854     UINT_32*            pBytesPerTile   ///< [in,out] pointer to bytes per slice
2855     ) const
2856 {
2857     return EgBasedLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile);
2858 }
2859 
2860 /**
2861 ****************************************************************************************************
2862 *   SiLib::HwlTileInfoEqual
2863 *
2864 *   @brief
2865 *       Return TRUE if all field are equal
2866 *   @note
2867 *       Only takes care of current HWL's data
2868 ****************************************************************************************************
2869 */
HwlTileInfoEqual(const ADDR_TILEINFO * pLeft,const ADDR_TILEINFO * pRight) const2870 BOOL_32 SiLib::HwlTileInfoEqual(
2871     const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand
2872     const ADDR_TILEINFO* pRight ///<[in] Right compare operand
2873     ) const
2874 {
2875     BOOL_32 equal = FALSE;
2876 
2877     if (pLeft->pipeConfig == pRight->pipeConfig)
2878     {
2879         equal =  EgBasedLib::HwlTileInfoEqual(pLeft, pRight);
2880     }
2881 
2882     return equal;
2883 }
2884 
2885 /**
2886 ****************************************************************************************************
2887 *   SiLib::GetTileSettings
2888 *
2889 *   @brief
2890 *       Get tile setting infos by index.
2891 *   @return
2892 *       Tile setting info.
2893 ****************************************************************************************************
2894 */
GetTileSetting(UINT_32 index) const2895 const TileConfig* SiLib::GetTileSetting(
2896     UINT_32 index          ///< [in] Tile index
2897     ) const
2898 {
2899     ADDR_ASSERT(index < m_noOfEntries);
2900     return &m_tileTable[index];
2901 }
2902 
2903 /**
2904 ****************************************************************************************************
2905 *   SiLib::HwlPostCheckTileIndex
2906 *
2907 *   @brief
2908 *       Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
2909 *       tile mode/type/info and change the index if needed
2910 *   @return
2911 *       Tile index.
2912 ****************************************************************************************************
2913 */
HwlPostCheckTileIndex(const ADDR_TILEINFO * pInfo,AddrTileMode mode,AddrTileType type,INT curIndex) const2914 INT_32 SiLib::HwlPostCheckTileIndex(
2915     const ADDR_TILEINFO* pInfo,     ///< [in] Tile Info
2916     AddrTileMode         mode,      ///< [in] Tile mode
2917     AddrTileType         type,      ///< [in] Tile type
2918     INT                  curIndex   ///< [in] Current index assigned in HwlSetupTileInfo
2919     ) const
2920 {
2921     INT_32 index = curIndex;
2922 
2923     if (mode == ADDR_TM_LINEAR_GENERAL)
2924     {
2925         index = TileIndexLinearGeneral;
2926     }
2927     else
2928     {
2929         BOOL_32 macroTiled = IsMacroTiled(mode);
2930 
2931         // We need to find a new index if either of them is true
2932         // 1. curIndex is invalid
2933         // 2. tile mode is changed
2934         // 3. tile info does not match for macro tiled
2935         if ((index == TileIndexInvalid         ||
2936             (mode != m_tileTable[index].mode)  ||
2937             (macroTiled && (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) == FALSE))))
2938         {
2939             for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
2940             {
2941                 if (macroTiled)
2942                 {
2943                     // macro tile modes need all to match
2944                     if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) &&
2945                         (mode == m_tileTable[index].mode)                 &&
2946                         (type == m_tileTable[index].type))
2947                     {
2948                         break;
2949                     }
2950                 }
2951                 else if (mode == ADDR_TM_LINEAR_ALIGNED)
2952                 {
2953                     // linear mode only needs tile mode to match
2954                     if (mode == m_tileTable[index].mode)
2955                     {
2956                         break;
2957                     }
2958                 }
2959                 else
2960                 {
2961                     // micro tile modes only need tile mode and tile type to match
2962                     if (mode == m_tileTable[index].mode &&
2963                         type == m_tileTable[index].type)
2964                     {
2965                         break;
2966                     }
2967                 }
2968             }
2969         }
2970     }
2971 
2972     ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
2973 
2974     if (index >= static_cast<INT_32>(m_noOfEntries))
2975     {
2976         index = TileIndexInvalid;
2977     }
2978 
2979     return index;
2980 }
2981 
2982 /**
2983 ****************************************************************************************************
2984 *   SiLib::HwlSetupTileCfg
2985 *
2986 *   @brief
2987 *       Map tile index to tile setting.
2988 *   @return
2989 *       ADDR_E_RETURNCODE
2990 ****************************************************************************************************
2991 */
HwlSetupTileCfg(UINT_32 bpp,INT_32 index,INT_32 macroModeIndex,ADDR_TILEINFO * pInfo,AddrTileMode * pMode,AddrTileType * pType) const2992 ADDR_E_RETURNCODE SiLib::HwlSetupTileCfg(
2993     UINT_32         bpp,            ///< Bits per pixel
2994     INT_32          index,          ///< Tile index
2995     INT_32          macroModeIndex, ///< Index in macro tile mode table(CI)
2996     ADDR_TILEINFO*  pInfo,          ///< [out] Tile Info
2997     AddrTileMode*   pMode,          ///< [out] Tile mode
2998     AddrTileType*   pType           ///< [out] Tile type
2999     ) const
3000 {
3001     ADDR_E_RETURNCODE returnCode = ADDR_OK;
3002 
3003     // Global flag to control usage of tileIndex
3004     if (UseTileIndex(index))
3005     {
3006         if (index == TileIndexLinearGeneral)
3007         {
3008             if (pMode)
3009             {
3010                 *pMode = ADDR_TM_LINEAR_GENERAL;
3011             }
3012 
3013             if (pType)
3014             {
3015                 *pType = ADDR_DISPLAYABLE;
3016             }
3017 
3018             if (pInfo)
3019             {
3020                 pInfo->banks = 2;
3021                 pInfo->bankWidth = 1;
3022                 pInfo->bankHeight = 1;
3023                 pInfo->macroAspectRatio = 1;
3024                 pInfo->tileSplitBytes = 64;
3025                 pInfo->pipeConfig = ADDR_PIPECFG_P2;
3026             }
3027         }
3028         else if (static_cast<UINT_32>(index) >= m_noOfEntries)
3029         {
3030             returnCode = ADDR_INVALIDPARAMS;
3031         }
3032         else
3033         {
3034             const TileConfig* pCfgTable = GetTileSetting(index);
3035 
3036             if (pInfo)
3037             {
3038                 *pInfo = pCfgTable->info;
3039             }
3040             else
3041             {
3042                 if (IsMacroTiled(pCfgTable->mode))
3043                 {
3044                     returnCode = ADDR_INVALIDPARAMS;
3045                 }
3046             }
3047 
3048             if (pMode)
3049             {
3050                 *pMode = pCfgTable->mode;
3051             }
3052 
3053             if (pType)
3054             {
3055                 *pType = pCfgTable->type;
3056             }
3057         }
3058     }
3059 
3060     return returnCode;
3061 }
3062 
3063 /**
3064 ****************************************************************************************************
3065 *   SiLib::ReadGbTileMode
3066 *
3067 *   @brief
3068 *       Convert GB_TILE_MODE HW value to TileConfig.
3069 *   @return
3070 *       NA.
3071 ****************************************************************************************************
3072 */
ReadGbTileMode(UINT_32 regValue,TileConfig * pCfg) const3073 VOID SiLib::ReadGbTileMode(
3074     UINT_32     regValue,   ///< [in] GB_TILE_MODE register
3075     TileConfig* pCfg        ///< [out] output structure
3076     ) const
3077 {
3078     GB_TILE_MODE gbTileMode;
3079     gbTileMode.val = regValue;
3080 
3081     pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode);
3082     pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height;
3083     pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width;
3084     pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1);
3085     pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
3086     pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
3087     pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
3088 
3089     UINT_32 regArrayMode = gbTileMode.f.array_mode;
3090 
3091     pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
3092 
3093     if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK
3094     {
3095         pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
3096     }
3097     else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK
3098     {
3099         pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3);
3100     }
3101 }
3102 
3103 /**
3104 ****************************************************************************************************
3105 *   SiLib::InitTileSettingTable
3106 *
3107 *   @brief
3108 *       Initialize the ADDR_TILE_CONFIG table.
3109 *   @return
3110 *       TRUE if tile table is correctly initialized
3111 ****************************************************************************************************
3112 */
InitTileSettingTable(const UINT_32 * pCfg,UINT_32 noOfEntries)3113 BOOL_32 SiLib::InitTileSettingTable(
3114     const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
3115     UINT_32         noOfEntries     ///< [in] Numbe of entries in the table above
3116     )
3117 {
3118     BOOL_32 initOk = TRUE;
3119 
3120     ADDR_ASSERT(noOfEntries <= TileTableSize);
3121 
3122     memset(m_tileTable, 0, sizeof(m_tileTable));
3123 
3124     if (noOfEntries != 0)
3125     {
3126         m_noOfEntries = noOfEntries;
3127     }
3128     else
3129     {
3130         m_noOfEntries = TileTableSize;
3131     }
3132 
3133     if (pCfg) // From Client
3134     {
3135         for (UINT_32 i = 0; i < m_noOfEntries; i++)
3136         {
3137             ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
3138         }
3139     }
3140     else
3141     {
3142         ADDR_ASSERT_ALWAYS();
3143         initOk = FALSE;
3144     }
3145 
3146     if (initOk)
3147     {
3148         ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
3149     }
3150 
3151     return initOk;
3152 }
3153 
3154 /**
3155 ****************************************************************************************************
3156 *   SiLib::HwlGetTileIndex
3157 *
3158 *   @brief
3159 *       Return the virtual/real index for given mode/type/info
3160 *   @return
3161 *       ADDR_OK if successful.
3162 ****************************************************************************************************
3163 */
HwlGetTileIndex(const ADDR_GET_TILEINDEX_INPUT * pIn,ADDR_GET_TILEINDEX_OUTPUT * pOut) const3164 ADDR_E_RETURNCODE SiLib::HwlGetTileIndex(
3165     const ADDR_GET_TILEINDEX_INPUT* pIn,
3166     ADDR_GET_TILEINDEX_OUTPUT*      pOut) const
3167 {
3168     ADDR_E_RETURNCODE returnCode = ADDR_OK;
3169 
3170     pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType);
3171 
3172     return returnCode;
3173 }
3174 
3175 /**
3176 ****************************************************************************************************
3177 *   SiLib::HwlFmaskPreThunkSurfInfo
3178 *
3179 *   @brief
3180 *       Some preparation before thunking a ComputeSurfaceInfo call for Fmask
3181 *   @return
3182 *       ADDR_E_RETURNCODE
3183 ****************************************************************************************************
3184 */
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) const3185 VOID SiLib::HwlFmaskPreThunkSurfInfo(
3186     const ADDR_COMPUTE_FMASK_INFO_INPUT*    pFmaskIn,   ///< [in] Input of fmask info
3187     const ADDR_COMPUTE_FMASK_INFO_OUTPUT*   pFmaskOut,  ///< [in] Output of fmask info
3188     ADDR_COMPUTE_SURFACE_INFO_INPUT*        pSurfIn,    ///< [out] Input of thunked surface info
3189     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pSurfOut    ///< [out] Output of thunked surface info
3190     ) const
3191 {
3192     pSurfIn->tileIndex = pFmaskIn->tileIndex;
3193 }
3194 
3195 /**
3196 ****************************************************************************************************
3197 *   SiLib::HwlFmaskPostThunkSurfInfo
3198 *
3199 *   @brief
3200 *       Copy hwl extra field after calling thunked ComputeSurfaceInfo
3201 *   @return
3202 *       ADDR_E_RETURNCODE
3203 ****************************************************************************************************
3204 */
HwlFmaskPostThunkSurfInfo(const ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pSurfOut,ADDR_COMPUTE_FMASK_INFO_OUTPUT * pFmaskOut) const3205 VOID SiLib::HwlFmaskPostThunkSurfInfo(
3206     const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut,   ///< [in] Output of surface info
3207     ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut           ///< [out] Output of fmask info
3208     ) const
3209 {
3210     pFmaskOut->macroModeIndex = TileIndexInvalid;
3211     pFmaskOut->tileIndex = pSurfOut->tileIndex;
3212 }
3213 
3214 /**
3215 ****************************************************************************************************
3216 *   SiLib::HwlComputeFmaskBits
3217 *   @brief
3218 *       Computes fmask bits
3219 *   @return
3220 *       Fmask bits
3221 ****************************************************************************************************
3222 */
HwlComputeFmaskBits(const ADDR_COMPUTE_FMASK_INFO_INPUT * pIn,UINT_32 * pNumSamples) const3223 UINT_32 SiLib::HwlComputeFmaskBits(
3224     const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn,
3225     UINT_32* pNumSamples
3226     ) const
3227 {
3228     UINT_32 numSamples = pIn->numSamples;
3229     UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags);
3230     UINT_32 bpp;
3231 
3232     if (numFrags != numSamples) // EQAA
3233     {
3234         ADDR_ASSERT(numFrags <= 8);
3235 
3236         if (pIn->resolved == FALSE)
3237         {
3238             if (numFrags == 1)
3239             {
3240                 bpp          = 1;
3241                 numSamples   = numSamples == 16 ? 16 : 8;
3242             }
3243             else if (numFrags == 2)
3244             {
3245                 ADDR_ASSERT(numSamples >= 4);
3246 
3247                 bpp          = 2;
3248                 numSamples   = numSamples;
3249             }
3250             else if (numFrags == 4)
3251             {
3252                 ADDR_ASSERT(numSamples >= 4);
3253 
3254                 bpp          = 4;
3255                 numSamples   = numSamples;
3256             }
3257             else // numFrags == 8
3258             {
3259                 ADDR_ASSERT(numSamples == 16);
3260 
3261                 bpp          = 4;
3262                 numSamples   = numSamples;
3263             }
3264         }
3265         else
3266         {
3267             if (numFrags == 1)
3268             {
3269                 bpp          = (numSamples == 16) ? 16 : 8;
3270                 numSamples   = 1;
3271             }
3272             else if (numFrags == 2)
3273             {
3274                 ADDR_ASSERT(numSamples >= 4);
3275 
3276                 bpp          = numSamples*2;
3277                 numSamples   = 1;
3278             }
3279             else if (numFrags == 4)
3280             {
3281                 ADDR_ASSERT(numSamples >= 4);
3282 
3283                 bpp          = numSamples*4;
3284                 numSamples   = 1;
3285             }
3286             else // numFrags == 8
3287             {
3288                 ADDR_ASSERT(numSamples >= 16);
3289 
3290                 bpp          = 16*4;
3291                 numSamples   = 1;
3292             }
3293         }
3294     }
3295     else // Normal AA
3296     {
3297         if (pIn->resolved == FALSE)
3298         {
3299             bpp          = ComputeFmaskNumPlanesFromNumSamples(numSamples);
3300             numSamples   = numSamples == 2 ? 8 : numSamples;
3301         }
3302         else
3303         {
3304             // The same as 8XX
3305             bpp          = ComputeFmaskResolvedBppFromNumSamples(numSamples);
3306             numSamples   = 1; // 1x sample
3307         }
3308     }
3309 
3310     SafeAssign(pNumSamples, numSamples);
3311 
3312     return bpp;
3313 }
3314 
3315 /**
3316 ****************************************************************************************************
3317 *   SiLib::HwlOptimizeTileMode
3318 *
3319 *   @brief
3320 *       Optimize tile mode on SI
3321 *
3322 *   @return
3323 *       N/A
3324 *
3325 ****************************************************************************************************
3326 */
HwlOptimizeTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3327 VOID SiLib::HwlOptimizeTileMode(
3328     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut      ///< [in,out] input output structure
3329     ) const
3330 {
3331     AddrTileMode tileMode = pInOut->tileMode;
3332 
3333     if ((pInOut->flags.needEquation == TRUE) &&
3334         (IsMacroTiled(tileMode) == TRUE) &&
3335         (pInOut->numSamples <= 1))
3336     {
3337         UINT_32 thickness = Thickness(tileMode);
3338 
3339         if (thickness > 1)
3340         {
3341             tileMode = ADDR_TM_1D_TILED_THICK;
3342         }
3343         else if (pInOut->numSlices > 1)
3344         {
3345             tileMode = ADDR_TM_1D_TILED_THIN1;
3346         }
3347         else
3348         {
3349             tileMode = ADDR_TM_2D_TILED_THIN1;
3350         }
3351     }
3352 
3353     if (tileMode != pInOut->tileMode)
3354     {
3355         pInOut->tileMode = tileMode;
3356     }
3357 }
3358 
3359 /**
3360 ****************************************************************************************************
3361 *   SiLib::HwlOverrideTileMode
3362 *
3363 *   @brief
3364 *       Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI.
3365 *
3366 *   @return
3367 *       N/A
3368 *
3369 ****************************************************************************************************
3370 */
HwlOverrideTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3371 VOID SiLib::HwlOverrideTileMode(
3372     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut          ///< [in,out] input output structure
3373     ) const
3374 {
3375     AddrTileMode tileMode = pInOut->tileMode;
3376 
3377     switch (tileMode)
3378     {
3379         case ADDR_TM_PRT_TILED_THIN1:
3380             tileMode = ADDR_TM_2D_TILED_THIN1;
3381             break;
3382 
3383         case ADDR_TM_PRT_TILED_THICK:
3384             tileMode = ADDR_TM_2D_TILED_THICK;
3385             break;
3386 
3387         case ADDR_TM_PRT_2D_TILED_THICK:
3388             tileMode = ADDR_TM_2D_TILED_THICK;
3389             break;
3390 
3391         case ADDR_TM_PRT_3D_TILED_THICK:
3392             tileMode = ADDR_TM_3D_TILED_THICK;
3393             break;
3394 
3395         default:
3396             break;
3397     }
3398 
3399     if (tileMode != pInOut->tileMode)
3400     {
3401         pInOut->tileMode  = tileMode;
3402         // Only PRT tile modes are overridden for now. Revisit this once new modes are added above.
3403         pInOut->flags.prt = TRUE;
3404     }
3405 }
3406 
3407 /**
3408 ****************************************************************************************************
3409 *   SiLib::HwlSetPrtTileMode
3410 *
3411 *   @brief
3412 *       Set prt tile modes.
3413 *
3414 *   @return
3415 *       N/A
3416 *
3417 ****************************************************************************************************
3418 */
HwlSetPrtTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3419 VOID SiLib::HwlSetPrtTileMode(
3420     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
3421     ) const
3422 {
3423     pInOut->tileMode = ADDR_TM_2D_TILED_THIN1;
3424     pInOut->tileType = (pInOut->tileType == ADDR_DEPTH_SAMPLE_ORDER) ?
3425                        ADDR_DEPTH_SAMPLE_ORDER : ADDR_NON_DISPLAYABLE;
3426     pInOut->flags.prt = TRUE;
3427 }
3428 
3429 /**
3430 ****************************************************************************************************
3431 *   SiLib::HwlSelectTileMode
3432 *
3433 *   @brief
3434 *       Select tile modes.
3435 *
3436 *   @return
3437 *       N/A
3438 *
3439 ****************************************************************************************************
3440 */
HwlSelectTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3441 VOID SiLib::HwlSelectTileMode(
3442     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
3443     ) const
3444 {
3445     AddrTileMode tileMode;
3446     AddrTileType tileType;
3447 
3448     if (pInOut->flags.volume)
3449     {
3450         if (pInOut->numSlices >= 8)
3451         {
3452             tileMode = ADDR_TM_2D_TILED_XTHICK;
3453         }
3454         else if (pInOut->numSlices >= 4)
3455         {
3456             tileMode = ADDR_TM_2D_TILED_THICK;
3457         }
3458         else
3459         {
3460             tileMode = ADDR_TM_2D_TILED_THIN1;
3461         }
3462         tileType = ADDR_NON_DISPLAYABLE;
3463     }
3464     else
3465     {
3466         tileMode = ADDR_TM_2D_TILED_THIN1;
3467 
3468         if (pInOut->flags.depth || pInOut->flags.stencil)
3469         {
3470             tileType = ADDR_DEPTH_SAMPLE_ORDER;
3471         }
3472         else if ((pInOut->bpp <= 32) ||
3473                  (pInOut->flags.display == TRUE) ||
3474                  (pInOut->flags.overlay == TRUE))
3475         {
3476             tileType = ADDR_DISPLAYABLE;
3477         }
3478         else
3479         {
3480             tileType = ADDR_NON_DISPLAYABLE;
3481         }
3482     }
3483 
3484     if (pInOut->flags.prt)
3485     {
3486         tileMode = ADDR_TM_2D_TILED_THIN1;
3487         tileType = (tileType == ADDR_DISPLAYABLE) ? ADDR_NON_DISPLAYABLE : tileType;
3488     }
3489 
3490     pInOut->tileMode = tileMode;
3491     pInOut->tileType = tileType;
3492 
3493     // Optimize tile mode if possible
3494     pInOut->flags.opt4Space = TRUE;
3495 
3496     // Optimize tile mode if possible
3497     OptimizeTileMode(pInOut);
3498 
3499     HwlOverrideTileMode(pInOut);
3500 }
3501 
3502 /**
3503 ****************************************************************************************************
3504 *   SiLib::HwlComputeMaxBaseAlignments
3505 *
3506 *   @brief
3507 *       Gets maximum alignments
3508 *   @return
3509 *       maximum alignments
3510 ****************************************************************************************************
3511 */
HwlComputeMaxBaseAlignments() const3512 UINT_32 SiLib::HwlComputeMaxBaseAlignments() const
3513 {
3514     const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info);
3515 
3516     // Initial size is 64 KiB for PRT.
3517     UINT_32 maxBaseAlign = 64 * 1024;
3518 
3519     for (UINT_32 i = 0; i < m_noOfEntries; i++)
3520     {
3521         if ((IsMacroTiled(m_tileTable[i].mode) == TRUE) &&
3522             (IsPrtTileMode(m_tileTable[i].mode) == FALSE))
3523         {
3524             // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
3525             UINT_32 tileSize = Min(m_tileTable[i].info.tileSplitBytes,
3526                                    MicroTilePixels * 8 * 16);
3527 
3528             UINT_32 baseAlign = tileSize * pipes * m_tileTable[i].info.banks *
3529                                 m_tileTable[i].info.bankWidth * m_tileTable[i].info.bankHeight;
3530 
3531             if (baseAlign > maxBaseAlign)
3532             {
3533                 maxBaseAlign = baseAlign;
3534             }
3535         }
3536     }
3537 
3538     return maxBaseAlign;
3539 }
3540 
3541 /**
3542 ****************************************************************************************************
3543 *   SiLib::HwlComputeMaxMetaBaseAlignments
3544 *
3545 *   @brief
3546 *       Gets maximum alignments for metadata
3547 *   @return
3548 *       maximum alignments for metadata
3549 ****************************************************************************************************
3550 */
HwlComputeMaxMetaBaseAlignments() const3551 UINT_32 SiLib::HwlComputeMaxMetaBaseAlignments() const
3552 {
3553     UINT_32 maxPipe = 1;
3554 
3555     for (UINT_32 i = 0; i < m_noOfEntries; i++)
3556     {
3557         maxPipe = Max(maxPipe, HwlGetPipes(&m_tileTable[i].info));
3558     }
3559 
3560     return m_pipeInterleaveBytes * maxPipe;
3561 }
3562 
3563 /**
3564 ****************************************************************************************************
3565 *   SiLib::HwlComputeSurfaceAlignmentsMacroTiled
3566 *
3567 *   @brief
3568 *       Hardware layer function to compute alignment request for macro tile mode
3569 *
3570 *   @return
3571 *       N/A
3572 *
3573 ****************************************************************************************************
3574 */
HwlComputeSurfaceAlignmentsMacroTiled(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 mipLevel,UINT_32 numSamples,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const3575 VOID SiLib::HwlComputeSurfaceAlignmentsMacroTiled(
3576     AddrTileMode                      tileMode,           ///< [in] tile mode
3577     UINT_32                           bpp,                ///< [in] bits per pixel
3578     ADDR_SURFACE_FLAGS                flags,              ///< [in] surface flags
3579     UINT_32                           mipLevel,           ///< [in] mip level
3580     UINT_32                           numSamples,         ///< [in] number of samples
3581     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut                ///< [in,out] Surface output
3582     ) const
3583 {
3584     if ((mipLevel == 0) && (flags.prt))
3585     {
3586         UINT_32 macroTileSize = pOut->blockWidth * pOut->blockHeight * numSamples * bpp / 8;
3587 
3588         if (macroTileSize < PrtTileSize)
3589         {
3590             UINT_32 numMacroTiles = PrtTileSize / macroTileSize;
3591 
3592             ADDR_ASSERT((PrtTileSize % macroTileSize) == 0);
3593 
3594             pOut->pitchAlign *= numMacroTiles;
3595             pOut->baseAlign  *= numMacroTiles;
3596         }
3597     }
3598 }
3599 
3600 /**
3601 ****************************************************************************************************
3602 *   SiLib::InitEquationTable
3603 *
3604 *   @brief
3605 *       Initialize Equation table.
3606 *
3607 *   @return
3608 *       N/A
3609 ****************************************************************************************************
3610 */
InitEquationTable()3611 VOID SiLib::InitEquationTable()
3612 {
3613     ADDR_EQUATION_KEY equationKeyTable[EquationTableSize];
3614     memset(equationKeyTable, 0, sizeof(equationKeyTable));
3615 
3616     memset(m_equationTable, 0, sizeof(m_equationTable));
3617 
3618     memset(m_blockWidth, 0, sizeof(m_blockWidth));
3619 
3620     memset(m_blockHeight, 0, sizeof(m_blockHeight));
3621 
3622     memset(m_blockSlices, 0, sizeof(m_blockSlices));
3623 
3624     // Loop all possible bpp
3625     for (UINT_32 log2ElementBytes = 0; log2ElementBytes < MaxNumElementBytes; log2ElementBytes++)
3626     {
3627         // Get bits per pixel
3628         UINT_32 bpp = 1 << (log2ElementBytes + 3);
3629 
3630         // Loop all possible tile index
3631         for (INT_32 tileIndex = 0; tileIndex < static_cast<INT_32>(m_noOfEntries); tileIndex++)
3632         {
3633             UINT_32 equationIndex = ADDR_INVALID_EQUATION_INDEX;
3634 
3635             TileConfig tileConfig = m_tileTable[tileIndex];
3636 
3637             ADDR_SURFACE_FLAGS flags = {{0}};
3638 
3639             // Compute tile info, hardcode numSamples to 1 because MSAA is not supported
3640             // in swizzle pattern equation
3641             HwlComputeMacroModeIndex(tileIndex, flags, bpp, 1, &tileConfig.info, NULL, NULL);
3642 
3643             // Check if the input is supported
3644             if (IsEquationSupported(bpp, tileConfig, tileIndex, log2ElementBytes) == TRUE)
3645             {
3646                 ADDR_EQUATION_KEY  key   = {{0}};
3647 
3648                 // Generate swizzle equation key from bpp and tile config
3649                 key.fields.log2ElementBytes = log2ElementBytes;
3650                 key.fields.tileMode         = tileConfig.mode;
3651                 // Treat depth micro tile type and non-display micro tile type as the same key
3652                 // because they have the same equation actually
3653                 key.fields.microTileType    = (tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) ?
3654                                               ADDR_NON_DISPLAYABLE : tileConfig.type;
3655                 key.fields.pipeConfig       = tileConfig.info.pipeConfig;
3656                 key.fields.numBanksLog2     = Log2(tileConfig.info.banks);
3657                 key.fields.bankWidth        = tileConfig.info.bankWidth;
3658                 key.fields.bankHeight       = tileConfig.info.bankHeight;
3659                 key.fields.macroAspectRatio = tileConfig.info.macroAspectRatio;
3660                 key.fields.prt              = ((m_chipFamily == ADDR_CHIP_FAMILY_SI) &&
3661                                                ((1 << tileIndex) & SiPrtTileIndexMask)) ? 1 : 0;
3662 
3663                 // Find in the table if the equation has been built based on the key
3664                 for (UINT_32 i = 0; i < m_numEquations; i++)
3665                 {
3666                     if (key.value == equationKeyTable[i].value)
3667                     {
3668                         equationIndex = i;
3669                         break;
3670                     }
3671                 }
3672 
3673                 // If found, just fill the index into the lookup table and no need
3674                 // to generate the equation again. Otherwise, generate the equation.
3675                 if (equationIndex == ADDR_INVALID_EQUATION_INDEX)
3676                 {
3677                     ADDR_EQUATION equation;
3678                     ADDR_E_RETURNCODE retCode;
3679 
3680                     memset(&equation, 0, sizeof(ADDR_EQUATION));
3681 
3682                     // Generate the equation
3683                     if (IsMicroTiled(tileConfig.mode))
3684                     {
3685                         retCode = ComputeMicroTileEquation(log2ElementBytes,
3686                                                            tileConfig.mode,
3687                                                            tileConfig.type,
3688                                                            &equation);
3689                     }
3690                     else
3691                     {
3692                         retCode = ComputeMacroTileEquation(log2ElementBytes,
3693                                                            tileConfig.mode,
3694                                                            tileConfig.type,
3695                                                            &tileConfig.info,
3696                                                            &equation);
3697                     }
3698                     // Only fill the equation into the table if the return code is ADDR_OK,
3699                     // otherwise if the return code is not ADDR_OK, it indicates this is not
3700                     // a valid input, we do nothing but just fill invalid equation index
3701                     // into the lookup table.
3702                     if (retCode == ADDR_OK)
3703                     {
3704                         equationIndex = m_numEquations;
3705                         ADDR_ASSERT(equationIndex < EquationTableSize);
3706 
3707                         m_blockSlices[equationIndex] = Thickness(tileConfig.mode);
3708 
3709                         if (IsMicroTiled(tileConfig.mode))
3710                         {
3711                             m_blockWidth[equationIndex]  = MicroTileWidth;
3712                             m_blockHeight[equationIndex] = MicroTileHeight;
3713                         }
3714                         else
3715                         {
3716                             const ADDR_TILEINFO* pTileInfo = &tileConfig.info;
3717 
3718                             m_blockWidth[equationIndex]  =
3719                                 HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth *
3720                                 pTileInfo->macroAspectRatio;
3721                             m_blockHeight[equationIndex] =
3722                                 MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
3723                                 pTileInfo->macroAspectRatio;
3724 
3725                             if (key.fields.prt)
3726                             {
3727                                 UINT_32 macroTileSize =
3728                                     m_blockWidth[equationIndex] * m_blockHeight[equationIndex] *
3729                                     bpp / 8;
3730 
3731                                 if (macroTileSize < PrtTileSize)
3732                                 {
3733                                     UINT_32 numMacroTiles = PrtTileSize / macroTileSize;
3734 
3735                                     ADDR_ASSERT(macroTileSize == (1u << equation.numBits));
3736                                     ADDR_ASSERT((PrtTileSize % macroTileSize) == 0);
3737 
3738                                     UINT_32 numBits = Log2(numMacroTiles);
3739 
3740                                     UINT_32 xStart = Log2(m_blockWidth[equationIndex]) +
3741                                                      log2ElementBytes;
3742 
3743                                     m_blockWidth[equationIndex] *= numMacroTiles;
3744 
3745                                     for (UINT_32 i = 0; i < numBits; i++)
3746                                     {
3747                                         equation.addr[equation.numBits + i].valid = 1;
3748                                         equation.addr[equation.numBits + i].index = xStart + i;
3749                                     }
3750 
3751                                     equation.numBits += numBits;
3752                                 }
3753                             }
3754                         }
3755 
3756                         equationKeyTable[equationIndex] = key;
3757                         m_equationTable[equationIndex]  = equation;
3758 
3759                         m_numEquations++;
3760                     }
3761                 }
3762             }
3763 
3764             // Fill the index into the lookup table, if the combination is not supported
3765             // fill the invalid equation index
3766             m_equationLookupTable[log2ElementBytes][tileIndex] = equationIndex;
3767         }
3768 
3769         if (m_chipFamily == ADDR_CHIP_FAMILY_SI)
3770         {
3771             // For tile index 3 which is shared between PRT depth and uncompressed depth
3772             m_uncompressDepthEqIndex = m_numEquations;
3773 
3774             for (UINT_32 log2ElemBytes = 0; log2ElemBytes < MaxNumElementBytes; log2ElemBytes++)
3775             {
3776                 TileConfig        tileConfig = m_tileTable[3];
3777                 ADDR_EQUATION     equation;
3778                 ADDR_E_RETURNCODE retCode;
3779 
3780                 memset(&equation, 0, sizeof(ADDR_EQUATION));
3781 
3782                 retCode = ComputeMacroTileEquation(log2ElemBytes,
3783                                                    tileConfig.mode,
3784                                                    tileConfig.type,
3785                                                    &tileConfig.info,
3786                                                    &equation);
3787 
3788                 if (retCode == ADDR_OK)
3789                 {
3790                     UINT_32 equationIndex = m_numEquations;
3791                     ADDR_ASSERT(equationIndex < EquationTableSize);
3792 
3793                     m_blockSlices[equationIndex] = 1;
3794 
3795                     const ADDR_TILEINFO* pTileInfo = &tileConfig.info;
3796 
3797                     m_blockWidth[equationIndex]  =
3798                         HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth *
3799                         pTileInfo->macroAspectRatio;
3800                     m_blockHeight[equationIndex] =
3801                         MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
3802                         pTileInfo->macroAspectRatio;
3803 
3804                     m_equationTable[equationIndex] = equation;
3805 
3806                     m_numEquations++;
3807                 }
3808             }
3809         }
3810     }
3811 }
3812 
3813 /**
3814 ****************************************************************************************************
3815 *   SiLib::IsEquationSupported
3816 *
3817 *   @brief
3818 *       Check if it is supported for given bpp and tile config to generate a equation.
3819 *
3820 *   @return
3821 *       TRUE if supported
3822 ****************************************************************************************************
3823 */
IsEquationSupported(UINT_32 bpp,TileConfig tileConfig,INT_32 tileIndex,UINT_32 elementBytesLog2) const3824 BOOL_32 SiLib::IsEquationSupported(
3825     UINT_32    bpp,             ///< Bits per pixel
3826     TileConfig tileConfig,      ///< Tile config
3827     INT_32     tileIndex,       ///< Tile index
3828     UINT_32    elementBytesLog2 ///< Log2 of element bytes
3829     ) const
3830 {
3831     BOOL_32 supported = TRUE;
3832 
3833     // Linear tile mode is not supported in swizzle pattern equation
3834     if (IsLinear(tileConfig.mode))
3835     {
3836         supported = FALSE;
3837     }
3838     // These tile modes are for Tex2DArray and Tex3D which has depth (num_slice > 1) use,
3839     // which is not supported in swizzle pattern equation due to slice rotation
3840     else if ((tileConfig.mode == ADDR_TM_2D_TILED_THICK)  ||
3841              (tileConfig.mode == ADDR_TM_2D_TILED_XTHICK) ||
3842              (tileConfig.mode == ADDR_TM_3D_TILED_THIN1)  ||
3843              (tileConfig.mode == ADDR_TM_3D_TILED_THICK)  ||
3844              (tileConfig.mode == ADDR_TM_3D_TILED_XTHICK))
3845     {
3846         supported = FALSE;
3847     }
3848     // Only 8bpp(stencil), 16bpp and 32bpp is supported for depth
3849     else if ((tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) && (bpp > 32))
3850     {
3851         supported = FALSE;
3852     }
3853     // Tile split is not supported in swizzle pattern equation
3854     else if (IsMacroTiled(tileConfig.mode))
3855     {
3856         UINT_32 thickness = Thickness(tileConfig.mode);
3857         if (((bpp >> 3) * MicroTilePixels * thickness) > tileConfig.info.tileSplitBytes)
3858         {
3859             supported = FALSE;
3860         }
3861 
3862         if ((supported == TRUE) && (m_chipFamily == ADDR_CHIP_FAMILY_SI))
3863         {
3864             supported = m_EquationSupport[tileIndex][elementBytesLog2];
3865         }
3866     }
3867 
3868     return supported;
3869 }
3870 
3871 } // V1
3872 } // Addr
3873