xref: /haiku/src/add-ons/accelerants/et6x00/Acceleration.c (revision abfa93e2e6ebc7660a76335203d421737bd215df)
187313834SIngo Weinhold /*****************************************************************************\
287313834SIngo Weinhold  * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
387313834SIngo Weinhold  * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
487313834SIngo Weinhold \*****************************************************************************/
587313834SIngo Weinhold 
687313834SIngo Weinhold #include "GlobalData.h"
787313834SIngo Weinhold #include "generic.h"
887313834SIngo Weinhold 
987313834SIngo Weinhold 
1087313834SIngo Weinhold /*****************************************************************************/
1187313834SIngo Weinhold /*
1287313834SIngo Weinhold  * Set bits in a byte pointed by addr; mask must contain 0s at the bits
1387313834SIngo Weinhold  * positions to be set and must contain 1s at all other bits; val must
1487313834SIngo Weinhold  * contain the values of bits to be set.
1587313834SIngo Weinhold  */
set8(volatile unsigned char * addr,unsigned char mask,unsigned char val)16*abfa93e2SFrançois Revol static __inline void set8(volatile unsigned char *addr, unsigned char mask,
17*abfa93e2SFrançois Revol 	unsigned char val)
1887313834SIngo Weinhold {
1987313834SIngo Weinhold     if (mask == 0)
2087313834SIngo Weinhold         *addr = val;
2187313834SIngo Weinhold     else
2287313834SIngo Weinhold         *addr = (*addr & mask) | (val & ~mask);
2387313834SIngo Weinhold }
2487313834SIngo Weinhold /*****************************************************************************/
get8(volatile unsigned char * addr)25*abfa93e2SFrançois Revol static __inline unsigned char get8(volatile unsigned char *addr)
2687313834SIngo Weinhold {
2787313834SIngo Weinhold     return *addr;
2887313834SIngo Weinhold }
2987313834SIngo Weinhold /*****************************************************************************/
et6000aclTerminate(void)30*abfa93e2SFrançois Revol static __inline void et6000aclTerminate(void) {
3187313834SIngo Weinhold     set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */
3287313834SIngo Weinhold     et6000aclWaitIdle();
3387313834SIngo Weinhold     set8(mmRegs+0x30, 0, 0x00);
3487313834SIngo Weinhold     set8(mmRegs+0x30, 0, 0x01);
3587313834SIngo Weinhold     et6000aclWaitIdle();
3687313834SIngo Weinhold     set8(mmRegs+0x30, 0, 0x00);
3787313834SIngo Weinhold     set8(mmRegs+0x30, 0, 0x10);
3887313834SIngo Weinhold     et6000aclWaitIdle();
3987313834SIngo Weinhold     set8(mmRegs+0x30, 0, 0x00);
4087313834SIngo Weinhold }
4187313834SIngo Weinhold /*****************************************************************************/
4287313834SIngo Weinhold /*
4387313834SIngo Weinhold  * bpp must be bytes per pixel, not bits!
4487313834SIngo Weinhold  */
et6000aclInit(uint8 bpp)4587313834SIngo Weinhold void et6000aclInit(uint8 bpp) {
4687313834SIngo Weinhold 
4787313834SIngo Weinhold     et6000aclTerminate();
4887313834SIngo Weinhold 
4987313834SIngo Weinhold     set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */
5087313834SIngo Weinhold     set8(mmRegs+0x32, 0x99, 0x00); /* maximize the performance */
5187313834SIngo Weinhold     set8(mmRegs+0x8e, 0xcf, (bpp - 1) << 4); /* set pixel color depth */
5287313834SIngo Weinhold     set8(mmRegs+0x91, 0x80, 0x00); /* maximize the performance */
5387313834SIngo Weinhold     set8(mmRegs+0x9d, 0x00, 0x00); /* maximize the performance */
5487313834SIngo Weinhold }
5587313834SIngo Weinhold /*****************************************************************************/
5687313834SIngo Weinhold /*
5787313834SIngo Weinhold  * Wait until ACL becomes idle.
5887313834SIngo Weinhold  */
et6000aclWaitIdle(void)5987313834SIngo Weinhold void et6000aclWaitIdle(void) {
6087313834SIngo Weinhold     while ((get8(mmRegs+0x36) & 0x02) == 0x02);
6187313834SIngo Weinhold }
6287313834SIngo Weinhold /*****************************************************************************/
6387313834SIngo Weinhold /*
6487313834SIngo Weinhold  * Wait until ACL queue becomes not full.
6587313834SIngo Weinhold  */
et6000aclWaitQueueNotFull(void)66*abfa93e2SFrançois Revol static __inline void et6000aclWaitQueueNotFull(void) {
6787313834SIngo Weinhold     while ((get8(mmRegs+0x36) & 0x01) == 0x01);
6887313834SIngo Weinhold }
6987313834SIngo Weinhold /*****************************************************************************/
7087313834SIngo Weinhold /*
7187313834SIngo Weinhold  * Move the specified list of rectangular regions from one location in
7287313834SIngo Weinhold  * the frame buffer to another in the order they are specified in the
7387313834SIngo Weinhold  * blit_params *list. The list is uint32 count elements in length.
7487313834SIngo Weinhold  */
SCREEN_TO_SCREEN_BLIT(engine_token * et,blit_params * list,uint32 count)7587313834SIngo Weinhold void SCREEN_TO_SCREEN_BLIT(engine_token *et,
7687313834SIngo Weinhold                            blit_params *list,
7787313834SIngo Weinhold                            uint32 count)
7887313834SIngo Weinhold {
7987313834SIngo Weinhold uint16 screenWidth = si->dm.virtual_width;
8087313834SIngo Weinhold uint8 bpp = si->bytesPerPixel;
8187313834SIngo Weinhold uint8 bltDir;
8287313834SIngo Weinhold uint16 src_left, src_top, dest_left, dest_top, width, height;
83*abfa93e2SFrançois Revol uint32 srcAddr = 0, destAddr = 0;
8487313834SIngo Weinhold 
8587313834SIngo Weinhold     et6000aclWaitQueueNotFull();
8687313834SIngo Weinhold 
8787313834SIngo Weinhold     set8(mmRegs+0x92, 0x80, 0x77); /* no source wrap */
8887313834SIngo Weinhold     set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */
8987313834SIngo Weinhold     set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */
9087313834SIngo Weinhold 
9187313834SIngo Weinhold     /* Set the source Y offset */
9287313834SIngo Weinhold     *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1;
9387313834SIngo Weinhold 
9487313834SIngo Weinhold     /* Set the destination Y offset */
9587313834SIngo Weinhold     *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1;
9687313834SIngo Weinhold 
9787313834SIngo Weinhold     while(count--) {
9887313834SIngo Weinhold         src_left = list->src_left;
9987313834SIngo Weinhold         src_top = list->src_top;
10087313834SIngo Weinhold         dest_left = list->dest_left;
10187313834SIngo Weinhold         dest_top = list->dest_top;
10287313834SIngo Weinhold         width = list->width;
10387313834SIngo Weinhold         height = list->height;
10487313834SIngo Weinhold 
10587313834SIngo Weinhold         et6000aclWaitQueueNotFull();
10687313834SIngo Weinhold 
10787313834SIngo Weinhold         /* Set the direction and opcode(BitBLT) register */
10887313834SIngo Weinhold         bltDir = 0x00;
10987313834SIngo Weinhold         if (src_left < dest_left) bltDir |= 0x01;
11087313834SIngo Weinhold         if (src_top < dest_top) bltDir |= 0x02;
11187313834SIngo Weinhold         set8(mmRegs+0x8f, 0x3c, bltDir);
11287313834SIngo Weinhold 
11387313834SIngo Weinhold         /* Set the X count register */
11487313834SIngo Weinhold         *((vuint16 *)(mmRegs+0x98)) = (width + 1) * bpp - 1;
11587313834SIngo Weinhold 
11687313834SIngo Weinhold         /* Set the Y count register */
11787313834SIngo Weinhold         *((vuint16 *)(mmRegs+0x9a)) = height;
11887313834SIngo Weinhold 
11987313834SIngo Weinhold         switch (bltDir & 0x03) {
12087313834SIngo Weinhold         case 0x00:
12187313834SIngo Weinhold             srcAddr = (src_top * screenWidth + src_left) * bpp;
12287313834SIngo Weinhold             destAddr = (dest_top * screenWidth + dest_left) * bpp;
12387313834SIngo Weinhold             break;
12487313834SIngo Weinhold 
12587313834SIngo Weinhold         case 0x01:
12687313834SIngo Weinhold             srcAddr =  (src_top * screenWidth + src_left + width) * bpp + bpp-1;
12787313834SIngo Weinhold             destAddr = (dest_top * screenWidth + dest_left + width) * bpp + bpp-1;
12887313834SIngo Weinhold             break;
12987313834SIngo Weinhold 
13087313834SIngo Weinhold         case 0x02:
13187313834SIngo Weinhold             srcAddr = ((src_top + height)*screenWidth + src_left) * bpp;
13287313834SIngo Weinhold             destAddr = ((dest_top + height)*screenWidth + dest_left) * bpp;
13387313834SIngo Weinhold             break;
13487313834SIngo Weinhold 
13587313834SIngo Weinhold         case 0x03:
13687313834SIngo Weinhold             srcAddr = ((src_top + height)*screenWidth + src_left + width) * bpp + bpp-1;
13787313834SIngo Weinhold             destAddr = ((dest_top + height)*screenWidth + dest_left + width) * bpp + bpp-1;
13887313834SIngo Weinhold             break;
13987313834SIngo Weinhold         }
14087313834SIngo Weinhold 
14187313834SIngo Weinhold         /* Set the source address */
14287313834SIngo Weinhold         *((vuint32 *)(mmRegs+0x84)) = srcAddr;
14387313834SIngo Weinhold 
14487313834SIngo Weinhold         /*
14587313834SIngo Weinhold          * Set the destination address -
14687313834SIngo Weinhold          * this action starts the BitBLT operation.
14787313834SIngo Weinhold          */
14887313834SIngo Weinhold         *((vuint32 *)(mmRegs+0xa0)) = destAddr;
14987313834SIngo Weinhold 
15087313834SIngo Weinhold         list++;
15187313834SIngo Weinhold     }
15287313834SIngo Weinhold 
15387313834SIngo Weinhold     si->engine.count++;
15487313834SIngo Weinhold }
15587313834SIngo Weinhold /*****************************************************************************/
15687313834SIngo Weinhold /*
15787313834SIngo Weinhold  * Fill the specified list of rectangular regions with the specified color.
15887313834SIngo Weinhold  * The list is uint32 count elements in length. The rectangular regions are
15987313834SIngo Weinhold  * inclusive. The uint32 color is specified in the same configuration and
16087313834SIngo Weinhold  * byte order as the current display_mode. All coordinates in the list of
16187313834SIngo Weinhold  * rectangles is guaranteed to have been clipped to the virtual limits of
16287313834SIngo Weinhold  * the display_mode.
16387313834SIngo Weinhold  */
FILL_RECTANGLE(engine_token * et,uint32 color,fill_rect_params * list,uint32 count)16487313834SIngo Weinhold void FILL_RECTANGLE(engine_token *et,
16587313834SIngo Weinhold                     uint32 color,
16687313834SIngo Weinhold                     fill_rect_params *list,
16787313834SIngo Weinhold                     uint32 count)
16887313834SIngo Weinhold {
16987313834SIngo Weinhold uint16 screenWidth = si->dm.virtual_width;
17087313834SIngo Weinhold uint8 bpp = si->bytesPerPixel;
17187313834SIngo Weinhold uint16 left, top, right, bottom;
17287313834SIngo Weinhold uint32 srcAddr;
17387313834SIngo Weinhold uint8 i;
17487313834SIngo Weinhold 
17587313834SIngo Weinhold     /*
17687313834SIngo Weinhold      * Normally WaitQueueNotFull should be required & enough, but in reality
17787313834SIngo Weinhold      * this is somewhy sometimes not enough for pixel depth of 3 bytes.
17887313834SIngo Weinhold      */
17987313834SIngo Weinhold     if (bpp == 2)
18087313834SIngo Weinhold         et6000aclWaitQueueNotFull();
18187313834SIngo Weinhold     else
18287313834SIngo Weinhold         et6000aclWaitIdle();
18387313834SIngo Weinhold 
18487313834SIngo Weinhold     /*
18587313834SIngo Weinhold      * We'll put the color at 4 bytes just after the framebuffer.
18687313834SIngo Weinhold      * The srcAddr must be 4 bytes aligned and is always for standard
18787313834SIngo Weinhold      * resolutions.
18887313834SIngo Weinhold      */
18987313834SIngo Weinhold     srcAddr = (uint32)si->framebuffer - (uint32)si->memory +
19087313834SIngo Weinhold         si->dm.virtual_width * si->dm.virtual_height * bpp;
19187313834SIngo Weinhold 
19287313834SIngo Weinhold     switch(bpp) {
19387313834SIngo Weinhold         case 2:
19487313834SIngo Weinhold             set8(mmRegs+0x92, 0x80, 0x02); /* 4x1 source wrap */
19587313834SIngo Weinhold             for (i = 0; i < 2; i++) /* copy the color to source address */
19687313834SIngo Weinhold                 ((vuint16 *)((uint32)si->memory + srcAddr))[i] = (uint16)color;
19787313834SIngo Weinhold             break;
19887313834SIngo Weinhold         case 3:
19987313834SIngo Weinhold             set8(mmRegs+0x92, 0x80, 0x0a); /* 3x1 source wrap */
20087313834SIngo Weinhold             for (i = 0; i < 3; i++) /* copy the color to source address */
20187313834SIngo Weinhold                 ((vuint8 *)((uint32)si->memory + srcAddr))[i] = ((uint8 *)&color)[i];
20287313834SIngo Weinhold 
20387313834SIngo Weinhold             break;
20487313834SIngo Weinhold     }
20587313834SIngo Weinhold 
20687313834SIngo Weinhold     set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */
20787313834SIngo Weinhold     set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */
20887313834SIngo Weinhold 
20987313834SIngo Weinhold     /* Set the source Y offset */
21087313834SIngo Weinhold     *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1;
21187313834SIngo Weinhold     /* Set the destination Y offset */
21287313834SIngo Weinhold     *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1;
21387313834SIngo Weinhold 
21487313834SIngo Weinhold     /* Set the direction and opcode(trapezoid) register (primary edge) */
21587313834SIngo Weinhold     set8(mmRegs+0x8f, 0x18, 0x40);
21687313834SIngo Weinhold     /* Set the secondary edge register */
21787313834SIngo Weinhold     set8(mmRegs+0x93, 0x1a, 0x00);
21887313834SIngo Weinhold 
21987313834SIngo Weinhold     /* Set the primary delta minor register */
22087313834SIngo Weinhold     *((vuint16 *)(mmRegs+0xac)) = 0;
22187313834SIngo Weinhold     /* Set the secondary delta minor register */
22287313834SIngo Weinhold     *((vuint16 *)(mmRegs+0xb4)) = 0;
22387313834SIngo Weinhold 
22487313834SIngo Weinhold     while(count--) {
22587313834SIngo Weinhold         left = list->left;
22687313834SIngo Weinhold         top = list->top;
22787313834SIngo Weinhold         right = list->right;
22887313834SIngo Weinhold         bottom = list->bottom;
22987313834SIngo Weinhold 
23087313834SIngo Weinhold         et6000aclWaitQueueNotFull();
23187313834SIngo Weinhold 
23287313834SIngo Weinhold         /* Set the X count register */
23387313834SIngo Weinhold         *((vuint16 *)(mmRegs+0x98)) = (right-left+1)*bpp - 1;
23487313834SIngo Weinhold         /* Set the Y count register */
23587313834SIngo Weinhold         *((vuint16 *)(mmRegs+0x9a)) = bottom-top;
23687313834SIngo Weinhold 
23787313834SIngo Weinhold         /* Set the primary delta major register */
23887313834SIngo Weinhold         *((vuint16 *)(mmRegs+0xae)) = bottom-top;
23987313834SIngo Weinhold 
24087313834SIngo Weinhold         /* Set the secondary delta major register */
24187313834SIngo Weinhold         *((vuint16 *)(mmRegs+0xb6)) = bottom-top;
24287313834SIngo Weinhold 
24387313834SIngo Weinhold         /* Set the source address */
24487313834SIngo Weinhold         *((vuint32 *)(mmRegs+0x84)) = srcAddr;
24587313834SIngo Weinhold 
24687313834SIngo Weinhold         /*
24787313834SIngo Weinhold          * Set the destination address -
24887313834SIngo Weinhold          * this action starts the trapezoid operation.
24987313834SIngo Weinhold          */
25087313834SIngo Weinhold         *((vuint32 *)(mmRegs+0xa0)) = (top * screenWidth + left) * bpp;
25187313834SIngo Weinhold 
25287313834SIngo Weinhold         list++;
25387313834SIngo Weinhold     }
25487313834SIngo Weinhold 
25587313834SIngo Weinhold     si->engine.count++;
25687313834SIngo Weinhold }
25787313834SIngo Weinhold /*****************************************************************************/
258