linux/drivers/gpu/drm/radeon/r200.c
<<
>>
Prefs
   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#include "drmP.h"
  29#include "drm.h"
  30#include "radeon_drm.h"
  31#include "radeon_reg.h"
  32#include "radeon.h"
  33
  34#include "r200_reg_safe.h"
  35
  36#include "r100_track.h"
  37
  38static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
  39{
  40        int vtx_size, i;
  41        vtx_size = 2;
  42
  43        if (vtx_fmt_0 & R200_VTX_Z0)
  44                vtx_size++;
  45        if (vtx_fmt_0 & R200_VTX_W0)
  46                vtx_size++;
  47        /* blend weight */
  48        if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
  49                vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
  50        if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
  51                vtx_size++;
  52        if (vtx_fmt_0 & R200_VTX_N0)
  53                vtx_size += 3;
  54        if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
  55                vtx_size++;
  56        if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
  57                vtx_size++;
  58        if (vtx_fmt_0 & R200_VTX_SHININESS_0)
  59                vtx_size++;
  60        if (vtx_fmt_0 & R200_VTX_SHININESS_1)
  61                vtx_size++;
  62        for (i = 0; i < 8; i++) {
  63                int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
  64                switch (color_size) {
  65                case 0: break;
  66                case 1: vtx_size++; break;
  67                case 2: vtx_size += 3; break;
  68                case 3: vtx_size += 4; break;
  69                }
  70        }
  71        if (vtx_fmt_0 & R200_VTX_XY1)
  72                vtx_size += 2;
  73        if (vtx_fmt_0 & R200_VTX_Z1)
  74                vtx_size++;
  75        if (vtx_fmt_0 & R200_VTX_W1)
  76                vtx_size++;
  77        if (vtx_fmt_0 & R200_VTX_N1)
  78                vtx_size += 3;
  79        return vtx_size;
  80}
  81
  82static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
  83{
  84        int vtx_size, i, tex_size;
  85        vtx_size = 0;
  86        for (i = 0; i < 6; i++) {
  87                tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
  88                if (tex_size > 4)
  89                        continue;
  90                vtx_size += tex_size;
  91        }
  92        return vtx_size;
  93}
  94
  95int r200_packet0_check(struct radeon_cs_parser *p,
  96                       struct radeon_cs_packet *pkt,
  97                       unsigned idx, unsigned reg)
  98{
  99        struct radeon_cs_reloc *reloc;
 100        struct r100_cs_track *track;
 101        volatile uint32_t *ib;
 102        uint32_t tmp;
 103        int r;
 104        int i;
 105        int face;
 106        u32 tile_flags = 0;
 107        u32 idx_value;
 108
 109        ib = p->ib->ptr;
 110        track = (struct r100_cs_track *)p->track;
 111        idx_value = radeon_get_ib_value(p, idx);
 112        switch (reg) {
 113        case RADEON_CRTC_GUI_TRIG_VLINE:
 114                r = r100_cs_packet_parse_vline(p);
 115                if (r) {
 116                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 117                                  idx, reg);
 118                        r100_cs_dump_packet(p, pkt);
 119                        return r;
 120                }
 121                break;
 122                /* FIXME: only allow PACKET3 blit? easier to check for out of
 123                 * range access */
 124        case RADEON_DST_PITCH_OFFSET:
 125        case RADEON_SRC_PITCH_OFFSET:
 126                r = r100_reloc_pitch_offset(p, pkt, idx, reg);
 127                if (r)
 128                        return r;
 129                break;
 130        case RADEON_RB3D_DEPTHOFFSET:
 131                r = r100_cs_packet_next_reloc(p, &reloc);
 132                if (r) {
 133                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 134                                  idx, reg);
 135                        r100_cs_dump_packet(p, pkt);
 136                        return r;
 137                }
 138                track->zb.robj = reloc->robj;
 139                track->zb.offset = idx_value;
 140                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 141                break;
 142        case RADEON_RB3D_COLOROFFSET:
 143                r = r100_cs_packet_next_reloc(p, &reloc);
 144                if (r) {
 145                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 146                                  idx, reg);
 147                        r100_cs_dump_packet(p, pkt);
 148                        return r;
 149                }
 150                track->cb[0].robj = reloc->robj;
 151                track->cb[0].offset = idx_value;
 152                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 153                break;
 154        case R200_PP_TXOFFSET_0:
 155        case R200_PP_TXOFFSET_1:
 156        case R200_PP_TXOFFSET_2:
 157        case R200_PP_TXOFFSET_3:
 158        case R200_PP_TXOFFSET_4:
 159        case R200_PP_TXOFFSET_5:
 160                i = (reg - R200_PP_TXOFFSET_0) / 24;
 161                r = r100_cs_packet_next_reloc(p, &reloc);
 162                if (r) {
 163                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 164                                  idx, reg);
 165                        r100_cs_dump_packet(p, pkt);
 166                        return r;
 167                }
 168                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 169                track->textures[i].robj = reloc->robj;
 170                break;
 171        case R200_PP_CUBIC_OFFSET_F1_0:
 172        case R200_PP_CUBIC_OFFSET_F2_0:
 173        case R200_PP_CUBIC_OFFSET_F3_0:
 174        case R200_PP_CUBIC_OFFSET_F4_0:
 175        case R200_PP_CUBIC_OFFSET_F5_0:
 176        case R200_PP_CUBIC_OFFSET_F1_1:
 177        case R200_PP_CUBIC_OFFSET_F2_1:
 178        case R200_PP_CUBIC_OFFSET_F3_1:
 179        case R200_PP_CUBIC_OFFSET_F4_1:
 180        case R200_PP_CUBIC_OFFSET_F5_1:
 181        case R200_PP_CUBIC_OFFSET_F1_2:
 182        case R200_PP_CUBIC_OFFSET_F2_2:
 183        case R200_PP_CUBIC_OFFSET_F3_2:
 184        case R200_PP_CUBIC_OFFSET_F4_2:
 185        case R200_PP_CUBIC_OFFSET_F5_2:
 186        case R200_PP_CUBIC_OFFSET_F1_3:
 187        case R200_PP_CUBIC_OFFSET_F2_3:
 188        case R200_PP_CUBIC_OFFSET_F3_3:
 189        case R200_PP_CUBIC_OFFSET_F4_3:
 190        case R200_PP_CUBIC_OFFSET_F5_3:
 191        case R200_PP_CUBIC_OFFSET_F1_4:
 192        case R200_PP_CUBIC_OFFSET_F2_4:
 193        case R200_PP_CUBIC_OFFSET_F3_4:
 194        case R200_PP_CUBIC_OFFSET_F4_4:
 195        case R200_PP_CUBIC_OFFSET_F5_4:
 196        case R200_PP_CUBIC_OFFSET_F1_5:
 197        case R200_PP_CUBIC_OFFSET_F2_5:
 198        case R200_PP_CUBIC_OFFSET_F3_5:
 199        case R200_PP_CUBIC_OFFSET_F4_5:
 200        case R200_PP_CUBIC_OFFSET_F5_5:
 201                i = (reg - R200_PP_TXOFFSET_0) / 24;
 202                face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
 203                r = r100_cs_packet_next_reloc(p, &reloc);
 204                if (r) {
 205                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 206                                  idx, reg);
 207                        r100_cs_dump_packet(p, pkt);
 208                        return r;
 209                }
 210                track->textures[i].cube_info[face - 1].offset = idx_value;
 211                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 212                track->textures[i].cube_info[face - 1].robj = reloc->robj;
 213                break;
 214        case RADEON_RE_WIDTH_HEIGHT:
 215                track->maxy = ((idx_value >> 16) & 0x7FF);
 216                break;
 217        case RADEON_RB3D_COLORPITCH:
 218                r = r100_cs_packet_next_reloc(p, &reloc);
 219                if (r) {
 220                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 221                                  idx, reg);
 222                        r100_cs_dump_packet(p, pkt);
 223                        return r;
 224                }
 225
 226                if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 227                        tile_flags |= RADEON_COLOR_TILE_ENABLE;
 228                if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
 229                        tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
 230
 231                tmp = idx_value & ~(0x7 << 16);
 232                tmp |= tile_flags;
 233                ib[idx] = tmp;
 234
 235                track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
 236                break;
 237        case RADEON_RB3D_DEPTHPITCH:
 238                track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
 239                break;
 240        case RADEON_RB3D_CNTL:
 241                switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
 242                case 7:
 243                case 8:
 244                case 9:
 245                case 11:
 246                case 12:
 247                        track->cb[0].cpp = 1;
 248                        break;
 249                case 3:
 250                case 4:
 251                case 15:
 252                        track->cb[0].cpp = 2;
 253                        break;
 254                case 6:
 255                        track->cb[0].cpp = 4;
 256                        break;
 257                default:
 258                        DRM_ERROR("Invalid color buffer format (%d) !\n",
 259                                  ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
 260                        return -EINVAL;
 261                }
 262                if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
 263                        DRM_ERROR("No support for depth xy offset in kms\n");
 264                        return -EINVAL;
 265                }
 266
 267                track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
 268                break;
 269        case RADEON_RB3D_ZSTENCILCNTL:
 270                switch (idx_value & 0xf) {
 271                case 0:
 272                        track->zb.cpp = 2;
 273                        break;
 274                case 2:
 275                case 3:
 276                case 4:
 277                case 5:
 278                case 9:
 279                case 11:
 280                        track->zb.cpp = 4;
 281                        break;
 282                default:
 283                        break;
 284                }
 285                break;
 286        case RADEON_RB3D_ZPASS_ADDR:
 287                r = r100_cs_packet_next_reloc(p, &reloc);
 288                if (r) {
 289                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 290                                  idx, reg);
 291                        r100_cs_dump_packet(p, pkt);
 292                        return r;
 293                }
 294                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 295                break;
 296        case RADEON_PP_CNTL:
 297                {
 298                        uint32_t temp = idx_value >> 4;
 299                        for (i = 0; i < track->num_texture; i++)
 300                                track->textures[i].enabled = !!(temp & (1 << i));
 301                }
 302                break;
 303        case RADEON_SE_VF_CNTL:
 304                track->vap_vf_cntl = idx_value;
 305                break;
 306        case 0x210c:
 307                /* VAP_VF_MAX_VTX_INDX */
 308                track->max_indx = idx_value & 0x00FFFFFFUL;
 309                break;
 310        case R200_SE_VTX_FMT_0:
 311                track->vtx_size = r200_get_vtx_size_0(idx_value);
 312                break;
 313        case R200_SE_VTX_FMT_1:
 314                track->vtx_size += r200_get_vtx_size_1(idx_value);
 315                break;
 316        case R200_PP_TXSIZE_0:
 317        case R200_PP_TXSIZE_1:
 318        case R200_PP_TXSIZE_2:
 319        case R200_PP_TXSIZE_3:
 320        case R200_PP_TXSIZE_4:
 321        case R200_PP_TXSIZE_5:
 322                i = (reg - R200_PP_TXSIZE_0) / 32;
 323                track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
 324                track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
 325                break;
 326        case R200_PP_TXPITCH_0:
 327        case R200_PP_TXPITCH_1:
 328        case R200_PP_TXPITCH_2:
 329        case R200_PP_TXPITCH_3:
 330        case R200_PP_TXPITCH_4:
 331        case R200_PP_TXPITCH_5:
 332                i = (reg - R200_PP_TXPITCH_0) / 32;
 333                track->textures[i].pitch = idx_value + 32;
 334                break;
 335        case R200_PP_TXFILTER_0:
 336        case R200_PP_TXFILTER_1:
 337        case R200_PP_TXFILTER_2:
 338        case R200_PP_TXFILTER_3:
 339        case R200_PP_TXFILTER_4:
 340        case R200_PP_TXFILTER_5:
 341                i = (reg - R200_PP_TXFILTER_0) / 32;
 342                track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
 343                                                 >> R200_MAX_MIP_LEVEL_SHIFT);
 344                tmp = (idx_value >> 23) & 0x7;
 345                if (tmp == 2 || tmp == 6)
 346                        track->textures[i].roundup_w = false;
 347                tmp = (idx_value >> 27) & 0x7;
 348                if (tmp == 2 || tmp == 6)
 349                        track->textures[i].roundup_h = false;
 350                break;
 351        case R200_PP_TXMULTI_CTL_0:
 352        case R200_PP_TXMULTI_CTL_1:
 353        case R200_PP_TXMULTI_CTL_2:
 354        case R200_PP_TXMULTI_CTL_3:
 355        case R200_PP_TXMULTI_CTL_4:
 356        case R200_PP_TXMULTI_CTL_5:
 357                i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
 358                break;
 359        case R200_PP_TXFORMAT_X_0:
 360        case R200_PP_TXFORMAT_X_1:
 361        case R200_PP_TXFORMAT_X_2:
 362        case R200_PP_TXFORMAT_X_3:
 363        case R200_PP_TXFORMAT_X_4:
 364        case R200_PP_TXFORMAT_X_5:
 365                i = (reg - R200_PP_TXFORMAT_X_0) / 32;
 366                track->textures[i].txdepth = idx_value & 0x7;
 367                tmp = (idx_value >> 16) & 0x3;
 368                /* 2D, 3D, CUBE */
 369                switch (tmp) {
 370                case 0:
 371                case 5:
 372                case 6:
 373                case 7:
 374                        track->textures[i].tex_coord_type = 0;
 375                        break;
 376                case 1:
 377                        track->textures[i].tex_coord_type = 1;
 378                        break;
 379                case 2:
 380                        track->textures[i].tex_coord_type = 2;
 381                        break;
 382                }
 383                break;
 384        case R200_PP_TXFORMAT_0:
 385        case R200_PP_TXFORMAT_1:
 386        case R200_PP_TXFORMAT_2:
 387        case R200_PP_TXFORMAT_3:
 388        case R200_PP_TXFORMAT_4:
 389        case R200_PP_TXFORMAT_5:
 390                i = (reg - R200_PP_TXFORMAT_0) / 32;
 391                if (idx_value & R200_TXFORMAT_NON_POWER2) {
 392                        track->textures[i].use_pitch = 1;
 393                } else {
 394                        track->textures[i].use_pitch = 0;
 395                        track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
 396                        track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
 397                }
 398                switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
 399                case R200_TXFORMAT_I8:
 400                case R200_TXFORMAT_RGB332:
 401                case R200_TXFORMAT_Y8:
 402                        track->textures[i].cpp = 1;
 403                        break;
 404                case R200_TXFORMAT_DXT1:
 405                case R200_TXFORMAT_AI88:
 406                case R200_TXFORMAT_ARGB1555:
 407                case R200_TXFORMAT_RGB565:
 408                case R200_TXFORMAT_ARGB4444:
 409                case R200_TXFORMAT_VYUY422:
 410                case R200_TXFORMAT_YVYU422:
 411                case R200_TXFORMAT_LDVDU655:
 412                case R200_TXFORMAT_DVDU88:
 413                case R200_TXFORMAT_AVYU4444:
 414                        track->textures[i].cpp = 2;
 415                        break;
 416                case R200_TXFORMAT_ARGB8888:
 417                case R200_TXFORMAT_RGBA8888:
 418                case R200_TXFORMAT_ABGR8888:
 419                case R200_TXFORMAT_BGR111110:
 420                case R200_TXFORMAT_LDVDU8888:
 421                case R200_TXFORMAT_DXT23:
 422                case R200_TXFORMAT_DXT45:
 423                        track->textures[i].cpp = 4;
 424                        break;
 425                }
 426                track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
 427                track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
 428                break;
 429        case R200_PP_CUBIC_FACES_0:
 430        case R200_PP_CUBIC_FACES_1:
 431        case R200_PP_CUBIC_FACES_2:
 432        case R200_PP_CUBIC_FACES_3:
 433        case R200_PP_CUBIC_FACES_4:
 434        case R200_PP_CUBIC_FACES_5:
 435                tmp = idx_value;
 436                i = (reg - R200_PP_CUBIC_FACES_0) / 32;
 437                for (face = 0; face < 4; face++) {
 438                        track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
 439                        track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
 440                }
 441                break;
 442        default:
 443                printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
 444                       reg, idx);
 445                return -EINVAL;
 446        }
 447        return 0;
 448}
 449
 450void r200_set_safe_registers(struct radeon_device *rdev)
 451{
 452        rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
 453        rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
 454}
 455