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