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