1145132Sanholt/* mach64_drv.h -- Private header for mach64 driver -*- linux-c -*-
2145132Sanholt * Created: Fri Nov 24 22:07:58 2000 by gareth@valinux.com
3152909Sanholt */
4152909Sanholt/*-
5145132Sanholt * Copyright 2000 Gareth Hughes
6145132Sanholt * Copyright 2002 Frank C. Earl
7145132Sanholt * Copyright 2002-2003 Leif Delgass
8145132Sanholt * All Rights Reserved.
9145132Sanholt *
10145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a
11145132Sanholt * copy of this software and associated documentation files (the "Software"),
12145132Sanholt * to deal in the Software without restriction, including without limitation
13145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the
15145132Sanholt * Software is furnished to do so, subject to the following conditions:
16145132Sanholt *
17145132Sanholt * The above copyright notice and this permission notice (including the next
18145132Sanholt * paragraph) shall be included in all copies or substantial portions of the
19145132Sanholt * Software.
20145132Sanholt *
21145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24145132Sanholt * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25145132Sanholt * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26145132Sanholt * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27145132Sanholt *
28145132Sanholt * Authors:
29145132Sanholt *    Gareth Hughes <gareth@valinux.com>
30145132Sanholt *    Frank C. Earl <fearl@airmail.net>
31145132Sanholt *    Leif Delgass <ldelgass@retinalburn.net>
32182080Srnoland *    Jos�� Fonseca <j_r_fonseca@yahoo.co.uk>
33145132Sanholt */
34145132Sanholt
35152909Sanholt#include <sys/cdefs.h>
36152909Sanholt__FBSDID("$FreeBSD$");
37152909Sanholt
38145132Sanholt#ifndef __MACH64_DRV_H__
39145132Sanholt#define __MACH64_DRV_H__
40145132Sanholt
41145132Sanholt/* General customization:
42145132Sanholt */
43145132Sanholt
44145132Sanholt#define DRIVER_AUTHOR		"Gareth Hughes, Leif Delgass, Jos�� Fonseca"
45145132Sanholt
46145132Sanholt#define DRIVER_NAME		"mach64"
47145132Sanholt#define DRIVER_DESC		"DRM module for the ATI Rage Pro"
48182080Srnoland#define DRIVER_DATE		"20060718"
49145132Sanholt
50182080Srnoland#define DRIVER_MAJOR		2
51145132Sanholt#define DRIVER_MINOR		0
52145132Sanholt#define DRIVER_PATCHLEVEL	0
53145132Sanholt
54145132Sanholt/* FIXME: remove these when not needed */
55145132Sanholt/* Development driver options */
56145132Sanholt#define MACH64_EXTRA_CHECKING     0	/* Extra sanity checks for DMA/freelist management */
57145132Sanholt#define MACH64_VERBOSE		  0	/* Verbose debugging output */
58145132Sanholt
59145132Sanholttypedef struct drm_mach64_freelist {
60145132Sanholt	struct list_head list;	/* List pointers for free_list, placeholders, or pending list */
61182080Srnoland	struct drm_buf *buf;		/* Pointer to the buffer */
62145132Sanholt	int discard;		/* This flag is set when we're done (re)using a buffer */
63145132Sanholt	u32 ring_ofs;		/* dword offset in ring of last descriptor for this buffer */
64145132Sanholt} drm_mach64_freelist_t;
65145132Sanholt
66145132Sanholttypedef struct drm_mach64_descriptor_ring {
67145132Sanholt	void *start;		/* write pointer (cpu address) to start of descriptor ring */
68145132Sanholt	u32 start_addr;		/* bus address of beginning of descriptor ring */
69145132Sanholt	int size;		/* size of ring in bytes */
70145132Sanholt
71145132Sanholt	u32 head_addr;		/* bus address of descriptor ring head */
72145132Sanholt	u32 head;		/* dword offset of descriptor ring head */
73145132Sanholt	u32 tail;		/* dword offset of descriptor ring tail */
74145132Sanholt	u32 tail_mask;		/* mask used to wrap ring */
75145132Sanholt	int space;		/* number of free bytes in ring */
76145132Sanholt} drm_mach64_descriptor_ring_t;
77145132Sanholt
78145132Sanholttypedef struct drm_mach64_private {
79145132Sanholt	drm_mach64_sarea_t *sarea_priv;
80145132Sanholt
81145132Sanholt	int is_pci;
82145132Sanholt	drm_mach64_dma_mode_t driver_mode;	/* Async DMA, sync DMA, or MMIO */
83145132Sanholt
84145132Sanholt	int usec_timeout;	/* Timeout for the wait functions */
85145132Sanholt
86145132Sanholt	drm_mach64_descriptor_ring_t ring;	/* DMA descriptor table (ring buffer) */
87145132Sanholt	int ring_running;	/* Is bus mastering is enabled */
88145132Sanholt
89145132Sanholt	struct list_head free_list;	/* Free-list head */
90145132Sanholt	struct list_head placeholders;	/* Placeholder list for buffers held by clients */
91145132Sanholt	struct list_head pending;	/* Buffers pending completion */
92145132Sanholt
93145132Sanholt	u32 frame_ofs[MACH64_MAX_QUEUED_FRAMES];	/* dword ring offsets of most recent frame swaps */
94145132Sanholt
95145132Sanholt	unsigned int fb_bpp;
96145132Sanholt	unsigned int front_offset, front_pitch;
97145132Sanholt	unsigned int back_offset, back_pitch;
98145132Sanholt
99145132Sanholt	unsigned int depth_bpp;
100145132Sanholt	unsigned int depth_offset, depth_pitch;
101145132Sanholt
102182080Srnoland	atomic_t vbl_received;          /**< Number of vblanks received. */
103182080Srnoland
104145132Sanholt	u32 front_offset_pitch;
105145132Sanholt	u32 back_offset_pitch;
106145132Sanholt	u32 depth_offset_pitch;
107145132Sanholt
108145132Sanholt	drm_local_map_t *sarea;
109145132Sanholt	drm_local_map_t *fb;
110145132Sanholt	drm_local_map_t *mmio;
111145132Sanholt	drm_local_map_t *ring_map;
112145132Sanholt	drm_local_map_t *dev_buffers;	/* this is a pointer to a structure in dev */
113145132Sanholt	drm_local_map_t *agp_textures;
114145132Sanholt} drm_mach64_private_t;
115145132Sanholt
116182080Srnolandextern struct drm_ioctl_desc mach64_ioctls[];
117152909Sanholtextern int mach64_max_ioctl;
118152909Sanholt
119145132Sanholt				/* mach64_dma.c */
120182080Srnolandextern int mach64_dma_init(struct drm_device *dev, void *data,
121182080Srnoland			   struct drm_file *file_priv);
122182080Srnolandextern int mach64_dma_idle(struct drm_device *dev, void *data,
123182080Srnoland			   struct drm_file *file_priv);
124182080Srnolandextern int mach64_dma_flush(struct drm_device *dev, void *data,
125182080Srnoland			    struct drm_file *file_priv);
126182080Srnolandextern int mach64_engine_reset(struct drm_device *dev, void *data,
127182080Srnoland			       struct drm_file *file_priv);
128182080Srnolandextern int mach64_dma_buffers(struct drm_device *dev, void *data,
129182080Srnoland			      struct drm_file *file_priv);
130182080Srnolandextern void mach64_driver_lastclose(struct drm_device * dev);
131145132Sanholt
132182080Srnolandextern int mach64_init_freelist(struct drm_device * dev);
133182080Srnolandextern void mach64_destroy_freelist(struct drm_device * dev);
134182080Srnolandextern struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv);
135182080Srnolandextern int mach64_freelist_put(drm_mach64_private_t * dev_priv,
136182080Srnoland			       struct drm_buf * copy_buf);
137145132Sanholt
138145132Sanholtextern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv,
139145132Sanholt				   int entries);
140145132Sanholtextern int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv);
141145132Sanholtextern int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n);
142145132Sanholtextern int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv);
143145132Sanholtextern int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv);
144145132Sanholtextern void mach64_dump_engine_info(drm_mach64_private_t * dev_priv);
145145132Sanholtextern void mach64_dump_ring_info(drm_mach64_private_t * dev_priv);
146145132Sanholtextern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv);
147145132Sanholt
148182080Srnolandextern int mach64_add_buf_to_ring(drm_mach64_private_t *dev_priv,
149182080Srnoland                                  drm_mach64_freelist_t *_entry);
150182080Srnolandextern int mach64_add_hostdata_buf_to_ring(drm_mach64_private_t *dev_priv,
151182080Srnoland                                           drm_mach64_freelist_t *_entry);
152182080Srnoland
153145132Sanholtextern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv);
154145132Sanholtextern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv);
155182080Srnolandextern int mach64_do_cleanup_dma(struct drm_device * dev);
156145132Sanholt
157145132Sanholt				/* mach64_state.c */
158182080Srnolandextern int mach64_dma_clear(struct drm_device *dev, void *data,
159182080Srnoland			    struct drm_file *file_priv);
160182080Srnolandextern int mach64_dma_swap(struct drm_device *dev, void *data,
161182080Srnoland			   struct drm_file *file_priv);
162182080Srnolandextern int mach64_dma_vertex(struct drm_device *dev, void *data,
163182080Srnoland			     struct drm_file *file_priv);
164182080Srnolandextern int mach64_dma_blit(struct drm_device *dev, void *data,
165182080Srnoland			   struct drm_file *file_priv);
166182080Srnolandextern int mach64_get_param(struct drm_device *dev, void *data,
167182080Srnoland			    struct drm_file *file_priv);
168145132Sanholt
169189130Srnolandextern int mach64_driver_load(struct drm_device * dev, unsigned long flags);
170182080Srnolandextern u32 mach64_get_vblank_counter(struct drm_device *dev, int crtc);
171182080Srnolandextern int mach64_enable_vblank(struct drm_device *dev, int crtc);
172182080Srnolandextern void mach64_disable_vblank(struct drm_device *dev, int crtc);
173145132Sanholtextern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS);
174182080Srnolandextern void mach64_driver_irq_preinstall(struct drm_device *dev);
175182080Srnolandextern int mach64_driver_irq_postinstall(struct drm_device *dev);
176182080Srnolandextern void mach64_driver_irq_uninstall(struct drm_device *dev);
177145132Sanholt
178145132Sanholt/* ================================================================
179145132Sanholt * Registers
180145132Sanholt */
181145132Sanholt
182145132Sanholt#define MACH64_AGP_BASE				0x0148
183145132Sanholt#define MACH64_AGP_CNTL				0x014c
184145132Sanholt#define MACH64_ALPHA_TST_CNTL			0x0550
185145132Sanholt
186182080Srnoland#define MACH64_DSP_CONFIG			0x0420
187182080Srnoland#define MACH64_DSP_ON_OFF			0x0424
188182080Srnoland#define MACH64_EXT_MEM_CNTL			0x04ac
189182080Srnoland#define MACH64_GEN_TEST_CNTL			0x04d0
190182080Srnoland#define MACH64_HW_DEBUG				0x047c
191182080Srnoland#define MACH64_MEM_ADDR_CONFIG			0x0434
192182080Srnoland#define MACH64_MEM_BUF_CNTL			0x042c
193182080Srnoland#define MACH64_MEM_CNTL				0x04b0
194145132Sanholt
195145132Sanholt#define MACH64_BM_ADDR				0x0648
196145132Sanholt#define MACH64_BM_COMMAND			0x0188
197145132Sanholt#define MACH64_BM_DATA				0x0648
198145132Sanholt#define MACH64_BM_FRAME_BUF_OFFSET		0x0180
199145132Sanholt#define MACH64_BM_GUI_TABLE			0x01b8
200145132Sanholt#define MACH64_BM_GUI_TABLE_CMD			0x064c
201145132Sanholt#	define MACH64_CIRCULAR_BUF_SIZE_16KB		(0 << 0)
202145132Sanholt#	define MACH64_CIRCULAR_BUF_SIZE_32KB		(1 << 0)
203145132Sanholt#	define MACH64_CIRCULAR_BUF_SIZE_64KB		(2 << 0)
204145132Sanholt#	define MACH64_CIRCULAR_BUF_SIZE_128KB		(3 << 0)
205145132Sanholt#	define MACH64_LAST_DESCRIPTOR			(1 << 31)
206145132Sanholt#define MACH64_BM_HOSTDATA			0x0644
207145132Sanholt#define MACH64_BM_STATUS			0x018c
208145132Sanholt#define MACH64_BM_SYSTEM_MEM_ADDR		0x0184
209145132Sanholt#define MACH64_BM_SYSTEM_TABLE			0x01bc
210145132Sanholt#define MACH64_BUS_CNTL				0x04a0
211145132Sanholt#	define MACH64_BUS_MSTR_RESET			(1 << 1)
212145132Sanholt#	define MACH64_BUS_APER_REG_DIS			(1 << 4)
213145132Sanholt#	define MACH64_BUS_FLUSH_BUF			(1 << 2)
214145132Sanholt#	define MACH64_BUS_MASTER_DIS			(1 << 6)
215145132Sanholt#	define MACH64_BUS_EXT_REG_EN			(1 << 27)
216145132Sanholt
217145132Sanholt#define MACH64_CLR_CMP_CLR			0x0700
218145132Sanholt#define MACH64_CLR_CMP_CNTL			0x0708
219145132Sanholt#define MACH64_CLR_CMP_MASK			0x0704
220182080Srnoland#define MACH64_CONFIG_CHIP_ID			0x04e0
221182080Srnoland#define MACH64_CONFIG_CNTL			0x04dc
222182080Srnoland#define MACH64_CONFIG_STAT0			0x04e4
223182080Srnoland#define MACH64_CONFIG_STAT1			0x0494
224182080Srnoland#define MACH64_CONFIG_STAT2			0x0498
225145132Sanholt#define MACH64_CONTEXT_LOAD_CNTL		0x072c
226145132Sanholt#define MACH64_CONTEXT_MASK			0x0720
227145132Sanholt#define MACH64_COMPOSITE_SHADOW_ID		0x0798
228182080Srnoland#define MACH64_CRC_SIG				0x04e8
229182080Srnoland#define MACH64_CUSTOM_MACRO_CNTL		0x04d4
230145132Sanholt
231145132Sanholt#define MACH64_DP_BKGD_CLR			0x06c0
232145132Sanholt#define MACH64_DP_FOG_CLR			0x06c4
233145132Sanholt#define MACH64_DP_FGRD_BKGD_CLR			0x06e0
234145132Sanholt#define MACH64_DP_FRGD_CLR			0x06c4
235145132Sanholt#define MACH64_DP_FGRD_CLR_MIX			0x06dc
236145132Sanholt
237145132Sanholt#define MACH64_DP_MIX				0x06d4
238145132Sanholt#	define BKGD_MIX_NOT_D				(0 << 0)
239145132Sanholt#	define BKGD_MIX_ZERO				(1 << 0)
240145132Sanholt#	define BKGD_MIX_ONE				(2 << 0)
241145132Sanholt#	define MACH64_BKGD_MIX_D			(3 << 0)
242145132Sanholt#	define BKGD_MIX_NOT_S				(4 << 0)
243145132Sanholt#	define BKGD_MIX_D_XOR_S				(5 << 0)
244145132Sanholt#	define BKGD_MIX_NOT_D_XOR_S			(6 << 0)
245145132Sanholt#	define MACH64_BKGD_MIX_S			(7 << 0)
246145132Sanholt#	define BKGD_MIX_NOT_D_OR_NOT_S			(8 << 0)
247145132Sanholt#	define BKGD_MIX_D_OR_NOT_S			(9 << 0)
248145132Sanholt#	define BKGD_MIX_NOT_D_OR_S			(10 << 0)
249145132Sanholt#	define BKGD_MIX_D_OR_S				(11 << 0)
250145132Sanholt#	define BKGD_MIX_D_AND_S				(12 << 0)
251145132Sanholt#	define BKGD_MIX_NOT_D_AND_S			(13 << 0)
252145132Sanholt#	define BKGD_MIX_D_AND_NOT_S			(14 << 0)
253145132Sanholt#	define BKGD_MIX_NOT_D_AND_NOT_S			(15 << 0)
254145132Sanholt#	define BKGD_MIX_D_PLUS_S_DIV2			(23 << 0)
255145132Sanholt#	define FRGD_MIX_NOT_D				(0 << 16)
256145132Sanholt#	define FRGD_MIX_ZERO				(1 << 16)
257145132Sanholt#	define FRGD_MIX_ONE				(2 << 16)
258145132Sanholt#	define FRGD_MIX_D				(3 << 16)
259145132Sanholt#	define FRGD_MIX_NOT_S				(4 << 16)
260145132Sanholt#	define FRGD_MIX_D_XOR_S				(5 << 16)
261145132Sanholt#	define FRGD_MIX_NOT_D_XOR_S			(6 << 16)
262145132Sanholt#	define MACH64_FRGD_MIX_S			(7 << 16)
263145132Sanholt#	define FRGD_MIX_NOT_D_OR_NOT_S			(8 << 16)
264145132Sanholt#	define FRGD_MIX_D_OR_NOT_S			(9 << 16)
265145132Sanholt#	define FRGD_MIX_NOT_D_OR_S			(10 << 16)
266145132Sanholt#	define FRGD_MIX_D_OR_S				(11 << 16)
267145132Sanholt#	define FRGD_MIX_D_AND_S				(12 << 16)
268145132Sanholt#	define FRGD_MIX_NOT_D_AND_S			(13 << 16)
269145132Sanholt#	define FRGD_MIX_D_AND_NOT_S			(14 << 16)
270145132Sanholt#	define FRGD_MIX_NOT_D_AND_NOT_S			(15 << 16)
271145132Sanholt#	define FRGD_MIX_D_PLUS_S_DIV2			(23 << 16)
272145132Sanholt
273145132Sanholt#define MACH64_DP_PIX_WIDTH			0x06d0
274145132Sanholt#	define MACH64_HOST_TRIPLE_ENABLE		(1 << 13)
275145132Sanholt#	define MACH64_BYTE_ORDER_MSB_TO_LSB		(0 << 24)
276145132Sanholt#	define MACH64_BYTE_ORDER_LSB_TO_MSB		(1 << 24)
277145132Sanholt
278145132Sanholt#define MACH64_DP_SRC				0x06d8
279145132Sanholt#	define MACH64_BKGD_SRC_BKGD_CLR			(0 << 0)
280145132Sanholt#	define MACH64_BKGD_SRC_FRGD_CLR			(1 << 0)
281145132Sanholt#	define MACH64_BKGD_SRC_HOST			(2 << 0)
282145132Sanholt#	define MACH64_BKGD_SRC_BLIT			(3 << 0)
283145132Sanholt#	define MACH64_BKGD_SRC_PATTERN			(4 << 0)
284145132Sanholt#	define MACH64_BKGD_SRC_3D			(5 << 0)
285145132Sanholt#	define MACH64_FRGD_SRC_BKGD_CLR			(0 << 8)
286145132Sanholt#	define MACH64_FRGD_SRC_FRGD_CLR			(1 << 8)
287145132Sanholt#	define MACH64_FRGD_SRC_HOST			(2 << 8)
288145132Sanholt#	define MACH64_FRGD_SRC_BLIT			(3 << 8)
289145132Sanholt#	define MACH64_FRGD_SRC_PATTERN			(4 << 8)
290145132Sanholt#	define MACH64_FRGD_SRC_3D			(5 << 8)
291145132Sanholt#	define MACH64_MONO_SRC_ONE			(0 << 16)
292145132Sanholt#	define MACH64_MONO_SRC_PATTERN			(1 << 16)
293145132Sanholt#	define MACH64_MONO_SRC_HOST			(2 << 16)
294145132Sanholt#	define MACH64_MONO_SRC_BLIT			(3 << 16)
295145132Sanholt
296145132Sanholt#define MACH64_DP_WRITE_MASK			0x06c8
297145132Sanholt
298145132Sanholt#define MACH64_DST_CNTL				0x0530
299145132Sanholt#	define MACH64_DST_X_RIGHT_TO_LEFT		(0 << 0)
300145132Sanholt#	define MACH64_DST_X_LEFT_TO_RIGHT		(1 << 0)
301145132Sanholt#	define MACH64_DST_Y_BOTTOM_TO_TOP		(0 << 1)
302145132Sanholt#	define MACH64_DST_Y_TOP_TO_BOTTOM		(1 << 1)
303145132Sanholt#	define MACH64_DST_X_MAJOR			(0 << 2)
304145132Sanholt#	define MACH64_DST_Y_MAJOR			(1 << 2)
305145132Sanholt#	define MACH64_DST_X_TILE			(1 << 3)
306145132Sanholt#	define MACH64_DST_Y_TILE			(1 << 4)
307145132Sanholt#	define MACH64_DST_LAST_PEL			(1 << 5)
308145132Sanholt#	define MACH64_DST_POLYGON_ENABLE		(1 << 6)
309145132Sanholt#	define MACH64_DST_24_ROTATION_ENABLE		(1 << 7)
310145132Sanholt
311145132Sanholt#define MACH64_DST_HEIGHT_WIDTH			0x0518
312145132Sanholt#define MACH64_DST_OFF_PITCH			0x0500
313145132Sanholt#define MACH64_DST_WIDTH_HEIGHT			0x06ec
314145132Sanholt#define MACH64_DST_X_Y				0x06e8
315145132Sanholt#define MACH64_DST_Y_X				0x050c
316145132Sanholt
317145132Sanholt#define MACH64_FIFO_STAT			0x0710
318145132Sanholt#	define MACH64_FIFO_SLOT_MASK			0x0000ffff
319145132Sanholt#	define MACH64_FIFO_ERR				(1 << 31)
320145132Sanholt
321145132Sanholt#define MACH64_GEN_TEST_CNTL			0x04d0
322145132Sanholt#	define MACH64_GUI_ENGINE_ENABLE			(1 << 8)
323145132Sanholt#define MACH64_GUI_CMDFIFO_DEBUG		0x0170
324145132Sanholt#define MACH64_GUI_CMDFIFO_DATA			0x0174
325145132Sanholt#define MACH64_GUI_CNTL				0x0178
326145132Sanholt#       define MACH64_CMDFIFO_SIZE_MASK                 0x00000003ul
327145132Sanholt#       define MACH64_CMDFIFO_SIZE_192                  0x00000000ul
328145132Sanholt#       define MACH64_CMDFIFO_SIZE_128                  0x00000001ul
329145132Sanholt#       define MACH64_CMDFIFO_SIZE_64                   0x00000002ul
330145132Sanholt#define MACH64_GUI_STAT				0x0738
331145132Sanholt#	define MACH64_GUI_ACTIVE			(1 << 0)
332145132Sanholt#define MACH64_GUI_TRAJ_CNTL			0x0730
333145132Sanholt
334145132Sanholt#define MACH64_HOST_CNTL			0x0640
335145132Sanholt#define MACH64_HOST_DATA0			0x0600
336145132Sanholt
337145132Sanholt#define MACH64_ONE_OVER_AREA			0x029c
338145132Sanholt#define MACH64_ONE_OVER_AREA_UC			0x0300
339145132Sanholt
340145132Sanholt#define MACH64_PAT_REG0				0x0680
341145132Sanholt#define MACH64_PAT_REG1				0x0684
342145132Sanholt
343145132Sanholt#define MACH64_SC_LEFT                          0x06a0
344145132Sanholt#define MACH64_SC_RIGHT                         0x06a4
345145132Sanholt#define MACH64_SC_LEFT_RIGHT                    0x06a8
346145132Sanholt#define MACH64_SC_TOP                           0x06ac
347145132Sanholt#define MACH64_SC_BOTTOM                        0x06b0
348145132Sanholt#define MACH64_SC_TOP_BOTTOM                    0x06b4
349145132Sanholt
350145132Sanholt#define MACH64_SCALE_3D_CNTL			0x05fc
351145132Sanholt#define MACH64_SCRATCH_REG0			0x0480
352145132Sanholt#define MACH64_SCRATCH_REG1			0x0484
353145132Sanholt#define MACH64_SECONDARY_TEX_OFF		0x0778
354145132Sanholt#define MACH64_SETUP_CNTL			0x0304
355145132Sanholt#define MACH64_SRC_CNTL				0x05b4
356145132Sanholt#	define MACH64_SRC_BM_ENABLE			(1 << 8)
357145132Sanholt#	define MACH64_SRC_BM_SYNC			(1 << 9)
358145132Sanholt#	define MACH64_SRC_BM_OP_FRAME_TO_SYSTEM		(0 << 10)
359145132Sanholt#	define MACH64_SRC_BM_OP_SYSTEM_TO_FRAME		(1 << 10)
360145132Sanholt#	define MACH64_SRC_BM_OP_REG_TO_SYSTEM		(2 << 10)
361145132Sanholt#	define MACH64_SRC_BM_OP_SYSTEM_TO_REG		(3 << 10)
362145132Sanholt#define MACH64_SRC_HEIGHT1			0x0594
363145132Sanholt#define MACH64_SRC_HEIGHT2			0x05ac
364145132Sanholt#define MACH64_SRC_HEIGHT1_WIDTH1		0x0598
365145132Sanholt#define MACH64_SRC_HEIGHT2_WIDTH2		0x05b0
366145132Sanholt#define MACH64_SRC_OFF_PITCH			0x0580
367145132Sanholt#define MACH64_SRC_WIDTH1			0x0590
368145132Sanholt#define MACH64_SRC_Y_X				0x058c
369145132Sanholt
370145132Sanholt#define MACH64_TEX_0_OFF			0x05c0
371145132Sanholt#define MACH64_TEX_CNTL				0x0774
372145132Sanholt#define MACH64_TEX_SIZE_PITCH			0x0770
373182080Srnoland#define MACH64_TIMER_CONFIG			0x0428
374145132Sanholt
375145132Sanholt#define MACH64_VERTEX_1_ARGB			0x0254
376145132Sanholt#define MACH64_VERTEX_1_S			0x0240
377145132Sanholt#define MACH64_VERTEX_1_SECONDARY_S		0x0328
378145132Sanholt#define MACH64_VERTEX_1_SECONDARY_T		0x032c
379145132Sanholt#define MACH64_VERTEX_1_SECONDARY_W		0x0330
380145132Sanholt#define MACH64_VERTEX_1_SPEC_ARGB		0x024c
381145132Sanholt#define MACH64_VERTEX_1_T			0x0244
382145132Sanholt#define MACH64_VERTEX_1_W			0x0248
383145132Sanholt#define MACH64_VERTEX_1_X_Y			0x0258
384145132Sanholt#define MACH64_VERTEX_1_Z			0x0250
385145132Sanholt#define MACH64_VERTEX_2_ARGB			0x0274
386145132Sanholt#define MACH64_VERTEX_2_S			0x0260
387145132Sanholt#define MACH64_VERTEX_2_SECONDARY_S		0x0334
388145132Sanholt#define MACH64_VERTEX_2_SECONDARY_T		0x0338
389145132Sanholt#define MACH64_VERTEX_2_SECONDARY_W		0x033c
390145132Sanholt#define MACH64_VERTEX_2_SPEC_ARGB		0x026c
391145132Sanholt#define MACH64_VERTEX_2_T			0x0264
392145132Sanholt#define MACH64_VERTEX_2_W			0x0268
393145132Sanholt#define MACH64_VERTEX_2_X_Y			0x0278
394145132Sanholt#define MACH64_VERTEX_2_Z			0x0270
395145132Sanholt#define MACH64_VERTEX_3_ARGB			0x0294
396145132Sanholt#define MACH64_VERTEX_3_S			0x0280
397145132Sanholt#define MACH64_VERTEX_3_SECONDARY_S		0x02a0
398145132Sanholt#define MACH64_VERTEX_3_SECONDARY_T		0x02a4
399145132Sanholt#define MACH64_VERTEX_3_SECONDARY_W		0x02a8
400145132Sanholt#define MACH64_VERTEX_3_SPEC_ARGB		0x028c
401145132Sanholt#define MACH64_VERTEX_3_T			0x0284
402145132Sanholt#define MACH64_VERTEX_3_W			0x0288
403145132Sanholt#define MACH64_VERTEX_3_X_Y			0x0298
404145132Sanholt#define MACH64_VERTEX_3_Z			0x0290
405145132Sanholt
406145132Sanholt#define MACH64_Z_CNTL				0x054c
407145132Sanholt#define MACH64_Z_OFF_PITCH			0x0548
408145132Sanholt
409145132Sanholt#define MACH64_CRTC_VLINE_CRNT_VLINE		0x0410
410145132Sanholt#	define MACH64_CRTC_VLINE_MASK		        0x000007ff
411145132Sanholt#	define MACH64_CRTC_CRNT_VLINE_MASK		0x07ff0000
412145132Sanholt#define MACH64_CRTC_OFF_PITCH			0x0414
413145132Sanholt#define MACH64_CRTC_INT_CNTL			0x0418
414145132Sanholt#	define MACH64_CRTC_VBLANK			(1 << 0)
415145132Sanholt#	define MACH64_CRTC_VBLANK_INT_EN		(1 << 1)
416145132Sanholt#	define MACH64_CRTC_VBLANK_INT			(1 << 2)
417145132Sanholt#	define MACH64_CRTC_VLINE_INT_EN			(1 << 3)
418145132Sanholt#	define MACH64_CRTC_VLINE_INT			(1 << 4)
419145132Sanholt#	define MACH64_CRTC_VLINE_SYNC			(1 << 5)	/* 0=even, 1=odd */
420145132Sanholt#	define MACH64_CRTC_FRAME			(1 << 6)	/* 0=even, 1=odd */
421145132Sanholt#	define MACH64_CRTC_SNAPSHOT_INT_EN		(1 << 7)
422145132Sanholt#	define MACH64_CRTC_SNAPSHOT_INT			(1 << 8)
423145132Sanholt#	define MACH64_CRTC_I2C_INT_EN			(1 << 9)
424145132Sanholt#	define MACH64_CRTC_I2C_INT			(1 << 10)
425145132Sanholt#	define MACH64_CRTC2_VBLANK			(1 << 11)	/* LT Pro */
426145132Sanholt#	define MACH64_CRTC2_VBLANK_INT_EN		(1 << 12)	/* LT Pro */
427145132Sanholt#	define MACH64_CRTC2_VBLANK_INT			(1 << 13)	/* LT Pro */
428145132Sanholt#	define MACH64_CRTC2_VLINE_INT_EN		(1 << 14)	/* LT Pro */
429145132Sanholt#	define MACH64_CRTC2_VLINE_INT			(1 << 15)	/* LT Pro */
430145132Sanholt#	define MACH64_CRTC_CAPBUF0_INT_EN		(1 << 16)
431145132Sanholt#	define MACH64_CRTC_CAPBUF0_INT			(1 << 17)
432145132Sanholt#	define MACH64_CRTC_CAPBUF1_INT_EN		(1 << 18)
433145132Sanholt#	define MACH64_CRTC_CAPBUF1_INT			(1 << 19)
434145132Sanholt#	define MACH64_CRTC_OVERLAY_EOF_INT_EN		(1 << 20)
435145132Sanholt#	define MACH64_CRTC_OVERLAY_EOF_INT		(1 << 21)
436145132Sanholt#	define MACH64_CRTC_ONESHOT_CAP_INT_EN		(1 << 22)
437145132Sanholt#	define MACH64_CRTC_ONESHOT_CAP_INT		(1 << 23)
438145132Sanholt#	define MACH64_CRTC_BUSMASTER_EOL_INT_EN		(1 << 24)
439145132Sanholt#	define MACH64_CRTC_BUSMASTER_EOL_INT		(1 << 25)
440145132Sanholt#	define MACH64_CRTC_GP_INT_EN			(1 << 26)
441145132Sanholt#	define MACH64_CRTC_GP_INT			(1 << 27)
442145132Sanholt#	define MACH64_CRTC2_VLINE_SYNC			(1 << 28) /* LT Pro */	/* 0=even, 1=odd */
443145132Sanholt#	define MACH64_CRTC_SNAPSHOT2_INT_EN		(1 << 29)	/* LT Pro */
444145132Sanholt#	define MACH64_CRTC_SNAPSHOT2_INT		(1 << 30)	/* LT Pro */
445145132Sanholt#	define MACH64_CRTC_VBLANK2_INT			(1 << 31)
446145132Sanholt#	define MACH64_CRTC_INT_ENS				\
447145132Sanholt		(						\
448145132Sanholt			MACH64_CRTC_VBLANK_INT_EN |		\
449145132Sanholt			MACH64_CRTC_VLINE_INT_EN |		\
450145132Sanholt			MACH64_CRTC_SNAPSHOT_INT_EN |		\
451145132Sanholt			MACH64_CRTC_I2C_INT_EN |		\
452145132Sanholt			MACH64_CRTC2_VBLANK_INT_EN |		\
453145132Sanholt			MACH64_CRTC2_VLINE_INT_EN |		\
454145132Sanholt			MACH64_CRTC_CAPBUF0_INT_EN |		\
455145132Sanholt			MACH64_CRTC_CAPBUF1_INT_EN |		\
456145132Sanholt			MACH64_CRTC_OVERLAY_EOF_INT_EN |	\
457145132Sanholt			MACH64_CRTC_ONESHOT_CAP_INT_EN |	\
458145132Sanholt			MACH64_CRTC_BUSMASTER_EOL_INT_EN |	\
459145132Sanholt			MACH64_CRTC_GP_INT_EN |			\
460145132Sanholt			MACH64_CRTC_SNAPSHOT2_INT_EN |		\
461145132Sanholt			0					\
462145132Sanholt		)
463145132Sanholt#	define MACH64_CRTC_INT_ACKS			\
464145132Sanholt		(					\
465145132Sanholt			MACH64_CRTC_VBLANK_INT |	\
466145132Sanholt			MACH64_CRTC_VLINE_INT |		\
467145132Sanholt			MACH64_CRTC_SNAPSHOT_INT |	\
468145132Sanholt			MACH64_CRTC_I2C_INT |		\
469145132Sanholt			MACH64_CRTC2_VBLANK_INT |	\
470145132Sanholt			MACH64_CRTC2_VLINE_INT |	\
471145132Sanholt			MACH64_CRTC_CAPBUF0_INT |	\
472145132Sanholt			MACH64_CRTC_CAPBUF1_INT |	\
473145132Sanholt			MACH64_CRTC_OVERLAY_EOF_INT |	\
474145132Sanholt			MACH64_CRTC_ONESHOT_CAP_INT |	\
475145132Sanholt			MACH64_CRTC_BUSMASTER_EOL_INT |	\
476145132Sanholt			MACH64_CRTC_GP_INT |		\
477145132Sanholt			MACH64_CRTC_SNAPSHOT2_INT |	\
478145132Sanholt			MACH64_CRTC_VBLANK2_INT |	\
479145132Sanholt			0				\
480145132Sanholt		)
481145132Sanholt
482145132Sanholt#define MACH64_DATATYPE_CI8				2
483145132Sanholt#define MACH64_DATATYPE_ARGB1555			3
484145132Sanholt#define MACH64_DATATYPE_RGB565				4
485145132Sanholt#define MACH64_DATATYPE_ARGB8888			6
486145132Sanholt#define MACH64_DATATYPE_RGB332				7
487145132Sanholt#define MACH64_DATATYPE_Y8				8
488145132Sanholt#define MACH64_DATATYPE_RGB8				9
489145132Sanholt#define MACH64_DATATYPE_VYUY422				11
490145132Sanholt#define MACH64_DATATYPE_YVYU422				12
491145132Sanholt#define MACH64_DATATYPE_AYUV444				14
492145132Sanholt#define MACH64_DATATYPE_ARGB4444			15
493145132Sanholt
494145132Sanholt#define MACH64_READ(reg)	DRM_READ32(dev_priv->mmio, (reg) )
495145132Sanholt#define MACH64_WRITE(reg,val)	DRM_WRITE32(dev_priv->mmio, (reg), (val) )
496145132Sanholt
497145132Sanholt#define DWMREG0		0x0400
498145132Sanholt#define DWMREG0_END	0x07ff
499145132Sanholt#define DWMREG1		0x0000
500145132Sanholt#define DWMREG1_END	0x03ff
501145132Sanholt
502145132Sanholt#define ISREG0(r)	(((r) >= DWMREG0) && ((r) <= DWMREG0_END))
503145132Sanholt#define DMAREG0(r)	(((r) - DWMREG0) >> 2)
504145132Sanholt#define DMAREG1(r)	((((r) - DWMREG1) >> 2 ) | 0x0100)
505145132Sanholt#define DMAREG(r)	(ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
506145132Sanholt
507145132Sanholt#define MMREG0		0x0000
508145132Sanholt#define MMREG0_END	0x00ff
509145132Sanholt
510145132Sanholt#define ISMMREG0(r)	(((r) >= MMREG0) && ((r) <= MMREG0_END))
511145132Sanholt#define MMSELECT0(r)	(((r) << 2) + DWMREG0)
512145132Sanholt#define MMSELECT1(r)	(((((r) & 0xff) << 2) + DWMREG1))
513145132Sanholt#define MMSELECT(r)	(ISMMREG0(r) ? MMSELECT0(r) : MMSELECT1(r))
514145132Sanholt
515145132Sanholt/* ================================================================
516145132Sanholt * DMA constants
517145132Sanholt */
518145132Sanholt
519145132Sanholt/* DMA descriptor field indices:
520145132Sanholt * The descriptor fields are loaded into the read-only
521145132Sanholt * BM_* system bus master registers during a bus-master operation
522145132Sanholt */
523145132Sanholt#define MACH64_DMA_FRAME_BUF_OFFSET	0	/* BM_FRAME_BUF_OFFSET */
524145132Sanholt#define MACH64_DMA_SYS_MEM_ADDR		1	/* BM_SYSTEM_MEM_ADDR */
525145132Sanholt#define MACH64_DMA_COMMAND		2	/* BM_COMMAND */
526145132Sanholt#define MACH64_DMA_RESERVED		3	/* BM_STATUS */
527145132Sanholt
528145132Sanholt/* BM_COMMAND descriptor field flags */
529145132Sanholt#define MACH64_DMA_HOLD_OFFSET		(1<<30)	/* Don't increment DMA_FRAME_BUF_OFFSET */
530145132Sanholt#define MACH64_DMA_EOL			(1<<31)	/* End of descriptor list flag */
531145132Sanholt
532145132Sanholt#define MACH64_DMA_CHUNKSIZE	        0x1000	/* 4kB per DMA descriptor */
533145132Sanholt#define MACH64_APERTURE_OFFSET	        0x7ff800	/* frame-buffer offset for gui-masters */
534145132Sanholt
535145132Sanholt/* ================================================================
536182080Srnoland * Ring operations
537182080Srnoland *
538182080Srnoland * Since the Mach64 bus master engine requires polling, these functions end
539182080Srnoland * up being called frequently, hence being inline.
540145132Sanholt */
541145132Sanholt
542145132Sanholtstatic __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv)
543145132Sanholt{
544145132Sanholt	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
545145132Sanholt
546182080Srnoland	DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
547145132Sanholt		  ring->head_addr, ring->head, ring->tail, ring->space);
548145132Sanholt
549145132Sanholt	if (mach64_do_wait_for_idle(dev_priv) < 0) {
550145132Sanholt		mach64_do_engine_reset(dev_priv);
551145132Sanholt	}
552145132Sanholt
553145132Sanholt	if (dev_priv->driver_mode != MACH64_MODE_MMIO) {
554145132Sanholt		/* enable bus mastering and block 1 registers */
555145132Sanholt		MACH64_WRITE(MACH64_BUS_CNTL,
556145132Sanholt			     (MACH64_READ(MACH64_BUS_CNTL) &
557145132Sanholt			      ~MACH64_BUS_MASTER_DIS)
558145132Sanholt			     | MACH64_BUS_EXT_REG_EN);
559145132Sanholt		mach64_do_wait_for_idle(dev_priv);
560145132Sanholt	}
561145132Sanholt
562145132Sanholt	/* reset descriptor table ring head */
563145132Sanholt	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
564145132Sanholt		     ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
565145132Sanholt
566145132Sanholt	dev_priv->ring_running = 1;
567145132Sanholt}
568145132Sanholt
569145132Sanholtstatic __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv,
570145132Sanholt					  drm_mach64_descriptor_ring_t * ring)
571145132Sanholt{
572182080Srnoland	DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
573145132Sanholt		  ring->head_addr, ring->head, ring->tail, ring->space);
574145132Sanholt
575145132Sanholt	/* reset descriptor table ring head */
576145132Sanholt	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
577145132Sanholt		     ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
578145132Sanholt
579145132Sanholt	if (dev_priv->driver_mode == MACH64_MODE_MMIO) {
580145132Sanholt		mach64_do_dispatch_pseudo_dma(dev_priv);
581145132Sanholt	} else {
582145132Sanholt		/* enable GUI bus mastering, and sync the bus master to the GUI */
583145132Sanholt		MACH64_WRITE(MACH64_SRC_CNTL,
584145132Sanholt			     MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC |
585145132Sanholt			     MACH64_SRC_BM_OP_SYSTEM_TO_REG);
586145132Sanholt
587145132Sanholt		/* kick off the transfer */
588145132Sanholt		MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0);
589145132Sanholt		if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) {
590145132Sanholt			if ((mach64_do_wait_for_idle(dev_priv)) < 0) {
591182080Srnoland				DRM_ERROR("idle failed, resetting engine\n");
592145132Sanholt				mach64_dump_engine_info(dev_priv);
593145132Sanholt				mach64_do_engine_reset(dev_priv);
594145132Sanholt				return;
595145132Sanholt			}
596145132Sanholt			mach64_do_release_used_buffers(dev_priv);
597145132Sanholt		}
598145132Sanholt	}
599145132Sanholt}
600145132Sanholt
601182080Srnoland/**
602182080Srnoland * Poll the ring head and make sure the bus master is alive.
603182080Srnoland *
604182080Srnoland * Mach64's bus master engine will stop if there are no more entries to process.
605182080Srnoland * This function polls the engine for the last processed entry and calls
606182080Srnoland * mach64_ring_resume if there is an unprocessed entry.
607182080Srnoland *
608182080Srnoland * Note also that, since we update the ring tail while the bus master engine is
609182080Srnoland * in operation, it is possible that the last tail update was too late to be
610182080Srnoland * processed, and the bus master engine stops at the previous tail position.
611182080Srnoland * Therefore it is important to call this function frequently.
612182080Srnoland */
613145132Sanholtstatic __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv,
614145132Sanholt					drm_mach64_descriptor_ring_t * ring)
615145132Sanholt{
616182080Srnoland	DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
617145132Sanholt		  ring->head_addr, ring->head, ring->tail, ring->space);
618145132Sanholt
619145132Sanholt	if (!dev_priv->ring_running) {
620145132Sanholt		mach64_ring_start(dev_priv);
621145132Sanholt
622145132Sanholt		if (ring->head != ring->tail) {
623145132Sanholt			mach64_ring_resume(dev_priv, ring);
624145132Sanholt		}
625145132Sanholt	} else {
626145132Sanholt		/* GUI_ACTIVE must be read before BM_GUI_TABLE to
627145132Sanholt		 * correctly determine the ring head
628145132Sanholt		 */
629145132Sanholt		int gui_active =
630145132Sanholt		    MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE;
631145132Sanholt
632145132Sanholt		ring->head_addr = MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0;
633145132Sanholt
634145132Sanholt		if (gui_active) {
635145132Sanholt			/* If not idle, BM_GUI_TABLE points one descriptor
636145132Sanholt			 * past the current head
637145132Sanholt			 */
638145132Sanholt			if (ring->head_addr == ring->start_addr) {
639145132Sanholt				ring->head_addr += ring->size;
640145132Sanholt			}
641145132Sanholt			ring->head_addr -= 4 * sizeof(u32);
642145132Sanholt		}
643145132Sanholt
644145132Sanholt		if (ring->head_addr < ring->start_addr ||
645145132Sanholt		    ring->head_addr >= ring->start_addr + ring->size) {
646145132Sanholt			DRM_ERROR("bad ring head address: 0x%08x\n",
647145132Sanholt				  ring->head_addr);
648145132Sanholt			mach64_dump_ring_info(dev_priv);
649145132Sanholt			mach64_do_engine_reset(dev_priv);
650145132Sanholt			return;
651145132Sanholt		}
652145132Sanholt
653145132Sanholt		ring->head = (ring->head_addr - ring->start_addr) / sizeof(u32);
654145132Sanholt
655145132Sanholt		if (!gui_active && ring->head != ring->tail) {
656145132Sanholt			mach64_ring_resume(dev_priv, ring);
657145132Sanholt		}
658145132Sanholt	}
659145132Sanholt}
660145132Sanholt
661145132Sanholtstatic __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv)
662145132Sanholt{
663182080Srnoland	DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
664145132Sanholt		  dev_priv->ring.head_addr, dev_priv->ring.head,
665145132Sanholt		  dev_priv->ring.tail, dev_priv->ring.space);
666145132Sanholt
667145132Sanholt	/* restore previous SRC_CNTL to disable busmastering */
668145132Sanholt	mach64_do_wait_for_fifo(dev_priv, 1);
669145132Sanholt	MACH64_WRITE(MACH64_SRC_CNTL, 0);
670145132Sanholt
671145132Sanholt	/* disable busmastering but keep the block 1 registers enabled */
672145132Sanholt	mach64_do_wait_for_idle(dev_priv);
673145132Sanholt	MACH64_WRITE(MACH64_BUS_CNTL, MACH64_READ(MACH64_BUS_CNTL)
674145132Sanholt		     | MACH64_BUS_MASTER_DIS | MACH64_BUS_EXT_REG_EN);
675145132Sanholt
676145132Sanholt	dev_priv->ring_running = 0;
677145132Sanholt}
678145132Sanholt
679145132Sanholtstatic __inline__ void
680145132Sanholtmach64_update_ring_snapshot(drm_mach64_private_t * dev_priv)
681145132Sanholt{
682145132Sanholt	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
683145132Sanholt
684182080Srnoland	DRM_DEBUG("\n");
685145132Sanholt
686145132Sanholt	mach64_ring_tick(dev_priv, ring);
687145132Sanholt
688145132Sanholt	ring->space = (ring->head - ring->tail) * sizeof(u32);
689145132Sanholt	if (ring->space <= 0) {
690145132Sanholt		ring->space += ring->size;
691145132Sanholt	}
692145132Sanholt}
693145132Sanholt
694145132Sanholt/* ================================================================
695145132Sanholt * DMA macros
696182080Srnoland *
697182080Srnoland * Mach64's ring buffer doesn't take register writes directly. These
698182080Srnoland * have to be written indirectly in DMA buffers. These macros simplify
699182080Srnoland * the task of setting up a buffer, writing commands to it, and
700182080Srnoland * queuing the buffer in the ring.
701145132Sanholt */
702145132Sanholt
703145132Sanholt#define DMALOCALS				\
704145132Sanholt	drm_mach64_freelist_t *_entry = NULL;	\
705182080Srnoland	struct drm_buf *_buf = NULL;		\
706145132Sanholt	u32 *_buf_wptr; int _outcount
707145132Sanholt
708145132Sanholt#define GETBUFPTR( __buf )						\
709182080Srnoland((dev_priv->is_pci) ?							\
710182080Srnoland	((u32 *)(__buf)->address) :					\
711145132Sanholt	((u32 *)((char *)dev_priv->dev_buffers->handle + (__buf)->offset)))
712145132Sanholt
713145132Sanholt#define GETBUFADDR( __buf ) ((u32)(__buf)->bus_address)
714145132Sanholt
715145132Sanholt#define GETRINGOFFSET() (_entry->ring_ofs)
716145132Sanholt
717145132Sanholtstatic __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t *
718145132Sanholt						    dev_priv,
719145132Sanholt						    drm_mach64_freelist_t **
720182080Srnoland						    entry, struct drm_buf * buf)
721145132Sanholt{
722145132Sanholt	struct list_head *ptr;
723145132Sanholt#if MACH64_EXTRA_CHECKING
724145132Sanholt	if (list_empty(&dev_priv->pending)) {
725182080Srnoland		DRM_ERROR("Empty pending list in \n");
726182080Srnoland		return -EINVAL;
727145132Sanholt	}
728145132Sanholt#endif
729145132Sanholt	ptr = dev_priv->pending.prev;
730145132Sanholt	*entry = list_entry(ptr, drm_mach64_freelist_t, list);
731145132Sanholt	while ((*entry)->buf != buf) {
732145132Sanholt		if (ptr == &dev_priv->pending) {
733182080Srnoland			return -EFAULT;
734145132Sanholt		}
735145132Sanholt		ptr = ptr->prev;
736145132Sanholt		*entry = list_entry(ptr, drm_mach64_freelist_t, list);
737145132Sanholt	}
738145132Sanholt	return 0;
739145132Sanholt}
740145132Sanholt
741182080Srnoland#define DMASETPTR( _p )				\
742145132Sanholtdo {						\
743145132Sanholt	_buf = (_p);				\
744145132Sanholt	_outcount = 0;				\
745145132Sanholt	_buf_wptr = GETBUFPTR( _buf );		\
746145132Sanholt} while(0)
747145132Sanholt
748145132Sanholt/* FIXME: use a private set of smaller buffers for state emits, clears, and swaps? */
749182080Srnoland#define DMAGETPTR( file_priv, dev_priv, n )				\
750145132Sanholtdo {									\
751145132Sanholt	if ( MACH64_VERBOSE ) {						\
752182080Srnoland		DRM_INFO( "DMAGETPTR( %d )\n", (n) );			\
753145132Sanholt	}								\
754145132Sanholt	_buf = mach64_freelist_get( dev_priv );				\
755145132Sanholt	if (_buf == NULL) {						\
756182080Srnoland		DRM_ERROR("couldn't get buffer in DMAGETPTR\n");	\
757182080Srnoland		return -EAGAIN;					\
758145132Sanholt	}								\
759145132Sanholt	if (_buf->pending) {						\
760182080Srnoland	        DRM_ERROR("pending buf in DMAGETPTR\n");		\
761182080Srnoland		return -EFAULT;					\
762145132Sanholt	}								\
763182080Srnoland	_buf->file_priv = file_priv;					\
764145132Sanholt	_outcount = 0;							\
765145132Sanholt									\
766145132Sanholt        _buf_wptr = GETBUFPTR( _buf );					\
767145132Sanholt} while (0)
768145132Sanholt
769145132Sanholt#define DMAOUTREG( reg, val )					\
770145132Sanholtdo {								\
771145132Sanholt	if ( MACH64_VERBOSE ) {					\
772145132Sanholt		DRM_INFO( "   DMAOUTREG( 0x%x = 0x%08x )\n",	\
773145132Sanholt			  reg, val );				\
774145132Sanholt	}							\
775145132Sanholt	_buf_wptr[_outcount++] = cpu_to_le32(DMAREG(reg));	\
776145132Sanholt	_buf_wptr[_outcount++] = cpu_to_le32((val));		\
777145132Sanholt	_buf->used += 8;					\
778145132Sanholt} while (0)
779145132Sanholt
780182080Srnoland#define DMAADVANCE( dev_priv, _discard )				\
781182080Srnoland	do {								\
782182080Srnoland		struct list_head *ptr;					\
783182080Srnoland		int ret;						\
784182080Srnoland									\
785182080Srnoland		if ( MACH64_VERBOSE ) {					\
786182080Srnoland			DRM_INFO( "DMAADVANCE() in \n" );		\
787182080Srnoland		}							\
788182080Srnoland									\
789182080Srnoland		if (_buf->used <= 0) {					\
790182080Srnoland			DRM_ERROR( "DMAADVANCE(): sending empty buf %d\n", \
791182080Srnoland				   _buf->idx );				\
792182080Srnoland			return -EFAULT;					\
793182080Srnoland		}							\
794182080Srnoland		if (_buf->pending) {					\
795182080Srnoland			/* This is a resued buffer, so we need to find it in the pending list */ \
796182080Srnoland			if ((ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \
797182080Srnoland				DRM_ERROR( "DMAADVANCE(): couldn't find pending buf %d\n", _buf->idx );	\
798182080Srnoland				return ret;				\
799182080Srnoland			}						\
800182080Srnoland			if (_entry->discard) {				\
801182080Srnoland				DRM_ERROR( "DMAADVANCE(): sending discarded pending buf %d\n", _buf->idx ); \
802182080Srnoland				return -EFAULT;				\
803182080Srnoland			}						\
804182080Srnoland		} else {						\
805182080Srnoland			if (list_empty(&dev_priv->placeholders)) {	\
806182080Srnoland				DRM_ERROR( "DMAADVANCE(): empty placeholder list\n"); \
807182080Srnoland				return -EFAULT;				\
808182080Srnoland			}						\
809182080Srnoland			ptr = dev_priv->placeholders.next;		\
810182080Srnoland			list_del(ptr);					\
811182080Srnoland			_entry = list_entry(ptr, drm_mach64_freelist_t, list); \
812182080Srnoland			_buf->pending = 1;				\
813182080Srnoland			_entry->buf = _buf;				\
814182080Srnoland			list_add_tail(ptr, &dev_priv->pending);		\
815182080Srnoland		}							\
816182080Srnoland		_entry->discard = (_discard);				\
817182080Srnoland		if ((ret = mach64_add_buf_to_ring( dev_priv, _entry ))) \
818182080Srnoland			return ret;					\
819182080Srnoland	} while (0)
820145132Sanholt
821182080Srnoland#define DMADISCARDBUF()							\
822182080Srnoland	do {								\
823182080Srnoland		if (_entry == NULL) {					\
824182080Srnoland			int ret;					\
825182080Srnoland			if ((ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \
826182080Srnoland				DRM_ERROR( "couldn't find pending buf %d\n", \
827182080Srnoland					   _buf->idx );			\
828182080Srnoland				return ret;				\
829182080Srnoland			}						\
830182080Srnoland		}							\
831182080Srnoland		_entry->discard = 1;					\
832182080Srnoland	} while(0)
833145132Sanholt
834182080Srnoland#define DMAADVANCEHOSTDATA( dev_priv )					\
835182080Srnoland	do {								\
836182080Srnoland		struct list_head *ptr;					\
837182080Srnoland		int ret;						\
838182080Srnoland									\
839182080Srnoland		if ( MACH64_VERBOSE ) {					\
840182080Srnoland			DRM_INFO( "DMAADVANCEHOSTDATA() in \n" );	\
841182080Srnoland		}							\
842182080Srnoland									\
843182080Srnoland		if (_buf->used <= 0) {					\
844182080Srnoland			DRM_ERROR( "DMAADVANCEHOSTDATA(): sending empty buf %d\n", _buf->idx );	\
845182080Srnoland			return -EFAULT;					\
846182080Srnoland		}							\
847182080Srnoland		if (list_empty(&dev_priv->placeholders)) {		\
848182080Srnoland			DRM_ERROR( "empty placeholder list in DMAADVANCEHOSTDATA()\n" ); \
849182080Srnoland			return -EFAULT;					\
850182080Srnoland		}							\
851182080Srnoland									\
852182080Srnoland		ptr = dev_priv->placeholders.next;			\
853182080Srnoland		list_del(ptr);						\
854182080Srnoland		_entry = list_entry(ptr, drm_mach64_freelist_t, list);	\
855182080Srnoland		_entry->buf = _buf;					\
856182080Srnoland		_entry->buf->pending = 1;				\
857182080Srnoland		list_add_tail(ptr, &dev_priv->pending);			\
858182080Srnoland		_entry->discard = 1;					\
859182080Srnoland		if ((ret = mach64_add_hostdata_buf_to_ring( dev_priv, _entry ))) \
860182080Srnoland			return ret;					\
861182080Srnoland	} while (0)
862145132Sanholt
863145132Sanholt#endif				/* __MACH64_DRV_H__ */
864