1 /* 2 * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 #ifdef DRV_I915 8 9 #include <assert.h> 10 #include <errno.h> 11 #include <i915_drm.h> 12 #include <stdbool.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <sys/mman.h> 16 #include <xf86drm.h> 17 18 #include "drv_priv.h" 19 #include "helpers.h" 20 #include "util.h" 21 22 #define I915_CACHELINE_SIZE 64 23 #define I915_CACHELINE_MASK (I915_CACHELINE_SIZE - 1) 24 25 static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB1555, 26 DRM_FORMAT_ARGB8888, DRM_FORMAT_BGR888, 27 DRM_FORMAT_RGB565, DRM_FORMAT_XBGR2101010, 28 DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB1555, 29 DRM_FORMAT_XRGB2101010, DRM_FORMAT_XRGB8888 }; 30 31 static const uint32_t tileable_texture_source_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_R8, 32 DRM_FORMAT_UYVY, DRM_FORMAT_YUYV }; 33 34 static const uint32_t texture_source_formats[] = { DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID, 35 DRM_FORMAT_NV12 }; 36 37 struct i915_device { 38 uint32_t gen; 39 int32_t has_llc; 40 }; 41 42 static uint32_t i915_get_gen(int device_id) 43 { 44 const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE, 45 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 }; 46 unsigned i; 47 for (i = 0; i < ARRAY_SIZE(gen3_ids); i++) 48 if (gen3_ids[i] == device_id) 49 return 3; 50 51 return 4; 52 } 53 54 /* 55 * We allow allocation of ARGB formats for SCANOUT if the corresponding XRGB 56 * formats supports it. It's up to the caller (chrome ozone) to ultimately not 57 * scan out ARGB if the display controller only supports XRGB, but we'll allow 58 * the allocation of the bo here. 59 */ 60 static bool format_compatible(const struct combination *combo, uint32_t format) 61 { 62 if (combo->format == format) 63 return true; 64 65 switch (format) { 66 case DRM_FORMAT_XRGB8888: 67 return combo->format == DRM_FORMAT_ARGB8888; 68 case DRM_FORMAT_XBGR8888: 69 return combo->format == DRM_FORMAT_ABGR8888; 70 case DRM_FORMAT_RGBX8888: 71 return combo->format == DRM_FORMAT_RGBA8888; 72 case DRM_FORMAT_BGRX8888: 73 return combo->format == DRM_FORMAT_BGRA8888; 74 default: 75 return false; 76 } 77 } 78 79 static int i915_add_kms_item(struct driver *drv, const struct kms_item *item) 80 { 81 uint32_t i; 82 struct combination *combo; 83 84 /* 85 * Older hardware can't scanout Y-tiled formats. Newer devices can, and 86 * report this functionality via format modifiers. 87 */ 88 for (i = 0; i < drv_array_size(drv->combos); i++) { 89 combo = (struct combination *)drv_array_at_idx(drv->combos, i); 90 if (!format_compatible(combo, item->format)) 91 continue; 92 93 if (item->modifier == DRM_FORMAT_MOD_LINEAR && 94 combo->metadata.tiling == I915_TILING_X) { 95 /* 96 * FIXME: drv_query_kms() does not report the available modifiers 97 * yet, but we know that all hardware can scanout from X-tiled 98 * buffers, so let's add this to our combinations, except for 99 * cursor, which must not be tiled. 100 */ 101 combo->use_flags |= item->use_flags & ~BO_USE_CURSOR; 102 } 103 104 /* If we can scanout NV12, we support all tiling modes. */ 105 if (item->format == DRM_FORMAT_NV12) 106 combo->use_flags |= item->use_flags; 107 108 if (combo->metadata.modifier == item->modifier) 109 combo->use_flags |= item->use_flags; 110 } 111 112 return 0; 113 } 114 115 static int i915_add_combinations(struct driver *drv) 116 { 117 int ret; 118 uint32_t i; 119 struct drv_array *kms_items; 120 struct format_metadata metadata; 121 uint64_t render_use_flags, texture_use_flags; 122 123 render_use_flags = BO_USE_RENDER_MASK; 124 texture_use_flags = BO_USE_TEXTURE_MASK; 125 126 metadata.tiling = I915_TILING_NONE; 127 metadata.priority = 1; 128 metadata.modifier = DRM_FORMAT_MOD_LINEAR; 129 130 drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 131 &metadata, render_use_flags); 132 133 drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), 134 &metadata, texture_use_flags); 135 136 drv_add_combinations(drv, tileable_texture_source_formats, 137 ARRAY_SIZE(tileable_texture_source_formats), &metadata, 138 texture_use_flags); 139 140 drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 141 drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 142 143 /* IPU3 camera ISP supports only NV12 output. */ 144 drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, 145 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); 146 /* 147 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots 148 * from camera. 149 */ 150 drv_modify_combination(drv, DRM_FORMAT_R8, &metadata, 151 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); 152 153 render_use_flags &= ~BO_USE_RENDERSCRIPT; 154 render_use_flags &= ~BO_USE_SW_WRITE_OFTEN; 155 render_use_flags &= ~BO_USE_SW_READ_OFTEN; 156 render_use_flags &= ~BO_USE_LINEAR; 157 158 texture_use_flags &= ~BO_USE_RENDERSCRIPT; 159 texture_use_flags &= ~BO_USE_SW_WRITE_OFTEN; 160 texture_use_flags &= ~BO_USE_SW_READ_OFTEN; 161 texture_use_flags &= ~BO_USE_LINEAR; 162 163 metadata.tiling = I915_TILING_X; 164 metadata.priority = 2; 165 metadata.modifier = I915_FORMAT_MOD_X_TILED; 166 167 drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 168 &metadata, render_use_flags); 169 170 drv_add_combinations(drv, tileable_texture_source_formats, 171 ARRAY_SIZE(tileable_texture_source_formats), &metadata, 172 texture_use_flags); 173 174 metadata.tiling = I915_TILING_Y; 175 metadata.priority = 3; 176 metadata.modifier = I915_FORMAT_MOD_Y_TILED; 177 178 drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 179 &metadata, render_use_flags); 180 181 drv_add_combinations(drv, tileable_texture_source_formats, 182 ARRAY_SIZE(tileable_texture_source_formats), &metadata, 183 texture_use_flags); 184 185 /* Support y-tiled NV12 for libva */ 186 const uint32_t nv12_format = DRM_FORMAT_NV12; 187 drv_add_combinations(drv, &nv12_format, 1, &metadata, 188 BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER); 189 190 kms_items = drv_query_kms(drv); 191 if (!kms_items) 192 return 0; 193 194 for (i = 0; i < drv_array_size(kms_items); i++) { 195 ret = i915_add_kms_item(drv, (struct kms_item *)drv_array_at_idx(kms_items, i)); 196 if (ret) { 197 drv_array_destroy(kms_items); 198 return ret; 199 } 200 } 201 202 drv_array_destroy(kms_items); 203 return 0; 204 } 205 206 static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *stride, 207 uint32_t *aligned_height) 208 { 209 struct i915_device *i915 = bo->drv->priv; 210 uint32_t horizontal_alignment; 211 uint32_t vertical_alignment; 212 213 switch (tiling) { 214 default: 215 case I915_TILING_NONE: 216 /* 217 * The Intel GPU doesn't need any alignment in linear mode, 218 * but libva requires the allocation stride to be aligned to 219 * 16 bytes and height to 4 rows. Further, we round up the 220 * horizontal alignment so that row start on a cache line (64 221 * bytes). 222 */ 223 horizontal_alignment = 64; 224 vertical_alignment = 4; 225 break; 226 227 case I915_TILING_X: 228 horizontal_alignment = 512; 229 vertical_alignment = 8; 230 break; 231 232 case I915_TILING_Y: 233 if (i915->gen == 3) { 234 horizontal_alignment = 512; 235 vertical_alignment = 8; 236 } else { 237 horizontal_alignment = 128; 238 vertical_alignment = 32; 239 } 240 break; 241 } 242 243 *aligned_height = ALIGN(bo->height, vertical_alignment); 244 if (i915->gen > 3) { 245 *stride = ALIGN(*stride, horizontal_alignment); 246 } else { 247 while (*stride > horizontal_alignment) 248 horizontal_alignment <<= 1; 249 250 *stride = horizontal_alignment; 251 } 252 253 if (i915->gen <= 3 && *stride > 8192) 254 return -EINVAL; 255 256 return 0; 257 } 258 259 static void i915_clflush(void *start, size_t size) 260 { 261 void *p = (void *)(((uintptr_t)start) & ~I915_CACHELINE_MASK); 262 void *end = (void *)((uintptr_t)start + size); 263 264 __builtin_ia32_mfence(); 265 while (p < end) { 266 __builtin_ia32_clflush(p); 267 p = (void *)((uintptr_t)p + I915_CACHELINE_SIZE); 268 } 269 } 270 271 static int i915_init(struct driver *drv) 272 { 273 int ret; 274 int device_id; 275 struct i915_device *i915; 276 drm_i915_getparam_t get_param; 277 278 i915 = calloc(1, sizeof(*i915)); 279 if (!i915) 280 return -ENOMEM; 281 282 memset(&get_param, 0, sizeof(get_param)); 283 get_param.param = I915_PARAM_CHIPSET_ID; 284 get_param.value = &device_id; 285 ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param); 286 if (ret) { 287 drv_log("Failed to get I915_PARAM_CHIPSET_ID\n"); 288 free(i915); 289 return -EINVAL; 290 } 291 292 i915->gen = i915_get_gen(device_id); 293 294 memset(&get_param, 0, sizeof(get_param)); 295 get_param.param = I915_PARAM_HAS_LLC; 296 get_param.value = &i915->has_llc; 297 ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param); 298 if (ret) { 299 drv_log("Failed to get I915_PARAM_HAS_LLC\n"); 300 free(i915); 301 return -EINVAL; 302 } 303 304 drv->priv = i915; 305 306 return i915_add_combinations(drv); 307 } 308 309 static int i915_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, uint32_t format) 310 { 311 uint32_t offset; 312 size_t plane; 313 int ret; 314 315 offset = 0; 316 for (plane = 0; plane < drv_num_planes_from_format(format); plane++) { 317 uint32_t stride = drv_stride_from_format(format, width, plane); 318 uint32_t plane_height = drv_height_from_format(format, height, plane); 319 320 if (bo->tiling != I915_TILING_NONE) 321 assert(IS_ALIGNED(offset, 4096)); 322 323 ret = i915_align_dimensions(bo, bo->tiling, &stride, &plane_height); 324 if (ret) 325 return ret; 326 327 bo->strides[plane] = stride; 328 bo->sizes[plane] = stride * plane_height; 329 bo->offsets[plane] = offset; 330 offset += bo->sizes[plane]; 331 } 332 333 bo->total_size = offset; 334 335 return 0; 336 } 337 338 static int i915_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t height, 339 uint32_t format, uint64_t modifier) 340 { 341 int ret; 342 size_t plane; 343 struct drm_i915_gem_create gem_create; 344 struct drm_i915_gem_set_tiling gem_set_tiling; 345 346 switch (modifier) { 347 case DRM_FORMAT_MOD_LINEAR: 348 bo->tiling = I915_TILING_NONE; 349 break; 350 case I915_FORMAT_MOD_X_TILED: 351 bo->tiling = I915_TILING_X; 352 break; 353 case I915_FORMAT_MOD_Y_TILED: 354 bo->tiling = I915_TILING_Y; 355 break; 356 } 357 358 bo->format_modifiers[0] = modifier; 359 360 if (format == DRM_FORMAT_YVU420_ANDROID) { 361 /* 362 * We only need to be able to use this as a linear texture, 363 * which doesn't put any HW restrictions on how we lay it 364 * out. The Android format does require the stride to be a 365 * multiple of 16 and expects the Cr and Cb stride to be 366 * ALIGN(Y_stride / 2, 16), which we can make happen by 367 * aligning to 32 bytes here. 368 */ 369 uint32_t stride = ALIGN(width, 32); 370 drv_bo_from_format(bo, stride, height, format); 371 } else { 372 i915_bo_from_format(bo, width, height, format); 373 } 374 375 memset(&gem_create, 0, sizeof(gem_create)); 376 gem_create.size = bo->total_size; 377 378 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create); 379 if (ret) { 380 drv_log("DRM_IOCTL_I915_GEM_CREATE failed (size=%llu)\n", gem_create.size); 381 return ret; 382 } 383 384 for (plane = 0; plane < bo->num_planes; plane++) 385 bo->handles[plane].u32 = gem_create.handle; 386 387 memset(&gem_set_tiling, 0, sizeof(gem_set_tiling)); 388 gem_set_tiling.handle = bo->handles[0].u32; 389 gem_set_tiling.tiling_mode = bo->tiling; 390 gem_set_tiling.stride = bo->strides[0]; 391 392 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling); 393 if (ret) { 394 struct drm_gem_close gem_close; 395 memset(&gem_close, 0, sizeof(gem_close)); 396 gem_close.handle = bo->handles[0].u32; 397 drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); 398 399 drv_log("DRM_IOCTL_I915_GEM_SET_TILING failed with %d\n", errno); 400 return -errno; 401 } 402 403 return 0; 404 } 405 406 static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 407 uint64_t use_flags) 408 { 409 struct combination *combo; 410 411 combo = drv_get_combination(bo->drv, format, use_flags); 412 if (!combo) 413 return -EINVAL; 414 415 return i915_bo_create_for_modifier(bo, width, height, format, combo->metadata.modifier); 416 } 417 418 static int i915_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, 419 uint32_t format, const uint64_t *modifiers, uint32_t count) 420 { 421 static const uint64_t modifier_order[] = { 422 I915_FORMAT_MOD_Y_TILED, 423 I915_FORMAT_MOD_X_TILED, 424 DRM_FORMAT_MOD_LINEAR, 425 }; 426 uint64_t modifier; 427 428 modifier = drv_pick_modifier(modifiers, count, modifier_order, ARRAY_SIZE(modifier_order)); 429 430 return i915_bo_create_for_modifier(bo, width, height, format, modifier); 431 } 432 433 static void i915_close(struct driver *drv) 434 { 435 free(drv->priv); 436 drv->priv = NULL; 437 } 438 439 static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data) 440 { 441 int ret; 442 struct drm_i915_gem_get_tiling gem_get_tiling; 443 444 ret = drv_prime_bo_import(bo, data); 445 if (ret) 446 return ret; 447 448 /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */ 449 memset(&gem_get_tiling, 0, sizeof(gem_get_tiling)); 450 gem_get_tiling.handle = bo->handles[0].u32; 451 452 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling); 453 if (ret) { 454 drv_gem_bo_destroy(bo); 455 drv_log("DRM_IOCTL_I915_GEM_GET_TILING failed.\n"); 456 return ret; 457 } 458 459 bo->tiling = gem_get_tiling.tiling_mode; 460 return 0; 461 } 462 463 static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) 464 { 465 int ret; 466 void *addr; 467 468 if (bo->tiling == I915_TILING_NONE) { 469 struct drm_i915_gem_mmap gem_map; 470 memset(&gem_map, 0, sizeof(gem_map)); 471 472 if ((bo->use_flags & BO_USE_SCANOUT) && !(bo->use_flags & BO_USE_RENDERSCRIPT)) 473 gem_map.flags = I915_MMAP_WC; 474 475 gem_map.handle = bo->handles[0].u32; 476 gem_map.offset = 0; 477 gem_map.size = bo->total_size; 478 479 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map); 480 if (ret) { 481 drv_log("DRM_IOCTL_I915_GEM_MMAP failed\n"); 482 return MAP_FAILED; 483 } 484 485 addr = (void *)(uintptr_t)gem_map.addr_ptr; 486 } else { 487 struct drm_i915_gem_mmap_gtt gem_map; 488 memset(&gem_map, 0, sizeof(gem_map)); 489 490 gem_map.handle = bo->handles[0].u32; 491 492 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map); 493 if (ret) { 494 drv_log("DRM_IOCTL_I915_GEM_MMAP_GTT failed\n"); 495 return MAP_FAILED; 496 } 497 498 addr = mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, 499 gem_map.offset); 500 } 501 502 if (addr == MAP_FAILED) { 503 drv_log("i915 GEM mmap failed\n"); 504 return addr; 505 } 506 507 vma->length = bo->total_size; 508 return addr; 509 } 510 511 static int i915_bo_invalidate(struct bo *bo, struct mapping *mapping) 512 { 513 int ret; 514 struct drm_i915_gem_set_domain set_domain; 515 516 memset(&set_domain, 0, sizeof(set_domain)); 517 set_domain.handle = bo->handles[0].u32; 518 if (bo->tiling == I915_TILING_NONE) { 519 set_domain.read_domains = I915_GEM_DOMAIN_CPU; 520 if (mapping->vma->map_flags & BO_MAP_WRITE) 521 set_domain.write_domain = I915_GEM_DOMAIN_CPU; 522 } else { 523 set_domain.read_domains = I915_GEM_DOMAIN_GTT; 524 if (mapping->vma->map_flags & BO_MAP_WRITE) 525 set_domain.write_domain = I915_GEM_DOMAIN_GTT; 526 } 527 528 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); 529 if (ret) { 530 drv_log("DRM_IOCTL_I915_GEM_SET_DOMAIN with %d\n", ret); 531 return ret; 532 } 533 534 return 0; 535 } 536 537 static int i915_bo_flush(struct bo *bo, struct mapping *mapping) 538 { 539 struct i915_device *i915 = bo->drv->priv; 540 if (!i915->has_llc && bo->tiling == I915_TILING_NONE) 541 i915_clflush(mapping->vma->addr, mapping->vma->length); 542 543 return 0; 544 } 545 546 static uint32_t i915_resolve_format(uint32_t format, uint64_t use_flags) 547 { 548 switch (format) { 549 case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: 550 /* KBL camera subsystem requires NV12. */ 551 if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) 552 return DRM_FORMAT_NV12; 553 /*HACK: See b/28671744 */ 554 return DRM_FORMAT_XBGR8888; 555 case DRM_FORMAT_FLEX_YCbCr_420_888: 556 /* 557 * KBL camera subsystem requires NV12. Our other use cases 558 * don't care: 559 * - Hardware video supports NV12, 560 * - USB Camera HALv3 supports NV12, 561 * - USB Camera HALv1 doesn't use this format. 562 * Moreover, NV12 is preferred for video, due to overlay 563 * support on SKL+. 564 */ 565 return DRM_FORMAT_NV12; 566 default: 567 return format; 568 } 569 } 570 571 const struct backend backend_i915 = { 572 .name = "i915", 573 .init = i915_init, 574 .close = i915_close, 575 .bo_create = i915_bo_create, 576 .bo_create_with_modifiers = i915_bo_create_with_modifiers, 577 .bo_destroy = drv_gem_bo_destroy, 578 .bo_import = i915_bo_import, 579 .bo_map = i915_bo_map, 580 .bo_unmap = drv_bo_munmap, 581 .bo_invalidate = i915_bo_invalidate, 582 .bo_flush = i915_bo_flush, 583 .resolve_format = i915_resolve_format, 584 }; 585 586 #endif 587