blob: 511e4f4b7a2778ffc15e6948f2985abe70441b0c [file] [log] [blame]
Stéphane Marchesin25a26062014-09-12 16:18:59 -07001/*
2 * Copyright (c) 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 GBM_I915
8
Ilja H. Friedelf9d2ab72015-04-09 14:08:36 -07009#include <stdio.h>
Stéphane Marchesin25a26062014-09-12 16:18:59 -070010#include <errno.h>
11#include <string.h>
12#include <stdio.h>
13#include <xf86drm.h>
14#include <i915_drm.h>
15
16#include "gbm_priv.h"
17#include "helpers.h"
18#include "util.h"
19
20struct gbm_i915_device
21{
22 int gen;
23};
24
25
26static int get_gen(int device_id)
27{
28 const uint16_t gen3_ids[] = {0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE, 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011};
Stéphane Marchesina39dfde2014-09-15 15:38:25 -070029 unsigned i;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070030 for(i = 0; i < ARRAY_SIZE(gen3_ids); i++)
31 if (gen3_ids[i] == device_id)
32 return 3;
33
34 return 4;
35}
36
37int gbm_i915_init(struct gbm_device *gbm)
38{
39 struct gbm_i915_device *i915_gbm;
40 drm_i915_getparam_t get_param;
41 int device_id;
42 int ret;
43
44 i915_gbm = (struct gbm_i915_device*)malloc(sizeof(*i915_gbm));
45 if (!i915_gbm)
46 return -1;
47
48 memset(&get_param, 0, sizeof(get_param));
49 get_param.param = I915_PARAM_CHIPSET_ID;
50 get_param.value = &device_id;
51 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
52 if (ret) {
Ilja H. Friedelf9d2ab72015-04-09 14:08:36 -070053 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GETPARAM failed\n");
Stéphane Marchesin25a26062014-09-12 16:18:59 -070054 free(i915_gbm);
55 return -1;
56 }
57
58 i915_gbm->gen = get_gen(device_id);
59
60 gbm->priv = i915_gbm;
61
62 return 0;
63}
64
65void gbm_i915_close(struct gbm_device *gbm)
66{
67 free(gbm->priv);
68 gbm->priv = NULL;
69}
70
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080071static void i915_align_dimensions(struct gbm_device *gbm, uint32_t tiling_mode, uint32_t *width, uint32_t *height, int bpp)
Stéphane Marchesin25a26062014-09-12 16:18:59 -070072{
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080073 struct gbm_i915_device *i915_gbm = (struct gbm_i915_device *)gbm->priv;
74 uint32_t width_alignment = 4, height_alignment = 4;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070075
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080076 switch(tiling_mode) {
77 default:
78 case I915_TILING_NONE:
79 width_alignment = 64 / bpp;
80 break;
81
82 case I915_TILING_X:
83 width_alignment = 512 / bpp;
84 height_alignment = 8;
85 break;
86
87 case I915_TILING_Y:
88 if (i915_gbm->gen == 3) {
89 width_alignment = 512 / bpp;
90 height_alignment = 8;
91 } else {
92 width_alignment = 128 / bpp;
93 height_alignment = 32;
94 }
95 break;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070096 }
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080097
98 if (i915_gbm->gen > 3) {
99 *width = ALIGN(*width, width_alignment);
100 *height = ALIGN(*height, height_alignment);
101 } else {
102 uint32_t w;
Stéphane Marchesine3d7c1f2015-03-31 13:47:22 -0700103 for (w = width_alignment; w < *width; w <<= 1)
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800104 ;
105 *width = w;
106 *height = ALIGN(*height, height_alignment);
107 }
108}
109
110static int i915_verify_dimensions(struct gbm_device *gbm, uint32_t stride, uint32_t height)
111{
112 struct gbm_i915_device *i915_gbm = (struct gbm_i915_device *)gbm->priv;
113 if (i915_gbm->gen <= 3 && stride > 8192)
114 return 0;
115
116 return 1;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700117}
118
119int gbm_i915_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
120{
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800121 struct gbm_device *gbm = bo->gbm;
122 int bpp = gbm_bytes_from_format(format);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700123 struct drm_i915_gem_create gem_create;
124 struct drm_i915_gem_set_tiling gem_set_tiling;
125 uint32_t tiling_mode = I915_TILING_NONE;
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800126 size_t size;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700127 int ret;
128
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700129 if (flags & GBM_BO_USE_CURSOR)
130 tiling_mode = I915_TILING_NONE;
131 else if (flags & GBM_BO_USE_SCANOUT)
132 tiling_mode = I915_TILING_X;
133 else if (flags & GBM_BO_USE_RENDERING)
134 tiling_mode = I915_TILING_Y;
135
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800136 i915_align_dimensions(gbm, tiling_mode, &width, &height, bpp);
137
138 bo->stride = width * bpp;
139
140 if (!i915_verify_dimensions(gbm, bo->stride, height))
141 return EINVAL;
142
143 memset(&gem_create, 0, sizeof(gem_create));
144 size = width * height * bpp;
145 gem_create.size = size;
146
147 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
Ilja H. Friedelf9d2ab72015-04-09 14:08:36 -0700148 if (ret) {
149 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GEM_CREATE failed "
150 "(size=%zu)\n", size);
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800151 return ret;
Ilja H. Friedelf9d2ab72015-04-09 14:08:36 -0700152 }
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800153 bo->handle.u32 = gem_create.handle;
154 bo->size = size;
Daniel Nicoara1de26dc2014-09-25 18:53:19 -0400155
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700156 memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
157 do {
158 gem_set_tiling.handle = bo->handle.u32;
159 gem_set_tiling.tiling_mode = tiling_mode;
Daniel Nicoara1de26dc2014-09-25 18:53:19 -0400160 gem_set_tiling.stride = bo->stride;
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800161 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700162 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
163
164 if (ret == -1) {
165 struct drm_gem_close gem_close;
166 gem_close.handle = bo->handle.u32;
Ilja H. Friedelf9d2ab72015-04-09 14:08:36 -0700167 fprintf(stderr, "minigbm: DRM_IOCTL_I915_GEM_SET_TILING failed "
168 "errno=%x (handle=%x, tiling=%x, stride=%x)\n",
169 errno,
170 gem_set_tiling.handle,
171 gem_set_tiling.tiling_mode,
172 gem_set_tiling.stride);
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800173 drmIoctl(gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700174 return -errno;
175 }
176
177 return 0;
178}
179
180const struct gbm_driver gbm_driver_i915 =
181{
182 .name = "i915",
183 .init = gbm_i915_init,
184 .close = gbm_i915_close,
185 .bo_create = gbm_i915_bo_create,
186 .bo_destroy = gbm_gem_bo_destroy,
187 .format_list = {
188 {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
189 {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
190 {GBM_FORMAT_XBGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
191 {GBM_FORMAT_ABGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
192 {GBM_FORMAT_XRGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
193 {GBM_FORMAT_ARGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
194 {GBM_FORMAT_RGB565, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
195 }
196};
197
198#endif