From: Jerome Glisse <jgli...@redhat.com>

Allow userspace to query for the tile mode array so userspace can properly
compute surface pitch and alignment requirement depending on tiling.

Signed-off-by: Jerome Glisse <jglisse at redhat.com>
---
 drivers/gpu/drm/radeon/radeon.h     |   1 +
 drivers/gpu/drm/radeon/radeon_drv.c |   3 +-
 drivers/gpu/drm/radeon/radeon_kms.c | 158 +++++++++++++++++++-----------------
 drivers/gpu/drm/radeon/si.c         |   2 +
 include/uapi/drm/radeon_drm.h       |  20 +++++
 5 files changed, 109 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8263af3..961659e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1443,6 +1443,7 @@ struct si_asic {
        unsigned multi_gpu_tile_size;

        unsigned tile_config;
+       uint32_t tile_mode_array[32];
 };

 union radeon_asic_config {
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index 66a7f0f..1e48ab6 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -71,9 +71,10 @@
  *   2.28.0 - r600-eg: Add MEM_WRITE packet support
  *   2.29.0 - R500 FP16 color clear registers
  *   2.30.0 - fix for FMASK texturing
+ *   2.31.0 - Add SI tiling mode array query
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       30
+#define KMS_DRIVER_MINOR       31
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c 
b/drivers/gpu/drm/radeon/radeon_kms.c
index c75cb2c..8076434 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -176,80 +176,65 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
        struct radeon_device *rdev = dev->dev_private;
        struct drm_radeon_info *info = data;
        struct radeon_mode_info *minfo = &rdev->mode_info;
-       uint32_t value, *value_ptr;
-       uint64_t value64, *value_ptr64;
+       uint32_t *value, value_tmp, *value_ptr, value_size;
+       uint64_t value64;
        struct drm_crtc *crtc;
        int i, found;

-       /* TIMESTAMP is a 64-bit value, needs special handling. */
-       if (info->request == RADEON_INFO_TIMESTAMP) {
-               if (rdev->family >= CHIP_R600) {
-                       value_ptr64 = (uint64_t*)((unsigned long)info->value);
-                       value64 = radeon_get_gpu_clock_counter(rdev);
-
-                       if (DRM_COPY_TO_USER(value_ptr64, &value64, 
sizeof(value64))) {
-                               DRM_ERROR("copy_to_user %s:%u\n", __func__, 
__LINE__);
-                               return -EFAULT;
-                       }
-                       return 0;
-               } else {
-                       DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
-                       return -EINVAL;
-               }
-       }
-
        value_ptr = (uint32_t *)((unsigned long)info->value);
-       if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) {
-               DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
-               return -EFAULT;
-       }
+       value = &value_tmp;
+       value_size = sizeof(uint32_t);

        switch (info->request) {
        case RADEON_INFO_DEVICE_ID:
-               value = dev->pci_device;
+               *value = dev->pci_device;
                break;
        case RADEON_INFO_NUM_GB_PIPES:
-               value = rdev->num_gb_pipes;
+               *value = rdev->num_gb_pipes;
                break;
        case RADEON_INFO_NUM_Z_PIPES:
-               value = rdev->num_z_pipes;
+               *value = rdev->num_z_pipes;
                break;
        case RADEON_INFO_ACCEL_WORKING:
                /* xf86-video-ati 6.13.0 relies on this being false for 
evergreen */
                if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= 
CHIP_HEMLOCK))
-                       value = false;
+                       *value = false;
                else
-                       value = rdev->accel_working;
+                       *value = rdev->accel_working;
                break;
        case RADEON_INFO_CRTC_FROM_ID:
