diff options
Diffstat (limited to 'src/gallium/winsys/r600/drm/r600_drm.c')
-rw-r--r-- | src/gallium/winsys/r600/drm/r600_drm.c | 219 |
1 files changed, 218 insertions, 1 deletions
diff --git a/src/gallium/winsys/r600/drm/r600_drm.c b/src/gallium/winsys/r600/drm/r600_drm.c index 7a1a762f54..c9de95ffc0 100644 --- a/src/gallium/winsys/r600/drm/r600_drm.c +++ b/src/gallium/winsys/r600/drm/r600_drm.c @@ -25,14 +25,231 @@ * Corbin Simpson <MostAwesomeDude@gmail.com> * Joakim Sindholt <opensource@zhasha.com> */ +#include <stdio.h> +#include <errno.h> #include <sys/ioctl.h> #include "util/u_inlines.h" #include "util/u_debug.h" -#include "radeon_priv.h" +#include <pipebuffer/pb_bufmgr.h> +#include "r600.h" +#include "r600_priv.h" #include "r600_drm_public.h" +#include "xf86drm.h" +#include "radeon_drm.h" + +#ifndef RADEON_INFO_TILING_CONFIG +#define RADEON_INFO_TILING_CONFIG 0x6 +#endif +static int radeon_get_device(struct radeon *radeon) +{ + struct drm_radeon_info info; + int r; + + radeon->device = 0; + info.request = RADEON_INFO_DEVICE_ID; + info.value = (uintptr_t)&radeon->device; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + return r; +} + +static int radeon_drm_get_tiling(struct radeon *radeon) +{ + struct drm_radeon_info info; + int r; + uint32_t tiling_config; + + info.request = RADEON_INFO_TILING_CONFIG; + info.value = (uintptr_t)&tiling_config; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + + if (r) + return r; + + switch ((tiling_config & 0xe) >> 1) { + case 0: + radeon->tiling_info.num_channels = 1; + break; + case 1: + radeon->tiling_info.num_channels = 2; + break; + case 2: + radeon->tiling_info.num_channels = 4; + break; + case 3: + radeon->tiling_info.num_channels = 8; + break; + default: + return -EINVAL; + } + + switch ((tiling_config & 0x30) >> 4) { + case 0: + radeon->tiling_info.num_banks = 4; + break; + case 1: + radeon->tiling_info.num_banks = 8; + break; + default: + return -EINVAL; + + } + switch ((tiling_config & 0xc0) >> 6) { + case 0: + radeon->tiling_info.group_bytes = 256; + break; + case 1: + radeon->tiling_info.group_bytes = 512; + break; + default: + return -EINVAL; + } + return 0; +} + +struct radeon *radeon_new(int fd, unsigned device) +{ + struct radeon *radeon; + int r; + + radeon = calloc(1, sizeof(*radeon)); + if (radeon == NULL) { + return NULL; + } + radeon->fd = fd; + radeon->device = device; + radeon->refcount = 1; + if (fd >= 0) { + r = radeon_get_device(radeon); + if (r) { + fprintf(stderr, "Failed to get device id\n"); + return radeon_decref(radeon); + } + } + radeon->family = radeon_family_from_device(radeon->device); + if (radeon->family == CHIP_UNKNOWN) { + fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->device); + return radeon_decref(radeon); + } + switch (radeon->family) { + case CHIP_R600: + case CHIP_RV610: + case CHIP_RV630: + case CHIP_RV670: + case CHIP_RV620: + case CHIP_RV635: + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + case CHIP_RV740: + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_JUNIPER: + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + break; + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + case CHIP_R200: + case CHIP_RV250: + case CHIP_RS300: + case CHIP_RV280: + case CHIP_R300: + case CHIP_R350: + case CHIP_RV350: + case CHIP_RV380: + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: + case CHIP_RS400: + case CHIP_RS480: + case CHIP_RS600: + case CHIP_RS690: + case CHIP_RS740: + case CHIP_RV515: + case CHIP_R520: + case CHIP_RV530: + case CHIP_RV560: + case CHIP_RV570: + case CHIP_R580: + default: + fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n", + __func__, radeon->device); + break; + } + + /* setup class */ + switch (radeon->family) { + case CHIP_R600: + case CHIP_RV610: + case CHIP_RV630: + case CHIP_RV670: + case CHIP_RV620: + case CHIP_RV635: + case CHIP_RS780: + case CHIP_RS880: + radeon->chip_class = R600; + break; + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + case CHIP_RV740: + radeon->chip_class = R700; + break; + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_JUNIPER: + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + radeon->chip_class = EVERGREEN; + break; + default: + fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n", + __func__, radeon->device); + break; + } + + if (radeon->chip_class == R600 || radeon->chip_class == R700) { + if (radeon_drm_get_tiling(radeon)) + return NULL; + } + radeon->kman = radeon_bo_pbmgr_create(radeon); + if (!radeon->kman) + return NULL; + radeon->cman = pb_cache_manager_create(radeon->kman, 100000); + if (!radeon->cman) + return NULL; + return radeon; +} struct radeon *r600_drm_winsys_create(int drmfd) { return radeon_new(drmfd, 0); } +struct radeon *radeon_decref(struct radeon *radeon) +{ + if (radeon == NULL) + return NULL; + if (--radeon->refcount > 0) { + return NULL; + } + + if (radeon->cman) + radeon->cman->destroy(radeon->cman); + + if (radeon->kman) + radeon->kman->destroy(radeon->kman); + + if (radeon->fd >= 0) + drmClose(radeon->fd); + + free(radeon); + return NULL; +} |