The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/r128_state.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* r128_state.c -- State support for r128 -*- linux-c -*-
    2  * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
    3  *
    4  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
    5  * All Rights Reserved.
    6  *
    7  * Permission is hereby granted, free of charge, to any person obtaining a
    8  * copy of this software and associated documentation files (the "Software"),
    9  * to deal in the Software without restriction, including without limitation
   10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   11  * and/or sell copies of the Software, and to permit persons to whom the
   12  * Software is furnished to do so, subject to the following conditions:
   13  *
   14  * The above copyright notice and this permission notice (including the next
   15  * paragraph) shall be included in all copies or substantial portions of the
   16  * Software.
   17  *
   18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   21  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   24  * DEALINGS IN THE SOFTWARE.
   25  *
   26  * Authors:
   27  *    Gareth Hughes <gareth@valinux.com>
   28  *
   29  * $FreeBSD: releng/5.0/sys/dev/drm/r128_state.c 97683 2002-05-31 23:19:50Z anholt $
   30  */
   31 
   32 #ifdef __linux__
   33 #define __NO_VERSION__
   34 #include <linux/delay.h>
   35 #endif /* __linux__ */
   36 
   37 #include "dev/drm/r128.h"
   38 #include "dev/drm/drmP.h"
   39 #include "dev/drm/r128_drm.h"
   40 #include "dev/drm/r128_drv.h"
   41 #include "dev/drm/drm.h"
   42 
   43 
   44 
   45 /* ================================================================
   46  * CCE hardware state programming functions
   47  */
   48 
   49 static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
   50                                   drm_clip_rect_t *boxes, int count )
   51 {
   52         u32 aux_sc_cntl = 0x00000000;
   53         RING_LOCALS;
   54         DRM_DEBUG( "    %s\n", __func__ );
   55 
   56         BEGIN_RING( 17 );
   57 
   58         if ( count >= 1 ) {
   59                 OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
   60                 OUT_RING( boxes[0].x1 );
   61                 OUT_RING( boxes[0].x2 - 1 );
   62                 OUT_RING( boxes[0].y1 );
   63                 OUT_RING( boxes[0].y2 - 1 );
   64 
   65                 aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
   66         }
   67         if ( count >= 2 ) {
   68                 OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
   69                 OUT_RING( boxes[1].x1 );
   70                 OUT_RING( boxes[1].x2 - 1 );
   71                 OUT_RING( boxes[1].y1 );
   72                 OUT_RING( boxes[1].y2 - 1 );
   73 
   74                 aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
   75         }
   76         if ( count >= 3 ) {
   77                 OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
   78                 OUT_RING( boxes[2].x1 );
   79                 OUT_RING( boxes[2].x2 - 1 );
   80                 OUT_RING( boxes[2].y1 );
   81                 OUT_RING( boxes[2].y2 - 1 );
   82 
   83                 aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
   84         }
   85 
   86         OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
   87         OUT_RING( aux_sc_cntl );
   88 
   89         ADVANCE_RING();
   90 }
   91 
   92 static __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
   93 {
   94         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
   95         drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
   96         RING_LOCALS;
   97         DRM_DEBUG( "    %s\n", __func__ );
   98 
   99         BEGIN_RING( 2 );
  100 
  101         OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
  102         OUT_RING( ctx->scale_3d_cntl );
  103 
  104         ADVANCE_RING();
  105 }
  106 
  107 static __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
  108 {
  109         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  110         drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
  111         RING_LOCALS;
  112         DRM_DEBUG( "    %s\n", __func__ );
  113 
  114         BEGIN_RING( 13 );
  115 
  116         OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
  117         OUT_RING( ctx->dst_pitch_offset_c );
  118         OUT_RING( ctx->dp_gui_master_cntl_c );
  119         OUT_RING( ctx->sc_top_left_c );
  120         OUT_RING( ctx->sc_bottom_right_c );
  121         OUT_RING( ctx->z_offset_c );
  122         OUT_RING( ctx->z_pitch_c );
  123         OUT_RING( ctx->z_sten_cntl_c );
  124         OUT_RING( ctx->tex_cntl_c );
  125         OUT_RING( ctx->misc_3d_state_cntl_reg );
  126         OUT_RING( ctx->texture_clr_cmp_clr_c );
  127         OUT_RING( ctx->texture_clr_cmp_msk_c );
  128         OUT_RING( ctx->fog_color_c );
  129 
  130         ADVANCE_RING();
  131 }
  132 
  133 static __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
  134 {
  135         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  136         drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
  137         RING_LOCALS;
  138         DRM_DEBUG( "    %s\n", __func__ );
  139 
  140         BEGIN_RING( 3 );
  141 
  142         OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
  143         OUT_RING( ctx->setup_cntl );
  144         OUT_RING( ctx->pm4_vc_fpu_setup );
  145 
  146         ADVANCE_RING();
  147 }
  148 
  149 static __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
  150 {
  151         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  152         drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
  153         RING_LOCALS;
  154         DRM_DEBUG( "    %s\n", __func__ );
  155 
  156         BEGIN_RING( 5 );
  157 
  158         OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
  159         OUT_RING( ctx->dp_write_mask );
  160 
  161         OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
  162         OUT_RING( ctx->sten_ref_mask_c );
  163         OUT_RING( ctx->plane_3d_mask_c );
  164 
  165         ADVANCE_RING();
  166 }
  167 
  168 static __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
  169 {
  170         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  171         drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
  172         RING_LOCALS;
  173         DRM_DEBUG( "    %s\n", __func__ );
  174 
  175         BEGIN_RING( 2 );
  176 
  177         OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
  178         OUT_RING( ctx->window_xy_offset );
  179 
  180         ADVANCE_RING();
  181 }
  182 
  183 static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
  184 {
  185         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  186         drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
  187         drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
  188         int i;
  189         RING_LOCALS;
  190         DRM_DEBUG( "    %s\n", __func__ );
  191 
  192         BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
  193 
  194         OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
  195                                2 + R128_MAX_TEXTURE_LEVELS ) );
  196         OUT_RING( tex->tex_cntl );
  197         OUT_RING( tex->tex_combine_cntl );
  198         OUT_RING( ctx->tex_size_pitch_c );
  199         for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
  200                 OUT_RING( tex->tex_offset[i] );
  201         }
  202 
  203         OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
  204         OUT_RING( ctx->constant_color_c );
  205         OUT_RING( tex->tex_border_color );
  206 
  207         ADVANCE_RING();
  208 }
  209 
  210 static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
  211 {
  212         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  213         drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
  214         int i;
  215         RING_LOCALS;
  216         DRM_DEBUG( "    %s\n", __func__ );
  217 
  218         BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
  219 
  220         OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
  221                                1 + R128_MAX_TEXTURE_LEVELS ) );
  222         OUT_RING( tex->tex_cntl );
  223         OUT_RING( tex->tex_combine_cntl );
  224         for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
  225                 OUT_RING( tex->tex_offset[i] );
  226         }
  227 
  228         OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
  229         OUT_RING( tex->tex_border_color );
  230 
  231         ADVANCE_RING();
  232 }
  233 
  234 static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
  235 {
  236         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  237         unsigned int dirty = sarea_priv->dirty;
  238 
  239         DRM_DEBUG( "%s: dirty=0x%08x\n", __func__, dirty );
  240 
  241         if ( dirty & R128_UPLOAD_CORE ) {
  242                 r128_emit_core( dev_priv );
  243                 sarea_priv->dirty &= ~R128_UPLOAD_CORE;
  244         }
  245 
  246         if ( dirty & R128_UPLOAD_CONTEXT ) {
  247                 r128_emit_context( dev_priv );
  248                 sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
  249         }
  250 
  251         if ( dirty & R128_UPLOAD_SETUP ) {
  252                 r128_emit_setup( dev_priv );
  253                 sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
  254         }
  255 
  256         if ( dirty & R128_UPLOAD_MASKS ) {
  257                 r128_emit_masks( dev_priv );
  258                 sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
  259         }
  260 
  261         if ( dirty & R128_UPLOAD_WINDOW ) {
  262                 r128_emit_window( dev_priv );
  263                 sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
  264         }
  265 
  266         if ( dirty & R128_UPLOAD_TEX0 ) {
  267                 r128_emit_tex0( dev_priv );
  268                 sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
  269         }
  270 
  271         if ( dirty & R128_UPLOAD_TEX1 ) {
  272                 r128_emit_tex1( dev_priv );
  273                 sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
  274         }
  275 
  276         /* Turn off the texture cache flushing */
  277         sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
  278 
  279         sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
  280 }
  281 
  282 
  283 #if R128_PERFORMANCE_BOXES
  284 /* ================================================================
  285  * Performance monitoring functions
  286  */
  287 
  288 static void r128_clear_box( drm_r128_private_t *dev_priv,
  289                             int x, int y, int w, int h,
  290                             int r, int g, int b )
  291 {
  292         u32 pitch, offset;
  293         u32 fb_bpp, color;
  294         RING_LOCALS;
  295 
  296         switch ( dev_priv->fb_bpp ) {
  297         case 16:
  298                 fb_bpp = R128_GMC_DST_16BPP;
  299                 color = (((r & 0xf8) << 8) |
  300                          ((g & 0xfc) << 3) |
  301                          ((b & 0xf8) >> 3));
  302                 break;
  303         case 24:
  304                 fb_bpp = R128_GMC_DST_24BPP;
  305                 color = ((r << 16) | (g << 8) | b);
  306                 break;
  307         case 32:
  308                 fb_bpp = R128_GMC_DST_32BPP;
  309                 color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);
  310                 break;
  311         default:
  312                 return;
  313         }
  314 
  315         offset = dev_priv->back_offset;
  316         pitch = dev_priv->back_pitch >> 3;
  317 
  318         BEGIN_RING( 6 );
  319 
  320         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
  321         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
  322                   R128_GMC_BRUSH_SOLID_COLOR |
  323                   fb_bpp |
  324                   R128_GMC_SRC_DATATYPE_COLOR |
  325                   R128_ROP3_P |
  326                   R128_GMC_CLR_CMP_CNTL_DIS |
  327                   R128_GMC_AUX_CLIP_DIS );
  328 
  329         OUT_RING( (pitch << 21) | (offset >> 5) );
  330         OUT_RING( color );
  331 
  332         OUT_RING( (x << 16) | y );
  333         OUT_RING( (w << 16) | h );
  334 
  335         ADVANCE_RING();
  336 }
  337 
  338 static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
  339 {
  340         if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
  341                 r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
  342         } else {
  343                 atomic_set( &dev_priv->idle_count, 0 );
  344         }
  345 }
  346 
  347 #endif
  348 
  349 
  350 /* ================================================================
  351  * CCE command dispatch functions
  352  */
  353 
  354 static void r128_print_dirty( const char *msg, unsigned int flags )
  355 {
  356         DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
  357                   msg,
  358                   flags,
  359                   (flags & R128_UPLOAD_CORE)        ? "core, " : "",
  360                   (flags & R128_UPLOAD_CONTEXT)     ? "context, " : "",
  361                   (flags & R128_UPLOAD_SETUP)       ? "setup, " : "",
  362                   (flags & R128_UPLOAD_TEX0)        ? "tex0, " : "",
  363                   (flags & R128_UPLOAD_TEX1)        ? "tex1, " : "",
  364                   (flags & R128_UPLOAD_MASKS)       ? "masks, " : "",
  365                   (flags & R128_UPLOAD_WINDOW)      ? "window, " : "",
  366                   (flags & R128_UPLOAD_CLIPRECTS)   ? "cliprects, " : "",
  367                   (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
  368 }
  369 
  370 static void r128_cce_dispatch_clear( drm_device_t *dev,
  371                                      drm_r128_clear_t *clear )
  372 {
  373         drm_r128_private_t *dev_priv = dev->dev_private;
  374         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  375         int nbox = sarea_priv->nbox;
  376         drm_clip_rect_t *pbox = sarea_priv->boxes;
  377         unsigned int flags = clear->flags;
  378         int i;
  379         RING_LOCALS;
  380         DRM_DEBUG( "%s\n", __func__ );
  381 
  382         if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
  383                 unsigned int tmp = flags;
  384 
  385                 flags &= ~(R128_FRONT | R128_BACK);
  386                 if ( tmp & R128_FRONT ) flags |= R128_BACK;
  387                 if ( tmp & R128_BACK )  flags |= R128_FRONT;
  388         }
  389 
  390         for ( i = 0 ; i < nbox ; i++ ) {
  391                 int x = pbox[i].x1;
  392                 int y = pbox[i].y1;
  393                 int w = pbox[i].x2 - x;
  394                 int h = pbox[i].y2 - y;
  395 
  396                 DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
  397                            pbox[i].x1, pbox[i].y1, pbox[i].x2,
  398                            pbox[i].y2, flags );
  399 
  400                 if ( flags & (R128_FRONT | R128_BACK) ) {
  401                         BEGIN_RING( 2 );
  402 
  403                         OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
  404                         OUT_RING( clear->color_mask );
  405 
  406                         ADVANCE_RING();
  407                 }
  408 
  409                 if ( flags & R128_FRONT ) {
  410                         BEGIN_RING( 6 );
  411 
  412                         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
  413                         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
  414                                   R128_GMC_BRUSH_SOLID_COLOR |
  415                                   (dev_priv->color_fmt << 8) |
  416                                   R128_GMC_SRC_DATATYPE_COLOR |
  417                                   R128_ROP3_P |
  418                                   R128_GMC_CLR_CMP_CNTL_DIS |
  419                                   R128_GMC_AUX_CLIP_DIS );
  420 
  421                         OUT_RING( dev_priv->front_pitch_offset_c );
  422                         OUT_RING( clear->clear_color );
  423 
  424                         OUT_RING( (x << 16) | y );
  425                         OUT_RING( (w << 16) | h );
  426 
  427                         ADVANCE_RING();
  428                 }
  429 
  430                 if ( flags & R128_BACK ) {
  431                         BEGIN_RING( 6 );
  432 
  433                         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
  434                         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
  435                                   R128_GMC_BRUSH_SOLID_COLOR |
  436                                   (dev_priv->color_fmt << 8) |
  437                                   R128_GMC_SRC_DATATYPE_COLOR |
  438                                   R128_ROP3_P |
  439                                   R128_GMC_CLR_CMP_CNTL_DIS |
  440                                   R128_GMC_AUX_CLIP_DIS );
  441 
  442                         OUT_RING( dev_priv->back_pitch_offset_c );
  443                         OUT_RING( clear->clear_color );
  444 
  445                         OUT_RING( (x << 16) | y );
  446                         OUT_RING( (w << 16) | h );
  447 
  448                         ADVANCE_RING();
  449                 }
  450 
  451                 if ( flags & R128_DEPTH ) {
  452                         BEGIN_RING( 6 );
  453 
  454                         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
  455                         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
  456                                   R128_GMC_BRUSH_SOLID_COLOR |
  457                                   (dev_priv->depth_fmt << 8) |
  458                                   R128_GMC_SRC_DATATYPE_COLOR |
  459                                   R128_ROP3_P |
  460                                   R128_GMC_CLR_CMP_CNTL_DIS |
  461                                   R128_GMC_AUX_CLIP_DIS |
  462                                   R128_GMC_WR_MSK_DIS );
  463 
  464                         OUT_RING( dev_priv->depth_pitch_offset_c );
  465                         OUT_RING( clear->clear_depth );
  466 
  467                         OUT_RING( (x << 16) | y );
  468                         OUT_RING( (w << 16) | h );
  469 
  470                         ADVANCE_RING();
  471                 }
  472         }
  473 }
  474 
  475 static void r128_cce_dispatch_swap( drm_device_t *dev )
  476 {
  477         drm_r128_private_t *dev_priv = dev->dev_private;
  478         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  479         int nbox = sarea_priv->nbox;
  480         drm_clip_rect_t *pbox = sarea_priv->boxes;
  481         int i;
  482         RING_LOCALS;
  483         DRM_DEBUG( "%s\n", __func__ );
  484 
  485 #if R128_PERFORMANCE_BOXES
  486         /* Do some trivial performance monitoring...
  487          */
  488         r128_cce_performance_boxes( dev_priv );
  489 #endif
  490 
  491         for ( i = 0 ; i < nbox ; i++ ) {
  492                 int x = pbox[i].x1;
  493                 int y = pbox[i].y1;
  494                 int w = pbox[i].x2 - x;
  495                 int h = pbox[i].y2 - y;
  496 
  497                 BEGIN_RING( 7 );
  498 
  499                 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
  500                 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
  501                           R128_GMC_DST_PITCH_OFFSET_CNTL |
  502                           R128_GMC_BRUSH_NONE |
  503                           (dev_priv->color_fmt << 8) |
  504                           R128_GMC_SRC_DATATYPE_COLOR |
  505                           R128_ROP3_S |
  506                           R128_DP_SRC_SOURCE_MEMORY |
  507                           R128_GMC_CLR_CMP_CNTL_DIS |
  508                           R128_GMC_AUX_CLIP_DIS |
  509                           R128_GMC_WR_MSK_DIS );
  510 
  511                 OUT_RING( dev_priv->back_pitch_offset_c );
  512                 OUT_RING( dev_priv->front_pitch_offset_c );
  513 
  514                 OUT_RING( (x << 16) | y );
  515                 OUT_RING( (x << 16) | y );
  516                 OUT_RING( (w << 16) | h );
  517 
  518                 ADVANCE_RING();
  519         }
  520 
  521         /* Increment the frame counter.  The client-side 3D driver must
  522          * throttle the framerate by waiting for this value before
  523          * performing the swapbuffer ioctl.
  524          */
  525         dev_priv->sarea_priv->last_frame++;
  526 
  527         BEGIN_RING( 2 );
  528 
  529         OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
  530         OUT_RING( dev_priv->sarea_priv->last_frame );
  531 
  532         ADVANCE_RING();
  533 }
  534 
  535 static void r128_cce_dispatch_flip( drm_device_t *dev )
  536 {
  537         drm_r128_private_t *dev_priv = dev->dev_private;
  538         RING_LOCALS;
  539         DRM_DEBUG( "%s: page=%d\n", __func__, dev_priv->current_page );
  540 
  541 #if R128_PERFORMANCE_BOXES
  542         /* Do some trivial performance monitoring...
  543          */
  544         r128_cce_performance_boxes( dev_priv );
  545 #endif
  546 
  547         BEGIN_RING( 4 );
  548 
  549         R128_WAIT_UNTIL_PAGE_FLIPPED();
  550         OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
  551 
  552         if ( dev_priv->current_page == 0 ) {
  553                 OUT_RING( dev_priv->back_offset );
  554                 dev_priv->current_page = 1;
  555         } else {
  556                 OUT_RING( dev_priv->front_offset );
  557                 dev_priv->current_page = 0;
  558         }
  559 
  560         ADVANCE_RING();
  561 
  562         /* Increment the frame counter.  The client-side 3D driver must
  563          * throttle the framerate by waiting for this value before
  564          * performing the swapbuffer ioctl.
  565          */
  566         dev_priv->sarea_priv->last_frame++;
  567 
  568         BEGIN_RING( 2 );
  569 
  570         OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
  571         OUT_RING( dev_priv->sarea_priv->last_frame );
  572 
  573         ADVANCE_RING();
  574 }
  575 
  576 static void r128_cce_dispatch_vertex( drm_device_t *dev,
  577                                       drm_buf_t *buf )
  578 {
  579         drm_r128_private_t *dev_priv = dev->dev_private;
  580         drm_r128_buf_priv_t *buf_priv = buf->dev_private;
  581         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  582         int format = sarea_priv->vc_format;
  583         int offset = buf->bus_address;
  584         int size = buf->used;
  585         int prim = buf_priv->prim;
  586         int i = 0;
  587         RING_LOCALS;
  588         DRM_DEBUG( "%s: buf=%d nbox=%d\n",
  589                    __func__, buf->idx, sarea_priv->nbox );
  590 
  591         if ( 0 )
  592                 r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
  593 
  594         if ( buf->used ) {
  595                 buf_priv->dispatched = 1;
  596 
  597                 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
  598                         r128_emit_state( dev_priv );
  599                 }
  600 
  601                 do {
  602                         /* Emit the next set of up to three cliprects */
  603                         if ( i < sarea_priv->nbox ) {
  604                                 r128_emit_clip_rects( dev_priv,
  605                                                       &sarea_priv->boxes[i],
  606                                                       sarea_priv->nbox - i );
  607                         }
  608 
  609                         /* Emit the vertex buffer rendering commands */
  610                         BEGIN_RING( 5 );
  611 
  612                         OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
  613                         OUT_RING( offset );
  614                         OUT_RING( size );
  615                         OUT_RING( format );
  616                         OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
  617                                   (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
  618 
  619                         ADVANCE_RING();
  620 
  621                         i += 3;
  622                 } while ( i < sarea_priv->nbox );
  623         }
  624 
  625         if ( buf_priv->discard ) {
  626                 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
  627 
  628                 /* Emit the vertex buffer age */
  629                 BEGIN_RING( 2 );
  630 
  631                 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
  632                 OUT_RING( buf_priv->age );
  633 
  634                 ADVANCE_RING();
  635 
  636                 buf->pending = 1;
  637                 buf->used = 0;
  638                 /* FIXME: Check dispatched field */
  639                 buf_priv->dispatched = 0;
  640         }
  641 
  642         dev_priv->sarea_priv->last_dispatch++;
  643 
  644         sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
  645         sarea_priv->nbox = 0;
  646 }
  647 
  648 static void r128_cce_dispatch_indirect( drm_device_t *dev,
  649                                         drm_buf_t *buf,
  650                                         int start, int end )
  651 {
  652         drm_r128_private_t *dev_priv = dev->dev_private;
  653         drm_r128_buf_priv_t *buf_priv = buf->dev_private;
  654         RING_LOCALS;
  655         DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
  656                    buf->idx, start, end );
  657 
  658         if ( start != end ) {
  659                 int offset = buf->bus_address + start;
  660                 int dwords = (end - start + 3) / sizeof(u32);
  661 
  662                 /* Indirect buffer data must be an even number of
  663                  * dwords, so if we've been given an odd number we must
  664                  * pad the data with a Type-2 CCE packet.
  665                  */
  666                 if ( dwords & 1 ) {
  667                         u32 *data = (u32 *)
  668                                 ((char *)dev_priv->buffers->handle
  669                                  + buf->offset + start);
  670                         data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
  671                 }
  672 
  673                 buf_priv->dispatched = 1;
  674 
  675                 /* Fire off the indirect buffer */
  676                 BEGIN_RING( 3 );
  677 
  678                 OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
  679                 OUT_RING( offset );
  680                 OUT_RING( dwords );
  681 
  682                 ADVANCE_RING();
  683         }
  684 
  685         if ( buf_priv->discard ) {
  686                 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
  687 
  688                 /* Emit the indirect buffer age */
  689                 BEGIN_RING( 2 );
  690 
  691                 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
  692                 OUT_RING( buf_priv->age );
  693 
  694                 ADVANCE_RING();
  695 
  696                 buf->pending = 1;
  697                 buf->used = 0;
  698                 /* FIXME: Check dispatched field */
  699                 buf_priv->dispatched = 0;
  700         }
  701 
  702         dev_priv->sarea_priv->last_dispatch++;
  703 }
  704 
  705 static void r128_cce_dispatch_indices( drm_device_t *dev,
  706                                        drm_buf_t *buf,
  707                                        int start, int end,
  708                                        int count )
  709 {
  710         drm_r128_private_t *dev_priv = dev->dev_private;
  711         drm_r128_buf_priv_t *buf_priv = buf->dev_private;
  712         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
  713         int format = sarea_priv->vc_format;
  714         int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
  715         int prim = buf_priv->prim;
  716         u32 *data;
  717         int dwords;
  718         int i = 0;
  719         RING_LOCALS;
  720         DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
  721 
  722         if ( 0 )
  723                 r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
  724 
  725         if ( start != end ) {
  726                 buf_priv->dispatched = 1;
  727 
  728                 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
  729                         r128_emit_state( dev_priv );
  730                 }
  731 
  732                 dwords = (end - start + 3) / sizeof(u32);
  733 
  734                 data = (u32 *)((char *)dev_priv->buffers->handle
  735                                + buf->offset + start);
  736 
  737                 data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
  738                                                     dwords-2 ) );
  739 
  740                 data[1] = cpu_to_le32( offset );
  741                 data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
  742                 data[3] = cpu_to_le32( format );
  743                 data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
  744                                         (count << 16)) );
  745 
  746                 if ( count & 0x1 ) {
  747 #ifdef __LITTLE_ENDIAN
  748                         data[dwords-1] &= 0x0000ffff;
  749 #else
  750                         data[dwords-1] &= 0xffff0000;
  751 #endif
  752                 }
  753 
  754                 do {
  755                         /* Emit the next set of up to three cliprects */
  756                         if ( i < sarea_priv->nbox ) {
  757                                 r128_emit_clip_rects( dev_priv,
  758                                                       &sarea_priv->boxes[i],
  759                                                       sarea_priv->nbox - i );
  760                         }
  761 
  762                         r128_cce_dispatch_indirect( dev, buf, start, end );
  763 
  764                         i += 3;
  765                 } while ( i < sarea_priv->nbox );
  766         }
  767 
  768         if ( buf_priv->discard ) {
  769                 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
  770 
  771                 /* Emit the vertex buffer age */
  772                 BEGIN_RING( 2 );
  773 
  774                 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
  775                 OUT_RING( buf_priv->age );
  776 
  777                 ADVANCE_RING();
  778 
  779                 buf->pending = 1;
  780                 /* FIXME: Check dispatched field */
  781                 buf_priv->dispatched = 0;
  782         }
  783 
  784         dev_priv->sarea_priv->last_dispatch++;
  785 
  786         sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
  787         sarea_priv->nbox = 0;
  788 }
  789 
  790 static int r128_cce_dispatch_blit( drm_device_t *dev,
  791                                    drm_r128_blit_t *blit, int pid )
  792 {
  793         drm_r128_private_t *dev_priv = dev->dev_private;
  794         drm_device_dma_t *dma = dev->dma;
  795         drm_buf_t *buf;
  796         drm_r128_buf_priv_t *buf_priv;
  797         u32 *data;
  798         int dword_shift, dwords;
  799         RING_LOCALS;
  800         DRM_DEBUG( "%s\n", __func__ );
  801 
  802         /* The compiler won't optimize away a division by a variable,
  803          * even if the only legal values are powers of two.  Thus, we'll
  804          * use a shift instead.
  805          */
  806         switch ( blit->format ) {
  807         case R128_DATATYPE_ARGB8888:
  808                 dword_shift = 0;
  809                 break;
  810         case R128_DATATYPE_ARGB1555:
  811         case R128_DATATYPE_RGB565:
  812         case R128_DATATYPE_ARGB4444:
  813                 dword_shift = 1;
  814                 break;
  815         case R128_DATATYPE_CI8:
  816         case R128_DATATYPE_RGB8:
  817                 dword_shift = 2;
  818                 break;
  819         default:
  820                 DRM_ERROR( "invalid blit format %d\n", blit->format );
  821                 return DRM_OS_ERR(EINVAL);
  822         }
  823 
  824         /* Flush the pixel cache, and mark the contents as Read Invalid.
  825          * This ensures no pixel data gets mixed up with the texture
  826          * data from the host data blit, otherwise part of the texture
  827          * image may be corrupted.
  828          */
  829         BEGIN_RING( 2 );
  830 
  831         OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
  832         OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
  833 
  834         ADVANCE_RING();
  835 
  836         /* Dispatch the indirect buffer.
  837          */
  838         buf = dma->buflist[blit->idx];
  839         buf_priv = buf->dev_private;
  840 
  841         if ( buf->pid != pid ) {
  842                 DRM_ERROR( "process %d using buffer owned by %d\n",
  843                            pid, buf->pid );
  844                 return DRM_OS_ERR(EINVAL);
  845         }
  846         if ( buf->pending ) {
  847                 DRM_ERROR( "sending pending buffer %d\n", blit->idx );
  848                 return DRM_OS_ERR(EINVAL);
  849         }
  850 
  851         buf_priv->discard = 1;
  852 
  853         dwords = (blit->width * blit->height) >> dword_shift;
  854 
  855         data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
  856 
  857         data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
  858         data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
  859                                 R128_GMC_BRUSH_NONE |
  860                                 (blit->format << 8) |
  861                                 R128_GMC_SRC_DATATYPE_COLOR |
  862                                 R128_ROP3_S |
  863                                 R128_DP_SRC_SOURCE_HOST_DATA |
  864                                 R128_GMC_CLR_CMP_CNTL_DIS |
  865                                 R128_GMC_AUX_CLIP_DIS |
  866                                 R128_GMC_WR_MSK_DIS) );
  867 
  868         data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
  869         data[3] = cpu_to_le32( 0xffffffff );
  870         data[4] = cpu_to_le32( 0xffffffff );
  871         data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
  872         data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
  873         data[7] = cpu_to_le32( dwords );
  874 
  875         buf->used = (dwords + 8) * sizeof(u32);
  876 
  877         r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
  878 
  879         /* Flush the pixel cache after the blit completes.  This ensures
  880          * the texture data is written out to memory before rendering
  881          * continues.
  882          */
  883         BEGIN_RING( 2 );
  884 
  885         OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
  886         OUT_RING( R128_PC_FLUSH_GUI );
  887 
  888         ADVANCE_RING();
  889 
  890         return 0;
  891 }
  892 
  893 
  894 /* ================================================================
  895  * Tiled depth buffer management
  896  *
  897  * FIXME: These should all set the destination write mask for when we
  898  * have hardware stencil support.
  899  */
  900 
  901 static int r128_cce_dispatch_write_span( drm_device_t *dev,
  902                                          drm_r128_depth_t *depth )
  903 {
  904         drm_r128_private_t *dev_priv = dev->dev_private;
  905         int count, x, y;
  906         u32 *buffer;
  907         u8 *mask;
  908         int i;
  909         RING_LOCALS;
  910         DRM_DEBUG( "%s\n", __func__ );
  911 
  912         count = depth->n;
  913         if ( DRM_OS_COPYFROMUSR( &x, depth->x, sizeof(x) ) ) {
  914                 return DRM_OS_ERR(EFAULT);
  915         }
  916         if ( DRM_OS_COPYFROMUSR( &y, depth->y, sizeof(y) ) ) {
  917                 return DRM_OS_ERR(EFAULT);
  918         }
  919 
  920         buffer = DRM_OS_MALLOC( depth->n * sizeof(u32) );
  921         if ( buffer == NULL )
  922                 return DRM_OS_ERR(ENOMEM);
  923         if ( DRM_OS_COPYFROMUSR( buffer, depth->buffer,
  924                              depth->n * sizeof(u32) ) ) {
  925                 DRM_OS_FREE( buffer );
  926                 return DRM_OS_ERR(EFAULT);
  927         }
  928 
  929         if ( depth->mask ) {
  930                 mask = DRM_OS_MALLOC( depth->n * sizeof(u8) );
  931                 if ( mask == NULL ) {
  932                         DRM_OS_FREE( buffer );
  933                         return DRM_OS_ERR(ENOMEM);
  934                 }
  935                 if ( DRM_OS_COPYFROMUSR( mask, depth->mask,
  936                                      depth->n * sizeof(u8) ) ) {
  937                         DRM_OS_FREE( buffer );
  938                         DRM_OS_FREE( mask );
  939                         return DRM_OS_ERR(EFAULT);
  940                 }
  941 
  942                 for ( i = 0 ; i < count ; i++, x++ ) {
  943                         if ( mask[i] ) {
  944                                 BEGIN_RING( 6 );
  945 
  946                                 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
  947                                 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
  948                                           R128_GMC_BRUSH_SOLID_COLOR |
  949                                           (dev_priv->depth_fmt << 8) |
  950                                           R128_GMC_SRC_DATATYPE_COLOR |
  951                                           R128_ROP3_P |
  952                                           R128_GMC_CLR_CMP_CNTL_DIS |
  953                                           R128_GMC_WR_MSK_DIS );
  954 
  955                                 OUT_RING( dev_priv->depth_pitch_offset_c );
  956                                 OUT_RING( buffer[i] );
  957 
  958                                 OUT_RING( (x << 16) | y );
  959                                 OUT_RING( (1 << 16) | 1 );
  960 
  961                                 ADVANCE_RING();
  962                         }
  963                 }
  964 
  965                 DRM_OS_FREE( mask );
  966         } else {
  967                 for ( i = 0 ; i < count ; i++, x++ ) {
  968                         BEGIN_RING( 6 );
  969 
  970                         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
  971                         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
  972                                   R128_GMC_BRUSH_SOLID_COLOR |
  973                                   (dev_priv->depth_fmt << 8) |
  974                                   R128_GMC_SRC_DATATYPE_COLOR |
  975                                   R128_ROP3_P |
  976                                   R128_GMC_CLR_CMP_CNTL_DIS |
  977                                   R128_GMC_WR_MSK_DIS );
  978 
  979                         OUT_RING( dev_priv->depth_pitch_offset_c );
  980                         OUT_RING( buffer[i] );
  981 
  982                         OUT_RING( (x << 16) | y );
  983                         OUT_RING( (1 << 16) | 1 );
  984 
  985                         ADVANCE_RING();
  986                 }
  987         }
  988 
  989         DRM_OS_FREE( buffer );
  990 
  991         return 0;
  992 }
  993 
  994 static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
  995                                            drm_r128_depth_t *depth )
  996 {
  997         drm_r128_private_t *dev_priv = dev->dev_private;
  998         int count, *x, *y;
  999         u32 *buffer;
 1000         u8 *mask;
 1001         int i;
 1002         RING_LOCALS;
 1003         DRM_DEBUG( "%s\n", __func__ );
 1004 
 1005         count = depth->n;
 1006 
 1007         x = DRM_OS_MALLOC( count * sizeof(*x) );
 1008         if ( x == NULL ) {
 1009                 return DRM_OS_ERR(ENOMEM);
 1010         }
 1011         y = DRM_OS_MALLOC( count * sizeof(*y) );
 1012         if ( y == NULL ) {
 1013                 DRM_OS_FREE( x );
 1014                 return DRM_OS_ERR(ENOMEM);
 1015         }
 1016         if ( DRM_OS_COPYFROMUSR( x, depth->x, count * sizeof(int) ) ) {
 1017                 DRM_OS_FREE( x );
 1018                 DRM_OS_FREE( y );
 1019                 return DRM_OS_ERR(EFAULT);
 1020         }
 1021         if ( DRM_OS_COPYFROMUSR( y, depth->y, count * sizeof(int) ) ) {
 1022                 DRM_OS_FREE( x );
 1023                 DRM_OS_FREE( y );
 1024                 return DRM_OS_ERR(EFAULT);
 1025         }
 1026 
 1027         buffer = DRM_OS_MALLOC( depth->n * sizeof(u32) );
 1028         if ( buffer == NULL ) {
 1029                 DRM_OS_FREE( x );
 1030                 DRM_OS_FREE( y );
 1031                 return DRM_OS_ERR(ENOMEM);
 1032         }
 1033         if ( DRM_OS_COPYFROMUSR( buffer, depth->buffer,
 1034                              depth->n * sizeof(u32) ) ) {
 1035                 DRM_OS_FREE( x );
 1036                 DRM_OS_FREE( y );
 1037                 DRM_OS_FREE( buffer );
 1038                 return DRM_OS_ERR(EFAULT);
 1039         }
 1040 
 1041         if ( depth->mask ) {
 1042                 mask = DRM_OS_MALLOC( depth->n * sizeof(u8) );
 1043                 if ( mask == NULL ) {
 1044                         DRM_OS_FREE( x );
 1045                         DRM_OS_FREE( y );
 1046                         DRM_OS_FREE( buffer );
 1047                         return DRM_OS_ERR(ENOMEM);
 1048                 }
 1049                 if ( DRM_OS_COPYFROMUSR( mask, depth->mask,
 1050                                      depth->n * sizeof(u8) ) ) {
 1051                         DRM_OS_FREE( x );
 1052                         DRM_OS_FREE( y );
 1053                         DRM_OS_FREE( buffer );
 1054                         DRM_OS_FREE( mask );
 1055                         return DRM_OS_ERR(EFAULT);
 1056                 }
 1057 
 1058                 for ( i = 0 ; i < count ; i++ ) {
 1059                         if ( mask[i] ) {
 1060                                 BEGIN_RING( 6 );
 1061 
 1062                                 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
 1063                                 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
 1064                                           R128_GMC_BRUSH_SOLID_COLOR |
 1065                                           (dev_priv->depth_fmt << 8) |
 1066                                           R128_GMC_SRC_DATATYPE_COLOR |
 1067                                           R128_ROP3_P |
 1068                                           R128_GMC_CLR_CMP_CNTL_DIS |
 1069                                           R128_GMC_WR_MSK_DIS );
 1070 
 1071                                 OUT_RING( dev_priv->depth_pitch_offset_c );
 1072                                 OUT_RING( buffer[i] );
 1073 
 1074                                 OUT_RING( (x[i] << 16) | y[i] );
 1075                                 OUT_RING( (1 << 16) | 1 );
 1076 
 1077                                 ADVANCE_RING();
 1078                         }
 1079                 }
 1080 
 1081                 DRM_OS_FREE( mask );
 1082         } else {
 1083                 for ( i = 0 ; i < count ; i++ ) {
 1084                         BEGIN_RING( 6 );
 1085 
 1086                         OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
 1087                         OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
 1088                                   R128_GMC_BRUSH_SOLID_COLOR |
 1089                                   (dev_priv->depth_fmt << 8) |
 1090                                   R128_GMC_SRC_DATATYPE_COLOR |
 1091                                   R128_ROP3_P |
 1092                                   R128_GMC_CLR_CMP_CNTL_DIS |
 1093                                   R128_GMC_WR_MSK_DIS );
 1094 
 1095                         OUT_RING( dev_priv->depth_pitch_offset_c );
 1096                         OUT_RING( buffer[i] );
 1097 
 1098                         OUT_RING( (x[i] << 16) | y[i] );
 1099                         OUT_RING( (1 << 16) | 1 );
 1100 
 1101                         ADVANCE_RING();
 1102                 }
 1103         }
 1104 
 1105         DRM_OS_FREE( x );
 1106         DRM_OS_FREE( y );
 1107         DRM_OS_FREE( buffer );
 1108 
 1109         return 0;
 1110 }
 1111 
 1112 static int r128_cce_dispatch_read_span( drm_device_t *dev,
 1113                                         drm_r128_depth_t *depth )
 1114 {
 1115         drm_r128_private_t *dev_priv = dev->dev_private;
 1116         int count, x, y;
 1117         RING_LOCALS;
 1118         DRM_DEBUG( "%s\n", __func__ );
 1119 
 1120         count = depth->n;
 1121         if ( DRM_OS_COPYFROMUSR( &x, depth->x, sizeof(x) ) ) {
 1122                 return DRM_OS_ERR(EFAULT);
 1123         }
 1124         if ( DRM_OS_COPYFROMUSR( &y, depth->y, sizeof(y) ) ) {
 1125                 return DRM_OS_ERR(EFAULT);
 1126         }
 1127 
 1128         BEGIN_RING( 7 );
 1129 
 1130         OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
 1131         OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
 1132                   R128_GMC_DST_PITCH_OFFSET_CNTL |
 1133                   R128_GMC_BRUSH_NONE |
 1134                   (dev_priv->depth_fmt << 8) |
 1135                   R128_GMC_SRC_DATATYPE_COLOR |
 1136                   R128_ROP3_S |
 1137                   R128_DP_SRC_SOURCE_MEMORY |
 1138                   R128_GMC_CLR_CMP_CNTL_DIS |
 1139                   R128_GMC_WR_MSK_DIS );
 1140 
 1141         OUT_RING( dev_priv->depth_pitch_offset_c );
 1142         OUT_RING( dev_priv->span_pitch_offset_c );
 1143 
 1144         OUT_RING( (x << 16) | y );
 1145         OUT_RING( (0 << 16) | 0 );
 1146         OUT_RING( (count << 16) | 1 );
 1147 
 1148         ADVANCE_RING();
 1149 
 1150         return 0;
 1151 }
 1152 
 1153 static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
 1154                                           drm_r128_depth_t *depth )
 1155 {
 1156         drm_r128_private_t *dev_priv = dev->dev_private;
 1157         int count, *x, *y;
 1158         int i;
 1159         RING_LOCALS;
 1160         DRM_DEBUG( "%s\n", __func__ );
 1161 
 1162         count = depth->n;
 1163         if ( count > dev_priv->depth_pitch ) {
 1164                 count = dev_priv->depth_pitch;
 1165         }
 1166 
 1167         x = DRM_OS_MALLOC( count * sizeof(*x) );
 1168         if ( x == NULL ) {
 1169                 return DRM_OS_ERR(ENOMEM);
 1170         }
 1171         y = DRM_OS_MALLOC( count * sizeof(*y) );
 1172         if ( y == NULL ) {
 1173                 DRM_OS_FREE( x );
 1174                 return DRM_OS_ERR(ENOMEM);
 1175         }
 1176         if ( DRM_OS_COPYFROMUSR( x, depth->x, count * sizeof(int) ) ) {
 1177                 DRM_OS_FREE( x );
 1178                 DRM_OS_FREE( y );
 1179                 return DRM_OS_ERR(EFAULT);
 1180         }
 1181         if ( DRM_OS_COPYFROMUSR( y, depth->y, count * sizeof(int) ) ) {
 1182                 DRM_OS_FREE( x );
 1183                 DRM_OS_FREE( y );
 1184                 return DRM_OS_ERR(EFAULT);
 1185         }
 1186 
 1187         for ( i = 0 ; i < count ; i++ ) {
 1188                 BEGIN_RING( 7 );
 1189 
 1190                 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
 1191                 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
 1192                           R128_GMC_DST_PITCH_OFFSET_CNTL |
 1193                           R128_GMC_BRUSH_NONE |
 1194                           (dev_priv->depth_fmt << 8) |
 1195                           R128_GMC_SRC_DATATYPE_COLOR |
 1196                           R128_ROP3_S |
 1197                           R128_DP_SRC_SOURCE_MEMORY |
 1198                           R128_GMC_CLR_CMP_CNTL_DIS |
 1199                           R128_GMC_WR_MSK_DIS );
 1200 
 1201                 OUT_RING( dev_priv->depth_pitch_offset_c );
 1202                 OUT_RING( dev_priv->span_pitch_offset_c );
 1203 
 1204                 OUT_RING( (x[i] << 16) | y[i] );
 1205                 OUT_RING( (i << 16) | 0 );
 1206                 OUT_RING( (1 << 16) | 1 );
 1207 
 1208                 ADVANCE_RING();
 1209         }
 1210 
 1211         DRM_OS_FREE( x );
 1212         DRM_OS_FREE( y );
 1213 
 1214         return 0;
 1215 }
 1216 
 1217 
 1218 /* ================================================================
 1219  * Polygon stipple
 1220  */
 1221 
 1222 static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
 1223 {
 1224         drm_r128_private_t *dev_priv = dev->dev_private;
 1225         int i;
 1226         RING_LOCALS;
 1227         DRM_DEBUG( "%s\n", __func__ );
 1228 
 1229         BEGIN_RING( 33 );
 1230 
 1231         OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
 1232         for ( i = 0 ; i < 32 ; i++ ) {
 1233                 OUT_RING( stipple[i] );
 1234         }
 1235 
 1236         ADVANCE_RING();
 1237 }
 1238 
 1239 
 1240 /* ================================================================
 1241  * IOCTL functions
 1242  */
 1243 
 1244 int r128_cce_clear( DRM_OS_IOCTL )
 1245 {
 1246         DRM_OS_DEVICE;
 1247         drm_r128_private_t *dev_priv = dev->dev_private;
 1248         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 1249         drm_r128_clear_t clear;
 1250         DRM_DEBUG( "%s\n", __func__ );
 1251 
 1252         LOCK_TEST_WITH_RETURN( dev );
 1253 
 1254         DRM_OS_KRNFROMUSR( clear, (drm_r128_clear_t *) data,
 1255                              sizeof(clear) );
 1256 
 1257         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1258 
 1259         if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
 1260                 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
 1261 
 1262         r128_cce_dispatch_clear( dev, &clear );
 1263 
 1264         /* Make sure we restore the 3D state next time.
 1265          */
 1266         dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
 1267 
 1268         return 0;
 1269 }
 1270 
 1271 int r128_cce_swap( DRM_OS_IOCTL )
 1272 {
 1273         DRM_OS_DEVICE;
 1274         drm_r128_private_t *dev_priv = dev->dev_private;
 1275         drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 1276         DRM_DEBUG( "%s\n", __func__ );
 1277 
 1278         LOCK_TEST_WITH_RETURN( dev );
 1279 
 1280         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1281 
 1282         if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
 1283                 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
 1284 
 1285         if ( !dev_priv->page_flipping ) {
 1286                 r128_cce_dispatch_swap( dev );
 1287                 dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
 1288                                                 R128_UPLOAD_MASKS);
 1289         } else {
 1290                 r128_cce_dispatch_flip( dev );
 1291         }
 1292 
 1293         return 0;
 1294 }
 1295 
 1296 int r128_cce_vertex( DRM_OS_IOCTL )
 1297 {
 1298         DRM_OS_DEVICE;
 1299         drm_r128_private_t *dev_priv = dev->dev_private;
 1300         drm_device_dma_t *dma = dev->dma;
 1301         drm_buf_t *buf;
 1302         drm_r128_buf_priv_t *buf_priv;
 1303         drm_r128_vertex_t vertex;
 1304 
 1305         LOCK_TEST_WITH_RETURN( dev );
 1306 
 1307         if ( !dev_priv ) {
 1308                 DRM_ERROR( "%s called with no initialization\n", __func__ );
 1309                 return DRM_OS_ERR(EINVAL);
 1310         }
 1311 
 1312         DRM_OS_KRNFROMUSR( vertex, (drm_r128_vertex_t *) data,
 1313                              sizeof(vertex) );
 1314 
 1315         DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
 1316                    __func__, DRM_OS_CURRENTPID,
 1317                    vertex.idx, vertex.count, vertex.discard );
 1318 
 1319         if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
 1320                 DRM_ERROR( "buffer index %d (of %d max)\n",
 1321                            vertex.idx, dma->buf_count - 1 );
 1322                 return DRM_OS_ERR(EINVAL);
 1323         }
 1324         if ( vertex.prim < 0 ||
 1325              vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
 1326                 DRM_ERROR( "buffer prim %d\n", vertex.prim );
 1327                 return DRM_OS_ERR(EINVAL);
 1328         }
 1329 
 1330         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1331         VB_AGE_TEST_WITH_RETURN( dev_priv );
 1332 
 1333         buf = dma->buflist[vertex.idx];
 1334         buf_priv = buf->dev_private;
 1335 
 1336         if ( buf->pid != DRM_OS_CURRENTPID ) {
 1337                 DRM_ERROR( "process %d using buffer owned by %d\n",
 1338                            DRM_OS_CURRENTPID, buf->pid );
 1339                 return DRM_OS_ERR(EINVAL);
 1340         }
 1341         if ( buf->pending ) {
 1342                 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
 1343                 return DRM_OS_ERR(EINVAL);
 1344         }
 1345 
 1346         buf->used = vertex.count;
 1347         buf_priv->prim = vertex.prim;
 1348         buf_priv->discard = vertex.discard;
 1349 
 1350         r128_cce_dispatch_vertex( dev, buf );
 1351 
 1352         return 0;
 1353 }
 1354 
 1355 int r128_cce_indices( DRM_OS_IOCTL )
 1356 {
 1357         DRM_OS_DEVICE;
 1358         drm_r128_private_t *dev_priv = dev->dev_private;
 1359         drm_device_dma_t *dma = dev->dma;
 1360         drm_buf_t *buf;
 1361         drm_r128_buf_priv_t *buf_priv;
 1362         drm_r128_indices_t elts;
 1363         int count;
 1364 
 1365         LOCK_TEST_WITH_RETURN( dev );
 1366 
 1367         if ( !dev_priv ) {
 1368                 DRM_ERROR( "%s called with no initialization\n", __func__ );
 1369                 return DRM_OS_ERR(EINVAL);
 1370         }
 1371 
 1372         DRM_OS_KRNFROMUSR( elts, (drm_r128_indices_t *) data,
 1373                              sizeof(elts) );
 1374 
 1375         DRM_DEBUG( "%s: pid=%d buf=%d s=%d e=%d d=%d\n",
 1376                    __func__, DRM_OS_CURRENTPID,
 1377                    elts.idx, elts.start, elts.end, elts.discard );
 1378 
 1379         if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
 1380                 DRM_ERROR( "buffer index %d (of %d max)\n",
 1381                            elts.idx, dma->buf_count - 1 );
 1382                 return DRM_OS_ERR(EINVAL);
 1383         }
 1384         if ( elts.prim < 0 ||
 1385              elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
 1386                 DRM_ERROR( "buffer prim %d\n", elts.prim );
 1387                 return DRM_OS_ERR(EINVAL);
 1388         }
 1389 
 1390         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1391         VB_AGE_TEST_WITH_RETURN( dev_priv );
 1392 
 1393         buf = dma->buflist[elts.idx];
 1394         buf_priv = buf->dev_private;
 1395 
 1396         if ( buf->pid != DRM_OS_CURRENTPID ) {
 1397                 DRM_ERROR( "process %d using buffer owned by %d\n",
 1398                            DRM_OS_CURRENTPID, buf->pid );
 1399                 return DRM_OS_ERR(EINVAL);
 1400         }
 1401         if ( buf->pending ) {
 1402                 DRM_ERROR( "sending pending buffer %d\n", elts.idx );
 1403                 return DRM_OS_ERR(EINVAL);
 1404         }
 1405 
 1406         count = (elts.end - elts.start) / sizeof(u16);
 1407         elts.start -= R128_INDEX_PRIM_OFFSET;
 1408 
 1409         if ( elts.start & 0x7 ) {
 1410                 DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
 1411                 return DRM_OS_ERR(EINVAL);
 1412         }
 1413         if ( elts.start < buf->used ) {
 1414                 DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
 1415                 return DRM_OS_ERR(EINVAL);
 1416         }
 1417 
 1418         buf->used = elts.end;
 1419         buf_priv->prim = elts.prim;
 1420         buf_priv->discard = elts.discard;
 1421 
 1422         r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
 1423 
 1424         return 0;
 1425 }
 1426 
 1427 int r128_cce_blit( DRM_OS_IOCTL )
 1428 {
 1429         DRM_OS_DEVICE;
 1430         drm_device_dma_t *dma = dev->dma;
 1431         drm_r128_private_t *dev_priv = dev->dev_private;
 1432         drm_r128_blit_t blit;
 1433 
 1434         LOCK_TEST_WITH_RETURN( dev );
 1435 
 1436         DRM_OS_KRNFROMUSR( blit, (drm_r128_blit_t *) data,
 1437                              sizeof(blit) );
 1438 
 1439         DRM_DEBUG( "%s: pid=%d index=%d\n",
 1440                    __func__, DRM_OS_CURRENTPID, blit.idx );
 1441 
 1442         if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
 1443                 DRM_ERROR( "buffer index %d (of %d max)\n",
 1444                            blit.idx, dma->buf_count - 1 );
 1445                 return DRM_OS_ERR(EINVAL);
 1446         }
 1447 
 1448         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1449         VB_AGE_TEST_WITH_RETURN( dev_priv );
 1450 
 1451         return r128_cce_dispatch_blit( dev, &blit, DRM_OS_CURRENTPID );
 1452 }
 1453 
 1454 int r128_cce_depth( DRM_OS_IOCTL )
 1455 {
 1456         DRM_OS_DEVICE;
 1457         drm_r128_private_t *dev_priv = dev->dev_private;
 1458         drm_r128_depth_t depth;
 1459 
 1460         LOCK_TEST_WITH_RETURN( dev );
 1461 
 1462         DRM_OS_KRNFROMUSR( depth, (drm_r128_depth_t *) data,
 1463                              sizeof(depth) );
 1464 
 1465         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1466 
 1467         switch ( depth.func ) {
 1468         case R128_WRITE_SPAN:
 1469                 return r128_cce_dispatch_write_span( dev, &depth );
 1470         case R128_WRITE_PIXELS:
 1471                 return r128_cce_dispatch_write_pixels( dev, &depth );
 1472         case R128_READ_SPAN:
 1473                 return r128_cce_dispatch_read_span( dev, &depth );
 1474         case R128_READ_PIXELS:
 1475                 return r128_cce_dispatch_read_pixels( dev, &depth );
 1476         }
 1477 
 1478         return DRM_OS_ERR(EINVAL);
 1479 }
 1480 
 1481 int r128_cce_stipple( DRM_OS_IOCTL )
 1482 {
 1483         DRM_OS_DEVICE;
 1484         drm_r128_private_t *dev_priv = dev->dev_private;
 1485         drm_r128_stipple_t stipple;
 1486         u32 mask[32];
 1487 
 1488         LOCK_TEST_WITH_RETURN( dev );
 1489 
 1490         DRM_OS_KRNFROMUSR( stipple, (drm_r128_stipple_t *) data,
 1491                              sizeof(stipple) );
 1492 
 1493         if ( DRM_OS_COPYFROMUSR( &mask, stipple.mask,
 1494                              32 * sizeof(u32) ) )
 1495                 return DRM_OS_ERR(EFAULT);
 1496 
 1497         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1498 
 1499         r128_cce_dispatch_stipple( dev, mask );
 1500 
 1501         return 0;
 1502 }
 1503 
 1504 int r128_cce_indirect( DRM_OS_IOCTL )
 1505 {
 1506         DRM_OS_DEVICE;
 1507         drm_r128_private_t *dev_priv = dev->dev_private;
 1508         drm_device_dma_t *dma = dev->dma;
 1509         drm_buf_t *buf;
 1510         drm_r128_buf_priv_t *buf_priv;
 1511         drm_r128_indirect_t indirect;
 1512 #if 0
 1513         RING_LOCALS;
 1514 #endif
 1515 
 1516         LOCK_TEST_WITH_RETURN( dev );
 1517 
 1518         if ( !dev_priv ) {
 1519                 DRM_ERROR( "%s called with no initialization\n", __func__ );
 1520                 return DRM_OS_ERR(EINVAL);
 1521         }
 1522 
 1523         DRM_OS_KRNFROMUSR( indirect, (drm_r128_indirect_t *) data,
 1524                              sizeof(indirect) );
 1525 
 1526         DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
 1527                    indirect.idx, indirect.start,
 1528                    indirect.end, indirect.discard );
 1529 
 1530         if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
 1531                 DRM_ERROR( "buffer index %d (of %d max)\n",
 1532                            indirect.idx, dma->buf_count - 1 );
 1533                 return DRM_OS_ERR(EINVAL);
 1534         }
 1535 
 1536         buf = dma->buflist[indirect.idx];
 1537         buf_priv = buf->dev_private;
 1538 
 1539         if ( buf->pid != DRM_OS_CURRENTPID ) {
 1540                 DRM_ERROR( "process %d using buffer owned by %d\n",
 1541                            DRM_OS_CURRENTPID, buf->pid );
 1542                 return DRM_OS_ERR(EINVAL);
 1543         }
 1544         if ( buf->pending ) {
 1545                 DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
 1546                 return DRM_OS_ERR(EINVAL);
 1547         }
 1548 
 1549         if ( indirect.start < buf->used ) {
 1550                 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
 1551                            indirect.start, buf->used );
 1552                 return DRM_OS_ERR(EINVAL);
 1553         }
 1554 
 1555         RING_SPACE_TEST_WITH_RETURN( dev_priv );
 1556         VB_AGE_TEST_WITH_RETURN( dev_priv );
 1557 
 1558         buf->used = indirect.end;
 1559         buf_priv->discard = indirect.discard;
 1560 
 1561 #if 0
 1562         /* Wait for the 3D stream to idle before the indirect buffer
 1563          * containing 2D acceleration commands is processed.
 1564          */
 1565         BEGIN_RING( 2 );
 1566         RADEON_WAIT_UNTIL_3D_IDLE();
 1567         ADVANCE_RING();
 1568 #endif
 1569 
 1570         /* Dispatch the indirect buffer full of commands from the
 1571          * X server.  This is insecure and is thus only available to
 1572          * privileged clients.
 1573          */
 1574         r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
 1575 
 1576         return 0;
 1577 }

Cache object: feef9a24198ec603ffad4fc7c4a80d0e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.