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