Tizen 2.0 Release
[profile/ivi/osmesa.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 #include <stdio.h>
29 #include <errno.h>
30 #include <sys/ioctl.h>
31 #include "util/u_inlines.h"
32 #include "util/u_debug.h"
33 #include "util/u_hash_table.h"
34 #include <pipebuffer/pb_bufmgr.h>
35 #include "r600.h"
36 #include "r600_priv.h"
37 #include "r600_drm_public.h"
38 #include "xf86drm.h"
39 #include "radeon_drm.h"
40
41 #ifndef RADEON_INFO_TILING_CONFIG
42 #define RADEON_INFO_TILING_CONFIG 0x6
43 #endif
44
45 #ifndef RADEON_INFO_CLOCK_CRYSTAL_FREQ
46 #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x9
47 #endif
48
49 #ifndef RADEON_INFO_NUM_BACKENDS
50 #define RADEON_INFO_NUM_BACKENDS 0xa
51 #endif
52
53 #ifndef RADEON_INFO_NUM_TILE_PIPES
54 #define RADEON_INFO_NUM_TILE_PIPES 0xb
55 #endif
56
57 #ifndef RADEON_INFO_BACKEND_MAP
58 #define RADEON_INFO_BACKEND_MAP 0xd
59 #endif
60
61 enum radeon_family r600_get_family(struct radeon *r600)
62 {
63         return r600->family;
64 }
65
66 enum chip_class r600_get_family_class(struct radeon *radeon)
67 {
68         return radeon->chip_class;
69 }
70
71 struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon)
72 {
73         return &radeon->tiling_info;
74 }
75
76 unsigned r600_get_clock_crystal_freq(struct radeon *radeon)
77 {
78         return radeon->clock_crystal_freq;
79 }
80
81 unsigned r600_get_num_backends(struct radeon *radeon)
82 {
83         return radeon->num_backends;
84 }
85
86 unsigned r600_get_num_tile_pipes(struct radeon *radeon)
87 {
88         return radeon->num_tile_pipes;
89 }
90
91 unsigned r600_get_backend_map(struct radeon *radeon)
92 {
93         return radeon->backend_map;
94 }
95
96 unsigned r600_get_minor_version(struct radeon *radeon)
97 {
98         return radeon->minor_version;
99 }
100
101
102 static int radeon_get_device(struct radeon *radeon)
103 {
104         struct drm_radeon_info info = {};
105         int r;
106
107         radeon->device = 0;
108         info.request = RADEON_INFO_DEVICE_ID;
109         info.value = (uintptr_t)&radeon->device;
110         r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
111                         sizeof(struct drm_radeon_info));
112         return r;
113 }
114
115 static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
116 {
117         switch ((tiling_config & 0xe) >> 1) {
118         case 0:
119                 radeon->tiling_info.num_channels = 1;
120                 break;
121         case 1:
122                 radeon->tiling_info.num_channels = 2;
123                 break;
124         case 2:
125                 radeon->tiling_info.num_channels = 4;
126                 break;
127         case 3:
128                 radeon->tiling_info.num_channels = 8;
129                 break;
130         default:
131                 return -EINVAL;
132         }
133
134         switch ((tiling_config & 0x30) >> 4) {
135         case 0:
136                 radeon->tiling_info.num_banks = 4;
137                 break;
138         case 1:
139                 radeon->tiling_info.num_banks = 8;
140                 break;
141         default:
142                 return -EINVAL;
143
144         }
145         switch ((tiling_config & 0xc0) >> 6) {
146         case 0:
147                 radeon->tiling_info.group_bytes = 256;
148                 break;
149         case 1:
150                 radeon->tiling_info.group_bytes = 512;
151                 break;
152         default:
153                 return -EINVAL;
154         }
155         return 0;
156 }
157
158 static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
159 {
160         switch (tiling_config & 0xf) {
161         case 0:
162                 radeon->tiling_info.num_channels = 1;
163                 break;
164         case 1:
165                 radeon->tiling_info.num_channels = 2;
166                 break;
167         case 2:
168                 radeon->tiling_info.num_channels = 4;
169                 break;
170         case 3:
171                 radeon->tiling_info.num_channels = 8;
172                 break;
173         default:
174                 return -EINVAL;
175         }
176
177         switch ((tiling_config & 0xf0) >> 4) {
178         case 0:
179                 radeon->tiling_info.num_banks = 4;
180                 break;
181         case 1:
182                 radeon->tiling_info.num_banks = 8;
183                 break;
184         case 2:
185                 radeon->tiling_info.num_banks = 16;
186                 break;
187         default:
188                 return -EINVAL;
189
190         }
191
192         switch ((tiling_config & 0xf00) >> 8) {
193         case 0:
194                 radeon->tiling_info.group_bytes = 256;
195                 break;
196         case 1:
197                 radeon->tiling_info.group_bytes = 512;
198                 break;
199         default:
200                 return -EINVAL;
201         }
202         return 0;
203 }
204
205 static int radeon_drm_get_tiling(struct radeon *radeon)
206 {
207         struct drm_radeon_info info = {};
208         int r;
209         uint32_t tiling_config = 0;
210
211         info.request = RADEON_INFO_TILING_CONFIG;
212         info.value = (uintptr_t)&tiling_config;
213         r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
214                                 sizeof(struct drm_radeon_info));
215
216         if (r)
217                 return 0;
218
219         if (radeon->chip_class == R600 || radeon->chip_class == R700) {
220                 r = r600_interpret_tiling(radeon, tiling_config);
221         } else {
222                 r = eg_interpret_tiling(radeon, tiling_config);
223         }
224         return r;
225 }
226
227 static int radeon_get_clock_crystal_freq(struct radeon *radeon)
228 {
229         struct drm_radeon_info info = {};
230         uint32_t clock_crystal_freq = 0;
231         int r;
232
233         info.request = RADEON_INFO_CLOCK_CRYSTAL_FREQ;
234         info.value = (uintptr_t)&clock_crystal_freq;
235         r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
236                         sizeof(struct drm_radeon_info));
237         if (r)
238                 return r;
239
240         radeon->clock_crystal_freq = clock_crystal_freq;
241         return 0;
242 }
243
244
245 static int radeon_get_num_backends(struct radeon *radeon)
246 {
247         struct drm_radeon_info info = {};
248         uint32_t num_backends = 0;
249         int r;
250
251         info.request = RADEON_INFO_NUM_BACKENDS;
252         info.value = (uintptr_t)&num_backends;
253         r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
254                         sizeof(struct drm_radeon_info));
255         if (r)
256                 return r;
257
258         radeon->num_backends = num_backends;
259         return 0;
260 }
261
262 static int radeon_get_num_tile_pipes(struct radeon *radeon)
263 {
264         struct drm_radeon_info info = {};
265         uint32_t num_tile_pipes = 0;
266         int r;
267
268         info.request = RADEON_INFO_NUM_TILE_PIPES;
269         info.value = (uintptr_t)&num_tile_pipes;
270         r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
271                         sizeof(struct drm_radeon_info));
272         if (r)
273                 return r;
274
275         radeon->num_tile_pipes = num_tile_pipes;
276         return 0;
277 }
278
279 static int radeon_get_backend_map(struct radeon *radeon)
280 {
281         struct drm_radeon_info info = {};
282         uint32_t backend_map = 0;
283         int r;
284
285         info.request = RADEON_INFO_BACKEND_MAP;
286         info.value = (uintptr_t)&backend_map;
287         r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
288                         sizeof(struct drm_radeon_info));
289         if (r)
290                 return r;
291
292         radeon->backend_map = backend_map;
293         radeon->backend_map_valid = TRUE;
294
295         return 0;
296 }
297
298
299 static int radeon_init_fence(struct radeon *radeon)
300 {
301         radeon->fence = 1;
302         radeon->fence_bo = r600_bo(radeon, 4096, 0, 0, 0);
303         if (radeon->fence_bo == NULL) {
304                 return -ENOMEM;
305         }
306         radeon->cfence = r600_bo_map(radeon, radeon->fence_bo, PB_USAGE_UNSYNCHRONIZED, NULL);
307         *radeon->cfence = 0;
308         return 0;
309 }
310
311 #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
312
313 static unsigned handle_hash(void *key)
314 {
315     return PTR_TO_UINT(key);
316 }
317
318 static int handle_compare(void *key1, void *key2)
319 {
320     return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
321 }
322
323 static struct radeon *radeon_new(int fd, unsigned device)
324 {
325         struct radeon *radeon;
326         int r;
327         drmVersionPtr version;
328
329         radeon = calloc(1, sizeof(*radeon));
330         if (radeon == NULL) {
331                 return NULL;
332         }
333         radeon->fd = fd;
334         radeon->device = device;
335         radeon->refcount = 1;
336
337         version = drmGetVersion(radeon->fd);
338         if (version->version_major != 2) {
339                 fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is "
340                         "only compatible with 2.x.x\n", __FUNCTION__,
341                         version->version_major, version->version_minor,
342                         version->version_patchlevel);
343                 drmFreeVersion(version);
344                 exit(1);
345         }
346
347         radeon->minor_version = version->version_minor;
348
349         drmFreeVersion(version);
350
351         r = radeon_get_device(radeon);
352         if (r) {
353                 fprintf(stderr, "Failed to get device id\n");
354                 return radeon_decref(radeon);
355         }
356
357         radeon->family = radeon_family_from_device(radeon->device);
358         if (radeon->family == CHIP_UNKNOWN) {
359                 fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->device);
360                 return radeon_decref(radeon);
361         }
362         /* setup class */
363         switch (radeon->family) {
364         case CHIP_R600:
365         case CHIP_RV610:
366         case CHIP_RV630:
367         case CHIP_RV670:
368         case CHIP_RV620:
369         case CHIP_RV635:
370         case CHIP_RS780:
371         case CHIP_RS880:
372                 radeon->chip_class = R600;
373                 /* set default group bytes, overridden by tiling info ioctl */
374                 radeon->tiling_info.group_bytes = 256;
375                 break;
376         case CHIP_RV770:
377         case CHIP_RV730:
378         case CHIP_RV710:
379         case CHIP_RV740:
380                 radeon->chip_class = R700;
381                 /* set default group bytes, overridden by tiling info ioctl */
382                 radeon->tiling_info.group_bytes = 256;
383                 break;
384         case CHIP_CEDAR:
385         case CHIP_REDWOOD:
386         case CHIP_JUNIPER:
387         case CHIP_CYPRESS:
388         case CHIP_HEMLOCK:
389         case CHIP_PALM:
390         case CHIP_SUMO:
391         case CHIP_SUMO2:
392         case CHIP_BARTS:
393         case CHIP_TURKS:
394         case CHIP_CAICOS:
395                 radeon->chip_class = EVERGREEN;
396                 /* set default group bytes, overridden by tiling info ioctl */
397                 radeon->tiling_info.group_bytes = 512;
398                 break;
399         case CHIP_CAYMAN:
400                 radeon->chip_class = CAYMAN;
401                 /* set default group bytes, overridden by tiling info ioctl */
402                 radeon->tiling_info.group_bytes = 512;
403                 break;
404         default:
405                 fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n",
406                         __func__, radeon->device);
407                 break;
408         }
409
410         if (radeon_drm_get_tiling(radeon))
411                 return NULL;
412
413         /* get the GPU counter frequency, failure is non fatal */
414         radeon_get_clock_crystal_freq(radeon);
415
416         if (radeon->minor_version >= 9)
417                 radeon_get_num_backends(radeon);
418
419         if (radeon->minor_version >= 11) {
420                 radeon_get_num_tile_pipes(radeon);
421                 radeon_get_backend_map(radeon);
422         }
423
424         radeon->bomgr = r600_bomgr_create(radeon, 1000000);
425         if (radeon->bomgr == NULL) {
426                 return NULL;
427         }
428         r = radeon_init_fence(radeon);
429         if (r) {
430                 radeon_decref(radeon);
431                 return NULL;
432         }
433
434         radeon->bo_handles = util_hash_table_create(handle_hash, handle_compare);
435         pipe_mutex_init(radeon->bo_handles_mutex);
436         return radeon;
437 }
438
439 struct radeon *r600_drm_winsys_create(int drmfd)
440 {
441         return radeon_new(drmfd, 0);
442 }
443
444 struct radeon *radeon_decref(struct radeon *radeon)
445 {
446         if (radeon == NULL)
447                 return NULL;
448         if (--radeon->refcount > 0) {
449                 return NULL;
450         }
451
452         util_hash_table_destroy(radeon->bo_handles);
453         pipe_mutex_destroy(radeon->bo_handles_mutex);
454         if (radeon->fence_bo) {
455                 r600_bo_reference(radeon, &radeon->fence_bo, NULL);
456         }
457
458         if (radeon->bomgr)
459                 r600_bomgr_destroy(radeon->bomgr);
460
461         free(radeon);
462         return NULL;
463 }