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.
11 #include <intel_bufmgr.h>
20 static const uint32_t tileable_formats[] = { DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR8888,
21 DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565,
22 DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB1555,
23 DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY,
26 static const uint32_t linear_only_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_R8, DRM_FORMAT_YVU420,
27 DRM_FORMAT_YVU420_ANDROID };
31 drm_intel_bufmgr *mgr;
36 drm_intel_bo *ibos[DRV_MAX_PLANES];
39 static int get_gen(int device_id)
41 const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
42 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 };
44 for (i = 0; i < ARRAY_SIZE(gen3_ids); i++)
45 if (gen3_ids[i] == device_id)
51 static int i915_add_kms_item(struct driver *drv, const struct kms_item *item)
54 struct combination *combo;
57 * Older hardware can't scanout Y-tiled formats. Newer devices can, and
58 * report this functionality via format modifiers.
60 for (i = 0; i < drv->backend->combos.size; i++) {
61 combo = &drv->backend->combos.data[i];
62 if (combo->format == item->format) {
63 if ((combo->metadata.tiling == I915_TILING_Y &&
64 item->modifier == I915_FORMAT_MOD_Y_TILED) ||
65 (combo->metadata.tiling == I915_TILING_X &&
66 item->modifier == I915_FORMAT_MOD_X_TILED)) {
67 combo->metadata.modifier = item->modifier;
68 combo->usage |= item->usage;
69 } else if (combo->metadata.tiling != I915_TILING_Y) {
70 combo->usage |= item->usage;
78 static int i915_add_combinations(struct driver *drv)
81 uint32_t i, num_items;
82 struct kms_item *items;
83 struct format_metadata metadata;
84 uint64_t flags = BO_COMMON_USE_MASK;
86 metadata.tiling = I915_TILING_NONE;
87 metadata.priority = 1;
88 metadata.modifier = DRM_FORMAT_MOD_NONE;
90 ret = drv_add_combinations(drv, linear_only_formats, ARRAY_SIZE(linear_only_formats),
95 ret = drv_add_combinations(drv, tileable_formats, ARRAY_SIZE(tileable_formats), &metadata,
100 drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
101 drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
103 flags &= ~BO_USE_SW_WRITE_OFTEN;
104 flags &= ~BO_USE_SW_READ_OFTEN;
105 flags &= ~BO_USE_LINEAR;
107 metadata.tiling = I915_TILING_X;
108 metadata.priority = 2;
110 ret = drv_add_combinations(drv, tileable_formats, ARRAY_SIZE(tileable_formats), &metadata,
115 metadata.tiling = I915_TILING_Y;
116 metadata.priority = 3;
118 ret = drv_add_combinations(drv, tileable_formats, ARRAY_SIZE(tileable_formats), &metadata,
123 items = drv_query_kms(drv, &num_items);
124 if (!items || !num_items)
127 for (i = 0; i < num_items; i++) {
128 ret = i915_add_kms_item(drv, &items[i]);
139 static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *stride,
140 uint32_t *aligned_height)
142 struct i915_device *i915 = bo->drv->priv;
143 uint32_t horizontal_alignment = 4;
144 uint32_t vertical_alignment = 4;
148 case I915_TILING_NONE:
149 horizontal_alignment = 64;
153 horizontal_alignment = 512;
154 vertical_alignment = 8;
158 if (i915->gen == 3) {
159 horizontal_alignment = 512;
160 vertical_alignment = 8;
162 horizontal_alignment = 128;
163 vertical_alignment = 32;
168 *aligned_height = ALIGN(bo->height, vertical_alignment);
170 *stride = ALIGN(*stride, horizontal_alignment);
172 while (*stride > horizontal_alignment)
173 horizontal_alignment <<= 1;
175 *stride = horizontal_alignment;
178 if (i915->gen <= 3 && *stride > 8192)
184 static int i915_init(struct driver *drv)
186 struct i915_device *i915_dev;
187 drm_i915_getparam_t get_param;
191 i915_dev = calloc(1, sizeof(*i915_dev));
195 memset(&get_param, 0, sizeof(get_param));
196 get_param.param = I915_PARAM_CHIPSET_ID;
197 get_param.value = &device_id;
198 ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
200 fprintf(stderr, "drv: DRM_IOCTL_I915_GETPARAM failed\n");
205 i915_dev->gen = get_gen(device_id);
208 i915_dev->mgr = drm_intel_bufmgr_gem_init(drv->fd, 16 * 1024);
209 if (!i915_dev->mgr) {
210 fprintf(stderr, "drv: drm_intel_bufmgr_gem_init failed\n");
215 drv->priv = i915_dev;
217 return i915_add_combinations(drv);
220 static void i915_close(struct driver *drv)
222 struct i915_device *i915_dev = drv->priv;
223 drm_intel_bufmgr_destroy(i915_dev->mgr);
228 static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
235 uint32_t tiling_mode;
236 struct i915_bo *i915_bo;
238 stride = drv_stride_from_format(format, width, 0);
239 struct i915_device *i915_dev = (struct i915_device *)bo->drv->priv;
241 if (flags & (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))
242 tiling_mode = I915_TILING_NONE;
243 else if (flags & BO_USE_SCANOUT)
244 tiling_mode = I915_TILING_X;
246 tiling_mode = I915_TILING_Y;
249 * Align the Y plane to 128 bytes so the chroma planes would be aligned
250 * to 64 byte boundaries. This is an Intel HW requirement.
252 if (format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID) {
253 stride = ALIGN(stride, 128);
254 tiling_mode = I915_TILING_NONE;
257 ret = i915_align_dimensions(bo, tiling_mode, &stride, &height);
261 drv_bo_from_format(bo, stride, height, format);
263 snprintf(name, sizeof(name), "i915-buffer-%u", i915_dev->count);
266 i915_bo = calloc(1, sizeof(*i915_bo));
272 i915_bo->ibos[0] = drm_intel_bo_alloc(i915_dev->mgr, name, bo->total_size, 0);
273 if (!i915_bo->ibos[0]) {
274 fprintf(stderr, "drv: drm_intel_bo_alloc failed");
280 for (plane = 0; plane < bo->num_planes; plane++) {
282 drm_intel_bo_reference(i915_bo->ibos[0]);
284 bo->handles[plane].u32 = i915_bo->ibos[0]->handle;
285 i915_bo->ibos[plane] = i915_bo->ibos[0];
288 bo->tiling = tiling_mode;
290 ret = drm_intel_bo_set_tiling(i915_bo->ibos[0], &bo->tiling, bo->strides[0]);
292 if (ret || bo->tiling != tiling_mode) {
293 fprintf(stderr, "drv: drm_intel_gem_bo_set_tiling failed errno=%x, stride=%x\n",
294 errno, bo->strides[0]);
295 /* Calls i915 bo destroy. */
296 bo->drv->backend->bo_destroy(bo);
303 static int i915_bo_destroy(struct bo *bo)
306 struct i915_bo *i915_bo = bo->priv;
308 for (plane = 0; plane < bo->num_planes; plane++)
309 drm_intel_bo_unreference(i915_bo->ibos[plane]);
317 static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
321 struct i915_bo *i915_bo;
322 struct i915_device *i915_dev = bo->drv->priv;
324 i915_bo = calloc(1, sizeof(*i915_bo));
331 * When self-importing, libdrm_intel increments the reference count
332 * on the drm_intel_bo. It also returns the same drm_intel_bo per GEM
333 * handle. Thus, we don't need to increase the reference count
334 * (i.e, drv_increment_reference_count) when importing with this
337 for (plane = 0; plane < bo->num_planes; plane++) {
339 i915_bo->ibos[plane] = drm_intel_bo_gem_create_from_prime(
340 i915_dev->mgr, data->fds[plane], data->sizes[plane]);
342 if (!i915_bo->ibos[plane]) {
344 * Need to call GEM close on planes that were opened,
345 * if any. Adjust the num_planes variable to be the
346 * plane that failed, so GEM close will be called on
347 * planes before that plane.
349 bo->num_planes = plane;
351 fprintf(stderr, "drv: i915: failed to import failed");
355 bo->handles[plane].u32 = i915_bo->ibos[plane]->handle;
358 if (drm_intel_bo_get_tiling(i915_bo->ibos[0], &bo->tiling, &swizzling)) {
359 fprintf(stderr, "drv: drm_intel_bo_get_tiling failed");
367 static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane)
370 struct i915_bo *i915_bo = bo->priv;
372 if (bo->tiling == I915_TILING_NONE)
373 /* TODO(gsingh): use bo_map flags to determine if we should
376 ret = drm_intel_bo_map(i915_bo->ibos[0], 1);
378 ret = drm_intel_gem_bo_map_gtt(i915_bo->ibos[0]);
381 fprintf(stderr, "drv: i915_bo_map failed.");
385 return i915_bo->ibos[0]->virtual;
388 static int i915_bo_unmap(struct bo *bo, struct map_info *data)
391 struct i915_bo *i915_bo = bo->priv;
393 if (bo->tiling == I915_TILING_NONE)
394 ret = drm_intel_bo_unmap(i915_bo->ibos[0]);
396 ret = drm_intel_gem_bo_unmap_gtt(i915_bo->ibos[0]);
401 static uint32_t i915_resolve_format(uint32_t format)
404 case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
405 /*HACK: See b/28671744 */
406 return DRM_FORMAT_XBGR8888;
407 case DRM_FORMAT_FLEX_YCbCr_420_888:
408 return DRM_FORMAT_YVU420_ANDROID;
414 struct backend backend_i915 = {
418 .bo_create = i915_bo_create,
419 .bo_destroy = i915_bo_destroy,
420 .bo_import = i915_bo_import,
421 .bo_map = i915_bo_map,
422 .bo_unmap = i915_bo_unmap,
423 .resolve_format = i915_resolve_format,