blob: 2d3dc62f2d690d285c2eed7e077fd0516533e960 [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
9#include <errno.h>
10#include <string.h>
11#include <stdio.h>
12#include <xf86drm.h>
13#include <i915_drm.h>
14
15#include "gbm_priv.h"
16#include "helpers.h"
17#include "util.h"
18
19struct gbm_i915_device
20{
21 int gen;
22};
23
24
25static int get_gen(int device_id)
26{
27 const uint16_t gen3_ids[] = {0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE, 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011};
Stéphane Marchesina39dfde2014-09-15 15:38:25 -070028 unsigned i;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070029 for(i = 0; i < ARRAY_SIZE(gen3_ids); i++)
30 if (gen3_ids[i] == device_id)
31 return 3;
32
33 return 4;
34}
35
36int gbm_i915_init(struct gbm_device *gbm)
37{
38 struct gbm_i915_device *i915_gbm;
39 drm_i915_getparam_t get_param;
40 int device_id;
41 int ret;
42
43 i915_gbm = (struct gbm_i915_device*)malloc(sizeof(*i915_gbm));
44 if (!i915_gbm)
45 return -1;
46
47 memset(&get_param, 0, sizeof(get_param));
48 get_param.param = I915_PARAM_CHIPSET_ID;
49 get_param.value = &device_id;
50 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
51 if (ret) {
52 free(i915_gbm);
53 return -1;
54 }
55
56 i915_gbm->gen = get_gen(device_id);
57
58 gbm->priv = i915_gbm;
59
60 return 0;
61}
62
63void gbm_i915_close(struct gbm_device *gbm)
64{
65 free(gbm->priv);
66 gbm->priv = NULL;
67}
68
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080069static 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 -070070{
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080071 struct gbm_i915_device *i915_gbm = (struct gbm_i915_device *)gbm->priv;
72 uint32_t width_alignment = 4, height_alignment = 4;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070073
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080074 switch(tiling_mode) {
75 default:
76 case I915_TILING_NONE:
77 width_alignment = 64 / bpp;
78 break;
79
80 case I915_TILING_X:
81 width_alignment = 512 / bpp;
82 height_alignment = 8;
83 break;
84
85 case I915_TILING_Y:
86 if (i915_gbm->gen == 3) {
87 width_alignment = 512 / bpp;
88 height_alignment = 8;
89 } else {
90 width_alignment = 128 / bpp;
91 height_alignment = 32;
92 }
93 break;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070094 }
Stéphane Marchesin5d867a42014-11-24 17:09:49 -080095
96 if (i915_gbm->gen > 3) {
97 *width = ALIGN(*width, width_alignment);
98 *height = ALIGN(*height, height_alignment);
99 } else {
100 uint32_t w;
101 for (w = width_alignment; w < *width * bpp; w <<= 1)
102 ;
103 *width = w;
104 *height = ALIGN(*height, height_alignment);
105 }
106}
107
108static int i915_verify_dimensions(struct gbm_device *gbm, uint32_t stride, uint32_t height)
109{
110 struct gbm_i915_device *i915_gbm = (struct gbm_i915_device *)gbm->priv;
111 if (i915_gbm->gen <= 3 && stride > 8192)
112 return 0;
113
114 return 1;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700115}
116
117int gbm_i915_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
118{
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800119 struct gbm_device *gbm = bo->gbm;
120 int bpp = gbm_bytes_from_format(format);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700121 struct drm_i915_gem_create gem_create;
122 struct drm_i915_gem_set_tiling gem_set_tiling;
123 uint32_t tiling_mode = I915_TILING_NONE;
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800124 size_t size;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700125 int ret;
126
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700127 if (flags & GBM_BO_USE_CURSOR)
128 tiling_mode = I915_TILING_NONE;
129 else if (flags & GBM_BO_USE_SCANOUT)
130 tiling_mode = I915_TILING_X;
131 else if (flags & GBM_BO_USE_RENDERING)
132 tiling_mode = I915_TILING_Y;
133
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800134 i915_align_dimensions(gbm, tiling_mode, &width, &height, bpp);
135
136 bo->stride = width * bpp;
137
138 if (!i915_verify_dimensions(gbm, bo->stride, height))
139 return EINVAL;
140
141 memset(&gem_create, 0, sizeof(gem_create));
142 size = width * height * bpp;
143 gem_create.size = size;
144
145 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
146 if (ret)
147 return ret;
148
149 bo->handle.u32 = gem_create.handle;
150 bo->size = size;
Daniel Nicoara1de26dc2014-09-25 18:53:19 -0400151
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700152 memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
153 do {
154 gem_set_tiling.handle = bo->handle.u32;
155 gem_set_tiling.tiling_mode = tiling_mode;
Daniel Nicoara1de26dc2014-09-25 18:53:19 -0400156 gem_set_tiling.stride = bo->stride;
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800157 ret = drmIoctl(gbm->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700158 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
159
160 if (ret == -1) {
161 struct drm_gem_close gem_close;
162 gem_close.handle = bo->handle.u32;
Stéphane Marchesin5d867a42014-11-24 17:09:49 -0800163 drmIoctl(gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700164 return -errno;
165 }
166
167 return 0;
168}
169
170const struct gbm_driver gbm_driver_i915 =
171{
172 .name = "i915",
173 .init = gbm_i915_init,
174 .close = gbm_i915_close,
175 .bo_create = gbm_i915_bo_create,
176 .bo_destroy = gbm_gem_bo_destroy,
177 .format_list = {
178 {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
179 {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
180 {GBM_FORMAT_XBGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
181 {GBM_FORMAT_ABGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
182 {GBM_FORMAT_XRGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
183 {GBM_FORMAT_ARGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
184 {GBM_FORMAT_RGB565, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
185 }
186};
187
188#endif