+               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+                       DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
+                       return -EFAULT;
+               }
                for (i = 0, found = 0; i < rdev->num_crtc; i++) {
                        crtc = (struct drm_crtc *)minfo->crtcs[i];
-                       if (crtc && crtc->base.id == value) {
+                       if (crtc && crtc->base.id == *value) {
                                struct radeon_crtc *radeon_crtc = 
to_radeon_crtc(crtc);
-                               value = radeon_crtc->crtc_id;
+                               *value = radeon_crtc->crtc_id;
                                found = 1;
                                break;
                        }
                }
                if (!found) {
-                       DRM_DEBUG_KMS("unknown crtc id %d\n", value);
+                       DRM_DEBUG_KMS("unknown crtc id %d\n", *value);
                        return -EINVAL;
                }
                break;
        case RADEON_INFO_ACCEL_WORKING2:
-               value = rdev->accel_working;
+               *value = rdev->accel_working;
                break;
        case RADEON_INFO_TILING_CONFIG:
                if (rdev->family >= CHIP_TAHITI)
-                       value = rdev->config.si.tile_config;
+                       *value = rdev->config.si.tile_config;
                else if (rdev->family >= CHIP_CAYMAN)
-                       value = rdev->config.cayman.tile_config;
+                       *value = rdev->config.cayman.tile_config;
                else if (rdev->family >= CHIP_CEDAR)
-                       value = rdev->config.evergreen.tile_config;
+                       *value = rdev->config.evergreen.tile_config;
                else if (rdev->family >= CHIP_RV770)
-                       value = rdev->config.rv770.tile_config;
+                       *value = rdev->config.rv770.tile_config;
                else if (rdev->family >= CHIP_R600)
-                       value = rdev->config.r600.tile_config;
+                       *value = rdev->config.r600.tile_config;
                else {
                        DRM_DEBUG_KMS("tiling config is r6xx+ only!\n");
                        return -EINVAL;
@@ -262,73 +247,81 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
                 *
                 * When returning, the value is 1 if filp owns hyper-z access,
                 * 0 otherwise. */
-               if (value >= 2) {
-                       DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value);
+               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+                       DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
+                       return -EFAULT;
+               }
+               if (*value >= 2) {
+                       DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", 
*value);
                        return -EINVAL;
                }
-               radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value);
+               radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, value);
                break;
        case RADEON_INFO_WANT_CMASK:
                /* The same logic as Hyper-Z. */
-               if (value >= 2) {
-                       DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value);
+               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+                       DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
+                       return -EFAULT;
+               }
+               if (*value >= 2) {
+                       DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", *value);
                        return -EINVAL;
                }
-               radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value);
+               radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, value);
                break;
        case RADEON_INFO_CLOCK_CRYSTAL_FREQ:
                /* return clock value in KHz */
                if (rdev->asic->get_xclk)
-                       value = radeon_get_xclk(rdev) * 10;
+                       *value = radeon_get_xclk(rdev) * 10;
                else
-                       value = rdev->clock.spll.reference_freq * 10;
+                       *value = rdev->clock.spll.reference_freq * 10;
                break;
        case RADEON_INFO_NUM_BACKENDS:
                if (rdev->family >= CHIP_TAHITI)
-                       value = rdev->config.si.max_backends_per_se *
+                       *value = rdev->config.si.max_backends_per_se *
                                rdev->config.si.max_shader_engines;
                else if (rdev->family >= CHIP_CAYMAN)
-                       value = rdev->config.cayman.max_backends_per_se *
+                       *value = rdev->config.cayman.max_backends_per_se *
                                rdev->config.cayman.max_shader_engines;
                else if (rdev->family >= CHIP_CEDAR)
-                       value = rdev->config.evergreen.max_backends;
+                       *value = rdev->config.evergreen.max_backends;
                else if (rdev->family >= CHIP_RV770)
-                       value = rdev->config.rv770.max_backends;
+                       *value = rdev->config.rv770.max_backends;
                else if (rdev->family >= CHIP_R600)
