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