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 (copy_from_user(&x, depth->x, sizeof(x))) 899 return -EFAULT; 900 if (copy_from_user(&y, depth->y, sizeof(y))) 901 return -EFAULT; 902 903 buffer_size = depth->n * sizeof(u32); 904 buffer = memdup_user(depth->buffer, buffer_size); 905 if (IS_ERR(buffer)) 906 return PTR_ERR(buffer); 907 908 mask_size = depth->n; 909 if (depth->mask) { 910 mask = memdup_user(depth->mask, mask_size); 911 if (IS_ERR(mask)) { 912 kfree(buffer); 913 return PTR_ERR(mask); 914 } 915 916 for (i = 0; i < count; i++, x++) { 917 if (mask[i]) { 918 BEGIN_RING(6); 919 920 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 921 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 922 R128_GMC_BRUSH_SOLID_COLOR | 923 (dev_priv->depth_fmt << 8) | 924 R128_GMC_SRC_DATATYPE_COLOR | 925 R128_ROP3_P | 926 R128_GMC_CLR_CMP_CNTL_DIS | 927 R128_GMC_WR_MSK_DIS); 928 929 OUT_RING(dev_priv->depth_pitch_offset_c); 930 OUT_RING(buffer[i]); 931 932 OUT_RING((x << 16) | y); 933 OUT_RING((1 << 16) | 1); 934 935 ADVANCE_RING(); 936 } 937 } 938 939 kfree(mask); 940 } else { 941 for (i = 0; i < count; i++, x++) { 942 BEGIN_RING(6); 943 944 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 945 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 946 R128_GMC_BRUSH_SOLID_COLOR | 947 (dev_priv->depth_fmt << 8) | 948 R128_GMC_SRC_DATATYPE_COLOR | 949 R128_ROP3_P | 950 R128_GMC_CLR_CMP_CNTL_DIS | 951 R128_GMC_WR_MSK_DIS); 952 953 OUT_RING(dev_priv->depth_pitch_offset_c); 954 OUT_RING(buffer[i]); 955 956 OUT_RING((x << 16) | y); 957 OUT_RING((1 << 16) | 1); 958 959 ADVANCE_RING(); 960 } 961 } 962 963 kfree(buffer); 964 965 return 0; 966} 967 968static int r128_cce_dispatch_write_pixels(struct drm_device *dev, 969 drm_r128_depth_t *depth) 970{ 971 drm_r128_private_t *dev_priv = dev->dev_private; 972 int count, *x, *y; 973 u32 *buffer; 974 u8 *mask; 975 int i, xbuf_size, ybuf_size, buffer_size, mask_size; 976 RING_LOCALS; 977 DRM_DEBUG("\n"); 978 979 count = depth->n; 980 if (count > 4096 || count <= 0) 981 return -EMSGSIZE; 982 983 xbuf_size = count * sizeof(*x); 984 ybuf_size = count * sizeof(*y); 985 x = kmalloc(xbuf_size, GFP_KERNEL); 986 if (x == NULL) 987 return -ENOMEM; 988 y = kmalloc(ybuf_size, GFP_KERNEL); 989 if (y == NULL) { 990 kfree(x); 991 return -ENOMEM; 992 } 993 if (copy_from_user(x, depth->x, xbuf_size)) { 994 kfree(x); 995 kfree(y); 996 return -EFAULT; 997 } 998 if (copy_from_user(y, depth->y, xbuf_size)) { 999 kfree(x); 1000 kfree(y); 1001 return -EFAULT; 1002 } 1003 1004 buffer_size = depth->n * sizeof(u32); 1005 buffer = memdup_user(depth->buffer, buffer_size); 1006 if (IS_ERR(buffer)) { 1007 kfree(x); 1008 kfree(y); 1009 return PTR_ERR(buffer); 1010 } 1011 1012 if (depth->mask) { 1013 mask_size = depth->n; 1014 mask = memdup_user(depth->mask, mask_size); 1015 if (IS_ERR(mask)) { 1016 kfree(x); 1017 kfree(y); 1018 kfree(buffer); 1019 return PTR_ERR(mask); 1020 } 1021 1022 for (i = 0; i < count; i++) { 1023 if (mask[i]) { 1024 BEGIN_RING(6); 1025 1026 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 1027 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 1028 R128_GMC_BRUSH_SOLID_COLOR | 1029 (dev_priv->depth_fmt << 8) | 1030 R128_GMC_SRC_DATATYPE_COLOR | 1031 R128_ROP3_P | 1032 R128_GMC_CLR_CMP_CNTL_DIS | 1033 R128_GMC_WR_MSK_DIS); 1034 1035 OUT_RING(dev_priv->depth_pitch_offset_c); 1036 OUT_RING(buffer[i]); 1037 1038 OUT_RING((x[i] << 16) | y[i]); 1039 OUT_RING((1 << 16) | 1); 1040 1041 ADVANCE_RING(); 1042 } 1043 } 1044 1045 kfree(mask); 1046 } else { 1047 for (i = 0; i < count; i++) { 1048 BEGIN_RING(6); 1049 1050 OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); 1051 OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | 1052 R128_GMC_BRUSH_SOLID_COLOR | 1053 (dev_priv->depth_fmt << 8) | 1054 R128_GMC_SRC_DATATYPE_COLOR | 1055 R128_ROP3_P | 1056 R128_GMC_CLR_CMP_CNTL_DIS | 1057 R128_GMC_WR_MSK_DIS); 1058 1059 OUT_RING(dev_priv->depth_pitch_offset_c); 1060 OUT_RING(buffer[i]); 1061 1062 OUT_RING((x[i] << 16) | y[i]); 1063 OUT_RING((1 << 16) | 1); 1064 1065 ADVANCE_RING(); 1066 } 1067 } 1068 1069 kfree(x); 1070 kfree(y); 1071 kfree(buffer); 1072 1073 return 0; 1074} 1075 1076static int r128_cce_dispatch_read_span(struct drm_device *dev, 1077 drm_r128_depth_t *depth) 1078{ 1079 drm_r128_private_t *dev_priv = dev->dev_private; 1080 int count, x, y; 1081 RING_LOCALS; 1082 DRM_DEBUG("\n"); 1083 1084 count = depth->n; 1085 if (count > 4096 || count <= 0) 1086 return -EMSGSIZE; 1087 1088 if (copy_from_user(&x, depth->x, sizeof(x))) 1089 return -EFAULT; 1090 if (copy_from_user(&y, depth->y, sizeof(y))) 1091 return -EFAULT; 1092 1093 BEGIN_RING(7); 1094 1095 OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); 1096 OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | 1097 R128_GMC_DST_PITCH_OFFSET_CNTL | 1098 R128_GMC_BRUSH_NONE | 1099 (dev_priv->depth_fmt << 8) | 1100 R128_GMC_SRC_DATATYPE_COLOR | 1101 R128_ROP3_S | 1102 R128_DP_SRC_SOURCE_MEMORY | 1103 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); 1104 1105 OUT_RING(dev_priv->depth_pitch_offset_c); 1106 OUT_RING(dev_priv->span_pitch_offset_c); 1107 1108 OUT_RING((x << 16) | y); 1109 OUT_RING((0 << 16) | 0); 1110 OUT_RING((count << 16) | 1); 1111 1112 ADVANCE_RING(); 1113 1114 return 0; 1115} 1116 1117static int r128_cce_dispatch_read_pixels(struct drm_device *dev, 1118 drm_r128_depth_t *depth) 1119{ 1120 drm_r128_private_t *dev_priv = dev->dev_private; 1121 int count, *x, *y; 1122 int i, xbuf_size, ybuf_size; 1123 RING_LOCALS; 1124 DRM_DEBUG("\n"); 1125 1126 count = depth->n; 1127 if (count > 4096 || count <= 0) 1128 return -EMSGSIZE; 1129 1130 if (count > dev_priv->depth_pitch) 1131 count = dev_priv->depth_pitch; 1132 1133 xbuf_size = count * sizeof(*x); 1134 ybuf_size = count * sizeof(*y); 1135 x = kmalloc(xbuf_size, GFP_KERNEL); 1136 if (x == NULL) 1137 return -ENOMEM; 1138 y = kmalloc(ybuf_size, GFP_KERNEL); 1139 if (y == NULL) { 1140 kfree(x); 1141 return -ENOMEM; 1142 } 1143 if (copy_from_user(x, depth->x, xbuf_size)) { 1144 kfree(x); 1145 kfree(y); 1146 return -EFAULT; 1147 } 1148 if (copy_from_user(y, depth->y, ybuf_size)) { 1149 kfree(x); 1150 kfree(y); 1151 return -EFAULT; 1152 } 1153 1154 for (i = 0; i < count; i++) { 1155 BEGIN_RING(7); 1156 1157 OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); 1158 OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | 1159 R128_GMC_DST_PITCH_OFFSET_CNTL | 1160 R128_GMC_BRUSH_NONE | 1161 (dev_priv->depth_fmt << 8) | 1162 R128_GMC_SRC_DATATYPE_COLOR | 1163 R128_ROP3_S | 1164 R128_DP_SRC_SOURCE_MEMORY | 1165 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); 1166 1167 OUT_RING(dev_priv->depth_pitch_offset_c); 1168 OUT_RING(dev_priv->span_pitch_offset_c); 1169 1170 OUT_RING((x[i] << 16) | y[i]); 1171 OUT_RING((i << 16) | 0); 1172 OUT_RING((1 << 16) | 1); 1173 1174 ADVANCE_RING(); 1175 } 1176 1177 kfree(x); 1178 kfree(y); 1179 1180 return 0; 1181} 1182 1183/* ================================================================ 1184 * Polygon stipple 1185 */ 1186 1187static void r128_cce_dispatch_stipple(struct drm_device *dev, u32 *stipple) 1188{ 1189 drm_r128_private_t *dev_priv = dev->dev_private; 1190 int i; 1191 RING_LOCALS; 1192 DRM_DEBUG("\n"); 1193 1194 BEGIN_RING(33); 1195 1196 OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31)); 1197 for (i = 0; i < 32; i++) 1198 OUT_RING(stipple[i]); 1199 1200 ADVANCE_RING(); 1201} 1202 1203/* ================================================================ 1204 * IOCTL functions 1205 */ 1206 1207static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) 1208{ 1209 drm_r128_private_t *dev_priv = dev->dev_private; 1210 drm_r128_sarea_t *sarea_priv; 1211 drm_r128_clear_t *clear = data; 1212 DRM_DEBUG("\n"); 1213 1214 LOCK_TEST_WITH_RETURN(dev, file_priv); 1215 1216 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1217 1218 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1219 1220 sarea_priv = dev_priv->sarea_priv; 1221 1222 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) 1223 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; 1224 1225 r128_cce_dispatch_clear(dev, clear); 1226 COMMIT_RING(); 1227 1228 /* Make sure we restore the 3D state next time. 1229 */ 1230 dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; 1231 1232 return 0; 1233} 1234 1235static int r128_do_init_pageflip(struct drm_device *dev) 1236{ 1237 drm_r128_private_t *dev_priv = dev->dev_private; 1238 DRM_DEBUG("\n"); 1239 1240 dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET); 1241 dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL); 1242 1243 R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset); 1244 R128_WRITE(R128_CRTC_OFFSET_CNTL, 1245 dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL); 1246 1247 dev_priv->page_flipping = 1; 1248 dev_priv->current_page = 0; 1249 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; 1250 1251 return 0; 1252} 1253 1254static int r128_do_cleanup_pageflip(struct drm_device *dev) 1255{ 1256 drm_r128_private_t *dev_priv = dev->dev_private; 1257 DRM_DEBUG("\n"); 1258 1259 R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset); 1260 R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl); 1261 1262 if (dev_priv->current_page != 0) { 1263 r128_cce_dispatch_flip(dev); 1264 COMMIT_RING(); 1265 } 1266 1267 dev_priv->page_flipping = 0; 1268 return 0; 1269} 1270 1271/* Swapping and flipping are different operations, need different ioctls. 1272 * They can & should be intermixed to support multiple 3d windows. 1273 */ 1274 1275static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) 1276{ 1277 drm_r128_private_t *dev_priv = dev->dev_private; 1278 DRM_DEBUG("\n"); 1279 1280 LOCK_TEST_WITH_RETURN(dev, file_priv); 1281 1282 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1283 1284 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1285 1286 if (!dev_priv->page_flipping) 1287 r128_do_init_pageflip(dev); 1288 1289 r128_cce_dispatch_flip(dev); 1290 1291 COMMIT_RING(); 1292 return 0; 1293} 1294 1295static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) 1296{ 1297 drm_r128_private_t *dev_priv = dev->dev_private; 1298 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 1299 DRM_DEBUG("\n"); 1300 1301 LOCK_TEST_WITH_RETURN(dev, file_priv); 1302 1303 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1304 1305 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1306 1307 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) 1308 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; 1309 1310 r128_cce_dispatch_swap(dev); 1311 dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | 1312 R128_UPLOAD_MASKS); 1313 1314 COMMIT_RING(); 1315 return 0; 1316} 1317 1318static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) 1319{ 1320 drm_r128_private_t *dev_priv = dev->dev_private; 1321 struct drm_device_dma *dma = dev->dma; 1322 struct drm_buf *buf; 1323 drm_r128_buf_priv_t *buf_priv; 1324 drm_r128_vertex_t *vertex = data; 1325 1326 LOCK_TEST_WITH_RETURN(dev, file_priv); 1327 1328 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1329 1330 DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", 1331 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); 1332 1333 if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { 1334 DRM_ERROR("buffer index %d (of %d max)\n", 1335 vertex->idx, dma->buf_count - 1); 1336 return -EINVAL; 1337 } 1338 if (vertex->prim < 0 || 1339 vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { 1340 DRM_ERROR("buffer prim %d\n", vertex->prim); 1341 return -EINVAL; 1342 } 1343 1344 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1345 VB_AGE_TEST_WITH_RETURN(dev_priv); 1346 1347 buf = dma->buflist[vertex->idx]; 1348 buf_priv = buf->dev_private; 1349 1350 if (buf->file_priv != file_priv) { 1351 DRM_ERROR("process %d using buffer owned by %p\n", 1352 DRM_CURRENTPID, buf->file_priv); 1353 return -EINVAL; 1354 } 1355 if (buf->pending) { 1356 DRM_ERROR("sending pending buffer %d\n", vertex->idx); 1357 return -EINVAL; 1358 } 1359 1360 buf->used = vertex->count; 1361 buf_priv->prim = vertex->prim; 1362 buf_priv->discard = vertex->discard; 1363 1364 r128_cce_dispatch_vertex(dev, buf); 1365 1366 COMMIT_RING(); 1367 return 0; 1368} 1369 1370static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) 1371{ 1372 drm_r128_private_t *dev_priv = dev->dev_private; 1373 struct drm_device_dma *dma = dev->dma; 1374 struct drm_buf *buf; 1375 drm_r128_buf_priv_t *buf_priv; 1376 drm_r128_indices_t *elts = data; 1377 int count; 1378 1379 LOCK_TEST_WITH_RETURN(dev, file_priv); 1380 1381 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1382 1383 DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID, 1384 elts->idx, elts->start, elts->end, elts->discard); 1385 1386 if (elts->idx < 0 || elts->idx >= dma->buf_count) { 1387 DRM_ERROR("buffer index %d (of %d max)\n", 1388 elts->idx, dma->buf_count - 1); 1389 return -EINVAL; 1390 } 1391 if (elts->prim < 0 || 1392 elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { 1393 DRM_ERROR("buffer prim %d\n", elts->prim); 1394 return -EINVAL; 1395 } 1396 1397 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1398 VB_AGE_TEST_WITH_RETURN(dev_priv); 1399 1400 buf = dma->buflist[elts->idx]; 1401 buf_priv = buf->dev_private; 1402 1403 if (buf->file_priv != file_priv) { 1404 DRM_ERROR("process %d using buffer owned by %p\n", 1405 DRM_CURRENTPID, buf->file_priv); 1406 return -EINVAL; 1407 } 1408 if (buf->pending) { 1409 DRM_ERROR("sending pending buffer %d\n", elts->idx); 1410 return -EINVAL; 1411 } 1412 1413 count = (elts->end - elts->start) / sizeof(u16); 1414 elts->start -= R128_INDEX_PRIM_OFFSET; 1415 1416 if (elts->start & 0x7) { 1417 DRM_ERROR("misaligned buffer 0x%x\n", elts->start); 1418 return -EINVAL; 1419 } 1420 if (elts->start < buf->used) { 1421 DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); 1422 return -EINVAL; 1423 } 1424 1425 buf->used = elts->end; 1426 buf_priv->prim = elts->prim; 1427 buf_priv->discard = elts->discard; 1428 1429 r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count); 1430 1431 COMMIT_RING(); 1432 return 0; 1433} 1434 1435static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) 1436{ 1437 struct drm_device_dma *dma = dev->dma; 1438 drm_r128_private_t *dev_priv = dev->dev_private; 1439 drm_r128_blit_t *blit = data; 1440 int ret; 1441 1442 LOCK_TEST_WITH_RETURN(dev, file_priv); 1443 1444 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1445 1446 DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx); 1447 1448 if (blit->idx < 0 || blit->idx >= dma->buf_count) { 1449 DRM_ERROR("buffer index %d (of %d max)\n", 1450 blit->idx, dma->buf_count - 1); 1451 return -EINVAL; 1452 } 1453 1454 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1455 VB_AGE_TEST_WITH_RETURN(dev_priv); 1456 1457 ret = r128_cce_dispatch_blit(dev, file_priv, blit); 1458 1459 COMMIT_RING(); 1460 return ret; 1461} 1462 1463static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) 1464{ 1465 drm_r128_private_t *dev_priv = dev->dev_private; 1466 drm_r128_depth_t *depth = data; 1467 int ret; 1468 1469 LOCK_TEST_WITH_RETURN(dev, file_priv); 1470 1471 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1472 1473 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1474 1475 ret = -EINVAL; 1476 switch (depth->func) { 1477 case R128_WRITE_SPAN: 1478 ret = r128_cce_dispatch_write_span(dev, depth); 1479 break; 1480 case R128_WRITE_PIXELS: 1481 ret = r128_cce_dispatch_write_pixels(dev, depth); 1482 break; 1483 case R128_READ_SPAN: 1484 ret = r128_cce_dispatch_read_span(dev, depth); 1485 break; 1486 case R128_READ_PIXELS: 1487 ret = r128_cce_dispatch_read_pixels(dev, depth); 1488 break; 1489 } 1490 1491 COMMIT_RING(); 1492 return ret; 1493} 1494 1495static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) 1496{ 1497 drm_r128_private_t *dev_priv = dev->dev_private; 1498 drm_r128_stipple_t *stipple = data; 1499 u32 mask[32]; 1500 1501 LOCK_TEST_WITH_RETURN(dev, file_priv); 1502 1503 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1504 1505 if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32))) 1506 return -EFAULT; 1507 1508 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1509 1510 r128_cce_dispatch_stipple(dev, mask); 1511 1512 COMMIT_RING(); 1513 return 0; 1514} 1515 1516static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) 1517{ 1518 drm_r128_private_t *dev_priv = dev->dev_private; 1519 struct drm_device_dma *dma = dev->dma; 1520 struct drm_buf *buf; 1521 drm_r128_buf_priv_t *buf_priv; 1522 drm_r128_indirect_t *indirect = data; 1523#if 0 1524 RING_LOCALS; 1525#endif 1526 1527 LOCK_TEST_WITH_RETURN(dev, file_priv); 1528 1529 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1530 1531 DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", 1532 indirect->idx, indirect->start, indirect->end, 1533 indirect->discard); 1534 1535 if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { 1536 DRM_ERROR("buffer index %d (of %d max)\n", 1537 indirect->idx, dma->buf_count - 1); 1538 return -EINVAL; 1539 } 1540 1541 buf = dma->buflist[indirect->idx]; 1542 buf_priv = buf->dev_private; 1543 1544 if (buf->file_priv != file_priv) { 1545 DRM_ERROR("process %d using buffer owned by %p\n", 1546 DRM_CURRENTPID, buf->file_priv); 1547 return -EINVAL; 1548 } 1549 if (buf->pending) { 1550 DRM_ERROR("sending pending buffer %d\n", indirect->idx); 1551 return -EINVAL; 1552 } 1553 1554 if (indirect->start < buf->used) { 1555 DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", 1556 indirect->start, buf->used); 1557 return -EINVAL; 1558 } 1559 1560 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1561 VB_AGE_TEST_WITH_RETURN(dev_priv); 1562 1563 buf->used = indirect->end; 1564 buf_priv->discard = indirect->discard; 1565 1566#if 0 1567 /* Wait for the 3D stream to idle before the indirect buffer 1568 * containing 2D acceleration commands is processed. 1569 */ 1570 BEGIN_RING(2); 1571 RADEON_WAIT_UNTIL_3D_IDLE(); 1572 ADVANCE_RING(); 1573#endif 1574 1575 /* Dispatch the indirect buffer full of commands from the 1576 * X server. This is insecure and is thus only available to 1577 * privileged clients. 1578 */ 1579 r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end); 1580 1581 COMMIT_RING(); 1582 return 0; 1583} 1584 1585static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) 1586{ 1587 drm_r128_private_t *dev_priv = dev->dev_private; 1588 drm_r128_getparam_t *param = data; 1589 int value; 1590 1591 DEV_INIT_TEST_WITH_RETURN(dev_priv); 1592 1593 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 1594 1595 switch (param->param) { 1596 case R128_PARAM_IRQ_NR: 1597 value = dev->pdev->irq; 1598 break; 1599 default: 1600 return -EINVAL; 1601 } 1602 1603 if (copy_to_user(param->value, &value, sizeof(int))) { 1604 DRM_ERROR("copy_to_user\n"); 1605 return -EFAULT; 1606 } 1607 1608 return 0; 1609} 1610 1611void r128_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) 1612{ 1613 if (dev->dev_private) { 1614 drm_r128_private_t *dev_priv = dev->dev_private; 1615 if (dev_priv->page_flipping) 1616 r128_do_cleanup_pageflip(dev); 1617 } 1618} 1619void r128_driver_lastclose(struct drm_device *dev) 1620{ 1621 r128_do_cleanup_cce(dev); 1622} 1623 1624const struct drm_ioctl_desc r128_ioctls[] = { 1625 DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1626 DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1627 DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1628 DRM_IOCTL_DEF_DRV(R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1629 DRM_IOCTL_DEF_DRV(R128_CCE_IDLE, r128_cce_idle, DRM_AUTH), 1630 DRM_IOCTL_DEF_DRV(R128_RESET, r128_engine_reset, DRM_AUTH), 1631 DRM_IOCTL_DEF_DRV(R128_FULLSCREEN, r128_fullscreen, DRM_AUTH), 1632 DRM_IOCTL_DEF_DRV(R128_SWAP, r128_cce_swap, DRM_AUTH), 1633 DRM_IOCTL_DEF_DRV(R128_FLIP, r128_cce_flip, DRM_AUTH), 1634 DRM_IOCTL_DEF_DRV(R128_CLEAR, r128_cce_clear, DRM_AUTH), 1635 DRM_IOCTL_DEF_DRV(R128_VERTEX, r128_cce_vertex, DRM_AUTH), 1636 DRM_IOCTL_DEF_DRV(R128_INDICES, r128_cce_indices, DRM_AUTH), 1637 DRM_IOCTL_DEF_DRV(R128_BLIT, r128_cce_blit, DRM_AUTH), 1638 DRM_IOCTL_DEF_DRV(R128_DEPTH, r128_cce_depth, DRM_AUTH), 1639 DRM_IOCTL_DEF_DRV(R128_STIPPLE, r128_cce_stipple, DRM_AUTH), 1640 DRM_IOCTL_DEF_DRV(R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1641 DRM_IOCTL_DEF_DRV(R128_GETPARAM, r128_getparam, DRM_AUTH), 1642}; 1643 1644int r128_max_ioctl = ARRAY_SIZE(r128_ioctls); 1645