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