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