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