Home | History | Annotate | Line # | Download | only in shared-core
      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