-                       value = rdev->config.r600.max_backends;
+                       *value = rdev->config.r600.max_backends;
                else {
                        return -EINVAL;
                }
                break;
        case RADEON_INFO_NUM_TILE_PIPES:
                if (rdev->family >= CHIP_TAHITI)
-                       value = rdev->config.si.max_tile_pipes;
+                       *value = rdev->config.si.max_tile_pipes;
                else if (rdev->family >= CHIP_CAYMAN)
-                       value = rdev->config.cayman.max_tile_pipes;
+                       *value = rdev->config.cayman.max_tile_pipes;
                else if (rdev->family >= CHIP_CEDAR)
-                       value = rdev->config.evergreen.max_tile_pipes;
+                       *value = rdev->config.evergreen.max_tile_pipes;
                else if (rdev->family >= CHIP_RV770)
-                       value = rdev->config.rv770.max_tile_pipes;
+                       *value = rdev->config.rv770.max_tile_pipes;
                else if (rdev->family >= CHIP_R600)
-                       value = rdev->config.r600.max_tile_pipes;
+                       *value = rdev->config.r600.max_tile_pipes;
                else {
                        return -EINVAL;
                }
                break;
        case RADEON_INFO_FUSION_GART_WORKING:
-               value = 1;
+               *value = 1;
                break;
        case RADEON_INFO_BACKEND_MAP:
                if (rdev->family >= CHIP_TAHITI)
-                       value = rdev->config.si.backend_map;
+                       *value = rdev->config.si.backend_map;
                else if (rdev->family >= CHIP_CAYMAN)
-                       value = rdev->config.cayman.backend_map;
+                       *value = rdev->config.cayman.backend_map;
                else if (rdev->family >= CHIP_CEDAR)
-                       value = rdev->config.evergreen.backend_map;
+                       *value = rdev->config.evergreen.backend_map;
                else if (rdev->family >= CHIP_RV770)
-                       value = rdev->config.rv770.backend_map;
+                       *value = rdev->config.rv770.backend_map;
                else if (rdev->family >= CHIP_R600)
-                       value = rdev->config.r600.backend_map;
+                       *value = rdev->config.r600.backend_map;
                else {
                        return -EINVAL;
                }
@@ -337,50 +330,67 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
                /* this is where we report if vm is supported or not */
                if (rdev->family < CHIP_CAYMAN)
                        return -EINVAL;
-               value = RADEON_VA_RESERVED_SIZE;
+               *value = RADEON_VA_RESERVED_SIZE;
                break;
        case RADEON_INFO_IB_VM_MAX_SIZE:
                /* this is where we report if vm is supported or not */
                if (rdev->family < CHIP_CAYMAN)
                        return -EINVAL;
-               value = RADEON_IB_VM_MAX_SIZE;
+               *value = RADEON_IB_VM_MAX_SIZE;
                break;
        case RADEON_INFO_MAX_PIPES:
                if (rdev->family >= CHIP_TAHITI)
-                       value = rdev->config.si.max_cu_per_sh;
+                       *value = rdev->config.si.max_cu_per_sh;
                else if (rdev->family >= CHIP_CAYMAN)
-                       value = rdev->config.cayman.max_pipes_per_simd;
+                       *value = rdev->config.cayman.max_pipes_per_simd;
                else if (rdev->family >= CHIP_CEDAR)
-                       value = rdev->config.evergreen.max_pipes;
+                       *value = rdev->config.evergreen.max_pipes;
                else if (rdev->family >= CHIP_RV770)
-                       value = rdev->config.rv770.max_pipes;
+                       *value = rdev->config.rv770.max_pipes;
                else if (rdev->family >= CHIP_R600)
-                       value = rdev->config.r600.max_pipes;
+                       *value = rdev->config.r600.max_pipes;
                else {
                        return -EINVAL;
                }
                break;
