195584Sanholt/* r128_state.c -- State support for r128 -*- linux-c -*- 2152909Sanholt * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com 3152909Sanholt */ 4139749Simp/*- 595584Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 695584Sanholt * All Rights Reserved. 795584Sanholt * 895584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 995584Sanholt * copy of this software and associated documentation files (the "Software"), 1095584Sanholt * to deal in the Software without restriction, including without limitation 1195584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1295584Sanholt * and/or sell copies of the Software, and to permit persons to whom the 1395584Sanholt * Software is furnished to do so, subject to the following conditions: 1495584Sanholt * 1595584Sanholt * The above copyright notice and this permission notice (including the next 1695584Sanholt * paragraph) shall be included in all copies or substantial portions of the 1795584Sanholt * Software. 1895584Sanholt * 1995584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2095584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2195584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2295584Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2395584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2495584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2595584Sanholt * DEALINGS IN THE SOFTWARE. 2695584Sanholt * 2795584Sanholt * Authors: 2895584Sanholt * Gareth Hughes <gareth@valinux.com> 2995584Sanholt */ 3095584Sanholt 31152909Sanholt#include <sys/cdefs.h> 32152909Sanholt__FBSDID("$FreeBSD$"); 33152909Sanholt 3495584Sanholt#include "dev/drm/drmP.h" 35112015Sanholt#include "dev/drm/drm.h" 3695746Sanholt#include "dev/drm/r128_drm.h" 3795584Sanholt#include "dev/drm/r128_drv.h" 3895584Sanholt 3995584Sanholt/* ================================================================ 4095584Sanholt * CCE hardware state programming functions 4195584Sanholt */ 4295584Sanholt 43145132Sanholtstatic void r128_emit_clip_rects(drm_r128_private_t * dev_priv, 44182080Srnoland struct drm_clip_rect * boxes, int count) 4595584Sanholt{ 4695584Sanholt u32 aux_sc_cntl = 0x00000000; 4795584Sanholt RING_LOCALS; 48182080Srnoland DRM_DEBUG("\n"); 4995584Sanholt 50145132Sanholt BEGIN_RING((count < 3 ? count : 3) * 5 + 2); 5195584Sanholt 52145132Sanholt if (count >= 1) { 53145132Sanholt OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3)); 54145132Sanholt OUT_RING(boxes[0].x1); 55145132Sanholt OUT_RING(boxes[0].x2 - 1); 56145132Sanholt OUT_RING(boxes[0].y1); 57145132Sanholt OUT_RING(boxes[0].y2 - 1); 5895584Sanholt 5995584Sanholt aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR); 6095584Sanholt } 61145132Sanholt if (count >= 2) { 62145132Sanholt OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3)); 63145132Sanholt OUT_RING(boxes[1].x1); 64145132Sanholt OUT_RING(boxes[1].x2 - 1); 65145132Sanholt OUT_RING(boxes[1].y1); 66145132Sanholt OUT_RING(boxes[1].y2 - 1); 6795584Sanholt 6895584Sanholt aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR); 6995584Sanholt } 70145132Sanholt if (count >= 3) { 71145132Sanholt OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3)); 72145132Sanholt OUT_RING(boxes[2].x1); 73145132Sanholt OUT_RING(boxes[2].x2 - 1); 74145132Sanholt OUT_RING(boxes[2].y1); 75145132Sanholt OUT_RING(boxes[2].y2 - 1); 7695584Sanholt 7795584Sanholt aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR); 7895584Sanholt } 7995584Sanholt 80145132Sanholt OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0)); 81145132Sanholt OUT_RING(aux_sc_cntl); 8295584Sanholt 8395584Sanholt ADVANCE_RING(); 8495584Sanholt} 8595584Sanholt 86145132Sanholtstatic __inline__ void r128_emit_core(drm_r128_private_t * dev_priv) 8795584Sanholt{ 8895584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 8995584Sanholt drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 9095584Sanholt RING_LOCALS; 91182080Srnoland DRM_DEBUG("\n"); 9295584Sanholt 93145132Sanholt BEGIN_RING(2); 9495584Sanholt 95145132Sanholt OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0)); 96145132Sanholt OUT_RING(ctx->scale_3d_cntl); 9795584Sanholt 9895584Sanholt ADVANCE_RING(); 9995584Sanholt} 10095584Sanholt 101145132Sanholtstatic __inline__ void r128_emit_context(drm_r128_private_t * dev_priv) 10295584Sanholt{ 10395584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 10495584Sanholt drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 10595584Sanholt RING_LOCALS; 106182080Srnoland DRM_DEBUG("\n"); 10795584Sanholt 108145132Sanholt BEGIN_RING(13); 10995584Sanholt 110145132Sanholt OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11)); 111145132Sanholt OUT_RING(ctx->dst_pitch_offset_c); 112145132Sanholt OUT_RING(ctx->dp_gui_master_cntl_c); 113145132Sanholt OUT_RING(ctx->sc_top_left_c); 114145132Sanholt OUT_RING(ctx->sc_bottom_right_c); 115145132Sanholt OUT_RING(ctx->z_offset_c); 116145132Sanholt OUT_RING(ctx->z_pitch_c); 117145132Sanholt OUT_RING(ctx->z_sten_cntl_c); 118145132Sanholt OUT_RING(ctx->tex_cntl_c); 119145132Sanholt OUT_RING(ctx->misc_3d_state_cntl_reg); 120145132Sanholt OUT_RING(ctx->texture_clr_cmp_clr_c); 121145132Sanholt OUT_RING(ctx->texture_clr_cmp_msk_c); 122145132Sanholt OUT_RING(ctx->fog_color_c); 12395584Sanholt 12495584Sanholt ADVANCE_RING(); 12595584Sanholt} 12695584Sanholt 127145132Sanholtstatic __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv) 12895584Sanholt{ 12995584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 13095584Sanholt drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 13195584Sanholt RING_LOCALS; 132182080Srnoland DRM_DEBUG("\n"); 13395584Sanholt 134145132Sanholt BEGIN_RING(3); 13595584Sanholt 136145132Sanholt OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP)); 137145132Sanholt OUT_RING(ctx->setup_cntl); 138145132Sanholt OUT_RING(ctx->pm4_vc_fpu_setup); 13995584Sanholt 14095584Sanholt ADVANCE_RING(); 14195584Sanholt} 14295584Sanholt 143145132Sanholtstatic __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv) 14495584Sanholt{ 14595584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 14695584Sanholt drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 14795584Sanholt RING_LOCALS; 148182080Srnoland DRM_DEBUG("\n"); 14995584Sanholt 150145132Sanholt BEGIN_RING(5); 15195584Sanholt 152145132Sanholt OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0)); 153145132Sanholt OUT_RING(ctx->dp_write_mask); 15495584Sanholt 155145132Sanholt OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1)); 156145132Sanholt OUT_RING(ctx->sten_ref_mask_c); 157145132Sanholt OUT_RING(ctx->plane_3d_mask_c); 15895584Sanholt 15995584Sanholt ADVANCE_RING(); 16095584Sanholt} 16195584Sanholt 162145132Sanholtstatic __inline__ void r128_emit_window(drm_r128_private_t * dev_priv) 16395584Sanholt{ 16495584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 16595584Sanholt drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 16695584Sanholt RING_LOCALS; 167182080Srnoland DRM_DEBUG("\n"); 16895584Sanholt 169145132Sanholt BEGIN_RING(2); 17095584Sanholt 171145132Sanholt OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0)); 172145132Sanholt OUT_RING(ctx->window_xy_offset); 17395584Sanholt 17495584Sanholt ADVANCE_RING(); 17595584Sanholt} 17695584Sanholt 177145132Sanholtstatic __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv) 17895584Sanholt{ 17995584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 18095584Sanholt drm_r128_context_regs_t *ctx = &sarea_priv->context_state; 18195584Sanholt drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0]; 18295584Sanholt int i; 18395584Sanholt RING_LOCALS; 184182080Srnoland DRM_DEBUG("\n"); 18595584Sanholt 186145132Sanholt BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS); 18795584Sanholt 188145132Sanholt OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C, 189145132Sanholt 2 + R128_MAX_TEXTURE_LEVELS)); 190145132Sanholt OUT_RING(tex->tex_cntl); 191145132Sanholt OUT_RING(tex->tex_combine_cntl); 192145132Sanholt OUT_RING(ctx->tex_size_pitch_c); 193145132Sanholt for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) { 194145132Sanholt OUT_RING(tex->tex_offset[i]); 19595584Sanholt } 19695584Sanholt 197145132Sanholt OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1)); 198145132Sanholt OUT_RING(ctx->constant_color_c); 199145132Sanholt OUT_RING(tex->tex_border_color); 20095584Sanholt 20195584Sanholt ADVANCE_RING(); 20295584Sanholt} 20395584Sanholt 204145132Sanholtstatic __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv) 20595584Sanholt{ 20695584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 20795584Sanholt drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1]; 20895584Sanholt int i; 20995584Sanholt RING_LOCALS; 210182080Srnoland DRM_DEBUG("\n"); 21195584Sanholt 212145132Sanholt BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS); 21395584Sanholt 214145132Sanholt OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS)); 215145132Sanholt OUT_RING(tex->tex_cntl); 216145132Sanholt OUT_RING(tex->tex_combine_cntl); 217145132Sanholt for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) { 218145132Sanholt OUT_RING(tex->tex_offset[i]); 21995584Sanholt } 22095584Sanholt 221145132Sanholt OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0)); 222145132Sanholt OUT_RING(tex->tex_border_color); 22395584Sanholt 22495584Sanholt ADVANCE_RING(); 22595584Sanholt} 22695584Sanholt 227182080Srnolandstatic void r128_emit_state(drm_r128_private_t * dev_priv) 22895584Sanholt{ 22995584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 23095584Sanholt unsigned int dirty = sarea_priv->dirty; 23195584Sanholt 232182080Srnoland DRM_DEBUG("dirty=0x%08x\n", dirty); 23395584Sanholt 234145132Sanholt if (dirty & R128_UPLOAD_CORE) { 235145132Sanholt r128_emit_core(dev_priv); 23695584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_CORE; 23795584Sanholt } 23895584Sanholt 239145132Sanholt if (dirty & R128_UPLOAD_CONTEXT) { 240145132Sanholt r128_emit_context(dev_priv); 24195584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT; 24295584Sanholt } 24395584Sanholt 244145132Sanholt if (dirty & R128_UPLOAD_SETUP) { 245145132Sanholt r128_emit_setup(dev_priv); 24695584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_SETUP; 24795584Sanholt } 24895584Sanholt 249145132Sanholt if (dirty & R128_UPLOAD_MASKS) { 250145132Sanholt r128_emit_masks(dev_priv); 25195584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_MASKS; 25295584Sanholt } 25395584Sanholt 254145132Sanholt if (dirty & R128_UPLOAD_WINDOW) { 255145132Sanholt r128_emit_window(dev_priv); 25695584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_WINDOW; 25795584Sanholt } 25895584Sanholt 259145132Sanholt if (dirty & R128_UPLOAD_TEX0) { 260145132Sanholt r128_emit_tex0(dev_priv); 26195584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_TEX0; 26295584Sanholt } 26395584Sanholt 264145132Sanholt if (dirty & R128_UPLOAD_TEX1) { 265145132Sanholt r128_emit_tex1(dev_priv); 26695584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_TEX1; 26795584Sanholt } 26895584Sanholt 26995584Sanholt /* Turn off the texture cache flushing */ 27095584Sanholt sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; 27195584Sanholt 27295584Sanholt sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE; 27395584Sanholt} 27495584Sanholt 27595584Sanholt#if R128_PERFORMANCE_BOXES 27695584Sanholt/* ================================================================ 27795584Sanholt * Performance monitoring functions 27895584Sanholt */ 27995584Sanholt 280145132Sanholtstatic void r128_clear_box(drm_r128_private_t * dev_priv, 281145132Sanholt int x, int y, int w, int h, int r, int g, int b) 28295584Sanholt{ 28395584Sanholt u32 pitch, offset; 28495584Sanholt u32 fb_bpp, color; 28595584Sanholt RING_LOCALS; 28695584Sanholt 287145132Sanholt switch (dev_priv->fb_bpp) { 28895584Sanholt case 16: 28995584Sanholt fb_bpp = R128_GMC_DST_16BPP; 29095584Sanholt color = (((r & 0xf8) << 8) | 291145132Sanholt ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); 29295584Sanholt break; 29395584Sanholt case 24: 29495584Sanholt fb_bpp = R128_GMC_DST_24BPP; 29595584Sanholt color = ((r << 16) | (g << 8) | b); 29695584Sanholt break; 29795584Sanholt case 32: 29895584Sanholt fb_bpp = R128_GMC_DST_32BPP; 299145132Sanholt color = (((0xff) << 24) | (r << 16) | (g << 8) | b); 30095584Sanholt break; 30195584Sanholt default: 30295584Sanholt return; 30395584Sanholt } 30495584Sanholt 30595584Sanholt offset = dev_priv->back_offset; 30695584Sanholt pitch = dev_priv->back_pitch >> 3; 30795584Sanholt 308145132Sanholt BEGIN_RING(6); 30995584Sanholt 310145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 311145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 312145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 313145132Sanholt fb_bpp | 314145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 315145132Sanholt R128_ROP3_P | 316145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS); 31795584Sanholt 318145132Sanholt OUT_RING((pitch << 21) | (offset >> 5)); 319145132Sanholt OUT_RING(color); 32095584Sanholt 321145132Sanholt OUT_RING((x << 16) | y); 322145132Sanholt OUT_RING((w << 16) | h); 32395584Sanholt 32495584Sanholt ADVANCE_RING(); 32595584Sanholt} 32695584Sanholt 327145132Sanholtstatic void r128_cce_performance_boxes(drm_r128_private_t * dev_priv) 32895584Sanholt{ 329145132Sanholt if (atomic_read(&dev_priv->idle_count) == 0) { 330145132Sanholt r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); 33195584Sanholt } else { 332145132Sanholt atomic_set(&dev_priv->idle_count, 0); 33395584Sanholt } 33495584Sanholt} 33595584Sanholt 33695584Sanholt#endif 33795584Sanholt 33895584Sanholt/* ================================================================ 33995584Sanholt * CCE command dispatch functions 34095584Sanholt */ 34195584Sanholt 342145132Sanholtstatic void r128_print_dirty(const char *msg, unsigned int flags) 34395584Sanholt{ 344145132Sanholt DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n", 345145132Sanholt msg, 346145132Sanholt flags, 347145132Sanholt (flags & R128_UPLOAD_CORE) ? "core, " : "", 348145132Sanholt (flags & R128_UPLOAD_CONTEXT) ? "context, " : "", 349145132Sanholt (flags & R128_UPLOAD_SETUP) ? "setup, " : "", 350145132Sanholt (flags & R128_UPLOAD_TEX0) ? "tex0, " : "", 351145132Sanholt (flags & R128_UPLOAD_TEX1) ? "tex1, " : "", 352145132Sanholt (flags & R128_UPLOAD_MASKS) ? "masks, " : "", 353145132Sanholt (flags & R128_UPLOAD_WINDOW) ? "window, " : "", 354145132Sanholt (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "", 355145132Sanholt (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : ""); 35695584Sanholt} 35795584Sanholt 358182080Srnolandstatic void r128_cce_dispatch_clear(struct drm_device * dev, 359145132Sanholt drm_r128_clear_t * clear) 36095584Sanholt{ 36195584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 36295584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 36395584Sanholt int nbox = sarea_priv->nbox; 364182080Srnoland struct drm_clip_rect *pbox = sarea_priv->boxes; 36595584Sanholt unsigned int flags = clear->flags; 36695584Sanholt int i; 36795584Sanholt RING_LOCALS; 368182080Srnoland DRM_DEBUG("\n"); 36995584Sanholt 370145132Sanholt if (dev_priv->page_flipping && dev_priv->current_page == 1) { 37195584Sanholt unsigned int tmp = flags; 37295584Sanholt 37395584Sanholt flags &= ~(R128_FRONT | R128_BACK); 374145132Sanholt if (tmp & R128_FRONT) 375145132Sanholt flags |= R128_BACK; 376145132Sanholt if (tmp & R128_BACK) 377145132Sanholt flags |= R128_FRONT; 37895584Sanholt } 37995584Sanholt 380145132Sanholt for (i = 0; i < nbox; i++) { 38195584Sanholt int x = pbox[i].x1; 38295584Sanholt int y = pbox[i].y1; 38395584Sanholt int w = pbox[i].x2 - x; 38495584Sanholt int h = pbox[i].y2 - y; 38595584Sanholt 386145132Sanholt DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", 387145132Sanholt pbox[i].x1, pbox[i].y1, pbox[i].x2, 388145132Sanholt pbox[i].y2, flags); 38995584Sanholt 390145132Sanholt if (flags & (R128_FRONT | R128_BACK)) { 391145132Sanholt BEGIN_RING(2); 39295584Sanholt 393145132Sanholt OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0)); 394145132Sanholt OUT_RING(clear->color_mask); 39595584Sanholt 39695584Sanholt ADVANCE_RING(); 39795584Sanholt } 39895584Sanholt 399145132Sanholt if (flags & R128_FRONT) { 400145132Sanholt BEGIN_RING(6); 40195584Sanholt 402145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 403145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 404145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 405145132Sanholt (dev_priv->color_fmt << 8) | 406145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 407145132Sanholt R128_ROP3_P | 408145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 409145132Sanholt R128_GMC_AUX_CLIP_DIS); 41095584Sanholt 411145132Sanholt OUT_RING(dev_priv->front_pitch_offset_c); 412145132Sanholt OUT_RING(clear->clear_color); 41395584Sanholt 414145132Sanholt OUT_RING((x << 16) | y); 415145132Sanholt OUT_RING((w << 16) | h); 41695584Sanholt 41795584Sanholt ADVANCE_RING(); 41895584Sanholt } 41995584Sanholt 420145132Sanholt if (flags & R128_BACK) { 421145132Sanholt BEGIN_RING(6); 42295584Sanholt 423145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 424145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 425145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 426145132Sanholt (dev_priv->color_fmt << 8) | 427145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 428145132Sanholt R128_ROP3_P | 429145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 430145132Sanholt R128_GMC_AUX_CLIP_DIS); 43195584Sanholt 432145132Sanholt OUT_RING(dev_priv->back_pitch_offset_c); 433145132Sanholt OUT_RING(clear->clear_color); 43495584Sanholt 435145132Sanholt OUT_RING((x << 16) | y); 436145132Sanholt OUT_RING((w << 16) | h); 43795584Sanholt 43895584Sanholt ADVANCE_RING(); 43995584Sanholt } 44095584Sanholt 441145132Sanholt if (flags & R128_DEPTH) { 442145132Sanholt BEGIN_RING(6); 44395584Sanholt 444145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 445145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 446145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 447145132Sanholt (dev_priv->depth_fmt << 8) | 448145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 449145132Sanholt R128_ROP3_P | 450145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 451145132Sanholt R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS); 45295584Sanholt 453145132Sanholt OUT_RING(dev_priv->depth_pitch_offset_c); 454145132Sanholt OUT_RING(clear->clear_depth); 45595584Sanholt 456145132Sanholt OUT_RING((x << 16) | y); 457145132Sanholt OUT_RING((w << 16) | h); 45895584Sanholt 45995584Sanholt ADVANCE_RING(); 46095584Sanholt } 46195584Sanholt } 46295584Sanholt} 46395584Sanholt 464182080Srnolandstatic void r128_cce_dispatch_swap(struct drm_device * dev) 46595584Sanholt{ 46695584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 46795584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 46895584Sanholt int nbox = sarea_priv->nbox; 469182080Srnoland struct drm_clip_rect *pbox = sarea_priv->boxes; 47095584Sanholt int i; 47195584Sanholt RING_LOCALS; 472182080Srnoland DRM_DEBUG("\n"); 47395584Sanholt 47495584Sanholt#if R128_PERFORMANCE_BOXES 47595584Sanholt /* Do some trivial performance monitoring... 47695584Sanholt */ 477145132Sanholt r128_cce_performance_boxes(dev_priv); 47895584Sanholt#endif 47995584Sanholt 480145132Sanholt for (i = 0; i < nbox; i++) { 48195584Sanholt int x = pbox[i].x1; 48295584Sanholt int y = pbox[i].y1; 48395584Sanholt int w = pbox[i].x2 - x; 48495584Sanholt int h = pbox[i].y2 - y; 48595584Sanholt 486145132Sanholt BEGIN_RING(7); 48795584Sanholt 488145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); 489145132Sanholt OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | 490145132Sanholt R128_GMC_DST_PITCH_OFFSET_CNTL | 491145132Sanholt R128_GMC_BRUSH_NONE | 492145132Sanholt (dev_priv->color_fmt << 8) | 493145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 494145132Sanholt R128_ROP3_S | 495145132Sanholt R128_DP_SRC_SOURCE_MEMORY | 496145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 497145132Sanholt R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS); 49895584Sanholt 499119098Sanholt /* Make this work even if front & back are flipped: 500119098Sanholt */ 501119098Sanholt if (dev_priv->current_page == 0) { 502145132Sanholt OUT_RING(dev_priv->back_pitch_offset_c); 503145132Sanholt OUT_RING(dev_priv->front_pitch_offset_c); 504145132Sanholt } else { 505145132Sanholt OUT_RING(dev_priv->front_pitch_offset_c); 506145132Sanholt OUT_RING(dev_priv->back_pitch_offset_c); 507119098Sanholt } 50895584Sanholt 509145132Sanholt OUT_RING((x << 16) | y); 510145132Sanholt OUT_RING((x << 16) | y); 511145132Sanholt OUT_RING((w << 16) | h); 51295584Sanholt 51395584Sanholt ADVANCE_RING(); 51495584Sanholt } 51595584Sanholt 51695584Sanholt /* Increment the frame counter. The client-side 3D driver must 51795584Sanholt * throttle the framerate by waiting for this value before 51895584Sanholt * performing the swapbuffer ioctl. 51995584Sanholt */ 52095584Sanholt dev_priv->sarea_priv->last_frame++; 52195584Sanholt 522145132Sanholt BEGIN_RING(2); 52395584Sanholt 524145132Sanholt OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0)); 525145132Sanholt OUT_RING(dev_priv->sarea_priv->last_frame); 52695584Sanholt 52795584Sanholt ADVANCE_RING(); 52895584Sanholt} 52995584Sanholt 530182080Srnolandstatic void r128_cce_dispatch_flip(struct drm_device * dev) 53195584Sanholt{ 53295584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 53395584Sanholt RING_LOCALS; 534182080Srnoland DRM_DEBUG("page=%d pfCurrentPage=%d\n", 535145132Sanholt dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); 53695584Sanholt 53795584Sanholt#if R128_PERFORMANCE_BOXES 53895584Sanholt /* Do some trivial performance monitoring... 53995584Sanholt */ 540145132Sanholt r128_cce_performance_boxes(dev_priv); 54195584Sanholt#endif 54295584Sanholt 543145132Sanholt BEGIN_RING(4); 54495584Sanholt 54595584Sanholt R128_WAIT_UNTIL_PAGE_FLIPPED(); 546145132Sanholt OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0)); 54795584Sanholt 548145132Sanholt if (dev_priv->current_page == 0) { 549145132Sanholt OUT_RING(dev_priv->back_offset); 55095584Sanholt } else { 551145132Sanholt OUT_RING(dev_priv->front_offset); 55295584Sanholt } 55395584Sanholt 55495584Sanholt ADVANCE_RING(); 55595584Sanholt 55695584Sanholt /* Increment the frame counter. The client-side 3D driver must 55795584Sanholt * throttle the framerate by waiting for this value before 55895584Sanholt * performing the swapbuffer ioctl. 55995584Sanholt */ 56095584Sanholt dev_priv->sarea_priv->last_frame++; 561119098Sanholt dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = 562145132Sanholt 1 - dev_priv->current_page; 56395584Sanholt 564145132Sanholt BEGIN_RING(2); 56595584Sanholt 566145132Sanholt OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0)); 567145132Sanholt OUT_RING(dev_priv->sarea_priv->last_frame); 56895584Sanholt 56995584Sanholt ADVANCE_RING(); 57095584Sanholt} 57195584Sanholt 572182080Srnolandstatic void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf) 57395584Sanholt{ 57495584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 57595584Sanholt drm_r128_buf_priv_t *buf_priv = buf->dev_private; 57695584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 57795584Sanholt int format = sarea_priv->vc_format; 57895584Sanholt int offset = buf->bus_address; 57995584Sanholt int size = buf->used; 58095584Sanholt int prim = buf_priv->prim; 58195584Sanholt int i = 0; 58295584Sanholt RING_LOCALS; 583145132Sanholt DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox); 58495584Sanholt 585145132Sanholt if (0) 586145132Sanholt r128_print_dirty("dispatch_vertex", sarea_priv->dirty); 58795584Sanholt 588145132Sanholt if (buf->used) { 58995584Sanholt buf_priv->dispatched = 1; 59095584Sanholt 591145132Sanholt if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) { 592145132Sanholt r128_emit_state(dev_priv); 59395584Sanholt } 59495584Sanholt 59595584Sanholt do { 59695584Sanholt /* Emit the next set of up to three cliprects */ 597145132Sanholt if (i < sarea_priv->nbox) { 598145132Sanholt r128_emit_clip_rects(dev_priv, 599145132Sanholt &sarea_priv->boxes[i], 600145132Sanholt sarea_priv->nbox - i); 60195584Sanholt } 60295584Sanholt 60395584Sanholt /* Emit the vertex buffer rendering commands */ 604145132Sanholt BEGIN_RING(5); 60595584Sanholt 606145132Sanholt OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3)); 607145132Sanholt OUT_RING(offset); 608145132Sanholt OUT_RING(size); 609145132Sanholt OUT_RING(format); 610145132Sanholt OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | 611145132Sanholt (size << R128_CCE_VC_CNTL_NUM_SHIFT)); 61295584Sanholt 61395584Sanholt ADVANCE_RING(); 61495584Sanholt 61595584Sanholt i += 3; 616145132Sanholt } while (i < sarea_priv->nbox); 61795584Sanholt } 61895584Sanholt 619145132Sanholt if (buf_priv->discard) { 62095584Sanholt buf_priv->age = dev_priv->sarea_priv->last_dispatch; 62195584Sanholt 62295584Sanholt /* Emit the vertex buffer age */ 623145132Sanholt BEGIN_RING(2); 62495584Sanholt 625145132Sanholt OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); 626145132Sanholt OUT_RING(buf_priv->age); 62795584Sanholt 62895584Sanholt ADVANCE_RING(); 62995584Sanholt 63095584Sanholt buf->pending = 1; 63195584Sanholt buf->used = 0; 63295584Sanholt /* FIXME: Check dispatched field */ 63395584Sanholt buf_priv->dispatched = 0; 63495584Sanholt } 63595584Sanholt 63695584Sanholt dev_priv->sarea_priv->last_dispatch++; 63795584Sanholt 63895584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; 63995584Sanholt sarea_priv->nbox = 0; 64095584Sanholt} 64195584Sanholt 642182080Srnolandstatic void r128_cce_dispatch_indirect(struct drm_device * dev, 643182080Srnoland struct drm_buf * buf, int start, int end) 64495584Sanholt{ 64595584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 64695584Sanholt drm_r128_buf_priv_t *buf_priv = buf->dev_private; 64795584Sanholt RING_LOCALS; 648145132Sanholt DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); 64995584Sanholt 650145132Sanholt if (start != end) { 65195584Sanholt int offset = buf->bus_address + start; 65295584Sanholt int dwords = (end - start + 3) / sizeof(u32); 65395584Sanholt 65495584Sanholt /* Indirect buffer data must be an even number of 65595584Sanholt * dwords, so if we've been given an odd number we must 65695584Sanholt * pad the data with a Type-2 CCE packet. 65795584Sanholt */ 658145132Sanholt if (dwords & 1) { 65995584Sanholt u32 *data = (u32 *) 660207066Srnoland ((char *)dev->agp_buffer_map->virtual 661145132Sanholt + buf->offset + start); 662145132Sanholt data[dwords++] = cpu_to_le32(R128_CCE_PACKET2); 66395584Sanholt } 66495584Sanholt 66595584Sanholt buf_priv->dispatched = 1; 66695584Sanholt 66795584Sanholt /* Fire off the indirect buffer */ 668145132Sanholt BEGIN_RING(3); 66995584Sanholt 670145132Sanholt OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1)); 671145132Sanholt OUT_RING(offset); 672145132Sanholt OUT_RING(dwords); 67395584Sanholt 67495584Sanholt ADVANCE_RING(); 67595584Sanholt } 67695584Sanholt 677145132Sanholt if (buf_priv->discard) { 67895584Sanholt buf_priv->age = dev_priv->sarea_priv->last_dispatch; 67995584Sanholt 68095584Sanholt /* Emit the indirect buffer age */ 681145132Sanholt BEGIN_RING(2); 68295584Sanholt 683145132Sanholt OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); 684145132Sanholt OUT_RING(buf_priv->age); 68595584Sanholt 68695584Sanholt ADVANCE_RING(); 68795584Sanholt 68895584Sanholt buf->pending = 1; 68995584Sanholt buf->used = 0; 69095584Sanholt /* FIXME: Check dispatched field */ 69195584Sanholt buf_priv->dispatched = 0; 69295584Sanholt } 69395584Sanholt 69495584Sanholt dev_priv->sarea_priv->last_dispatch++; 69595584Sanholt} 69695584Sanholt 697182080Srnolandstatic void r128_cce_dispatch_indices(struct drm_device * dev, 698182080Srnoland struct drm_buf * buf, 699145132Sanholt int start, int end, int count) 70095584Sanholt{ 70195584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 70295584Sanholt drm_r128_buf_priv_t *buf_priv = buf->dev_private; 70395584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 70495584Sanholt int format = sarea_priv->vc_format; 705145132Sanholt int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset; 70695584Sanholt int prim = buf_priv->prim; 70795584Sanholt u32 *data; 70895584Sanholt int dwords; 70995584Sanholt int i = 0; 71095584Sanholt RING_LOCALS; 711145132Sanholt DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count); 71295584Sanholt 713145132Sanholt if (0) 714145132Sanholt r128_print_dirty("dispatch_indices", sarea_priv->dirty); 71595584Sanholt 716145132Sanholt if (start != end) { 71795584Sanholt buf_priv->dispatched = 1; 71895584Sanholt 719145132Sanholt if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) { 720145132Sanholt r128_emit_state(dev_priv); 72195584Sanholt } 72295584Sanholt 72395584Sanholt dwords = (end - start + 3) / sizeof(u32); 72495584Sanholt 725207066Srnoland data = (u32 *) ((char *)dev->agp_buffer_map->virtual 726145132Sanholt + buf->offset + start); 72795584Sanholt 728145132Sanholt data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 729145132Sanholt dwords - 2)); 73095584Sanholt 731145132Sanholt data[1] = cpu_to_le32(offset); 732145132Sanholt data[2] = cpu_to_le32(R128_MAX_VB_VERTS); 733145132Sanholt data[3] = cpu_to_le32(format); 734145132Sanholt data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND | 735145132Sanholt (count << 16))); 73695584Sanholt 737145132Sanholt if (count & 0x1) { 73895584Sanholt#ifdef __LITTLE_ENDIAN 739145132Sanholt data[dwords - 1] &= 0x0000ffff; 74095584Sanholt#else 741145132Sanholt data[dwords - 1] &= 0xffff0000; 74295584Sanholt#endif 74395584Sanholt } 74495584Sanholt 74595584Sanholt do { 74695584Sanholt /* Emit the next set of up to three cliprects */ 747145132Sanholt if (i < sarea_priv->nbox) { 748145132Sanholt r128_emit_clip_rects(dev_priv, 749145132Sanholt &sarea_priv->boxes[i], 750145132Sanholt sarea_priv->nbox - i); 75195584Sanholt } 75295584Sanholt 753145132Sanholt r128_cce_dispatch_indirect(dev, buf, start, end); 75495584Sanholt 75595584Sanholt i += 3; 756145132Sanholt } while (i < sarea_priv->nbox); 75795584Sanholt } 75895584Sanholt 759145132Sanholt if (buf_priv->discard) { 76095584Sanholt buf_priv->age = dev_priv->sarea_priv->last_dispatch; 76195584Sanholt 76295584Sanholt /* Emit the vertex buffer age */ 763145132Sanholt BEGIN_RING(2); 76495584Sanholt 765145132Sanholt OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); 766145132Sanholt OUT_RING(buf_priv->age); 76795584Sanholt 76895584Sanholt ADVANCE_RING(); 76995584Sanholt 77095584Sanholt buf->pending = 1; 77195584Sanholt /* FIXME: Check dispatched field */ 77295584Sanholt buf_priv->dispatched = 0; 77395584Sanholt } 77495584Sanholt 77595584Sanholt dev_priv->sarea_priv->last_dispatch++; 77695584Sanholt 77795584Sanholt sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; 77895584Sanholt sarea_priv->nbox = 0; 77995584Sanholt} 78095584Sanholt 781182080Srnolandstatic int r128_cce_dispatch_blit(struct drm_device * dev, 782182080Srnoland struct drm_file *file_priv, 783182080Srnoland drm_r128_blit_t * blit) 78495584Sanholt{ 78595584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 786182080Srnoland struct drm_device_dma *dma = dev->dma; 787182080Srnoland struct drm_buf *buf; 78895584Sanholt drm_r128_buf_priv_t *buf_priv; 78995584Sanholt u32 *data; 79095584Sanholt int dword_shift, dwords; 79195584Sanholt RING_LOCALS; 792145132Sanholt DRM_DEBUG("\n"); 79395584Sanholt 79495584Sanholt /* The compiler won't optimize away a division by a variable, 79595584Sanholt * even if the only legal values are powers of two. Thus, we'll 79695584Sanholt * use a shift instead. 79795584Sanholt */ 798145132Sanholt switch (blit->format) { 79995584Sanholt case R128_DATATYPE_ARGB8888: 80095584Sanholt dword_shift = 0; 80195584Sanholt break; 80295584Sanholt case R128_DATATYPE_ARGB1555: 80395584Sanholt case R128_DATATYPE_RGB565: 80495584Sanholt case R128_DATATYPE_ARGB4444: 805119098Sanholt case R128_DATATYPE_YVYU422: 806119098Sanholt case R128_DATATYPE_VYUY422: 80795584Sanholt dword_shift = 1; 80895584Sanholt break; 80995584Sanholt case R128_DATATYPE_CI8: 81095584Sanholt case R128_DATATYPE_RGB8: 81195584Sanholt dword_shift = 2; 81295584Sanholt break; 81395584Sanholt default: 814145132Sanholt DRM_ERROR("invalid blit format %d\n", blit->format); 815182080Srnoland return -EINVAL; 81695584Sanholt } 81795584Sanholt 81895584Sanholt /* Flush the pixel cache, and mark the contents as Read Invalid. 81995584Sanholt * This ensures no pixel data gets mixed up with the texture 82095584Sanholt * data from the host data blit, otherwise part of the texture 82195584Sanholt * image may be corrupted. 82295584Sanholt */ 823145132Sanholt BEGIN_RING(2); 82495584Sanholt 825145132Sanholt OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0)); 826145132Sanholt OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI); 82795584Sanholt 82895584Sanholt ADVANCE_RING(); 82995584Sanholt 83095584Sanholt /* Dispatch the indirect buffer. 83195584Sanholt */ 83295584Sanholt buf = dma->buflist[blit->idx]; 83395584Sanholt buf_priv = buf->dev_private; 83495584Sanholt 835182080Srnoland if (buf->file_priv != file_priv) { 836145132Sanholt DRM_ERROR("process %d using buffer owned by %p\n", 837182080Srnoland DRM_CURRENTPID, buf->file_priv); 838182080Srnoland return -EINVAL; 83995584Sanholt } 840145132Sanholt if (buf->pending) { 841145132Sanholt DRM_ERROR("sending pending buffer %d\n", blit->idx); 842182080Srnoland return -EINVAL; 84395584Sanholt } 84495584Sanholt 84595584Sanholt buf_priv->discard = 1; 84695584Sanholt 84795584Sanholt dwords = (blit->width * blit->height) >> dword_shift; 84895584Sanholt 849145132Sanholt data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); 85095584Sanholt 851145132Sanholt data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6)); 852145132Sanholt data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL | 853145132Sanholt R128_GMC_BRUSH_NONE | 854145132Sanholt (blit->format << 8) | 855145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 856145132Sanholt R128_ROP3_S | 857145132Sanholt R128_DP_SRC_SOURCE_HOST_DATA | 858145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 859145132Sanholt R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS)); 86095584Sanholt 861145132Sanholt data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5)); 862145132Sanholt data[3] = cpu_to_le32(0xffffffff); 863145132Sanholt data[4] = cpu_to_le32(0xffffffff); 864145132Sanholt data[5] = cpu_to_le32((blit->y << 16) | blit->x); 865145132Sanholt data[6] = cpu_to_le32((blit->height << 16) | blit->width); 866145132Sanholt data[7] = cpu_to_le32(dwords); 86795584Sanholt 86895584Sanholt buf->used = (dwords + 8) * sizeof(u32); 86995584Sanholt 870145132Sanholt r128_cce_dispatch_indirect(dev, buf, 0, buf->used); 87195584Sanholt 87295584Sanholt /* Flush the pixel cache after the blit completes. This ensures 87395584Sanholt * the texture data is written out to memory before rendering 87495584Sanholt * continues. 87595584Sanholt */ 876145132Sanholt BEGIN_RING(2); 87795584Sanholt 878145132Sanholt OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0)); 879145132Sanholt OUT_RING(R128_PC_FLUSH_GUI); 88095584Sanholt 88195584Sanholt ADVANCE_RING(); 88295584Sanholt 88395584Sanholt return 0; 88495584Sanholt} 88595584Sanholt 88695584Sanholt/* ================================================================ 88795584Sanholt * Tiled depth buffer management 88895584Sanholt * 88995584Sanholt * FIXME: These should all set the destination write mask for when we 89095584Sanholt * have hardware stencil support. 89195584Sanholt */ 89295584Sanholt 893182080Srnolandstatic int r128_cce_dispatch_write_span(struct drm_device * dev, 894145132Sanholt drm_r128_depth_t * depth) 89595584Sanholt{ 89695584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 89795584Sanholt int count, x, y; 89895584Sanholt u32 *buffer; 89995584Sanholt u8 *mask; 900112015Sanholt int i, buffer_size, mask_size; 90195584Sanholt RING_LOCALS; 902145132Sanholt DRM_DEBUG("\n"); 90395584Sanholt 90495584Sanholt count = depth->n; 905130331Sanholt if (count > 4096 || count <= 0) 906182080Srnoland return -EMSGSIZE; 907130331Sanholt 908145132Sanholt if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { 909182080Srnoland return -EFAULT; 91095584Sanholt } 911145132Sanholt if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { 912182080Srnoland return -EFAULT; 91395584Sanholt } 91495584Sanholt 915112015Sanholt buffer_size = depth->n * sizeof(u32); 916145132Sanholt buffer = drm_alloc(buffer_size, DRM_MEM_BUFS); 917145132Sanholt if (buffer == NULL) 918182080Srnoland return -ENOMEM; 919145132Sanholt if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { 920145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 921182080Srnoland return -EFAULT; 92295584Sanholt } 92395584Sanholt 924112015Sanholt mask_size = depth->n * sizeof(u8); 925145132Sanholt if (depth->mask) { 926145132Sanholt mask = drm_alloc(mask_size, DRM_MEM_BUFS); 927145132Sanholt if (mask == NULL) { 928145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 929182080Srnoland return -ENOMEM; 93095584Sanholt } 931145132Sanholt if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { 932145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 933145132Sanholt drm_free(mask, mask_size, DRM_MEM_BUFS); 934182080Srnoland return -EFAULT; 93595584Sanholt } 93695584Sanholt 937145132Sanholt for (i = 0; i < count; i++, x++) { 938145132Sanholt if (mask[i]) { 939145132Sanholt BEGIN_RING(6); 94095584Sanholt 941145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 942145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 943145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 944145132Sanholt (dev_priv->depth_fmt << 8) | 945145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 946145132Sanholt R128_ROP3_P | 947145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 948145132Sanholt R128_GMC_WR_MSK_DIS); 94995584Sanholt 950145132Sanholt OUT_RING(dev_priv->depth_pitch_offset_c); 951145132Sanholt OUT_RING(buffer[i]); 95295584Sanholt 953145132Sanholt OUT_RING((x << 16) | y); 954145132Sanholt OUT_RING((1 << 16) | 1); 95595584Sanholt 95695584Sanholt ADVANCE_RING(); 95795584Sanholt } 95895584Sanholt } 95995584Sanholt 960145132Sanholt drm_free(mask, mask_size, DRM_MEM_BUFS); 96195584Sanholt } else { 962145132Sanholt for (i = 0; i < count; i++, x++) { 963145132Sanholt BEGIN_RING(6); 96495584Sanholt 965145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 966145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 967145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 968145132Sanholt (dev_priv->depth_fmt << 8) | 969145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 970145132Sanholt R128_ROP3_P | 971145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 972145132Sanholt R128_GMC_WR_MSK_DIS); 97395584Sanholt 974145132Sanholt OUT_RING(dev_priv->depth_pitch_offset_c); 975145132Sanholt OUT_RING(buffer[i]); 97695584Sanholt 977145132Sanholt OUT_RING((x << 16) | y); 978145132Sanholt OUT_RING((1 << 16) | 1); 97995584Sanholt 98095584Sanholt ADVANCE_RING(); 98195584Sanholt } 98295584Sanholt } 98395584Sanholt 984145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 98595584Sanholt 98695584Sanholt return 0; 98795584Sanholt} 98895584Sanholt 989182080Srnolandstatic int r128_cce_dispatch_write_pixels(struct drm_device * dev, 990145132Sanholt drm_r128_depth_t * depth) 99195584Sanholt{ 99295584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 99395584Sanholt int count, *x, *y; 99495584Sanholt u32 *buffer; 99595584Sanholt u8 *mask; 996112015Sanholt int i, xbuf_size, ybuf_size, buffer_size, mask_size; 99795584Sanholt RING_LOCALS; 998145132Sanholt DRM_DEBUG("\n"); 99995584Sanholt 100095584Sanholt count = depth->n; 1001130331Sanholt if (count > 4096 || count <= 0) 1002182080Srnoland return -EMSGSIZE; 100395584Sanholt 1004112015Sanholt xbuf_size = count * sizeof(*x); 1005112015Sanholt ybuf_size = count * sizeof(*y); 1006145132Sanholt x = drm_alloc(xbuf_size, DRM_MEM_BUFS); 1007145132Sanholt if (x == NULL) { 1008182080Srnoland return -ENOMEM; 100995584Sanholt } 1010145132Sanholt y = drm_alloc(ybuf_size, DRM_MEM_BUFS); 1011145132Sanholt if (y == NULL) { 1012145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1013182080Srnoland return -ENOMEM; 101495584Sanholt } 1015145132Sanholt if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { 1016145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1017145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1018182080Srnoland return -EFAULT; 101995584Sanholt } 1020145132Sanholt if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) { 1021145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1022145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1023182080Srnoland return -EFAULT; 102495584Sanholt } 102595584Sanholt 1026112015Sanholt buffer_size = depth->n * sizeof(u32); 1027145132Sanholt buffer = drm_alloc(buffer_size, DRM_MEM_BUFS); 1028145132Sanholt if (buffer == NULL) { 1029145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1030145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1031182080Srnoland return -ENOMEM; 103295584Sanholt } 1033145132Sanholt if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { 1034145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1035145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1036145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 1037182080Srnoland return -EFAULT; 103895584Sanholt } 103995584Sanholt 1040145132Sanholt if (depth->mask) { 1041112015Sanholt mask_size = depth->n * sizeof(u8); 1042145132Sanholt mask = drm_alloc(mask_size, DRM_MEM_BUFS); 1043145132Sanholt if (mask == NULL) { 1044145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1045145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1046145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 1047182080Srnoland return -ENOMEM; 104895584Sanholt } 1049145132Sanholt if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { 1050145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1051145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1052145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 1053145132Sanholt drm_free(mask, mask_size, DRM_MEM_BUFS); 1054182080Srnoland return -EFAULT; 105595584Sanholt } 105695584Sanholt 1057145132Sanholt for (i = 0; i < count; i++) { 1058145132Sanholt if (mask[i]) { 1059145132Sanholt BEGIN_RING(6); 106095584Sanholt 1061145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 1062145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 1063145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 1064145132Sanholt (dev_priv->depth_fmt << 8) | 1065145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 1066145132Sanholt R128_ROP3_P | 1067145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 1068145132Sanholt R128_GMC_WR_MSK_DIS); 106995584Sanholt 1070145132Sanholt OUT_RING(dev_priv->depth_pitch_offset_c); 1071145132Sanholt OUT_RING(buffer[i]); 107295584Sanholt 1073145132Sanholt OUT_RING((x[i] << 16) | y[i]); 1074145132Sanholt OUT_RING((1 << 16) | 1); 107595584Sanholt 107695584Sanholt ADVANCE_RING(); 107795584Sanholt } 107895584Sanholt } 107995584Sanholt 1080145132Sanholt drm_free(mask, mask_size, DRM_MEM_BUFS); 108195584Sanholt } else { 1082145132Sanholt for (i = 0; i < count; i++) { 1083145132Sanholt BEGIN_RING(6); 108495584Sanholt 1085145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 1086145132Sanholt OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 1087145132Sanholt R128_GMC_BRUSH_SOLID_COLOR | 1088145132Sanholt (dev_priv->depth_fmt << 8) | 1089145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 1090145132Sanholt R128_ROP3_P | 1091145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | 1092145132Sanholt R128_GMC_WR_MSK_DIS); 109395584Sanholt 1094145132Sanholt OUT_RING(dev_priv->depth_pitch_offset_c); 1095145132Sanholt OUT_RING(buffer[i]); 109695584Sanholt 1097145132Sanholt OUT_RING((x[i] << 16) | y[i]); 1098145132Sanholt OUT_RING((1 << 16) | 1); 109995584Sanholt 110095584Sanholt ADVANCE_RING(); 110195584Sanholt } 110295584Sanholt } 110395584Sanholt 1104145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1105145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1106145132Sanholt drm_free(buffer, buffer_size, DRM_MEM_BUFS); 110795584Sanholt 110895584Sanholt return 0; 110995584Sanholt} 111095584Sanholt 1111182080Srnolandstatic int r128_cce_dispatch_read_span(struct drm_device * dev, 1112145132Sanholt drm_r128_depth_t * depth) 111395584Sanholt{ 111495584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 111595584Sanholt int count, x, y; 111695584Sanholt RING_LOCALS; 1117145132Sanholt DRM_DEBUG("\n"); 111895584Sanholt 111995584Sanholt count = depth->n; 1120130331Sanholt if (count > 4096 || count <= 0) 1121182080Srnoland return -EMSGSIZE; 1122126137Srwatson 1123145132Sanholt if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { 1124182080Srnoland return -EFAULT; 112595584Sanholt } 1126145132Sanholt if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { 1127182080Srnoland return -EFAULT; 112895584Sanholt } 112995584Sanholt 1130145132Sanholt BEGIN_RING(7); 113195584Sanholt 1132145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); 1133145132Sanholt OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | 1134145132Sanholt R128_GMC_DST_PITCH_OFFSET_CNTL | 1135145132Sanholt R128_GMC_BRUSH_NONE | 1136145132Sanholt (dev_priv->depth_fmt << 8) | 1137145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 1138145132Sanholt R128_ROP3_S | 1139145132Sanholt R128_DP_SRC_SOURCE_MEMORY | 1140145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); 114195584Sanholt 1142145132Sanholt OUT_RING(dev_priv->depth_pitch_offset_c); 1143145132Sanholt OUT_RING(dev_priv->span_pitch_offset_c); 114495584Sanholt 1145145132Sanholt OUT_RING((x << 16) | y); 1146145132Sanholt OUT_RING((0 << 16) | 0); 1147145132Sanholt OUT_RING((count << 16) | 1); 114895584Sanholt 114995584Sanholt ADVANCE_RING(); 115095584Sanholt 115195584Sanholt return 0; 115295584Sanholt} 115395584Sanholt 1154182080Srnolandstatic int r128_cce_dispatch_read_pixels(struct drm_device * dev, 1155145132Sanholt drm_r128_depth_t * depth) 115695584Sanholt{ 115795584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 115895584Sanholt int count, *x, *y; 1159112015Sanholt int i, xbuf_size, ybuf_size; 116095584Sanholt RING_LOCALS; 1161182080Srnoland DRM_DEBUG("\n"); 116295584Sanholt 116395584Sanholt count = depth->n; 1164130331Sanholt if (count > 4096 || count <= 0) 1165182080Srnoland return -EMSGSIZE; 1166130331Sanholt 1167145132Sanholt if (count > dev_priv->depth_pitch) { 116895584Sanholt count = dev_priv->depth_pitch; 116995584Sanholt } 117095584Sanholt 1171112015Sanholt xbuf_size = count * sizeof(*x); 1172112015Sanholt ybuf_size = count * sizeof(*y); 1173145132Sanholt x = drm_alloc(xbuf_size, DRM_MEM_BUFS); 1174145132Sanholt if (x == NULL) { 1175182080Srnoland return -ENOMEM; 117695584Sanholt } 1177145132Sanholt y = drm_alloc(ybuf_size, DRM_MEM_BUFS); 1178145132Sanholt if (y == NULL) { 1179145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1180182080Srnoland return -ENOMEM; 118195584Sanholt } 1182145132Sanholt if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { 1183145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1184145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1185182080Srnoland return -EFAULT; 118695584Sanholt } 1187145132Sanholt if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) { 1188145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1189145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 1190182080Srnoland return -EFAULT; 119195584Sanholt } 119295584Sanholt 1193145132Sanholt for (i = 0; i < count; i++) { 1194145132Sanholt BEGIN_RING(7); 119595584Sanholt 1196145132Sanholt OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); 1197145132Sanholt OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | 1198145132Sanholt R128_GMC_DST_PITCH_OFFSET_CNTL | 1199145132Sanholt R128_GMC_BRUSH_NONE | 1200145132Sanholt (dev_priv->depth_fmt << 8) | 1201145132Sanholt R128_GMC_SRC_DATATYPE_COLOR | 1202145132Sanholt R128_ROP3_S | 1203145132Sanholt R128_DP_SRC_SOURCE_MEMORY | 1204145132Sanholt R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); 120595584Sanholt 1206145132Sanholt OUT_RING(dev_priv->depth_pitch_offset_c); 1207145132Sanholt OUT_RING(dev_priv->span_pitch_offset_c); 120895584Sanholt 1209145132Sanholt OUT_RING((x[i] << 16) | y[i]); 1210145132Sanholt OUT_RING((i << 16) | 0); 1211145132Sanholt OUT_RING((1 << 16) | 1); 121295584Sanholt 121395584Sanholt ADVANCE_RING(); 121495584Sanholt } 121595584Sanholt 1216145132Sanholt drm_free(x, xbuf_size, DRM_MEM_BUFS); 1217145132Sanholt drm_free(y, ybuf_size, DRM_MEM_BUFS); 121895584Sanholt 121995584Sanholt return 0; 122095584Sanholt} 122195584Sanholt 122295584Sanholt/* ================================================================ 122395584Sanholt * Polygon stipple 122495584Sanholt */ 122595584Sanholt 1226182080Srnolandstatic void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple) 122795584Sanholt{ 122895584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 122995584Sanholt int i; 123095584Sanholt RING_LOCALS; 1231182080Srnoland DRM_DEBUG("\n"); 123295584Sanholt 1233145132Sanholt BEGIN_RING(33); 123495584Sanholt 1235145132Sanholt OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31)); 1236145132Sanholt for (i = 0; i < 32; i++) { 1237145132Sanholt OUT_RING(stipple[i]); 123895584Sanholt } 123995584Sanholt 124095584Sanholt ADVANCE_RING(); 124195584Sanholt} 124295584Sanholt 124395584Sanholt/* ================================================================ 124495584Sanholt * IOCTL functions 124595584Sanholt */ 124695584Sanholt 1247182080Srnolandstatic int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) 124895584Sanholt{ 124995584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 125095584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 1251182080Srnoland drm_r128_clear_t *clear = data; 1252145132Sanholt DRM_DEBUG("\n"); 125395584Sanholt 1254182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 125595584Sanholt 1256145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 125795584Sanholt 1258145132Sanholt if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) 125995584Sanholt sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; 126095584Sanholt 1261182080Srnoland r128_cce_dispatch_clear(dev, clear); 1262121447Sanholt COMMIT_RING(); 126395584Sanholt 126495584Sanholt /* Make sure we restore the 3D state next time. 126595584Sanholt */ 126695584Sanholt dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; 126795584Sanholt 126895584Sanholt return 0; 126995584Sanholt} 127095584Sanholt 1271182080Srnolandstatic int r128_do_init_pageflip(struct drm_device * dev) 1272119098Sanholt{ 1273119098Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1274145132Sanholt DRM_DEBUG("\n"); 1275119098Sanholt 1276145132Sanholt dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET); 1277145132Sanholt dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL); 1278119098Sanholt 1279145132Sanholt R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset); 1280145132Sanholt R128_WRITE(R128_CRTC_OFFSET_CNTL, 1281145132Sanholt dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL); 1282119098Sanholt 1283119098Sanholt dev_priv->page_flipping = 1; 1284119098Sanholt dev_priv->current_page = 0; 1285119098Sanholt dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; 1286119098Sanholt 1287119098Sanholt return 0; 1288119098Sanholt} 1289119098Sanholt 1290182080Srnolandstatic int r128_do_cleanup_pageflip(struct drm_device * dev) 1291119098Sanholt{ 1292119098Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1293145132Sanholt DRM_DEBUG("\n"); 1294119098Sanholt 1295145132Sanholt R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset); 1296145132Sanholt R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl); 1297119098Sanholt 1298121447Sanholt if (dev_priv->current_page != 0) { 1299145132Sanholt r128_cce_dispatch_flip(dev); 1300121447Sanholt COMMIT_RING(); 1301121447Sanholt } 1302119098Sanholt 1303119098Sanholt dev_priv->page_flipping = 0; 1304119098Sanholt return 0; 1305119098Sanholt} 1306119098Sanholt 1307119098Sanholt/* Swapping and flipping are different operations, need different ioctls. 1308145132Sanholt * They can & should be intermixed to support multiple 3d windows. 1309119098Sanholt */ 1310119098Sanholt 1311182080Srnolandstatic int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) 1312119098Sanholt{ 1313119098Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1314182080Srnoland DRM_DEBUG("\n"); 1315119098Sanholt 1316182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 1317119098Sanholt 1318145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 1319119098Sanholt 1320145132Sanholt if (!dev_priv->page_flipping) 1321145132Sanholt r128_do_init_pageflip(dev); 1322119098Sanholt 1323145132Sanholt r128_cce_dispatch_flip(dev); 1324119098Sanholt 1325121447Sanholt COMMIT_RING(); 1326119098Sanholt return 0; 1327119098Sanholt} 1328119098Sanholt 1329182080Srnolandstatic int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) 133095584Sanholt{ 133195584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 133295584Sanholt drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 1333182080Srnoland DRM_DEBUG("\n"); 133495584Sanholt 1335182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 133695584Sanholt 1337145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 133895584Sanholt 1339145132Sanholt if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) 134095584Sanholt sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; 134195584Sanholt 1342145132Sanholt r128_cce_dispatch_swap(dev); 1343119098Sanholt dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | 1344119098Sanholt R128_UPLOAD_MASKS); 134595584Sanholt 1346121447Sanholt COMMIT_RING(); 134795584Sanholt return 0; 134895584Sanholt} 134995584Sanholt 1350182080Srnolandstatic int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) 135195584Sanholt{ 135295584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1353182080Srnoland struct drm_device_dma *dma = dev->dma; 1354182080Srnoland struct drm_buf *buf; 135595584Sanholt drm_r128_buf_priv_t *buf_priv; 1356182080Srnoland drm_r128_vertex_t *vertex = data; 135795584Sanholt 1358182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 135995584Sanholt 1360145132Sanholt if (!dev_priv) { 1361182080Srnoland DRM_ERROR("called with no initialization\n"); 1362182080Srnoland return -EINVAL; 136395584Sanholt } 136495584Sanholt 1365145132Sanholt DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", 1366182080Srnoland DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); 136795584Sanholt 1368182080Srnoland if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { 1369145132Sanholt DRM_ERROR("buffer index %d (of %d max)\n", 1370182080Srnoland vertex->idx, dma->buf_count - 1); 1371182080Srnoland return -EINVAL; 137295584Sanholt } 1373182080Srnoland if (vertex->prim < 0 || 1374182080Srnoland vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { 1375182080Srnoland DRM_ERROR("buffer prim %d\n", vertex->prim); 1376182080Srnoland return -EINVAL; 137795584Sanholt } 137895584Sanholt 1379145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 1380145132Sanholt VB_AGE_TEST_WITH_RETURN(dev_priv); 138195584Sanholt 1382182080Srnoland buf = dma->buflist[vertex->idx]; 138395584Sanholt buf_priv = buf->dev_private; 138495584Sanholt 1385182080Srnoland if (buf->file_priv != file_priv) { 1386145132Sanholt DRM_ERROR("process %d using buffer owned by %p\n", 1387182080Srnoland DRM_CURRENTPID, buf->file_priv); 1388182080Srnoland return -EINVAL; 138995584Sanholt } 1390145132Sanholt if (buf->pending) { 1391182080Srnoland DRM_ERROR("sending pending buffer %d\n", vertex->idx); 1392182080Srnoland return -EINVAL; 139395584Sanholt } 139495584Sanholt 1395182080Srnoland buf->used = vertex->count; 1396182080Srnoland buf_priv->prim = vertex->prim; 1397182080Srnoland buf_priv->discard = vertex->discard; 139895584Sanholt 1399145132Sanholt r128_cce_dispatch_vertex(dev, buf); 140095584Sanholt 1401121447Sanholt COMMIT_RING(); 140295584Sanholt return 0; 140395584Sanholt} 140495584Sanholt 1405182080Srnolandstatic int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) 140695584Sanholt{ 140795584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1408182080Srnoland struct drm_device_dma *dma = dev->dma; 1409182080Srnoland struct drm_buf *buf; 141095584Sanholt drm_r128_buf_priv_t *buf_priv; 1411182080Srnoland drm_r128_indices_t *elts = data; 141295584Sanholt int count; 141395584Sanholt 1414182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 141595584Sanholt 1416145132Sanholt if (!dev_priv) { 1417182080Srnoland DRM_ERROR("called with no initialization\n"); 1418182080Srnoland return -EINVAL; 141995584Sanholt } 142095584Sanholt 1421145132Sanholt DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID, 1422182080Srnoland elts->idx, elts->start, elts->end, elts->discard); 142395584Sanholt 1424182080Srnoland if (elts->idx < 0 || elts->idx >= dma->buf_count) { 1425145132Sanholt DRM_ERROR("buffer index %d (of %d max)\n", 1426182080Srnoland elts->idx, dma->buf_count - 1); 1427182080Srnoland return -EINVAL; 142895584Sanholt } 1429182080Srnoland if (elts->prim < 0 || 1430182080Srnoland elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { 1431182080Srnoland DRM_ERROR("buffer prim %d\n", elts->prim); 1432182080Srnoland return -EINVAL; 143395584Sanholt } 143495584Sanholt 1435145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 1436145132Sanholt VB_AGE_TEST_WITH_RETURN(dev_priv); 143795584Sanholt 1438182080Srnoland buf = dma->buflist[elts->idx]; 143995584Sanholt buf_priv = buf->dev_private; 144095584Sanholt 1441182080Srnoland if (buf->file_priv != file_priv) { 1442145132Sanholt DRM_ERROR("process %d using buffer owned by %p\n", 1443182080Srnoland DRM_CURRENTPID, buf->file_priv); 1444182080Srnoland return -EINVAL; 144595584Sanholt } 1446145132Sanholt if (buf->pending) { 1447182080Srnoland DRM_ERROR("sending pending buffer %d\n", elts->idx); 1448182080Srnoland return -EINVAL; 144995584Sanholt } 145095584Sanholt 1451182080Srnoland count = (elts->end - elts->start) / sizeof(u16); 1452182080Srnoland elts->start -= R128_INDEX_PRIM_OFFSET; 145395584Sanholt 1454182080Srnoland if (elts->start & 0x7) { 1455182080Srnoland DRM_ERROR("misaligned buffer 0x%x\n", elts->start); 1456182080Srnoland return -EINVAL; 145795584Sanholt } 1458182080Srnoland if (elts->start < buf->used) { 1459182080Srnoland DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); 1460182080Srnoland return -EINVAL; 146195584Sanholt } 146295584Sanholt 1463182080Srnoland buf->used = elts->end; 1464182080Srnoland buf_priv->prim = elts->prim; 1465182080Srnoland buf_priv->discard = elts->discard; 146695584Sanholt 1467182080Srnoland r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count); 146895584Sanholt 1469121447Sanholt COMMIT_RING(); 147095584Sanholt return 0; 147195584Sanholt} 147295584Sanholt 1473182080Srnolandstatic int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) 147495584Sanholt{ 1475182080Srnoland struct drm_device_dma *dma = dev->dma; 147695584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1477182080Srnoland drm_r128_blit_t *blit = data; 1478121447Sanholt int ret; 147995584Sanholt 1480182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 148195584Sanholt 1482182080Srnoland DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx); 148395584Sanholt 1484182080Srnoland if (blit->idx < 0 || blit->idx >= dma->buf_count) { 1485145132Sanholt DRM_ERROR("buffer index %d (of %d max)\n", 1486182080Srnoland blit->idx, dma->buf_count - 1); 1487182080Srnoland return -EINVAL; 148895584Sanholt } 148995584Sanholt 1490145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 1491145132Sanholt VB_AGE_TEST_WITH_RETURN(dev_priv); 149295584Sanholt 1493182080Srnoland ret = r128_cce_dispatch_blit(dev, file_priv, blit); 1494121447Sanholt 1495121447Sanholt COMMIT_RING(); 1496121447Sanholt return ret; 149795584Sanholt} 149895584Sanholt 1499182080Srnolandstatic int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) 150095584Sanholt{ 150195584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1502182080Srnoland drm_r128_depth_t *depth = data; 1503121447Sanholt int ret; 150495584Sanholt 1505182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 150695584Sanholt 1507145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 150895584Sanholt 1509182080Srnoland ret = -EINVAL; 1510182080Srnoland switch (depth->func) { 151195584Sanholt case R128_WRITE_SPAN: 1512182080Srnoland ret = r128_cce_dispatch_write_span(dev, depth); 1513152909Sanholt break; 151495584Sanholt case R128_WRITE_PIXELS: 1515182080Srnoland ret = r128_cce_dispatch_write_pixels(dev, depth); 1516152909Sanholt break; 151795584Sanholt case R128_READ_SPAN: 1518182080Srnoland ret = r128_cce_dispatch_read_span(dev, depth); 1519152909Sanholt break; 152095584Sanholt case R128_READ_PIXELS: 1521182080Srnoland ret = r128_cce_dispatch_read_pixels(dev, depth); 1522152909Sanholt break; 152395584Sanholt } 152495584Sanholt 1525121447Sanholt COMMIT_RING(); 1526121447Sanholt return ret; 152795584Sanholt} 152895584Sanholt 1529182080Srnolandstatic int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) 153095584Sanholt{ 153195584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1532182080Srnoland drm_r128_stipple_t *stipple = data; 153395584Sanholt u32 mask[32]; 153495584Sanholt 1535182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 153695584Sanholt 1537182080Srnoland if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) 1538182080Srnoland return -EFAULT; 153995584Sanholt 1540145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 154195584Sanholt 1542145132Sanholt r128_cce_dispatch_stipple(dev, mask); 154395584Sanholt 1544121447Sanholt COMMIT_RING(); 154595584Sanholt return 0; 154695584Sanholt} 154795584Sanholt 1548182080Srnolandstatic int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) 154995584Sanholt{ 155095584Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1551182080Srnoland struct drm_device_dma *dma = dev->dma; 1552182080Srnoland struct drm_buf *buf; 155395584Sanholt drm_r128_buf_priv_t *buf_priv; 1554182080Srnoland drm_r128_indirect_t *indirect = data; 155595584Sanholt#if 0 155695584Sanholt RING_LOCALS; 155795584Sanholt#endif 155895584Sanholt 1559182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 156095584Sanholt 1561145132Sanholt if (!dev_priv) { 1562182080Srnoland DRM_ERROR("called with no initialization\n"); 1563182080Srnoland return -EINVAL; 156495584Sanholt } 156595584Sanholt 1566182080Srnoland DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", 1567182080Srnoland indirect->idx, indirect->start, indirect->end, 1568182080Srnoland indirect->discard); 156995584Sanholt 1570182080Srnoland if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { 1571145132Sanholt DRM_ERROR("buffer index %d (of %d max)\n", 1572182080Srnoland indirect->idx, dma->buf_count - 1); 1573182080Srnoland return -EINVAL; 157495584Sanholt } 157595584Sanholt 1576182080Srnoland buf = dma->buflist[indirect->idx]; 157795584Sanholt buf_priv = buf->dev_private; 157895584Sanholt 1579182080Srnoland if (buf->file_priv != file_priv) { 1580145132Sanholt DRM_ERROR("process %d using buffer owned by %p\n", 1581182080Srnoland DRM_CURRENTPID, buf->file_priv); 1582182080Srnoland return -EINVAL; 158395584Sanholt } 1584145132Sanholt if (buf->pending) { 1585182080Srnoland DRM_ERROR("sending pending buffer %d\n", indirect->idx); 1586182080Srnoland return -EINVAL; 158795584Sanholt } 158895584Sanholt 1589182080Srnoland if (indirect->start < buf->used) { 1590145132Sanholt DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", 1591182080Srnoland indirect->start, buf->used); 1592182080Srnoland return -EINVAL; 159395584Sanholt } 159495584Sanholt 1595145132Sanholt RING_SPACE_TEST_WITH_RETURN(dev_priv); 1596145132Sanholt VB_AGE_TEST_WITH_RETURN(dev_priv); 159795584Sanholt 1598182080Srnoland buf->used = indirect->end; 1599182080Srnoland buf_priv->discard = indirect->discard; 160095584Sanholt 160195584Sanholt#if 0 160295584Sanholt /* Wait for the 3D stream to idle before the indirect buffer 160395584Sanholt * containing 2D acceleration commands is processed. 160495584Sanholt */ 1605145132Sanholt BEGIN_RING(2); 160695584Sanholt RADEON_WAIT_UNTIL_3D_IDLE(); 160795584Sanholt ADVANCE_RING(); 160895584Sanholt#endif 160995584Sanholt 161095584Sanholt /* Dispatch the indirect buffer full of commands from the 161195584Sanholt * X server. This is insecure and is thus only available to 161295584Sanholt * privileged clients. 161395584Sanholt */ 1614182080Srnoland r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end); 161595584Sanholt 1616121447Sanholt COMMIT_RING(); 161795584Sanholt return 0; 161895584Sanholt} 1619112015Sanholt 1620182080Srnolandstatic int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) 1621112015Sanholt{ 1622112015Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1623182080Srnoland drm_r128_getparam_t *param = data; 1624112015Sanholt int value; 1625112015Sanholt 1626145132Sanholt if (!dev_priv) { 1627182080Srnoland DRM_ERROR("called with no initialization\n"); 1628182080Srnoland return -EINVAL; 1629112015Sanholt } 1630112015Sanholt 1631145132Sanholt DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 1632112015Sanholt 1633182080Srnoland switch (param->param) { 1634112015Sanholt case R128_PARAM_IRQ_NR: 1635112015Sanholt value = dev->irq; 1636112015Sanholt break; 1637112015Sanholt default: 1638182080Srnoland return -EINVAL; 1639112015Sanholt } 1640112015Sanholt 1641182080Srnoland if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { 1642145132Sanholt DRM_ERROR("copy_to_user\n"); 1643182080Srnoland return -EFAULT; 1644112015Sanholt } 1645145132Sanholt 1646112015Sanholt return 0; 1647112015Sanholt} 1648145132Sanholt 1649182080Srnolandvoid r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) 1650145132Sanholt{ 1651145132Sanholt if (dev->dev_private) { 1652145132Sanholt drm_r128_private_t *dev_priv = dev->dev_private; 1653145132Sanholt if (dev_priv->page_flipping) { 1654145132Sanholt r128_do_cleanup_pageflip(dev); 1655145132Sanholt } 1656145132Sanholt } 1657145132Sanholt} 1658145132Sanholt 1659182080Srnolandvoid r128_driver_lastclose(struct drm_device * dev) 1660145132Sanholt{ 1661145132Sanholt r128_do_cleanup_cce(dev); 1662145132Sanholt} 1663145132Sanholt 1664182080Srnolandstruct drm_ioctl_desc r128_ioctls[] = { 1665182080Srnoland DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1666182080Srnoland DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1667182080Srnoland DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1668182080Srnoland DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1669182080Srnoland DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH), 1670182080Srnoland DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH), 1671182080Srnoland DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH), 1672182080Srnoland DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH), 1673182080Srnoland DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH), 1674182080Srnoland DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH), 1675182080Srnoland DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH), 1676182080Srnoland DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH), 1677182080Srnoland DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH), 1678182080Srnoland DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH), 1679182080Srnoland DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH), 1680182080Srnoland DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1681182080Srnoland DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH), 1682145132Sanholt}; 1683145132Sanholt 1684145132Sanholtint r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls); 1685