Merge branch 'vendor/OPENSSL'
[dragonfly.git] / sys / dev / drm / radeon / r200.c
1 /*
2  * Copyright 2008 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  * Copyright 2009 Jerome Glisse.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: Dave Airlie
25  *          Alex Deucher
26  *          Jerome Glisse
27  *
28  * $FreeBSD: head/sys/dev/drm2/radeon/r200.c 254885 2013-08-25 19:37:15Z dumbbell $
29  */
30
31 #include <drm/drmP.h>
32 #include <uapi_drm/radeon_drm.h>
33 #include "radeon_reg.h"
34 #include "radeon.h"
35 #include "radeon_asic.h"
36
37 #include "r100d.h"
38 #include "r200_reg_safe.h"
39
40 #include "r100_track.h"
41
42 static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
43 {
44         int vtx_size, i;
45         vtx_size = 2;
46
47         if (vtx_fmt_0 & R200_VTX_Z0)
48                 vtx_size++;
49         if (vtx_fmt_0 & R200_VTX_W0)
50                 vtx_size++;
51         /* blend weight */
52         if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
53                 vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
54         if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
55                 vtx_size++;
56         if (vtx_fmt_0 & R200_VTX_N0)
57                 vtx_size += 3;
58         if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
59                 vtx_size++;
60         if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
61                 vtx_size++;
62         if (vtx_fmt_0 & R200_VTX_SHININESS_0)
63                 vtx_size++;
64         if (vtx_fmt_0 & R200_VTX_SHININESS_1)
65                 vtx_size++;
66         for (i = 0; i < 8; i++) {
67                 int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
68                 switch (color_size) {
69                 case 0: break;
70                 case 1: vtx_size++; break;
71                 case 2: vtx_size += 3; break;
72                 case 3: vtx_size += 4; break;
73                 }
74         }
75         if (vtx_fmt_0 & R200_VTX_XY1)
76                 vtx_size += 2;
77         if (vtx_fmt_0 & R200_VTX_Z1)
78                 vtx_size++;
79         if (vtx_fmt_0 & R200_VTX_W1)
80                 vtx_size++;
81         if (vtx_fmt_0 & R200_VTX_N1)
82                 vtx_size += 3;
83         return vtx_size;
84 }
85
86 int r200_copy_dma(struct radeon_device *rdev,
87                   uint64_t src_offset,
88                   uint64_t dst_offset,
89                   unsigned num_gpu_pages,
90                   struct radeon_fence **fence)
91 {
92         struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
93         uint32_t size;
94         uint32_t cur_size;
95         int i, num_loops;
96         int r = 0;
97
98         /* radeon pitch is /64 */
99         size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT;
100         num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
101         r = radeon_ring_lock(rdev, ring, num_loops * 4 + 64);
102         if (r) {
103                 DRM_ERROR("radeon: moving bo (%d).\n", r);
104                 return r;
105         }
106         /* Must wait for 2D idle & clean before DMA or hangs might happen */
107         radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
108         radeon_ring_write(ring, (1 << 16));
109         for (i = 0; i < num_loops; i++) {
110                 cur_size = size;
111                 if (cur_size > 0x1FFFFF) {
112                         cur_size = 0x1FFFFF;
113                 }
114                 size -= cur_size;
115                 radeon_ring_write(ring, PACKET0(0x720, 2));
116                 radeon_ring_write(ring, src_offset);
117                 radeon_ring_write(ring, dst_offset);
118                 radeon_ring_write(ring, cur_size | (1 << 31) | (1 << 30));
119                 src_offset += cur_size;
120                 dst_offset += cur_size;
121         }
122         radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
123         radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
124         if (fence) {
125                 r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
126         }
127         radeon_ring_unlock_commit(rdev, ring);
128         return r;
129 }
130
131
132 static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
133 {
134         int vtx_size, i, tex_size;
135         vtx_size = 0;
136         for (i = 0; i < 6; i++) {
137                 tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
138                 if (tex_size > 4)
139                         continue;
140                 vtx_size += tex_size;
141         }
142         return vtx_size;
143 }
144
145 int r200_packet0_check(struct radeon_cs_parser *p,
146                        struct radeon_cs_packet *pkt,
147                        unsigned idx, unsigned reg)
148 {
149         struct radeon_cs_reloc *reloc;
150         struct r100_cs_track *track;
151         volatile uint32_t *ib;
152         uint32_t tmp;
153         int r;
154         int i;
155         int face;
156         u32 tile_flags = 0;
157         u32 idx_value;
158
159         ib = p->ib.ptr;
160         track = (struct r100_cs_track *)p->track;
161         idx_value = radeon_get_ib_value(p, idx);
162         switch (reg) {
163         case RADEON_CRTC_GUI_TRIG_VLINE:
164                 r = r100_cs_packet_parse_vline(p);
165                 if (r) {
166                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
167                                   idx, reg);
168                         r100_cs_dump_packet(p, pkt);
169                         return r;
170                 }
171                 break;
172                 /* FIXME: only allow PACKET3 blit? easier to check for out of
173                  * range access */
174         case RADEON_DST_PITCH_OFFSET:
175         case RADEON_SRC_PITCH_OFFSET:
176                 r = r100_reloc_pitch_offset(p, pkt, idx, reg);
177                 if (r)
178                         return r;
179                 break;
180         case RADEON_RB3D_DEPTHOFFSET:
181                 r = r100_cs_packet_next_reloc(p, &reloc);
182                 if (r) {
183                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
184                                   idx, reg);
185                         r100_cs_dump_packet(p, pkt);
186                         return r;
187                 }
188                 track->zb.robj = reloc->robj;
189                 track->zb.offset = idx_value;
190                 track->zb_dirty = true;
191                 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
192                 break;
193         case RADEON_RB3D_COLOROFFSET:
194                 r = r100_cs_packet_next_reloc(p, &reloc);
195                 if (r) {
196                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
197                                   idx, reg);
198                         r100_cs_dump_packet(p, pkt);
199                         return r;
200                 }
201                 track->cb[0].robj = reloc->robj;
202                 track->cb[0].offset = idx_value;
203                 track->cb_dirty = true;
204                 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
205                 break;
206         case R200_PP_TXOFFSET_0:
207         case R200_PP_TXOFFSET_1:
208         case R200_PP_TXOFFSET_2:
209         case R200_PP_TXOFFSET_3:
210         case R200_PP_TXOFFSET_4:
211         case R200_PP_TXOFFSET_5:
212                 i = (reg - R200_PP_TXOFFSET_0) / 24;
213                 r = r100_cs_packet_next_reloc(p, &reloc);
214                 if (r) {
215                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
216                                   idx, reg);
217                         r100_cs_dump_packet(p, pkt);
218                         return r;
219                 }
220                 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
221                         if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
222                                 tile_flags |= R200_TXO_MACRO_TILE;
223                         if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
224                                 tile_flags |= R200_TXO_MICRO_TILE;
225
226                         tmp = idx_value & ~(0x7 << 2);
227                         tmp |= tile_flags;
228                         ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset);
229                 } else
230                         ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
231                 track->textures[i].robj = reloc->robj;
232                 track->tex_dirty = true;
233                 break;
234         case R200_PP_CUBIC_OFFSET_F1_0:
235         case R200_PP_CUBIC_OFFSET_F2_0:
236         case R200_PP_CUBIC_OFFSET_F3_0:
237         case R200_PP_CUBIC_OFFSET_F4_0:
238         case R200_PP_CUBIC_OFFSET_F5_0:
239         case R200_PP_CUBIC_OFFSET_F1_1:
240         case R200_PP_CUBIC_OFFSET_F2_1:
241         case R200_PP_CUBIC_OFFSET_F3_1:
242         case R200_PP_CUBIC_OFFSET_F4_1:
243         case R200_PP_CUBIC_OFFSET_F5_1:
244         case R200_PP_CUBIC_OFFSET_F1_2:
245         case R200_PP_CUBIC_OFFSET_F2_2:
246         case R200_PP_CUBIC_OFFSET_F3_2:
247         case R200_PP_CUBIC_OFFSET_F4_2:
248         case R200_PP_CUBIC_OFFSET_F5_2:
249         case R200_PP_CUBIC_OFFSET_F1_3:
250         case R200_PP_CUBIC_OFFSET_F2_3:
251         case R200_PP_CUBIC_OFFSET_F3_3:
252         case R200_PP_CUBIC_OFFSET_F4_3:
253         case R200_PP_CUBIC_OFFSET_F5_3:
254         case R200_PP_CUBIC_OFFSET_F1_4:
255         case R200_PP_CUBIC_OFFSET_F2_4:
256         case R200_PP_CUBIC_OFFSET_F3_4:
257         case R200_PP_CUBIC_OFFSET_F4_4:
258         case R200_PP_CUBIC_OFFSET_F5_4:
259         case R200_PP_CUBIC_OFFSET_F1_5:
260         case R200_PP_CUBIC_OFFSET_F2_5:
261         case R200_PP_CUBIC_OFFSET_F3_5:
262         case R200_PP_CUBIC_OFFSET_F4_5:
263         case R200_PP_CUBIC_OFFSET_F5_5:
264                 i = (reg - R200_PP_TXOFFSET_0) / 24;
265                 face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
266                 r = r100_cs_packet_next_reloc(p, &reloc);
267                 if (r) {
268                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
269                                   idx, reg);
270                         r100_cs_dump_packet(p, pkt);
271                         return r;
272                 }
273                 track->textures[i].cube_info[face - 1].offset = idx_value;
274                 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
275                 track->textures[i].cube_info[face - 1].robj = reloc->robj;
276                 track->tex_dirty = true;
277                 break;
278         case RADEON_RE_WIDTH_HEIGHT:
279                 track->maxy = ((idx_value >> 16) & 0x7FF);
280                 track->cb_dirty = true;
281                 track->zb_dirty = true;
282                 break;
283         case RADEON_RB3D_COLORPITCH:
284                 r = r100_cs_packet_next_reloc(p, &reloc);
285                 if (r) {
286                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
287                                   idx, reg);
288                         r100_cs_dump_packet(p, pkt);
289                         return r;
290                 }
291
292                 if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
293                         if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
294                                 tile_flags |= RADEON_COLOR_TILE_ENABLE;
295                         if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
296                                 tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
297
298                         tmp = idx_value & ~(0x7 << 16);
299                         tmp |= tile_flags;
300                         ib[idx] = tmp;
301                 } else
302                         ib[idx] = idx_value;
303
304                 track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
305                 track->cb_dirty = true;
306                 break;
307         case RADEON_RB3D_DEPTHPITCH:
308                 track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
309                 track->zb_dirty = true;
310                 break;
311         case RADEON_RB3D_CNTL:
312                 switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
313                 case 7:
314                 case 8:
315                 case 9:
316                 case 11:
317                 case 12:
318                         track->cb[0].cpp = 1;
319                         break;
320                 case 3:
321                 case 4:
322                 case 15:
323                         track->cb[0].cpp = 2;
324                         break;
325                 case 6:
326                         track->cb[0].cpp = 4;
327                         break;
328                 default:
329                         DRM_ERROR("Invalid color buffer format (%d) !\n",
330                                   ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
331                         return -EINVAL;
332                 }
333                 if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
334                         DRM_ERROR("No support for depth xy offset in kms\n");
335                         return -EINVAL;
336                 }
337
338                 track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
339                 track->cb_dirty = true;
340                 track->zb_dirty = true;
341                 break;
342         case RADEON_RB3D_ZSTENCILCNTL:
343                 switch (idx_value & 0xf) {
344                 case 0:
345                         track->zb.cpp = 2;
346                         break;
347                 case 2:
348                 case 3:
349                 case 4:
350                 case 5:
351                 case 9:
352                 case 11:
353                         track->zb.cpp = 4;
354                         break;
355                 default:
356                         break;
357                 }
358                 track->zb_dirty = true;
359                 break;
360         case RADEON_RB3D_ZPASS_ADDR:
361                 r = r100_cs_packet_next_reloc(p, &reloc);
362                 if (r) {
363                         DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
364                                   idx, reg);
365                         r100_cs_dump_packet(p, pkt);
366                         return r;
367                 }
368                 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
369                 break;
370         case RADEON_PP_CNTL:
371                 {
372                         uint32_t temp = idx_value >> 4;
373                         for (i = 0; i < track->num_texture; i++)
374                                 track->textures[i].enabled = !!(temp & (1 << i));
375                         track->tex_dirty = true;
376                 }
377                 break;
378         case RADEON_SE_VF_CNTL:
379                 track->vap_vf_cntl = idx_value;
380                 break;
381         case 0x210c:
382                 /* VAP_VF_MAX_VTX_INDX */
383                 track->max_indx = idx_value & 0x00FFFFFFUL;
384                 break;
385         case R200_SE_VTX_FMT_0:
386                 track->vtx_size = r200_get_vtx_size_0(idx_value);
387                 break;
388         case R200_SE_VTX_FMT_1:
389                 track->vtx_size += r200_get_vtx_size_1(idx_value);
390                 break;
391         case R200_PP_TXSIZE_0:
392         case R200_PP_TXSIZE_1:
393         case R200_PP_TXSIZE_2:
394         case R200_PP_TXSIZE_3:
395         case R200_PP_TXSIZE_4:
396         case R200_PP_TXSIZE_5:
397                 i = (reg - R200_PP_TXSIZE_0) / 32;
398                 track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
399                 track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
400                 track->tex_dirty = true;
401                 break;
402         case R200_PP_TXPITCH_0:
403         case R200_PP_TXPITCH_1:
404         case R200_PP_TXPITCH_2:
405         case R200_PP_TXPITCH_3:
406         case R200_PP_TXPITCH_4:
407         case R200_PP_TXPITCH_5:
408                 i = (reg - R200_PP_TXPITCH_0) / 32;
409                 track->textures[i].pitch = idx_value + 32;
410                 track->tex_dirty = true;
411                 break;
412         case R200_PP_TXFILTER_0:
413         case R200_PP_TXFILTER_1:
414         case R200_PP_TXFILTER_2:
415         case R200_PP_TXFILTER_3:
416         case R200_PP_TXFILTER_4:
417         case R200_PP_TXFILTER_5:
418                 i = (reg - R200_PP_TXFILTER_0) / 32;
419                 track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
420                                                  >> R200_MAX_MIP_LEVEL_SHIFT);
421                 tmp = (idx_value >> 23) & 0x7;
422                 if (tmp == 2 || tmp == 6)
423                         track->textures[i].roundup_w = false;
424                 tmp = (idx_value >> 27) & 0x7;
425                 if (tmp == 2 || tmp == 6)
426                         track->textures[i].roundup_h = false;
427                 track->tex_dirty = true;
428                 break;
429         case R200_PP_TXMULTI_CTL_0:
430         case R200_PP_TXMULTI_CTL_1:
431         case R200_PP_TXMULTI_CTL_2:
432         case R200_PP_TXMULTI_CTL_3:
433         case R200_PP_TXMULTI_CTL_4:
434         case R200_PP_TXMULTI_CTL_5:
435                 i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
436                 break;
437         case R200_PP_TXFORMAT_X_0:
438         case R200_PP_TXFORMAT_X_1:
439         case R200_PP_TXFORMAT_X_2:
440         case R200_PP_TXFORMAT_X_3:
441         case R200_PP_TXFORMAT_X_4:
442         case R200_PP_TXFORMAT_X_5:
443                 i = (reg - R200_PP_TXFORMAT_X_0) / 32;
444                 track->textures[i].txdepth = idx_value & 0x7;
445                 tmp = (idx_value >> 16) & 0x3;
446                 /* 2D, 3D, CUBE */
447                 switch (tmp) {
448                 case 0:
449                 case 3:
450                 case 4:
451                 case 5:
452                 case 6:
453                 case 7:
454                         /* 1D/2D */
455                         track->textures[i].tex_coord_type = 0;
456                         break;
457                 case 1:
458                         /* CUBE */
459                         track->textures[i].tex_coord_type = 2;
460                         break;
461                 case 2:
462                         /* 3D */
463                         track->textures[i].tex_coord_type = 1;
464                         break;
465                 }
466                 track->tex_dirty = true;
467                 break;
468         case R200_PP_TXFORMAT_0:
469         case R200_PP_TXFORMAT_1:
470         case R200_PP_TXFORMAT_2:
471         case R200_PP_TXFORMAT_3:
472         case R200_PP_TXFORMAT_4:
473         case R200_PP_TXFORMAT_5:
474                 i = (reg - R200_PP_TXFORMAT_0) / 32;
475                 if (idx_value & R200_TXFORMAT_NON_POWER2) {
476                         track->textures[i].use_pitch = 1;
477                 } else {
478                         track->textures[i].use_pitch = 0;
479                         track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
480                         track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
481                 }
482                 if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
483                         track->textures[i].lookup_disable = true;
484                 switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
485                 case R200_TXFORMAT_I8:
486                 case R200_TXFORMAT_RGB332:
487                 case R200_TXFORMAT_Y8:
488                         track->textures[i].cpp = 1;
489                         track->textures[i].compress_format = R100_TRACK_COMP_NONE;
490                         break;
491                 case R200_TXFORMAT_AI88:
492                 case R200_TXFORMAT_ARGB1555:
493                 case R200_TXFORMAT_RGB565:
494                 case R200_TXFORMAT_ARGB4444:
495                 case R200_TXFORMAT_VYUY422:
496                 case R200_TXFORMAT_YVYU422:
497                 case R200_TXFORMAT_LDVDU655:
498                 case R200_TXFORMAT_DVDU88:
499                 case R200_TXFORMAT_AVYU4444:
500                         track->textures[i].cpp = 2;
501                         track->textures[i].compress_format = R100_TRACK_COMP_NONE;
502                         break;
503                 case R200_TXFORMAT_ARGB8888:
504                 case R200_TXFORMAT_RGBA8888:
505                 case R200_TXFORMAT_ABGR8888:
506                 case R200_TXFORMAT_BGR111110:
507                 case R200_TXFORMAT_LDVDU8888:
508                         track->textures[i].cpp = 4;
509                         track->textures[i].compress_format = R100_TRACK_COMP_NONE;
510                         break;
511                 case R200_TXFORMAT_DXT1:
512                         track->textures[i].cpp = 1;
513                         track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
514                         break;
515                 case R200_TXFORMAT_DXT23:
516                 case R200_TXFORMAT_DXT45:
517                         track->textures[i].cpp = 1;
518                         track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
519                         break;
520                 }
521                 track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
522                 track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
523                 track->tex_dirty = true;
524                 break;
525         case R200_PP_CUBIC_FACES_0:
526         case R200_PP_CUBIC_FACES_1:
527         case R200_PP_CUBIC_FACES_2:
528         case R200_PP_CUBIC_FACES_3:
529         case R200_PP_CUBIC_FACES_4:
530         case R200_PP_CUBIC_FACES_5:
531                 tmp = idx_value;
532                 i = (reg - R200_PP_CUBIC_FACES_0) / 32;
533                 for (face = 0; face < 4; face++) {
534                         track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
535                         track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
536                 }
537                 track->tex_dirty = true;
538                 break;
539         default:
540                 DRM_ERROR("Forbidden register 0x%04X in cs at %d\n",
541                        reg, idx);
542                 return -EINVAL;
543         }
544         return 0;
545 }
546
547 void r200_set_safe_registers(struct radeon_device *rdev)
548 {
549         rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
550         rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(r200_reg_safe_bm);
551 }