r128_cce.c revision 182080
177957Sbenno/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- 277957Sbenno * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com 377957Sbenno */ 4139825Simp/*- 577957Sbenno * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. 677957Sbenno * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 777957Sbenno * All Rights Reserved. 877957Sbenno * 977957Sbenno * Permission is hereby granted, free of charge, to any person obtaining a 1077957Sbenno * copy of this software and associated documentation files (the "Software"), 1177957Sbenno * to deal in the Software without restriction, including without limitation 1277957Sbenno * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1377957Sbenno * and/or sell copies of the Software, and to permit persons to whom the 1477957Sbenno * Software is furnished to do so, subject to the following conditions: 1577957Sbenno * 1677957Sbenno * The above copyright notice and this permission notice (including the next 1777957Sbenno * paragraph) shall be included in all copies or substantial portions of the 1877957Sbenno * Software. 1977957Sbenno * 2077957Sbenno * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2177957Sbenno * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2277957Sbenno * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2377957Sbenno * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2477957Sbenno * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2577957Sbenno * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2677957Sbenno * DEALINGS IN THE SOFTWARE. 2777957Sbenno * 28139825Simp * Authors: 2977957Sbenno * Gareth Hughes <gareth@valinux.com> 3077957Sbenno */ 3177957Sbenno 3277957Sbenno#include <sys/cdefs.h> 3377957Sbenno__FBSDID("$FreeBSD: head/sys/dev/drm/r128_cce.c 182080 2008-08-23 20:59:12Z rnoland $"); 3477957Sbenno 3577957Sbenno#include "dev/drm/drmP.h" 3677957Sbenno#include "dev/drm/drm.h" 3777957Sbenno#include "dev/drm/r128_drm.h" 3877957Sbenno#include "dev/drm/r128_drv.h" 3977957Sbenno 4077957Sbenno#define R128_FIFO_DEBUG 0 4177957Sbenno 4277957Sbenno/* CCE microcode (from ATI) */ 4377957Sbennostatic u32 r128_cce_microcode[] = { 4477957Sbenno 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, 4577957Sbenno 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, 4677957Sbenno 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1, 4777957Sbenno 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11, 4877957Sbenno 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28, 4977957Sbenno 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, 5077957Sbenno 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, 5177957Sbenno 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, 5277957Sbenno 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071, 5377957Sbenno 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2, 5477957Sbenno 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1, 5577957Sbenno 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1, 5677957Sbenno 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, 5777957Sbenno 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, 5877957Sbenno 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1, 5977957Sbenno 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82, 60198723Snwhitehorn 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729, 6177957Sbenno 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008, 6277957Sbenno 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0, 6377957Sbenno 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, 6477957Sbenno 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, 6577957Sbenno 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0, 6677957Sbenno 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370, 6777957Sbenno 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1, 68291442Snwhitehorn 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793, 69291442Snwhitehorn 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1, 70291442Snwhitehorn 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, 71291442Snwhitehorn 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1, 72277335Snwhitehorn 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1, 73277335Snwhitehorn 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894, 7477957Sbenno 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14, 75178628Smarcel 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1, 76178628Smarcel 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, 77231019Sandreast 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, 78223485Snwhitehorn 409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79278429Snwhitehorn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80278429Snwhitehorn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81178628Smarcel 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82178628Smarcel 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83178628Smarcel 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84172887Sgrehan 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 85172887Sgrehan}; 86172887Sgrehan 87118893Sgrehanstatic int R128_READ_PLL(struct drm_device * dev, int addr) 88118893Sgrehan{ 8977957Sbenno drm_r128_private_t *dev_priv = dev->dev_private; 90231019Sandreast 91209975Snwhitehorn R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); 92209975Snwhitehorn return R128_READ(R128_CLOCK_CNTL_DATA); 93118893Sgrehan} 94209975Snwhitehorn 95209975Snwhitehorn#if R128_FIFO_DEBUG 96209975Snwhitehornstatic void r128_status(drm_r128_private_t * dev_priv) 97209975Snwhitehorn{ 98209975Snwhitehorn printk("GUI_STAT = 0x%08x\n", 99209975Snwhitehorn (unsigned int)R128_READ(R128_GUI_STAT)); 100209975Snwhitehorn printk("PM4_STAT = 0x%08x\n", 101209975Snwhitehorn (unsigned int)R128_READ(R128_PM4_STAT)); 102209975Snwhitehorn printk("PM4_BUFFER_DL_WPTR = 0x%08x\n", 103209975Snwhitehorn (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR)); 104209975Snwhitehorn printk("PM4_BUFFER_DL_RPTR = 0x%08x\n", 105209975Snwhitehorn (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR)); 106209975Snwhitehorn printk("PM4_MICRO_CNTL = 0x%08x\n", 107209975Snwhitehorn (unsigned int)R128_READ(R128_PM4_MICRO_CNTL)); 108209975Snwhitehorn printk("PM4_BUFFER_CNTL = 0x%08x\n", 109209975Snwhitehorn (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL)); 110209975Snwhitehorn} 111209975Snwhitehorn#endif 112118893Sgrehan 11391486Sbenno/* ================================================================ 114209975Snwhitehorn * Engine, FIFO control 11591486Sbenno */ 116209975Snwhitehorn 117209975Snwhitehornstatic int r128_do_pixcache_flush(drm_r128_private_t * dev_priv) 118209975Snwhitehorn{ 119209975Snwhitehorn u32 tmp; 120118893Sgrehan int i; 121223485Snwhitehorn 122198723Snwhitehorn tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL; 123198731Snwhitehorn R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp); 124118893Sgrehan 125209975Snwhitehorn for (i = 0; i < dev_priv->usec_timeout; i++) { 126209975Snwhitehorn if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) { 127198731Snwhitehorn return 0; 128178628Smarcel } 129198731Snwhitehorn DRM_UDELAY(1); 13086066Smp } 131218824Snwhitehorn 132209975Snwhitehorn#if R128_FIFO_DEBUG 133188860Snwhitehorn DRM_ERROR("failed!\n"); 134188860Snwhitehorn#endif 135198731Snwhitehorn return -EBUSY; 136198731Snwhitehorn} 137188860Snwhitehorn 138198731Snwhitehornstatic int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries) 139188860Snwhitehorn{ 140218824Snwhitehorn int i; 141209975Snwhitehorn 142188860Snwhitehorn for (i = 0; i < dev_priv->usec_timeout; i++) { 143188860Snwhitehorn int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; 144118893Sgrehan if (slots >= entries) 145218824Snwhitehorn return 0; 146209975Snwhitehorn DRM_UDELAY(1); 14791486Sbenno } 148234517Snwhitehorn 149209975Snwhitehorn#if R128_FIFO_DEBUG 150178628Smarcel DRM_ERROR("failed!\n"); 151198723Snwhitehorn#endif 152198723Snwhitehorn return -EBUSY; 153277335Snwhitehorn} 154198723Snwhitehorn 155223485Snwhitehornstatic int r128_do_wait_for_idle(drm_r128_private_t * dev_priv) 156209975Snwhitehorn{ 157235013Snwhitehorn int i, ret; 158235013Snwhitehorn 159198723Snwhitehorn ret = r128_do_wait_for_fifo(dev_priv, 64); 160278429Snwhitehorn if (ret) 161278429Snwhitehorn return ret; 162278429Snwhitehorn 163198723Snwhitehorn for (i = 0; i < dev_priv->usec_timeout; i++) { 164278429Snwhitehorn if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) { 165278429Snwhitehorn r128_do_pixcache_flush(dev_priv); 166278429Snwhitehorn return 0; 167278429Snwhitehorn } 168278429Snwhitehorn DRM_UDELAY(1); 169278429Snwhitehorn } 170223485Snwhitehorn 171223485Snwhitehorn#if R128_FIFO_DEBUG 172209975Snwhitehorn DRM_ERROR("failed!\n"); 17377957Sbenno#endif 174223485Snwhitehorn return -EBUSY; 175218824Snwhitehorn} 176209975Snwhitehorn 177183088Smarcel/* ================================================================ 178178628Smarcel * CCE control, initialization 179178628Smarcel */ 180118893Sgrehan 181188860Snwhitehorn/* Load the microcode for the CCE */ 182223485Snwhitehornstatic void r128_cce_load_microcode(drm_r128_private_t * dev_priv) 183218824Snwhitehorn{ 184209975Snwhitehorn int i; 18586066Smp 186188860Snwhitehorn DRM_DEBUG("\n"); 187188860Snwhitehorn 188188860Snwhitehorn r128_do_wait_for_idle(dev_priv); 189188860Snwhitehorn 190188860Snwhitehorn R128_WRITE(R128_PM4_MICROCODE_ADDR, 0); 191223485Snwhitehorn for (i = 0; i < 256; i++) { 192218824Snwhitehorn R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]); 193209975Snwhitehorn R128_WRITE(R128_PM4_MICROCODE_DATAL, 194188860Snwhitehorn r128_cce_microcode[i * 2 + 1]); 19599036Sbenno } 196188860Snwhitehorn} 197209975Snwhitehorn 198118893Sgrehan/* Flush any pending commands to the CCE. This should only be used just 199209975Snwhitehorn * prior to a wait for idle, as it informs the engine that the command 200209975Snwhitehorn * stream is ending. 201209975Snwhitehorn */ 202209975Snwhitehornstatic void r128_do_cce_flush(drm_r128_private_t * dev_priv) 203209975Snwhitehorn{ 204209975Snwhitehorn u32 tmp; 205209975Snwhitehorn 206209975Snwhitehorn tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE; 207209975Snwhitehorn R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp); 208209975Snwhitehorn} 209209975Snwhitehorn 210209975Snwhitehorn/* Wait for the CCE to go idle. 211209975Snwhitehorn */ 212209975Snwhitehornint r128_do_cce_idle(drm_r128_private_t * dev_priv) 213209975Snwhitehorn{ 214209975Snwhitehorn int i; 215209975Snwhitehorn 216209975Snwhitehorn for (i = 0; i < dev_priv->usec_timeout; i++) { 217209975Snwhitehorn if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) { 218209975Snwhitehorn int pm4stat = R128_READ(R128_PM4_STAT); 21984945Smp if (((pm4stat & R128_PM4_FIFOCNT_MASK) >= 220209975Snwhitehorn dev_priv->cce_fifo_size) && 22191486Sbenno !(pm4stat & (R128_PM4_BUSY | 222209975Snwhitehorn R128_PM4_GUI_ACTIVE))) { 223209975Snwhitehorn return r128_do_pixcache_flush(dev_priv); 224209975Snwhitehorn } 225190704Smarcel } 226209975Snwhitehorn DRM_UDELAY(1); 227190704Smarcel } 228209975Snwhitehorn 229190704Smarcel#if R128_FIFO_DEBUG 230209975Snwhitehorn DRM_ERROR("failed!\n"); 23177957Sbenno r128_status(dev_priv); 23277957Sbenno#endif 23377957Sbenno return -EBUSY; 23484945Smp} 23584945Smp 23677957Sbenno/* Start the Concurrent Command Engine. 237231019Sandreast */ 238209975Snwhitehornstatic void r128_do_cce_start(drm_r128_private_t * dev_priv) 239209975Snwhitehorn{ 240209975Snwhitehorn r128_do_wait_for_idle(dev_priv); 241209975Snwhitehorn 242209975Snwhitehorn R128_WRITE(R128_PM4_BUFFER_CNTL, 243209975Snwhitehorn dev_priv->cce_mode | dev_priv->ring.size_l2qw 244209975Snwhitehorn | R128_PM4_BUFFER_CNTL_NOUPDATE); 245209975Snwhitehorn R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */ 246209975Snwhitehorn R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); 247209975Snwhitehorn 248209975Snwhitehorn dev_priv->cce_running = 1; 249209975Snwhitehorn} 250209975Snwhitehorn 251209975Snwhitehorn/* Reset the Concurrent Command Engine. This will not flush any pending 252209975Snwhitehorn * commands, so you must wait for the CCE command stream to complete 253209975Snwhitehorn * before calling this routine. 254209975Snwhitehorn */ 255209975Snwhitehornstatic void r128_do_cce_reset(drm_r128_private_t * dev_priv) 256209975Snwhitehorn{ 257209975Snwhitehorn R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); 258209975Snwhitehorn R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); 25984945Smp dev_priv->ring.tail = 0; 260209975Snwhitehorn} 261209975Snwhitehorn 262288909Sjhibbits/* Stop the Concurrent Command Engine. This will not flush any pending 263288909Sjhibbits * commands, so you must flush the command stream and wait for the CCE 26477957Sbenno * to go idle before calling this routine. 26591467Sbenno */ 26691467Sbennostatic void r128_do_cce_stop(drm_r128_private_t * dev_priv) 26791467Sbenno{ 26891467Sbenno R128_WRITE(R128_PM4_MICRO_CNTL, 0); 26991467Sbenno R128_WRITE(R128_PM4_BUFFER_CNTL, 270230400Sandreast R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE); 271230400Sandreast 272209975Snwhitehorn dev_priv->cce_running = 0; 273209975Snwhitehorn} 274209975Snwhitehorn 275209975Snwhitehorn/* Reset the engine. This will stop the CCE if it is running. 276209975Snwhitehorn */ 277218824Snwhitehornstatic int r128_do_engine_reset(struct drm_device * dev) 278209975Snwhitehorn{ 279209975Snwhitehorn drm_r128_private_t *dev_priv = dev->dev_private; 280132520Sgrehan u32 clock_cntl_index, mclk_cntl, gen_reset_cntl; 281132520Sgrehan 282132520Sgrehan r128_do_pixcache_flush(dev_priv); 28395719Sbenno 284209975Snwhitehorn clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX); 285 mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL); 286 287 R128_WRITE_PLL(R128_MCLK_CNTL, 288 mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP); 289 290 gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL); 291 292 /* Taken from the sample code - do not change */ 293 R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); 294 R128_READ(R128_GEN_RESET_CNTL); 295 R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); 296 R128_READ(R128_GEN_RESET_CNTL); 297 298 R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl); 299 R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index); 300 R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl); 301 302 /* Reset the CCE ring */ 303 r128_do_cce_reset(dev_priv); 304 305 /* The CCE is no longer running after an engine reset */ 306 dev_priv->cce_running = 0; 307 308 /* Reset any pending vertex, indirect buffers */ 309 r128_freelist_reset(dev); 310 311 return 0; 312} 313 314static void r128_cce_init_ring_buffer(struct drm_device * dev, 315 drm_r128_private_t * dev_priv) 316{ 317 u32 ring_start; 318 u32 tmp; 319 320 DRM_DEBUG("\n"); 321 322 /* The manual (p. 2) says this address is in "VM space". This 323 * means it's an offset from the start of AGP space. 324 */ 325#if __OS_HAS_AGP 326 if (!dev_priv->is_pci) 327 ring_start = dev_priv->cce_ring->offset - dev->agp->base; 328 else 329#endif 330 ring_start = dev_priv->cce_ring->offset - 331 (unsigned long)dev->sg->virtual; 332 333 R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET); 334 335 R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); 336 R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); 337 338 /* Set watermark control */ 339 R128_WRITE(R128_PM4_BUFFER_WM_CNTL, 340 ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT) 341 | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT) 342 | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT) 343 | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT)); 344 345 /* Force read. Why? Because it's in the examples... */ 346 R128_READ(R128_PM4_BUFFER_ADDR); 347 348 /* Turn on bus mastering */ 349 tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS; 350 R128_WRITE(R128_BUS_CNTL, tmp); 351} 352 353static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) 354{ 355 drm_r128_private_t *dev_priv; 356 357 DRM_DEBUG("\n"); 358 359 dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); 360 if (dev_priv == NULL) 361 return -ENOMEM; 362 363 memset(dev_priv, 0, sizeof(drm_r128_private_t)); 364 365 dev_priv->is_pci = init->is_pci; 366 367 if (dev_priv->is_pci && !dev->sg) { 368 DRM_ERROR("PCI GART memory not allocated!\n"); 369 dev->dev_private = (void *)dev_priv; 370 r128_do_cleanup_cce(dev); 371 return -EINVAL; 372 } 373 374 dev_priv->usec_timeout = init->usec_timeout; 375 if (dev_priv->usec_timeout < 1 || 376 dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { 377 DRM_DEBUG("TIMEOUT problem!\n"); 378 dev->dev_private = (void *)dev_priv; 379 r128_do_cleanup_cce(dev); 380 return -EINVAL; 381 } 382 383 dev_priv->cce_mode = init->cce_mode; 384 385 /* GH: Simple idle check. 386 */ 387 atomic_set(&dev_priv->idle_count, 0); 388 389 /* We don't support anything other than bus-mastering ring mode, 390 * but the ring can be in either AGP or PCI space for the ring 391 * read pointer. 392 */ 393 if ((init->cce_mode != R128_PM4_192BM) && 394 (init->cce_mode != R128_PM4_128BM_64INDBM) && 395 (init->cce_mode != R128_PM4_64BM_128INDBM) && 396 (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) { 397 DRM_DEBUG("Bad cce_mode!\n"); 398 dev->dev_private = (void *)dev_priv; 399 r128_do_cleanup_cce(dev); 400 return -EINVAL; 401 } 402 403 switch (init->cce_mode) { 404 case R128_PM4_NONPM4: 405 dev_priv->cce_fifo_size = 0; 406 break; 407 case R128_PM4_192PIO: 408 case R128_PM4_192BM: 409 dev_priv->cce_fifo_size = 192; 410 break; 411 case R128_PM4_128PIO_64INDBM: 412 case R128_PM4_128BM_64INDBM: 413 dev_priv->cce_fifo_size = 128; 414 break; 415 case R128_PM4_64PIO_128INDBM: 416 case R128_PM4_64BM_128INDBM: 417 case R128_PM4_64PIO_64VCBM_64INDBM: 418 case R128_PM4_64BM_64VCBM_64INDBM: 419 case R128_PM4_64PIO_64VCPIO_64INDPIO: 420 dev_priv->cce_fifo_size = 64; 421 break; 422 } 423 424 switch (init->fb_bpp) { 425 case 16: 426 dev_priv->color_fmt = R128_DATATYPE_RGB565; 427 break; 428 case 32: 429 default: 430 dev_priv->color_fmt = R128_DATATYPE_ARGB8888; 431 break; 432 } 433 dev_priv->front_offset = init->front_offset; 434 dev_priv->front_pitch = init->front_pitch; 435 dev_priv->back_offset = init->back_offset; 436 dev_priv->back_pitch = init->back_pitch; 437 438 switch (init->depth_bpp) { 439 case 16: 440 dev_priv->depth_fmt = R128_DATATYPE_RGB565; 441 break; 442 case 24: 443 case 32: 444 default: 445 dev_priv->depth_fmt = R128_DATATYPE_ARGB8888; 446 break; 447 } 448 dev_priv->depth_offset = init->depth_offset; 449 dev_priv->depth_pitch = init->depth_pitch; 450 dev_priv->span_offset = init->span_offset; 451 452 dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) | 453 (dev_priv->front_offset >> 5)); 454 dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) | 455 (dev_priv->back_offset >> 5)); 456 dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | 457 (dev_priv->depth_offset >> 5) | 458 R128_DST_TILE); 459 dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | 460 (dev_priv->span_offset >> 5)); 461 462 dev_priv->sarea = drm_getsarea(dev); 463 if (!dev_priv->sarea) { 464 DRM_ERROR("could not find sarea!\n"); 465 dev->dev_private = (void *)dev_priv; 466 r128_do_cleanup_cce(dev); 467 return -EINVAL; 468 } 469 470 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); 471 if (!dev_priv->mmio) { 472 DRM_ERROR("could not find mmio region!\n"); 473 dev->dev_private = (void *)dev_priv; 474 r128_do_cleanup_cce(dev); 475 return -EINVAL; 476 } 477 dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset); 478 if (!dev_priv->cce_ring) { 479 DRM_ERROR("could not find cce ring region!\n"); 480 dev->dev_private = (void *)dev_priv; 481 r128_do_cleanup_cce(dev); 482 return -EINVAL; 483 } 484 dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); 485 if (!dev_priv->ring_rptr) { 486 DRM_ERROR("could not find ring read pointer!\n"); 487 dev->dev_private = (void *)dev_priv; 488 r128_do_cleanup_cce(dev); 489 return -EINVAL; 490 } 491 dev->agp_buffer_token = init->buffers_offset; 492 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); 493 if (!dev->agp_buffer_map) { 494 DRM_ERROR("could not find dma buffer region!\n"); 495 dev->dev_private = (void *)dev_priv; 496 r128_do_cleanup_cce(dev); 497 return -EINVAL; 498 } 499 500 if (!dev_priv->is_pci) { 501 dev_priv->agp_textures = 502 drm_core_findmap(dev, init->agp_textures_offset); 503 if (!dev_priv->agp_textures) { 504 DRM_ERROR("could not find agp texture region!\n"); 505 dev->dev_private = (void *)dev_priv; 506 r128_do_cleanup_cce(dev); 507 return -EINVAL; 508 } 509 } 510 511 dev_priv->sarea_priv = 512 (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle + 513 init->sarea_priv_offset); 514 515#if __OS_HAS_AGP 516 if (!dev_priv->is_pci) { 517 drm_core_ioremap(dev_priv->cce_ring, dev); 518 drm_core_ioremap(dev_priv->ring_rptr, dev); 519 drm_core_ioremap(dev->agp_buffer_map, dev); 520 if (!dev_priv->cce_ring->handle || 521 !dev_priv->ring_rptr->handle || 522 !dev->agp_buffer_map->handle) { 523 DRM_ERROR("Could not ioremap agp regions!\n"); 524 dev->dev_private = (void *)dev_priv; 525 r128_do_cleanup_cce(dev); 526 return -ENOMEM; 527 } 528 } else 529#endif 530 { 531 dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset; 532 dev_priv->ring_rptr->handle = 533 (void *)dev_priv->ring_rptr->offset; 534 dev->agp_buffer_map->handle = 535 (void *)dev->agp_buffer_map->offset; 536 } 537 538#if __OS_HAS_AGP 539 if (!dev_priv->is_pci) 540 dev_priv->cce_buffers_offset = dev->agp->base; 541 else 542#endif 543 dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual; 544 545 dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle; 546 dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle 547 + init->ring_size / sizeof(u32)); 548 dev_priv->ring.size = init->ring_size; 549 dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); 550 551 dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; 552 553 dev_priv->ring.high_mark = 128; 554 555 dev_priv->sarea_priv->last_frame = 0; 556 R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); 557 558 dev_priv->sarea_priv->last_dispatch = 0; 559 R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch); 560 561#if __OS_HAS_AGP 562 if (dev_priv->is_pci) { 563#endif 564 dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); 565 dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; 566 dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; 567 dev_priv->gart_info.addr = NULL; 568 dev_priv->gart_info.bus_addr = 0; 569 dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; 570 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { 571 DRM_ERROR("failed to init PCI GART!\n"); 572 dev->dev_private = (void *)dev_priv; 573 r128_do_cleanup_cce(dev); 574 return -ENOMEM; 575 } 576 R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr); 577#if __OS_HAS_AGP 578 } 579#endif 580 581 r128_cce_init_ring_buffer(dev, dev_priv); 582 r128_cce_load_microcode(dev_priv); 583 584 dev->dev_private = (void *)dev_priv; 585 586 r128_do_engine_reset(dev); 587 588 return 0; 589} 590 591int r128_do_cleanup_cce(struct drm_device * dev) 592{ 593 594 /* Make sure interrupts are disabled here because the uninstall ioctl 595 * may not have been called from userspace and after dev_private 596 * is freed, it's too late. 597 */ 598 if (dev->irq_enabled) 599 drm_irq_uninstall(dev); 600 601 if (dev->dev_private) { 602 drm_r128_private_t *dev_priv = dev->dev_private; 603 604#if __OS_HAS_AGP 605 if (!dev_priv->is_pci) { 606 if (dev_priv->cce_ring != NULL) 607 drm_core_ioremapfree(dev_priv->cce_ring, dev); 608 if (dev_priv->ring_rptr != NULL) 609 drm_core_ioremapfree(dev_priv->ring_rptr, dev); 610 if (dev->agp_buffer_map != NULL) { 611 drm_core_ioremapfree(dev->agp_buffer_map, dev); 612 dev->agp_buffer_map = NULL; 613 } 614 } else 615#endif 616 { 617 if (dev_priv->gart_info.bus_addr) 618 if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) 619 DRM_ERROR("failed to cleanup PCI GART!\n"); 620 } 621 622 drm_free(dev->dev_private, sizeof(drm_r128_private_t), 623 DRM_MEM_DRIVER); 624 dev->dev_private = NULL; 625 } 626 627 return 0; 628} 629 630int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 631{ 632 drm_r128_init_t *init = data; 633 634 DRM_DEBUG("\n"); 635 636 LOCK_TEST_WITH_RETURN(dev, file_priv); 637 638 switch (init->func) { 639 case R128_INIT_CCE: 640 return r128_do_init_cce(dev, init); 641 case R128_CLEANUP_CCE: 642 return r128_do_cleanup_cce(dev); 643 } 644 645 return -EINVAL; 646} 647 648int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv) 649{ 650 drm_r128_private_t *dev_priv = dev->dev_private; 651 DRM_DEBUG("\n"); 652 653 LOCK_TEST_WITH_RETURN(dev, file_priv); 654 655 if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { 656 DRM_DEBUG("while CCE running\n"); 657 return 0; 658 } 659 660 r128_do_cce_start(dev_priv); 661 662 return 0; 663} 664 665/* Stop the CCE. The engine must have been idled before calling this 666 * routine. 667 */ 668int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) 669{ 670 drm_r128_private_t *dev_priv = dev->dev_private; 671 drm_r128_cce_stop_t *stop = data; 672 int ret; 673 DRM_DEBUG("\n"); 674 675 LOCK_TEST_WITH_RETURN(dev, file_priv); 676 677 /* Flush any pending CCE commands. This ensures any outstanding 678 * commands are exectuted by the engine before we turn it off. 679 */ 680 if (stop->flush) { 681 r128_do_cce_flush(dev_priv); 682 } 683 684 /* If we fail to make the engine go idle, we return an error 685 * code so that the DRM ioctl wrapper can try again. 686 */ 687 if (stop->idle) { 688 ret = r128_do_cce_idle(dev_priv); 689 if (ret) 690 return ret; 691 } 692 693 /* Finally, we can turn off the CCE. If the engine isn't idle, 694 * we will get some dropped triangles as they won't be fully 695 * rendered before the CCE is shut down. 696 */ 697 r128_do_cce_stop(dev_priv); 698 699 /* Reset the engine */ 700 r128_do_engine_reset(dev); 701 702 return 0; 703} 704 705/* Just reset the CCE ring. Called as part of an X Server engine reset. 706 */ 707int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) 708{ 709 drm_r128_private_t *dev_priv = dev->dev_private; 710 DRM_DEBUG("\n"); 711 712 LOCK_TEST_WITH_RETURN(dev, file_priv); 713 714 if (!dev_priv) { 715 DRM_DEBUG("called before init done\n"); 716 return -EINVAL; 717 } 718 719 r128_do_cce_reset(dev_priv); 720 721 /* The CCE is no longer running after an engine reset */ 722 dev_priv->cce_running = 0; 723 724 return 0; 725} 726 727int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) 728{ 729 drm_r128_private_t *dev_priv = dev->dev_private; 730 DRM_DEBUG("\n"); 731 732 LOCK_TEST_WITH_RETURN(dev, file_priv); 733 734 if (dev_priv->cce_running) { 735 r128_do_cce_flush(dev_priv); 736 } 737 738 return r128_do_cce_idle(dev_priv); 739} 740 741int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) 742{ 743 DRM_DEBUG("\n"); 744 745 LOCK_TEST_WITH_RETURN(dev, file_priv); 746 747 return r128_do_engine_reset(dev); 748} 749 750int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) 751{ 752 return -EINVAL; 753} 754 755/* ================================================================ 756 * Freelist management 757 */ 758#define R128_BUFFER_USED 0xffffffff 759#define R128_BUFFER_FREE 0 760 761#if 0 762static int r128_freelist_init(struct drm_device * dev) 763{ 764 struct drm_device_dma *dma = dev->dma; 765 drm_r128_private_t *dev_priv = dev->dev_private; 766 struct drm_buf *buf; 767 drm_r128_buf_priv_t *buf_priv; 768 drm_r128_freelist_t *entry; 769 int i; 770 771 dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); 772 if (dev_priv->head == NULL) 773 return -ENOMEM; 774 775 memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t)); 776 dev_priv->head->age = R128_BUFFER_USED; 777 778 for (i = 0; i < dma->buf_count; i++) { 779 buf = dma->buflist[i]; 780 buf_priv = buf->dev_private; 781 782 entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); 783 if (!entry) 784 return -ENOMEM; 785 786 entry->age = R128_BUFFER_FREE; 787 entry->buf = buf; 788 entry->prev = dev_priv->head; 789 entry->next = dev_priv->head->next; 790 if (!entry->next) 791 dev_priv->tail = entry; 792 793 buf_priv->discard = 0; 794 buf_priv->dispatched = 0; 795 buf_priv->list_entry = entry; 796 797 dev_priv->head->next = entry; 798 799 if (dev_priv->head->next) 800 dev_priv->head->next->prev = entry; 801 } 802 803 return 0; 804 805} 806#endif 807 808static struct drm_buf *r128_freelist_get(struct drm_device * dev) 809{ 810 struct drm_device_dma *dma = dev->dma; 811 drm_r128_private_t *dev_priv = dev->dev_private; 812 drm_r128_buf_priv_t *buf_priv; 813 struct drm_buf *buf; 814 int i, t; 815 816 /* FIXME: Optimize -- use freelist code */ 817 818 for (i = 0; i < dma->buf_count; i++) { 819 buf = dma->buflist[i]; 820 buf_priv = buf->dev_private; 821 if (buf->file_priv == 0) 822 return buf; 823 } 824 825 for (t = 0; t < dev_priv->usec_timeout; t++) { 826 u32 done_age = R128_READ(R128_LAST_DISPATCH_REG); 827 828 for (i = 0; i < dma->buf_count; i++) { 829 buf = dma->buflist[i]; 830 buf_priv = buf->dev_private; 831 if (buf->pending && buf_priv->age <= done_age) { 832 /* The buffer has been processed, so it 833 * can now be used. 834 */ 835 buf->pending = 0; 836 return buf; 837 } 838 } 839 DRM_UDELAY(1); 840 } 841 842 DRM_DEBUG("returning NULL!\n"); 843 return NULL; 844} 845 846void r128_freelist_reset(struct drm_device * dev) 847{ 848 struct drm_device_dma *dma = dev->dma; 849 int i; 850 851 for (i = 0; i < dma->buf_count; i++) { 852 struct drm_buf *buf = dma->buflist[i]; 853 drm_r128_buf_priv_t *buf_priv = buf->dev_private; 854 buf_priv->age = 0; 855 } 856} 857 858/* ================================================================ 859 * CCE command submission 860 */ 861 862int r128_wait_ring(drm_r128_private_t * dev_priv, int n) 863{ 864 drm_r128_ring_buffer_t *ring = &dev_priv->ring; 865 int i; 866 867 for (i = 0; i < dev_priv->usec_timeout; i++) { 868 r128_update_ring_snapshot(dev_priv); 869 if (ring->space >= n) 870 return 0; 871 DRM_UDELAY(1); 872 } 873 874 /* FIXME: This is being ignored... */ 875 DRM_ERROR("failed!\n"); 876 return -EBUSY; 877} 878 879static int r128_cce_get_buffers(struct drm_device * dev, 880 struct drm_file *file_priv, 881 struct drm_dma * d) 882{ 883 int i; 884 struct drm_buf *buf; 885 886 for (i = d->granted_count; i < d->request_count; i++) { 887 buf = r128_freelist_get(dev); 888 if (!buf) 889 return -EAGAIN; 890 891 buf->file_priv = file_priv; 892 893 if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, 894 sizeof(buf->idx))) 895 return -EFAULT; 896 if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, 897 sizeof(buf->total))) 898 return -EFAULT; 899 900 d->granted_count++; 901 } 902 return 0; 903} 904 905int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) 906{ 907 struct drm_device_dma *dma = dev->dma; 908 int ret = 0; 909 struct drm_dma *d = data; 910 911 LOCK_TEST_WITH_RETURN(dev, file_priv); 912 913 /* Please don't send us buffers. 914 */ 915 if (d->send_count != 0) { 916 DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", 917 DRM_CURRENTPID, d->send_count); 918 return -EINVAL; 919 } 920 921 /* We'll send you buffers. 922 */ 923 if (d->request_count < 0 || d->request_count > dma->buf_count) { 924 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", 925 DRM_CURRENTPID, d->request_count, dma->buf_count); 926 return -EINVAL; 927 } 928 929 d->granted_count = 0; 930 931 if (d->request_count) { 932 ret = r128_cce_get_buffers(dev, file_priv, d); 933 } 934 935 return ret; 936} 937