blob: 8d120c4fafdc9f0713b31754cc0b82fcd4ef1d96 [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
69static int i915_get_pitch(struct gbm_device *gbm, uint32_t pitch, int tiling_mode)
70{
71 struct gbm_i915_device *dev_priv = (struct gbm_i915_device *)gbm->priv;
72 if (tiling_mode == I915_TILING_NONE)
73 return ALIGN(pitch, 64);
74
75 if (dev_priv->gen >= 4) {
76 uint32_t tile_width = tiling_mode == I915_TILING_X ? 512 : 128;
77 return ALIGN(pitch, tile_width);
78 } else {
79 uint32_t i = 128;
80 while(i < pitch)
81 i <<= 1;
82 return i;
83 }
84}
85
86int gbm_i915_bo_create(struct gbm_bo *bo, uint32_t width, uint32_t height, uint32_t format, uint32_t flags)
87{
88 size_t size = width * height * gbm_bytes_from_format(format);
89 struct drm_i915_gem_create gem_create;
90 struct drm_i915_gem_set_tiling gem_set_tiling;
91 uint32_t tiling_mode = I915_TILING_NONE;
92 int ret;
93
94 memset(&gem_create, 0, sizeof(gem_create));
95 gem_create.size = size;
96
97 ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
98 if (ret)
99 return ret;
100
101 bo->handle.u32 = gem_create.handle;
102 bo->size = size;
103
104 if (flags & GBM_BO_USE_CURSOR)
105 tiling_mode = I915_TILING_NONE;
106 else if (flags & GBM_BO_USE_SCANOUT)
107 tiling_mode = I915_TILING_X;
108 else if (flags & GBM_BO_USE_RENDERING)
109 tiling_mode = I915_TILING_Y;
110
Daniel Nicoara1de26dc2014-09-25 18:53:19 -0400111 bo->stride = i915_get_pitch(bo->gbm,
112 width * gbm_bytes_from_format(format),
113 tiling_mode);
114
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700115 memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
116 do {
117 gem_set_tiling.handle = bo->handle.u32;
118 gem_set_tiling.tiling_mode = tiling_mode;
Daniel Nicoara1de26dc2014-09-25 18:53:19 -0400119 gem_set_tiling.stride = bo->stride;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700120 ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
121 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
122
123 if (ret == -1) {
124 struct drm_gem_close gem_close;
125 gem_close.handle = bo->handle.u32;
126 drmIoctl(bo->gbm->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
127 return -errno;
128 }
129
130 return 0;
131}
132
133const struct gbm_driver gbm_driver_i915 =
134{
135 .name = "i915",
136 .init = gbm_i915_init,
137 .close = gbm_i915_close,
138 .bo_create = gbm_i915_bo_create,
139 .bo_destroy = gbm_gem_bo_destroy,
140 .format_list = {
141 {GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
142 {GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
143 {GBM_FORMAT_XBGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
144 {GBM_FORMAT_ABGR8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
145 {GBM_FORMAT_XRGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
146 {GBM_FORMAT_ARGB1555, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
147 {GBM_FORMAT_RGB565, GBM_BO_USE_SCANOUT | GBM_BO_USE_CURSOR | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE},
148 }
149};
150
151#endif