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