update libdrm to 2.4.51

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

update libdrm to 2.4.51

Jonathan Gray-11
Update libdrm to 2.4.51.  Needs the previous drm
header diff.  Most of the changes concern hardware
we don't support (Intel hardware not publically available
and the latest radeons) but tests welcome.

Index: Makefile.inc
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/Makefile.inc,v
retrieving revision 1.8
diff -u -p -r1.8 Makefile.inc
--- Makefile.inc 21 Nov 2013 13:30:07 -0000 1.8
+++ Makefile.inc 11 Jan 2014 09:23:58 -0000
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile.inc,v 1.8 2013/11/21 13:30:07 kettenis Exp $
 
-PACKAGE_VERSION= 2.4.47
+PACKAGE_VERSION= 2.4.51
 
 NOPROFILE=
 
Index: xf86drmMode.h
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/xf86drmMode.h,v
retrieving revision 1.6
diff -u -p -r1.6 xf86drmMode.h
--- xf86drmMode.h 21 Nov 2013 13:30:07 -0000 1.6
+++ xf86drmMode.h 11 Jan 2014 09:21:42 -0000
@@ -128,6 +128,8 @@ extern "C" {
 #define DRM_MODE_ENCODER_TMDS   2
 #define DRM_MODE_ENCODER_LVDS   3
 #define DRM_MODE_ENCODER_TVDAC  4
+#define DRM_MODE_ENCODER_VIRTUAL 5
+#define DRM_MODE_ENCODER_DSI 6
 
 #define DRM_MODE_SUBCONNECTOR_Automatic 0
 #define DRM_MODE_SUBCONNECTOR_Unknown   0
@@ -136,6 +138,7 @@ extern "C" {
 #define DRM_MODE_SUBCONNECTOR_Composite 5
 #define DRM_MODE_SUBCONNECTOR_SVIDEO    6
 #define DRM_MODE_SUBCONNECTOR_Component 8
+#define DRM_MODE_SUBCONNECTOR_SCART     9
 
 #define DRM_MODE_CONNECTOR_Unknown      0
 #define DRM_MODE_CONNECTOR_VGA          1
@@ -152,6 +155,8 @@ extern "C" {
 #define DRM_MODE_CONNECTOR_HDMIB        12
 #define DRM_MODE_CONNECTOR_TV 13
 #define DRM_MODE_CONNECTOR_eDP 14
+#define DRM_MODE_CONNECTOR_VIRTUAL      15
+#define DRM_MODE_CONNECTOR_DSI          16
 
 #define DRM_MODE_PROP_PENDING   (1<<0)
 #define DRM_MODE_PROP_RANGE     (1<<1)
Index: intel/intel_bufmgr.h
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/intel/intel_bufmgr.h,v
retrieving revision 1.8
diff -u -p -r1.8 intel_bufmgr.h
--- intel/intel_bufmgr.h 8 Jul 2013 09:10:05 -0000 1.8
+++ intel/intel_bufmgr.h 11 Jan 2014 09:21:22 -0000
@@ -248,6 +248,11 @@ int drm_intel_reg_read(drm_intel_bufmgr
        uint32_t offset,
        uint64_t *result);
 
+int drm_intel_get_reset_stats(drm_intel_context *ctx,
+      uint32_t *reset_count,
+      uint32_t *active,
+      uint32_t *pending);
+
 /** @{ Compatibility defines to keep old code building despite the symbol rename
  * from dri_* to drm_intel_*
  */
Index: intel/intel_bufmgr_gem.c
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/intel/intel_bufmgr_gem.c,v
retrieving revision 1.17
diff -u -p -r1.17 intel_bufmgr_gem.c
--- intel/intel_bufmgr_gem.c 21 Nov 2013 13:30:07 -0000 1.17
+++ intel/intel_bufmgr_gem.c 11 Jan 2014 09:21:22 -0000
@@ -151,6 +151,8 @@ struct _drm_intel_bo_gem {
 
  /**
  * Kenel-assigned global name for this object
+         *
+         * List contains both flink named and prime fd'd objects
  */
  unsigned int global_name;
  drmMMListHead name_list;
@@ -866,10 +868,6 @@ drm_intel_bo_gem_create_from_name(drm_in
  }
  }
 
- bo_gem = calloc(1, sizeof(*bo_gem));
- if (!bo_gem)
- return NULL;
-
  VG_CLEAR(open_arg);
  open_arg.name = handle;
  ret = drmIoctl(bufmgr_gem->fd,
@@ -878,9 +876,26 @@ drm_intel_bo_gem_create_from_name(drm_in
  if (ret != 0) {
  DBG("Couldn't reference %s handle 0x%08x: %s\n",
     name, handle, strerror(errno));
- free(bo_gem);
  return NULL;
  }
+        /* Now see if someone has used a prime handle to get this
+         * object from the kernel before by looking through the list
+         * again for a matching gem_handle
+         */
+ for (list = bufmgr_gem->named.next;
+     list != &bufmgr_gem->named;
+     list = list->next) {
+ bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list);
+ if (bo_gem->gem_handle == open_arg.handle) {
+ drm_intel_gem_bo_reference(&bo_gem->bo);
+ return &bo_gem->bo;
+ }
+ }
+
+ bo_gem = calloc(1, sizeof(*bo_gem));
+ if (!bo_gem)
+ return NULL;
+
  bo_gem->bo.size = open_arg.size;
  bo_gem->bo.offset = 0;
  bo_gem->bo.virtual = NULL;
@@ -1954,12 +1969,14 @@ aub_write_trace_block(drm_intel_bo *bo,
 
  aub_out(bufmgr_gem,
  CMD_AUB_TRACE_HEADER_BLOCK |
- (5 - 2));
+ ((bufmgr_gem->gen >= 8 ? 6 : 5) - 2));
  aub_out(bufmgr_gem,
  AUB_TRACE_MEMTYPE_GTT | type | AUB_TRACE_OP_DATA_WRITE);
  aub_out(bufmgr_gem, subtype);
  aub_out(bufmgr_gem, bo_gem->aub_offset + offset);
  aub_out(bufmgr_gem, size);
+ if (bufmgr_gem->gen >= 8)
+ aub_out(bufmgr_gem, 0);
  aub_write_bo_data(bo, offset, size);
 }
 
@@ -2036,20 +2053,28 @@ aub_build_dump_ringbuffer(drm_intel_bufm
 
  /* Make a ring buffer to execute our batchbuffer. */
  memset(ringbuffer, 0, sizeof(ringbuffer));
- ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
- ringbuffer[ring_count++] = batch_buffer;
+ if (bufmgr_gem->gen >= 8) {
+ ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2);
+ ringbuffer[ring_count++] = batch_buffer;
+ ringbuffer[ring_count++] = 0;
+ } else {
+ ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
+ ringbuffer[ring_count++] = batch_buffer;
+ }
 
  /* Write out the ring.  This appears to trigger execution of
  * the ring in the simulator.
  */
  aub_out(bufmgr_gem,
  CMD_AUB_TRACE_HEADER_BLOCK |
- (5 - 2));
+ ((bufmgr_gem->gen >= 8 ? 6 : 5) - 2));
  aub_out(bufmgr_gem,
  AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE);
  aub_out(bufmgr_gem, 0); /* general/surface subtype */
  aub_out(bufmgr_gem, bufmgr_gem->aub_offset);
  aub_out(bufmgr_gem, ring_count * 4);
+ if (bufmgr_gem->gen >= 8)
+ aub_out(bufmgr_gem, 0);
 
  /* FIXME: Need some flush operations here? */
  aub_out_data(bufmgr_gem, ringbuffer, ring_count * 4);
@@ -2455,8 +2480,25 @@ drm_intel_bo_gem_create_from_prime(drm_i
  uint32_t handle;
  drm_intel_bo_gem *bo_gem;
  struct drm_i915_gem_get_tiling get_tiling;
+ drmMMListHead *list;
 
  ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
+
+ /*
+ * See if the kernel has already returned this buffer to us. Just as
+ * for named buffers, we must not create two bo's pointing at the same
+ * kernel object
+ */
+ for (list = bufmgr_gem->named.next;
+     list != &bufmgr_gem->named;
+     list = list->next) {
+ bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list);
+ if (bo_gem->gem_handle == handle) {
+ drm_intel_gem_bo_reference(&bo_gem->bo);
+ return &bo_gem->bo;
+ }
+ }
+
  if (ret) {
   fprintf(stderr,"ret is %d %d\n", ret, errno);
  return NULL;
@@ -2491,8 +2533,8 @@ drm_intel_bo_gem_create_from_prime(drm_i
  bo_gem->has_error = false;
  bo_gem->reusable = false;
 
- DRMINITLISTHEAD(&bo_gem->name_list);
  DRMINITLISTHEAD(&bo_gem->vma_list);
+ DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
 
  VG_CLEAR(get_tiling);
  get_tiling.handle = bo_gem->gem_handle;
@@ -2517,6 +2559,9 @@ drm_intel_bo_gem_export_to_prime(drm_int
  drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
  drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
 
+        if (DRMLISTEMPTY(&bo_gem->name_list))
+                DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
+
  if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
        DRM_CLOEXEC, prime_fd) != 0)
  return -errno;
@@ -2546,7 +2591,8 @@ drm_intel_gem_bo_flink(drm_intel_bo *bo,
  bo_gem->global_name = flink.name;
  bo_gem->reusable = false;
 
- DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
+                if (DRMLISTEMPTY(&bo_gem->name_list))
+                        DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
  }
 
  *name = bo_gem->global_name;
@@ -2966,11 +3012,13 @@ drm_intel_bufmgr_gem_set_aub_dump(drm_in
  aub_out(bufmgr_gem, 0); /* comment len */
 
  /* Set up the GTT. The max we can handle is 256M */
- aub_out(bufmgr_gem, CMD_AUB_TRACE_HEADER_BLOCK | (5 - 2));
+ aub_out(bufmgr_gem, CMD_AUB_TRACE_HEADER_BLOCK | ((bufmgr_gem->gen >= 8 ? 6 : 5) - 2));
  aub_out(bufmgr_gem, AUB_TRACE_MEMTYPE_NONLOCAL | 0 | AUB_TRACE_OP_DATA_WRITE);
  aub_out(bufmgr_gem, 0); /* subtype */
  aub_out(bufmgr_gem, 0); /* offset */
  aub_out(bufmgr_gem, gtt_size); /* size */
+ if (bufmgr_gem->gen >= 8)
+ aub_out(bufmgr_gem, 0);
  for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) {
  aub_out(bufmgr_gem, entry);
  }
@@ -3023,6 +3071,40 @@ drm_intel_gem_context_destroy(drm_intel_
 }
 
 int
+drm_intel_get_reset_stats(drm_intel_context *ctx,
+  uint32_t *reset_count,
+  uint32_t *active,
+  uint32_t *pending)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem;
+ struct drm_i915_reset_stats stats;
+ int ret;
+
+ if (ctx == NULL)
+ return -EINVAL;
+
+ memset(&stats, 0, sizeof(stats));
+
+ bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
+ stats.ctx_id = ctx->ctx_id;
+ ret = drmIoctl(bufmgr_gem->fd,
+       DRM_IOCTL_I915_GET_RESET_STATS,
+       &stats);
+ if (ret == 0) {
+ if (reset_count != NULL)
+ *reset_count = stats.reset_count;
+
+ if (active != NULL)
+ *active = stats.batch_active;
+
+ if (pending != NULL)
+ *pending = stats.batch_pending;
+ }
+
+ return ret;
+}
+
+int
 drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
    uint32_t offset,
    uint64_t *result)
@@ -3140,6 +3222,8 @@ drm_intel_bufmgr_gem_init(int fd, int ba
  bufmgr_gem->gen = 6;
  else if (IS_GEN7(bufmgr_gem->pci_device))
  bufmgr_gem->gen = 7;
+ else if (IS_GEN8(bufmgr_gem->pci_device))
+ bufmgr_gem->gen = 8;
  else {
  free(bufmgr_gem);
  return NULL;
Index: intel/intel_chipset.h
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/intel/intel_chipset.h,v
retrieving revision 1.6
diff -u -p -r1.6 intel_chipset.h
--- intel/intel_chipset.h 8 Jul 2013 09:10:05 -0000 1.6
+++ intel/intel_chipset.h 11 Jan 2014 09:21:22 -0000
@@ -148,6 +148,12 @@
 #define PCI_CHIP_HASWELL_CRW_E_GT1 0x0D0E /* Reserved */
 #define PCI_CHIP_HASWELL_CRW_E_GT2 0x0D1E
 #define PCI_CHIP_HASWELL_CRW_E_GT3 0x0D2E
+#define BDW_SPARE 0x2
+#define BDW_ULT 0x6
+#define BDW_SERVER 0xa
+#define BDW_IRIS 0xb
+#define BDW_WORKSTATION 0xd
+#define BDW_ULX 0xe
 
 #define PCI_CHIP_VALLEYVIEW_PO 0x0f30 /* VLV PO board */
 #define PCI_CHIP_VALLEYVIEW_1 0x0f31
@@ -296,10 +302,24 @@
  IS_HSW_GT2(devid) || \
  IS_HSW_GT3(devid))
 
+#define IS_BROADWELL(devid)     (((devid & 0xff00) != 0x1600) ? 0 : \
+ (((devid & 0x00f0) >> 4) > 3) ? 0 : \
+ ((devid & 0x000f) == BDW_SPARE) ? 1 : \
+ ((devid & 0x000f) == BDW_ULT) ? 1 : \
+ ((devid & 0x000f) == BDW_IRIS) ? 1 : \
+ ((devid & 0x000f) == BDW_SERVER) ? 1 : \
+ ((devid & 0x000f) == BDW_WORKSTATION) ? 1 : \
+ ((devid & 0x000f) == BDW_ULX) ? 1 : 0)
+
+
+#define IS_GEN8(devid) IS_BROADWELL(devid)
+
 #define IS_9XX(dev) (IS_GEN3(dev) || \
  IS_GEN4(dev) || \
  IS_GEN5(dev) || \
  IS_GEN6(dev) || \
- IS_GEN7(dev))
+ IS_GEN7(dev) || \
+ IS_GEN8(dev))
+
 
 #endif /* _INTEL_CHIPSET_H */
