390f51a561c9d4405fe4b390f0860ec1b7785a11
[mesa.git] / src / gallium / winsys / r600 / drm / r600_drm.c
1 /*
2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Jerome Glisse
25 * Corbin Simpson <MostAwesomeDude@gmail.com>
26 * Joakim Sindholt <opensource@zhasha.com>
27 */
28
29 #include "r600_priv.h"
30 #include "r600_drm_public.h"
31 #include "util/u_memory.h"
32 #include <radeon_drm.h>
33 #include <xf86drm.h>
34 #include <errno.h>
35
36 #ifndef RADEON_INFO_NUM_TILE_PIPES
37 #define RADEON_INFO_NUM_TILE_PIPES 0xb
38 #endif
39
40 #ifndef RADEON_INFO_BACKEND_MAP
41 #define RADEON_INFO_BACKEND_MAP 0xd
42 #endif
43
44 enum radeon_family r600_get_family(struct radeon *r600)
45 {
46 return r600->family;
47 }
48
49 enum chip_class r600_get_family_class(struct radeon *radeon)
50 {
51 return radeon->chip_class;
52 }
53
54 struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon)
55 {
56 return &radeon->tiling_info;
57 }
58
59 unsigned r600_get_clock_crystal_freq(struct radeon *radeon)
60 {
61 return radeon->info.r600_clock_crystal_freq;
62 }
63
64 unsigned r600_get_num_backends(struct radeon *radeon)
65 {
66 return radeon->info.r600_num_backends;
67 }
68
69 unsigned r600_get_num_tile_pipes(struct radeon *radeon)
70 {
71 return radeon->num_tile_pipes;
72 }
73
74 unsigned r600_get_backend_map(struct radeon *radeon)
75 {
76 return radeon->backend_map;
77 }
78
79 unsigned r600_get_minor_version(struct radeon *radeon)
80 {
81 return radeon->info.drm_minor;
82 }
83
84 static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
85 {
86 switch ((tiling_config & 0xe) >> 1) {
87 case 0:
88 radeon->tiling_info.num_channels = 1;
89 break;
90 case 1:
91 radeon->tiling_info.num_channels = 2;
92 break;
93 case 2:
94 radeon->tiling_info.num_channels = 4;
95 break;
96 case 3:
97 radeon->tiling_info.num_channels = 8;
98 break;
99 default:
100 return -EINVAL;
101 }
102
103 switch ((tiling_config & 0x30) >> 4) {
104 case 0:
105 radeon->tiling_info.num_banks = 4;
106 break;
107 case 1:
108 radeon->tiling_info.num_banks = 8;
109 break;
110 default:
111 return -EINVAL;
112
113 }
114 switch ((tiling_config & 0xc0) >> 6) {
115 case 0:
116 radeon->tiling_info.group_bytes = 256;
117 break;
118 case 1:
119 radeon->tiling_info.group_bytes = 512;
120 break;
121 default:
122 return -EINVAL;
123 }
124 return 0;
125 }
126
127 static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
128 {
129 switch (tiling_config & 0xf) {
130 case 0:
131 radeon->tiling_info.num_channels = 1;
132 break;
133 case 1:
134 radeon->tiling_info.num_channels = 2;
135 break;
136 case 2:
137 radeon->tiling_info.num_channels = 4;
138 break;
139 case 3:
140 radeon->tiling_info.num_channels = 8;
141 break;
142 default:
143 return -EINVAL;
144 }
145
146 switch ((tiling_config & 0xf0) >> 4) {
147 case 0:
148 radeon->tiling_info.num_banks = 4;
149 break;
150 case 1:
151 radeon->tiling_info.num_banks = 8;
152 break;
153 case 2:
154 radeon->tiling_info.num_banks = 16;
155 break;
156 default:
157 return -EINVAL;
158
159 }
160
161 switch ((tiling_config & 0xf00) >> 8) {
162 case 0:
163 radeon->tiling_info.group_bytes = 256;
164 break;
165 case 1:
166 radeon->tiling_info.group_bytes = 512;
167 break;
168 default:
169 return -EINVAL;
170 }
171 return 0;
172 }
173
174 static int radeon_drm_get_tiling(struct radeon *radeon)
175 {
176 uint32_t tiling_config = radeon->info.r600_tiling_config;
177
178 if (!tiling_config)
179 return 0;
180
181 if (radeon->chip_class == R600 || radeon->chip_class == R700) {
182 return r600_interpret_tiling(radeon, tiling_config);
183 } else {
184 return eg_interpret_tiling(radeon, tiling_config);
185 }
186 }
187
188 static int radeon_get_num_tile_pipes(struct radeon *radeon)
189 {
190 struct drm_radeon_info info = {};
191 uint32_t num_tile_pipes = 0;
192 int r;
193
194 info.request = RADEON_INFO_NUM_TILE_PIPES;
195 info.value = (uintptr_t)&num_tile_pipes;
196 r = drmCommandWriteRead(radeon->info.fd, DRM_RADEON_INFO, &info,
197 sizeof(struct drm_radeon_info));
198 if (r)
199 return r;
200
201 radeon->num_tile_pipes = num_tile_pipes;
202 return 0;
203 }
204
205 static int radeon_get_backend_map(struct radeon *radeon)
206 {
207 struct drm_radeon_info info = {};
208 uint32_t backend_map = 0;
209 int r;
210
211 info.request = RADEON_INFO_BACKEND_MAP;
212 info.value = (uintptr_t)&backend_map;
213 r = drmCommandWriteRead(radeon->info.fd, DRM_RADEON_INFO, &info,
214 sizeof(struct drm_radeon_info));
215 if (r)
216 return r;
217
218 radeon->backend_map = backend_map;
219 radeon->backend_map_valid = TRUE;
220
221 return 0;
222 }
223
224 static int radeon_init_fence(struct radeon *radeon)
225 {
226 radeon->fence = 1;
227 radeon->fence_bo = r600_bo(radeon, 4096, 0, 0, 0);
228 if (radeon->fence_bo == NULL) {
229 return -ENOMEM;
230 }
231 radeon->cfence = r600_bo_map(radeon, radeon->fence_bo, PIPE_TRANSFER_UNSYNCHRONIZED, NULL);
232 *radeon->cfence = 0;
233 return 0;
234 }
235
236 struct radeon *radeon_create(struct radeon_winsys *ws)
237 {
238 int r;
239 struct radeon *radeon = CALLOC_STRUCT(radeon);
240 if (radeon == NULL) {
241 return NULL;
242 }
243
244 radeon->ws = ws;
245 ws->query_info(ws, &radeon->info);
246
247 radeon->family = radeon_family_from_device(radeon->info.pci_id);
248 if (radeon->family == CHIP_UNKNOWN) {
249 fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->info.pci_id);
250 return radeon_destroy(radeon);
251 }
252 /* setup class */
253 switch (radeon->family) {
254 case CHIP_R600:
255 case CHIP_RV610:
256 case CHIP_RV630:
257 case CHIP_RV670:
258 case CHIP_RV620:
259 case CHIP_RV635:
260 case CHIP_RS780:
261 case CHIP_RS880:
262 radeon->chip_class = R600;
263 /* set default group bytes, overridden by tiling info ioctl */
264 radeon->tiling_info.group_bytes = 256;
265 break;
266 case CHIP_RV770:
267 case CHIP_RV730:
268 case CHIP_RV710:
269 case CHIP_RV740:
270 radeon->chip_class = R700;
271 /* set default group bytes, overridden by tiling info ioctl */
272 radeon->tiling_info.group_bytes = 256;
273 break;
274 case CHIP_CEDAR:
275 case CHIP_REDWOOD:
276 case CHIP_JUNIPER:
277 case CHIP_CYPRESS:
278 case CHIP_HEMLOCK:
279 case CHIP_PALM:
280 case CHIP_SUMO:
281 case CHIP_SUMO2:
282 case CHIP_BARTS:
283 case CHIP_TURKS:
284 case CHIP_CAICOS:
285 radeon->chip_class = EVERGREEN;
286 /* set default group bytes, overridden by tiling info ioctl */
287 radeon->tiling_info.group_bytes = 512;
288 break;
289 case CHIP_CAYMAN:
290 radeon->chip_class = CAYMAN;
291 /* set default group bytes, overridden by tiling info ioctl */
292 radeon->tiling_info.group_bytes = 512;
293 break;
294 default:
295 fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n",
296 __func__, radeon->info.pci_id);
297 break;
298 }
299
300 if (radeon_drm_get_tiling(radeon))
301 return NULL;
302
303 if (radeon->info.drm_minor >= 11) {
304 radeon_get_num_tile_pipes(radeon);
305 radeon_get_backend_map(radeon);
306 }
307
308 r = radeon_init_fence(radeon);
309 if (r) {
310 radeon_destroy(radeon);
311 return NULL;
312 }
313
314 return radeon;
315 }
316
317 struct radeon *radeon_destroy(struct radeon *radeon)
318 {
319 if (radeon == NULL)
320 return NULL;
321
322 if (radeon->fence_bo) {
323 r600_bo_reference(radeon, &radeon->fence_bo, NULL);
324 }
325
326 FREE(radeon);
327 return NULL;
328 }