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