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