1 /* 2 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe (at) gmail.com> 3 * Copyright (C) 2010-2011 LunarG Inc. 4 * 5 * Based on xf86-video-ati, which has 6 * 7 * Copyright 2009 Red Hat, Inc. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 */ 27 28 /* XXX This driver assumes evergreen. */ 29 30 #define LOG_TAG "GRALLOC-RADEON" 31 32 #include <cutils/log.h> 33 #include <stdlib.h> 34 #include <errno.h> 35 #include <drm.h> 36 #include <radeon_drm.h> 37 #include <radeon_bo_gem.h> 38 #include <radeon_bo.h> 39 40 #include "gralloc_drm.h" 41 #include "gralloc_drm_priv.h" 42 43 #include "radeon/radeon.h" 44 #include "radeon/radeon_chipinfo_gen.h" 45 46 #define RADEON_GPU_PAGE_SIZE 4096 47 48 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 49 50 struct radeon_info { 51 struct gralloc_drm_drv_t base; 52 53 int fd; 54 struct radeon_bo_manager *bufmgr; 55 56 uint32_t chipset; 57 RADEONChipFamily chip_family; 58 int is_mobility; 59 int is_igp; 60 61 uint32_t tile_config; 62 int num_channels; 63 int num_banks; 64 int group_bytes; 65 /* r6xx+ tile config */ 66 int have_tiling_info; 67 68 int allow_color_tiling; 69 70 int vram_size; 71 int gart_size; 72 }; 73 74 struct radeon_buffer { 75 struct gralloc_drm_bo_t base; 76 77 struct radeon_bo *rbo; 78 }; 79 80 /* returns pitch alignment in pixels */ 81 static int radeon_get_pitch_align(struct radeon_info *info, int bpe, uint32_t tiling) 82 { 83 int pitch_align = 1; 84 85 if (info->chip_family >= CHIP_FAMILY_R600) { 86 if (tiling & RADEON_TILING_MACRO) { 87 /* general surface requirements */ 88 pitch_align = (((info->group_bytes / 8) / bpe) * 89 info->num_banks) * 8; 90 /* further restrictions for scanout */ 91 pitch_align = MAX(info->num_banks * 8, pitch_align); 92 } else if (tiling & RADEON_TILING_MICRO) { 93 /* general surface requirements */ 94 pitch_align = MAX(8, (info->group_bytes / (8 * bpe))); 95 /* further restrictions for scanout */ 96 pitch_align = MAX(info->group_bytes / bpe, pitch_align); 97 } else { 98 if (info->have_tiling_info) 99 /* linear aligned requirements */ 100 pitch_align = MAX(64, info->group_bytes / bpe); 101 else 102 /* default to 512 elements if we don't know the real 103 * group size otherwise the kernel may reject the CS 104 * if the group sizes don't match as the pitch won't 105 * be aligned properly. 106 */ 107 pitch_align = 512; 108 } 109 } 110 else { 111 /* general surface requirements */ 112 if (tiling) 113 pitch_align = 256 / bpe; 114 else 115 pitch_align = 64; 116 } 117 118 return pitch_align; 119 } 120 121 /* returns height alignment in pixels */ 122 static int radeon_get_height_align(struct radeon_info *info, uint32_t tiling) 123 { 124 int height_align = 1; 125 126 if (info->chip_family >= CHIP_FAMILY_R600) { 127 if (tiling & RADEON_TILING_MACRO) 128 height_align = info->num_channels * 8; 129 else if (tiling & RADEON_TILING_MICRO) 130 height_align = 8; 131 else 132 height_align = 8; 133 } 134 else { 135 if (tiling) 136 height_align = 16; 137 else 138 height_align = 1; 139 } 140 141 return height_align; 142 } 143 144 /* returns base alignment in bytes */ 145 static int radeon_get_base_align(struct radeon_info *info, 146 int bpe, uint32_t tiling) 147 { 148 int pixel_align = radeon_get_pitch_align(info, bpe, tiling); 149 int height_align = radeon_get_height_align(info, tiling); 150 int base_align = RADEON_GPU_PAGE_SIZE; 151 152 if (info->chip_family >= CHIP_FAMILY_R600) { 153 if (tiling & RADEON_TILING_MACRO) 154 base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe, 155 pixel_align * bpe * height_align); 156 else { 157 if (info->have_tiling_info) 158 base_align = info->group_bytes; 159 else 160 /* default to 512 if we don't know the real 161 * group size otherwise the kernel may reject the CS 162 * if the group sizes don't match as the base won't 163 * be aligned properly. 164 */ 165 base_align = 512; 166 } 167 } 168 return base_align; 169 } 170 171 static uint32_t radeon_get_tiling(struct radeon_info *info, 172 const struct gralloc_drm_handle_t *handle) 173 { 174 int sw = (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK); 175 176 if ((handle->usage & sw) && !info->allow_color_tiling) 177 return 0; 178 179 if (info->chip_family >= CHIP_FAMILY_R600) 180 return RADEON_TILING_MICRO; 181 else 182 return RADEON_TILING_MACRO; 183 } 184 185 static struct radeon_bo *radeon_alloc(struct radeon_info *info, 186 struct gralloc_drm_handle_t *handle) 187 { 188 struct radeon_bo *rbo; 189 int aligned_width, aligned_height; 190 int pitch, size, base_align; 191 uint32_t tiling, domain; 192 int cpp; 193 194 cpp = gralloc_drm_get_bpp(handle->format); 195 if (!cpp) { 196 ALOGE("unrecognized format 0x%x", handle->format); 197 return NULL; 198 } 199 200 tiling = radeon_get_tiling(info, handle); 201 domain = RADEON_GEM_DOMAIN_VRAM; 202 203 aligned_width = handle->width; 204 aligned_height = handle->height; 205 gralloc_drm_align_geometry(handle->format, 206 &aligned_width, &aligned_height); 207 208 if (handle->usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_TEXTURE)) { 209 aligned_width = ALIGN(aligned_width, 210 radeon_get_pitch_align(info, cpp, tiling)); 211 aligned_height = ALIGN(aligned_height, 212 radeon_get_height_align(info, tiling)); 213 } 214 215 if (!(handle->usage & (GRALLOC_USAGE_HW_FB | 216 GRALLOC_USAGE_HW_RENDER)) && 217 (handle->usage & GRALLOC_USAGE_SW_READ_OFTEN)) 218 domain = RADEON_GEM_DOMAIN_GTT; 219 220 pitch = aligned_width * cpp; 221 size = ALIGN(aligned_height * pitch, RADEON_GPU_PAGE_SIZE); 222 base_align = radeon_get_base_align(info, cpp, tiling); 223 224 rbo = radeon_bo_open(info->bufmgr, 0, size, base_align, domain, 0); 225 if (!rbo) { 226 ALOGE("failed to allocate rbo %dx%dx%d", 227 handle->width, handle->height, cpp); 228 return NULL; 229 } 230 231 if (tiling) 232 radeon_bo_set_tiling(rbo, tiling, pitch); 233 234 if (radeon_gem_get_kernel_name(rbo, 235 (uint32_t *) &handle->name)) { 236 ALOGE("failed to flink rbo"); 237 radeon_bo_unref(rbo); 238 return NULL; 239 } 240 241 handle->stride = pitch; 242 243 return rbo; 244 } 245 246 static void radeon_zero(struct radeon_info *info, 247 struct radeon_bo *rbo) 248 { 249 /* should use HW clear... */ 250 if (!radeon_bo_map(rbo, 1)) { 251 memset(rbo->ptr, 0, rbo->size); 252 radeon_bo_unmap(rbo); 253 } 254 } 255 256 static struct gralloc_drm_bo_t * 257 drm_gem_radeon_alloc(struct gralloc_drm_drv_t *drv, struct gralloc_drm_handle_t *handle) 258 { 259 struct radeon_info *info = (struct radeon_info *) drv; 260 struct radeon_buffer *rbuf; 261 262 rbuf = calloc(1, sizeof(*rbuf)); 263 if (!rbuf) 264 return NULL; 265 266 if (handle->name) { 267 rbuf->rbo = radeon_bo_open(info->bufmgr, 268 handle->name, 0, 0, 0, 0); 269 if (!rbuf->rbo) { 270 ALOGE("failed to create rbo from name %u", 271 handle->name); 272 free(rbuf); 273 return NULL; 274 } 275 } 276 else { 277 rbuf->rbo = radeon_alloc(info, handle); 278 if (!rbuf->rbo) { 279 free(rbuf); 280 return NULL; 281 } 282 283 /* Android expects the buffer to be zeroed */ 284 radeon_zero(info, rbuf->rbo); 285 } 286 287 if (handle->usage & GRALLOC_USAGE_HW_FB) 288 rbuf->base.fb_handle = rbuf->rbo->handle; 289 290 rbuf->base.handle = handle; 291 292 return &rbuf->base; 293 } 294 295 static void drm_gem_radeon_free(struct gralloc_drm_drv_t *drv, 296 struct gralloc_drm_bo_t *bo) 297 { 298 struct radeon_buffer *rbuf = (struct radeon_buffer *) bo; 299 radeon_bo_unref(rbuf->rbo); 300 } 301 302 static int drm_gem_radeon_map(struct gralloc_drm_drv_t *drv, 303 struct gralloc_drm_bo_t *bo, int x, int y, int w, int h, 304 int enable_write, void **addr) 305 { 306 struct radeon_buffer *rbuf = (struct radeon_buffer *) bo; 307 int err; 308 309 err = radeon_bo_map(rbuf->rbo, enable_write); 310 if (!err) 311 *addr = rbuf->rbo->ptr; 312 313 return err; 314 } 315 316 static void drm_gem_radeon_unmap(struct gralloc_drm_drv_t *drv, 317 struct gralloc_drm_bo_t *bo) 318 { 319 struct radeon_buffer *rbuf = (struct radeon_buffer *) bo; 320 radeon_bo_unmap(rbuf->rbo); 321 } 322 323 static void drm_gem_radeon_destroy(struct gralloc_drm_drv_t *drv) 324 { 325 struct radeon_info *info = (struct radeon_info *) drv; 326 327 radeon_bo_manager_gem_dtor(info->bufmgr); 328 free(info); 329 } 330 331 static int radeon_init_tile_config(struct radeon_info *info) 332 { 333 struct drm_radeon_info ginfo; 334 uint32_t val; 335 int ret; 336 337 memset(&ginfo, 0, sizeof(ginfo)); 338 ginfo.request = RADEON_INFO_TILING_CONFIG; 339 ginfo.value = (long) &val; 340 ret = drmCommandWriteRead(info->fd, DRM_RADEON_INFO, 341 &ginfo, sizeof(ginfo)); 342 if (ret) 343 return ret; 344 345 info->tile_config = val; 346 347 if (info->chip_family >= CHIP_FAMILY_CEDAR) { 348 switch (info->tile_config & 0xf) { 349 case 0: 350 info->num_channels = 1; 351 break; 352 case 1: 353 info->num_channels = 2; 354 break; 355 case 2: 356 info->num_channels = 4; 357 break; 358 case 3: 359 info->num_channels = 8; 360 break; 361 default: 362 return -EINVAL; 363 break; 364 } 365 366 switch ((info->tile_config & 0xf0) >> 4) { 367 case 0: 368 info->num_banks = 4; 369 break; 370 case 1: 371 info->num_banks = 8; 372 break; 373 case 2: 374 info->num_banks = 16; 375 break; 376 default: 377 return -EINVAL; 378 break; 379 } 380 381 switch ((info->tile_config & 0xf00) >> 8) { 382 case 0: 383 info->group_bytes = 256; 384 break; 385 case 1: 386 info->group_bytes = 512; 387 break; 388 default: 389 return -EINVAL; 390 break; 391 } 392 } 393 else { 394 switch ((info->tile_config & 0xe) >> 1) { 395 case 0: 396 info->num_channels = 1; 397 break; 398 case 1: 399 info->num_channels = 2; 400 break; 401 case 2: 402 info->num_channels = 4; 403 break; 404 case 3: 405 info->num_channels = 8; 406 break; 407 default: 408 return -EINVAL; 409 break; 410 } 411 412 switch ((info->tile_config & 0x30) >> 4) { 413 case 0: 414 info->num_banks = 4; 415 break; 416 case 1: 417 info->num_banks = 8; 418 break; 419 default: 420 return -EINVAL; 421 break; 422 } 423 424 switch ((info->tile_config & 0xc0) >> 6) { 425 case 0: 426 info->group_bytes = 256; 427 break; 428 case 1: 429 info->group_bytes = 512; 430 break; 431 default: 432 return -EINVAL; 433 break; 434 } 435 } 436 437 info->have_tiling_info = 1; 438 439 return 0; 440 } 441 442 static int radeon_probe(struct radeon_info *info) 443 { 444 struct drm_radeon_info kinfo; 445 struct drm_radeon_gem_info mminfo; 446 unsigned int i; 447 int err; 448 449 memset(&kinfo, 0, sizeof(kinfo)); 450 kinfo.request = RADEON_INFO_DEVICE_ID; 451 kinfo.value = (long) &info->chipset; 452 err = drmCommandWriteRead(info->fd, DRM_RADEON_INFO, &kinfo, sizeof(kinfo)); 453 if (err) { 454 ALOGE("failed to get device id"); 455 return err; 456 } 457 458 for (i = 0; i < sizeof(RADEONCards) / sizeof(RADEONCards[0]); i++) { 459 const RADEONCardInfo *card = &RADEONCards[i]; 460 461 if (info->chipset == card->pci_device_id) { 462 info->chip_family = card->chip_family; 463 info->is_mobility = card->mobility; 464 info->is_igp = card->igp; 465 break; 466 } 467 } 468 469 if (info->chip_family == CHIP_FAMILY_UNKNOW) { 470 ALOGE("unknown device id 0x%04x", info->chipset); 471 return -EINVAL; 472 } 473 474 if (info->chip_family >= CHIP_FAMILY_R600) { 475 err = radeon_init_tile_config(info); 476 if (err) { 477 ALOGE("failed to get tiling config"); 478 return err; 479 } 480 } else { 481 /* No tiling config for family older than 06xx */ 482 info->have_tiling_info = 0; 483 } 484 485 /* CPU cannot handle tiled buffers (need scratch buffers) */ 486 info->allow_color_tiling = 0; 487 488 memset(&mminfo, 0, sizeof(mminfo)); 489 err = drmCommandWriteRead(info->fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)); 490 if (err) { 491 ALOGE("failed to get gem info"); 492 return err; 493 } 494 495 info->vram_size = mminfo.vram_visible; 496 info->gart_size = mminfo.gart_size; 497 498 ALOGI("detected chipset 0x%04x family 0x%02x (vram size %dMiB, gart size %dMiB)", 499 info->chipset, info->chip_family, 500 info->vram_size / 1024 / 1024, 501 info->gart_size / 1024 / 1024); 502 503 return 0; 504 } 505 506 struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_radeon(int fd) 507 { 508 struct radeon_info *info; 509 510 info = calloc(1, sizeof(*info)); 511 if (!info) 512 return NULL; 513 514 info->fd = fd; 515 if (radeon_probe(info)) { 516 free(info); 517 return NULL; 518 } 519 520 info->bufmgr = radeon_bo_manager_gem_ctor(info->fd); 521 if (!info->bufmgr) { 522 ALOGE("failed to create buffer manager"); 523 free(info); 524 return NULL; 525 } 526 527 info->base.destroy = drm_gem_radeon_destroy; 528 info->base.alloc = drm_gem_radeon_alloc; 529 info->base.free = drm_gem_radeon_free; 530 info->base.map = drm_gem_radeon_map; 531 info->base.unmap = drm_gem_radeon_unmap; 532 533 return &info->base; 534 } 535