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