1 // SPDX-License-Identifier: GPL-2.0
4 * ATI Mach64 Hardware Acceleration
7 #include <linux/delay.h>
8 #include <asm/unaligned.h>
10 #include <video/mach64.h>
14 * Generic Mach64 routines
17 /* this is for DMA GUI engine! work in progress */
23 } BM_DESCRIPTOR_ENTRY
;
25 #define LAST_DESCRIPTOR (1 << 31)
26 #define SYSTEM_TO_FRAME_BUFFER 0
28 static u32
rotation24bpp(u32 dx
, u32 direction
)
31 if (direction
& DST_X_LEFT_TO_RIGHT
) {
32 rotation
= (dx
/ 4) % 6;
34 rotation
= ((dx
+ 2) / 4) % 6;
37 return ((rotation
<< 8) | DST_24_ROTATION_ENABLE
);
40 void aty_reset_engine(const struct atyfb_par
*par
)
43 aty_st_le32(GEN_TEST_CNTL
,
44 aty_ld_le32(GEN_TEST_CNTL
, par
) &
45 ~(GUI_ENGINE_ENABLE
| HWCURSOR_ENABLE
), par
);
47 aty_st_le32(GEN_TEST_CNTL
,
48 aty_ld_le32(GEN_TEST_CNTL
, par
) | GUI_ENGINE_ENABLE
, par
);
49 /* ensure engine is not locked up by clearing any FIFO or */
52 aty_ld_le32(BUS_CNTL
, par
) | BUS_HOST_ERR_ACK
| BUS_FIFO_ERR_ACK
, par
);
55 static void reset_GTC_3D_engine(const struct atyfb_par
*par
)
57 aty_st_le32(SCALE_3D_CNTL
, 0xc0, par
);
58 mdelay(GTC_3D_RESET_DELAY
);
59 aty_st_le32(SETUP_CNTL
, 0x00, par
);
60 mdelay(GTC_3D_RESET_DELAY
);
61 aty_st_le32(SCALE_3D_CNTL
, 0x00, par
);
62 mdelay(GTC_3D_RESET_DELAY
);
65 void aty_init_engine(struct atyfb_par
*par
, struct fb_info
*info
)
70 /* determine modal information from global mode structure */
71 pitch_value
= info
->fix
.line_length
/ (info
->var
.bits_per_pixel
/ 8);
72 vxres
= info
->var
.xres_virtual
;
74 if (info
->var
.bits_per_pixel
== 24) {
75 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
76 /* horizontal coordinates and widths must be adjusted */
81 /* On GTC (RagePro), we need to reset the 3D engine before */
82 if (M64_HAS(RESET_3D
))
83 reset_GTC_3D_engine(par
);
85 /* Reset engine, enable, and clear any engine errors */
86 aty_reset_engine(par
);
87 /* Ensure that vga page pointers are set to zero - the upper */
88 /* page pointers are set to 1 to handle overflows in the */
90 aty_st_le32(MEM_VGA_WP_SEL
, 0x00010000, par
);
91 aty_st_le32(MEM_VGA_RP_SEL
, 0x00010000, par
);
93 /* ---- Setup standard engine context ---- */
95 /* All GUI registers here are FIFOed - therefore, wait for */
96 /* the appropriate number of empty FIFO entries */
97 wait_for_fifo(14, par
);
99 /* enable all registers to be loaded for context loads */
100 aty_st_le32(CONTEXT_MASK
, 0xFFFFFFFF, par
);
102 /* set destination pitch to modal pitch, set offset to zero */
103 aty_st_le32(DST_OFF_PITCH
, (pitch_value
/ 8) << 22, par
);
105 /* zero these registers (set them to a known state) */
106 aty_st_le32(DST_Y_X
, 0, par
);
107 aty_st_le32(DST_HEIGHT
, 0, par
);
108 aty_st_le32(DST_BRES_ERR
, 0, par
);
109 aty_st_le32(DST_BRES_INC
, 0, par
);
110 aty_st_le32(DST_BRES_DEC
, 0, par
);
112 /* set destination drawing attributes */
113 aty_st_le32(DST_CNTL
, DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
114 DST_X_LEFT_TO_RIGHT
, par
);
116 /* set source pitch to modal pitch, set offset to zero */
117 aty_st_le32(SRC_OFF_PITCH
, (pitch_value
/ 8) << 22, par
);
119 /* set these registers to a known state */
120 aty_st_le32(SRC_Y_X
, 0, par
);
121 aty_st_le32(SRC_HEIGHT1_WIDTH1
, 1, par
);
122 aty_st_le32(SRC_Y_X_START
, 0, par
);
123 aty_st_le32(SRC_HEIGHT2_WIDTH2
, 1, par
);
125 /* set source pixel retrieving attributes */
126 aty_st_le32(SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
, par
);
128 /* set host attributes */
129 wait_for_fifo(13, par
);
130 aty_st_le32(HOST_CNTL
, 0, par
);
132 /* set pattern attributes */
133 aty_st_le32(PAT_REG0
, 0, par
);
134 aty_st_le32(PAT_REG1
, 0, par
);
135 aty_st_le32(PAT_CNTL
, 0, par
);
137 /* set scissors to modal size */
138 aty_st_le32(SC_LEFT
, 0, par
);
139 aty_st_le32(SC_TOP
, 0, par
);
140 aty_st_le32(SC_BOTTOM
, par
->crtc
.vyres
- 1, par
);
141 aty_st_le32(SC_RIGHT
, vxres
- 1, par
);
143 /* set background color to minimum value (usually BLACK) */
144 aty_st_le32(DP_BKGD_CLR
, 0, par
);
146 /* set foreground color to maximum value (usually WHITE) */
147 aty_st_le32(DP_FRGD_CLR
, 0xFFFFFFFF, par
);
149 /* set write mask to effect all pixel bits */
150 aty_st_le32(DP_WRITE_MASK
, 0xFFFFFFFF, par
);
152 /* set foreground mix to overpaint and background mix to */
154 aty_st_le32(DP_MIX
, FRGD_MIX_S
| BKGD_MIX_D
, par
);
156 /* set primary source pixel channel to foreground color */
158 aty_st_le32(DP_SRC
, FRGD_SRC_FRGD_CLR
, par
);
160 /* set compare functionality to false (no-effect on */
162 wait_for_fifo(3, par
);
163 aty_st_le32(CLR_CMP_CLR
, 0, par
);
164 aty_st_le32(CLR_CMP_MASK
, 0xFFFFFFFF, par
);
165 aty_st_le32(CLR_CMP_CNTL
, 0, par
);
167 /* set pixel depth */
168 wait_for_fifo(2, par
);
169 aty_st_le32(DP_PIX_WIDTH
, par
->crtc
.dp_pix_width
, par
);
170 aty_st_le32(DP_CHAIN_MASK
, par
->crtc
.dp_chain_mask
, par
);
172 wait_for_fifo(5, par
);
173 aty_st_le32(SCALE_3D_CNTL
, 0, par
);
174 aty_st_le32(Z_CNTL
, 0, par
);
175 aty_st_le32(CRTC_INT_CNTL
, aty_ld_le32(CRTC_INT_CNTL
, par
) & ~0x20,
177 aty_st_le32(GUI_TRAJ_CNTL
, 0x100023, par
);
179 /* insure engine is idle before leaving */
184 * Accelerated functions
187 static inline void draw_rect(s16 x
, s16 y
, u16 width
, u16 height
,
188 struct atyfb_par
*par
)
190 /* perform rectangle fill */
191 wait_for_fifo(2, par
);
192 aty_st_le32(DST_Y_X
, (x
<< 16) | y
, par
);
193 aty_st_le32(DST_HEIGHT_WIDTH
, (width
<< 16) | height
, par
);
194 par
->blitter_may_be_busy
= 1;
197 void atyfb_copyarea(struct fb_info
*info
, const struct fb_copyarea
*area
)
199 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
200 u32 dy
= area
->dy
, sy
= area
->sy
, direction
= DST_LAST_PEL
;
201 u32 sx
= area
->sx
, dx
= area
->dx
, width
= area
->width
, rotation
= 0;
205 if (!area
->width
|| !area
->height
)
207 if (!par
->accel_flags
) {
208 cfb_copyarea(info
, area
);
212 if (info
->var
.bits_per_pixel
== 24) {
213 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
214 /* horizontal coordinates and widths must be adjusted */
220 if (area
->sy
< area
->dy
) {
221 dy
+= area
->height
- 1;
222 sy
+= area
->height
- 1;
224 direction
|= DST_Y_TOP_TO_BOTTOM
;
230 direction
|= DST_X_LEFT_TO_RIGHT
;
232 if (info
->var
.bits_per_pixel
== 24) {
233 rotation
= rotation24bpp(dx
, direction
);
236 wait_for_fifo(4, par
);
237 aty_st_le32(DP_SRC
, FRGD_SRC_BLIT
, par
);
238 aty_st_le32(SRC_Y_X
, (sx
<< 16) | sy
, par
);
239 aty_st_le32(SRC_HEIGHT1_WIDTH1
, (width
<< 16) | area
->height
, par
);
240 aty_st_le32(DST_CNTL
, direction
| rotation
, par
);
241 draw_rect(dx
, dy
, width
, area
->height
, par
);
244 void atyfb_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
246 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
247 u32 color
, dx
= rect
->dx
, width
= rect
->width
, rotation
= 0;
251 if (!rect
->width
|| !rect
->height
)
253 if (!par
->accel_flags
) {
254 cfb_fillrect(info
, rect
);
258 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
259 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
260 color
= ((u32
*)(info
->pseudo_palette
))[rect
->color
];
264 if (info
->var
.bits_per_pixel
== 24) {
265 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
266 /* horizontal coordinates and widths must be adjusted */
269 rotation
= rotation24bpp(dx
, DST_X_LEFT_TO_RIGHT
);
272 wait_for_fifo(3, par
);
273 aty_st_le32(DP_FRGD_CLR
, color
, par
);
275 BKGD_SRC_BKGD_CLR
| FRGD_SRC_FRGD_CLR
| MONO_SRC_ONE
,
277 aty_st_le32(DST_CNTL
,
278 DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
279 DST_X_LEFT_TO_RIGHT
| rotation
, par
);
280 draw_rect(dx
, rect
->dy
, width
, rect
->height
, par
);
283 void atyfb_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
285 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
286 u32 src_bytes
, dx
= image
->dx
, dy
= image
->dy
, width
= image
->width
;
287 u32 pix_width_save
, pix_width
, host_cntl
, rotation
= 0, src
, mix
;
291 if (!image
->width
|| !image
->height
)
293 if (!par
->accel_flags
||
294 (image
->depth
!= 1 && info
->var
.bits_per_pixel
!= image
->depth
)) {
295 cfb_imageblit(info
, image
);
299 pix_width
= pix_width_save
= aty_ld_le32(DP_PIX_WIDTH
, par
);
300 host_cntl
= aty_ld_le32(HOST_CNTL
, par
) | HOST_BYTE_ALIGN
;
302 switch (image
->depth
) {
304 pix_width
&= ~(BYTE_ORDER_MASK
| HOST_MASK
);
305 pix_width
|= (BYTE_ORDER_MSB_TO_LSB
| HOST_1BPP
);
308 pix_width
&= ~(BYTE_ORDER_MASK
| HOST_MASK
);
309 pix_width
|= (BYTE_ORDER_MSB_TO_LSB
| HOST_4BPP
);
312 pix_width
&= ~HOST_MASK
;
313 pix_width
|= HOST_8BPP
;
316 pix_width
&= ~HOST_MASK
;
317 pix_width
|= HOST_15BPP
;
320 pix_width
&= ~HOST_MASK
;
321 pix_width
|= HOST_16BPP
;
324 pix_width
&= ~HOST_MASK
;
325 pix_width
|= HOST_24BPP
;
328 pix_width
&= ~HOST_MASK
;
329 pix_width
|= HOST_32BPP
;
333 if (info
->var
.bits_per_pixel
== 24) {
334 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
335 /* horizontal coordinates and widths must be adjusted */
339 rotation
= rotation24bpp(dx
, DST_X_LEFT_TO_RIGHT
);
341 pix_width
&= ~DST_MASK
;
342 pix_width
|= DST_8BPP
;
345 * since Rage 3D IIc we have DP_HOST_TRIPLE_EN bit
346 * this hwaccelerated triple has an issue with not aligned data
348 if (M64_HAS(HW_TRIPLE
) && image
->width
% 8 == 0)
349 pix_width
|= DP_HOST_TRIPLE_EN
;
352 if (image
->depth
== 1) {
354 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
355 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
356 fg
= ((u32
*)(info
->pseudo_palette
))[image
->fg_color
];
357 bg
= ((u32
*)(info
->pseudo_palette
))[image
->bg_color
];
359 fg
= image
->fg_color
;
360 bg
= image
->bg_color
;
363 wait_for_fifo(2, par
);
364 aty_st_le32(DP_BKGD_CLR
, bg
, par
);
365 aty_st_le32(DP_FRGD_CLR
, fg
, par
);
366 src
= MONO_SRC_HOST
| FRGD_SRC_FRGD_CLR
| BKGD_SRC_BKGD_CLR
;
367 mix
= FRGD_MIX_S
| BKGD_MIX_S
;
369 src
= MONO_SRC_ONE
| FRGD_SRC_HOST
;
370 mix
= FRGD_MIX_D_XOR_S
| BKGD_MIX_D
;
373 wait_for_fifo(6, par
);
374 aty_st_le32(DP_WRITE_MASK
, 0xFFFFFFFF, par
);
375 aty_st_le32(DP_PIX_WIDTH
, pix_width
, par
);
376 aty_st_le32(DP_MIX
, mix
, par
);
377 aty_st_le32(DP_SRC
, src
, par
);
378 aty_st_le32(HOST_CNTL
, host_cntl
, par
);
379 aty_st_le32(DST_CNTL
, DST_Y_TOP_TO_BOTTOM
| DST_X_LEFT_TO_RIGHT
| rotation
, par
);
381 draw_rect(dx
, dy
, width
, image
->height
, par
);
382 src_bytes
= (((image
->width
* image
->depth
) + 7) / 8) * image
->height
;
384 /* manual triple each pixel */
385 if (info
->var
.bits_per_pixel
== 24 && !(pix_width
& DP_HOST_TRIPLE_EN
)) {
386 int inbit
, outbit
, mult24
, byte_id_in_dword
, width
;
387 u8
*pbitmapin
= (u8
*)image
->data
, *pbitmapout
;
390 for (width
= image
->width
, inbit
= 7, mult24
= 0; src_bytes
; ) {
391 for (hostdword
= 0, pbitmapout
= (u8
*)&hostdword
, byte_id_in_dword
= 0;
392 byte_id_in_dword
< 4 && src_bytes
;
393 byte_id_in_dword
++, pbitmapout
++) {
394 for (outbit
= 7; outbit
>= 0; outbit
--) {
395 *pbitmapout
|= (((*pbitmapin
>> inbit
) & 1) << outbit
);
405 if (inbit
< 0 || width
== 0) {
411 width
= image
->width
;
417 wait_for_fifo(1, par
);
418 aty_st_le32(HOST_DATA0
, hostdword
, par
);
421 u32
*pbitmap
, dwords
= (src_bytes
+ 3) / 4;
422 for (pbitmap
= (u32
*)(image
->data
); dwords
; dwords
--, pbitmap
++) {
423 wait_for_fifo(1, par
);
424 aty_st_le32(HOST_DATA0
, get_unaligned_le32(pbitmap
), par
);
428 /* restore pix_width */
429 wait_for_fifo(1, par
);
430 aty_st_le32(DP_PIX_WIDTH
, pix_width_save
, par
);