xref: /aosp_15_r20/external/libdrm/radeon/radeon_surface.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1*7688df22SAndroid Build Coastguard Worker /*
2*7688df22SAndroid Build Coastguard Worker  * Copyright © 2011 Red Hat All Rights Reserved.
3*7688df22SAndroid Build Coastguard Worker  *
4*7688df22SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
5*7688df22SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files (the
6*7688df22SAndroid Build Coastguard Worker  * "Software"), to deal in the Software without restriction, including
7*7688df22SAndroid Build Coastguard Worker  * without limitation the rights to use, copy, modify, merge, publish,
8*7688df22SAndroid Build Coastguard Worker  * distribute, sub license, and/or sell copies of the Software, and to
9*7688df22SAndroid Build Coastguard Worker  * permit persons to whom the Software is furnished to do so, subject to
10*7688df22SAndroid Build Coastguard Worker  * the following conditions:
11*7688df22SAndroid Build Coastguard Worker  *
12*7688df22SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13*7688df22SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
14*7688df22SAndroid Build Coastguard Worker  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15*7688df22SAndroid Build Coastguard Worker  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
16*7688df22SAndroid Build Coastguard Worker  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17*7688df22SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18*7688df22SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19*7688df22SAndroid Build Coastguard Worker  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20*7688df22SAndroid Build Coastguard Worker  *
21*7688df22SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the
22*7688df22SAndroid Build Coastguard Worker  * next paragraph) shall be included in all copies or substantial portions
23*7688df22SAndroid Build Coastguard Worker  * of the Software.
24*7688df22SAndroid Build Coastguard Worker  */
25*7688df22SAndroid Build Coastguard Worker /*
26*7688df22SAndroid Build Coastguard Worker  * Authors:
27*7688df22SAndroid Build Coastguard Worker  *      Jérôme Glisse <[email protected]>
28*7688df22SAndroid Build Coastguard Worker  */
29*7688df22SAndroid Build Coastguard Worker #include <stdbool.h>
30*7688df22SAndroid Build Coastguard Worker #include <assert.h>
31*7688df22SAndroid Build Coastguard Worker #include <errno.h>
32*7688df22SAndroid Build Coastguard Worker #include <stdio.h>
33*7688df22SAndroid Build Coastguard Worker #include <stdlib.h>
34*7688df22SAndroid Build Coastguard Worker #include <string.h>
35*7688df22SAndroid Build Coastguard Worker #include <sys/ioctl.h>
36*7688df22SAndroid Build Coastguard Worker #include "drm.h"
37*7688df22SAndroid Build Coastguard Worker #include "libdrm_macros.h"
38*7688df22SAndroid Build Coastguard Worker #include "xf86drm.h"
39*7688df22SAndroid Build Coastguard Worker #include "radeon_drm.h"
40*7688df22SAndroid Build Coastguard Worker #include "radeon_surface.h"
41*7688df22SAndroid Build Coastguard Worker 
42*7688df22SAndroid Build Coastguard Worker #define CIK_TILE_MODE_COLOR_2D			14
43*7688df22SAndroid Build Coastguard Worker #define CIK_TILE_MODE_COLOR_2D_SCANOUT		10
44*7688df22SAndroid Build Coastguard Worker #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64       0
45*7688df22SAndroid Build Coastguard Worker #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128      1
46*7688df22SAndroid Build Coastguard Worker #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256      2
47*7688df22SAndroid Build Coastguard Worker #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512      3
48*7688df22SAndroid Build Coastguard Worker #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE 4
49*7688df22SAndroid Build Coastguard Worker 
50*7688df22SAndroid Build Coastguard Worker #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
51*7688df22SAndroid Build Coastguard Worker #define MAX2(A, B)              ((A) > (B) ? (A) : (B))
52*7688df22SAndroid Build Coastguard Worker #define MIN2(A, B)              ((A) < (B) ? (A) : (B))
53*7688df22SAndroid Build Coastguard Worker 
54*7688df22SAndroid Build Coastguard Worker /* keep this private */
55*7688df22SAndroid Build Coastguard Worker enum radeon_family {
56*7688df22SAndroid Build Coastguard Worker     CHIP_UNKNOWN,
57*7688df22SAndroid Build Coastguard Worker     CHIP_R600,
58*7688df22SAndroid Build Coastguard Worker     CHIP_RV610,
59*7688df22SAndroid Build Coastguard Worker     CHIP_RV630,
60*7688df22SAndroid Build Coastguard Worker     CHIP_RV670,
61*7688df22SAndroid Build Coastguard Worker     CHIP_RV620,
62*7688df22SAndroid Build Coastguard Worker     CHIP_RV635,
63*7688df22SAndroid Build Coastguard Worker     CHIP_RS780,
64*7688df22SAndroid Build Coastguard Worker     CHIP_RS880,
65*7688df22SAndroid Build Coastguard Worker     CHIP_RV770,
66*7688df22SAndroid Build Coastguard Worker     CHIP_RV730,
67*7688df22SAndroid Build Coastguard Worker     CHIP_RV710,
68*7688df22SAndroid Build Coastguard Worker     CHIP_RV740,
69*7688df22SAndroid Build Coastguard Worker     CHIP_CEDAR,
70*7688df22SAndroid Build Coastguard Worker     CHIP_REDWOOD,
71*7688df22SAndroid Build Coastguard Worker     CHIP_JUNIPER,
72*7688df22SAndroid Build Coastguard Worker     CHIP_CYPRESS,
73*7688df22SAndroid Build Coastguard Worker     CHIP_HEMLOCK,
74*7688df22SAndroid Build Coastguard Worker     CHIP_PALM,
75*7688df22SAndroid Build Coastguard Worker     CHIP_SUMO,
76*7688df22SAndroid Build Coastguard Worker     CHIP_SUMO2,
77*7688df22SAndroid Build Coastguard Worker     CHIP_BARTS,
78*7688df22SAndroid Build Coastguard Worker     CHIP_TURKS,
79*7688df22SAndroid Build Coastguard Worker     CHIP_CAICOS,
80*7688df22SAndroid Build Coastguard Worker     CHIP_CAYMAN,
81*7688df22SAndroid Build Coastguard Worker     CHIP_ARUBA,
82*7688df22SAndroid Build Coastguard Worker     CHIP_TAHITI,
83*7688df22SAndroid Build Coastguard Worker     CHIP_PITCAIRN,
84*7688df22SAndroid Build Coastguard Worker     CHIP_VERDE,
85*7688df22SAndroid Build Coastguard Worker     CHIP_OLAND,
86*7688df22SAndroid Build Coastguard Worker     CHIP_HAINAN,
87*7688df22SAndroid Build Coastguard Worker     CHIP_BONAIRE,
88*7688df22SAndroid Build Coastguard Worker     CHIP_KAVERI,
89*7688df22SAndroid Build Coastguard Worker     CHIP_KABINI,
90*7688df22SAndroid Build Coastguard Worker     CHIP_HAWAII,
91*7688df22SAndroid Build Coastguard Worker     CHIP_MULLINS,
92*7688df22SAndroid Build Coastguard Worker     CHIP_LAST,
93*7688df22SAndroid Build Coastguard Worker };
94*7688df22SAndroid Build Coastguard Worker 
95*7688df22SAndroid Build Coastguard Worker typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
96*7688df22SAndroid Build Coastguard Worker                                  struct radeon_surface *surf);
97*7688df22SAndroid Build Coastguard Worker typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
98*7688df22SAndroid Build Coastguard Worker                                  struct radeon_surface *surf);
99*7688df22SAndroid Build Coastguard Worker 
100*7688df22SAndroid Build Coastguard Worker struct radeon_hw_info {
101*7688df22SAndroid Build Coastguard Worker     /* apply to r6, eg */
102*7688df22SAndroid Build Coastguard Worker     uint32_t                        group_bytes;
103*7688df22SAndroid Build Coastguard Worker     uint32_t                        num_banks;
104*7688df22SAndroid Build Coastguard Worker     uint32_t                        num_pipes;
105*7688df22SAndroid Build Coastguard Worker     /* apply to eg */
106*7688df22SAndroid Build Coastguard Worker     uint32_t                        row_size;
107*7688df22SAndroid Build Coastguard Worker     unsigned                        allow_2d;
108*7688df22SAndroid Build Coastguard Worker     /* apply to si */
109*7688df22SAndroid Build Coastguard Worker     uint32_t                        tile_mode_array[32];
110*7688df22SAndroid Build Coastguard Worker     /* apply to cik */
111*7688df22SAndroid Build Coastguard Worker     uint32_t                        macrotile_mode_array[16];
112*7688df22SAndroid Build Coastguard Worker };
113*7688df22SAndroid Build Coastguard Worker 
114*7688df22SAndroid Build Coastguard Worker struct radeon_surface_manager {
115*7688df22SAndroid Build Coastguard Worker     int                         fd;
116*7688df22SAndroid Build Coastguard Worker     uint32_t                    device_id;
117*7688df22SAndroid Build Coastguard Worker     struct radeon_hw_info       hw_info;
118*7688df22SAndroid Build Coastguard Worker     unsigned                    family;
119*7688df22SAndroid Build Coastguard Worker     hw_init_surface_t           surface_init;
120*7688df22SAndroid Build Coastguard Worker     hw_best_surface_t           surface_best;
121*7688df22SAndroid Build Coastguard Worker };
122*7688df22SAndroid Build Coastguard Worker 
123*7688df22SAndroid Build Coastguard Worker /* helper */
radeon_get_value(int fd,unsigned req,uint32_t * value)124*7688df22SAndroid Build Coastguard Worker static int radeon_get_value(int fd, unsigned req, uint32_t *value)
125*7688df22SAndroid Build Coastguard Worker {
126*7688df22SAndroid Build Coastguard Worker     struct drm_radeon_info info = {};
127*7688df22SAndroid Build Coastguard Worker     int r;
128*7688df22SAndroid Build Coastguard Worker 
129*7688df22SAndroid Build Coastguard Worker     *value = 0;
130*7688df22SAndroid Build Coastguard Worker     info.request = req;
131*7688df22SAndroid Build Coastguard Worker     info.value = (uintptr_t)value;
132*7688df22SAndroid Build Coastguard Worker     r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
133*7688df22SAndroid Build Coastguard Worker                             sizeof(struct drm_radeon_info));
134*7688df22SAndroid Build Coastguard Worker     return r;
135*7688df22SAndroid Build Coastguard Worker }
136*7688df22SAndroid Build Coastguard Worker 
radeon_get_family(struct radeon_surface_manager * surf_man)137*7688df22SAndroid Build Coastguard Worker static int radeon_get_family(struct radeon_surface_manager *surf_man)
138*7688df22SAndroid Build Coastguard Worker {
139*7688df22SAndroid Build Coastguard Worker     switch (surf_man->device_id) {
140*7688df22SAndroid Build Coastguard Worker #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
141*7688df22SAndroid Build Coastguard Worker #include "r600_pci_ids.h"
142*7688df22SAndroid Build Coastguard Worker #undef CHIPSET
143*7688df22SAndroid Build Coastguard Worker     default:
144*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
145*7688df22SAndroid Build Coastguard Worker     }
146*7688df22SAndroid Build Coastguard Worker     return 0;
147*7688df22SAndroid Build Coastguard Worker }
148*7688df22SAndroid Build Coastguard Worker 
next_power_of_two(unsigned x)149*7688df22SAndroid Build Coastguard Worker static unsigned next_power_of_two(unsigned x)
150*7688df22SAndroid Build Coastguard Worker {
151*7688df22SAndroid Build Coastguard Worker    if (x <= 1)
152*7688df22SAndroid Build Coastguard Worker        return 1;
153*7688df22SAndroid Build Coastguard Worker 
154*7688df22SAndroid Build Coastguard Worker    return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
155*7688df22SAndroid Build Coastguard Worker }
156*7688df22SAndroid Build Coastguard Worker 
mip_minify(unsigned size,unsigned level)157*7688df22SAndroid Build Coastguard Worker static unsigned mip_minify(unsigned size, unsigned level)
158*7688df22SAndroid Build Coastguard Worker {
159*7688df22SAndroid Build Coastguard Worker     unsigned val;
160*7688df22SAndroid Build Coastguard Worker 
161*7688df22SAndroid Build Coastguard Worker     val = MAX2(1, size >> level);
162*7688df22SAndroid Build Coastguard Worker     if (level > 0)
163*7688df22SAndroid Build Coastguard Worker         val = next_power_of_two(val);
164*7688df22SAndroid Build Coastguard Worker     return val;
165*7688df22SAndroid Build Coastguard Worker }
166*7688df22SAndroid Build Coastguard Worker 
surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,uint32_t xalign,uint32_t yalign,uint32_t zalign,uint64_t offset)167*7688df22SAndroid Build Coastguard Worker static void surf_minify(struct radeon_surface *surf,
168*7688df22SAndroid Build Coastguard Worker                         struct radeon_surface_level *surflevel,
169*7688df22SAndroid Build Coastguard Worker                         unsigned bpe, unsigned level,
170*7688df22SAndroid Build Coastguard Worker                         uint32_t xalign, uint32_t yalign, uint32_t zalign,
171*7688df22SAndroid Build Coastguard Worker                         uint64_t offset)
172*7688df22SAndroid Build Coastguard Worker {
173*7688df22SAndroid Build Coastguard Worker     surflevel->npix_x = mip_minify(surf->npix_x, level);
174*7688df22SAndroid Build Coastguard Worker     surflevel->npix_y = mip_minify(surf->npix_y, level);
175*7688df22SAndroid Build Coastguard Worker     surflevel->npix_z = mip_minify(surf->npix_z, level);
176*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
177*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
178*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
179*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
180*7688df22SAndroid Build Coastguard Worker         !(surf->flags & RADEON_SURF_FMASK)) {
181*7688df22SAndroid Build Coastguard Worker         if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
182*7688df22SAndroid Build Coastguard Worker             surflevel->mode = RADEON_SURF_MODE_1D;
183*7688df22SAndroid Build Coastguard Worker             return;
184*7688df22SAndroid Build Coastguard Worker         }
185*7688df22SAndroid Build Coastguard Worker     }
186*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
187*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
188*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
189*7688df22SAndroid Build Coastguard Worker 
190*7688df22SAndroid Build Coastguard Worker     surflevel->offset = offset;
191*7688df22SAndroid Build Coastguard Worker     surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
192*7688df22SAndroid Build Coastguard Worker     surflevel->slice_size = (uint64_t)surflevel->pitch_bytes * surflevel->nblk_y;
193*7688df22SAndroid Build Coastguard Worker 
194*7688df22SAndroid Build Coastguard Worker     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
195*7688df22SAndroid Build Coastguard Worker }
196*7688df22SAndroid Build Coastguard Worker 
197*7688df22SAndroid Build Coastguard Worker /* ===========================================================================
198*7688df22SAndroid Build Coastguard Worker  * r600/r700 family
199*7688df22SAndroid Build Coastguard Worker  */
r6_init_hw_info(struct radeon_surface_manager * surf_man)200*7688df22SAndroid Build Coastguard Worker static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
201*7688df22SAndroid Build Coastguard Worker {
202*7688df22SAndroid Build Coastguard Worker     uint32_t tiling_config;
203*7688df22SAndroid Build Coastguard Worker     drmVersionPtr version;
204*7688df22SAndroid Build Coastguard Worker     int r;
205*7688df22SAndroid Build Coastguard Worker 
206*7688df22SAndroid Build Coastguard Worker     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
207*7688df22SAndroid Build Coastguard Worker                          &tiling_config);
208*7688df22SAndroid Build Coastguard Worker     if (r) {
209*7688df22SAndroid Build Coastguard Worker         return r;
210*7688df22SAndroid Build Coastguard Worker     }
211*7688df22SAndroid Build Coastguard Worker 
212*7688df22SAndroid Build Coastguard Worker     surf_man->hw_info.allow_2d = 0;
213*7688df22SAndroid Build Coastguard Worker     version = drmGetVersion(surf_man->fd);
214*7688df22SAndroid Build Coastguard Worker     if (version && version->version_minor >= 14) {
215*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 1;
216*7688df22SAndroid Build Coastguard Worker     }
217*7688df22SAndroid Build Coastguard Worker     drmFreeVersion(version);
218*7688df22SAndroid Build Coastguard Worker 
219*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xe) >> 1) {
220*7688df22SAndroid Build Coastguard Worker     case 0:
221*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 1;
222*7688df22SAndroid Build Coastguard Worker         break;
223*7688df22SAndroid Build Coastguard Worker     case 1:
224*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 2;
225*7688df22SAndroid Build Coastguard Worker         break;
226*7688df22SAndroid Build Coastguard Worker     case 2:
227*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 4;
228*7688df22SAndroid Build Coastguard Worker         break;
229*7688df22SAndroid Build Coastguard Worker     case 3:
230*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
231*7688df22SAndroid Build Coastguard Worker         break;
232*7688df22SAndroid Build Coastguard Worker     default:
233*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
234*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
235*7688df22SAndroid Build Coastguard Worker         break;
236*7688df22SAndroid Build Coastguard Worker     }
237*7688df22SAndroid Build Coastguard Worker 
238*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0x30) >> 4) {
239*7688df22SAndroid Build Coastguard Worker     case 0:
240*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 4;
241*7688df22SAndroid Build Coastguard Worker         break;
242*7688df22SAndroid Build Coastguard Worker     case 1:
243*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
244*7688df22SAndroid Build Coastguard Worker         break;
245*7688df22SAndroid Build Coastguard Worker     default:
246*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
247*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
248*7688df22SAndroid Build Coastguard Worker         break;
249*7688df22SAndroid Build Coastguard Worker     }
250*7688df22SAndroid Build Coastguard Worker 
251*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xc0) >> 6) {
252*7688df22SAndroid Build Coastguard Worker     case 0:
253*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
254*7688df22SAndroid Build Coastguard Worker         break;
255*7688df22SAndroid Build Coastguard Worker     case 1:
256*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 512;
257*7688df22SAndroid Build Coastguard Worker         break;
258*7688df22SAndroid Build Coastguard Worker     default:
259*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
260*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
261*7688df22SAndroid Build Coastguard Worker         break;
262*7688df22SAndroid Build Coastguard Worker     }
263*7688df22SAndroid Build Coastguard Worker     return 0;
264*7688df22SAndroid Build Coastguard Worker }
265*7688df22SAndroid Build Coastguard Worker 
r6_surface_init_linear(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)266*7688df22SAndroid Build Coastguard Worker static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
267*7688df22SAndroid Build Coastguard Worker                                   struct radeon_surface *surf,
268*7688df22SAndroid Build Coastguard Worker                                   uint64_t offset, unsigned start_level)
269*7688df22SAndroid Build Coastguard Worker {
270*7688df22SAndroid Build Coastguard Worker     uint32_t xalign, yalign, zalign;
271*7688df22SAndroid Build Coastguard Worker     unsigned i;
272*7688df22SAndroid Build Coastguard Worker 
273*7688df22SAndroid Build Coastguard Worker     /* compute alignment */
274*7688df22SAndroid Build Coastguard Worker     if (!start_level) {
275*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
276*7688df22SAndroid Build Coastguard Worker     }
277*7688df22SAndroid Build Coastguard Worker     /* the 32 alignment is for scanout, cb or db but to allow texture to be
278*7688df22SAndroid Build Coastguard Worker      * easily bound as such we force this alignment to all surface
279*7688df22SAndroid Build Coastguard Worker      */
280*7688df22SAndroid Build Coastguard Worker     xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
281*7688df22SAndroid Build Coastguard Worker     yalign = 1;
282*7688df22SAndroid Build Coastguard Worker     zalign = 1;
283*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SCANOUT) {
284*7688df22SAndroid Build Coastguard Worker         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
285*7688df22SAndroid Build Coastguard Worker     }
286*7688df22SAndroid Build Coastguard Worker 
287*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
288*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
289*7688df22SAndroid Build Coastguard Worker         surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
290*7688df22SAndroid Build Coastguard Worker         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
291*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
292*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
293*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
294*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, surf->bo_alignment);
295*7688df22SAndroid Build Coastguard Worker         }
296*7688df22SAndroid Build Coastguard Worker     }
297*7688df22SAndroid Build Coastguard Worker     return 0;
298*7688df22SAndroid Build Coastguard Worker }
299*7688df22SAndroid Build Coastguard Worker 
r6_surface_init_linear_aligned(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)300*7688df22SAndroid Build Coastguard Worker static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
301*7688df22SAndroid Build Coastguard Worker                                           struct radeon_surface *surf,
302*7688df22SAndroid Build Coastguard Worker                                           uint64_t offset, unsigned start_level)
303*7688df22SAndroid Build Coastguard Worker {
304*7688df22SAndroid Build Coastguard Worker     uint32_t xalign, yalign, zalign;
305*7688df22SAndroid Build Coastguard Worker     unsigned i;
306*7688df22SAndroid Build Coastguard Worker 
307*7688df22SAndroid Build Coastguard Worker     /* compute alignment */
308*7688df22SAndroid Build Coastguard Worker     if (!start_level) {
309*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
310*7688df22SAndroid Build Coastguard Worker     }
311*7688df22SAndroid Build Coastguard Worker     xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
312*7688df22SAndroid Build Coastguard Worker     yalign = 1;
313*7688df22SAndroid Build Coastguard Worker     zalign = 1;
314*7688df22SAndroid Build Coastguard Worker 
315*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
316*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
317*7688df22SAndroid Build Coastguard Worker         surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
318*7688df22SAndroid Build Coastguard Worker         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
319*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
320*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
321*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
322*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, surf->bo_alignment);
323*7688df22SAndroid Build Coastguard Worker         }
324*7688df22SAndroid Build Coastguard Worker     }
325*7688df22SAndroid Build Coastguard Worker     return 0;
326*7688df22SAndroid Build Coastguard Worker }
327*7688df22SAndroid Build Coastguard Worker 
r6_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)328*7688df22SAndroid Build Coastguard Worker static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
329*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface *surf,
330*7688df22SAndroid Build Coastguard Worker                               uint64_t offset, unsigned start_level)
331*7688df22SAndroid Build Coastguard Worker {
332*7688df22SAndroid Build Coastguard Worker     uint32_t xalign, yalign, zalign, tilew;
333*7688df22SAndroid Build Coastguard Worker     unsigned i;
334*7688df22SAndroid Build Coastguard Worker 
335*7688df22SAndroid Build Coastguard Worker     /* compute alignment */
336*7688df22SAndroid Build Coastguard Worker     tilew = 8;
337*7688df22SAndroid Build Coastguard Worker     xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
338*7688df22SAndroid Build Coastguard Worker     xalign = MAX2(tilew, xalign);
339*7688df22SAndroid Build Coastguard Worker     yalign = tilew;
340*7688df22SAndroid Build Coastguard Worker     zalign = 1;
341*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SCANOUT) {
342*7688df22SAndroid Build Coastguard Worker         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
343*7688df22SAndroid Build Coastguard Worker     }
344*7688df22SAndroid Build Coastguard Worker     if (!start_level) {
345*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
346*7688df22SAndroid Build Coastguard Worker     }
347*7688df22SAndroid Build Coastguard Worker 
348*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
349*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
350*7688df22SAndroid Build Coastguard Worker         surf->level[i].mode = RADEON_SURF_MODE_1D;
351*7688df22SAndroid Build Coastguard Worker         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
352*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
353*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
354*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
355*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, surf->bo_alignment);
356*7688df22SAndroid Build Coastguard Worker         }
357*7688df22SAndroid Build Coastguard Worker     }
358*7688df22SAndroid Build Coastguard Worker     return 0;
359*7688df22SAndroid Build Coastguard Worker }
360*7688df22SAndroid Build Coastguard Worker 
r6_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)361*7688df22SAndroid Build Coastguard Worker static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
362*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface *surf,
363*7688df22SAndroid Build Coastguard Worker                               uint64_t offset, unsigned start_level)
364*7688df22SAndroid Build Coastguard Worker {
365*7688df22SAndroid Build Coastguard Worker     uint32_t xalign, yalign, zalign, tilew;
366*7688df22SAndroid Build Coastguard Worker     unsigned i;
367*7688df22SAndroid Build Coastguard Worker 
368*7688df22SAndroid Build Coastguard Worker     /* compute alignment */
369*7688df22SAndroid Build Coastguard Worker     tilew = 8;
370*7688df22SAndroid Build Coastguard Worker     zalign = 1;
371*7688df22SAndroid Build Coastguard Worker     xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
372*7688df22SAndroid Build Coastguard Worker              (tilew * surf->bpe * surf->nsamples);
373*7688df22SAndroid Build Coastguard Worker     xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
374*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_FMASK)
375*7688df22SAndroid Build Coastguard Worker 	xalign = MAX2(128, xalign);
376*7688df22SAndroid Build Coastguard Worker     yalign = tilew * surf_man->hw_info.num_pipes;
377*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SCANOUT) {
378*7688df22SAndroid Build Coastguard Worker         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
379*7688df22SAndroid Build Coastguard Worker     }
380*7688df22SAndroid Build Coastguard Worker     if (!start_level) {
381*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment =
382*7688df22SAndroid Build Coastguard Worker             MAX2(surf_man->hw_info.num_pipes *
383*7688df22SAndroid Build Coastguard Worker                  surf_man->hw_info.num_banks *
384*7688df22SAndroid Build Coastguard Worker                  surf->nsamples * surf->bpe * 64,
385*7688df22SAndroid Build Coastguard Worker                  xalign * yalign * surf->nsamples * surf->bpe);
386*7688df22SAndroid Build Coastguard Worker     }
387*7688df22SAndroid Build Coastguard Worker 
388*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
389*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
390*7688df22SAndroid Build Coastguard Worker         surf->level[i].mode = RADEON_SURF_MODE_2D;
391*7688df22SAndroid Build Coastguard Worker         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
392*7688df22SAndroid Build Coastguard Worker         if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
393*7688df22SAndroid Build Coastguard Worker             return r6_surface_init_1d(surf_man, surf, offset, i);
394*7688df22SAndroid Build Coastguard Worker         }
395*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
396*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
397*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
398*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, surf->bo_alignment);
399*7688df22SAndroid Build Coastguard Worker         }
400*7688df22SAndroid Build Coastguard Worker     }
401*7688df22SAndroid Build Coastguard Worker     return 0;
402*7688df22SAndroid Build Coastguard Worker }
403*7688df22SAndroid Build Coastguard Worker 
r6_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)404*7688df22SAndroid Build Coastguard Worker static int r6_surface_init(struct radeon_surface_manager *surf_man,
405*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface *surf)
406*7688df22SAndroid Build Coastguard Worker {
407*7688df22SAndroid Build Coastguard Worker     unsigned mode;
408*7688df22SAndroid Build Coastguard Worker     int r;
409*7688df22SAndroid Build Coastguard Worker 
410*7688df22SAndroid Build Coastguard Worker     /* MSAA surfaces support the 2D mode only. */
411*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples > 1) {
412*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
413*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
414*7688df22SAndroid Build Coastguard Worker     }
415*7688df22SAndroid Build Coastguard Worker 
416*7688df22SAndroid Build Coastguard Worker     /* tiling mode */
417*7688df22SAndroid Build Coastguard Worker     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
418*7688df22SAndroid Build Coastguard Worker 
419*7688df22SAndroid Build Coastguard Worker     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
420*7688df22SAndroid Build Coastguard Worker         /* zbuffer only support 1D or 2D tiled surface */
421*7688df22SAndroid Build Coastguard Worker         switch (mode) {
422*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_1D:
423*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_2D:
424*7688df22SAndroid Build Coastguard Worker             break;
425*7688df22SAndroid Build Coastguard Worker         default:
426*7688df22SAndroid Build Coastguard Worker             mode = RADEON_SURF_MODE_1D;
427*7688df22SAndroid Build Coastguard Worker             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
428*7688df22SAndroid Build Coastguard Worker             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
429*7688df22SAndroid Build Coastguard Worker             break;
430*7688df22SAndroid Build Coastguard Worker         }
431*7688df22SAndroid Build Coastguard Worker     }
432*7688df22SAndroid Build Coastguard Worker 
433*7688df22SAndroid Build Coastguard Worker     /* force 1d on kernel that can't do 2d */
434*7688df22SAndroid Build Coastguard Worker     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
435*7688df22SAndroid Build Coastguard Worker         if (surf->nsamples > 1) {
436*7688df22SAndroid Build Coastguard Worker             fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
437*7688df22SAndroid Build Coastguard Worker             return -EFAULT;
438*7688df22SAndroid Build Coastguard Worker         }
439*7688df22SAndroid Build Coastguard Worker         mode = RADEON_SURF_MODE_1D;
440*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
441*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(mode, MODE);
442*7688df22SAndroid Build Coastguard Worker     }
443*7688df22SAndroid Build Coastguard Worker 
444*7688df22SAndroid Build Coastguard Worker     /* check surface dimension */
445*7688df22SAndroid Build Coastguard Worker     if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
446*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
447*7688df22SAndroid Build Coastguard Worker     }
448*7688df22SAndroid Build Coastguard Worker 
449*7688df22SAndroid Build Coastguard Worker     /* check mipmap last_level */
450*7688df22SAndroid Build Coastguard Worker     if (surf->last_level > 14) {
451*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
452*7688df22SAndroid Build Coastguard Worker     }
453*7688df22SAndroid Build Coastguard Worker 
454*7688df22SAndroid Build Coastguard Worker     /* check tiling mode */
455*7688df22SAndroid Build Coastguard Worker     switch (mode) {
456*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR:
457*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_linear(surf_man, surf, 0, 0);
458*7688df22SAndroid Build Coastguard Worker         break;
459*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR_ALIGNED:
460*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
461*7688df22SAndroid Build Coastguard Worker         break;
462*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_1D:
463*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_1d(surf_man, surf, 0, 0);
464*7688df22SAndroid Build Coastguard Worker         break;
465*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_2D:
466*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_2d(surf_man, surf, 0, 0);
467*7688df22SAndroid Build Coastguard Worker         break;
468*7688df22SAndroid Build Coastguard Worker     default:
469*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
470*7688df22SAndroid Build Coastguard Worker     }
471*7688df22SAndroid Build Coastguard Worker     return r;
472*7688df22SAndroid Build Coastguard Worker }
473*7688df22SAndroid Build Coastguard Worker 
r6_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)474*7688df22SAndroid Build Coastguard Worker static int r6_surface_best(struct radeon_surface_manager *surf_man,
475*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface *surf)
476*7688df22SAndroid Build Coastguard Worker {
477*7688df22SAndroid Build Coastguard Worker     /* no value to optimize for r6xx/r7xx */
478*7688df22SAndroid Build Coastguard Worker     return 0;
479*7688df22SAndroid Build Coastguard Worker }
480*7688df22SAndroid Build Coastguard Worker 
481*7688df22SAndroid Build Coastguard Worker 
482*7688df22SAndroid Build Coastguard Worker /* ===========================================================================
483*7688df22SAndroid Build Coastguard Worker  * evergreen family
484*7688df22SAndroid Build Coastguard Worker  */
eg_init_hw_info(struct radeon_surface_manager * surf_man)485*7688df22SAndroid Build Coastguard Worker static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
486*7688df22SAndroid Build Coastguard Worker {
487*7688df22SAndroid Build Coastguard Worker     uint32_t tiling_config;
488*7688df22SAndroid Build Coastguard Worker     drmVersionPtr version;
489*7688df22SAndroid Build Coastguard Worker     int r;
490*7688df22SAndroid Build Coastguard Worker 
491*7688df22SAndroid Build Coastguard Worker     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
492*7688df22SAndroid Build Coastguard Worker                          &tiling_config);
493*7688df22SAndroid Build Coastguard Worker     if (r) {
494*7688df22SAndroid Build Coastguard Worker         return r;
495*7688df22SAndroid Build Coastguard Worker     }
496*7688df22SAndroid Build Coastguard Worker 
497*7688df22SAndroid Build Coastguard Worker     surf_man->hw_info.allow_2d = 0;
498*7688df22SAndroid Build Coastguard Worker     version = drmGetVersion(surf_man->fd);
499*7688df22SAndroid Build Coastguard Worker     if (version && version->version_minor >= 16) {
500*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 1;
501*7688df22SAndroid Build Coastguard Worker     }
502*7688df22SAndroid Build Coastguard Worker     drmFreeVersion(version);
503*7688df22SAndroid Build Coastguard Worker 
504*7688df22SAndroid Build Coastguard Worker     switch (tiling_config & 0xf) {
505*7688df22SAndroid Build Coastguard Worker     case 0:
506*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 1;
507*7688df22SAndroid Build Coastguard Worker         break;
508*7688df22SAndroid Build Coastguard Worker     case 1:
509*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 2;
510*7688df22SAndroid Build Coastguard Worker         break;
511*7688df22SAndroid Build Coastguard Worker     case 2:
512*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 4;
513*7688df22SAndroid Build Coastguard Worker         break;
514*7688df22SAndroid Build Coastguard Worker     case 3:
515*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
516*7688df22SAndroid Build Coastguard Worker         break;
517*7688df22SAndroid Build Coastguard Worker     default:
518*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
519*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
520*7688df22SAndroid Build Coastguard Worker         break;
521*7688df22SAndroid Build Coastguard Worker     }
522*7688df22SAndroid Build Coastguard Worker 
523*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf0) >> 4) {
524*7688df22SAndroid Build Coastguard Worker     case 0:
525*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 4;
526*7688df22SAndroid Build Coastguard Worker         break;
527*7688df22SAndroid Build Coastguard Worker     case 1:
528*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
529*7688df22SAndroid Build Coastguard Worker         break;
530*7688df22SAndroid Build Coastguard Worker     case 2:
531*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 16;
532*7688df22SAndroid Build Coastguard Worker         break;
533*7688df22SAndroid Build Coastguard Worker     default:
534*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
535*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
536*7688df22SAndroid Build Coastguard Worker         break;
537*7688df22SAndroid Build Coastguard Worker     }
538*7688df22SAndroid Build Coastguard Worker 
539*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf00) >> 8) {
540*7688df22SAndroid Build Coastguard Worker     case 0:
541*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
542*7688df22SAndroid Build Coastguard Worker         break;
543*7688df22SAndroid Build Coastguard Worker     case 1:
544*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 512;
545*7688df22SAndroid Build Coastguard Worker         break;
546*7688df22SAndroid Build Coastguard Worker     default:
547*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
548*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
549*7688df22SAndroid Build Coastguard Worker         break;
550*7688df22SAndroid Build Coastguard Worker     }
551*7688df22SAndroid Build Coastguard Worker 
552*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf000) >> 12) {
553*7688df22SAndroid Build Coastguard Worker     case 0:
554*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 1024;
555*7688df22SAndroid Build Coastguard Worker         break;
556*7688df22SAndroid Build Coastguard Worker     case 1:
557*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 2048;
558*7688df22SAndroid Build Coastguard Worker         break;
559*7688df22SAndroid Build Coastguard Worker     case 2:
560*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 4096;
561*7688df22SAndroid Build Coastguard Worker         break;
562*7688df22SAndroid Build Coastguard Worker     default:
563*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 4096;
564*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
565*7688df22SAndroid Build Coastguard Worker         break;
566*7688df22SAndroid Build Coastguard Worker     }
567*7688df22SAndroid Build Coastguard Worker     return 0;
568*7688df22SAndroid Build Coastguard Worker }
569*7688df22SAndroid Build Coastguard Worker 
eg_surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,unsigned slice_pt,unsigned mtilew,unsigned mtileh,unsigned mtileb,uint64_t offset)570*7688df22SAndroid Build Coastguard Worker static void eg_surf_minify(struct radeon_surface *surf,
571*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface_level *surflevel,
572*7688df22SAndroid Build Coastguard Worker                            unsigned bpe,
573*7688df22SAndroid Build Coastguard Worker                            unsigned level,
574*7688df22SAndroid Build Coastguard Worker                            unsigned slice_pt,
575*7688df22SAndroid Build Coastguard Worker                            unsigned mtilew,
576*7688df22SAndroid Build Coastguard Worker                            unsigned mtileh,
577*7688df22SAndroid Build Coastguard Worker                            unsigned mtileb,
578*7688df22SAndroid Build Coastguard Worker                            uint64_t offset)
579*7688df22SAndroid Build Coastguard Worker {
580*7688df22SAndroid Build Coastguard Worker     unsigned mtile_pr, mtile_ps;
581*7688df22SAndroid Build Coastguard Worker 
582*7688df22SAndroid Build Coastguard Worker     surflevel->npix_x = mip_minify(surf->npix_x, level);
583*7688df22SAndroid Build Coastguard Worker     surflevel->npix_y = mip_minify(surf->npix_y, level);
584*7688df22SAndroid Build Coastguard Worker     surflevel->npix_z = mip_minify(surf->npix_z, level);
585*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
586*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
587*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
588*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
589*7688df22SAndroid Build Coastguard Worker         !(surf->flags & RADEON_SURF_FMASK)) {
590*7688df22SAndroid Build Coastguard Worker         if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
591*7688df22SAndroid Build Coastguard Worker             surflevel->mode = RADEON_SURF_MODE_1D;
592*7688df22SAndroid Build Coastguard Worker             return;
593*7688df22SAndroid Build Coastguard Worker         }
594*7688df22SAndroid Build Coastguard Worker     }
595*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, mtilew);
596*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, mtileh);
597*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, 1);
598*7688df22SAndroid Build Coastguard Worker 
599*7688df22SAndroid Build Coastguard Worker     /* macro tile per row */
600*7688df22SAndroid Build Coastguard Worker     mtile_pr = surflevel->nblk_x / mtilew;
601*7688df22SAndroid Build Coastguard Worker     /* macro tile per slice */
602*7688df22SAndroid Build Coastguard Worker     mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
603*7688df22SAndroid Build Coastguard Worker 
604*7688df22SAndroid Build Coastguard Worker     surflevel->offset = offset;
605*7688df22SAndroid Build Coastguard Worker     surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
606*7688df22SAndroid Build Coastguard Worker     surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
607*7688df22SAndroid Build Coastguard Worker 
608*7688df22SAndroid Build Coastguard Worker     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
609*7688df22SAndroid Build Coastguard Worker }
610*7688df22SAndroid Build Coastguard Worker 
eg_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,uint64_t offset,unsigned start_level)611*7688df22SAndroid Build Coastguard Worker static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
612*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface *surf,
613*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface_level *level,
614*7688df22SAndroid Build Coastguard Worker                               unsigned bpe,
615*7688df22SAndroid Build Coastguard Worker                               uint64_t offset, unsigned start_level)
616*7688df22SAndroid Build Coastguard Worker {
617*7688df22SAndroid Build Coastguard Worker     uint32_t xalign, yalign, zalign, tilew;
618*7688df22SAndroid Build Coastguard Worker     unsigned i;
619*7688df22SAndroid Build Coastguard Worker 
620*7688df22SAndroid Build Coastguard Worker     /* compute alignment */
621*7688df22SAndroid Build Coastguard Worker     tilew = 8;
622*7688df22SAndroid Build Coastguard Worker     xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
623*7688df22SAndroid Build Coastguard Worker     xalign = MAX2(tilew, xalign);
624*7688df22SAndroid Build Coastguard Worker     yalign = tilew;
625*7688df22SAndroid Build Coastguard Worker     zalign = 1;
626*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SCANOUT) {
627*7688df22SAndroid Build Coastguard Worker         xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
628*7688df22SAndroid Build Coastguard Worker     }
629*7688df22SAndroid Build Coastguard Worker 
630*7688df22SAndroid Build Coastguard Worker     if (!start_level) {
631*7688df22SAndroid Build Coastguard Worker         unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
632*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
633*7688df22SAndroid Build Coastguard Worker 
634*7688df22SAndroid Build Coastguard Worker         if (offset) {
635*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, alignment);
636*7688df22SAndroid Build Coastguard Worker         }
637*7688df22SAndroid Build Coastguard Worker     }
638*7688df22SAndroid Build Coastguard Worker 
639*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
640*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
641*7688df22SAndroid Build Coastguard Worker         level[i].mode = RADEON_SURF_MODE_1D;
642*7688df22SAndroid Build Coastguard Worker         surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
643*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
644*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
645*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
646*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, surf->bo_alignment);
647*7688df22SAndroid Build Coastguard Worker         }
648*7688df22SAndroid Build Coastguard Worker     }
649*7688df22SAndroid Build Coastguard Worker     return 0;
650*7688df22SAndroid Build Coastguard Worker }
651*7688df22SAndroid Build Coastguard Worker 
eg_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_split,uint64_t offset,unsigned start_level)652*7688df22SAndroid Build Coastguard Worker static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
653*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface *surf,
654*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface_level *level,
655*7688df22SAndroid Build Coastguard Worker                               unsigned bpe, unsigned tile_split,
656*7688df22SAndroid Build Coastguard Worker                               uint64_t offset, unsigned start_level)
657*7688df22SAndroid Build Coastguard Worker {
658*7688df22SAndroid Build Coastguard Worker     unsigned tilew, tileh, tileb;
659*7688df22SAndroid Build Coastguard Worker     unsigned mtilew, mtileh, mtileb;
660*7688df22SAndroid Build Coastguard Worker     unsigned slice_pt;
661*7688df22SAndroid Build Coastguard Worker     unsigned i;
662*7688df22SAndroid Build Coastguard Worker 
663*7688df22SAndroid Build Coastguard Worker     /* compute tile values */
664*7688df22SAndroid Build Coastguard Worker     tilew = 8;
665*7688df22SAndroid Build Coastguard Worker     tileh = 8;
666*7688df22SAndroid Build Coastguard Worker     tileb = tilew * tileh * bpe * surf->nsamples;
667*7688df22SAndroid Build Coastguard Worker     /* slices per tile */
668*7688df22SAndroid Build Coastguard Worker     slice_pt = 1;
669*7688df22SAndroid Build Coastguard Worker     if (tileb > tile_split && tile_split) {
670*7688df22SAndroid Build Coastguard Worker         slice_pt = tileb / tile_split;
671*7688df22SAndroid Build Coastguard Worker     }
672*7688df22SAndroid Build Coastguard Worker     tileb = tileb / slice_pt;
673*7688df22SAndroid Build Coastguard Worker 
674*7688df22SAndroid Build Coastguard Worker     /* macro tile width & height */
675*7688df22SAndroid Build Coastguard Worker     mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
676*7688df22SAndroid Build Coastguard Worker     mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
677*7688df22SAndroid Build Coastguard Worker     /* macro tile bytes */
678*7688df22SAndroid Build Coastguard Worker     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
679*7688df22SAndroid Build Coastguard Worker 
680*7688df22SAndroid Build Coastguard Worker     if (!start_level) {
681*7688df22SAndroid Build Coastguard Worker         unsigned alignment = MAX2(256, mtileb);
682*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
683*7688df22SAndroid Build Coastguard Worker 
684*7688df22SAndroid Build Coastguard Worker         if (offset) {
685*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, alignment);
686*7688df22SAndroid Build Coastguard Worker         }
687*7688df22SAndroid Build Coastguard Worker     }
688*7688df22SAndroid Build Coastguard Worker 
689*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
690*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
691*7688df22SAndroid Build Coastguard Worker         level[i].mode = RADEON_SURF_MODE_2D;
692*7688df22SAndroid Build Coastguard Worker         eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
693*7688df22SAndroid Build Coastguard Worker         if (level[i].mode == RADEON_SURF_MODE_1D) {
694*7688df22SAndroid Build Coastguard Worker             return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
695*7688df22SAndroid Build Coastguard Worker         }
696*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
697*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
698*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
699*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, surf->bo_alignment);
700*7688df22SAndroid Build Coastguard Worker         }
701*7688df22SAndroid Build Coastguard Worker     }
702*7688df22SAndroid Build Coastguard Worker     return 0;
703*7688df22SAndroid Build Coastguard Worker }
704*7688df22SAndroid Build Coastguard Worker 
eg_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode)705*7688df22SAndroid Build Coastguard Worker static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
706*7688df22SAndroid Build Coastguard Worker                              struct radeon_surface *surf,
707*7688df22SAndroid Build Coastguard Worker                              unsigned mode)
708*7688df22SAndroid Build Coastguard Worker {
709*7688df22SAndroid Build Coastguard Worker     unsigned tileb;
710*7688df22SAndroid Build Coastguard Worker 
711*7688df22SAndroid Build Coastguard Worker     /* check surface dimension */
712*7688df22SAndroid Build Coastguard Worker     if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
713*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
714*7688df22SAndroid Build Coastguard Worker     }
715*7688df22SAndroid Build Coastguard Worker 
716*7688df22SAndroid Build Coastguard Worker     /* check mipmap last_level */
717*7688df22SAndroid Build Coastguard Worker     if (surf->last_level > 15) {
718*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
719*7688df22SAndroid Build Coastguard Worker     }
720*7688df22SAndroid Build Coastguard Worker 
721*7688df22SAndroid Build Coastguard Worker     /* force 1d on kernel that can't do 2d */
722*7688df22SAndroid Build Coastguard Worker     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
723*7688df22SAndroid Build Coastguard Worker         if (surf->nsamples > 1) {
724*7688df22SAndroid Build Coastguard Worker             fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
725*7688df22SAndroid Build Coastguard Worker             return -EFAULT;
726*7688df22SAndroid Build Coastguard Worker         }
727*7688df22SAndroid Build Coastguard Worker         mode = RADEON_SURF_MODE_1D;
728*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
729*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(mode, MODE);
730*7688df22SAndroid Build Coastguard Worker     }
731*7688df22SAndroid Build Coastguard Worker 
732*7688df22SAndroid Build Coastguard Worker     /* check tile split */
733*7688df22SAndroid Build Coastguard Worker     if (mode == RADEON_SURF_MODE_2D) {
734*7688df22SAndroid Build Coastguard Worker         switch (surf->tile_split) {
735*7688df22SAndroid Build Coastguard Worker         case 64:
736*7688df22SAndroid Build Coastguard Worker         case 128:
737*7688df22SAndroid Build Coastguard Worker         case 256:
738*7688df22SAndroid Build Coastguard Worker         case 512:
739*7688df22SAndroid Build Coastguard Worker         case 1024:
740*7688df22SAndroid Build Coastguard Worker         case 2048:
741*7688df22SAndroid Build Coastguard Worker         case 4096:
742*7688df22SAndroid Build Coastguard Worker             break;
743*7688df22SAndroid Build Coastguard Worker         default:
744*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
745*7688df22SAndroid Build Coastguard Worker         }
746*7688df22SAndroid Build Coastguard Worker         switch (surf->mtilea) {
747*7688df22SAndroid Build Coastguard Worker         case 1:
748*7688df22SAndroid Build Coastguard Worker         case 2:
749*7688df22SAndroid Build Coastguard Worker         case 4:
750*7688df22SAndroid Build Coastguard Worker         case 8:
751*7688df22SAndroid Build Coastguard Worker             break;
752*7688df22SAndroid Build Coastguard Worker         default:
753*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
754*7688df22SAndroid Build Coastguard Worker         }
755*7688df22SAndroid Build Coastguard Worker         /* check aspect ratio */
756*7688df22SAndroid Build Coastguard Worker         if (surf_man->hw_info.num_banks < surf->mtilea) {
757*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
758*7688df22SAndroid Build Coastguard Worker         }
759*7688df22SAndroid Build Coastguard Worker         /* check bank width */
760*7688df22SAndroid Build Coastguard Worker         switch (surf->bankw) {
761*7688df22SAndroid Build Coastguard Worker         case 1:
762*7688df22SAndroid Build Coastguard Worker         case 2:
763*7688df22SAndroid Build Coastguard Worker         case 4:
764*7688df22SAndroid Build Coastguard Worker         case 8:
765*7688df22SAndroid Build Coastguard Worker             break;
766*7688df22SAndroid Build Coastguard Worker         default:
767*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
768*7688df22SAndroid Build Coastguard Worker         }
769*7688df22SAndroid Build Coastguard Worker         /* check bank height */
770*7688df22SAndroid Build Coastguard Worker         switch (surf->bankh) {
771*7688df22SAndroid Build Coastguard Worker         case 1:
772*7688df22SAndroid Build Coastguard Worker         case 2:
773*7688df22SAndroid Build Coastguard Worker         case 4:
774*7688df22SAndroid Build Coastguard Worker         case 8:
775*7688df22SAndroid Build Coastguard Worker             break;
776*7688df22SAndroid Build Coastguard Worker         default:
777*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
778*7688df22SAndroid Build Coastguard Worker         }
779*7688df22SAndroid Build Coastguard Worker         tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
780*7688df22SAndroid Build Coastguard Worker         if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
781*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
782*7688df22SAndroid Build Coastguard Worker         }
783*7688df22SAndroid Build Coastguard Worker     }
784*7688df22SAndroid Build Coastguard Worker 
785*7688df22SAndroid Build Coastguard Worker     return 0;
786*7688df22SAndroid Build Coastguard Worker }
787*7688df22SAndroid Build Coastguard Worker 
eg_surface_init_1d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)788*7688df22SAndroid Build Coastguard Worker static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
789*7688df22SAndroid Build Coastguard Worker                                        struct radeon_surface *surf)
790*7688df22SAndroid Build Coastguard Worker {
791*7688df22SAndroid Build Coastguard Worker     unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
792*7688df22SAndroid Build Coastguard Worker     int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
793*7688df22SAndroid Build Coastguard Worker     /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
794*7688df22SAndroid Build Coastguard Worker     struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
795*7688df22SAndroid Build Coastguard Worker     struct radeon_surface_level *stencil_level =
796*7688df22SAndroid Build Coastguard Worker         (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
797*7688df22SAndroid Build Coastguard Worker 
798*7688df22SAndroid Build Coastguard Worker     r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
799*7688df22SAndroid Build Coastguard Worker     if (r)
800*7688df22SAndroid Build Coastguard Worker         return r;
801*7688df22SAndroid Build Coastguard Worker 
802*7688df22SAndroid Build Coastguard Worker     if (is_depth_stencil) {
803*7688df22SAndroid Build Coastguard Worker         r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
804*7688df22SAndroid Build Coastguard Worker                                surf->bo_size, 0);
805*7688df22SAndroid Build Coastguard Worker         surf->stencil_offset = stencil_level[0].offset;
806*7688df22SAndroid Build Coastguard Worker     }
807*7688df22SAndroid Build Coastguard Worker     return r;
808*7688df22SAndroid Build Coastguard Worker }
809*7688df22SAndroid Build Coastguard Worker 
eg_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)810*7688df22SAndroid Build Coastguard Worker static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
811*7688df22SAndroid Build Coastguard Worker                                        struct radeon_surface *surf)
812*7688df22SAndroid Build Coastguard Worker {
813*7688df22SAndroid Build Coastguard Worker     unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
814*7688df22SAndroid Build Coastguard Worker     int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
815*7688df22SAndroid Build Coastguard Worker     /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
816*7688df22SAndroid Build Coastguard Worker     struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
817*7688df22SAndroid Build Coastguard Worker     struct radeon_surface_level *stencil_level =
818*7688df22SAndroid Build Coastguard Worker         (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
819*7688df22SAndroid Build Coastguard Worker 
820*7688df22SAndroid Build Coastguard Worker     r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
821*7688df22SAndroid Build Coastguard Worker                            surf->tile_split, 0, 0);
822*7688df22SAndroid Build Coastguard Worker     if (r)
823*7688df22SAndroid Build Coastguard Worker         return r;
824*7688df22SAndroid Build Coastguard Worker 
825*7688df22SAndroid Build Coastguard Worker     if (is_depth_stencil) {
826*7688df22SAndroid Build Coastguard Worker         r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
827*7688df22SAndroid Build Coastguard Worker                                surf->stencil_tile_split, surf->bo_size, 0);
828*7688df22SAndroid Build Coastguard Worker         surf->stencil_offset = stencil_level[0].offset;
829*7688df22SAndroid Build Coastguard Worker     }
830*7688df22SAndroid Build Coastguard Worker     return r;
831*7688df22SAndroid Build Coastguard Worker }
832*7688df22SAndroid Build Coastguard Worker 
eg_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)833*7688df22SAndroid Build Coastguard Worker static int eg_surface_init(struct radeon_surface_manager *surf_man,
834*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface *surf)
835*7688df22SAndroid Build Coastguard Worker {
836*7688df22SAndroid Build Coastguard Worker     unsigned mode;
837*7688df22SAndroid Build Coastguard Worker     int r;
838*7688df22SAndroid Build Coastguard Worker 
839*7688df22SAndroid Build Coastguard Worker     /* MSAA surfaces support the 2D mode only. */
840*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples > 1) {
841*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
842*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
843*7688df22SAndroid Build Coastguard Worker     }
844*7688df22SAndroid Build Coastguard Worker 
845*7688df22SAndroid Build Coastguard Worker     /* tiling mode */
846*7688df22SAndroid Build Coastguard Worker     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
847*7688df22SAndroid Build Coastguard Worker 
848*7688df22SAndroid Build Coastguard Worker     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
849*7688df22SAndroid Build Coastguard Worker         /* zbuffer only support 1D or 2D tiled surface */
850*7688df22SAndroid Build Coastguard Worker         switch (mode) {
851*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_1D:
852*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_2D:
853*7688df22SAndroid Build Coastguard Worker             break;
854*7688df22SAndroid Build Coastguard Worker         default:
855*7688df22SAndroid Build Coastguard Worker             mode = RADEON_SURF_MODE_1D;
856*7688df22SAndroid Build Coastguard Worker             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
857*7688df22SAndroid Build Coastguard Worker             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
858*7688df22SAndroid Build Coastguard Worker             break;
859*7688df22SAndroid Build Coastguard Worker         }
860*7688df22SAndroid Build Coastguard Worker     }
861*7688df22SAndroid Build Coastguard Worker 
862*7688df22SAndroid Build Coastguard Worker     r = eg_surface_sanity(surf_man, surf, mode);
863*7688df22SAndroid Build Coastguard Worker     if (r) {
864*7688df22SAndroid Build Coastguard Worker         return r;
865*7688df22SAndroid Build Coastguard Worker     }
866*7688df22SAndroid Build Coastguard Worker 
867*7688df22SAndroid Build Coastguard Worker     surf->stencil_offset = 0;
868*7688df22SAndroid Build Coastguard Worker     surf->bo_alignment = 0;
869*7688df22SAndroid Build Coastguard Worker 
870*7688df22SAndroid Build Coastguard Worker     /* check tiling mode */
871*7688df22SAndroid Build Coastguard Worker     switch (mode) {
872*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR:
873*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_linear(surf_man, surf, 0, 0);
874*7688df22SAndroid Build Coastguard Worker         break;
875*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR_ALIGNED:
876*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
877*7688df22SAndroid Build Coastguard Worker         break;
878*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_1D:
879*7688df22SAndroid Build Coastguard Worker         r = eg_surface_init_1d_miptrees(surf_man, surf);
880*7688df22SAndroid Build Coastguard Worker         break;
881*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_2D:
882*7688df22SAndroid Build Coastguard Worker         r = eg_surface_init_2d_miptrees(surf_man, surf);
883*7688df22SAndroid Build Coastguard Worker         break;
884*7688df22SAndroid Build Coastguard Worker     default:
885*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
886*7688df22SAndroid Build Coastguard Worker     }
887*7688df22SAndroid Build Coastguard Worker     return r;
888*7688df22SAndroid Build Coastguard Worker }
889*7688df22SAndroid Build Coastguard Worker 
log2_int(unsigned x)890*7688df22SAndroid Build Coastguard Worker static unsigned log2_int(unsigned x)
891*7688df22SAndroid Build Coastguard Worker {
892*7688df22SAndroid Build Coastguard Worker     unsigned l;
893*7688df22SAndroid Build Coastguard Worker 
894*7688df22SAndroid Build Coastguard Worker     if (x < 2) {
895*7688df22SAndroid Build Coastguard Worker         return 0;
896*7688df22SAndroid Build Coastguard Worker     }
897*7688df22SAndroid Build Coastguard Worker     for (l = 2; ; l++) {
898*7688df22SAndroid Build Coastguard Worker         if ((unsigned)(1 << l) > x) {
899*7688df22SAndroid Build Coastguard Worker             return l - 1;
900*7688df22SAndroid Build Coastguard Worker         }
901*7688df22SAndroid Build Coastguard Worker     }
902*7688df22SAndroid Build Coastguard Worker     return 0;
903*7688df22SAndroid Build Coastguard Worker }
904*7688df22SAndroid Build Coastguard Worker 
905*7688df22SAndroid Build Coastguard Worker /* compute best tile_split, bankw, bankh, mtilea
906*7688df22SAndroid Build Coastguard Worker  * depending on surface
907*7688df22SAndroid Build Coastguard Worker  */
eg_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)908*7688df22SAndroid Build Coastguard Worker static int eg_surface_best(struct radeon_surface_manager *surf_man,
909*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface *surf)
910*7688df22SAndroid Build Coastguard Worker {
911*7688df22SAndroid Build Coastguard Worker     unsigned mode, tileb, h_over_w;
912*7688df22SAndroid Build Coastguard Worker     int r;
913*7688df22SAndroid Build Coastguard Worker 
914*7688df22SAndroid Build Coastguard Worker     /* tiling mode */
915*7688df22SAndroid Build Coastguard Worker     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
916*7688df22SAndroid Build Coastguard Worker 
917*7688df22SAndroid Build Coastguard Worker     /* set some default value to avoid sanity check choking on them */
918*7688df22SAndroid Build Coastguard Worker     surf->tile_split = 1024;
919*7688df22SAndroid Build Coastguard Worker     surf->bankw = 1;
920*7688df22SAndroid Build Coastguard Worker     surf->bankh = 1;
921*7688df22SAndroid Build Coastguard Worker     surf->mtilea = surf_man->hw_info.num_banks;
922*7688df22SAndroid Build Coastguard Worker     tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
923*7688df22SAndroid Build Coastguard Worker     for (; surf->bankh <= 8; surf->bankh *= 2) {
924*7688df22SAndroid Build Coastguard Worker         if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
925*7688df22SAndroid Build Coastguard Worker             break;
926*7688df22SAndroid Build Coastguard Worker         }
927*7688df22SAndroid Build Coastguard Worker     }
928*7688df22SAndroid Build Coastguard Worker     if (surf->mtilea > 8) {
929*7688df22SAndroid Build Coastguard Worker         surf->mtilea = 8;
930*7688df22SAndroid Build Coastguard Worker     }
931*7688df22SAndroid Build Coastguard Worker 
932*7688df22SAndroid Build Coastguard Worker     r = eg_surface_sanity(surf_man, surf, mode);
933*7688df22SAndroid Build Coastguard Worker     if (r) {
934*7688df22SAndroid Build Coastguard Worker         return r;
935*7688df22SAndroid Build Coastguard Worker     }
936*7688df22SAndroid Build Coastguard Worker 
937*7688df22SAndroid Build Coastguard Worker     if (mode != RADEON_SURF_MODE_2D) {
938*7688df22SAndroid Build Coastguard Worker         /* nothing to do for non 2D tiled surface */
939*7688df22SAndroid Build Coastguard Worker         return 0;
940*7688df22SAndroid Build Coastguard Worker     }
941*7688df22SAndroid Build Coastguard Worker 
942*7688df22SAndroid Build Coastguard Worker     /* Tweak TILE_SPLIT for performance here. */
943*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples > 1) {
944*7688df22SAndroid Build Coastguard Worker         if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
945*7688df22SAndroid Build Coastguard Worker             switch (surf->nsamples) {
946*7688df22SAndroid Build Coastguard Worker             case 2:
947*7688df22SAndroid Build Coastguard Worker                 surf->tile_split = 128;
948*7688df22SAndroid Build Coastguard Worker                 break;
949*7688df22SAndroid Build Coastguard Worker             case 4:
950*7688df22SAndroid Build Coastguard Worker                 surf->tile_split = 128;
951*7688df22SAndroid Build Coastguard Worker                 break;
952*7688df22SAndroid Build Coastguard Worker             case 8:
953*7688df22SAndroid Build Coastguard Worker                 surf->tile_split = 256;
954*7688df22SAndroid Build Coastguard Worker                 break;
955*7688df22SAndroid Build Coastguard Worker             case 16: /* cayman only */
956*7688df22SAndroid Build Coastguard Worker                 surf->tile_split = 512;
957*7688df22SAndroid Build Coastguard Worker                 break;
958*7688df22SAndroid Build Coastguard Worker             default:
959*7688df22SAndroid Build Coastguard Worker                 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
960*7688df22SAndroid Build Coastguard Worker                         surf->nsamples, __LINE__);
961*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
962*7688df22SAndroid Build Coastguard Worker             }
963*7688df22SAndroid Build Coastguard Worker             surf->stencil_tile_split = 64;
964*7688df22SAndroid Build Coastguard Worker         } else {
965*7688df22SAndroid Build Coastguard Worker             /* tile split must be >= 256 for colorbuffer surfaces,
966*7688df22SAndroid Build Coastguard Worker              * SAMPLE_SPLIT = tile_split / (bpe * 64), the optimal value is 2
967*7688df22SAndroid Build Coastguard Worker              */
968*7688df22SAndroid Build Coastguard Worker             surf->tile_split = MAX2(2 * surf->bpe * 64, 256);
969*7688df22SAndroid Build Coastguard Worker             if (surf->tile_split > 4096)
970*7688df22SAndroid Build Coastguard Worker                 surf->tile_split = 4096;
971*7688df22SAndroid Build Coastguard Worker         }
972*7688df22SAndroid Build Coastguard Worker     } else {
973*7688df22SAndroid Build Coastguard Worker         /* set tile split to row size */
974*7688df22SAndroid Build Coastguard Worker         surf->tile_split = surf_man->hw_info.row_size;
975*7688df22SAndroid Build Coastguard Worker         surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
976*7688df22SAndroid Build Coastguard Worker     }
977*7688df22SAndroid Build Coastguard Worker 
978*7688df22SAndroid Build Coastguard Worker     /* bankw or bankh greater than 1 increase alignment requirement, not
979*7688df22SAndroid Build Coastguard Worker      * sure if it's worth using smaller bankw & bankh to stick with 2D
980*7688df22SAndroid Build Coastguard Worker      * tiling on small surface rather than falling back to 1D tiling.
981*7688df22SAndroid Build Coastguard Worker      * Use recommended value based on tile size for now.
982*7688df22SAndroid Build Coastguard Worker      *
983*7688df22SAndroid Build Coastguard Worker      * fmask buffer has different optimal value figure them out once we
984*7688df22SAndroid Build Coastguard Worker      * use it.
985*7688df22SAndroid Build Coastguard Worker      */
986*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SBUFFER) {
987*7688df22SAndroid Build Coastguard Worker         /* assume 1 bytes for stencil, we optimize for stencil as stencil
988*7688df22SAndroid Build Coastguard Worker          * and depth shares surface values
989*7688df22SAndroid Build Coastguard Worker          */
990*7688df22SAndroid Build Coastguard Worker         tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
991*7688df22SAndroid Build Coastguard Worker     } else {
992*7688df22SAndroid Build Coastguard Worker         tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
993*7688df22SAndroid Build Coastguard Worker     }
994*7688df22SAndroid Build Coastguard Worker 
995*7688df22SAndroid Build Coastguard Worker     /* use bankw of 1 to minimize width alignment, might be interesting to
996*7688df22SAndroid Build Coastguard Worker      * increase it for large surface
997*7688df22SAndroid Build Coastguard Worker      */
998*7688df22SAndroid Build Coastguard Worker     surf->bankw = 1;
999*7688df22SAndroid Build Coastguard Worker     switch (tileb) {
1000*7688df22SAndroid Build Coastguard Worker     case 64:
1001*7688df22SAndroid Build Coastguard Worker         surf->bankh = 4;
1002*7688df22SAndroid Build Coastguard Worker         break;
1003*7688df22SAndroid Build Coastguard Worker     case 128:
1004*7688df22SAndroid Build Coastguard Worker     case 256:
1005*7688df22SAndroid Build Coastguard Worker         surf->bankh = 2;
1006*7688df22SAndroid Build Coastguard Worker         break;
1007*7688df22SAndroid Build Coastguard Worker     default:
1008*7688df22SAndroid Build Coastguard Worker         surf->bankh = 1;
1009*7688df22SAndroid Build Coastguard Worker         break;
1010*7688df22SAndroid Build Coastguard Worker     }
1011*7688df22SAndroid Build Coastguard Worker     /* double check the constraint */
1012*7688df22SAndroid Build Coastguard Worker     for (; surf->bankh <= 8; surf->bankh *= 2) {
1013*7688df22SAndroid Build Coastguard Worker         if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
1014*7688df22SAndroid Build Coastguard Worker             break;
1015*7688df22SAndroid Build Coastguard Worker         }
1016*7688df22SAndroid Build Coastguard Worker     }
1017*7688df22SAndroid Build Coastguard Worker 
1018*7688df22SAndroid Build Coastguard Worker     h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
1019*7688df22SAndroid Build Coastguard Worker                 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
1020*7688df22SAndroid Build Coastguard Worker     surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1021*7688df22SAndroid Build Coastguard Worker 
1022*7688df22SAndroid Build Coastguard Worker     return 0;
1023*7688df22SAndroid Build Coastguard Worker }
1024*7688df22SAndroid Build Coastguard Worker 
1025*7688df22SAndroid Build Coastguard Worker 
1026*7688df22SAndroid Build Coastguard Worker /* ===========================================================================
1027*7688df22SAndroid Build Coastguard Worker  * Southern Islands family
1028*7688df22SAndroid Build Coastguard Worker  */
1029*7688df22SAndroid Build Coastguard Worker #define SI__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
1030*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P2               0
1031*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
1032*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
1033*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
1034*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
1035*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
1036*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
1037*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
1038*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
1039*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
1040*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
1041*7688df22SAndroid Build Coastguard Worker #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
1042*7688df22SAndroid Build Coastguard Worker #define SI__GB_TILE_MODE__TILE_SPLIT(x)         (((x) >> 11) & 0x7)
1043*7688df22SAndroid Build Coastguard Worker #define     SI__TILE_SPLIT__64B                         0
1044*7688df22SAndroid Build Coastguard Worker #define     SI__TILE_SPLIT__128B                        1
1045*7688df22SAndroid Build Coastguard Worker #define     SI__TILE_SPLIT__256B                        2
1046*7688df22SAndroid Build Coastguard Worker #define     SI__TILE_SPLIT__512B                        3
1047*7688df22SAndroid Build Coastguard Worker #define     SI__TILE_SPLIT__1024B                       4
1048*7688df22SAndroid Build Coastguard Worker #define     SI__TILE_SPLIT__2048B                       5
1049*7688df22SAndroid Build Coastguard Worker #define     SI__TILE_SPLIT__4096B                       6
1050*7688df22SAndroid Build Coastguard Worker #define SI__GB_TILE_MODE__BANK_WIDTH(x)         (((x) >> 14) & 0x3)
1051*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_WIDTH__1                           0
1052*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_WIDTH__2                           1
1053*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_WIDTH__4                           2
1054*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_WIDTH__8                           3
1055*7688df22SAndroid Build Coastguard Worker #define SI__GB_TILE_MODE__BANK_HEIGHT(x)        (((x) >> 16) & 0x3)
1056*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_HEIGHT__1                          0
1057*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_HEIGHT__2                          1
1058*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_HEIGHT__4                          2
1059*7688df22SAndroid Build Coastguard Worker #define     SI__BANK_HEIGHT__8                          3
1060*7688df22SAndroid Build Coastguard Worker #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x)  (((x) >> 18) & 0x3)
1061*7688df22SAndroid Build Coastguard Worker #define     SI__MACRO_TILE_ASPECT__1                    0
1062*7688df22SAndroid Build Coastguard Worker #define     SI__MACRO_TILE_ASPECT__2                    1
1063*7688df22SAndroid Build Coastguard Worker #define     SI__MACRO_TILE_ASPECT__4                    2
1064*7688df22SAndroid Build Coastguard Worker #define     SI__MACRO_TILE_ASPECT__8                    3
1065*7688df22SAndroid Build Coastguard Worker #define SI__GB_TILE_MODE__NUM_BANKS(x)          (((x) >> 20) & 0x3)
1066*7688df22SAndroid Build Coastguard Worker #define     SI__NUM_BANKS__2_BANK                       0
1067*7688df22SAndroid Build Coastguard Worker #define     SI__NUM_BANKS__4_BANK                       1
1068*7688df22SAndroid Build Coastguard Worker #define     SI__NUM_BANKS__8_BANK                       2
1069*7688df22SAndroid Build Coastguard Worker #define     SI__NUM_BANKS__16_BANK                      3
1070*7688df22SAndroid Build Coastguard Worker 
1071*7688df22SAndroid Build Coastguard Worker 
si_gb_tile_mode(uint32_t gb_tile_mode,unsigned * num_pipes,unsigned * num_banks,uint32_t * macro_tile_aspect,uint32_t * bank_w,uint32_t * bank_h,uint32_t * tile_split)1072*7688df22SAndroid Build Coastguard Worker static void si_gb_tile_mode(uint32_t gb_tile_mode,
1073*7688df22SAndroid Build Coastguard Worker                             unsigned *num_pipes,
1074*7688df22SAndroid Build Coastguard Worker                             unsigned *num_banks,
1075*7688df22SAndroid Build Coastguard Worker                             uint32_t *macro_tile_aspect,
1076*7688df22SAndroid Build Coastguard Worker                             uint32_t *bank_w,
1077*7688df22SAndroid Build Coastguard Worker                             uint32_t *bank_h,
1078*7688df22SAndroid Build Coastguard Worker                             uint32_t *tile_split)
1079*7688df22SAndroid Build Coastguard Worker {
1080*7688df22SAndroid Build Coastguard Worker     if (num_pipes) {
1081*7688df22SAndroid Build Coastguard Worker         switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1082*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P2:
1083*7688df22SAndroid Build Coastguard Worker         default:
1084*7688df22SAndroid Build Coastguard Worker             *num_pipes = 2;
1085*7688df22SAndroid Build Coastguard Worker             break;
1086*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1087*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1088*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1089*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1090*7688df22SAndroid Build Coastguard Worker             *num_pipes = 4;
1091*7688df22SAndroid Build Coastguard Worker             break;
1092*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1093*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1094*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1095*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1096*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1097*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1098*7688df22SAndroid Build Coastguard Worker         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1099*7688df22SAndroid Build Coastguard Worker             *num_pipes = 8;
1100*7688df22SAndroid Build Coastguard Worker             break;
1101*7688df22SAndroid Build Coastguard Worker         }
1102*7688df22SAndroid Build Coastguard Worker     }
1103*7688df22SAndroid Build Coastguard Worker     if (num_banks) {
1104*7688df22SAndroid Build Coastguard Worker         switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1105*7688df22SAndroid Build Coastguard Worker         default:
1106*7688df22SAndroid Build Coastguard Worker         case SI__NUM_BANKS__2_BANK:
1107*7688df22SAndroid Build Coastguard Worker             *num_banks = 2;
1108*7688df22SAndroid Build Coastguard Worker             break;
1109*7688df22SAndroid Build Coastguard Worker         case SI__NUM_BANKS__4_BANK:
1110*7688df22SAndroid Build Coastguard Worker             *num_banks = 4;
1111*7688df22SAndroid Build Coastguard Worker             break;
1112*7688df22SAndroid Build Coastguard Worker         case SI__NUM_BANKS__8_BANK:
1113*7688df22SAndroid Build Coastguard Worker             *num_banks = 8;
1114*7688df22SAndroid Build Coastguard Worker             break;
1115*7688df22SAndroid Build Coastguard Worker         case SI__NUM_BANKS__16_BANK:
1116*7688df22SAndroid Build Coastguard Worker             *num_banks = 16;
1117*7688df22SAndroid Build Coastguard Worker             break;
1118*7688df22SAndroid Build Coastguard Worker         }
1119*7688df22SAndroid Build Coastguard Worker     }
1120*7688df22SAndroid Build Coastguard Worker     if (macro_tile_aspect) {
1121*7688df22SAndroid Build Coastguard Worker         switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1122*7688df22SAndroid Build Coastguard Worker         default:
1123*7688df22SAndroid Build Coastguard Worker         case SI__MACRO_TILE_ASPECT__1:
1124*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 1;
1125*7688df22SAndroid Build Coastguard Worker             break;
1126*7688df22SAndroid Build Coastguard Worker         case SI__MACRO_TILE_ASPECT__2:
1127*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 2;
1128*7688df22SAndroid Build Coastguard Worker             break;
1129*7688df22SAndroid Build Coastguard Worker         case SI__MACRO_TILE_ASPECT__4:
1130*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 4;
1131*7688df22SAndroid Build Coastguard Worker             break;
1132*7688df22SAndroid Build Coastguard Worker         case SI__MACRO_TILE_ASPECT__8:
1133*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 8;
1134*7688df22SAndroid Build Coastguard Worker             break;
1135*7688df22SAndroid Build Coastguard Worker         }
1136*7688df22SAndroid Build Coastguard Worker     }
1137*7688df22SAndroid Build Coastguard Worker     if (bank_w) {
1138*7688df22SAndroid Build Coastguard Worker         switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1139*7688df22SAndroid Build Coastguard Worker         default:
1140*7688df22SAndroid Build Coastguard Worker         case SI__BANK_WIDTH__1:
1141*7688df22SAndroid Build Coastguard Worker             *bank_w = 1;
1142*7688df22SAndroid Build Coastguard Worker             break;
1143*7688df22SAndroid Build Coastguard Worker         case SI__BANK_WIDTH__2:
1144*7688df22SAndroid Build Coastguard Worker             *bank_w = 2;
1145*7688df22SAndroid Build Coastguard Worker             break;
1146*7688df22SAndroid Build Coastguard Worker         case SI__BANK_WIDTH__4:
1147*7688df22SAndroid Build Coastguard Worker             *bank_w = 4;
1148*7688df22SAndroid Build Coastguard Worker             break;
1149*7688df22SAndroid Build Coastguard Worker         case SI__BANK_WIDTH__8:
1150*7688df22SAndroid Build Coastguard Worker             *bank_w = 8;
1151*7688df22SAndroid Build Coastguard Worker             break;
1152*7688df22SAndroid Build Coastguard Worker         }
1153*7688df22SAndroid Build Coastguard Worker     }
1154*7688df22SAndroid Build Coastguard Worker     if (bank_h) {
1155*7688df22SAndroid Build Coastguard Worker         switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1156*7688df22SAndroid Build Coastguard Worker         default:
1157*7688df22SAndroid Build Coastguard Worker         case SI__BANK_HEIGHT__1:
1158*7688df22SAndroid Build Coastguard Worker             *bank_h = 1;
1159*7688df22SAndroid Build Coastguard Worker             break;
1160*7688df22SAndroid Build Coastguard Worker         case SI__BANK_HEIGHT__2:
1161*7688df22SAndroid Build Coastguard Worker             *bank_h = 2;
1162*7688df22SAndroid Build Coastguard Worker             break;
1163*7688df22SAndroid Build Coastguard Worker         case SI__BANK_HEIGHT__4:
1164*7688df22SAndroid Build Coastguard Worker             *bank_h = 4;
1165*7688df22SAndroid Build Coastguard Worker             break;
1166*7688df22SAndroid Build Coastguard Worker         case SI__BANK_HEIGHT__8:
1167*7688df22SAndroid Build Coastguard Worker             *bank_h = 8;
1168*7688df22SAndroid Build Coastguard Worker             break;
1169*7688df22SAndroid Build Coastguard Worker         }
1170*7688df22SAndroid Build Coastguard Worker     }
1171*7688df22SAndroid Build Coastguard Worker     if (tile_split) {
1172*7688df22SAndroid Build Coastguard Worker         switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1173*7688df22SAndroid Build Coastguard Worker         default:
1174*7688df22SAndroid Build Coastguard Worker         case SI__TILE_SPLIT__64B:
1175*7688df22SAndroid Build Coastguard Worker             *tile_split = 64;
1176*7688df22SAndroid Build Coastguard Worker             break;
1177*7688df22SAndroid Build Coastguard Worker         case SI__TILE_SPLIT__128B:
1178*7688df22SAndroid Build Coastguard Worker             *tile_split = 128;
1179*7688df22SAndroid Build Coastguard Worker             break;
1180*7688df22SAndroid Build Coastguard Worker         case SI__TILE_SPLIT__256B:
1181*7688df22SAndroid Build Coastguard Worker             *tile_split = 256;
1182*7688df22SAndroid Build Coastguard Worker             break;
1183*7688df22SAndroid Build Coastguard Worker         case SI__TILE_SPLIT__512B:
1184*7688df22SAndroid Build Coastguard Worker             *tile_split = 512;
1185*7688df22SAndroid Build Coastguard Worker             break;
1186*7688df22SAndroid Build Coastguard Worker         case SI__TILE_SPLIT__1024B:
1187*7688df22SAndroid Build Coastguard Worker             *tile_split = 1024;
1188*7688df22SAndroid Build Coastguard Worker             break;
1189*7688df22SAndroid Build Coastguard Worker         case SI__TILE_SPLIT__2048B:
1190*7688df22SAndroid Build Coastguard Worker             *tile_split = 2048;
1191*7688df22SAndroid Build Coastguard Worker             break;
1192*7688df22SAndroid Build Coastguard Worker         case SI__TILE_SPLIT__4096B:
1193*7688df22SAndroid Build Coastguard Worker             *tile_split = 4096;
1194*7688df22SAndroid Build Coastguard Worker             break;
1195*7688df22SAndroid Build Coastguard Worker         }
1196*7688df22SAndroid Build Coastguard Worker     }
1197*7688df22SAndroid Build Coastguard Worker }
1198*7688df22SAndroid Build Coastguard Worker 
si_init_hw_info(struct radeon_surface_manager * surf_man)1199*7688df22SAndroid Build Coastguard Worker static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1200*7688df22SAndroid Build Coastguard Worker {
1201*7688df22SAndroid Build Coastguard Worker     uint32_t tiling_config;
1202*7688df22SAndroid Build Coastguard Worker     drmVersionPtr version;
1203*7688df22SAndroid Build Coastguard Worker     int r;
1204*7688df22SAndroid Build Coastguard Worker 
1205*7688df22SAndroid Build Coastguard Worker     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1206*7688df22SAndroid Build Coastguard Worker                          &tiling_config);
1207*7688df22SAndroid Build Coastguard Worker     if (r) {
1208*7688df22SAndroid Build Coastguard Worker         return r;
1209*7688df22SAndroid Build Coastguard Worker     }
1210*7688df22SAndroid Build Coastguard Worker 
1211*7688df22SAndroid Build Coastguard Worker     surf_man->hw_info.allow_2d = 0;
1212*7688df22SAndroid Build Coastguard Worker     version = drmGetVersion(surf_man->fd);
1213*7688df22SAndroid Build Coastguard Worker     if (version && version->version_minor >= 33) {
1214*7688df22SAndroid Build Coastguard Worker         if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1215*7688df22SAndroid Build Coastguard Worker             surf_man->hw_info.allow_2d = 1;
1216*7688df22SAndroid Build Coastguard Worker         }
1217*7688df22SAndroid Build Coastguard Worker     }
1218*7688df22SAndroid Build Coastguard Worker     drmFreeVersion(version);
1219*7688df22SAndroid Build Coastguard Worker 
1220*7688df22SAndroid Build Coastguard Worker     switch (tiling_config & 0xf) {
1221*7688df22SAndroid Build Coastguard Worker     case 0:
1222*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 1;
1223*7688df22SAndroid Build Coastguard Worker         break;
1224*7688df22SAndroid Build Coastguard Worker     case 1:
1225*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 2;
1226*7688df22SAndroid Build Coastguard Worker         break;
1227*7688df22SAndroid Build Coastguard Worker     case 2:
1228*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 4;
1229*7688df22SAndroid Build Coastguard Worker         break;
1230*7688df22SAndroid Build Coastguard Worker     case 3:
1231*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
1232*7688df22SAndroid Build Coastguard Worker         break;
1233*7688df22SAndroid Build Coastguard Worker     default:
1234*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
1235*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
1236*7688df22SAndroid Build Coastguard Worker         break;
1237*7688df22SAndroid Build Coastguard Worker     }
1238*7688df22SAndroid Build Coastguard Worker 
1239*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf0) >> 4) {
1240*7688df22SAndroid Build Coastguard Worker     case 0:
1241*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 4;
1242*7688df22SAndroid Build Coastguard Worker         break;
1243*7688df22SAndroid Build Coastguard Worker     case 1:
1244*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
1245*7688df22SAndroid Build Coastguard Worker         break;
1246*7688df22SAndroid Build Coastguard Worker     case 2:
1247*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 16;
1248*7688df22SAndroid Build Coastguard Worker         break;
1249*7688df22SAndroid Build Coastguard Worker     default:
1250*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
1251*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
1252*7688df22SAndroid Build Coastguard Worker         break;
1253*7688df22SAndroid Build Coastguard Worker     }
1254*7688df22SAndroid Build Coastguard Worker 
1255*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf00) >> 8) {
1256*7688df22SAndroid Build Coastguard Worker     case 0:
1257*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
1258*7688df22SAndroid Build Coastguard Worker         break;
1259*7688df22SAndroid Build Coastguard Worker     case 1:
1260*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 512;
1261*7688df22SAndroid Build Coastguard Worker         break;
1262*7688df22SAndroid Build Coastguard Worker     default:
1263*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
1264*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
1265*7688df22SAndroid Build Coastguard Worker         break;
1266*7688df22SAndroid Build Coastguard Worker     }
1267*7688df22SAndroid Build Coastguard Worker 
1268*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf000) >> 12) {
1269*7688df22SAndroid Build Coastguard Worker     case 0:
1270*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 1024;
1271*7688df22SAndroid Build Coastguard Worker         break;
1272*7688df22SAndroid Build Coastguard Worker     case 1:
1273*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 2048;
1274*7688df22SAndroid Build Coastguard Worker         break;
1275*7688df22SAndroid Build Coastguard Worker     case 2:
1276*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 4096;
1277*7688df22SAndroid Build Coastguard Worker         break;
1278*7688df22SAndroid Build Coastguard Worker     default:
1279*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 4096;
1280*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
1281*7688df22SAndroid Build Coastguard Worker         break;
1282*7688df22SAndroid Build Coastguard Worker     }
1283*7688df22SAndroid Build Coastguard Worker     return 0;
1284*7688df22SAndroid Build Coastguard Worker }
1285*7688df22SAndroid Build Coastguard Worker 
si_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode,unsigned * tile_mode,unsigned * stencil_tile_mode)1286*7688df22SAndroid Build Coastguard Worker static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1287*7688df22SAndroid Build Coastguard Worker                              struct radeon_surface *surf,
1288*7688df22SAndroid Build Coastguard Worker                              unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1289*7688df22SAndroid Build Coastguard Worker {
1290*7688df22SAndroid Build Coastguard Worker     uint32_t gb_tile_mode;
1291*7688df22SAndroid Build Coastguard Worker 
1292*7688df22SAndroid Build Coastguard Worker     /* check surface dimension */
1293*7688df22SAndroid Build Coastguard Worker     if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1294*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
1295*7688df22SAndroid Build Coastguard Worker     }
1296*7688df22SAndroid Build Coastguard Worker 
1297*7688df22SAndroid Build Coastguard Worker     /* check mipmap last_level */
1298*7688df22SAndroid Build Coastguard Worker     if (surf->last_level > 15) {
1299*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
1300*7688df22SAndroid Build Coastguard Worker     }
1301*7688df22SAndroid Build Coastguard Worker 
1302*7688df22SAndroid Build Coastguard Worker     /* force 1d on kernel that can't do 2d */
1303*7688df22SAndroid Build Coastguard Worker     if (mode > RADEON_SURF_MODE_1D &&
1304*7688df22SAndroid Build Coastguard Worker         (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1305*7688df22SAndroid Build Coastguard Worker         if (surf->nsamples > 1) {
1306*7688df22SAndroid Build Coastguard Worker             fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1307*7688df22SAndroid Build Coastguard Worker             return -EFAULT;
1308*7688df22SAndroid Build Coastguard Worker         }
1309*7688df22SAndroid Build Coastguard Worker         mode = RADEON_SURF_MODE_1D;
1310*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1311*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(mode, MODE);
1312*7688df22SAndroid Build Coastguard Worker     }
1313*7688df22SAndroid Build Coastguard Worker 
1314*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1315*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
1316*7688df22SAndroid Build Coastguard Worker     }
1317*7688df22SAndroid Build Coastguard Worker 
1318*7688df22SAndroid Build Coastguard Worker     if (!surf->tile_split) {
1319*7688df22SAndroid Build Coastguard Worker         /* default value */
1320*7688df22SAndroid Build Coastguard Worker         surf->mtilea = 1;
1321*7688df22SAndroid Build Coastguard Worker         surf->bankw = 1;
1322*7688df22SAndroid Build Coastguard Worker         surf->bankh = 1;
1323*7688df22SAndroid Build Coastguard Worker         surf->tile_split = 64;
1324*7688df22SAndroid Build Coastguard Worker         surf->stencil_tile_split = 64;
1325*7688df22SAndroid Build Coastguard Worker     }
1326*7688df22SAndroid Build Coastguard Worker 
1327*7688df22SAndroid Build Coastguard Worker     switch (mode) {
1328*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_2D:
1329*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_SBUFFER) {
1330*7688df22SAndroid Build Coastguard Worker             switch (surf->nsamples) {
1331*7688df22SAndroid Build Coastguard Worker             case 1:
1332*7688df22SAndroid Build Coastguard Worker                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1333*7688df22SAndroid Build Coastguard Worker                 break;
1334*7688df22SAndroid Build Coastguard Worker             case 2:
1335*7688df22SAndroid Build Coastguard Worker                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1336*7688df22SAndroid Build Coastguard Worker                 break;
1337*7688df22SAndroid Build Coastguard Worker             case 4:
1338*7688df22SAndroid Build Coastguard Worker                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1339*7688df22SAndroid Build Coastguard Worker                 break;
1340*7688df22SAndroid Build Coastguard Worker             case 8:
1341*7688df22SAndroid Build Coastguard Worker                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1342*7688df22SAndroid Build Coastguard Worker                 break;
1343*7688df22SAndroid Build Coastguard Worker             default:
1344*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
1345*7688df22SAndroid Build Coastguard Worker             }
1346*7688df22SAndroid Build Coastguard Worker             /* retrieve tiling mode value */
1347*7688df22SAndroid Build Coastguard Worker             gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1348*7688df22SAndroid Build Coastguard Worker             si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1349*7688df22SAndroid Build Coastguard Worker         }
1350*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_ZBUFFER) {
1351*7688df22SAndroid Build Coastguard Worker             switch (surf->nsamples) {
1352*7688df22SAndroid Build Coastguard Worker             case 1:
1353*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1354*7688df22SAndroid Build Coastguard Worker                 break;
1355*7688df22SAndroid Build Coastguard Worker             case 2:
1356*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1357*7688df22SAndroid Build Coastguard Worker                 break;
1358*7688df22SAndroid Build Coastguard Worker             case 4:
1359*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1360*7688df22SAndroid Build Coastguard Worker                 break;
1361*7688df22SAndroid Build Coastguard Worker             case 8:
1362*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1363*7688df22SAndroid Build Coastguard Worker                 break;
1364*7688df22SAndroid Build Coastguard Worker             default:
1365*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
1366*7688df22SAndroid Build Coastguard Worker             }
1367*7688df22SAndroid Build Coastguard Worker         } else if (surf->flags & RADEON_SURF_SCANOUT) {
1368*7688df22SAndroid Build Coastguard Worker             switch (surf->bpe) {
1369*7688df22SAndroid Build Coastguard Worker             case 2:
1370*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1371*7688df22SAndroid Build Coastguard Worker                 break;
1372*7688df22SAndroid Build Coastguard Worker             case 4:
1373*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1374*7688df22SAndroid Build Coastguard Worker                 break;
1375*7688df22SAndroid Build Coastguard Worker             default:
1376*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
1377*7688df22SAndroid Build Coastguard Worker             }
1378*7688df22SAndroid Build Coastguard Worker         } else {
1379*7688df22SAndroid Build Coastguard Worker             switch (surf->bpe) {
1380*7688df22SAndroid Build Coastguard Worker             case 1:
1381*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1382*7688df22SAndroid Build Coastguard Worker                 break;
1383*7688df22SAndroid Build Coastguard Worker             case 2:
1384*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1385*7688df22SAndroid Build Coastguard Worker                 break;
1386*7688df22SAndroid Build Coastguard Worker             case 4:
1387*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1388*7688df22SAndroid Build Coastguard Worker                 break;
1389*7688df22SAndroid Build Coastguard Worker             case 8:
1390*7688df22SAndroid Build Coastguard Worker             case 16:
1391*7688df22SAndroid Build Coastguard Worker                 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1392*7688df22SAndroid Build Coastguard Worker                 break;
1393*7688df22SAndroid Build Coastguard Worker             default:
1394*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
1395*7688df22SAndroid Build Coastguard Worker             }
1396*7688df22SAndroid Build Coastguard Worker         }
1397*7688df22SAndroid Build Coastguard Worker         /* retrieve tiling mode value */
1398*7688df22SAndroid Build Coastguard Worker         gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1399*7688df22SAndroid Build Coastguard Worker         si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1400*7688df22SAndroid Build Coastguard Worker         break;
1401*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_1D:
1402*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_SBUFFER) {
1403*7688df22SAndroid Build Coastguard Worker             *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1404*7688df22SAndroid Build Coastguard Worker         }
1405*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_ZBUFFER) {
1406*7688df22SAndroid Build Coastguard Worker             *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1407*7688df22SAndroid Build Coastguard Worker         } else if (surf->flags & RADEON_SURF_SCANOUT) {
1408*7688df22SAndroid Build Coastguard Worker             *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1409*7688df22SAndroid Build Coastguard Worker         } else {
1410*7688df22SAndroid Build Coastguard Worker             *tile_mode = SI_TILE_MODE_COLOR_1D;
1411*7688df22SAndroid Build Coastguard Worker         }
1412*7688df22SAndroid Build Coastguard Worker         break;
1413*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR_ALIGNED:
1414*7688df22SAndroid Build Coastguard Worker     default:
1415*7688df22SAndroid Build Coastguard Worker         *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1416*7688df22SAndroid Build Coastguard Worker     }
1417*7688df22SAndroid Build Coastguard Worker 
1418*7688df22SAndroid Build Coastguard Worker     return 0;
1419*7688df22SAndroid Build Coastguard Worker }
1420*7688df22SAndroid Build Coastguard Worker 
si_surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,uint32_t xalign,uint32_t yalign,uint32_t zalign,uint32_t slice_align,uint64_t offset)1421*7688df22SAndroid Build Coastguard Worker static void si_surf_minify(struct radeon_surface *surf,
1422*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface_level *surflevel,
1423*7688df22SAndroid Build Coastguard Worker                            unsigned bpe, unsigned level,
1424*7688df22SAndroid Build Coastguard Worker                            uint32_t xalign, uint32_t yalign, uint32_t zalign,
1425*7688df22SAndroid Build Coastguard Worker                            uint32_t slice_align, uint64_t offset)
1426*7688df22SAndroid Build Coastguard Worker {
1427*7688df22SAndroid Build Coastguard Worker     if (level == 0) {
1428*7688df22SAndroid Build Coastguard Worker         surflevel->npix_x = surf->npix_x;
1429*7688df22SAndroid Build Coastguard Worker     } else {
1430*7688df22SAndroid Build Coastguard Worker         surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1431*7688df22SAndroid Build Coastguard Worker     }
1432*7688df22SAndroid Build Coastguard Worker     surflevel->npix_y = mip_minify(surf->npix_y, level);
1433*7688df22SAndroid Build Coastguard Worker     surflevel->npix_z = mip_minify(surf->npix_z, level);
1434*7688df22SAndroid Build Coastguard Worker 
1435*7688df22SAndroid Build Coastguard Worker     if (level == 0 && surf->last_level > 0) {
1436*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1437*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1438*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1439*7688df22SAndroid Build Coastguard Worker     } else {
1440*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1441*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1442*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1443*7688df22SAndroid Build Coastguard Worker     }
1444*7688df22SAndroid Build Coastguard Worker 
1445*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
1446*7688df22SAndroid Build Coastguard Worker 
1447*7688df22SAndroid Build Coastguard Worker     /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1448*7688df22SAndroid Build Coastguard Worker      * these are just guesses for the rules behind those
1449*7688df22SAndroid Build Coastguard Worker      */
1450*7688df22SAndroid Build Coastguard Worker     if (level == 0 && surf->last_level == 0)
1451*7688df22SAndroid Build Coastguard Worker         /* Non-mipmap pitch padded to slice alignment */
1452*7688df22SAndroid Build Coastguard Worker         /* Using just bpe here breaks stencil blitting; surf->bpe works. */
1453*7688df22SAndroid Build Coastguard Worker         xalign = MAX2(xalign, slice_align / surf->bpe);
1454*7688df22SAndroid Build Coastguard Worker     else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED)
1455*7688df22SAndroid Build Coastguard Worker         /* Small rows evenly distributed across slice */
1456*7688df22SAndroid Build Coastguard Worker         xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y);
1457*7688df22SAndroid Build Coastguard Worker 
1458*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
1459*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
1460*7688df22SAndroid Build Coastguard Worker 
1461*7688df22SAndroid Build Coastguard Worker     surflevel->offset = offset;
1462*7688df22SAndroid Build Coastguard Worker     surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1463*7688df22SAndroid Build Coastguard Worker     surflevel->slice_size = ALIGN((uint64_t)surflevel->pitch_bytes * surflevel->nblk_y,
1464*7688df22SAndroid Build Coastguard Worker 				  (uint64_t)slice_align);
1465*7688df22SAndroid Build Coastguard Worker 
1466*7688df22SAndroid Build Coastguard Worker     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1467*7688df22SAndroid Build Coastguard Worker }
1468*7688df22SAndroid Build Coastguard Worker 
si_surf_minify_2d(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,unsigned slice_pt,uint32_t xalign,uint32_t yalign,uint32_t zalign,unsigned mtileb,uint64_t offset)1469*7688df22SAndroid Build Coastguard Worker static void si_surf_minify_2d(struct radeon_surface *surf,
1470*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface_level *surflevel,
1471*7688df22SAndroid Build Coastguard Worker                               unsigned bpe, unsigned level, unsigned slice_pt,
1472*7688df22SAndroid Build Coastguard Worker                               uint32_t xalign, uint32_t yalign, uint32_t zalign,
1473*7688df22SAndroid Build Coastguard Worker                               unsigned mtileb, uint64_t offset)
1474*7688df22SAndroid Build Coastguard Worker {
1475*7688df22SAndroid Build Coastguard Worker     unsigned mtile_pr, mtile_ps;
1476*7688df22SAndroid Build Coastguard Worker 
1477*7688df22SAndroid Build Coastguard Worker     if (level == 0) {
1478*7688df22SAndroid Build Coastguard Worker         surflevel->npix_x = surf->npix_x;
1479*7688df22SAndroid Build Coastguard Worker     } else {
1480*7688df22SAndroid Build Coastguard Worker         surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1481*7688df22SAndroid Build Coastguard Worker     }
1482*7688df22SAndroid Build Coastguard Worker     surflevel->npix_y = mip_minify(surf->npix_y, level);
1483*7688df22SAndroid Build Coastguard Worker     surflevel->npix_z = mip_minify(surf->npix_z, level);
1484*7688df22SAndroid Build Coastguard Worker 
1485*7688df22SAndroid Build Coastguard Worker     if (level == 0 && surf->last_level > 0) {
1486*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1487*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1488*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1489*7688df22SAndroid Build Coastguard Worker     } else {
1490*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1491*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1492*7688df22SAndroid Build Coastguard Worker         surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1493*7688df22SAndroid Build Coastguard Worker     }
1494*7688df22SAndroid Build Coastguard Worker 
1495*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1496*7688df22SAndroid Build Coastguard Worker         !(surf->flags & RADEON_SURF_FMASK)) {
1497*7688df22SAndroid Build Coastguard Worker         if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1498*7688df22SAndroid Build Coastguard Worker             surflevel->mode = RADEON_SURF_MODE_1D;
1499*7688df22SAndroid Build Coastguard Worker             return;
1500*7688df22SAndroid Build Coastguard Worker         }
1501*7688df22SAndroid Build Coastguard Worker     }
1502*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
1503*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
1504*7688df22SAndroid Build Coastguard Worker     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
1505*7688df22SAndroid Build Coastguard Worker 
1506*7688df22SAndroid Build Coastguard Worker     /* macro tile per row */
1507*7688df22SAndroid Build Coastguard Worker     mtile_pr = surflevel->nblk_x / xalign;
1508*7688df22SAndroid Build Coastguard Worker     /* macro tile per slice */
1509*7688df22SAndroid Build Coastguard Worker     mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1510*7688df22SAndroid Build Coastguard Worker     surflevel->offset = offset;
1511*7688df22SAndroid Build Coastguard Worker     surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1512*7688df22SAndroid Build Coastguard Worker     surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
1513*7688df22SAndroid Build Coastguard Worker 
1514*7688df22SAndroid Build Coastguard Worker     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1515*7688df22SAndroid Build Coastguard Worker }
1516*7688df22SAndroid Build Coastguard Worker 
si_surface_init_linear_aligned(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,uint64_t offset,unsigned start_level)1517*7688df22SAndroid Build Coastguard Worker static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1518*7688df22SAndroid Build Coastguard Worker                                           struct radeon_surface *surf,
1519*7688df22SAndroid Build Coastguard Worker                                           unsigned tile_mode,
1520*7688df22SAndroid Build Coastguard Worker                                           uint64_t offset, unsigned start_level)
1521*7688df22SAndroid Build Coastguard Worker {
1522*7688df22SAndroid Build Coastguard Worker     uint32_t xalign, yalign, zalign, slice_align;
1523*7688df22SAndroid Build Coastguard Worker     unsigned i;
1524*7688df22SAndroid Build Coastguard Worker 
1525*7688df22SAndroid Build Coastguard Worker     /* compute alignment */
1526*7688df22SAndroid Build Coastguard Worker     if (!start_level) {
1527*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1528*7688df22SAndroid Build Coastguard Worker     }
1529*7688df22SAndroid Build Coastguard Worker     xalign = MAX2(8, 64 / surf->bpe);
1530*7688df22SAndroid Build Coastguard Worker     yalign = 1;
1531*7688df22SAndroid Build Coastguard Worker     zalign = 1;
1532*7688df22SAndroid Build Coastguard Worker     slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1533*7688df22SAndroid Build Coastguard Worker 
1534*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
1535*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
1536*7688df22SAndroid Build Coastguard Worker         surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1537*7688df22SAndroid Build Coastguard Worker         si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1538*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
1539*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
1540*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
1541*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, surf->bo_alignment);
1542*7688df22SAndroid Build Coastguard Worker         }
1543*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1544*7688df22SAndroid Build Coastguard Worker             surf->tiling_index[i] = tile_mode;
1545*7688df22SAndroid Build Coastguard Worker         }
1546*7688df22SAndroid Build Coastguard Worker     }
1547*7688df22SAndroid Build Coastguard Worker     return 0;
1548*7688df22SAndroid Build Coastguard Worker }
1549*7688df22SAndroid Build Coastguard Worker 
si_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,uint64_t offset,unsigned start_level)1550*7688df22SAndroid Build Coastguard Worker static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1551*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface *surf,
1552*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface_level *level,
1553*7688df22SAndroid Build Coastguard Worker                               unsigned bpe, unsigned tile_mode,
1554*7688df22SAndroid Build Coastguard Worker                               uint64_t offset, unsigned start_level)
1555*7688df22SAndroid Build Coastguard Worker {
1556*7688df22SAndroid Build Coastguard Worker     uint32_t xalign, yalign, zalign, slice_align;
1557*7688df22SAndroid Build Coastguard Worker     unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
1558*7688df22SAndroid Build Coastguard Worker     unsigned i;
1559*7688df22SAndroid Build Coastguard Worker 
1560*7688df22SAndroid Build Coastguard Worker     /* compute alignment */
1561*7688df22SAndroid Build Coastguard Worker     xalign = 8;
1562*7688df22SAndroid Build Coastguard Worker     yalign = 8;
1563*7688df22SAndroid Build Coastguard Worker     zalign = 1;
1564*7688df22SAndroid Build Coastguard Worker     slice_align = surf_man->hw_info.group_bytes;
1565*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SCANOUT) {
1566*7688df22SAndroid Build Coastguard Worker         xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1567*7688df22SAndroid Build Coastguard Worker     }
1568*7688df22SAndroid Build Coastguard Worker 
1569*7688df22SAndroid Build Coastguard Worker     if (start_level <= 1) {
1570*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1571*7688df22SAndroid Build Coastguard Worker 
1572*7688df22SAndroid Build Coastguard Worker         if (offset) {
1573*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, alignment);
1574*7688df22SAndroid Build Coastguard Worker         }
1575*7688df22SAndroid Build Coastguard Worker     }
1576*7688df22SAndroid Build Coastguard Worker 
1577*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
1578*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
1579*7688df22SAndroid Build Coastguard Worker         level[i].mode = RADEON_SURF_MODE_1D;
1580*7688df22SAndroid Build Coastguard Worker         si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1581*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
1582*7688df22SAndroid Build Coastguard Worker         offset = surf->bo_size;
1583*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
1584*7688df22SAndroid Build Coastguard Worker             offset = ALIGN(offset, alignment);
1585*7688df22SAndroid Build Coastguard Worker         }
1586*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1587*7688df22SAndroid Build Coastguard Worker             if (surf->level == level) {
1588*7688df22SAndroid Build Coastguard Worker                 surf->tiling_index[i] = tile_mode;
1589*7688df22SAndroid Build Coastguard Worker                 /* it's ok because stencil is done after */
1590*7688df22SAndroid Build Coastguard Worker                 surf->stencil_tiling_index[i] = tile_mode;
1591*7688df22SAndroid Build Coastguard Worker             } else {
1592*7688df22SAndroid Build Coastguard Worker                 surf->stencil_tiling_index[i] = tile_mode;
1593*7688df22SAndroid Build Coastguard Worker             }
1594*7688df22SAndroid Build Coastguard Worker         }
1595*7688df22SAndroid Build Coastguard Worker     }
1596*7688df22SAndroid Build Coastguard Worker     return 0;
1597*7688df22SAndroid Build Coastguard Worker }
1598*7688df22SAndroid Build Coastguard Worker 
si_surface_init_1d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)1599*7688df22SAndroid Build Coastguard Worker static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1600*7688df22SAndroid Build Coastguard Worker                                        struct radeon_surface *surf,
1601*7688df22SAndroid Build Coastguard Worker                                        unsigned tile_mode, unsigned stencil_tile_mode)
1602*7688df22SAndroid Build Coastguard Worker {
1603*7688df22SAndroid Build Coastguard Worker     int r;
1604*7688df22SAndroid Build Coastguard Worker 
1605*7688df22SAndroid Build Coastguard Worker     r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1606*7688df22SAndroid Build Coastguard Worker     if (r) {
1607*7688df22SAndroid Build Coastguard Worker         return r;
1608*7688df22SAndroid Build Coastguard Worker     }
1609*7688df22SAndroid Build Coastguard Worker 
1610*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SBUFFER) {
1611*7688df22SAndroid Build Coastguard Worker         r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1612*7688df22SAndroid Build Coastguard Worker         surf->stencil_offset = surf->stencil_level[0].offset;
1613*7688df22SAndroid Build Coastguard Worker     }
1614*7688df22SAndroid Build Coastguard Worker     return r;
1615*7688df22SAndroid Build Coastguard Worker }
1616*7688df22SAndroid Build Coastguard Worker 
si_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,unsigned num_pipes,unsigned num_banks,unsigned tile_split,uint64_t offset,unsigned start_level)1617*7688df22SAndroid Build Coastguard Worker static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1618*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface *surf,
1619*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface_level *level,
1620*7688df22SAndroid Build Coastguard Worker                               unsigned bpe, unsigned tile_mode,
1621*7688df22SAndroid Build Coastguard Worker                               unsigned num_pipes, unsigned num_banks,
1622*7688df22SAndroid Build Coastguard Worker                               unsigned tile_split,
1623*7688df22SAndroid Build Coastguard Worker                               uint64_t offset,
1624*7688df22SAndroid Build Coastguard Worker                               unsigned start_level)
1625*7688df22SAndroid Build Coastguard Worker {
1626*7688df22SAndroid Build Coastguard Worker     uint64_t aligned_offset = offset;
1627*7688df22SAndroid Build Coastguard Worker     unsigned tilew, tileh, tileb;
1628*7688df22SAndroid Build Coastguard Worker     unsigned mtilew, mtileh, mtileb;
1629*7688df22SAndroid Build Coastguard Worker     unsigned slice_pt;
1630*7688df22SAndroid Build Coastguard Worker     unsigned i;
1631*7688df22SAndroid Build Coastguard Worker 
1632*7688df22SAndroid Build Coastguard Worker     /* compute tile values */
1633*7688df22SAndroid Build Coastguard Worker     tilew = 8;
1634*7688df22SAndroid Build Coastguard Worker     tileh = 8;
1635*7688df22SAndroid Build Coastguard Worker     tileb = tilew * tileh * bpe * surf->nsamples;
1636*7688df22SAndroid Build Coastguard Worker     /* slices per tile */
1637*7688df22SAndroid Build Coastguard Worker     slice_pt = 1;
1638*7688df22SAndroid Build Coastguard Worker     if (tileb > tile_split && tile_split) {
1639*7688df22SAndroid Build Coastguard Worker         slice_pt = tileb / tile_split;
1640*7688df22SAndroid Build Coastguard Worker     }
1641*7688df22SAndroid Build Coastguard Worker     tileb = tileb / slice_pt;
1642*7688df22SAndroid Build Coastguard Worker 
1643*7688df22SAndroid Build Coastguard Worker     /* macro tile width & height */
1644*7688df22SAndroid Build Coastguard Worker     mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1645*7688df22SAndroid Build Coastguard Worker     mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1646*7688df22SAndroid Build Coastguard Worker 
1647*7688df22SAndroid Build Coastguard Worker     /* macro tile bytes */
1648*7688df22SAndroid Build Coastguard Worker     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1649*7688df22SAndroid Build Coastguard Worker 
1650*7688df22SAndroid Build Coastguard Worker     if (start_level <= 1) {
1651*7688df22SAndroid Build Coastguard Worker         unsigned alignment = MAX2(256, mtileb);
1652*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1653*7688df22SAndroid Build Coastguard Worker 
1654*7688df22SAndroid Build Coastguard Worker         if (aligned_offset) {
1655*7688df22SAndroid Build Coastguard Worker             aligned_offset = ALIGN(aligned_offset, alignment);
1656*7688df22SAndroid Build Coastguard Worker         }
1657*7688df22SAndroid Build Coastguard Worker     }
1658*7688df22SAndroid Build Coastguard Worker 
1659*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
1660*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
1661*7688df22SAndroid Build Coastguard Worker         level[i].mode = RADEON_SURF_MODE_2D;
1662*7688df22SAndroid Build Coastguard Worker         si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
1663*7688df22SAndroid Build Coastguard Worker         if (level[i].mode == RADEON_SURF_MODE_1D) {
1664*7688df22SAndroid Build Coastguard Worker             switch (tile_mode) {
1665*7688df22SAndroid Build Coastguard Worker             case SI_TILE_MODE_COLOR_2D_8BPP:
1666*7688df22SAndroid Build Coastguard Worker             case SI_TILE_MODE_COLOR_2D_16BPP:
1667*7688df22SAndroid Build Coastguard Worker             case SI_TILE_MODE_COLOR_2D_32BPP:
1668*7688df22SAndroid Build Coastguard Worker             case SI_TILE_MODE_COLOR_2D_64BPP:
1669*7688df22SAndroid Build Coastguard Worker                 tile_mode = SI_TILE_MODE_COLOR_1D;
1670*7688df22SAndroid Build Coastguard Worker                 break;
1671*7688df22SAndroid Build Coastguard Worker             case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1672*7688df22SAndroid Build Coastguard Worker             case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1673*7688df22SAndroid Build Coastguard Worker                 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1674*7688df22SAndroid Build Coastguard Worker                 break;
1675*7688df22SAndroid Build Coastguard Worker             case SI_TILE_MODE_DEPTH_STENCIL_2D:
1676*7688df22SAndroid Build Coastguard Worker                 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1677*7688df22SAndroid Build Coastguard Worker                 break;
1678*7688df22SAndroid Build Coastguard Worker             default:
1679*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
1680*7688df22SAndroid Build Coastguard Worker             }
1681*7688df22SAndroid Build Coastguard Worker             return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1682*7688df22SAndroid Build Coastguard Worker         }
1683*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
1684*7688df22SAndroid Build Coastguard Worker         aligned_offset = offset = surf->bo_size;
1685*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
1686*7688df22SAndroid Build Coastguard Worker             aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
1687*7688df22SAndroid Build Coastguard Worker         }
1688*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1689*7688df22SAndroid Build Coastguard Worker             if (surf->level == level) {
1690*7688df22SAndroid Build Coastguard Worker                 surf->tiling_index[i] = tile_mode;
1691*7688df22SAndroid Build Coastguard Worker                 /* it's ok because stencil is done after */
1692*7688df22SAndroid Build Coastguard Worker                 surf->stencil_tiling_index[i] = tile_mode;
1693*7688df22SAndroid Build Coastguard Worker             } else {
1694*7688df22SAndroid Build Coastguard Worker                 surf->stencil_tiling_index[i] = tile_mode;
1695*7688df22SAndroid Build Coastguard Worker             }
1696*7688df22SAndroid Build Coastguard Worker         }
1697*7688df22SAndroid Build Coastguard Worker     }
1698*7688df22SAndroid Build Coastguard Worker     return 0;
1699*7688df22SAndroid Build Coastguard Worker }
1700*7688df22SAndroid Build Coastguard Worker 
si_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)1701*7688df22SAndroid Build Coastguard Worker static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1702*7688df22SAndroid Build Coastguard Worker                                        struct radeon_surface *surf,
1703*7688df22SAndroid Build Coastguard Worker                                        unsigned tile_mode, unsigned stencil_tile_mode)
1704*7688df22SAndroid Build Coastguard Worker {
1705*7688df22SAndroid Build Coastguard Worker     unsigned num_pipes, num_banks;
1706*7688df22SAndroid Build Coastguard Worker     uint32_t gb_tile_mode;
1707*7688df22SAndroid Build Coastguard Worker     int r;
1708*7688df22SAndroid Build Coastguard Worker 
1709*7688df22SAndroid Build Coastguard Worker     /* retrieve tiling mode value */
1710*7688df22SAndroid Build Coastguard Worker     gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1711*7688df22SAndroid Build Coastguard Worker     si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1712*7688df22SAndroid Build Coastguard Worker 
1713*7688df22SAndroid Build Coastguard Worker     r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1714*7688df22SAndroid Build Coastguard Worker     if (r) {
1715*7688df22SAndroid Build Coastguard Worker         return r;
1716*7688df22SAndroid Build Coastguard Worker     }
1717*7688df22SAndroid Build Coastguard Worker 
1718*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SBUFFER) {
1719*7688df22SAndroid Build Coastguard Worker         r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0);
1720*7688df22SAndroid Build Coastguard Worker         surf->stencil_offset = surf->stencil_level[0].offset;
1721*7688df22SAndroid Build Coastguard Worker     }
1722*7688df22SAndroid Build Coastguard Worker     return r;
1723*7688df22SAndroid Build Coastguard Worker }
1724*7688df22SAndroid Build Coastguard Worker 
si_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)1725*7688df22SAndroid Build Coastguard Worker static int si_surface_init(struct radeon_surface_manager *surf_man,
1726*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface *surf)
1727*7688df22SAndroid Build Coastguard Worker {
1728*7688df22SAndroid Build Coastguard Worker     unsigned mode, tile_mode, stencil_tile_mode;
1729*7688df22SAndroid Build Coastguard Worker     int r;
1730*7688df22SAndroid Build Coastguard Worker 
1731*7688df22SAndroid Build Coastguard Worker     /* MSAA surfaces support the 2D mode only. */
1732*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples > 1) {
1733*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1734*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1735*7688df22SAndroid Build Coastguard Worker     }
1736*7688df22SAndroid Build Coastguard Worker 
1737*7688df22SAndroid Build Coastguard Worker     /* tiling mode */
1738*7688df22SAndroid Build Coastguard Worker     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1739*7688df22SAndroid Build Coastguard Worker 
1740*7688df22SAndroid Build Coastguard Worker     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1741*7688df22SAndroid Build Coastguard Worker         /* zbuffer only support 1D or 2D tiled surface */
1742*7688df22SAndroid Build Coastguard Worker         switch (mode) {
1743*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_1D:
1744*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_2D:
1745*7688df22SAndroid Build Coastguard Worker             break;
1746*7688df22SAndroid Build Coastguard Worker         default:
1747*7688df22SAndroid Build Coastguard Worker             mode = RADEON_SURF_MODE_1D;
1748*7688df22SAndroid Build Coastguard Worker             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1749*7688df22SAndroid Build Coastguard Worker             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1750*7688df22SAndroid Build Coastguard Worker             break;
1751*7688df22SAndroid Build Coastguard Worker         }
1752*7688df22SAndroid Build Coastguard Worker     }
1753*7688df22SAndroid Build Coastguard Worker 
1754*7688df22SAndroid Build Coastguard Worker     r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1755*7688df22SAndroid Build Coastguard Worker     if (r) {
1756*7688df22SAndroid Build Coastguard Worker         return r;
1757*7688df22SAndroid Build Coastguard Worker     }
1758*7688df22SAndroid Build Coastguard Worker 
1759*7688df22SAndroid Build Coastguard Worker     surf->stencil_offset = 0;
1760*7688df22SAndroid Build Coastguard Worker     surf->bo_alignment = 0;
1761*7688df22SAndroid Build Coastguard Worker 
1762*7688df22SAndroid Build Coastguard Worker     /* check tiling mode */
1763*7688df22SAndroid Build Coastguard Worker     switch (mode) {
1764*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR:
1765*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_linear(surf_man, surf, 0, 0);
1766*7688df22SAndroid Build Coastguard Worker         break;
1767*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR_ALIGNED:
1768*7688df22SAndroid Build Coastguard Worker         r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1769*7688df22SAndroid Build Coastguard Worker         break;
1770*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_1D:
1771*7688df22SAndroid Build Coastguard Worker         r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1772*7688df22SAndroid Build Coastguard Worker         break;
1773*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_2D:
1774*7688df22SAndroid Build Coastguard Worker         r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1775*7688df22SAndroid Build Coastguard Worker         break;
1776*7688df22SAndroid Build Coastguard Worker     default:
1777*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
1778*7688df22SAndroid Build Coastguard Worker     }
1779*7688df22SAndroid Build Coastguard Worker     return r;
1780*7688df22SAndroid Build Coastguard Worker }
1781*7688df22SAndroid Build Coastguard Worker 
1782*7688df22SAndroid Build Coastguard Worker /*
1783*7688df22SAndroid Build Coastguard Worker  * depending on surface
1784*7688df22SAndroid Build Coastguard Worker  */
si_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)1785*7688df22SAndroid Build Coastguard Worker static int si_surface_best(struct radeon_surface_manager *surf_man,
1786*7688df22SAndroid Build Coastguard Worker                            struct radeon_surface *surf)
1787*7688df22SAndroid Build Coastguard Worker {
1788*7688df22SAndroid Build Coastguard Worker     unsigned mode, tile_mode, stencil_tile_mode;
1789*7688df22SAndroid Build Coastguard Worker 
1790*7688df22SAndroid Build Coastguard Worker     /* tiling mode */
1791*7688df22SAndroid Build Coastguard Worker     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1792*7688df22SAndroid Build Coastguard Worker 
1793*7688df22SAndroid Build Coastguard Worker     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1794*7688df22SAndroid Build Coastguard Worker         !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1795*7688df22SAndroid Build Coastguard Worker         /* depth/stencil force 1d tiling for old mesa */
1796*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1797*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1798*7688df22SAndroid Build Coastguard Worker     }
1799*7688df22SAndroid Build Coastguard Worker 
1800*7688df22SAndroid Build Coastguard Worker     return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1801*7688df22SAndroid Build Coastguard Worker }
1802*7688df22SAndroid Build Coastguard Worker 
1803*7688df22SAndroid Build Coastguard Worker 
1804*7688df22SAndroid Build Coastguard Worker /* ===========================================================================
1805*7688df22SAndroid Build Coastguard Worker  * Sea Islands family
1806*7688df22SAndroid Build Coastguard Worker  */
1807*7688df22SAndroid Build Coastguard Worker #define CIK__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
1808*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P2               0
1809*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
1810*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
1811*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
1812*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
1813*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
1814*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
1815*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
1816*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
1817*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
1818*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
1819*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
1820*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16   16
1821*7688df22SAndroid Build Coastguard Worker #define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16  17
1822*7688df22SAndroid Build Coastguard Worker #define CIK__GB_TILE_MODE__TILE_SPLIT(x)         (((x) >> 11) & 0x7)
1823*7688df22SAndroid Build Coastguard Worker #define     CIK__TILE_SPLIT__64B                         0
1824*7688df22SAndroid Build Coastguard Worker #define     CIK__TILE_SPLIT__128B                        1
1825*7688df22SAndroid Build Coastguard Worker #define     CIK__TILE_SPLIT__256B                        2
1826*7688df22SAndroid Build Coastguard Worker #define     CIK__TILE_SPLIT__512B                        3
1827*7688df22SAndroid Build Coastguard Worker #define     CIK__TILE_SPLIT__1024B                       4
1828*7688df22SAndroid Build Coastguard Worker #define     CIK__TILE_SPLIT__2048B                       5
1829*7688df22SAndroid Build Coastguard Worker #define     CIK__TILE_SPLIT__4096B                       6
1830*7688df22SAndroid Build Coastguard Worker #define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x)         (((x) >> 25) & 0x3)
1831*7688df22SAndroid Build Coastguard Worker #define     CIK__SAMPLE_SPLIT__1                         0
1832*7688df22SAndroid Build Coastguard Worker #define     CIK__SAMPLE_SPLIT__2                         1
1833*7688df22SAndroid Build Coastguard Worker #define     CIK__SAMPLE_SPLIT__4                         2
1834*7688df22SAndroid Build Coastguard Worker #define     CIK__SAMPLE_SPLIT__8                         3
1835*7688df22SAndroid Build Coastguard Worker #define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x)        ((x) & 0x3)
1836*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_WIDTH__1                           0
1837*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_WIDTH__2                           1
1838*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_WIDTH__4                           2
1839*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_WIDTH__8                           3
1840*7688df22SAndroid Build Coastguard Worker #define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x)       (((x) >> 2) & 0x3)
1841*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_HEIGHT__1                          0
1842*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_HEIGHT__2                          1
1843*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_HEIGHT__4                          2
1844*7688df22SAndroid Build Coastguard Worker #define     CIK__BANK_HEIGHT__8                          3
1845*7688df22SAndroid Build Coastguard Worker #define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
1846*7688df22SAndroid Build Coastguard Worker #define     CIK__MACRO_TILE_ASPECT__1                    0
1847*7688df22SAndroid Build Coastguard Worker #define     CIK__MACRO_TILE_ASPECT__2                    1
1848*7688df22SAndroid Build Coastguard Worker #define     CIK__MACRO_TILE_ASPECT__4                    2
1849*7688df22SAndroid Build Coastguard Worker #define     CIK__MACRO_TILE_ASPECT__8                    3
1850*7688df22SAndroid Build Coastguard Worker #define CIK__GB_MACROTILE_MODE__NUM_BANKS(x)         (((x) >> 6) & 0x3)
1851*7688df22SAndroid Build Coastguard Worker #define     CIK__NUM_BANKS__2_BANK                       0
1852*7688df22SAndroid Build Coastguard Worker #define     CIK__NUM_BANKS__4_BANK                       1
1853*7688df22SAndroid Build Coastguard Worker #define     CIK__NUM_BANKS__8_BANK                       2
1854*7688df22SAndroid Build Coastguard Worker #define     CIK__NUM_BANKS__16_BANK                      3
1855*7688df22SAndroid Build Coastguard Worker 
1856*7688df22SAndroid Build Coastguard Worker 
cik_get_2d_params(struct radeon_surface_manager * surf_man,unsigned bpe,unsigned nsamples,bool is_color,unsigned tile_mode,uint32_t * num_pipes,uint32_t * tile_split_ptr,uint32_t * num_banks,uint32_t * macro_tile_aspect,uint32_t * bank_w,uint32_t * bank_h)1857*7688df22SAndroid Build Coastguard Worker static void cik_get_2d_params(struct radeon_surface_manager *surf_man,
1858*7688df22SAndroid Build Coastguard Worker                               unsigned bpe, unsigned nsamples, bool is_color,
1859*7688df22SAndroid Build Coastguard Worker                               unsigned tile_mode,
1860*7688df22SAndroid Build Coastguard Worker                               uint32_t *num_pipes,
1861*7688df22SAndroid Build Coastguard Worker                               uint32_t *tile_split_ptr,
1862*7688df22SAndroid Build Coastguard Worker                               uint32_t *num_banks,
1863*7688df22SAndroid Build Coastguard Worker                               uint32_t *macro_tile_aspect,
1864*7688df22SAndroid Build Coastguard Worker                               uint32_t *bank_w,
1865*7688df22SAndroid Build Coastguard Worker                               uint32_t *bank_h)
1866*7688df22SAndroid Build Coastguard Worker {
1867*7688df22SAndroid Build Coastguard Worker     uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1868*7688df22SAndroid Build Coastguard Worker     unsigned tileb_1x, tileb;
1869*7688df22SAndroid Build Coastguard Worker     unsigned gb_macrotile_mode;
1870*7688df22SAndroid Build Coastguard Worker     unsigned macrotile_index;
1871*7688df22SAndroid Build Coastguard Worker     unsigned tile_split, sample_split;
1872*7688df22SAndroid Build Coastguard Worker 
1873*7688df22SAndroid Build Coastguard Worker     if (num_pipes) {
1874*7688df22SAndroid Build Coastguard Worker         switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1875*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P2:
1876*7688df22SAndroid Build Coastguard Worker         default:
1877*7688df22SAndroid Build Coastguard Worker             *num_pipes = 2;
1878*7688df22SAndroid Build Coastguard Worker             break;
1879*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1880*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1881*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1882*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1883*7688df22SAndroid Build Coastguard Worker             *num_pipes = 4;
1884*7688df22SAndroid Build Coastguard Worker             break;
1885*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1886*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1887*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1888*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1889*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1890*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1891*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1892*7688df22SAndroid Build Coastguard Worker             *num_pipes = 8;
1893*7688df22SAndroid Build Coastguard Worker             break;
1894*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
1895*7688df22SAndroid Build Coastguard Worker         case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
1896*7688df22SAndroid Build Coastguard Worker             *num_pipes = 16;
1897*7688df22SAndroid Build Coastguard Worker             break;
1898*7688df22SAndroid Build Coastguard Worker         }
1899*7688df22SAndroid Build Coastguard Worker     }
1900*7688df22SAndroid Build Coastguard Worker     switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1901*7688df22SAndroid Build Coastguard Worker     default:
1902*7688df22SAndroid Build Coastguard Worker     case CIK__TILE_SPLIT__64B:
1903*7688df22SAndroid Build Coastguard Worker         tile_split = 64;
1904*7688df22SAndroid Build Coastguard Worker         break;
1905*7688df22SAndroid Build Coastguard Worker     case CIK__TILE_SPLIT__128B:
1906*7688df22SAndroid Build Coastguard Worker         tile_split = 128;
1907*7688df22SAndroid Build Coastguard Worker         break;
1908*7688df22SAndroid Build Coastguard Worker     case CIK__TILE_SPLIT__256B:
1909*7688df22SAndroid Build Coastguard Worker         tile_split = 256;
1910*7688df22SAndroid Build Coastguard Worker         break;
1911*7688df22SAndroid Build Coastguard Worker     case CIK__TILE_SPLIT__512B:
1912*7688df22SAndroid Build Coastguard Worker         tile_split = 512;
1913*7688df22SAndroid Build Coastguard Worker         break;
1914*7688df22SAndroid Build Coastguard Worker     case CIK__TILE_SPLIT__1024B:
1915*7688df22SAndroid Build Coastguard Worker         tile_split = 1024;
1916*7688df22SAndroid Build Coastguard Worker         break;
1917*7688df22SAndroid Build Coastguard Worker     case CIK__TILE_SPLIT__2048B:
1918*7688df22SAndroid Build Coastguard Worker         tile_split = 2048;
1919*7688df22SAndroid Build Coastguard Worker         break;
1920*7688df22SAndroid Build Coastguard Worker     case CIK__TILE_SPLIT__4096B:
1921*7688df22SAndroid Build Coastguard Worker         tile_split = 4096;
1922*7688df22SAndroid Build Coastguard Worker         break;
1923*7688df22SAndroid Build Coastguard Worker     }
1924*7688df22SAndroid Build Coastguard Worker     switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
1925*7688df22SAndroid Build Coastguard Worker     default:
1926*7688df22SAndroid Build Coastguard Worker     case CIK__SAMPLE_SPLIT__1:
1927*7688df22SAndroid Build Coastguard Worker         sample_split = 1;
1928*7688df22SAndroid Build Coastguard Worker         break;
1929*7688df22SAndroid Build Coastguard Worker     case CIK__SAMPLE_SPLIT__2:
1930*7688df22SAndroid Build Coastguard Worker         sample_split = 2;
1931*7688df22SAndroid Build Coastguard Worker         break;
1932*7688df22SAndroid Build Coastguard Worker     case CIK__SAMPLE_SPLIT__4:
1933*7688df22SAndroid Build Coastguard Worker         sample_split = 4;
1934*7688df22SAndroid Build Coastguard Worker         break;
1935*7688df22SAndroid Build Coastguard Worker     case CIK__SAMPLE_SPLIT__8:
1936*7688df22SAndroid Build Coastguard Worker         sample_split = 8;
1937*7688df22SAndroid Build Coastguard Worker         break;
1938*7688df22SAndroid Build Coastguard Worker     }
1939*7688df22SAndroid Build Coastguard Worker 
1940*7688df22SAndroid Build Coastguard Worker     /* Adjust the tile split. */
1941*7688df22SAndroid Build Coastguard Worker     tileb_1x = 8 * 8 * bpe;
1942*7688df22SAndroid Build Coastguard Worker     if (is_color) {
1943*7688df22SAndroid Build Coastguard Worker         tile_split = MAX2(256, sample_split * tileb_1x);
1944*7688df22SAndroid Build Coastguard Worker     }
1945*7688df22SAndroid Build Coastguard Worker     tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
1946*7688df22SAndroid Build Coastguard Worker 
1947*7688df22SAndroid Build Coastguard Worker     /* Determine the macrotile index. */
1948*7688df22SAndroid Build Coastguard Worker     tileb = MIN2(tile_split, nsamples * tileb_1x);
1949*7688df22SAndroid Build Coastguard Worker 
1950*7688df22SAndroid Build Coastguard Worker     for (macrotile_index = 0; tileb > 64; macrotile_index++) {
1951*7688df22SAndroid Build Coastguard Worker         tileb >>= 1;
1952*7688df22SAndroid Build Coastguard Worker     }
1953*7688df22SAndroid Build Coastguard Worker     gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
1954*7688df22SAndroid Build Coastguard Worker 
1955*7688df22SAndroid Build Coastguard Worker     if (tile_split_ptr) {
1956*7688df22SAndroid Build Coastguard Worker         *tile_split_ptr = tile_split;
1957*7688df22SAndroid Build Coastguard Worker     }
1958*7688df22SAndroid Build Coastguard Worker     if (num_banks) {
1959*7688df22SAndroid Build Coastguard Worker         switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
1960*7688df22SAndroid Build Coastguard Worker         default:
1961*7688df22SAndroid Build Coastguard Worker         case CIK__NUM_BANKS__2_BANK:
1962*7688df22SAndroid Build Coastguard Worker             *num_banks = 2;
1963*7688df22SAndroid Build Coastguard Worker             break;
1964*7688df22SAndroid Build Coastguard Worker         case CIK__NUM_BANKS__4_BANK:
1965*7688df22SAndroid Build Coastguard Worker             *num_banks = 4;
1966*7688df22SAndroid Build Coastguard Worker             break;
1967*7688df22SAndroid Build Coastguard Worker         case CIK__NUM_BANKS__8_BANK:
1968*7688df22SAndroid Build Coastguard Worker             *num_banks = 8;
1969*7688df22SAndroid Build Coastguard Worker             break;
1970*7688df22SAndroid Build Coastguard Worker         case CIK__NUM_BANKS__16_BANK:
1971*7688df22SAndroid Build Coastguard Worker             *num_banks = 16;
1972*7688df22SAndroid Build Coastguard Worker             break;
1973*7688df22SAndroid Build Coastguard Worker         }
1974*7688df22SAndroid Build Coastguard Worker     }
1975*7688df22SAndroid Build Coastguard Worker     if (macro_tile_aspect) {
1976*7688df22SAndroid Build Coastguard Worker         switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
1977*7688df22SAndroid Build Coastguard Worker         default:
1978*7688df22SAndroid Build Coastguard Worker         case CIK__MACRO_TILE_ASPECT__1:
1979*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 1;
1980*7688df22SAndroid Build Coastguard Worker             break;
1981*7688df22SAndroid Build Coastguard Worker         case CIK__MACRO_TILE_ASPECT__2:
1982*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 2;
1983*7688df22SAndroid Build Coastguard Worker             break;
1984*7688df22SAndroid Build Coastguard Worker         case CIK__MACRO_TILE_ASPECT__4:
1985*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 4;
1986*7688df22SAndroid Build Coastguard Worker             break;
1987*7688df22SAndroid Build Coastguard Worker         case CIK__MACRO_TILE_ASPECT__8:
1988*7688df22SAndroid Build Coastguard Worker             *macro_tile_aspect = 8;
1989*7688df22SAndroid Build Coastguard Worker             break;
1990*7688df22SAndroid Build Coastguard Worker         }
1991*7688df22SAndroid Build Coastguard Worker     }
1992*7688df22SAndroid Build Coastguard Worker     if (bank_w) {
1993*7688df22SAndroid Build Coastguard Worker         switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
1994*7688df22SAndroid Build Coastguard Worker         default:
1995*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_WIDTH__1:
1996*7688df22SAndroid Build Coastguard Worker             *bank_w = 1;
1997*7688df22SAndroid Build Coastguard Worker             break;
1998*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_WIDTH__2:
1999*7688df22SAndroid Build Coastguard Worker             *bank_w = 2;
2000*7688df22SAndroid Build Coastguard Worker             break;
2001*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_WIDTH__4:
2002*7688df22SAndroid Build Coastguard Worker             *bank_w = 4;
2003*7688df22SAndroid Build Coastguard Worker             break;
2004*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_WIDTH__8:
2005*7688df22SAndroid Build Coastguard Worker             *bank_w = 8;
2006*7688df22SAndroid Build Coastguard Worker             break;
2007*7688df22SAndroid Build Coastguard Worker         }
2008*7688df22SAndroid Build Coastguard Worker     }
2009*7688df22SAndroid Build Coastguard Worker     if (bank_h) {
2010*7688df22SAndroid Build Coastguard Worker         switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
2011*7688df22SAndroid Build Coastguard Worker         default:
2012*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_HEIGHT__1:
2013*7688df22SAndroid Build Coastguard Worker             *bank_h = 1;
2014*7688df22SAndroid Build Coastguard Worker             break;
2015*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_HEIGHT__2:
2016*7688df22SAndroid Build Coastguard Worker             *bank_h = 2;
2017*7688df22SAndroid Build Coastguard Worker             break;
2018*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_HEIGHT__4:
2019*7688df22SAndroid Build Coastguard Worker             *bank_h = 4;
2020*7688df22SAndroid Build Coastguard Worker             break;
2021*7688df22SAndroid Build Coastguard Worker         case CIK__BANK_HEIGHT__8:
2022*7688df22SAndroid Build Coastguard Worker             *bank_h = 8;
2023*7688df22SAndroid Build Coastguard Worker             break;
2024*7688df22SAndroid Build Coastguard Worker         }
2025*7688df22SAndroid Build Coastguard Worker     }
2026*7688df22SAndroid Build Coastguard Worker }
2027*7688df22SAndroid Build Coastguard Worker 
cik_init_hw_info(struct radeon_surface_manager * surf_man)2028*7688df22SAndroid Build Coastguard Worker static int cik_init_hw_info(struct radeon_surface_manager *surf_man)
2029*7688df22SAndroid Build Coastguard Worker {
2030*7688df22SAndroid Build Coastguard Worker     uint32_t tiling_config;
2031*7688df22SAndroid Build Coastguard Worker     drmVersionPtr version;
2032*7688df22SAndroid Build Coastguard Worker     int r;
2033*7688df22SAndroid Build Coastguard Worker 
2034*7688df22SAndroid Build Coastguard Worker     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
2035*7688df22SAndroid Build Coastguard Worker                          &tiling_config);
2036*7688df22SAndroid Build Coastguard Worker     if (r) {
2037*7688df22SAndroid Build Coastguard Worker         return r;
2038*7688df22SAndroid Build Coastguard Worker     }
2039*7688df22SAndroid Build Coastguard Worker 
2040*7688df22SAndroid Build Coastguard Worker     surf_man->hw_info.allow_2d = 0;
2041*7688df22SAndroid Build Coastguard Worker     version = drmGetVersion(surf_man->fd);
2042*7688df22SAndroid Build Coastguard Worker     if (version && version->version_minor >= 35) {
2043*7688df22SAndroid Build Coastguard Worker         if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
2044*7688df22SAndroid Build Coastguard Worker 	    !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) {
2045*7688df22SAndroid Build Coastguard Worker             surf_man->hw_info.allow_2d = 1;
2046*7688df22SAndroid Build Coastguard Worker         }
2047*7688df22SAndroid Build Coastguard Worker     }
2048*7688df22SAndroid Build Coastguard Worker     drmFreeVersion(version);
2049*7688df22SAndroid Build Coastguard Worker 
2050*7688df22SAndroid Build Coastguard Worker     switch (tiling_config & 0xf) {
2051*7688df22SAndroid Build Coastguard Worker     case 0:
2052*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 1;
2053*7688df22SAndroid Build Coastguard Worker         break;
2054*7688df22SAndroid Build Coastguard Worker     case 1:
2055*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 2;
2056*7688df22SAndroid Build Coastguard Worker         break;
2057*7688df22SAndroid Build Coastguard Worker     case 2:
2058*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 4;
2059*7688df22SAndroid Build Coastguard Worker         break;
2060*7688df22SAndroid Build Coastguard Worker     case 3:
2061*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
2062*7688df22SAndroid Build Coastguard Worker         break;
2063*7688df22SAndroid Build Coastguard Worker     default:
2064*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_pipes = 8;
2065*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
2066*7688df22SAndroid Build Coastguard Worker         break;
2067*7688df22SAndroid Build Coastguard Worker     }
2068*7688df22SAndroid Build Coastguard Worker 
2069*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf0) >> 4) {
2070*7688df22SAndroid Build Coastguard Worker     case 0:
2071*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 4;
2072*7688df22SAndroid Build Coastguard Worker         break;
2073*7688df22SAndroid Build Coastguard Worker     case 1:
2074*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
2075*7688df22SAndroid Build Coastguard Worker         break;
2076*7688df22SAndroid Build Coastguard Worker     case 2:
2077*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 16;
2078*7688df22SAndroid Build Coastguard Worker         break;
2079*7688df22SAndroid Build Coastguard Worker     default:
2080*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.num_banks = 8;
2081*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
2082*7688df22SAndroid Build Coastguard Worker         break;
2083*7688df22SAndroid Build Coastguard Worker     }
2084*7688df22SAndroid Build Coastguard Worker 
2085*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf00) >> 8) {
2086*7688df22SAndroid Build Coastguard Worker     case 0:
2087*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
2088*7688df22SAndroid Build Coastguard Worker         break;
2089*7688df22SAndroid Build Coastguard Worker     case 1:
2090*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 512;
2091*7688df22SAndroid Build Coastguard Worker         break;
2092*7688df22SAndroid Build Coastguard Worker     default:
2093*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.group_bytes = 256;
2094*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
2095*7688df22SAndroid Build Coastguard Worker         break;
2096*7688df22SAndroid Build Coastguard Worker     }
2097*7688df22SAndroid Build Coastguard Worker 
2098*7688df22SAndroid Build Coastguard Worker     switch ((tiling_config & 0xf000) >> 12) {
2099*7688df22SAndroid Build Coastguard Worker     case 0:
2100*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 1024;
2101*7688df22SAndroid Build Coastguard Worker         break;
2102*7688df22SAndroid Build Coastguard Worker     case 1:
2103*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 2048;
2104*7688df22SAndroid Build Coastguard Worker         break;
2105*7688df22SAndroid Build Coastguard Worker     case 2:
2106*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 4096;
2107*7688df22SAndroid Build Coastguard Worker         break;
2108*7688df22SAndroid Build Coastguard Worker     default:
2109*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.row_size = 4096;
2110*7688df22SAndroid Build Coastguard Worker         surf_man->hw_info.allow_2d = 0;
2111*7688df22SAndroid Build Coastguard Worker         break;
2112*7688df22SAndroid Build Coastguard Worker     }
2113*7688df22SAndroid Build Coastguard Worker     return 0;
2114*7688df22SAndroid Build Coastguard Worker }
2115*7688df22SAndroid Build Coastguard Worker 
cik_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode,unsigned * tile_mode,unsigned * stencil_tile_mode)2116*7688df22SAndroid Build Coastguard Worker static int cik_surface_sanity(struct radeon_surface_manager *surf_man,
2117*7688df22SAndroid Build Coastguard Worker                               struct radeon_surface *surf,
2118*7688df22SAndroid Build Coastguard Worker                               unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
2119*7688df22SAndroid Build Coastguard Worker {
2120*7688df22SAndroid Build Coastguard Worker     /* check surface dimension */
2121*7688df22SAndroid Build Coastguard Worker     if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
2122*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2123*7688df22SAndroid Build Coastguard Worker     }
2124*7688df22SAndroid Build Coastguard Worker 
2125*7688df22SAndroid Build Coastguard Worker     /* check mipmap last_level */
2126*7688df22SAndroid Build Coastguard Worker     if (surf->last_level > 15) {
2127*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2128*7688df22SAndroid Build Coastguard Worker     }
2129*7688df22SAndroid Build Coastguard Worker 
2130*7688df22SAndroid Build Coastguard Worker     /* force 1d on kernel that can't do 2d */
2131*7688df22SAndroid Build Coastguard Worker     if (mode > RADEON_SURF_MODE_1D &&
2132*7688df22SAndroid Build Coastguard Worker         (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
2133*7688df22SAndroid Build Coastguard Worker         if (surf->nsamples > 1) {
2134*7688df22SAndroid Build Coastguard Worker             fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
2135*7688df22SAndroid Build Coastguard Worker             return -EFAULT;
2136*7688df22SAndroid Build Coastguard Worker         }
2137*7688df22SAndroid Build Coastguard Worker         mode = RADEON_SURF_MODE_1D;
2138*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2139*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(mode, MODE);
2140*7688df22SAndroid Build Coastguard Worker     }
2141*7688df22SAndroid Build Coastguard Worker 
2142*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
2143*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2144*7688df22SAndroid Build Coastguard Worker     }
2145*7688df22SAndroid Build Coastguard Worker 
2146*7688df22SAndroid Build Coastguard Worker     if (!surf->tile_split) {
2147*7688df22SAndroid Build Coastguard Worker         /* default value */
2148*7688df22SAndroid Build Coastguard Worker         surf->mtilea = 1;
2149*7688df22SAndroid Build Coastguard Worker         surf->bankw = 1;
2150*7688df22SAndroid Build Coastguard Worker         surf->bankh = 1;
2151*7688df22SAndroid Build Coastguard Worker         surf->tile_split = 64;
2152*7688df22SAndroid Build Coastguard Worker         surf->stencil_tile_split = 64;
2153*7688df22SAndroid Build Coastguard Worker     }
2154*7688df22SAndroid Build Coastguard Worker 
2155*7688df22SAndroid Build Coastguard Worker     switch (mode) {
2156*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_2D: {
2157*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) {
2158*7688df22SAndroid Build Coastguard Worker             switch (surf->nsamples) {
2159*7688df22SAndroid Build Coastguard Worker             case 1:
2160*7688df22SAndroid Build Coastguard Worker                 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
2161*7688df22SAndroid Build Coastguard Worker                 break;
2162*7688df22SAndroid Build Coastguard Worker             case 2:
2163*7688df22SAndroid Build Coastguard Worker             case 4:
2164*7688df22SAndroid Build Coastguard Worker                 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
2165*7688df22SAndroid Build Coastguard Worker                 break;
2166*7688df22SAndroid Build Coastguard Worker             case 8:
2167*7688df22SAndroid Build Coastguard Worker                 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
2168*7688df22SAndroid Build Coastguard Worker                 break;
2169*7688df22SAndroid Build Coastguard Worker             default:
2170*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
2171*7688df22SAndroid Build Coastguard Worker             }
2172*7688df22SAndroid Build Coastguard Worker 
2173*7688df22SAndroid Build Coastguard Worker             if (surf->flags & RADEON_SURF_SBUFFER) {
2174*7688df22SAndroid Build Coastguard Worker                 *stencil_tile_mode = *tile_mode;
2175*7688df22SAndroid Build Coastguard Worker 
2176*7688df22SAndroid Build Coastguard Worker                 cik_get_2d_params(surf_man, 1, surf->nsamples, false,
2177*7688df22SAndroid Build Coastguard Worker                                   *stencil_tile_mode, NULL,
2178*7688df22SAndroid Build Coastguard Worker                                   &surf->stencil_tile_split,
2179*7688df22SAndroid Build Coastguard Worker                                   NULL, NULL, NULL, NULL);
2180*7688df22SAndroid Build Coastguard Worker             }
2181*7688df22SAndroid Build Coastguard Worker         } else if (surf->flags & RADEON_SURF_SCANOUT) {
2182*7688df22SAndroid Build Coastguard Worker             *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
2183*7688df22SAndroid Build Coastguard Worker         } else {
2184*7688df22SAndroid Build Coastguard Worker             *tile_mode = CIK_TILE_MODE_COLOR_2D;
2185*7688df22SAndroid Build Coastguard Worker         }
2186*7688df22SAndroid Build Coastguard Worker 
2187*7688df22SAndroid Build Coastguard Worker         /* retrieve tiling mode values */
2188*7688df22SAndroid Build Coastguard Worker         cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2189*7688df22SAndroid Build Coastguard Worker                           !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
2190*7688df22SAndroid Build Coastguard Worker                           NULL, &surf->tile_split, NULL, &surf->mtilea,
2191*7688df22SAndroid Build Coastguard Worker                           &surf->bankw, &surf->bankh);
2192*7688df22SAndroid Build Coastguard Worker         break;
2193*7688df22SAndroid Build Coastguard Worker     }
2194*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_1D:
2195*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_SBUFFER) {
2196*7688df22SAndroid Build Coastguard Worker             *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2197*7688df22SAndroid Build Coastguard Worker         }
2198*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_ZBUFFER) {
2199*7688df22SAndroid Build Coastguard Worker             *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2200*7688df22SAndroid Build Coastguard Worker         } else if (surf->flags & RADEON_SURF_SCANOUT) {
2201*7688df22SAndroid Build Coastguard Worker             *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2202*7688df22SAndroid Build Coastguard Worker         } else {
2203*7688df22SAndroid Build Coastguard Worker             *tile_mode = SI_TILE_MODE_COLOR_1D;
2204*7688df22SAndroid Build Coastguard Worker         }
2205*7688df22SAndroid Build Coastguard Worker         break;
2206*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR_ALIGNED:
2207*7688df22SAndroid Build Coastguard Worker     default:
2208*7688df22SAndroid Build Coastguard Worker         *stencil_tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
2209*7688df22SAndroid Build Coastguard Worker         *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
2210*7688df22SAndroid Build Coastguard Worker     }
2211*7688df22SAndroid Build Coastguard Worker 
2212*7688df22SAndroid Build Coastguard Worker     return 0;
2213*7688df22SAndroid Build Coastguard Worker }
2214*7688df22SAndroid Build Coastguard Worker 
cik_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,unsigned tile_split,unsigned num_pipes,unsigned num_banks,uint64_t offset,unsigned start_level)2215*7688df22SAndroid Build Coastguard Worker static int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
2216*7688df22SAndroid Build Coastguard Worker                                struct radeon_surface *surf,
2217*7688df22SAndroid Build Coastguard Worker                                struct radeon_surface_level *level,
2218*7688df22SAndroid Build Coastguard Worker                                unsigned bpe, unsigned tile_mode,
2219*7688df22SAndroid Build Coastguard Worker                                unsigned tile_split,
2220*7688df22SAndroid Build Coastguard Worker                                unsigned num_pipes, unsigned num_banks,
2221*7688df22SAndroid Build Coastguard Worker                                uint64_t offset,
2222*7688df22SAndroid Build Coastguard Worker                                unsigned start_level)
2223*7688df22SAndroid Build Coastguard Worker {
2224*7688df22SAndroid Build Coastguard Worker     uint64_t aligned_offset = offset;
2225*7688df22SAndroid Build Coastguard Worker     unsigned tilew, tileh, tileb_1x, tileb;
2226*7688df22SAndroid Build Coastguard Worker     unsigned mtilew, mtileh, mtileb;
2227*7688df22SAndroid Build Coastguard Worker     unsigned slice_pt;
2228*7688df22SAndroid Build Coastguard Worker     unsigned i;
2229*7688df22SAndroid Build Coastguard Worker 
2230*7688df22SAndroid Build Coastguard Worker     /* compute tile values */
2231*7688df22SAndroid Build Coastguard Worker     tilew = 8;
2232*7688df22SAndroid Build Coastguard Worker     tileh = 8;
2233*7688df22SAndroid Build Coastguard Worker     tileb_1x = tilew * tileh * bpe;
2234*7688df22SAndroid Build Coastguard Worker 
2235*7688df22SAndroid Build Coastguard Worker     tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
2236*7688df22SAndroid Build Coastguard Worker 
2237*7688df22SAndroid Build Coastguard Worker     tileb = surf->nsamples * tileb_1x;
2238*7688df22SAndroid Build Coastguard Worker 
2239*7688df22SAndroid Build Coastguard Worker     /* slices per tile */
2240*7688df22SAndroid Build Coastguard Worker     slice_pt = 1;
2241*7688df22SAndroid Build Coastguard Worker     if (tileb > tile_split && tile_split) {
2242*7688df22SAndroid Build Coastguard Worker         slice_pt = tileb / tile_split;
2243*7688df22SAndroid Build Coastguard Worker         tileb = tileb / slice_pt;
2244*7688df22SAndroid Build Coastguard Worker     }
2245*7688df22SAndroid Build Coastguard Worker 
2246*7688df22SAndroid Build Coastguard Worker     /* macro tile width & height */
2247*7688df22SAndroid Build Coastguard Worker     mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
2248*7688df22SAndroid Build Coastguard Worker     mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
2249*7688df22SAndroid Build Coastguard Worker 
2250*7688df22SAndroid Build Coastguard Worker     /* macro tile bytes */
2251*7688df22SAndroid Build Coastguard Worker     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
2252*7688df22SAndroid Build Coastguard Worker 
2253*7688df22SAndroid Build Coastguard Worker     if (start_level <= 1) {
2254*7688df22SAndroid Build Coastguard Worker         unsigned alignment = MAX2(256, mtileb);
2255*7688df22SAndroid Build Coastguard Worker         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
2256*7688df22SAndroid Build Coastguard Worker 
2257*7688df22SAndroid Build Coastguard Worker         if (aligned_offset) {
2258*7688df22SAndroid Build Coastguard Worker             aligned_offset = ALIGN(aligned_offset, alignment);
2259*7688df22SAndroid Build Coastguard Worker         }
2260*7688df22SAndroid Build Coastguard Worker     }
2261*7688df22SAndroid Build Coastguard Worker 
2262*7688df22SAndroid Build Coastguard Worker     /* build mipmap tree */
2263*7688df22SAndroid Build Coastguard Worker     for (i = start_level; i <= surf->last_level; i++) {
2264*7688df22SAndroid Build Coastguard Worker         level[i].mode = RADEON_SURF_MODE_2D;
2265*7688df22SAndroid Build Coastguard Worker         si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
2266*7688df22SAndroid Build Coastguard Worker         if (level[i].mode == RADEON_SURF_MODE_1D) {
2267*7688df22SAndroid Build Coastguard Worker             switch (tile_mode) {
2268*7688df22SAndroid Build Coastguard Worker             case CIK_TILE_MODE_COLOR_2D:
2269*7688df22SAndroid Build Coastguard Worker                 tile_mode = SI_TILE_MODE_COLOR_1D;
2270*7688df22SAndroid Build Coastguard Worker                 break;
2271*7688df22SAndroid Build Coastguard Worker             case CIK_TILE_MODE_COLOR_2D_SCANOUT:
2272*7688df22SAndroid Build Coastguard Worker                 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2273*7688df22SAndroid Build Coastguard Worker                 break;
2274*7688df22SAndroid Build Coastguard Worker             case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
2275*7688df22SAndroid Build Coastguard Worker             case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
2276*7688df22SAndroid Build Coastguard Worker             case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
2277*7688df22SAndroid Build Coastguard Worker             case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
2278*7688df22SAndroid Build Coastguard Worker             case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
2279*7688df22SAndroid Build Coastguard Worker                 tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2280*7688df22SAndroid Build Coastguard Worker                 break;
2281*7688df22SAndroid Build Coastguard Worker             default:
2282*7688df22SAndroid Build Coastguard Worker                 return -EINVAL;
2283*7688df22SAndroid Build Coastguard Worker             }
2284*7688df22SAndroid Build Coastguard Worker             return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
2285*7688df22SAndroid Build Coastguard Worker         }
2286*7688df22SAndroid Build Coastguard Worker         /* level0 and first mipmap need to have alignment */
2287*7688df22SAndroid Build Coastguard Worker         aligned_offset = offset = surf->bo_size;
2288*7688df22SAndroid Build Coastguard Worker         if (i == 0) {
2289*7688df22SAndroid Build Coastguard Worker             aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
2290*7688df22SAndroid Build Coastguard Worker         }
2291*7688df22SAndroid Build Coastguard Worker         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
2292*7688df22SAndroid Build Coastguard Worker             if (surf->level == level) {
2293*7688df22SAndroid Build Coastguard Worker                 surf->tiling_index[i] = tile_mode;
2294*7688df22SAndroid Build Coastguard Worker                 /* it's ok because stencil is done after */
2295*7688df22SAndroid Build Coastguard Worker                 surf->stencil_tiling_index[i] = tile_mode;
2296*7688df22SAndroid Build Coastguard Worker             } else {
2297*7688df22SAndroid Build Coastguard Worker                 surf->stencil_tiling_index[i] = tile_mode;
2298*7688df22SAndroid Build Coastguard Worker             }
2299*7688df22SAndroid Build Coastguard Worker         }
2300*7688df22SAndroid Build Coastguard Worker     }
2301*7688df22SAndroid Build Coastguard Worker     return 0;
2302*7688df22SAndroid Build Coastguard Worker }
2303*7688df22SAndroid Build Coastguard Worker 
cik_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)2304*7688df22SAndroid Build Coastguard Worker static int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
2305*7688df22SAndroid Build Coastguard Worker                                         struct radeon_surface *surf,
2306*7688df22SAndroid Build Coastguard Worker                                         unsigned tile_mode, unsigned stencil_tile_mode)
2307*7688df22SAndroid Build Coastguard Worker {
2308*7688df22SAndroid Build Coastguard Worker     int r;
2309*7688df22SAndroid Build Coastguard Worker     uint32_t num_pipes, num_banks;
2310*7688df22SAndroid Build Coastguard Worker 
2311*7688df22SAndroid Build Coastguard Worker     cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2312*7688df22SAndroid Build Coastguard Worker                         !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
2313*7688df22SAndroid Build Coastguard Worker                         &num_pipes, NULL, &num_banks, NULL, NULL, NULL);
2314*7688df22SAndroid Build Coastguard Worker 
2315*7688df22SAndroid Build Coastguard Worker     r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
2316*7688df22SAndroid Build Coastguard Worker                             surf->tile_split, num_pipes, num_banks, 0, 0);
2317*7688df22SAndroid Build Coastguard Worker     if (r) {
2318*7688df22SAndroid Build Coastguard Worker         return r;
2319*7688df22SAndroid Build Coastguard Worker     }
2320*7688df22SAndroid Build Coastguard Worker 
2321*7688df22SAndroid Build Coastguard Worker     if (surf->flags & RADEON_SURF_SBUFFER) {
2322*7688df22SAndroid Build Coastguard Worker         r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
2323*7688df22SAndroid Build Coastguard Worker                                 surf->stencil_tile_split, num_pipes, num_banks,
2324*7688df22SAndroid Build Coastguard Worker                                 surf->bo_size, 0);
2325*7688df22SAndroid Build Coastguard Worker         surf->stencil_offset = surf->stencil_level[0].offset;
2326*7688df22SAndroid Build Coastguard Worker     }
2327*7688df22SAndroid Build Coastguard Worker     return r;
2328*7688df22SAndroid Build Coastguard Worker }
2329*7688df22SAndroid Build Coastguard Worker 
cik_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2330*7688df22SAndroid Build Coastguard Worker static int cik_surface_init(struct radeon_surface_manager *surf_man,
2331*7688df22SAndroid Build Coastguard Worker                             struct radeon_surface *surf)
2332*7688df22SAndroid Build Coastguard Worker {
2333*7688df22SAndroid Build Coastguard Worker     unsigned mode, tile_mode, stencil_tile_mode;
2334*7688df22SAndroid Build Coastguard Worker     int r;
2335*7688df22SAndroid Build Coastguard Worker 
2336*7688df22SAndroid Build Coastguard Worker     /* MSAA surfaces support the 2D mode only. */
2337*7688df22SAndroid Build Coastguard Worker     if (surf->nsamples > 1) {
2338*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2339*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2340*7688df22SAndroid Build Coastguard Worker     }
2341*7688df22SAndroid Build Coastguard Worker 
2342*7688df22SAndroid Build Coastguard Worker     /* tiling mode */
2343*7688df22SAndroid Build Coastguard Worker     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2344*7688df22SAndroid Build Coastguard Worker 
2345*7688df22SAndroid Build Coastguard Worker     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
2346*7688df22SAndroid Build Coastguard Worker         /* zbuffer only support 1D or 2D tiled surface */
2347*7688df22SAndroid Build Coastguard Worker         switch (mode) {
2348*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_1D:
2349*7688df22SAndroid Build Coastguard Worker         case RADEON_SURF_MODE_2D:
2350*7688df22SAndroid Build Coastguard Worker             break;
2351*7688df22SAndroid Build Coastguard Worker         default:
2352*7688df22SAndroid Build Coastguard Worker             mode = RADEON_SURF_MODE_1D;
2353*7688df22SAndroid Build Coastguard Worker             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2354*7688df22SAndroid Build Coastguard Worker             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2355*7688df22SAndroid Build Coastguard Worker             break;
2356*7688df22SAndroid Build Coastguard Worker         }
2357*7688df22SAndroid Build Coastguard Worker     }
2358*7688df22SAndroid Build Coastguard Worker 
2359*7688df22SAndroid Build Coastguard Worker     r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2360*7688df22SAndroid Build Coastguard Worker     if (r) {
2361*7688df22SAndroid Build Coastguard Worker         return r;
2362*7688df22SAndroid Build Coastguard Worker     }
2363*7688df22SAndroid Build Coastguard Worker 
2364*7688df22SAndroid Build Coastguard Worker     surf->stencil_offset = 0;
2365*7688df22SAndroid Build Coastguard Worker     surf->bo_alignment = 0;
2366*7688df22SAndroid Build Coastguard Worker 
2367*7688df22SAndroid Build Coastguard Worker     /* check tiling mode */
2368*7688df22SAndroid Build Coastguard Worker     switch (mode) {
2369*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR:
2370*7688df22SAndroid Build Coastguard Worker         r = r6_surface_init_linear(surf_man, surf, 0, 0);
2371*7688df22SAndroid Build Coastguard Worker         break;
2372*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_LINEAR_ALIGNED:
2373*7688df22SAndroid Build Coastguard Worker         r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
2374*7688df22SAndroid Build Coastguard Worker         break;
2375*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_1D:
2376*7688df22SAndroid Build Coastguard Worker         r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2377*7688df22SAndroid Build Coastguard Worker         break;
2378*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_MODE_2D:
2379*7688df22SAndroid Build Coastguard Worker         r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2380*7688df22SAndroid Build Coastguard Worker         break;
2381*7688df22SAndroid Build Coastguard Worker     default:
2382*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2383*7688df22SAndroid Build Coastguard Worker     }
2384*7688df22SAndroid Build Coastguard Worker     return r;
2385*7688df22SAndroid Build Coastguard Worker }
2386*7688df22SAndroid Build Coastguard Worker 
2387*7688df22SAndroid Build Coastguard Worker /*
2388*7688df22SAndroid Build Coastguard Worker  * depending on surface
2389*7688df22SAndroid Build Coastguard Worker  */
cik_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2390*7688df22SAndroid Build Coastguard Worker static int cik_surface_best(struct radeon_surface_manager *surf_man,
2391*7688df22SAndroid Build Coastguard Worker                             struct radeon_surface *surf)
2392*7688df22SAndroid Build Coastguard Worker {
2393*7688df22SAndroid Build Coastguard Worker     unsigned mode, tile_mode, stencil_tile_mode;
2394*7688df22SAndroid Build Coastguard Worker 
2395*7688df22SAndroid Build Coastguard Worker     /* tiling mode */
2396*7688df22SAndroid Build Coastguard Worker     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2397*7688df22SAndroid Build Coastguard Worker 
2398*7688df22SAndroid Build Coastguard Worker     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
2399*7688df22SAndroid Build Coastguard Worker         !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
2400*7688df22SAndroid Build Coastguard Worker         /* depth/stencil force 1d tiling for old mesa */
2401*7688df22SAndroid Build Coastguard Worker         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2402*7688df22SAndroid Build Coastguard Worker         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2403*7688df22SAndroid Build Coastguard Worker     }
2404*7688df22SAndroid Build Coastguard Worker 
2405*7688df22SAndroid Build Coastguard Worker     return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2406*7688df22SAndroid Build Coastguard Worker }
2407*7688df22SAndroid Build Coastguard Worker 
2408*7688df22SAndroid Build Coastguard Worker 
2409*7688df22SAndroid Build Coastguard Worker /* ===========================================================================
2410*7688df22SAndroid Build Coastguard Worker  * public API
2411*7688df22SAndroid Build Coastguard Worker  */
2412*7688df22SAndroid Build Coastguard Worker drm_public struct radeon_surface_manager *
radeon_surface_manager_new(int fd)2413*7688df22SAndroid Build Coastguard Worker radeon_surface_manager_new(int fd)
2414*7688df22SAndroid Build Coastguard Worker {
2415*7688df22SAndroid Build Coastguard Worker     struct radeon_surface_manager *surf_man;
2416*7688df22SAndroid Build Coastguard Worker 
2417*7688df22SAndroid Build Coastguard Worker     surf_man = calloc(1, sizeof(struct radeon_surface_manager));
2418*7688df22SAndroid Build Coastguard Worker     if (surf_man == NULL) {
2419*7688df22SAndroid Build Coastguard Worker         return NULL;
2420*7688df22SAndroid Build Coastguard Worker     }
2421*7688df22SAndroid Build Coastguard Worker     surf_man->fd = fd;
2422*7688df22SAndroid Build Coastguard Worker     if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
2423*7688df22SAndroid Build Coastguard Worker         goto out_err;
2424*7688df22SAndroid Build Coastguard Worker     }
2425*7688df22SAndroid Build Coastguard Worker     if (radeon_get_family(surf_man)) {
2426*7688df22SAndroid Build Coastguard Worker         goto out_err;
2427*7688df22SAndroid Build Coastguard Worker     }
2428*7688df22SAndroid Build Coastguard Worker 
2429*7688df22SAndroid Build Coastguard Worker     if (surf_man->family <= CHIP_RV740) {
2430*7688df22SAndroid Build Coastguard Worker         if (r6_init_hw_info(surf_man)) {
2431*7688df22SAndroid Build Coastguard Worker             goto out_err;
2432*7688df22SAndroid Build Coastguard Worker         }
2433*7688df22SAndroid Build Coastguard Worker         surf_man->surface_init = &r6_surface_init;
2434*7688df22SAndroid Build Coastguard Worker         surf_man->surface_best = &r6_surface_best;
2435*7688df22SAndroid Build Coastguard Worker     } else if (surf_man->family <= CHIP_ARUBA) {
2436*7688df22SAndroid Build Coastguard Worker         if (eg_init_hw_info(surf_man)) {
2437*7688df22SAndroid Build Coastguard Worker             goto out_err;
2438*7688df22SAndroid Build Coastguard Worker         }
2439*7688df22SAndroid Build Coastguard Worker         surf_man->surface_init = &eg_surface_init;
2440*7688df22SAndroid Build Coastguard Worker         surf_man->surface_best = &eg_surface_best;
2441*7688df22SAndroid Build Coastguard Worker     } else if (surf_man->family < CHIP_BONAIRE) {
2442*7688df22SAndroid Build Coastguard Worker         if (si_init_hw_info(surf_man)) {
2443*7688df22SAndroid Build Coastguard Worker             goto out_err;
2444*7688df22SAndroid Build Coastguard Worker         }
2445*7688df22SAndroid Build Coastguard Worker         surf_man->surface_init = &si_surface_init;
2446*7688df22SAndroid Build Coastguard Worker         surf_man->surface_best = &si_surface_best;
2447*7688df22SAndroid Build Coastguard Worker     } else {
2448*7688df22SAndroid Build Coastguard Worker         if (cik_init_hw_info(surf_man)) {
2449*7688df22SAndroid Build Coastguard Worker             goto out_err;
2450*7688df22SAndroid Build Coastguard Worker         }
2451*7688df22SAndroid Build Coastguard Worker         surf_man->surface_init = &cik_surface_init;
2452*7688df22SAndroid Build Coastguard Worker         surf_man->surface_best = &cik_surface_best;
2453*7688df22SAndroid Build Coastguard Worker     }
2454*7688df22SAndroid Build Coastguard Worker 
2455*7688df22SAndroid Build Coastguard Worker     return surf_man;
2456*7688df22SAndroid Build Coastguard Worker out_err:
2457*7688df22SAndroid Build Coastguard Worker     free(surf_man);
2458*7688df22SAndroid Build Coastguard Worker     return NULL;
2459*7688df22SAndroid Build Coastguard Worker }
2460*7688df22SAndroid Build Coastguard Worker 
2461*7688df22SAndroid Build Coastguard Worker drm_public void
radeon_surface_manager_free(struct radeon_surface_manager * surf_man)2462*7688df22SAndroid Build Coastguard Worker radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
2463*7688df22SAndroid Build Coastguard Worker {
2464*7688df22SAndroid Build Coastguard Worker     free(surf_man);
2465*7688df22SAndroid Build Coastguard Worker }
2466*7688df22SAndroid Build Coastguard Worker 
radeon_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned type,unsigned mode)2467*7688df22SAndroid Build Coastguard Worker static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
2468*7688df22SAndroid Build Coastguard Worker                                  struct radeon_surface *surf,
2469*7688df22SAndroid Build Coastguard Worker                                  unsigned type,
2470*7688df22SAndroid Build Coastguard Worker                                  unsigned mode)
2471*7688df22SAndroid Build Coastguard Worker {
2472*7688df22SAndroid Build Coastguard Worker     if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
2473*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2474*7688df22SAndroid Build Coastguard Worker     }
2475*7688df22SAndroid Build Coastguard Worker 
2476*7688df22SAndroid Build Coastguard Worker     /* all dimension must be at least 1 ! */
2477*7688df22SAndroid Build Coastguard Worker     if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
2478*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2479*7688df22SAndroid Build Coastguard Worker     }
2480*7688df22SAndroid Build Coastguard Worker     if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
2481*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2482*7688df22SAndroid Build Coastguard Worker     }
2483*7688df22SAndroid Build Coastguard Worker     if (!surf->array_size) {
2484*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2485*7688df22SAndroid Build Coastguard Worker     }
2486*7688df22SAndroid Build Coastguard Worker     /* array size must be a power of 2 */
2487*7688df22SAndroid Build Coastguard Worker     surf->array_size = next_power_of_two(surf->array_size);
2488*7688df22SAndroid Build Coastguard Worker 
2489*7688df22SAndroid Build Coastguard Worker     switch (surf->nsamples) {
2490*7688df22SAndroid Build Coastguard Worker     case 1:
2491*7688df22SAndroid Build Coastguard Worker     case 2:
2492*7688df22SAndroid Build Coastguard Worker     case 4:
2493*7688df22SAndroid Build Coastguard Worker     case 8:
2494*7688df22SAndroid Build Coastguard Worker         break;
2495*7688df22SAndroid Build Coastguard Worker     default:
2496*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2497*7688df22SAndroid Build Coastguard Worker     }
2498*7688df22SAndroid Build Coastguard Worker     /* check type */
2499*7688df22SAndroid Build Coastguard Worker     switch (type) {
2500*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_TYPE_1D:
2501*7688df22SAndroid Build Coastguard Worker         if (surf->npix_y > 1) {
2502*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
2503*7688df22SAndroid Build Coastguard Worker         }
2504*7688df22SAndroid Build Coastguard Worker         /* fallthrough */
2505*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_TYPE_2D:
2506*7688df22SAndroid Build Coastguard Worker         if (surf->npix_z > 1) {
2507*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
2508*7688df22SAndroid Build Coastguard Worker         }
2509*7688df22SAndroid Build Coastguard Worker         break;
2510*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_TYPE_CUBEMAP:
2511*7688df22SAndroid Build Coastguard Worker         if (surf->npix_z > 1) {
2512*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
2513*7688df22SAndroid Build Coastguard Worker         }
2514*7688df22SAndroid Build Coastguard Worker         /* deal with cubemap as they were texture array */
2515*7688df22SAndroid Build Coastguard Worker         if (surf_man->family >= CHIP_RV770) {
2516*7688df22SAndroid Build Coastguard Worker             surf->array_size = 8;
2517*7688df22SAndroid Build Coastguard Worker         } else {
2518*7688df22SAndroid Build Coastguard Worker             surf->array_size = 6;
2519*7688df22SAndroid Build Coastguard Worker         }
2520*7688df22SAndroid Build Coastguard Worker         break;
2521*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_TYPE_3D:
2522*7688df22SAndroid Build Coastguard Worker         break;
2523*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_TYPE_1D_ARRAY:
2524*7688df22SAndroid Build Coastguard Worker         if (surf->npix_y > 1) {
2525*7688df22SAndroid Build Coastguard Worker             return -EINVAL;
2526*7688df22SAndroid Build Coastguard Worker         }
2527*7688df22SAndroid Build Coastguard Worker     case RADEON_SURF_TYPE_2D_ARRAY:
2528*7688df22SAndroid Build Coastguard Worker         break;
2529*7688df22SAndroid Build Coastguard Worker     default:
2530*7688df22SAndroid Build Coastguard Worker         return -EINVAL;
2531*7688df22SAndroid Build Coastguard Worker     }
2532*7688df22SAndroid Build Coastguard Worker     return 0;
2533*7688df22SAndroid Build Coastguard Worker }
2534*7688df22SAndroid Build Coastguard Worker 
2535*7688df22SAndroid Build Coastguard Worker drm_public int
radeon_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2536*7688df22SAndroid Build Coastguard Worker radeon_surface_init(struct radeon_surface_manager *surf_man,
2537*7688df22SAndroid Build Coastguard Worker                     struct radeon_surface *surf)
2538*7688df22SAndroid Build Coastguard Worker {
2539*7688df22SAndroid Build Coastguard Worker     unsigned mode, type;
2540*7688df22SAndroid Build Coastguard Worker     int r;
2541*7688df22SAndroid Build Coastguard Worker 
2542*7688df22SAndroid Build Coastguard Worker     type = RADEON_SURF_GET(surf->flags, TYPE);
2543*7688df22SAndroid Build Coastguard Worker     mode = RADEON_SURF_GET(surf->flags, MODE);
2544*7688df22SAndroid Build Coastguard Worker 
2545*7688df22SAndroid Build Coastguard Worker     r = radeon_surface_sanity(surf_man, surf, type, mode);
2546*7688df22SAndroid Build Coastguard Worker     if (r) {
2547*7688df22SAndroid Build Coastguard Worker         return r;
2548*7688df22SAndroid Build Coastguard Worker     }
2549*7688df22SAndroid Build Coastguard Worker     return surf_man->surface_init(surf_man, surf);
2550*7688df22SAndroid Build Coastguard Worker }
2551*7688df22SAndroid Build Coastguard Worker 
2552*7688df22SAndroid Build Coastguard Worker drm_public int
radeon_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2553*7688df22SAndroid Build Coastguard Worker radeon_surface_best(struct radeon_surface_manager *surf_man,
2554*7688df22SAndroid Build Coastguard Worker                     struct radeon_surface *surf)
2555*7688df22SAndroid Build Coastguard Worker {
2556*7688df22SAndroid Build Coastguard Worker     unsigned mode, type;
2557*7688df22SAndroid Build Coastguard Worker     int r;
2558*7688df22SAndroid Build Coastguard Worker 
2559*7688df22SAndroid Build Coastguard Worker     type = RADEON_SURF_GET(surf->flags, TYPE);
2560*7688df22SAndroid Build Coastguard Worker     mode = RADEON_SURF_GET(surf->flags, MODE);
2561*7688df22SAndroid Build Coastguard Worker 
2562*7688df22SAndroid Build Coastguard Worker     r = radeon_surface_sanity(surf_man, surf, type, mode);
2563*7688df22SAndroid Build Coastguard Worker     if (r) {
2564*7688df22SAndroid Build Coastguard Worker         return r;
2565*7688df22SAndroid Build Coastguard Worker     }
2566*7688df22SAndroid Build Coastguard Worker     return surf_man->surface_best(surf_man, surf);
2567*7688df22SAndroid Build Coastguard Worker }
2568