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