Merge git://git.infradead.org/~dhowells/irq-2.6
[powerpc.git] / drivers / char / drm / radeon_state.c
index c5b8f77..feac5f0 100644 (file)
@@ -42,7 +42,11 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
                                                    drm_file_t * filp_priv,
                                                    u32 *offset)
 {
-       u32 off = *offset;
+       u64 off = *offset;
+       u32 fb_start = dev_priv->fb_location;
+       u32 fb_end = fb_start + dev_priv->fb_size - 1;
+       u32 gart_start = dev_priv->gart_vm_start;
+       u32 gart_end = gart_start + dev_priv->gart_size - 1;
        struct drm_radeon_driver_file_fields *radeon_priv;
 
        /* Hrm ... the story of the offset ... So this function converts
@@ -62,10 +66,8 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
        /* First, the best case, the offset already lands in either the
         * framebuffer or the GART mapped space
         */
-       if ((off >= dev_priv->fb_location &&
-            off < (dev_priv->fb_location + dev_priv->fb_size)) ||
-           (off >= dev_priv->gart_vm_start &&
-            off < (dev_priv->gart_vm_start + dev_priv->gart_size)))
+       if ((off >= fb_start && off <= fb_end) ||
+           (off >= gart_start && off <= gart_end))
                return 0;
 
        /* Ok, that didn't happen... now check if we have a zero based
@@ -78,16 +80,13 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
        }
 
        /* Finally, assume we aimed at a GART offset if beyond the fb */
-       if (off > (dev_priv->fb_location + dev_priv->fb_size))
-               off = off - (dev_priv->fb_location + dev_priv->fb_size) +
-                       dev_priv->gart_vm_start;
+       if (off > fb_end)
+               off = off - fb_end - 1 + gart_start;
 
        /* Now recheck and fail if out of bounds */
-       if ((off >= dev_priv->fb_location &&
-            off < (dev_priv->fb_location + dev_priv->fb_size)) ||
-           (off >= dev_priv->gart_vm_start &&
-            off < (dev_priv->gart_vm_start + dev_priv->gart_size))) {
-               DRM_DEBUG("offset fixed up to 0x%x\n", off);
+       if ((off >= fb_start && off <= fb_end) ||
+           (off >= gart_start && off <= gart_end)) {
+               DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
                *offset = off;
                return 0;
        }
@@ -175,6 +174,14 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
                }
                break;
 
+       case R200_EMIT_VAP_CTL:{
+                       RING_LOCALS;
+                       BEGIN_RING(2);
+                       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+                       ADVANCE_RING();
+               }
+               break;
+
        case RADEON_EMIT_RB3D_COLORPITCH:
        case RADEON_EMIT_RE_LINE_PATTERN:
        case RADEON_EMIT_SE_LINE_WIDTH:
@@ -202,7 +209,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
        case R200_EMIT_TFACTOR_0:
        case R200_EMIT_VTX_FMT_0:
-       case R200_EMIT_VAP_CTL:
        case R200_EMIT_MATRIX_SELECT_0:
        case R200_EMIT_TEX_PROC_CTL_2:
        case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
@@ -249,6 +255,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_PP_TXCTLALL_3:
        case R200_EMIT_PP_TXCTLALL_4:
        case R200_EMIT_PP_TXCTLALL_5:
+       case R200_EMIT_VAP_PVS_CNTL:
                /* These packets don't contain memory offsets */
                break;
 
@@ -626,6 +633,7 @@ static struct {
        {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
        {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
        {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+       {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
 };
 
 /* ================================================================
@@ -860,7 +868,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                 */
                dev_priv->sarea_priv->ctx_owner = 0;
 
-               if ((dev_priv->flags & CHIP_HAS_HIERZ)
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
                    && (flags & RADEON_USE_HIERZ)) {
                        /* FIXME : reverse engineer that for Rx00 cards */
                        /* FIXME : the mask supposedly contains low-res z values. So can't set
@@ -905,7 +913,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                for (i = 0; i < nbox; i++) {
                        int tileoffset, nrtilesx, nrtilesy, j;
                        /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
-                       if ((dev_priv->flags & CHIP_HAS_HIERZ)
+                       if ((dev_priv->flags & RADEON_HAS_HIERZ)
                            && !(dev_priv->microcode_version == UCODE_R200)) {
                                /* FIXME : figure this out for r200 (when hierz is enabled). Or
                                   maybe r200 actually doesn't need to put the low-res z value into
@@ -989,7 +997,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                }
 
                /* TODO don't always clear all hi-level z tiles */
-               if ((dev_priv->flags & CHIP_HAS_HIERZ)
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
                    && (dev_priv->microcode_version == UCODE_R200)
                    && (flags & RADEON_USE_HIERZ))
                        /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
@@ -1261,9 +1269,9 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
 
                DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
 
-               BEGIN_RING(7);
+               BEGIN_RING(9);
 
-               OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+               OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
                OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
                         RADEON_GMC_DST_PITCH_OFFSET_CNTL |
                         RADEON_GMC_BRUSH_NONE |
@@ -1275,6 +1283,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
 
                /* Make this work even if front & back are flipped:
                 */
+               OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
                if (dev_priv->current_page == 0) {
                        OUT_RING(dev_priv->back_pitch_offset);
                        OUT_RING(dev_priv->front_pitch_offset);
@@ -1283,6 +1292,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
                        OUT_RING(dev_priv->back_pitch_offset);
                }
 
+               OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
                OUT_RING((x << 16) | y);
                OUT_RING((x << 16) | y);
                OUT_RING((w << 16) | h);
@@ -2595,7 +2605,8 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
        int stride = header.vectors.stride;
        RING_LOCALS;
 
-       BEGIN_RING(3 + sz);
+       BEGIN_RING(5 + sz);
+       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
        OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
        OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
        OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
@@ -2607,6 +2618,32 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
        return 0;
 }
 
+static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
+                                         drm_radeon_cmd_header_t header,
+                                         drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       int sz = header.veclinear.count * 4;
+       int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
+       RING_LOCALS;
+
+        if (!sz)
+                return 0;
+        if (sz * 4 > cmdbuf->bufsz)
+                return DRM_ERR(EINVAL);
+
+       BEGIN_RING(5 + sz);
+       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+       OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+       OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+       OUT_RING_TABLE(cmdbuf->buf, sz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
 static int radeon_emit_packet3(drm_device_t * dev,
                               drm_file_t * filp_priv,
                               drm_radeon_kcmd_buffer_t *cmdbuf)
@@ -2865,6 +2902,14 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
                                goto err;
                        }
                        break;
+               case RADEON_CMD_VECLINEAR:
+                       DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
+                       if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) {
+                               DRM_ERROR("radeon_emit_veclinear failed\n");
+                               goto err;
+                       }
+                       break;
+
                default:
                        DRM_ERROR("bad cmd_type %d at %p\n",
                                  header.header.cmd_type,
@@ -2943,16 +2988,21 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
        case RADEON_PARAM_GART_TEX_HANDLE:
                value = dev_priv->gart_textures_offset;
                break;
-       
+       case RADEON_PARAM_SCRATCH_OFFSET:
+               if (!dev_priv->writeback_works)
+                       return DRM_ERR(EINVAL);
+               value = RADEON_SCRATCH_REG_OFFSET;
+               break;
        case RADEON_PARAM_CARD_TYPE:
-               if (dev_priv->flags & CHIP_IS_PCIE)
+               if (dev_priv->flags & RADEON_IS_PCIE)
                        value = RADEON_CARD_PCIE;
-               else if (dev_priv->flags & CHIP_IS_AGP)
+               else if (dev_priv->flags & RADEON_IS_AGP)
                        value = RADEON_CARD_AGP;
                else
                        value = RADEON_CARD_PCI;
                break;
        default:
+               DRM_DEBUG("Invalid parameter %d\n", param.param);
                return DRM_ERR(EINVAL);
        }