7d5583fd287d2aadacc1b91ee0b21fad0892897d
[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 <errno.h>
33
34 #ifndef RADEON_INFO_NUM_TILE_PIPES
35 #define RADEON_INFO_NUM_TILE_PIPES 0xb
36 #endif
37
38 #ifndef RADEON_INFO_BACKEND_MAP
39 #define RADEON_INFO_BACKEND_MAP 0xd
40 #endif
41
42 enum radeon_family r600_get_family(struct radeon *r600)
43 {
44 return r600->family;
45 }
46
47 enum chip_class r600_get_family_class(struct radeon *radeon)
48 {
49 return radeon->chip_class;
50 }
51
52 struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon)
53 {
54 return &radeon->tiling_info;
55 }
56
57 unsigned r600_get_clock_crystal_freq(struct radeon *radeon)
58 {
59 return radeon->info.r600_clock_crystal_freq;
60 }
61
62 unsigned r600_get_num_backends(struct radeon *radeon)
63 {
64 return radeon->info.r600_num_backends;
65 }
66
67 unsigned r600_get_num_tile_pipes(struct radeon *radeon)
68 {
69 return radeon->info.r600_num_tile_pipes;
70 }
71
72 unsigned r600_get_backend_map(struct radeon *radeon)
73 {
74 return radeon->info.r600_backend_map;
75 }
76
77 unsigned r600_get_minor_version(struct radeon *radeon)
78 {
79 return radeon->info.drm_minor;
80 }
81
82 static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
83 {
84 switch ((tiling_config & 0xe) >> 1) {
85 case 0:
86 radeon->tiling_info.num_channels = 1;
87 break;
88 case 1:
89 radeon->tiling_info.num_channels = 2;
90 break;
91 case 2:
92 radeon->tiling_info.num_channels = 4;
93 break;
94 case 3:
95 radeon->tiling_info.num_channels = 8;
96 break;
97 default:
98 return -EINVAL;
99 }
100
101 switch ((tiling_config & 0x30) >> 4) {
102 case 0:
103 radeon->tiling_info.num_banks = 4;
104 break;
105 case 1:
106 radeon->tiling_info.num_banks = 8;
107 break;
108 default:
109 return -EINVAL;
110
111 }
112 switch ((tiling_config & 0xc0) >> 6) {
113 case 0:
114 radeon->tiling_info.group_bytes = 256;
115 break;
116 case 1:
117 radeon->tiling_info.group_bytes = 512;
118 break;
119 default:
120 return -EINVAL;
121 }
122 return 0;
123 }
124
125 static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
126 {
127 switch (tiling_config & 0xf) {
128 case 0:
129 radeon->tiling_info.num_channels = 1;
130 break;
131 case 1:
132 radeon->tiling_info.num_channels = 2;
133 break;
134 case 2:
135 radeon->tiling_info.num_channels = 4;
136 break;
137 case 3:
138 radeon->tiling_info.num_channels = 8;
139 break;
140 default:
141 return -EINVAL;
142 }
143
144 switch ((tiling_config & 0xf0) >> 4) {
145 case 0:
146 radeon->tiling_info.num_banks = 4;
147 break;
148 case 1:
149 radeon->tiling_info.num_banks = 8;
150 break;
151 case 2:
152 radeon->tiling_info.num_banks = 16;
153 break;
154 default:
155 return -EINVAL;
156
157 }
158
159 switch ((tiling_config & 0xf00) >> 8) {
160 case 0:
161 radeon->tiling_info.group_bytes = 256;
162 break;
163 case 1:
164 radeon->tiling_info.group_bytes = 512;
165 break;
166 default:
167 return -EINVAL;
168 }
169 return 0;
170 }
171
172 static int radeon_drm_get_tiling(struct radeon *radeon)
173 {
174 uint32_t tiling_config = radeon->info.r600_tiling_config;
175
176 if (!tiling_config)
177 return 0;
178
179 if (radeon->chip_class == R600 || radeon->chip_class == R700) {
180 return r600_interpret_tiling(radeon, tiling_config);
181 } else {
182 return eg_interpret_tiling(radeon, tiling_config);
183 }
184 }
185
186 struct radeon *radeon_create(struct radeon_winsys *ws)
187 {
188 struct radeon *radeon = CALLOC_STRUCT(radeon);
189 if (radeon == NULL) {
190 return NULL;
191 }
192
193 radeon->ws = ws;
194 ws->query_info(ws, &radeon->info);
195
196 radeon->family = radeon_family_from_device(radeon->info.pci_id);
197 if (radeon->family == CHIP_UNKNOWN) {
198 fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->info.pci_id);
199 return radeon_destroy(radeon);
200 }
201 /* setup class */
202 switch (radeon->family) {
203 case CHIP_R600:
204 case CHIP_RV610:
205 case CHIP_RV630:
206 case CHIP_RV670:
207 case CHIP_RV620:
208 case CHIP_RV635:
209 case CHIP_RS780:
210 case CHIP_RS880:
211 radeon->chip_class = R600;
212 /* set default group bytes, overridden by tiling info ioctl */
213 radeon->tiling_info.group_bytes = 256;
214 break;
215 case CHIP_RV770:
216 case CHIP_RV730:
217 case CHIP_RV710:
218 case CHIP_RV740:
219 radeon->chip_class = R700;
220 /* set default group bytes, overridden by tiling info ioctl */
221 radeon->tiling_info.group_bytes = 256;
222 break;
223 case CHIP_CEDAR:
224 case CHIP_REDWOOD:
225 case CHIP_JUNIPER:
226 case CHIP_CYPRESS:
227 case CHIP_HEMLOCK:
228 case CHIP_PALM:
229 case CHIP_SUMO:
230 case CHIP_SUMO2:
231 case CHIP_BARTS:
232 case CHIP_TURKS:
233 case CHIP_CAICOS:
234 radeon->chip_class = EVERGREEN;
235 /* set default group bytes, overridden by tiling info ioctl */
236 radeon->tiling_info.group_bytes = 512;
237 break;
238 case CHIP_CAYMAN:
239 radeon->chip_class = CAYMAN;
240 /* set default group bytes, overridden by tiling info ioctl */
241 radeon->tiling_info.group_bytes = 512;
242 break;
243 default:
244 fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n",
245 __func__, radeon->info.pci_id);
246 break;
247 }
248
249 if (radeon_drm_get_tiling(radeon))
250 return NULL;
251
252 return radeon;
253 }
254
255 struct radeon *radeon_destroy(struct radeon *radeon)
256 {
257 if (radeon == NULL)
258 return NULL;
259
260 FREE(radeon);
261 return NULL;
262 }