36ec583ccee7e2768dd549df11aab0bea8701b32
[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 #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 "r600.h"
34 #include "r600_priv.h"
35 #include "r600_drm_public.h"
36 #include "xf86drm.h"
37 #include "radeon_drm.h"
38
39 #ifndef RADEON_INFO_TILING_CONFIG
40 #define RADEON_INFO_TILING_CONFIG 0x6
41 #endif
42
43 static struct radeon *radeon_new(int fd, unsigned device);
44
45 enum radeon_family r600_get_family(struct radeon *r600)
46 {
47 return r600->family;
48 }
49
50 enum chip_class r600_get_family_class(struct radeon *radeon)
51 {
52 return radeon->chip_class;
53 }
54
55 struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon)
56 {
57 return &radeon->tiling_info;
58 }
59
60 static int radeon_get_device(struct radeon *radeon)
61 {
62 struct drm_radeon_info info;
63 int r;
64
65 radeon->device = 0;
66 info.request = RADEON_INFO_DEVICE_ID;
67 info.value = (uintptr_t)&radeon->device;
68 r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
69 sizeof(struct drm_radeon_info));
70 return r;
71 }
72
73 static int radeon_drm_get_tiling(struct radeon *radeon)
74 {
75 struct drm_radeon_info info;
76 int r;
77 uint32_t tiling_config;
78
79 info.request = RADEON_INFO_TILING_CONFIG;
80 info.value = (uintptr_t)&tiling_config;
81 r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
82 sizeof(struct drm_radeon_info));
83
84 if (r)
85 return 0;
86
87 switch ((tiling_config & 0xe) >> 1) {
88 case 0:
89 radeon->tiling_info.num_channels = 1;
90 break;
91 case 1:
92 radeon->tiling_info.num_channels = 2;
93 break;
94 case 2:
95 radeon->tiling_info.num_channels = 4;
96 break;
97 case 3:
98 radeon->tiling_info.num_channels = 8;
99 break;
100 default:
101 return -EINVAL;
102 }
103
104 switch ((tiling_config & 0x30) >> 4) {
105 case 0:
106 radeon->tiling_info.num_banks = 4;
107 break;
108 case 1:
109 radeon->tiling_info.num_banks = 8;
110 break;
111 default:
112 return -EINVAL;
113
114 }
115 switch ((tiling_config & 0xc0) >> 6) {
116 case 0:
117 radeon->tiling_info.group_bytes = 256;
118 break;
119 case 1:
120 radeon->tiling_info.group_bytes = 512;
121 break;
122 default:
123 return -EINVAL;
124 }
125 return 0;
126 }
127
128 static struct radeon *radeon_new(int fd, unsigned device)
129 {
130 struct radeon *radeon;
131 int r;
132
133 radeon = calloc(1, sizeof(*radeon));
134 if (radeon == NULL) {
135 return NULL;
136 }
137 radeon->fd = fd;
138 radeon->device = device;
139 radeon->refcount = 1;
140 if (fd >= 0) {
141 r = radeon_get_device(radeon);
142 if (r) {
143 fprintf(stderr, "Failed to get device id\n");
144 return radeon_decref(radeon);
145 }
146 }
147 radeon->family = radeon_family_from_device(radeon->device);
148 if (radeon->family == CHIP_UNKNOWN) {
149 fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->device);
150 return radeon_decref(radeon);
151 }
152 /* setup class */
153 switch (radeon->family) {
154 case CHIP_R600:
155 case CHIP_RV610:
156 case CHIP_RV630:
157 case CHIP_RV670:
158 case CHIP_RV620:
159 case CHIP_RV635:
160 case CHIP_RS780:
161 case CHIP_RS880:
162 radeon->chip_class = R600;
163 /* set default group bytes, overridden by tiling info ioctl */
164 radeon->tiling_info.group_bytes = 256;
165 break;
166 case CHIP_RV770:
167 case CHIP_RV730:
168 case CHIP_RV710:
169 case CHIP_RV740:
170 radeon->chip_class = R700;
171 /* set default group bytes, overridden by tiling info ioctl */
172 radeon->tiling_info.group_bytes = 256;
173 break;
174 case CHIP_CEDAR:
175 case CHIP_REDWOOD:
176 case CHIP_JUNIPER:
177 case CHIP_CYPRESS:
178 case CHIP_HEMLOCK:
179 case CHIP_PALM:
180 case CHIP_BARTS:
181 case CHIP_TURKS:
182 case CHIP_CAICOS:
183 radeon->chip_class = EVERGREEN;
184 /* set default group bytes, overridden by tiling info ioctl */
185 radeon->tiling_info.group_bytes = 512;
186 break;
187 default:
188 fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n",
189 __func__, radeon->device);
190 break;
191 }
192
193 if (radeon->chip_class == R600 || radeon->chip_class == R700) {
194 if (radeon_drm_get_tiling(radeon))
195 return NULL;
196 }
197 radeon->bomgr = r600_bomgr_create(radeon, 1000000);
198 if (radeon->bomgr == NULL) {
199 return NULL;
200 }
201 return radeon;
202 }
203
204 struct radeon *r600_drm_winsys_create(int drmfd)
205 {
206 return radeon_new(drmfd, 0);
207 }
208
209 struct radeon *radeon_decref(struct radeon *radeon)
210 {
211 if (radeon == NULL)
212 return NULL;
213 if (--radeon->refcount > 0) {
214 return NULL;
215 }
216
217 if (radeon->bomgr)
218 r600_bomgr_destroy(radeon->bomgr);
219
220 if (radeon->fd >= 0)
221 drmClose(radeon->fd);
222
223 free(radeon);
224 return NULL;
225 }