Index: intel/intel_decode.c
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/intel/intel_decode.c,v
retrieving revision 1.2
diff -u -p -r1.2 intel_decode.c
--- intel/intel_decode.c 20 Jun 2013 09:55:30 -0000 1.2
+++ intel/intel_decode.c 11 Jan 2014 09:21:22 -0000
@@ -257,6 +257,8 @@ decode_mi(struct drm_intel_decode *ctx)
  { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT", decode_MI_WAIT_FOR_EVENT },
  { 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" },
  { 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" },
+ { 0x28, 0x3f, 3, 3, "MI_REPORT_PERF_COUNT" },
+ { 0x29, 0xff, 3, 3, "MI_LOAD_REGISTER_MEM" },
  { 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH"},
  }, *opcode_mi = NULL;
 
@@ -3825,7 +3827,9 @@ drm_intel_decode_context_alloc(uint32_t
  ctx->devid = devid;
  ctx->out = stdout;
 
- if (IS_GEN7(devid))
+ if (IS_GEN8(devid))
+ ctx->gen = 8;
+ else if (IS_GEN7(devid))
  ctx->gen = 7;
  else if (IS_GEN6(devid))
  ctx->gen = 6;
Index: intel/shlib_version
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/intel/shlib_version,v
retrieving revision 1.9
diff -u -p -r1.9 shlib_version
--- intel/shlib_version 13 Aug 2013 07:07:20 -0000 1.9
+++ intel/shlib_version 11 Jan 2014 09:22:10 -0000
@@ -1,2 +1,2 @@
 major=3
-minor=0
+minor=1
Index: radeon/r600_pci_ids.h
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/radeon/r600_pci_ids.h,v
retrieving revision 1.5
diff -u -p -r1.5 r600_pci_ids.h
--- radeon/r600_pci_ids.h 21 Nov 2013 13:30:07 -0000 1.5
+++ radeon/r600_pci_ids.h 11 Jan 2014 09:21:42 -0000
@@ -208,7 +208,7 @@ CHIPSET(0x9644, SUMO2_9644, SUMO2)
 CHIPSET(0x9645, SUMO2_9645, SUMO2)
 CHIPSET(0x9647, SUMO_9647,  SUMO)
 CHIPSET(0x9648, SUMO_9648,  SUMO)
-CHIPSET(0x9649, SUMO_9649,  SUMO)
+CHIPSET(0x9649, SUMO2_9649, SUMO2)
 CHIPSET(0x964a, SUMO_964A,  SUMO)
 CHIPSET(0x964b, SUMO_964B,  SUMO)
 CHIPSET(0x964c, SUMO_964C,  SUMO)
@@ -446,3 +446,16 @@ CHIPSET(0x1317, KAVERI_1317, KAVERI)
 CHIPSET(0x131B, KAVERI_131B, KAVERI)
 CHIPSET(0x131C, KAVERI_131C, KAVERI)
 CHIPSET(0x131D, KAVERI_131D, KAVERI)
+
+CHIPSET(0x67A0, HAWAII_67A0, HAWAII)
+CHIPSET(0x67A1, HAWAII_67A1, HAWAII)
+CHIPSET(0x67A2, HAWAII_67A2, HAWAII)
+CHIPSET(0x67A8, HAWAII_67A8, HAWAII)
+CHIPSET(0x67A9, HAWAII_67A9, HAWAII)
+CHIPSET(0x67AA, HAWAII_67AA, HAWAII)
+CHIPSET(0x67B0, HAWAII_67B0, HAWAII)
+CHIPSET(0x67B1, HAWAII_67B1, HAWAII)
+CHIPSET(0x67B8, HAWAII_67B8, HAWAII)
+CHIPSET(0x67B9, HAWAII_67B9, HAWAII)
+CHIPSET(0x67BA, HAWAII_67BA, HAWAII)
+CHIPSET(0x67BE, HAWAII_67BE, HAWAII)
Index: radeon/radeon_surface.c
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/radeon/radeon_surface.c,v
retrieving revision 1.5
diff -u -p -r1.5 radeon_surface.c
--- radeon/radeon_surface.c 21 Nov 2013 13:30:07 -0000 1.5
+++ radeon/radeon_surface.c 11 Jan 2014 09:21:42 -0000
@@ -26,6 +26,8 @@
  * Authors:
  *      JérÃŽme Glisse <[hidden email]>
  */
+#include <stdbool.h>
+#include <assert.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -77,6 +79,7 @@ enum radeon_family {
     CHIP_BONAIRE,
     CHIP_KAVERI,
     CHIP_KABINI,
+    CHIP_HAWAII,
     CHIP_LAST,
 };
 
@@ -95,6 +98,8 @@ struct radeon_hw_info {
     unsigned                        allow_2d;
     /* apply to si */
     uint32_t                        tile_mode_array[32];
+    /* apply to cik */
+    uint32_t                        macrotile_mode_array[16];
 };
 
 struct radeon_surface_manager {
@@ -650,7 +655,7 @@ static int eg_surface_init_2d(struct rad
     tileb = tilew * tileh * bpe * surf->nsamples;
     /* slices per tile */
     slice_pt = 1;
-    if (tileb > tile_split) {
+    if (tileb > tile_split && tile_split) {
         slice_pt = tileb / tile_split;
     }
     tileb = tileb / slice_pt;
@@ -1382,16 +1387,10 @@ static int si_surface_sanity(struct rade
         break;
     case RADEON_SURF_MODE_1D:
         if (surf->flags & RADEON_SURF_SBUFFER) {
-            if (surf_man->family >= CHIP_BONAIRE)
-                *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
-            else
-                *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
+            *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
         }
         if (surf->flags & RADEON_SURF_ZBUFFER) {
-            if (surf_man->family >= CHIP_BONAIRE)
-                *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
-            else
-                *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
+            *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
         } else if (surf->flags & RADEON_SURF_SCANOUT) {
             *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
         } else {
@@ -1437,16 +1436,17 @@ static void si_surf_minify(struct radeon
      */
     if (level == 0 && surf->last_level == 0)
         /* Non-mipmap pitch padded to slice alignment */
+        /* Using just bpe here breaks stencil blitting; surf->bpe works. */
         xalign = MAX2(xalign, slice_align / surf->bpe);
     else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED)
         /* Small rows evenly distributed across slice */
-        xalign = MAX2(xalign, slice_align / surf->bpe / surflevel->nblk_y);
+        xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y);
 
     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
 
     surflevel->offset = offset;
-    surflevel->pitch_bytes = surflevel->nblk_x * surf->bpe * surf->nsamples;
+    surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
     surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
 
     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
@@ -1540,6 +1540,7 @@ static int si_surface_init_1d(struct rad
                               uint64_t offset, unsigned start_level)
 {
     uint32_t xalign, yalign, zalign, slice_align;
+    unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
     unsigned i;
 
     /* compute alignment */
@@ -1551,11 +1552,11 @@ static int si_surface_init_1d(struct rad
         xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
     }
 
-    if (!start_level) {
-        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+    if (start_level <= 1) {
+        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
 
         if (offset) {
-            offset = ALIGN(offset, surf->bo_alignment);
+            offset = ALIGN(offset, alignment);
         }
     }
 
@@ -1566,7 +1567,7 @@ static int si_surface_init_1d(struct rad
         /* level0 and first mipmap need to have alignment */
         offset = surf->bo_size;
         if ((i == 0)) {
-            offset = ALIGN(offset, surf->bo_alignment);
+            offset = ALIGN(offset, alignment);
         }
         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
             if (surf->level == level) {
@@ -1608,6 +1609,7 @@ static int si_surface_init_2d(struct rad
                               uint64_t offset,
                               unsigned start_level)
 {
+    uint64_t aligned_offset = offset;
     unsigned tilew, tileh, tileb;
     unsigned mtilew, mtileh, mtileb;
     unsigned slice_pt;
@@ -1619,7 +1621,7 @@ static int si_surface_init_2d(struct rad
     tileb = tilew * tileh * bpe * surf->nsamples;
     /* slices per tile */
     slice_pt = 1;
-    if (tileb > tile_split) {
+    if (tileb > tile_split && tile_split) {
         slice_pt = tileb / tile_split;
     }
     tileb = tileb / slice_pt;
@@ -1631,19 +1633,19 @@ static int si_surface_init_2d(struct rad
     /* macro tile bytes */
     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
 
-    if (!start_level) {
+    if (start_level <= 1) {
         unsigned alignment = MAX2(256, mtileb);
         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
 
-        if (offset) {
-            offset = ALIGN(offset, alignment);
+        if (aligned_offset) {
+            aligned_offset = ALIGN(aligned_offset, alignment);
         }
     }
 
     /* build mipmap tree */
     for (i = start_level; i <= surf->last_level; i++) {
         level[i].mode = RADEON_SURF_MODE_2D;
-        si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset);
+        si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
         if (level[i].mode == RADEON_SURF_MODE_1D) {
             switch (tile_mode) {
             case SI_TILE_MODE_COLOR_2D_8BPP:
@@ -1657,10 +1659,7 @@ static int si_surface_init_2d(struct rad
                 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
                 break;
             case SI_TILE_MODE_DEPTH_STENCIL_2D:
-                if (surf_man->family >= CHIP_BONAIRE)
-                    tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
-                else
-                    tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
+                tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
                 break;
             default:
                 return -EINVAL;
@@ -1668,9 +1667,9 @@ static int si_surface_init_2d(struct rad
             return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
         }
         /* level0 and first mipmap need to have alignment */
-        offset = surf->bo_size;
+        aligned_offset = offset = surf->bo_size;
         if ((i == 0)) {
-            offset = ALIGN(offset, surf->bo_alignment);
+            aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
         }
         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
             if (surf->level == level) {
@@ -1789,6 +1788,610 @@ static int si_surface_best(struct radeon
 
 
 /* ===========================================================================
+ * Sea Islands family
+ */
+#define CIK__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P2               0
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16   16
+#define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16  17
+#define CIK__GB_TILE_MODE__TILE_SPLIT(x)         (((x) >> 11) & 0x7)
+#define     CIK__TILE_SPLIT__64B                         0
+#define     CIK__TILE_SPLIT__128B                        1
+#define     CIK__TILE_SPLIT__256B                        2
+#define     CIK__TILE_SPLIT__512B                        3
+#define     CIK__TILE_SPLIT__1024B                       4
+#define     CIK__TILE_SPLIT__2048B                       5
+#define     CIK__TILE_SPLIT__4096B                       6
+#define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x)         (((x) >> 25) & 0x3)
+#define     CIK__SAMPLE_SPLIT__1                         0
+#define     CIK__SAMPLE_SPLIT__2                         1
+#define     CIK__SAMPLE_SPLIT__4                         2
+#define     CIK__SAMPLE_SPLIT__8                         3
+#define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x)        ((x) & 0x3)
+#define     CIK__BANK_WIDTH__1                           0
+#define     CIK__BANK_WIDTH__2                           1
+#define     CIK__BANK_WIDTH__4                           2
+#define     CIK__BANK_WIDTH__8                           3
+#define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x)       (((x) >> 2) & 0x3)
+#define     CIK__BANK_HEIGHT__1                          0
+#define     CIK__BANK_HEIGHT__2                          1
+#define     CIK__BANK_HEIGHT__4                          2
+#define     CIK__BANK_HEIGHT__8                          3
+#define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
+#define     CIK__MACRO_TILE_ASPECT__1                    0
+#define     CIK__MACRO_TILE_ASPECT__2                    1
+#define     CIK__MACRO_TILE_ASPECT__4                    2
+#define     CIK__MACRO_TILE_ASPECT__8                    3
+#define CIK__GB_MACROTILE_MODE__NUM_BANKS(x)         (((x) >> 6) & 0x3)
+#define     CIK__NUM_BANKS__2_BANK                       0
+#define     CIK__NUM_BANKS__4_BANK                       1
+#define     CIK__NUM_BANKS__8_BANK                       2
+#define     CIK__NUM_BANKS__16_BANK                      3
+
+
+static void cik_get_2d_params(struct radeon_surface_manager *surf_man,
+                              unsigned bpe, unsigned nsamples, bool is_color,
+                              unsigned tile_mode,
+                              uint32_t *num_pipes,
+                              uint32_t *tile_split_ptr,
+                              uint32_t *num_banks,
+                              uint32_t *macro_tile_aspect,
+                              uint32_t *bank_w,
+                              uint32_t *bank_h)
+{
+    uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
+    unsigned tileb_1x, tileb;
+    unsigned gb_macrotile_mode;
+    unsigned macrotile_index;
+    unsigned tile_split, sample_split;
+
+    if (num_pipes) {
+        switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
+        case CIK__PIPE_CONFIG__ADDR_SURF_P2:
+        default:
+            *num_pipes = 2;
+            break;
+        case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
+            *num_pipes = 4;
+            break;
+        case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
+            *num_pipes = 8;
+            break;
+        case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
+        case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
+            *num_pipes = 16;
+            break;
+        }
+    }
+    switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
+    default:
+    case CIK__TILE_SPLIT__64B:
+        tile_split = 64;
+        break;
+    case CIK__TILE_SPLIT__128B:
+        tile_split = 128;
+        break;
+    case CIK__TILE_SPLIT__256B:
+        tile_split = 256;
+        break;
+    case CIK__TILE_SPLIT__512B:
+        tile_split = 512;
+        break;
+    case CIK__TILE_SPLIT__1024B:
+        tile_split = 1024;
+        break;
+    case CIK__TILE_SPLIT__2048B:
+        tile_split = 2048;
+        break;
+    case CIK__TILE_SPLIT__4096B:
+        tile_split = 4096;
+        break;
+    }
+    switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
+    default:
+    case CIK__SAMPLE_SPLIT__1:
+        sample_split = 1;
+        break;
+    case CIK__SAMPLE_SPLIT__2:
+        sample_split = 1;
+        break;
+    case CIK__SAMPLE_SPLIT__4:
+        sample_split = 4;
+        break;
+    case CIK__SAMPLE_SPLIT__8:
+        sample_split = 8;
+        break;
+    }
+
+    /* Adjust the tile split. */
+    tileb_1x = 8 * 8 * bpe;
+    if (is_color) {
+        tile_split = MAX2(256, sample_split * tileb_1x);
+    }
+    tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
+
+    /* Determine the macrotile index. */
+    tileb = MIN2(tile_split, nsamples * tileb_1x);
+
+    for (macrotile_index = 0; tileb > 64; macrotile_index++) {
+        tileb >>= 1;
+    }
+    gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
+
+    if (tile_split_ptr) {
+        *tile_split_ptr = tile_split;
+    }
+    if (num_banks) {
+        switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
+        default:
+        case CIK__NUM_BANKS__2_BANK:
+            *num_banks = 2;
+            break;
+        case CIK__NUM_BANKS__4_BANK:
+            *num_banks = 4;
+            break;
+        case CIK__NUM_BANKS__8_BANK:
+            *num_banks = 8;
+            break;
+        case CIK__NUM_BANKS__16_BANK:
+            *num_banks = 16;
+            break;
+        }
+    }
+    if (macro_tile_aspect) {
+        switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
+        default:
+        case CIK__MACRO_TILE_ASPECT__1:
+            *macro_tile_aspect = 1;
+            break;
+        case CIK__MACRO_TILE_ASPECT__2:
+            *macro_tile_aspect = 2;
+            break;
+        case CIK__MACRO_TILE_ASPECT__4:
+            *macro_tile_aspect = 4;
+            break;
+        case CIK__MACRO_TILE_ASPECT__8:
+            *macro_tile_aspect = 8;
+            break;
+        }
+    }
+    if (bank_w) {
+        switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
+        default:
+        case CIK__BANK_WIDTH__1:
+            *bank_w = 1;
+            break;
+        case CIK__BANK_WIDTH__2:
+            *bank_w = 2;
+            break;
+        case CIK__BANK_WIDTH__4:
+            *bank_w = 4;
+            break;
+        case CIK__BANK_WIDTH__8:
+            *bank_w = 8;
+            break;
+        }
+    }
+    if (bank_h) {
+        switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
+        default:
+        case CIK__BANK_HEIGHT__1:
+            *bank_h = 1;
+            break;
+        case CIK__BANK_HEIGHT__2:
+            *bank_h = 2;
+            break;
+        case CIK__BANK_HEIGHT__4:
+            *bank_h = 4;
+            break;
+        case CIK__BANK_HEIGHT__8:
+            *bank_h = 8;
+            break;
+        }
+    }
+}
+
+static int cik_init_hw_info(struct radeon_surface_manager *surf_man)
+{
+    uint32_t tiling_config;
+    drmVersionPtr version;
+    int r;
+
+    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
+                         &tiling_config);
+    if (r) {
+        return r;
+    }
+
+    surf_man->hw_info.allow_2d = 0;
+    version = drmGetVersion(surf_man->fd);
+    if (version && version->version_minor >= 35) {
+        if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
+    !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) {
+            surf_man->hw_info.allow_2d = 1;
+        }
+    }
+    drmFreeVersion(version);
+
+    switch (tiling_config & 0xf) {
+    case 0:
+        surf_man->hw_info.num_pipes = 1;
+        break;
+    case 1:
+        surf_man->hw_info.num_pipes = 2;
+        break;
+    case 2:
+        surf_man->hw_info.num_pipes = 4;
+        break;
+    case 3:
+        surf_man->hw_info.num_pipes = 8;
+        break;
+    default:
+        surf_man->hw_info.num_pipes = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0xf0) >> 4) {
+    case 0:
+        surf_man->hw_info.num_banks = 4;
+        break;
+    case 1:
+        surf_man->hw_info.num_banks = 8;
+        break;
+    case 2:
+        surf_man->hw_info.num_banks = 16;
+        break;
+    default:
+        surf_man->hw_info.num_banks = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0xf00) >> 8) {
+    case 0:
+        surf_man->hw_info.group_bytes = 256;
+        break;
+    case 1:
+        surf_man->hw_info.group_bytes = 512;
+        break;
+    default:
+        surf_man->hw_info.group_bytes = 256;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0xf000) >> 12) {
+    case 0:
+        surf_man->hw_info.row_size = 1024;
+        break;
+    case 1:
+        surf_man->hw_info.row_size = 2048;
+        break;
+    case 2:
+        surf_man->hw_info.row_size = 4096;
+        break;
+    default:
+        surf_man->hw_info.row_size = 4096;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+    return 0;
+}
+
+static int cik_surface_sanity(struct radeon_surface_manager *surf_man,
+                              struct radeon_surface *surf,
+                              unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
+{
+    /* check surface dimension */
+    if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
+        return -EINVAL;
+    }
+
+    /* check mipmap last_level */
+    if (surf->last_level > 15) {
+        return -EINVAL;
+    }
+
+    /* force 1d on kernel that can't do 2d */
+    if (mode > RADEON_SURF_MODE_1D &&
+        (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
+        if (surf->nsamples > 1) {
+            fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
+            return -EFAULT;
+        }
+        mode = RADEON_SURF_MODE_1D;
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(mode, MODE);
+    }
+
+    if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
+        return -EINVAL;
+    }
+
+    if (!surf->tile_split) {
+        /* default value */
+        surf->mtilea = 1;
+        surf->bankw = 1;
+        surf->bankw = 1;
+        surf->tile_split = 64;
+        surf->stencil_tile_split = 64;
+    }
+
+    switch (mode) {
+    case RADEON_SURF_MODE_2D: {
+        if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) {
+            switch (surf->nsamples) {
+            case 1:
+                *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
+                break;
+            case 2:
+            case 4:
+                *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
+                break;
+            case 8:
+                *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
+                break;
+            default:
+                return -EINVAL;
+            }
+
+            if (surf->flags & RADEON_SURF_SBUFFER) {
+                *stencil_tile_mode = *tile_mode;
+
+                cik_get_2d_params(surf_man, 1, surf->nsamples, false,
+                                  *stencil_tile_mode, NULL,
+                                  &surf->stencil_tile_split,
+                                  NULL, NULL, NULL, NULL);
+            }
+        } else if (surf->flags & RADEON_SURF_SCANOUT) {
+            *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
+        } else {
+            *tile_mode = CIK_TILE_MODE_COLOR_2D;
+        }
+
+        /* retrieve tiling mode values */
+        cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
+                          !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
+                          NULL, &surf->tile_split, NULL, &surf->mtilea,
+                          &surf->bankw, &surf->bankh);
+        break;
+    }
+    case RADEON_SURF_MODE_1D:
+        if (surf->flags & RADEON_SURF_SBUFFER) {
+            *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
+        }
+        if (surf->flags & RADEON_SURF_ZBUFFER) {
+            *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
+        } else if (surf->flags & RADEON_SURF_SCANOUT) {
+            *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
+        } else {
+            *tile_mode = SI_TILE_MODE_COLOR_1D;
+        }
+        break;
+    case RADEON_SURF_MODE_LINEAR_ALIGNED:
+    default:
+        *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
+    }
+
+    return 0;
+}
+
+static int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
+                               struct radeon_surface *surf,
+                               struct radeon_surface_level *level,
+                               unsigned bpe, unsigned tile_mode,
+                               unsigned tile_split,
+                               unsigned num_pipes, unsigned num_banks,
+                               uint64_t offset,
+                               unsigned start_level)
+{
+    uint64_t aligned_offset = offset;
+    unsigned tilew, tileh, tileb_1x, tileb;
+    unsigned mtilew, mtileh, mtileb;
+    unsigned slice_pt;
+    unsigned i;
+
+    /* compute tile values */
+    tilew = 8;
+    tileh = 8;
+    tileb_1x = tilew * tileh * bpe;
+
+    tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
+
+    tileb = surf->nsamples * tileb_1x;
+
+    /* slices per tile */
+    slice_pt = 1;
+    if (tileb > tile_split && tile_split) {
+        slice_pt = tileb / tile_split;
+        tileb = tileb / slice_pt;
+    }
+
+    /* macro tile width & height */
+    mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
+    mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
+
+    /* macro tile bytes */
+    mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
+
+    if (start_level <= 1) {
+        unsigned alignment = MAX2(256, mtileb);
+        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
+
+        if (aligned_offset) {
+            aligned_offset = ALIGN(aligned_offset, alignment);
+        }
+    }
+
+    /* build mipmap tree */
+    for (i = start_level; i <= surf->last_level; i++) {
+        level[i].mode = RADEON_SURF_MODE_2D;
+        si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
+        if (level[i].mode == RADEON_SURF_MODE_1D) {
+            switch (tile_mode) {
+            case CIK_TILE_MODE_COLOR_2D:
+                tile_mode = SI_TILE_MODE_COLOR_1D;
+                break;
+            case CIK_TILE_MODE_COLOR_2D_SCANOUT:
+                tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
+                break;
+            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
+            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
+            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
+            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
+            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
+                tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
+                break;
+            default:
+                return -EINVAL;
+            }
+            return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
+        }
+        /* level0 and first mipmap need to have alignment */
+        aligned_offset = offset = surf->bo_size;
+        if (i == 0) {
+            aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
+        }
+        if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
+            if (surf->level == level) {
+                surf->tiling_index[i] = tile_mode;
+                /* it's ok because stencil is done after */
+                surf->stencil_tiling_index[i] = tile_mode;
+            } else {
+                surf->stencil_tiling_index[i] = tile_mode;
+            }
+        }
+    }
+    return 0;
+}
+
+static int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
+                                        struct radeon_surface *surf,
+                                        unsigned tile_mode, unsigned stencil_tile_mode)
+{
+    int r;
+    uint32_t num_pipes, num_banks;
+
+    cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
+                        !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
+                        &num_pipes, NULL, &num_banks, NULL, NULL, NULL);
+
+    r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
+                            surf->tile_split, num_pipes, num_banks, 0, 0);
+    if (r) {
+        return r;
+    }
+
+    if (surf->flags & RADEON_SURF_SBUFFER) {
+        r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
+                                surf->stencil_tile_split, num_pipes, num_banks,
+                                surf->bo_size, 0);
+        surf->stencil_offset = surf->stencil_level[0].offset;
+    }
+    return r;
+}
+
+static int cik_surface_init(struct radeon_surface_manager *surf_man,
+                            struct radeon_surface *surf)
+{
+    unsigned mode, tile_mode, stencil_tile_mode;
+    int r;
+
+    /* MSAA surfaces support the 2D mode only. */
+    if (surf->nsamples > 1) {
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+    }
+
+    /* tiling mode */
+    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
+
+    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+        /* zbuffer only support 1D or 2D tiled surface */
+        switch (mode) {
+        case RADEON_SURF_MODE_1D:
+        case RADEON_SURF_MODE_2D:
+            break;
+        default:
+            mode = RADEON_SURF_MODE_1D;
+            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+            break;
+        }
+    }
+
+    r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
+    if (r) {
+        return r;
+    }
+
+    surf->stencil_offset = 0;
+    surf->bo_alignment = 0;
+
+    /* check tiling mode */
+    switch (mode) {
+    case RADEON_SURF_MODE_LINEAR:
+        r = r6_surface_init_linear(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_LINEAR_ALIGNED:
+        r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
+        break;
+    case RADEON_SURF_MODE_1D:
+        r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
+        break;
+    case RADEON_SURF_MODE_2D:
+        r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
+        break;
+    default:
+        return -EINVAL;
+    }
+    return r;
+}
+
+/*
+ * depending on surface
+ */
+static int cik_surface_best(struct radeon_surface_manager *surf_man,
+                            struct radeon_surface *surf)
+{
+    unsigned mode, tile_mode, stencil_tile_mode;
+
+    /* tiling mode */
+    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
+
+    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
+        !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
+        /* depth/stencil force 1d tiling for old mesa */
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+    }
+
+    return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
+}
+
+
+/* ===========================================================================
  * public API
  */
 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
@@ -1819,12 +2422,18 @@ struct radeon_surface_manager *radeon_su
         }
         surf_man->surface_init = &eg_surface_init;
         surf_man->surface_best = &eg_surface_best;
-    } else {
+    } else if (surf_man->family < CHIP_BONAIRE) {
         if (si_init_hw_info(surf_man)) {
             goto out_err;
         }
         surf_man->surface_init = &si_surface_init;
         surf_man->surface_best = &si_surface_best;
+    } else {
+        if (cik_init_hw_info(surf_man)) {
+            goto out_err;
+        }
+        surf_man->surface_init = &cik_surface_init;
+        surf_man->surface_best = &cik_surface_best;
     }
 
     return surf_man;
Index: radeon/radeon_surface.h
===================================================================
RCS file: /cvs/xenocara/lib/libdrm/radeon/radeon_surface.h,v
retrieving revision 1.3
diff -u -p -r1.3 radeon_surface.h
--- radeon/radeon_surface.h 20 Jun 2013 09:55:30 -0000 1.3
+++ radeon/radeon_surface.h 11 Jan 2014 09:21:42 -0000
@@ -54,6 +54,7 @@
 #define RADEON_SURF_SCANOUT                     (1 << 16)
 #define RADEON_SURF_ZBUFFER                     (1 << 17)
 #define RADEON_SURF_SBUFFER                     (1 << 18)
+#define RADEON_SURF_Z_OR_SBUFFER                (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)
 #define RADEON_SURF_HAS_SBUFFER_MIPTREE         (1 << 19)
 #define RADEON_SURF_HAS_TILE_MODE_INDEX         (1 << 20)
 #define RADEON_SURF_FMASK                       (1 << 21)