drm/radeon: add si tile mode array query v3
authorJerome Glisse <jglisse@redhat.com>
Tue, 9 Apr 2013 15:17:08 +0000 (11:17 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 11 Apr 2013 13:22:06 +0000 (09:22 -0400)
Allow userspace to query for the tile mode array so userspace can properly
compute surface pitch and alignment requirement depending on tiling.

v2: Make strict aliasing safer by casting to char when copying
v3: merge fix from Christian

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/si.c
include/uapi/drm/radeon_drm.h

index 394b20fa27dcf61bd5bd55672a848534567c9a3c..18904fb83d3aaf14445db319ca09f36e01aa013c 100644 (file)
@@ -1483,6 +1483,7 @@ struct si_asic {
        unsigned multi_gpu_tile_size;
 
        unsigned tile_config;
+       uint32_t tile_mode_array[32];
 };
 
 union radeon_asic_config {
index 6e1b2e66e837fd9a28e550a8023a4660c3d87939..d33f484ace48792d746e812d81fd84d56ce5d4b8 100644 (file)
  *   2.30.0 - fix for FMASK texturing
  *   2.31.0 - Add fastfb support for rs690
  *   2.32.0 - new info request for rings working
+ *   2.33.0 - Add SI tiling mode array query
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       32
+#define KMS_DRIVER_MINOR       33
 #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);
index 3037c38d9aa9b99b097ce692c3e70a73f3b9bef4..a24b9ba4de73090023a56713a2d054cb4a88f544 100644 (file)
@@ -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,70 +330,91 @@ 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_FASTFB_WORKING:
-               value = rdev->fastfb_working;
+               *value = rdev->fastfb_working;
                break;
        case RADEON_INFO_RING_WORKING:
-               switch (value) {
+               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+                       DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
+                       return -EFAULT;
+               }
+               switch (*value) {
                case RADEON_CS_RING_GFX:
                case RADEON_CS_RING_COMPUTE:
-                       value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready;
+                       *value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready;
                        break;
                case RADEON_CS_RING_DMA:
-                       value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready;
-                       value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready;
+                       *value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready;
+                       *value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready;
                        break;
                case RADEON_CS_RING_UVD:
-                       value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
+                       *value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
                        break;
                default:
                        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, (char*)value, value_size)) {
                DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
                return -EFAULT;
        }
index 7eda8303379f6548d8b248543c8817f5aa8897af..aa2c555ba87777ec1cce7e107ef5c2b4a9faba31 100644 (file)
@@ -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
index 05ed0107584d7669c922a0b641cd8622e81cdcbc..321d4ac5c5128ba58aafafb1d7b624ce25980461 100644 (file)
@@ -977,6 +977,8 @@ struct drm_radeon_cs {
 #define RADEON_INFO_FASTFB_WORKING     0x14
 /* query if a RADEON_CS_RING_* submission is supported */
 #define RADEON_INFO_RING_WORKING       0x15
+/* SI tile mode array */
+#define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16
 
 
 struct drm_radeon_info {
@@ -985,4 +987,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