1 /* mach64_drv.h -- Private header for mach64 driver -*- linux-c -*- 2 * Created: Fri Nov 24 22:07:58 2000 by gareth (at) valinux.com 3 */ 4 /* 5 * Copyright 2000 Gareth Hughes 6 * Copyright 2002 Frank C. Earl 7 * Copyright 2002-2003 Leif Delgass 8 * All Rights Reserved. 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a 11 * copy of this software and associated documentation files (the "Software"), 12 * to deal in the Software without restriction, including without limitation 13 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 * and/or sell copies of the Software, and to permit persons to whom the 15 * Software is furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice (including the next 18 * paragraph) shall be included in all copies or substantial portions of the 19 * Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 25 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 * 28 * Authors: 29 * Gareth Hughes <gareth (at) valinux.com> 30 * Frank C. Earl <fearl (at) airmail.net> 31 * Leif Delgass <ldelgass (at) retinalburn.net> 32 * Jos Fonseca <j_r_fonseca (at) yahoo.co.uk> 33 */ 34 35 #ifndef __MACH64_DRV_H__ 36 #define __MACH64_DRV_H__ 37 38 /* General customization: 39 */ 40 41 #define DRIVER_AUTHOR "Gareth Hughes, Leif Delgass, Jos Fonseca" 42 43 #define DRIVER_NAME "mach64" 44 #define DRIVER_DESC "DRM module for the ATI Rage Pro" 45 #define DRIVER_DATE "20060718" 46 47 #define DRIVER_MAJOR 2 48 #define DRIVER_MINOR 0 49 #define DRIVER_PATCHLEVEL 0 50 51 /* FIXME: remove these when not needed */ 52 /* Development driver options */ 53 #define MACH64_EXTRA_CHECKING 0 /* Extra sanity checks for DMA/freelist management */ 54 #define MACH64_VERBOSE 0 /* Verbose debugging output */ 55 56 typedef struct drm_mach64_freelist { 57 struct list_head list; /* List pointers for free_list, placeholders, or pending list */ 58 struct drm_buf *buf; /* Pointer to the buffer */ 59 int discard; /* This flag is set when we're done (re)using a buffer */ 60 u32 ring_ofs; /* dword offset in ring of last descriptor for this buffer */ 61 } drm_mach64_freelist_t; 62 63 typedef struct drm_mach64_descriptor_ring { 64 void *start; /* write pointer (cpu address) to start of descriptor ring */ 65 u32 start_addr; /* bus address of beginning of descriptor ring */ 66 int size; /* size of ring in bytes */ 67 68 u32 head_addr; /* bus address of descriptor ring head */ 69 u32 head; /* dword offset of descriptor ring head */ 70 u32 tail; /* dword offset of descriptor ring tail */ 71 u32 tail_mask; /* mask used to wrap ring */ 72 int space; /* number of free bytes in ring */ 73 } drm_mach64_descriptor_ring_t; 74 75 typedef struct drm_mach64_private { 76 drm_mach64_sarea_t *sarea_priv; 77 78 int is_pci; 79 drm_mach64_dma_mode_t driver_mode; /* Async DMA, sync DMA, or MMIO */ 80 81 int usec_timeout; /* Timeout for the wait functions */ 82 83 drm_mach64_descriptor_ring_t ring; /* DMA descriptor table (ring buffer) */ 84 int ring_running; /* Is bus mastering is enabled */ 85 86 struct list_head free_list; /* Free-list head */ 87 struct list_head placeholders; /* Placeholder list for buffers held by clients */ 88 struct list_head pending; /* Buffers pending completion */ 89 90 u32 frame_ofs[MACH64_MAX_QUEUED_FRAMES]; /* dword ring offsets of most recent frame swaps */ 91 92 unsigned int fb_bpp; 93 unsigned int front_offset, front_pitch; 94 unsigned int back_offset, back_pitch; 95 96 unsigned int depth_bpp; 97 unsigned int depth_offset, depth_pitch; 98 99 atomic_t vbl_received; /**< Number of vblanks received. */ 100 101 u32 front_offset_pitch; 102 u32 back_offset_pitch; 103 u32 depth_offset_pitch; 104 105 drm_local_map_t *sarea; 106 drm_local_map_t *fb; 107 drm_local_map_t *mmio; 108 drm_local_map_t *ring_map; 109 drm_local_map_t *dev_buffers; /* this is a pointer to a structure in dev */ 110 drm_local_map_t *agp_textures; 111 } drm_mach64_private_t; 112 113 extern struct drm_ioctl_desc mach64_ioctls[]; 114 extern int mach64_max_ioctl; 115 116 /* mach64_dma.c */ 117 extern int mach64_dma_init(struct drm_device *dev, void *data, 118 struct drm_file *file_priv); 119 extern int mach64_dma_idle(struct drm_device *dev, void *data, 120 struct drm_file *file_priv); 121 extern int mach64_dma_flush(struct drm_device *dev, void *data, 122 struct drm_file *file_priv); 123 extern int mach64_engine_reset(struct drm_device *dev, void *data, 124 struct drm_file *file_priv); 125 extern int mach64_dma_buffers(struct drm_device *dev, void *data, 126 struct drm_file *file_priv); 127 extern void mach64_driver_lastclose(struct drm_device * dev); 128 129 extern int mach64_init_freelist(struct drm_device * dev); 130 extern void mach64_destroy_freelist(struct drm_device * dev); 131 extern struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv); 132 extern int mach64_freelist_put(drm_mach64_private_t * dev_priv, 133 struct drm_buf * copy_buf); 134 135 extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, 136 int entries); 137 extern int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv); 138 extern int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n); 139 extern int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv); 140 extern int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv); 141 extern void mach64_dump_engine_info(drm_mach64_private_t * dev_priv); 142 extern void mach64_dump_ring_info(drm_mach64_private_t * dev_priv); 143 extern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv); 144 145 extern int mach64_add_buf_to_ring(drm_mach64_private_t *dev_priv, 146 drm_mach64_freelist_t *_entry); 147 extern int mach64_add_hostdata_buf_to_ring(drm_mach64_private_t *dev_priv, 148 drm_mach64_freelist_t *_entry); 149 150 extern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv); 151 extern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv); 152 extern int mach64_do_cleanup_dma(struct drm_device * dev); 153 154 /* mach64_state.c */ 155 extern int mach64_dma_clear(struct drm_device *dev, void *data, 156 struct drm_file *file_priv); 157 extern int mach64_dma_swap(struct drm_device *dev, void *data, 158 struct drm_file *file_priv); 159 extern int mach64_dma_vertex(struct drm_device *dev, void *data, 160 struct drm_file *file_priv); 161 extern int mach64_dma_blit(struct drm_device *dev, void *data, 162 struct drm_file *file_priv); 163 extern int mach64_get_param(struct drm_device *dev, void *data, 164 struct drm_file *file_priv); 165 166 extern int mach64_driver_load(struct drm_device * dev, unsigned long flags); 167 extern u32 mach64_get_vblank_counter(struct drm_device *dev, unsigned int crtc); 168 extern int mach64_enable_vblank(struct drm_device *dev, unsigned int crtc); 169 extern void mach64_disable_vblank(struct drm_device *dev, unsigned int crtc); 170 extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS); 171 extern void mach64_driver_irq_preinstall(struct drm_device *dev); 172 extern int mach64_driver_irq_postinstall(struct drm_device *dev); 173 extern void mach64_driver_irq_uninstall(struct drm_device *dev); 174 175 /* ================================================================ 176 * Registers 177 */ 178 179 #define MACH64_AGP_BASE 0x0148 180 #define MACH64_AGP_CNTL 0x014c 181 #define MACH64_ALPHA_TST_CNTL 0x0550 182 183 #define MACH64_DSP_CONFIG 0x0420 184 #define MACH64_DSP_ON_OFF 0x0424 185 #define MACH64_EXT_MEM_CNTL 0x04ac 186 #define MACH64_GEN_TEST_CNTL 0x04d0 187 #define MACH64_HW_DEBUG 0x047c 188 #define MACH64_MEM_ADDR_CONFIG 0x0434 189 #define MACH64_MEM_BUF_CNTL 0x042c 190 #define MACH64_MEM_CNTL 0x04b0 191 192 #define MACH64_BM_ADDR 0x0648 193 #define MACH64_BM_COMMAND 0x0188 194 #define MACH64_BM_DATA 0x0648 195 #define MACH64_BM_FRAME_BUF_OFFSET 0x0180 196 #define MACH64_BM_GUI_TABLE 0x01b8 197 #define MACH64_BM_GUI_TABLE_CMD 0x064c 198 # define MACH64_CIRCULAR_BUF_SIZE_16KB (0 << 0) 199 # define MACH64_CIRCULAR_BUF_SIZE_32KB (1 << 0) 200 # define MACH64_CIRCULAR_BUF_SIZE_64KB (2 << 0) 201 # define MACH64_CIRCULAR_BUF_SIZE_128KB (3 << 0) 202 # define MACH64_LAST_DESCRIPTOR (1 << 31) 203 #define MACH64_BM_HOSTDATA 0x0644 204 #define MACH64_BM_STATUS 0x018c 205 #define MACH64_BM_SYSTEM_MEM_ADDR 0x0184 206 #define MACH64_BM_SYSTEM_TABLE 0x01bc 207 #define MACH64_BUS_CNTL 0x04a0 208 # define MACH64_BUS_MSTR_RESET (1 << 1) 209 # define MACH64_BUS_APER_REG_DIS (1 << 4) 210 # define MACH64_BUS_FLUSH_BUF (1 << 2) 211 # define MACH64_BUS_MASTER_DIS (1 << 6) 212 # define MACH64_BUS_EXT_REG_EN (1 << 27) 213 214 #define MACH64_CLR_CMP_CLR 0x0700 215 #define MACH64_CLR_CMP_CNTL 0x0708 216 #define MACH64_CLR_CMP_MASK 0x0704 217 #define MACH64_CONFIG_CHIP_ID 0x04e0 218 #define MACH64_CONFIG_CNTL 0x04dc 219 #define MACH64_CONFIG_STAT0 0x04e4 220 #define MACH64_CONFIG_STAT1 0x0494 221 #define MACH64_CONFIG_STAT2 0x0498 222 #define MACH64_CONTEXT_LOAD_CNTL 0x072c 223 #define MACH64_CONTEXT_MASK 0x0720 224 #define MACH64_COMPOSITE_SHADOW_ID 0x0798 225 #define MACH64_CRC_SIG 0x04e8 226 #define MACH64_CUSTOM_MACRO_CNTL 0x04d4 227 228 #define MACH64_DP_BKGD_CLR 0x06c0 229 #define MACH64_DP_FOG_CLR 0x06c4 230 #define MACH64_DP_FGRD_BKGD_CLR 0x06e0 231 #define MACH64_DP_FRGD_CLR 0x06c4 232 #define MACH64_DP_FGRD_CLR_MIX 0x06dc 233 234 #define MACH64_DP_MIX 0x06d4 235 # define BKGD_MIX_NOT_D (0 << 0) 236 # define BKGD_MIX_ZERO (1 << 0) 237 # define BKGD_MIX_ONE (2 << 0) 238 # define MACH64_BKGD_MIX_D (3 << 0) 239 # define BKGD_MIX_NOT_S (4 << 0) 240 # define BKGD_MIX_D_XOR_S (5 << 0) 241 # define BKGD_MIX_NOT_D_XOR_S (6 << 0) 242 # define MACH64_BKGD_MIX_S (7 << 0) 243 # define BKGD_MIX_NOT_D_OR_NOT_S (8 << 0) 244 # define BKGD_MIX_D_OR_NOT_S (9 << 0) 245 # define BKGD_MIX_NOT_D_OR_S (10 << 0) 246 # define BKGD_MIX_D_OR_S (11 << 0) 247 # define BKGD_MIX_D_AND_S (12 << 0) 248 # define BKGD_MIX_NOT_D_AND_S (13 << 0) 249 # define BKGD_MIX_D_AND_NOT_S (14 << 0) 250 # define BKGD_MIX_NOT_D_AND_NOT_S (15 << 0) 251 # define BKGD_MIX_D_PLUS_S_DIV2 (23 << 0) 252 # define FRGD_MIX_NOT_D (0 << 16) 253 # define FRGD_MIX_ZERO (1 << 16) 254 # define FRGD_MIX_ONE (2 << 16) 255 # define FRGD_MIX_D (3 << 16) 256 # define FRGD_MIX_NOT_S (4 << 16) 257 # define FRGD_MIX_D_XOR_S (5 << 16) 258 # define FRGD_MIX_NOT_D_XOR_S (6 << 16) 259 # define MACH64_FRGD_MIX_S (7 << 16) 260 # define FRGD_MIX_NOT_D_OR_NOT_S (8 << 16) 261 # define FRGD_MIX_D_OR_NOT_S (9 << 16) 262 # define FRGD_MIX_NOT_D_OR_S (10 << 16) 263 # define FRGD_MIX_D_OR_S (11 << 16) 264 # define FRGD_MIX_D_AND_S (12 << 16) 265 # define FRGD_MIX_NOT_D_AND_S (13 << 16) 266 # define FRGD_MIX_D_AND_NOT_S (14 << 16) 267 # define FRGD_MIX_NOT_D_AND_NOT_S (15 << 16) 268 # define FRGD_MIX_D_PLUS_S_DIV2 (23 << 16) 269 270 #define MACH64_DP_PIX_WIDTH 0x06d0 271 # define MACH64_HOST_TRIPLE_ENABLE (1 << 13) 272 # define MACH64_BYTE_ORDER_MSB_TO_LSB (0 << 24) 273 # define MACH64_BYTE_ORDER_LSB_TO_MSB (1 << 24) 274 275 #define MACH64_DP_SRC 0x06d8 276 # define MACH64_BKGD_SRC_BKGD_CLR (0 << 0) 277 # define MACH64_BKGD_SRC_FRGD_CLR (1 << 0) 278 # define MACH64_BKGD_SRC_HOST (2 << 0) 279 # define MACH64_BKGD_SRC_BLIT (3 << 0) 280 # define MACH64_BKGD_SRC_PATTERN (4 << 0) 281 # define MACH64_BKGD_SRC_3D (5 << 0) 282 # define MACH64_FRGD_SRC_BKGD_CLR (0 << 8) 283 # define MACH64_FRGD_SRC_FRGD_CLR (1 << 8) 284 # define MACH64_FRGD_SRC_HOST (2 << 8) 285 # define MACH64_FRGD_SRC_BLIT (3 << 8) 286 # define MACH64_FRGD_SRC_PATTERN (4 << 8) 287 # define MACH64_FRGD_SRC_3D (5 << 8) 288 # define MACH64_MONO_SRC_ONE (0 << 16) 289 # define MACH64_MONO_SRC_PATTERN (1 << 16) 290 # define MACH64_MONO_SRC_HOST (2 << 16) 291 # define MACH64_MONO_SRC_BLIT (3 << 16) 292 293 #define MACH64_DP_WRITE_MASK 0x06c8 294 295 #define MACH64_DST_CNTL 0x0530 296 # define MACH64_DST_X_RIGHT_TO_LEFT (0 << 0) 297 # define MACH64_DST_X_LEFT_TO_RIGHT (1 << 0) 298 # define MACH64_DST_Y_BOTTOM_TO_TOP (0 << 1) 299 # define MACH64_DST_Y_TOP_TO_BOTTOM (1 << 1) 300 # define MACH64_DST_X_MAJOR (0 << 2) 301 # define MACH64_DST_Y_MAJOR (1 << 2) 302 # define MACH64_DST_X_TILE (1 << 3) 303 # define MACH64_DST_Y_TILE (1 << 4) 304 # define MACH64_DST_LAST_PEL (1 << 5) 305 # define MACH64_DST_POLYGON_ENABLE (1 << 6) 306 # define MACH64_DST_24_ROTATION_ENABLE (1 << 7) 307 308 #define MACH64_DST_HEIGHT_WIDTH 0x0518 309 #define MACH64_DST_OFF_PITCH 0x0500 310 #define MACH64_DST_WIDTH_HEIGHT 0x06ec 311 #define MACH64_DST_X_Y 0x06e8 312 #define MACH64_DST_Y_X 0x050c 313 314 #define MACH64_FIFO_STAT 0x0710 315 # define MACH64_FIFO_SLOT_MASK 0x0000ffff 316 # define MACH64_FIFO_ERR (1 << 31) 317 318 #define MACH64_GEN_TEST_CNTL 0x04d0 319 # define MACH64_GUI_ENGINE_ENABLE (1 << 8) 320 #define MACH64_GUI_CMDFIFO_DEBUG 0x0170 321 #define MACH64_GUI_CMDFIFO_DATA 0x0174 322 #define MACH64_GUI_CNTL 0x0178 323 # define MACH64_CMDFIFO_SIZE_MASK 0x00000003ul 324 # define MACH64_CMDFIFO_SIZE_192 0x00000000ul 325 # define MACH64_CMDFIFO_SIZE_128 0x00000001ul 326 # define MACH64_CMDFIFO_SIZE_64 0x00000002ul 327 #define MACH64_GUI_STAT 0x0738 328 # define MACH64_GUI_ACTIVE (1 << 0) 329 #define MACH64_GUI_TRAJ_CNTL 0x0730 330 331 #define MACH64_HOST_CNTL 0x0640 332 #define MACH64_HOST_DATA0 0x0600 333 334 #define MACH64_ONE_OVER_AREA 0x029c 335 #define MACH64_ONE_OVER_AREA_UC 0x0300 336 337 #define MACH64_PAT_REG0 0x0680 338 #define MACH64_PAT_REG1 0x0684 339 340 #define MACH64_SC_LEFT 0x06a0 341 #define MACH64_SC_RIGHT 0x06a4 342 #define MACH64_SC_LEFT_RIGHT 0x06a8 343 #define MACH64_SC_TOP 0x06ac 344 #define MACH64_SC_BOTTOM 0x06b0 345 #define MACH64_SC_TOP_BOTTOM 0x06b4 346 347 #define MACH64_SCALE_3D_CNTL 0x05fc 348 #define MACH64_SCRATCH_REG0 0x0480 349 #define MACH64_SCRATCH_REG1 0x0484 350 #define MACH64_SECONDARY_TEX_OFF 0x0778 351 #define MACH64_SETUP_CNTL 0x0304 352 #define MACH64_SRC_CNTL 0x05b4 353 # define MACH64_SRC_BM_ENABLE (1 << 8) 354 # define MACH64_SRC_BM_SYNC (1 << 9) 355 # define MACH64_SRC_BM_OP_FRAME_TO_SYSTEM (0 << 10) 356 # define MACH64_SRC_BM_OP_SYSTEM_TO_FRAME (1 << 10) 357 # define MACH64_SRC_BM_OP_REG_TO_SYSTEM (2 << 10) 358 # define MACH64_SRC_BM_OP_SYSTEM_TO_REG (3 << 10) 359 #define MACH64_SRC_HEIGHT1 0x0594 360 #define MACH64_SRC_HEIGHT2 0x05ac 361 #define MACH64_SRC_HEIGHT1_WIDTH1 0x0598 362 #define MACH64_SRC_HEIGHT2_WIDTH2 0x05b0 363 #define MACH64_SRC_OFF_PITCH 0x0580 364 #define MACH64_SRC_WIDTH1 0x0590 365 #define MACH64_SRC_Y_X 0x058c 366 367 #define MACH64_TEX_0_OFF 0x05c0 368 #define MACH64_TEX_CNTL 0x0774 369 #define MACH64_TEX_SIZE_PITCH 0x0770 370 #define MACH64_TIMER_CONFIG 0x0428 371 372 #define MACH64_VERTEX_1_ARGB 0x0254 373 #define MACH64_VERTEX_1_S 0x0240 374 #define MACH64_VERTEX_1_SECONDARY_S 0x0328 375 #define MACH64_VERTEX_1_SECONDARY_T 0x032c 376 #define MACH64_VERTEX_1_SECONDARY_W 0x0330 377 #define MACH64_VERTEX_1_SPEC_ARGB 0x024c 378 #define MACH64_VERTEX_1_T 0x0244 379 #define MACH64_VERTEX_1_W 0x0248 380 #define MACH64_VERTEX_1_X_Y 0x0258 381 #define MACH64_VERTEX_1_Z 0x0250 382 #define MACH64_VERTEX_2_ARGB 0x0274 383 #define MACH64_VERTEX_2_S 0x0260 384 #define MACH64_VERTEX_2_SECONDARY_S 0x0334 385 #define MACH64_VERTEX_2_SECONDARY_T 0x0338 386 #define MACH64_VERTEX_2_SECONDARY_W 0x033c 387 #define MACH64_VERTEX_2_SPEC_ARGB 0x026c 388 #define MACH64_VERTEX_2_T 0x0264 389 #define MACH64_VERTEX_2_W 0x0268 390 #define MACH64_VERTEX_2_X_Y 0x0278 391 #define MACH64_VERTEX_2_Z 0x0270 392 #define MACH64_VERTEX_3_ARGB 0x0294 393 #define MACH64_VERTEX_3_S 0x0280 394 #define MACH64_VERTEX_3_SECONDARY_S 0x02a0 395 #define MACH64_VERTEX_3_SECONDARY_T 0x02a4 396 #define MACH64_VERTEX_3_SECONDARY_W 0x02a8 397 #define MACH64_VERTEX_3_SPEC_ARGB 0x028c 398 #define MACH64_VERTEX_3_T 0x0284 399 #define MACH64_VERTEX_3_W 0x0288 400 #define MACH64_VERTEX_3_X_Y 0x0298 401 #define MACH64_VERTEX_3_Z 0x0290 402 403 #define MACH64_Z_CNTL 0x054c 404 #define MACH64_Z_OFF_PITCH 0x0548 405 406 #define MACH64_CRTC_VLINE_CRNT_VLINE 0x0410 407 # define MACH64_CRTC_VLINE_MASK 0x000007ff 408 # define MACH64_CRTC_CRNT_VLINE_MASK 0x07ff0000 409 #define MACH64_CRTC_OFF_PITCH 0x0414 410 #define MACH64_CRTC_INT_CNTL 0x0418 411 # define MACH64_CRTC_VBLANK (1 << 0) 412 # define MACH64_CRTC_VBLANK_INT_EN (1 << 1) 413 # define MACH64_CRTC_VBLANK_INT (1 << 2) 414 # define MACH64_CRTC_VLINE_INT_EN (1 << 3) 415 # define MACH64_CRTC_VLINE_INT (1 << 4) 416 # define MACH64_CRTC_VLINE_SYNC (1 << 5) /* 0=even, 1=odd */ 417 # define MACH64_CRTC_FRAME (1 << 6) /* 0=even, 1=odd */ 418 # define MACH64_CRTC_SNAPSHOT_INT_EN (1 << 7) 419 # define MACH64_CRTC_SNAPSHOT_INT (1 << 8) 420 # define MACH64_CRTC_I2C_INT_EN (1 << 9) 421 # define MACH64_CRTC_I2C_INT (1 << 10) 422 # define MACH64_CRTC2_VBLANK (1 << 11) /* LT Pro */ 423 # define MACH64_CRTC2_VBLANK_INT_EN (1 << 12) /* LT Pro */ 424 # define MACH64_CRTC2_VBLANK_INT (1 << 13) /* LT Pro */ 425 # define MACH64_CRTC2_VLINE_INT_EN (1 << 14) /* LT Pro */ 426 # define MACH64_CRTC2_VLINE_INT (1 << 15) /* LT Pro */ 427 # define MACH64_CRTC_CAPBUF0_INT_EN (1 << 16) 428 # define MACH64_CRTC_CAPBUF0_INT (1 << 17) 429 # define MACH64_CRTC_CAPBUF1_INT_EN (1 << 18) 430 # define MACH64_CRTC_CAPBUF1_INT (1 << 19) 431 # define MACH64_CRTC_OVERLAY_EOF_INT_EN (1 << 20) 432 # define MACH64_CRTC_OVERLAY_EOF_INT (1 << 21) 433 # define MACH64_CRTC_ONESHOT_CAP_INT_EN (1 << 22) 434 # define MACH64_CRTC_ONESHOT_CAP_INT (1 << 23) 435 # define MACH64_CRTC_BUSMASTER_EOL_INT_EN (1 << 24) 436 # define MACH64_CRTC_BUSMASTER_EOL_INT (1 << 25) 437 # define MACH64_CRTC_GP_INT_EN (1 << 26) 438 # define MACH64_CRTC_GP_INT (1 << 27) 439 # define MACH64_CRTC2_VLINE_SYNC (1 << 28) /* LT Pro */ /* 0=even, 1=odd */ 440 # define MACH64_CRTC_SNAPSHOT2_INT_EN (1 << 29) /* LT Pro */ 441 # define MACH64_CRTC_SNAPSHOT2_INT (1 << 30) /* LT Pro */ 442 # define MACH64_CRTC_VBLANK2_INT (1 << 31) 443 # define MACH64_CRTC_INT_ENS \ 444 ( \ 445 MACH64_CRTC_VBLANK_INT_EN | \ 446 MACH64_CRTC_VLINE_INT_EN | \ 447 MACH64_CRTC_SNAPSHOT_INT_EN | \ 448 MACH64_CRTC_I2C_INT_EN | \ 449 MACH64_CRTC2_VBLANK_INT_EN | \ 450 MACH64_CRTC2_VLINE_INT_EN | \ 451 MACH64_CRTC_CAPBUF0_INT_EN | \ 452 MACH64_CRTC_CAPBUF1_INT_EN | \ 453 MACH64_CRTC_OVERLAY_EOF_INT_EN | \ 454 MACH64_CRTC_ONESHOT_CAP_INT_EN | \ 455 MACH64_CRTC_BUSMASTER_EOL_INT_EN | \ 456 MACH64_CRTC_GP_INT_EN | \ 457 MACH64_CRTC_SNAPSHOT2_INT_EN | \ 458 0 \ 459 ) 460 # define MACH64_CRTC_INT_ACKS \ 461 ( \ 462 MACH64_CRTC_VBLANK_INT | \ 463 MACH64_CRTC_VLINE_INT | \ 464 MACH64_CRTC_SNAPSHOT_INT | \ 465 MACH64_CRTC_I2C_INT | \ 466 MACH64_CRTC2_VBLANK_INT | \ 467 MACH64_CRTC2_VLINE_INT | \ 468 MACH64_CRTC_CAPBUF0_INT | \ 469 MACH64_CRTC_CAPBUF1_INT | \ 470 MACH64_CRTC_OVERLAY_EOF_INT | \ 471 MACH64_CRTC_ONESHOT_CAP_INT | \ 472 MACH64_CRTC_BUSMASTER_EOL_INT | \ 473 MACH64_CRTC_GP_INT | \ 474 MACH64_CRTC_SNAPSHOT2_INT | \ 475 MACH64_CRTC_VBLANK2_INT | \ 476 0 \ 477 ) 478 479 #define MACH64_DATATYPE_CI8 2 480 #define MACH64_DATATYPE_ARGB1555 3 481 #define MACH64_DATATYPE_RGB565 4 482 #define MACH64_DATATYPE_ARGB8888 6 483 #define MACH64_DATATYPE_RGB332 7 484 #define MACH64_DATATYPE_Y8 8 485 #define MACH64_DATATYPE_RGB8 9 486 #define MACH64_DATATYPE_VYUY422 11 487 #define MACH64_DATATYPE_YVYU422 12 488 #define MACH64_DATATYPE_AYUV444 14 489 #define MACH64_DATATYPE_ARGB4444 15 490 491 #define MACH64_READ(reg) DRM_READ32(dev_priv->mmio, (reg) ) 492 #define MACH64_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio, (reg), (val) ) 493 494 #define DWMREG0 0x0400 495 #define DWMREG0_END 0x07ff 496 #define DWMREG1 0x0000 497 #define DWMREG1_END 0x03ff 498 499 #define ISREG0(r) (((r) >= DWMREG0) && ((r) <= DWMREG0_END)) 500 #define DMAREG0(r) (((r) - DWMREG0) >> 2) 501 #define DMAREG1(r) ((((r) - DWMREG1) >> 2 ) | 0x0100) 502 #define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r)) 503 504 #define MMREG0 0x0000 505 #define MMREG0_END 0x00ff 506 507 #define ISMMREG0(r) ((r) <= MMREG0_END) 508 #define MMSELECT0(r) (((r) << 2) + DWMREG0) 509 #define MMSELECT1(r) (((((r) & 0xff) << 2) + DWMREG1)) 510 #define MMSELECT(r) (ISMMREG0(r) ? MMSELECT0(r) : MMSELECT1(r)) 511 512 /* ================================================================ 513 * DMA constants 514 */ 515 516 /* DMA descriptor field indices: 517 * The descriptor fields are loaded into the read-only 518 * BM_* system bus master registers during a bus-master operation 519 */ 520 #define MACH64_DMA_FRAME_BUF_OFFSET 0 /* BM_FRAME_BUF_OFFSET */ 521 #define MACH64_DMA_SYS_MEM_ADDR 1 /* BM_SYSTEM_MEM_ADDR */ 522 #define MACH64_DMA_COMMAND 2 /* BM_COMMAND */ 523 #define MACH64_DMA_RESERVED 3 /* BM_STATUS */ 524 525 /* BM_COMMAND descriptor field flags */ 526 #define MACH64_DMA_HOLD_OFFSET (1<<30) /* Don't increment DMA_FRAME_BUF_OFFSET */ 527 #define MACH64_DMA_EOL (1<<31) /* End of descriptor list flag */ 528 529 #define MACH64_DMA_CHUNKSIZE 0x1000 /* 4kB per DMA descriptor */ 530 #define MACH64_APERTURE_OFFSET 0x7ff800 /* frame-buffer offset for gui-masters */ 531 532 /* ================================================================ 533 * Ring operations 534 * 535 * Since the Mach64 bus master engine requires polling, these functions end 536 * up being called frequently, hence being inline. 537 */ 538 539 static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv) 540 { 541 drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 542 543 DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", 544 ring->head_addr, ring->head, ring->tail, ring->space); 545 546 if (mach64_do_wait_for_idle(dev_priv) < 0) { 547 mach64_do_engine_reset(dev_priv); 548 } 549 550 if (dev_priv->driver_mode != MACH64_MODE_MMIO) { 551 /* enable bus mastering and block 1 registers */ 552 MACH64_WRITE(MACH64_BUS_CNTL, 553 (MACH64_READ(MACH64_BUS_CNTL) & 554 ~MACH64_BUS_MASTER_DIS) 555 | MACH64_BUS_EXT_REG_EN); 556 mach64_do_wait_for_idle(dev_priv); 557 } 558 559 /* reset descriptor table ring head */ 560 MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 561 ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); 562 563 dev_priv->ring_running = 1; 564 } 565 566 static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv, 567 drm_mach64_descriptor_ring_t * ring) 568 { 569 DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", 570 ring->head_addr, ring->head, ring->tail, ring->space); 571 572 /* reset descriptor table ring head */ 573 MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, 574 ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); 575 576 if (dev_priv->driver_mode == MACH64_MODE_MMIO) { 577 mach64_do_dispatch_pseudo_dma(dev_priv); 578 } else { 579 /* enable GUI bus mastering, and sync the bus master to the GUI */ 580 MACH64_WRITE(MACH64_SRC_CNTL, 581 MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | 582 MACH64_SRC_BM_OP_SYSTEM_TO_REG); 583 584 /* kick off the transfer */ 585 MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0); 586 if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) { 587 if ((mach64_do_wait_for_idle(dev_priv)) < 0) { 588 DRM_ERROR("idle failed, resetting engine\n"); 589 mach64_dump_engine_info(dev_priv); 590 mach64_do_engine_reset(dev_priv); 591 return; 592 } 593 mach64_do_release_used_buffers(dev_priv); 594 } 595 } 596 } 597 598 /** 599 * Poll the ring head and make sure the bus master is alive. 600 * 601 * Mach64's bus master engine will stop if there are no more entries to process. 602 * This function polls the engine for the last processed entry and calls 603 * mach64_ring_resume if there is an unprocessed entry. 604 * 605 * Note also that, since we update the ring tail while the bus master engine is 606 * in operation, it is possible that the last tail update was too late to be 607 * processed, and the bus master engine stops at the previous tail position. 608 * Therefore it is important to call this function frequently. 609 */ 610 static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv, 611 drm_mach64_descriptor_ring_t * ring) 612 { 613 DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", 614 ring->head_addr, ring->head, ring->tail, ring->space); 615 616 if (!dev_priv->ring_running) { 617 mach64_ring_start(dev_priv); 618 619 if (ring->head != ring->tail) { 620 mach64_ring_resume(dev_priv, ring); 621 } 622 } else { 623 /* GUI_ACTIVE must be read before BM_GUI_TABLE to 624 * correctly determine the ring head 625 */ 626 int gui_active = 627 MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE; 628 629 ring->head_addr = MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0; 630 631 if (gui_active) { 632 /* If not idle, BM_GUI_TABLE points one descriptor 633 * past the current head 634 */ 635 if (ring->head_addr == ring->start_addr) { 636 ring->head_addr += ring->size; 637 } 638 ring->head_addr -= 4 * sizeof(u32); 639 } 640 641 if (ring->head_addr < ring->start_addr || 642 ring->head_addr >= ring->start_addr + ring->size) { 643 DRM_ERROR("bad ring head address: 0x%08x\n", 644 ring->head_addr); 645 mach64_dump_ring_info(dev_priv); 646 mach64_do_engine_reset(dev_priv); 647 return; 648 } 649 650 ring->head = (ring->head_addr - ring->start_addr) / sizeof(u32); 651 652 if (!gui_active && ring->head != ring->tail) { 653 mach64_ring_resume(dev_priv, ring); 654 } 655 } 656 } 657 658 static __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv) 659 { 660 DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", 661 dev_priv->ring.head_addr, dev_priv->ring.head, 662 dev_priv->ring.tail, dev_priv->ring.space); 663 664 /* restore previous SRC_CNTL to disable busmastering */ 665 mach64_do_wait_for_fifo(dev_priv, 1); 666 MACH64_WRITE(MACH64_SRC_CNTL, 0); 667 668 /* disable busmastering but keep the block 1 registers enabled */ 669 mach64_do_wait_for_idle(dev_priv); 670 MACH64_WRITE(MACH64_BUS_CNTL, MACH64_READ(MACH64_BUS_CNTL) 671 | MACH64_BUS_MASTER_DIS | MACH64_BUS_EXT_REG_EN); 672 673 dev_priv->ring_running = 0; 674 } 675 676 static __inline__ void 677 mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv) 678 { 679 drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 680 681 DRM_DEBUG("\n"); 682 683 mach64_ring_tick(dev_priv, ring); 684 685 ring->space = (ring->head - ring->tail) * sizeof(u32); 686 if (ring->space <= 0) { 687 ring->space += ring->size; 688 } 689 } 690 691 /* ================================================================ 692 * DMA macros 693 * 694 * Mach64's ring buffer doesn't take register writes directly. These 695 * have to be written indirectly in DMA buffers. These macros simplify 696 * the task of setting up a buffer, writing commands to it, and 697 * queuing the buffer in the ring. 698 */ 699 700 #define DMALOCALS_NOOUT \ 701 drm_mach64_freelist_t *_entry = NULL; \ 702 struct drm_buf *_buf = NULL 703 704 #define DMALOCALS \ 705 DMALOCALS_NOOUT; \ 706 u32 *_buf_wptr; int _outcount 707 708 #define GETBUFPTR( __buf ) \ 709 ((dev_priv->is_pci) ? \ 710 ((u32 *)(__buf)->address) : \ 711 ((u32 *)((char *)dev_priv->dev_buffers->handle + (__buf)->offset))) 712 713 #define GETBUFADDR( __buf ) ((u32)(__buf)->bus_address) 714 715 #define GETRINGOFFSET() (_entry->ring_ofs) 716 717 static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t * 718 dev_priv, 719 drm_mach64_freelist_t ** 720 entry, struct drm_buf * buf) 721 { 722 struct list_head *ptr; 723 #if MACH64_EXTRA_CHECKING 724 if (list_empty(&dev_priv->pending)) { 725 DRM_ERROR("Empty pending list in \n"); 726 return -EINVAL; 727 } 728 #endif 729 ptr = dev_priv->pending.prev; 730 *entry = list_entry(ptr, drm_mach64_freelist_t, list); 731 while ((*entry)->buf != buf) { 732 if (ptr == &dev_priv->pending) { 733 return -EFAULT; 734 } 735 ptr = ptr->prev; 736 *entry = list_entry(ptr, drm_mach64_freelist_t, list); 737 } 738 return 0; 739 } 740 741 #define DMASETPTR_NOOUT( _p ) \ 742 _buf = (_p) 743 744 #define DMASETPTR( _p ) \ 745 do { \ 746 DMASETPTR_NOOUT( _p ); \ 747 _buf = (_p); \ 748 _outcount = 0; \ 749 _buf_wptr = GETBUFPTR( _buf ); \ 750 } while(0) 751 752 /* FIXME: use a private set of smaller buffers for state emits, clears, and swaps? */ 753 #define DMAGETPTR( file_priv, dev_priv, n ) \ 754 do { \ 755 if ( MACH64_VERBOSE ) { \ 756 DRM_INFO( "DMAGETPTR( %d )\n", (n) ); \ 757 } \ 758 _buf = mach64_freelist_get( dev_priv ); \ 759 if (_buf == NULL) { \ 760 DRM_ERROR("couldn't get buffer in DMAGETPTR\n"); \ 761 return -EAGAIN; \ 762 } \ 763 if (_buf->pending) { \ 764 DRM_ERROR("pending buf in DMAGETPTR\n"); \ 765 return -EFAULT; \ 766 } \ 767 _buf->file_priv = file_priv; \ 768 _outcount = 0; \ 769 \ 770 _buf_wptr = GETBUFPTR( _buf ); \ 771 } while (0) 772 773 #define DMAOUTREG( reg, val ) \ 774 do { \ 775 if ( MACH64_VERBOSE ) { \ 776 DRM_INFO( " DMAOUTREG( 0x%x = 0x%08x )\n", \ 777 reg, val ); \ 778 } \ 779 _buf_wptr[_outcount++] = cpu_to_le32(DMAREG(reg)); \ 780 _buf_wptr[_outcount++] = cpu_to_le32((val)); \ 781 _buf->used += 8; \ 782 } while (0) 783 784 #define DMAADVANCE( dev_priv, _discard ) \ 785 do { \ 786 struct list_head *_ptr; \ 787 int _ret; \ 788 \ 789 if ( MACH64_VERBOSE ) { \ 790 DRM_INFO( "DMAADVANCE() in \n" ); \ 791 } \ 792 \ 793 if (_buf->used <= 0) { \ 794 DRM_ERROR( "DMAADVANCE(): sending empty buf %d\n", \ 795 _buf->idx ); \ 796 return -EFAULT; \ 797 } \ 798 if (_buf->pending) { \ 799 /* This is a resued buffer, so we need to find it in the pending list */ \ 800 if ((_ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \ 801 DRM_ERROR( "DMAADVANCE(): couldn't find pending buf %d\n", _buf->idx ); \ 802 return _ret; \ 803 } \ 804 if (_entry->discard) { \ 805 DRM_ERROR( "DMAADVANCE(): sending discarded pending buf %d\n", _buf->idx ); \ 806 return -EFAULT; \ 807 } \ 808 } else { \ 809 if (list_empty(&dev_priv->placeholders)) { \ 810 DRM_ERROR( "DMAADVANCE(): empty placeholder list\n"); \ 811 return -EFAULT; \ 812 } \ 813 _ptr = dev_priv->placeholders.next; \ 814 list_del(_ptr); \ 815 _entry = list_entry(_ptr, drm_mach64_freelist_t, list); \ 816 _buf->pending = 1; \ 817 _entry->buf = _buf; \ 818 list_add_tail(_ptr, &dev_priv->pending); \ 819 } \ 820 _entry->discard = (_discard); \ 821 if ((_ret = mach64_add_buf_to_ring( dev_priv, _entry ))) \ 822 return _ret; \ 823 } while (0) 824 825 #define DMADISCARDBUF() \ 826 do { \ 827 if (_entry == NULL) { \ 828 int _ret; \ 829 if ((_ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \ 830 DRM_ERROR( "couldn't find pending buf %d\n", \ 831 _buf->idx ); \ 832 return _ret; \ 833 } \ 834 } \ 835 _entry->discard = 1; \ 836 } while(0) 837 838 #define DMAADVANCEHOSTDATA( dev_priv ) \ 839 do { \ 840 struct list_head *ptr; \ 841 int _ret; \ 842 \ 843 if ( MACH64_VERBOSE ) { \ 844 DRM_INFO( "DMAADVANCEHOSTDATA() in \n" ); \ 845 } \ 846 \ 847 if (_buf->used <= 0) { \ 848 DRM_ERROR( "DMAADVANCEHOSTDATA(): sending empty buf %d\n", _buf->idx ); \ 849 return -EFAULT; \ 850 } \ 851 if (list_empty(&dev_priv->placeholders)) { \ 852 DRM_ERROR( "empty placeholder list in DMAADVANCEHOSTDATA()\n" ); \ 853 return -EFAULT; \ 854 } \ 855 \ 856 ptr = dev_priv->placeholders.next; \ 857 list_del(ptr); \ 858 _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ 859 _entry->buf = _buf; \ 860 _entry->buf->pending = 1; \ 861 list_add_tail(ptr, &dev_priv->pending); \ 862 _entry->discard = 1; \ 863 if ((_ret = mach64_add_hostdata_buf_to_ring( dev_priv, _entry ))) \ 864 return _ret; \ 865 } while (0) 866 867 #endif /* __MACH64_DRV_H__ */ 868