+       case RADEON_INFO_TIMESTAMP:
+               if (rdev->family < CHIP_R600) {
+                       DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
+                       return -EINVAL;
+               }
+               value = (uint32_t*)&value64;
+               value_size = sizeof(uint64_t);
+               value64 = radeon_get_gpu_clock_counter(rdev);
+               break;
        case RADEON_INFO_MAX_SE:
                if (rdev->family >= CHIP_TAHITI)
-                       value = rdev->config.si.max_shader_engines;
+                       *value = rdev->config.si.max_shader_engines;
                else if (rdev->family >= CHIP_CAYMAN)
-                       value = rdev->config.cayman.max_shader_engines;
+                       *value = rdev->config.cayman.max_shader_engines;
                else if (rdev->family >= CHIP_CEDAR)
-                       value = rdev->config.evergreen.num_ses;
+                       *value = rdev->config.evergreen.num_ses;
                else
-                       value = 1;
+                       *value = 1;
                break;
        case RADEON_INFO_MAX_SH_PER_SE:
                if (rdev->family >= CHIP_TAHITI)
-                       value = rdev->config.si.max_sh_per_se;
+                       *value = rdev->config.si.max_sh_per_se;
                else
                        return -EINVAL;
                break;
+       case RADEON_INFO_SI_TILE_MODE_ARRAY:
+               if (rdev->family < CHIP_TAHITI) {
+                       DRM_DEBUG_KMS("tile mode array is si only!\n");
+                       return -EINVAL;
+               }
+               value = rdev->config.si.tile_mode_array;
+               value_size = sizeof(uint32_t)*32;
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
        }
-       if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) {
+       if (DRM_COPY_TO_USER(value_ptr, value, value_size)) {
                DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
                return -EFAULT;
        }
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 9128120..3cee0b2 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -1211,6 +1211,7 @@ static void si_tiling_mode_table_init(struct 
radeon_device *rdev)
                                gb_tile_moden = 0;
                                break;
                        }
+                       rdev->config.si.tile_mode_array[reg_offset] = 
gb_tile_moden;
                        WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden);
                }
        } else if ((rdev->family == CHIP_VERDE) ||
@@ -1451,6 +1452,7 @@ static void si_tiling_mode_table_init(struct 
radeon_device *rdev)
                                gb_tile_moden = 0;
                                break;
                        }
+                       rdev->config.si.tile_mode_array[reg_offset] = 
gb_tile_moden;
                        WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden);
                }
        } else
diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
index eeda917..db5049c 100644
--- a/include/uapi/drm/radeon_drm.h
+++ b/include/uapi/drm/radeon_drm.h
@@ -972,6 +972,8 @@ struct drm_radeon_cs {
 #define RADEON_INFO_MAX_SE             0x12
 /* max SH per SE */
 #define RADEON_INFO_MAX_SH_PER_SE      0x13
+/* SI tile mode array */
+#define RADEON_INFO_SI_TILE_MODE_ARRAY 0x14

 struct drm_radeon_info {
        uint32_t                request;
@@ -979,4 +981,22 @@ struct drm_radeon_info {
        uint64_t                value;
 };

+/* Those correspond to the tile index to use, this is to explicitly state
+ * the API that is implicitly defined by the tile mode array.
+ */
+#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED      8
+#define SI_TILE_MODE_COLOR_1D                  13
+#define SI_TILE_MODE_COLOR_1D_SCANOUT          9
+#define SI_TILE_MODE_COLOR_2D_8BPP             14
+#define SI_TILE_MODE_COLOR_2D_16BPP            15
+#define SI_TILE_MODE_COLOR_2D_32BPP            16
+#define SI_TILE_MODE_COLOR_2D_64BPP            17
+#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP    11
+#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP    12
+#define SI_TILE_MODE_DEPTH_STENCIL_1D          4
+#define SI_TILE_MODE_DEPTH_STENCIL_2D          0
+#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA      3
+#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA      3
+#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA      2
+
 #endif
-- 
1.8.1.4

Reply via email to