1
2/**************************************************************************
3
4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5All Rights Reserved.
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sub license, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice (including the
16next paragraph) shall be included in all copies or substantial portions
17of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27**************************************************************************/
28
29/*
30 * Authors:
31 *   Daryll Strauss <daryll@precisioninsight.com>
32 *
33 */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include "xf86.h"
40#include "xf86_OSproc.h"
41
42#include "compiler.h"
43
44#include "xf86Pci.h"
45
46#include "vgaHW.h"
47
48#include "xf86xv.h"
49#include "i740.h"
50
51#ifdef HAVE_XAA_H
52static unsigned int i740Rop[16] = {
53    0x00, /* GXclear      */
54    0x88, /* GXand        */
55    0x44, /* GXandReverse */
56    0xCC, /* GXcopy       */
57    0x22, /* GXandInvert  */
58    0xAA, /* GXnoop       */
59    0x66, /* GXxor        */
60    0xEE, /* GXor         */
61    0x11, /* GXnor        */
62    0x99, /* GXequiv      */
63    0x55, /* GXinvert     */
64    0xDD, /* GXorReverse  */
65    0x33, /* GXcopyInvert */
66    0xBB, /* GXorInverted */
67    0x77, /* GXnand       */
68    0xFF  /* GXset        */
69};
70
71static unsigned int i740PatternRop[16] = {
72    0x00, /* GXclear      */
73    0xA0, /* GXand        */
74    0x50, /* GXandReverse */
75    0xF0, /* GXcopy       */
76    0x0A, /* GXandInvert  */
77    0xAA, /* GXnoop       */
78    0x5A, /* GXxor        */
79    0xFA, /* GXor         */
80    0x05, /* GXnor        */
81    0xA5, /* GXequiv      */
82    0x55, /* GXinvert     */
83    0xF5, /* GXorReverse  */
84    0x0F, /* GXcopyInvert */
85    0xAF, /* GXorInverted */
86    0x5F, /* GXnand       */
87    0xFF  /* GXset        */
88};
89
90static void I740SyncPIO(ScrnInfoPtr pScrn);
91static void I740SyncMMIO(ScrnInfoPtr pScrn);
92static void I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
93				      unsigned int planemask);
94static void I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
95					int w, int h);
96static void I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
97					   int ydir, int rop,
98					   unsigned int planemask,
99					   int transparency_color);
100static void I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
101					     int x2, int y2, int w, int h);
102static void I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
103					   int pattx, int patty,
104					   int fg, int bg, int rop,
105					   unsigned int planemask);
106static void I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
107						  int pattx, int patty,
108						  int x, int y, int w, int h);
109#if 0
110static void I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
111						   int bg, int fg, int rop,
112						   unsigned int planemask);
113static void I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
114						     int x, int y, int w, int h,
115						     int skipleft);
116#endif
117#endif
118/*
119 * The following function sets up the supported acceleration. Call it
120 * from the FbInit() function in the SVGA driver, or before ScreenInit
121 * in a monolithic server.
122 */
123Bool
124I740AccelInit(ScreenPtr pScreen) {
125#ifdef HAVE_XAA_H
126  XAAInfoRecPtr infoPtr;
127  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
128  I740Ptr pI740 = I740PTR(pScrn);
129
130  pI740->AccelInfoRec = infoPtr = XAACreateInfoRec();
131  if (!infoPtr) return FALSE;
132
133  if (pScrn->bitsPerPixel == 32) {
134    infoPtr->Flags = 0; /* Disables all acceleration */
135    return TRUE;;
136  }
137
138  infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;
139
140  /* Sync */
141  if (pI740->usePIO)
142    infoPtr->Sync = I740SyncPIO;
143  else
144    infoPtr->Sync = I740SyncMMIO;
145
146  infoPtr->CachePixelGranularity=8/pI740->cpp;
147
148  /* Solid filled rectangles */
149  infoPtr->SolidFillFlags = NO_PLANEMASK;
150  infoPtr->SetupForSolidFill = I740SetupForSolidFill;
151  infoPtr->SubsequentSolidFillRect = I740SubsequentSolidFillRect;
152
153  /* Screen to screen copy */
154  infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY);
155  infoPtr->SetupForScreenToScreenCopy = I740SetupForScreenToScreenCopy;
156  infoPtr->SubsequentScreenToScreenCopy = I740SubsequentScreenToScreenCopy;
157
158  /* 8x8 pattern fills */
159  infoPtr->SetupForMono8x8PatternFill = I740SetupForMono8x8PatternFill;
160  infoPtr->SubsequentMono8x8PatternFillRect = I740SubsequentMono8x8PatternFillRect;
161  infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN |
162    BIT_ORDER_IN_BYTE_MSBFIRST;
163
164  /* CPU to screen color expansion */
165  /* Currently XAA is limited to only DWORD padding.  The 3.3 driver
166   * uses NO_PAD scanlines b/c of problems with using the chip in
167   * DWORD mode. Once other padding modes are available in XAA this
168   * Code can be turned back on.
169   */
170#if 0
171#ifndef ALLOW_PCI_COLOR_EXP
172  if (pI740->Chipset != PCI_CHIP_I740_PCI) {
173#endif
174    /*
175     * Currently, we are not properly able to read the bitblt engine
176     * busy bit on the PCI i740 card.  When we are able to do so, we
177     * can re-enable color expansion.
178     */
179    infoPtr->CPUToScreenColorExpandFillFlags =
180       					  NO_PLANEMASK |
181#ifdef USE_DWORD_COLOR_EXP
182					  SCANLINE_PAD_DWORD |
183#endif
184					  CPU_TRANSFER_PAD_QWORD |
185					  SYNC_AFTER_COLOR_EXPAND |
186					  BIT_ORDER_IN_BYTE_MSBFIRST;
187    infoPtr->ColorExpandBase = (unsigned char *)(pI740->MMIOBase + BLTDATA);
188    infoPtr->ColorExpandRange = 0x10000;
189    infoPtr->SetupForCPUToScreenColorExpandFill = I740SetupForCPUToScreenColorExpandFill;
190    infoPtr->SubsequentCPUToScreenColorExpandFill = I740SubsequentCPUToScreenColorExpandFill;
191#ifndef ALLOW_PCI_COLOR_EXP
192    }
193#endif
194#endif
195  return XAAInit(pScreen, infoPtr);
196#else
197  return FALSE;
198#endif
199}
200
201#ifdef HAVE_XAA_H
202
203static void
204I740SyncPIO(ScrnInfoPtr pScrn) {
205  WAIT_ENGINE_IDLE_PIO();
206}
207
208static void
209I740SyncMMIO(ScrnInfoPtr pScrn) {
210  I740Ptr pI740;
211
212  pI740 = I740PTR(pScrn);
213  WAIT_ENGINE_IDLE_MMIO();
214}
215
216static void
217I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
218		      unsigned int planemask) {
219  I740Ptr pI740;
220
221  pI740 = I740PTR(pScrn);
222
223  pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) |
224    (pScrn->displayWidth * pI740->cpp);
225  pI740->bltcmd.BR01 = color;
226  pI740->bltcmd.BR04 = SOLID_PAT_SELECT | PAT_IS_MONO | i740PatternRop[rop];
227}
228
229static void
230I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) {
231  I740Ptr pI740;
232
233  pI740 = I740PTR(pScrn);
234  WAIT_LP_FIFO(12);
235  OUTREG(LP_FIFO, 0x6000000A);
236  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
237  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
238  OUTREG(LP_FIFO, 0x00000000);
239  OUTREG(LP_FIFO, 0x00000000);
240  OUTREG(LP_FIFO, pI740->bltcmd.BR04);
241  OUTREG(LP_FIFO, 0x00000000);
242  OUTREG(LP_FIFO, 0x00000000);
243  OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
244  OUTREG(LP_FIFO, 0x00000000);
245  OUTREG(LP_FIFO, 0x00000000);
246  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
247}
248
249static void
250I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
251			       unsigned int planemask, int transparency_color)
252{
253  I740Ptr pI740;
254
255  pI740 = I740PTR(pScrn);
256  pI740->bltcmd.BR00 = (((pScrn->displayWidth * pI740->cpp) << 16) |
257			(pScrn->displayWidth * pI740->cpp));
258
259  pI740->bltcmd.BR04 = SRC_IS_IN_COLOR | SRC_USE_SRC_ADDR | i740Rop[rop];
260  if (xdir == -1)
261    pI740->bltcmd.BR04 |= BLT_RIGHT_TO_LEFT;
262  else
263    pI740->bltcmd.BR04 |= BLT_LEFT_TO_RIGHT;
264
265  if (ydir == -1)
266    pI740->bltcmd.BR04 |= BLT_BOT_TO_TOP;
267  else
268    pI740->bltcmd.BR04 |= BLT_TOP_TO_BOT;
269
270    pI740->bltcmd.BR01 = 0x00000000;
271
272}
273
274static void
275I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
276				 int x2, int y2, int w, int h) {
277  I740Ptr pI740;
278
279  pI740 = I740PTR(pScrn);
280  if (pI740->bltcmd.BR04 & BLT_BOT_TO_TOP) {
281    pI740->bltcmd.BR06 = (y1 + h - 1) *
282      pScrn->displayWidth * pI740->cpp;
283    pI740->bltcmd.BR07 = (y2 + h - 1) *
284      pScrn->displayWidth * pI740->cpp;
285    } else {
286      pI740->bltcmd.BR06 = y1 * pScrn->displayWidth * pI740->cpp;
287      pI740->bltcmd.BR07 = y2 * pScrn->displayWidth * pI740->cpp;
288    }
289
290  if (pI740->bltcmd.BR04 & BLT_RIGHT_TO_LEFT) {
291    pI740->bltcmd.BR06 += (x1 + w - 1) * pI740->cpp + pI740->cpp - 1;
292    pI740->bltcmd.BR07 += (x2 + w - 1) * pI740->cpp + pI740->cpp - 1;
293  } else {
294    pI740->bltcmd.BR06 += x1 * pI740->cpp;
295    pI740->bltcmd.BR07 += x2 * pI740->cpp;
296  }
297
298  WAIT_LP_FIFO(12);
299  OUTREG(LP_FIFO, 0x6000000A);
300  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
301  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
302  OUTREG(LP_FIFO, 0x00000000);
303  OUTREG(LP_FIFO, 0x00000000);
304  OUTREG(LP_FIFO, pI740->bltcmd.BR04);
305  OUTREG(LP_FIFO, 0x00000000);
306  OUTREG(LP_FIFO, pI740->bltcmd.BR06);
307  OUTREG(LP_FIFO, pI740->bltcmd.BR07);
308  OUTREG(LP_FIFO, 0x00000000);
309  OUTREG(LP_FIFO, 0x00000000);
310  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
311}
312
313static void
314I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
315				int fg, int bg, int rop,
316				unsigned int planemask) {
317  I740Ptr pI740;
318
319  pI740 = I740PTR(pScrn);
320  pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) |
321			(pScrn->displayWidth * pI740->cpp);
322
323  pI740->bltcmd.BR01 = bg;
324  pI740->bltcmd.BR02 = fg;
325
326  pI740->bltcmd.BR04 = PAT_IS_MONO | i740PatternRop[rop];
327  if (bg == -1) pI740->bltcmd.BR04 |= MONO_PAT_TRANSP;
328
329  pI740->bltcmd.BR05 = (pattx + patty * pScrn->displayWidth) * pI740->cpp;
330}
331
332static void
333I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
334				     int x, int y, int w, int h) {
335  I740Ptr pI740;
336
337  pI740 = I740PTR(pScrn);
338  WAIT_LP_FIFO(12);
339  OUTREG(LP_FIFO, 0x6000000A);
340  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
341  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
342  OUTREG(LP_FIFO, pI740->bltcmd.BR02);
343  OUTREG(LP_FIFO, 0x00000000);
344  OUTREG(LP_FIFO, pI740->bltcmd.BR04 | ((y<<20) & PAT_VERT_ALIGN));
345  OUTREG(LP_FIFO, pI740->bltcmd.BR05);
346  OUTREG(LP_FIFO, 0x00000000);
347  OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
348  OUTREG(LP_FIFO, 0x00000000);
349  OUTREG(LP_FIFO, 0x00000000);
350  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
351}
352#if 0
353static void
354I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int bg, int fg,
355				       int rop, unsigned int planemask) {
356  I740Ptr pI740;
357
358  pI740 = I740PTR(pScrn);
359  pI740->bltcmd.BR00 = (pScrn->displayWidth * pI740->cpp) << 16;
360  pI740->bltcmd.BR01 = bg;
361  pI740->bltcmd.BR02 = fg;
362#ifdef USE_DWORD_COLOR_EXP
363  pI740->bltcmd.BR03 = MONO_DWORD_ALIGN | MONO_USE_COLEXP;
364#else
365  pI740->bltcmd.BR03 = MONO_BIT_ALIGN | MONO_USE_COLEXP;
366#endif
367  pI740->bltcmd.BR04 = SRC_IS_MONO | SRC_USE_BLTDATA | i740Rop[rop];
368  if (bg == -1) pI740->bltcmd.BR04 |= MONO_SRC_TRANSP;
369}
370
371static void
372I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y,
373				     int w, int h, int skipleft) {
374  I740Ptr pI740;
375
376  pI740 = I740PTR(pScrn);
377  pI740->AccelInfoRec->Sync(pScrn);
378  OUTREG(LP_FIFO, 0x6000000A);
379  OUTREG(LP_FIFO, pI740->bltcmd.BR00);
380  OUTREG(LP_FIFO, pI740->bltcmd.BR01);
381  OUTREG(LP_FIFO, pI740->bltcmd.BR02);
382  OUTREG(LP_FIFO, pI740->bltcmd.BR03 | (skipleft & MONO_SRC_LEFT_CLIP));
383  OUTREG(LP_FIFO, pI740->bltcmd.BR04);
384  OUTREG(LP_FIFO, 0x00000000);
385  OUTREG(LP_FIFO, 0x00000000);
386  OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
387  OUTREG(LP_FIFO, 0x00000000);
388  OUTREG(LP_FIFO, 0x00000000);
389#ifdef USE_DWORD_COLOR_EXP
390  /*
391   * This extra wait is necessary to keep the bitblt engine from
392   * locking up, but I am not sure why it is needed.  If we take it
393   * out, "x11perf -copyplane10" will lock the bitblt engine.  When
394   * the bitblt engine is locked, it is waiting for mono data to be
395   * written to the BLTDATA region, which seems to imply that some of
396   * the data that was written was lost.  This might be fixed by
397   * BLT_SKEW changes.  Update: The engine still locks up with this
398   * extra wait.  More investigation (and time) is needed.
399   */
400  WAIT_BLT_IDLE();
401#endif
402  OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
403}
404#endif
405
406#endif
407