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