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