1/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * This file contains routines to program the 2D acceleration hardware for
28 * the first generation graphics unit (GXLV, SC1200).
29 *
30 *    gfx_set_bpp
31 *    gfx_set_solid_pattern
32 *    gfx_set_mono_pattern
33 *    gfx_set_color_pattern
34 *    gfx_set_solid_source
35 *    gfx_set_mono_source
36 *    gfx_set_raster_operation
37 *    gfx_pattern_fill
38 *    gfx_screen_to_screen_blt
39 *    gfx_screen_to_screen_xblt
40 *    gfx_color_bitmap_to_screen_blt
41 *    gfx_color_bitmap_to_screen_xblt
42 *    gfx_mono_bitmap_to_screen_blt
43 *    gfx_bresenham_line
44 *    gfx_wait_until_idle
45 * */
46
47#if GFX_NO_IO_IN_WAIT_MACROS
48#define GFX_WAIT_PENDING		\
49		while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { ; }
50#define GFX_WAIT_BUSY 			\
51		while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { ; }
52#define GFX_WAIT_PIPELINE 		\
53		while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { ; }
54#else
55#define GFX_WAIT_PENDING 		\
56		while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { INB (0x80); }
57#define GFX_WAIT_BUSY 			\
58		while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { INB (0x80); }
59#define GFX_WAIT_PIPELINE 		\
60		while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { INB (0x80); }
61#endif
62
63void gu1_detect_blt_buffer_base(void);
64
65/*---------------------------------------------------------------------------
66 * GFX_SET_BPP
67 *
68 * This routine sets the bits per pixel value in the graphics engine.
69 * It is also stored in a static variable to use in the future calls to
70 * the rendering routines.
71 *---------------------------------------------------------------------------
72 */
73#if GFX_2DACCEL_DYNAMIC
74void
75gu1_set_bpp(unsigned short bpp)
76#else
77void
78gfx_set_bpp(unsigned short bpp)
79#endif
80{
81    int control = 0;
82    unsigned short pitch = gfx_get_display_pitch();
83
84    GFXbpp = bpp;
85
86    /* DETECT BASE ADDRESSES FOR BLT BUFFERS */
87    /* Different for 2K or 3K of scratchpad.  Also need to calculate */
88    /* the number of pixels that can fit in a BLT buffer - need to */
89    /* subtract 16 for alignment considerations.  The 2K case, for */
90    /* example, is 816 bytes wide, allowing 800 pixels in 8 BPP, which */
91    /* means rendering operations won't be split for 800x600. */
92
93    gu1_detect_blt_buffer_base();
94    GFXbufferWidthPixels = GFXbb1Base - GFXbb0Base - 16;
95    if (bpp > 8) {
96        /* If 16bpp, divide GFXbufferWidthPixels by 2 */
97        GFXbufferWidthPixels >>= 1;
98    }
99
100    /* SET THE GRAPHICS CONTROLLER BPP AND PITCH */
101    if (bpp > 8) {
102        /* Set the 16bpp bit if necessary */
103        control = BC_16BPP;
104    }
105    if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) {
106        control |= BC_FB_WIDTH_4096;
107    }
108    else if (pitch > 1024) {
109        control |= BC_FB_WIDTH_2048;
110    }
111    GFX_WAIT_BUSY;
112    WRITE_REG32(GP_BLIT_STATUS, control);
113}
114
115/*
116 *---------------------------------------------------------------------------
117 * GFX_SET_SOLID_SOURCE
118 *
119 * This routine is used to specify a solid source color.  For the Xfree96
120 * display driver, the source color is used to specify a planemask and the
121 * ROP is adjusted accordingly.
122 *---------------------------------------------------------------------------
123 */
124#if GFX_2DACCEL_DYNAMIC
125void
126gu1_set_solid_source(unsigned long color)
127#else
128void
129gfx_set_solid_source(unsigned long color)
130#endif
131{
132    /* CLEAR TRANSPARENCY FLAG */
133
134    GFXsourceFlags = 0;
135
136    /* FORMAT 8 BPP COLOR */
137    /* GX requires 8BPP color data be duplicated into bits [15:8]. */
138
139    if (GFXbpp == 8) {
140        color &= 0x00FF;
141        color |= (color << 8);
142    }
143
144    /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
145
146    GFX_WAIT_PENDING;
147    WRITE_REG16(GP_SRC_COLOR_0, (unsigned short) color);
148    WRITE_REG16(GP_SRC_COLOR_1, (unsigned short) color);
149}
150
151/*
152 *---------------------------------------------------------------------------
153 * GFX_SET_MONO_SOURCE
154 *
155 * This routine is used to specify the monochrome source colors.
156 * It must be called *after* loading any pattern data (those routines
157 * clear the source flags).
158 *---------------------------------------------------------------------------
159 */
160#if GFX_2DACCEL_DYNAMIC
161void
162gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
163                    unsigned short transparent)
164#else
165void
166gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
167                    unsigned short transparent)
168#endif
169{
170    /* SET TRANSPARENCY FLAG */
171
172    GFXsourceFlags = transparent ? RM_SRC_TRANSPARENT : 0;
173
174    /* FORMAT 8 BPP COLOR */
175    /* GX requires 8BPP color data be duplicated into bits [15:8]. */
176
177    if (GFXbpp == 8) {
178        bgcolor &= 0x00FF;
179        bgcolor |= (bgcolor << 8);
180        fgcolor &= 0x00FF;
181        fgcolor |= (fgcolor << 8);
182    }
183
184    /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
185
186    GFX_WAIT_PENDING;
187    WRITE_REG16(GP_SRC_COLOR_0, (unsigned short) bgcolor);
188    WRITE_REG16(GP_SRC_COLOR_1, (unsigned short) fgcolor);
189}
190
191/*
192 *---------------------------------------------------------------------------
193 * GFX_SET_SOLID_PATTERN
194 *
195 * This routine is used to specify a solid pattern color.  It is called
196 * before performing solid rectangle fills or more complicated BLTs that
197 * use a solid pattern color.
198 *
199 * The driver should always call "gfx_load_raster_operation" after a call
200 * to this routine to make sure that the pattern flags are set appropriately.
201 *---------------------------------------------------------------------------
202 */
203#if GFX_2DACCEL_DYNAMIC
204void
205gu1_set_solid_pattern(unsigned long color)
206#else
207void
208gfx_set_solid_pattern(unsigned long color)
209#endif
210{
211    /* CLEAR TRANSPARENCY FLAG */
212
213    GFXsourceFlags = 0;
214
215    /* SET PATTERN FLAGS */
216
217    GFXpatternFlags = 0;
218
219    /* FORMAT 8 BPP COLOR */
220    /* GX requires 8BPP color data be duplicated into bits [15:8]. */
221
222    if (GFXbpp == 8) {
223        color &= 0x00FF;
224        color |= (color << 8);
225    }
226
227    /* SAVE THE REFORMATTED COLOR FOR LATER */
228    /* Used to call the "GFX_solid_fill" routine for special cases. */
229
230    GFXsavedColor = color;
231
232    /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
233
234    GFX_WAIT_PENDING;
235    WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) color);
236}
237
238/*
239 *---------------------------------------------------------------------------
240 * GFX_SET_MONO_PATTERN
241 *
242 * This routine is used to specify a monochrome pattern.
243 *---------------------------------------------------------------------------
244 */
245#if GFX_2DACCEL_DYNAMIC
246void
247gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
248                     unsigned long data0, unsigned long data1,
249                     unsigned char transparent)
250#else
251void
252gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
253                     unsigned long data0, unsigned long data1,
254                     unsigned char transparent)
255#endif
256{
257    /* CLEAR TRANSPARENCY FLAG */
258
259    GFXsourceFlags = 0;
260
261    /* SET PATTERN FLAGS */
262
263    GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
264        RM_PAT_MONO;
265
266    /* FORMAT 8 BPP COLOR */
267    /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
268
269    if (GFXbpp == 8) {
270        bgcolor &= 0x00FF;
271        bgcolor |= (bgcolor << 8);
272        fgcolor &= 0x00FF;
273        fgcolor |= (fgcolor << 8);
274    }
275
276    /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
277
278    GFX_WAIT_PENDING;
279    WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) bgcolor);
280    WRITE_REG16(GP_PAT_COLOR_1, (unsigned short) fgcolor);
281    WRITE_REG32(GP_PAT_DATA_0, data0);
282    WRITE_REG32(GP_PAT_DATA_1, data1);
283}
284
285/*
286 *---------------------------------------------------------------------------
287 * GFX_SET_COLOR_PATTERN
288 *
289 * This routine is used to specify a color pattern.
290 *---------------------------------------------------------------------------
291 */
292#if GFX_2DACCEL_DYNAMIC
293void
294gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
295                      unsigned long data0, unsigned long data1,
296                      unsigned long data2, unsigned long data3,
297                      unsigned char transparent)
298#else
299void
300gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
301                      unsigned long data0, unsigned long data1,
302                      unsigned long data2, unsigned long data3,
303                      unsigned char transparent)
304#endif
305{
306    /* CLEAR TRANSPARENCY FLAG */
307
308    GFXsourceFlags = 0;
309
310    /* SET PATTERN FLAGS */
311
312    GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
313        RM_PAT_MONO;
314
315    GFXpatternFlags |= RM_PAT_COLOR;
316    /* FORMAT 8 BPP COLOR */
317    /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
318
319    if (GFXbpp == 8) {
320        bgcolor &= 0x00FF;
321        bgcolor |= (bgcolor << 8);
322        fgcolor &= 0x00FF;
323        fgcolor |= (fgcolor << 8);
324    }
325
326    /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
327
328    GFX_WAIT_PENDING;
329    WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) bgcolor);
330    WRITE_REG16(GP_PAT_COLOR_1, (unsigned short) fgcolor);
331    WRITE_REG32(GP_PAT_DATA_0, data0);
332    WRITE_REG32(GP_PAT_DATA_1, data1);
333    if (GFXbpp > 8) {
334        WRITE_REG32(GP_PAT_DATA_2, data2);
335        WRITE_REG32(GP_PAT_DATA_3, data3);
336    }
337}
338
339/*
340 *---------------------------------------------------------------------------
341 * GFX_LOAD_COLOR_PATTERN_LINE
342 *
343 * This routine is used to load a single line of a 8x8 color pattern.
344 *---------------------------------------------------------------------------
345 */
346#if GFX_2DACCEL_DYNAMIC
347void
348gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8)
349#else
350void
351gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8)
352#endif
353{
354    /* CLEAR TRANSPARENCY FLAG */
355
356    GFXsourceFlags = 0;
357
358    /* SET PATTERN FLAGS */
359
360    GFXpatternFlags = RM_PAT_COLOR;
361
362    y &= 7;
363
364    if (GFXbpp > 8)
365        pattern_8x8 += (y << 2);
366    else
367        pattern_8x8 += (y << 1);
368
369    /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
370
371    GFX_WAIT_PENDING;
372    WRITE_REG32(GP_PAT_DATA_0, pattern_8x8[0]);
373    WRITE_REG32(GP_PAT_DATA_1, pattern_8x8[1]);
374    if (GFXbpp > 8) {
375        WRITE_REG32(GP_PAT_DATA_2, pattern_8x8[2]);
376        WRITE_REG32(GP_PAT_DATA_3, pattern_8x8[3]);
377    }
378}
379
380/*
381 *---------------------------------------------------------------------------
382 * GFX_SET_RASTER_OPERATION
383 *
384 * This routine loads the specified raster operation.  It sets the pattern
385 * flags appropriately.
386 *---------------------------------------------------------------------------
387 */
388#if GFX_2DACCEL_DYNAMIC
389void
390gu1_set_raster_operation(unsigned char rop)
391#else
392void
393gfx_set_raster_operation(unsigned char rop)
394#endif
395{
396    unsigned short rop16;
397
398    /* GENERATE 16-BIT VERSION OF ROP WITH PATTERN FLAGS */
399
400    rop16 = (unsigned short) rop | GFXpatternFlags;
401    if ((rop & 0x33) ^ ((rop >> 2) & 0x33))
402        rop16 |= GFXsourceFlags;
403
404    /* SAVE ROP FOR LATER COMPARISONS */
405    /* Need to have the pattern flags included */
406
407    GFXsavedRop = rop16;
408
409    /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */
410    /* True if even bits (0:2:4:6) do not equal the corresponding */
411    /* even bits (1:3:5:7). */
412
413    GFXusesDstData = ((rop & 0x55) ^ ((rop >> 1) & 0x55));
414
415    /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
416    /* Only one operation can be pending at a time. */
417
418    GFX_WAIT_PENDING;
419    WRITE_REG16(GP_RASTER_MODE, rop16);
420}
421
422/*
423 *---------------------------------------------------------------------------
424 * GFX_SOLID_FILL
425 *
426 * This routine MUST be used when performing a solid rectangle fill with
427 * the ROPs of PATCOPY (0xF0), BLACKNESS (0x00), WHITENESS (0xFF), or
428 * PATINVERT (0x0F).  There is a bug in GXm for these cases that requires a
429 * workaround.
430 *
431 * For BLACKNESS (ROP = 0x00), set the color to 0x0000.
432 * For WHITENESS (ROP = 0xFF), set the color to 0xFFFF.
433 * For PATINVERT (ROP = 0x0F), invert the desired color.
434 *
435 *     X               screen X position (left)
436 *     Y               screen Y position (top)
437 *     WIDTH           width of rectangle, in pixels
438 *     HEIGHT          height of rectangle, in scanlines
439 *     COLOR           fill color
440 *
441 * THIS ROUTINE SHOULD NOT BE DIRECTLY CALLED FROM THE DRIVER.  The driver
442 * should always use GFX_pattern_fill and let that routine call this one
443 * when approipriate.  This is to hide quirks specific to MediaGX hardware.
444 *---------------------------------------------------------------------------
445 */
446void
447gu1_solid_fill(unsigned short x, unsigned short y,
448               unsigned short width, unsigned short height, unsigned long color)
449{
450    unsigned short section;
451
452    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
453    /* Only one operation can be pending at a time. */
454
455    GFX_WAIT_PENDING;
456
457    /* SET REGISTERS TO DRAW RECTANGLE */
458
459    WRITE_REG16(GP_DST_XCOOR, x);
460    WRITE_REG16(GP_DST_YCOOR, y);
461    WRITE_REG16(GP_HEIGHT, height);
462    WRITE_REG16(GP_RASTER_MODE, 0x00F0);        /* PATCOPY */
463    WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) color);
464
465    /* CHECK WIDTH FOR GX BUG WORKAROUND */
466
467    if (width <= 16) {
468        /* OK TO DRAW SMALL RECTANGLE IN ONE PASS */
469
470        WRITE_REG16(GP_WIDTH, width);
471        WRITE_REG16(GP_BLIT_MODE, 0);
472    }
473    else {
474        /* DRAW FIRST PART OF RECTANGLE */
475        /* Get to a 16 pixel boundary. */
476
477        section = 0x10 - (x & 0x0F);
478        WRITE_REG16(GP_WIDTH, section);
479        WRITE_REG16(GP_BLIT_MODE, 0);
480
481        /* POLL UNTIL ABLE TO LOAD THE SECOND RECTANGLE */
482
483        GFX_WAIT_PENDING;
484        WRITE_REG16(GP_DST_XCOOR, x + section);
485        WRITE_REG16(GP_DST_YCOOR, y);
486        WRITE_REG16(GP_WIDTH, width - section);
487        WRITE_REG16(GP_BLIT_MODE, 0);
488    }
489}
490
491/*
492 *----------------------------------------------------------------------------
493 * GFX_PATTERN_FILL
494 *
495 * This routine is used to fill a rectangular region.  The pattern must
496 * be previously loaded using one of GFX_load_*_pattern routines.  Also, the
497 * raster operation must be previously specified using the
498 * "GFX_load_raster_operation" routine.
499 *
500 *      X               screen X position (left)
501 *      Y               screen Y position (top)
502 *      WIDTH           width of rectangle, in pixels
503 *      HEIGHT          height of rectangle, in scanlines
504 *----------------------------------------------------------------------------
505 */
506#if GFX_2DACCEL_DYNAMIC
507void
508gu1_pattern_fill(unsigned short x, unsigned short y,
509                 unsigned short width, unsigned short height)
510#else
511void
512gfx_pattern_fill(unsigned short x, unsigned short y,
513                 unsigned short width, unsigned short height)
514#endif
515{
516    unsigned short section, buffer_width, blit_mode;
517
518    /* CHECK IF OPTIMIZED SOLID CASES */
519    /* Check all 16 bits of the ROP to include solid pattern flags. */
520
521    switch (GFXsavedRop) {
522        /* CHECK FOR SPECIAL CASES WITHOUT DESTINATION DATA */
523        /* Need hardware workaround for fast "burst write" cases. */
524
525    case 0x00F0:
526        gu1_solid_fill(x, y, width, height, (unsigned short) GFXsavedColor);
527        break;
528    case 0x000F:
529        gu1_solid_fill(x, y, width, height, (unsigned short) ~GFXsavedColor);
530        break;
531    case 0x0000:
532        gu1_solid_fill(x, y, width, height, 0x0000);
533        break;
534    case 0x00FF:
535        gu1_solid_fill(x, y, width, height, 0xFFFF);
536        break;
537
538        /* REMAINING CASES REQUIRE DESTINATION DATA OR NOT SOLID COLOR */
539
540    default:
541
542        /* DETERMINE BLT MODE VALUE */
543        /* Still here for non-solid patterns without destination data. */
544
545        blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
546
547        /* SET SOURCE EXPANSION MODE */
548        /* If the ROP requires source data, then the source data is all 1's */
549        /* and then expanded into the desired color in GP_SRC_COLOR_1. */
550
551        blit_mode |= BM_SOURCE_EXPAND;
552
553        /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
554        /* Write the registers that do not change for each section. */
555
556        GFX_WAIT_PENDING;
557        WRITE_REG16(GP_HEIGHT, height);
558
559        /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
560        /* Therefore, width available = BLT buffer width * 2. */
561
562        buffer_width = GFXbufferWidthPixels << 1;
563
564        /* REPEAT UNTIL FINISHED WITH RECTANGLE */
565        /* Perform BLT in vertical sections, as wide as the BLT buffer */
566        /* allows.  Hardware does not split the operations, so */
567        /* software must do it to avoid large scanlines that would */
568        /* overflow the BLT buffers. */
569
570        while (width > 0) {
571            /* DETERMINE WIDTH OF SECTION */
572
573            if (width > buffer_width)
574                section = buffer_width;
575            else
576                section = width;
577
578            /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
579
580            GFX_WAIT_PENDING;
581            WRITE_REG16(GP_DST_XCOOR, x);
582            WRITE_REG16(GP_DST_YCOOR, y);
583            WRITE_REG16(GP_WIDTH, section);
584            WRITE_REG16(GP_BLIT_MODE, blit_mode);
585
586            /* ADJUST PARAMETERS FOR NEXT SECTION */
587
588            width -= section;
589            x += section;
590        }
591        break;
592    }
593}
594
595/*
596 *----------------------------------------------------------------------------
597 * GFX_COLOR_PATTERN_FILL
598 *
599 * This routine is used to render a rectangle using the current raster
600 * operation and the specified color pattern.  It allows an 8x8 color
601 * pattern to be rendered without multiple calls to the gfx_set_color_pattern
602 * and gfx_pattern_fill routines.
603 *
604 *      X               screen X position (left)
605 *      Y               screen Y position (top)
606 *      WIDTH           width of rectangle, in pixels
607 *      HEIGHT          height of rectangle, in scanlines
608 *      *PATTERN		pointer to 8x8 color pattern data
609 *----------------------------------------------------------------------------
610 */
611#if GFX_2DACCEL_DYNAMIC
612void
613gu1_color_pattern_fill(unsigned short x, unsigned short y,
614                       unsigned short width, unsigned short height,
615                       unsigned long *pattern)
616#else
617void
618gfx_color_pattern_fill(unsigned short x, unsigned short y,
619                       unsigned short width, unsigned short height,
620                       unsigned long *pattern)
621#endif
622{
623    unsigned short blit_mode, passes, cur_y, pat_y, i;
624    unsigned short buffer_width, line_width;
625    unsigned short bpp_shift, section, cur_x;
626
627    /* SET APPROPRIATE INCREMENT */
628
629    bpp_shift = (GFXbpp > 8) ? 2 : 1;
630
631    /* SET DESTINATION REQUIRED */
632
633    blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
634
635    /* SET SOURCE EXPANSION */
636
637    blit_mode |= BM_SOURCE_EXPAND;
638
639    /* OVERRIDE RASTER MODE TO FORCE A COLOR PATTERN */
640
641    GFX_WAIT_PENDING;
642    WRITE_REG16(GP_RASTER_MODE,
643                (GFXsavedRop & ~RM_PAT_MASK & ~RM_PAT_TRANSPARENT) |
644                RM_PAT_COLOR);
645
646    /* WRITE THE REGISTERS THAT DO NOT CHANGE         */
647    /* If destination data is required, the width and */
648    /* x position will be overwritten.                */
649
650    WRITE_REG16(GP_HEIGHT, 1);
651    WRITE_REG16(GP_WIDTH, width);
652    WRITE_REG16(GP_DST_XCOOR, x);
653
654    /* THE ENTIRE PATTERN WILL NOT BE DRAWN IF THE HEIGHT IS LESS THAN 8 */
655
656    passes = (height < 8) ? height : 8;
657
658    /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
659    /* Therefore, width available = BLT buffer width * 2. */
660
661    buffer_width = GFXbufferWidthPixels << 1;
662
663    for (i = 0; i < passes; i++) {
664        pat_y = ((y + i) & 7) << bpp_shift;
665        cur_y = y + i;
666
667        /* WRITE THE PATTERN DATA FOR THE ACTIVE LINE */
668
669        GFX_WAIT_PENDING;
670        WRITE_REG32(GP_PAT_DATA_0, pattern[pat_y]);
671        WRITE_REG32(GP_PAT_DATA_1, pattern[pat_y + 1]);
672
673        if (GFXbpp > 8) {
674            WRITE_REG32(GP_PAT_DATA_2, pattern[pat_y + 2]);
675            WRITE_REG32(GP_PAT_DATA_3, pattern[pat_y + 3]);
676        }
677
678        /* SPLIT BLT LINE INTO SECTIONS IF REQUIRED              */
679        /* If no destination data is required, we can ignore     */
680        /* the BLT buffers.  Otherwise, we must separate the BLT */
681        /* so as not to overflow the buffers                     */
682
683        if (blit_mode & BM_READ_DST_BB0) {
684            line_width = width;
685            cur_x = x;
686
687            while (line_width) {
688                section =
689                    (line_width > buffer_width) ? buffer_width : line_width;
690                cur_y = y + i;
691
692                GFX_WAIT_PENDING;
693                WRITE_REG16(GP_DST_XCOOR, cur_x);
694                WRITE_REG16(GP_WIDTH, section);
695
696                while (cur_y < y + height) {
697                    GFX_WAIT_PENDING;
698                    WRITE_REG16(GP_DST_YCOOR, cur_y);
699                    WRITE_REG16(GP_BLIT_MODE, blit_mode);
700                    cur_y += 8;
701                }
702
703                cur_x += section;
704                line_width -= section;
705            }
706
707        }
708        else {
709            while (cur_y < y + height) {
710                GFX_WAIT_PENDING;
711                WRITE_REG16(GP_DST_YCOOR, cur_y);
712                WRITE_REG16(GP_BLIT_MODE, blit_mode);
713                cur_y += 8;
714            }
715        }
716
717    }
718
719    /* RESTORE ORIGINAL ROP AND FLAGS */
720
721    GFX_WAIT_PENDING;
722    WRITE_REG16(GP_RASTER_MODE, GFXsavedRop);
723
724}
725
726/*
727 *----------------------------------------------------------------------------
728 * SCREEN TO SCREEN BLT
729 *
730 * This routine should be used to perform a screen to screen BLT when the
731 * ROP does not require destination data.
732 *
733 *      SRCX            screen X position to copy from
734 *      SRCY            screen Y position to copy from
735 *      DSTX            screen X position to copy to
736 *      DSTY            screen Y position to copy to
737 *      WIDTH           width of rectangle, in pixels
738 *      HEIGHT          height of rectangle, in scanlines
739 *----------------------------------------------------------------------------
740 */
741#if GFX_2DACCEL_DYNAMIC
742void
743gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
744                         unsigned short dstx, unsigned short dsty,
745                         unsigned short width, unsigned short height)
746#else
747void
748gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
749                         unsigned short dstx, unsigned short dsty,
750                         unsigned short width, unsigned short height)
751#endif
752{
753    unsigned short section, buffer_width;
754    unsigned short blit_mode;
755
756    /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
757
758    blit_mode = GFXusesDstData ? BM_READ_DST_FB1 | BM_READ_SRC_FB :
759        BM_READ_SRC_FB;
760
761    /* CHECK Y DIRECTION */
762    /* Hardware has support for negative Y direction. */
763
764    if (dsty > srcy) {
765        blit_mode |= BM_REVERSE_Y;
766        srcy += height - 1;
767        dsty += height - 1;
768    }
769
770    /* CHECK X DIRECTION */
771    /* Hardware does not support negative X direction since at the time */
772    /* of development all supported resolutions could fit a scanline of */
773    /* data at once into the BLT buffers (using both BB0 and BB1).  This */
774    /* code is more generic to allow for any size BLT buffer. */
775
776    if (dstx > srcx) {
777        srcx += width;
778        dstx += width;
779    }
780
781    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
782    /* Write the registers that do not change for each section. */
783
784    GFX_WAIT_PENDING;
785    WRITE_REG16(GP_HEIGHT, height);
786
787    /* CHECK AVAILABLE BLT BUFFER SIZE */
788    /* Can use both BLT buffers if no destination data is required. */
789
790    buffer_width = GFXusesDstData ? GFXbufferWidthPixels :
791        GFXbufferWidthPixels << 1;
792
793    /* REPEAT UNTIL FINISHED WITH RECTANGLE */
794    /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
795    /* Hardware does not split the operations, so software must do it to */
796    /* avoid large scanlines that would overflow the BLT buffers. */
797
798    while (width > 0) {
799        /* CHECK WIDTH OF CURRENT SECTION */
800
801        if (width > buffer_width)
802            section = buffer_width;
803        else
804            section = width;
805
806        /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
807
808        GFX_WAIT_PENDING;
809        WRITE_REG16(GP_SRC_YCOOR, srcy);
810        WRITE_REG16(GP_DST_YCOOR, dsty);
811        WRITE_REG16(GP_WIDTH, section);
812
813        /* CHECK X DIRECTION */
814
815        if (dstx > srcx) {
816            /* NEGATIVE X DIRECTION */
817            /* Still positive X direction within the section. */
818
819            srcx -= section;
820            dstx -= section;
821            WRITE_REG16(GP_SRC_XCOOR, srcx);
822            WRITE_REG16(GP_DST_XCOOR, dstx);
823            WRITE_REG16(GP_BLIT_MODE, blit_mode);
824        }
825        else {
826            /* POSITIVE X DIRECTION */
827
828            WRITE_REG16(GP_SRC_XCOOR, srcx);
829            WRITE_REG16(GP_DST_XCOOR, dstx);
830            WRITE_REG16(GP_BLIT_MODE, blit_mode);
831            dstx += section;
832            srcx += section;
833        }
834        width -= section;
835    }
836}
837
838/*
839 *----------------------------------------------------------------------------
840 * SCREEN TO SCREEN TRANSPARENT BLT
841 *
842 * This routine should be used to perform a screen to screen BLT when a
843 * specified color should by transparent.  The only supported ROP is SRCCOPY.
844 *
845 *      SRCX            screen X position to copy from
846 *      SRCY            screen Y position to copy from
847 *      DSTX            screen X position to copy to
848 *      DSTY            screen Y position to copy to
849 *      WIDTH           width of rectangle, in pixels
850 *      HEIGHT          height of rectangle, in scanlines
851 *      COLOR           transparent color
852 *----------------------------------------------------------------------------
853 */
854#if GFX_2DACCEL_DYNAMIC
855void
856gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
857                          unsigned short dstx, unsigned short dsty,
858                          unsigned short width, unsigned short height,
859                          unsigned long color)
860#else
861void
862gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
863                          unsigned short dstx, unsigned short dsty,
864                          unsigned short width, unsigned short height,
865                          unsigned long color)
866#endif
867{
868    unsigned short section, buffer_width;
869    unsigned short blit_mode = BM_READ_SRC_FB;
870
871    /* CHECK Y DIRECTION */
872    /* Hardware has support for negative Y direction. */
873
874    if (dsty > srcy) {
875        blit_mode |= BM_REVERSE_Y;
876        srcy += height - 1;
877        dsty += height - 1;
878    }
879
880    /* CHECK X DIRECTION */
881    /* Hardware does not support negative X direction since at the time */
882    /* of development all supported resolutions could fit a scanline of */
883    /* data at once into the BLT buffers (using both BB0 and BB1).  This */
884    /* code is more generic to allow for any size BLT buffer. */
885
886    if (dstx > srcx) {
887        srcx += width;
888        dstx += width;
889    }
890
891    /* CALCULATE BLT BUFFER SIZE */
892    /* Need to use BB1 to store the BLT buffer data. */
893
894    buffer_width = GFXbufferWidthPixels;
895
896    /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
897
898    if (GFXbpp == 8) {
899        color &= 0x00FF;
900        color |= (color << 8);
901    }
902    color = (color & 0x0000FFFF) | (color << 16);
903
904    /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
905    /* Need to make sure any previous BLT using BB1 is complete. */
906    /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
907
908    GFX_WAIT_BUSY;
909    WRITE_SCRATCH32(GFXbb1Base, color);
910
911    /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
912    /* Already know graphics pipeline is idle. */
913    /* Only need to latch data into the holding registers for the current */
914    /* data from BB1.  A 1 pixel wide BLT will suffice. */
915
916    WRITE_REG32(GP_DST_XCOOR, 0);
917    WRITE_REG32(GP_SRC_XCOOR, 0);
918    WRITE_REG32(GP_WIDTH, 0x00010001);
919    WRITE_REG16(GP_RASTER_MODE, 0x00CC);
920    WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
921
922    /* WRITE REGISTERS FOR REAL SCREEN TO SCREEN BLT */
923
924    GFX_WAIT_PENDING;
925    WRITE_REG16(GP_HEIGHT, height);
926    WRITE_REG16(GP_RASTER_MODE, 0x10C6);
927    WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
928
929    /* REPEAT UNTIL FINISHED WITH RECTANGLE */
930    /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
931    /* Hardware does not split the operations, so software must do it to */
932    /* avoid large scanlines that would overflow the BLT buffers. */
933
934    while (width > 0) {
935        /* CHECK WIDTH OF CURRENT SECTION */
936
937        if (width > buffer_width)
938            section = buffer_width;
939        else
940            section = width;
941
942        /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
943
944        GFX_WAIT_PENDING;
945        WRITE_REG16(GP_SRC_YCOOR, srcy);
946        WRITE_REG16(GP_DST_YCOOR, dsty);
947        WRITE_REG16(GP_WIDTH, section);
948
949        /* CHECK X DIRECTION */
950        /* Again, this must be done in software, and can be removed if the */
951        /* display driver knows that the BLT buffers will always be large  */
952        /* enough to contain an entire scanline of a screen to screen BLT. */
953
954        if (dstx > srcx) {
955            /* NEGATIVE X DIRECTION */
956            /* Still positive X direction within the section. */
957
958            srcx -= section;
959            dstx -= section;
960            WRITE_REG16(GP_SRC_XCOOR, srcx);
961            WRITE_REG16(GP_DST_XCOOR, dstx);
962            WRITE_REG16(GP_BLIT_MODE, blit_mode);
963        }
964        else {
965            /* POSITIVE X DIRECTION */
966
967            WRITE_REG16(GP_SRC_XCOOR, srcx);
968            WRITE_REG16(GP_DST_XCOOR, dstx);
969            WRITE_REG16(GP_BLIT_MODE, blit_mode);
970            dstx += section;
971            srcx += section;
972        }
973        width -= section;
974    }
975}
976
977/*
978 *----------------------------------------------------------------------------
979 * COLOR BITMAP TO SCREEN BLT
980 *
981 * This routine transfers color bitmap data to the screen.  For most cases,
982 * when the ROP is SRCCOPY, it may be faster to write a separate routine that
983 * copies the data to the frame buffer directly.  This routine should be
984 * used when the ROP requires destination data.
985 *
986 * Transparency is handled by another routine.
987 *
988 *      SRCX            X offset within source bitmap
989 *      SRCY            Y offset within source bitmap
990 *      DSTX            screen X position to render data
991 *      DSTY            screen Y position to render data
992 *      WIDTH           width of rectangle, in pixels
993 *      HEIGHT          height of rectangle, in scanlines
994 *      *DATA           pointer to bitmap data
995 *      PITCH           pitch of bitmap data (bytes between scanlines)
996 *----------------------------------------------------------------------------
997 */
998
999#if GFX_2DACCEL_DYNAMIC
1000void
1001gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1002                               unsigned short dstx, unsigned short dsty,
1003                               unsigned short width, unsigned short height,
1004                               unsigned char *data, long pitch)
1005#else
1006void
1007gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1008                               unsigned short dstx, unsigned short dsty,
1009                               unsigned short width, unsigned short height,
1010                               unsigned char *data, long pitch)
1011#endif
1012{
1013    unsigned short section, buffer_width;
1014    unsigned short blit_mode = BM_READ_SRC_BB0;
1015    unsigned short temp_height;
1016    unsigned long dword_bytes_needed, bytes_extra;
1017    unsigned long bpp_shift;
1018    long array_offset;
1019
1020    /* CHECK SIZE OF BLT BUFFER */
1021
1022    buffer_width = GFXbufferWidthPixels;
1023
1024    /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
1025    /* If no destination data, we have twice the room for  */
1026    /* source data.                                        */
1027
1028    if (GFXusesDstData)
1029        blit_mode |= BM_READ_DST_FB1;
1030    else
1031        buffer_width <<= 1;
1032
1033    /* SET THE SCRATCHPAD BASE */
1034
1035    SET_SCRATCH_BASE(GFXbb0Base);
1036
1037    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS                */
1038    /* Write the registers that do not change for each section. */
1039
1040    GFX_WAIT_PENDING;
1041    WRITE_REG16(GP_HEIGHT, 1);
1042
1043    bpp_shift = (GFXbpp + 7) >> 4;
1044
1045    while (width > 0) {
1046        if (width > buffer_width)
1047            section = buffer_width;
1048        else
1049            section = width;
1050
1051        dword_bytes_needed = (section << bpp_shift) & ~3l;
1052        bytes_extra = (section << bpp_shift) & 3l;
1053
1054        temp_height = height;
1055
1056        /* WRITE THE REGISTERS FOR EACH SECTION                          */
1057        /* The GX hardware will auto-increment the Y coordinate, meaning */
1058        /* that we don't have to.                                        */
1059
1060        WRITE_REG16(GP_WIDTH, section);
1061        WRITE_REG16(GP_DST_XCOOR, dstx);
1062        WRITE_REG16(GP_DST_YCOOR, dsty);
1063
1064        /* CALCULATE THE BITMAP OFFSET */
1065
1066        array_offset =
1067            (unsigned long) srcy *(long) pitch + ((long) srcx << bpp_shift);
1068
1069        while (temp_height--) {
1070            GFX_WAIT_PIPELINE;
1071
1072            /* WRITE ALL DATA TO THE BLT BUFFERS */
1073            /* The WRITE_SCRATCH_STRING macro assumes that the data begins
1074             * at the scratchpad offset set by the SET_SCRATCH_BASE macro.
1075             * */
1076
1077            WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
1078                                 array_offset);
1079            WRITE_REG16(GP_BLIT_MODE, blit_mode);
1080
1081            array_offset += pitch;
1082        }
1083
1084        width -= section;
1085        srcx += section;
1086        dstx += section;
1087    }
1088}
1089
1090/*
1091 *----------------------------------------------------------------------------
1092 * COLOR BITMAP TO SCREEN TRANSPARENT BLT
1093 *
1094 * This routine transfers color bitmap data to the screen with transparency.
1095 * The transparent color is specified.  The only supported ROP is SRCCOPY,
1096 * meaning that transparency cannot be applied if the ROP requires
1097 * destination data (this is a hardware restriction).
1098 *
1099 *      SRCX            X offset within source bitmap
1100 *      SRCY            Y offset within source bitmap
1101 *      DSTX            screen X position to render data
1102 *      DSTY            screen Y position to render data
1103 *      WIDTH           width of rectangle, in pixels
1104 *      HEIGHT          height of rectangle, in scanlines
1105 *      *DATA           pointer to bitmap data
1106 *      PITCH           pitch of bitmap data (bytes between scanlines)
1107 *      COLOR           transparent color
1108 *----------------------------------------------------------------------------
1109 */
1110#if GFX_2DACCEL_DYNAMIC
1111void
1112gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
1113                                unsigned short dstx, unsigned short dsty,
1114                                unsigned short width, unsigned short height,
1115                                unsigned char *data, long pitch,
1116                                unsigned long color)
1117#else
1118void
1119gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
1120                                unsigned short dstx, unsigned short dsty,
1121                                unsigned short width, unsigned short height,
1122                                unsigned char *data, long pitch,
1123                                unsigned long color)
1124#endif
1125{
1126    unsigned short section, buffer_width;
1127    unsigned short temp_height;
1128    unsigned long dword_bytes_needed, bytes_extra;
1129    unsigned long bpp_shift;
1130    long array_offset;
1131
1132    /* CHECK SIZE OF BLT BUFFER */
1133
1134    buffer_width = GFXbufferWidthPixels;
1135
1136    /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
1137
1138    if (GFXbpp == 8) {
1139        color &= 0x00FF;
1140        color |= (color << 8);
1141    }
1142    color = (color & 0x0000FFFF) | (color << 16);
1143
1144    /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
1145    /* Need to make sure any previous BLT using BB1 is complete. */
1146    /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
1147
1148    GFX_WAIT_PIPELINE;
1149    GFX_WAIT_PENDING;
1150    WRITE_SCRATCH32(GFXbb1Base, color);
1151
1152    /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
1153    /* Already know graphics pipeline is idle. */
1154    /* Only need to latch data into the holding registers for the current */
1155    /* data from BB1.  A 1 pixel wide BLT will suffice. */
1156
1157    WRITE_REG32(GP_DST_XCOOR, 0);
1158    WRITE_REG32(GP_SRC_XCOOR, 0);
1159    WRITE_REG32(GP_WIDTH, 0x00010001);
1160    WRITE_REG16(GP_RASTER_MODE, 0x00CC);
1161    WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
1162
1163    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1164    /* Write the registers that do not change for each section. */
1165
1166    GFX_WAIT_PENDING;
1167    WRITE_REG16(GP_HEIGHT, 1);
1168    WRITE_REG16(GP_RASTER_MODE, 0x10C6);
1169    WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
1170
1171    bpp_shift = (GFXbpp + 7) >> 4;
1172
1173    /* SET THE SCRATCHPAD BASE */
1174
1175    SET_SCRATCH_BASE(GFXbb0Base);
1176
1177    while (width > 0) {
1178        if (width > buffer_width)
1179            section = buffer_width;
1180        else
1181            section = width;
1182
1183        dword_bytes_needed = (section << bpp_shift) & ~3l;
1184        bytes_extra = (section << bpp_shift) & 3l;
1185
1186        temp_height = height;
1187
1188        /* WRITE THE REGISTERS FOR EACH SECTION                          */
1189        /* The GX hardware will auto-increment the Y coordinate, meaning */
1190        /* that we don't have to.                                        */
1191
1192        WRITE_REG16(GP_WIDTH, section);
1193        WRITE_REG16(GP_DST_XCOOR, dstx);
1194        WRITE_REG16(GP_DST_YCOOR, dsty);
1195
1196        /* CALCULATE THE BITMAP OFFSET */
1197
1198        array_offset =
1199            (unsigned long) srcy *(long) pitch + ((long) srcx << bpp_shift);
1200
1201        while (temp_height--) {
1202            GFX_WAIT_PIPELINE;
1203
1204            /* WRITE ALL DATA TO THE BLT BUFFERS */
1205            /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
1206            /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
1207
1208            WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
1209                                 array_offset);
1210            WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0);
1211
1212            array_offset += pitch;
1213        }
1214
1215        width -= section;
1216        srcx += section;
1217        dstx += section;
1218    }
1219}
1220
1221/*
1222 *----------------------------------------------------------------------------
1223 * MONOCHROME BITMAP TO SCREEN BLT
1224 *
1225 * This routine transfers monochrome bitmap data to the screen.
1226 *
1227 *      SRCX            X offset within source bitmap
1228 *      SRCY            Y offset within source bitmap
1229 *      DSTX            screen X position to render data
1230 *      DSTY            screen Y position to render data
1231 *      WIDTH           width of rectangle, in pixels
1232 *      HEIGHT          height of rectangle, in scanlines
1233 *      *DATA           pointer to bitmap data
1234 *      PITCH           pitch of bitmap data (bytes between scanlines)
1235 *----------------------------------------------------------------------------
1236 */
1237#if GFX_2DACCEL_DYNAMIC
1238void
1239gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1240                              unsigned short dstx, unsigned short dsty,
1241                              unsigned short width, unsigned short height,
1242                              unsigned char *data, short pitch)
1243#else
1244void
1245gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
1246                              unsigned short dstx, unsigned short dsty,
1247                              unsigned short width, unsigned short height,
1248                              unsigned char *data, short pitch)
1249#endif
1250{
1251    unsigned short section, buffer_width;
1252    unsigned short blit_mode = BM_READ_SRC_BB0 | BM_SOURCE_EXPAND;
1253    unsigned short temp_height;
1254    unsigned long dword_bytes_needed, bytes_extra;
1255    long array_offset;
1256
1257    /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA        */
1258    /* If no destination data, the source data will always fit.   */
1259    /* So, in that event we will set the buffer width to a        */
1260    /* fictitiously large value such that the BLT is never split. */
1261
1262    if (GFXusesDstData) {
1263        buffer_width = GFXbufferWidthPixels;
1264        blit_mode |= BM_READ_DST_FB1;
1265    }
1266    else
1267        buffer_width = 3200;
1268
1269    /* CHECK IF DATA ALREADY IN BLIT BUFFER */
1270    /* If the pointer is NULL, data for the full BLT is already there */
1271    /* WARNING: This could cause problems if destination data is */
1272    /* involved and it overflows the BLT buffer.  Need to remove */
1273    /* this option and change the drivers to use a temporary buffer. */
1274
1275    if (!data) {
1276        GFX_WAIT_PENDING;
1277        WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
1278        WRITE_REG16(GP_DST_XCOOR, dstx);
1279        WRITE_REG16(GP_DST_YCOOR, dsty);
1280        WRITE_REG16(GP_WIDTH, width);
1281        WRITE_REG16(GP_HEIGHT, height);
1282        WRITE_REG16(GP_BLIT_MODE, blit_mode);
1283        return;
1284    }
1285
1286    /* SET THE SCRATCHPAD BASE */
1287
1288    SET_SCRATCH_BASE(GFXbb0Base);
1289
1290    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1291    /* Write the registers that do not change for each section. */
1292
1293    GFX_WAIT_PENDING;
1294    WRITE_REG16(GP_HEIGHT, 1);
1295
1296    while (width > 0) {
1297        if (width > buffer_width)
1298            section = buffer_width;
1299        else
1300            section = width;
1301
1302        /* CALCULATE BYTES NEEDED */
1303        /* Add 1 for possible alignment issues. */
1304
1305        dword_bytes_needed = ((section + 7 + (srcx & 7)) >> 3) & ~3l;
1306        bytes_extra = ((section + 7 + (srcx & 7)) >> 3) & 3l;
1307
1308        temp_height = height;
1309
1310        /* WRITE THE REGISTERS FOR EACH SECTION                          */
1311        /* The GX hardware will auto-increment the Y coordinate, meaning */
1312        /* that we don't have to.                                        */
1313
1314        WRITE_REG16(GP_WIDTH, section);
1315        WRITE_REG16(GP_DST_XCOOR, dstx);
1316        WRITE_REG16(GP_DST_YCOOR, dsty);
1317        WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
1318
1319        /* CALCULATE THE BITMAP OFFSET */
1320
1321        array_offset = (unsigned long) srcy *(long) pitch + ((long) srcx >> 3);
1322
1323        while (temp_height--) {
1324            GFX_WAIT_PIPELINE;
1325
1326            /* WRITE ALL DATA TO THE BLT BUFFERS */
1327            /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
1328            /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
1329
1330            WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
1331                                 array_offset);
1332            WRITE_REG16(GP_BLIT_MODE, blit_mode);
1333
1334            array_offset += pitch;
1335        }
1336
1337        width -= section;
1338        srcx += section;
1339        dstx += section;
1340    }
1341}
1342
1343/*
1344 *----------------------------------------------------------------------------
1345 * MONOCHROME TEXT BLT
1346 *
1347 * This routine transfers contiguous monochrome text data to the screen.
1348 *
1349 *      DSTX            screen X position to render data
1350 *      DSTY            screen Y position to render data
1351 *      WIDTH           width of rectangle, in pixels
1352 *      HEIGHT          height of rectangle, in scanlines
1353 *      *DATA           pointer to bitmap data
1354 *----------------------------------------------------------------------------
1355 */
1356#if GFX_2DACCEL_DYNAMIC
1357void
1358gu1_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
1359             unsigned short height, unsigned char *data)
1360#else
1361void
1362gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
1363             unsigned short height, unsigned char *data)
1364#endif
1365{
1366    unsigned long dword_bytes_needed, bytes_extra;
1367    long pitch, buffer_bytes, data_bytes;
1368
1369    /* CALCULATE DATA SIZE */
1370
1371    pitch = (width + 7) >> 3;
1372    data_bytes = (long) height *pitch;
1373
1374    /* CHECK FOR SIMPLE CASE */
1375    /* This routine is designed to render a source copy text glyph.  If
1376     * destination data is required or the source data will not fit, we will
1377     * punt the operation to the more versatile (and slow) mono bitmap routine
1378     * */
1379
1380    if (GFXbpp > 8)
1381        buffer_bytes = GFXbufferWidthPixels << 1;
1382    else
1383        buffer_bytes = GFXbufferWidthPixels;
1384
1385    if (GFXusesDstData || data_bytes > buffer_bytes) {
1386        gfx_mono_bitmap_to_screen_blt(0, 0, dstx, dsty, width, height, data,
1387                                      (short) pitch);
1388        return;
1389    }
1390
1391    /* SET THE SCRATCHPAD BASE */
1392
1393    SET_SCRATCH_BASE(GFXbb0Base);
1394
1395    /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
1396
1397    dword_bytes_needed = data_bytes & ~3l;
1398    bytes_extra = data_bytes & 3l;
1399
1400    GFX_WAIT_PENDING;
1401    WRITE_REG16(GP_HEIGHT, height);
1402    WRITE_REG16(GP_WIDTH, width);
1403    WRITE_REG16(GP_DST_XCOOR, dstx);
1404    WRITE_REG16(GP_DST_YCOOR, dsty);
1405    WRITE_REG16(GP_SRC_XCOOR, 0);
1406
1407    /* WRITE ALL DATA TO THE BLT BUFFERS */
1408    /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
1409    /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
1410
1411    GFX_WAIT_PIPELINE;
1412
1413    WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 0);
1414    WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_SOURCE_TEXT);
1415}
1416
1417/*
1418 *----------------------------------------------------------------------------
1419 * BRESENHAM LINE
1420 *
1421 * This routine draws a vector using the specified Bresenham parameters.
1422 * Currently this file does not support a routine that accepts the two
1423 * endpoints of a vector and calculates the Bresenham parameters.  If it
1424 * ever does, this routine is still required for vectors that have been
1425 * clipped.
1426 *
1427 *      X               screen X position to start vector
1428 *      Y               screen Y position to start vector
1429 *      LENGTH          length of the vector, in pixels
1430 *      INITERR         Bresenham initial error term
1431 *      AXIALERR        Bresenham axial error term
1432 *      DIAGERR         Bresenham diagonal error term
1433 *      FLAGS           VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC
1434 *----------------------------------------------------------------------------
1435 */
1436#if GFX_2DACCEL_DYNAMIC
1437void
1438gu1_bresenham_line(unsigned short x, unsigned short y,
1439                   unsigned short length, unsigned short initerr,
1440                   unsigned short axialerr, unsigned short diagerr,
1441                   unsigned short flags)
1442#else
1443void
1444gfx_bresenham_line(unsigned short x, unsigned short y,
1445                   unsigned short length, unsigned short initerr,
1446                   unsigned short axialerr, unsigned short diagerr,
1447                   unsigned short flags)
1448#endif
1449{
1450    unsigned short vector_mode = flags;
1451
1452    if (GFXusesDstData)
1453        vector_mode |= VM_READ_DST_FB;
1454
1455    /* CHECK NULL LENGTH */
1456
1457    if (!length)
1458        return;
1459
1460    /* LOAD THE REGISTERS FOR THE VECTOR */
1461
1462    GFX_WAIT_PENDING;
1463    WRITE_REG16(GP_DST_XCOOR, x);
1464    WRITE_REG16(GP_DST_YCOOR, y);
1465    WRITE_REG16(GP_VECTOR_LENGTH, length);
1466    WRITE_REG16(GP_INIT_ERROR, initerr);
1467    WRITE_REG16(GP_AXIAL_ERROR, axialerr);
1468    WRITE_REG16(GP_DIAG_ERROR, diagerr);
1469    WRITE_REG16(GP_VECTOR_MODE, vector_mode);
1470}
1471
1472/*---------------------------------------------------------------------------
1473 * GFX_WAIT_UNTIL_IDLE
1474 *
1475 * This routine waits until the graphics engine is idle.  This is required
1476 * before allowing direct access to the frame buffer.
1477 *---------------------------------------------------------------------------
1478 */
1479#if GFX_2DACCEL_DYNAMIC
1480void
1481gu1_wait_until_idle(void)
1482#else
1483void
1484gfx_wait_until_idle(void)
1485#endif
1486{
1487    GFX_WAIT_BUSY;
1488}
1489
1490/*---------------------------------------------------------------------------
1491 * GFX_TEST_BLT_PENDING
1492 *
1493 * This routine returns 1 if a BLT is pending, meaning that a call to
1494 * perform a rendering operation would stall.  Otherwise it returns 0.
1495 * It is used by Darwin during random testing to only start a BLT
1496 * operation when it knows the Durango routines won't spin on graphics
1497 * (so Darwin can continue to do frame buffer reads and writes).
1498 *---------------------------------------------------------------------------
1499 */
1500#if GFX_2DACCEL_DYNAMIC
1501int
1502gu1_test_blt_pending(void)
1503#else
1504int
1505gfx_test_blt_pending(void)
1506#endif
1507{
1508    if (READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING)
1509        return (1);
1510    else
1511        return (0);
1512}
1513
1514/*---------------------------------------------------------------------------
1515 * BLT BUFFERS!!!!!
1516 *---------------------------------------------------------------------------
1517 */
1518
1519/* THE BOOT CODE MUST SET THE BLT BUFFER BASES USING THE "CPU_WRITE" */
1520/* INSTRUCTION TO ONE OF THE FOLLOWING VALUES: */
1521
1522#define BB0_BASE_2K		0x800
1523#define BB1_BASE_2K		0xB30
1524#define BB0_BASE_3K		0x400
1525#define BB1_BASE_3K		0x930
1526
1527/*---------------------------------------------------------------------------
1528 * gu1_detect_blt_buffer_base
1529 *
1530 * This detection is hidden from the driver by being called from the
1531 * "gfx_set_bpp" routine.
1532 *
1533 * This is fairly ugly for the following reasons:
1534 *
1535 * - It is the boot code that must set the BLT buffer bases to the
1536 *   appropriate values and load the scratchpad tags.
1537 * - The old drivers would also set the base address values to what they
1538 *   knew they should be for the 2K or 3K scratchpad configuration.
1539 * - Unfortunately, to set the base addresses requires the use of the
1540 *   CPU_WRITE instruction, an instruction specific to GX.
1541 * - Using the CPU_WRITE instruction requires the use of assembly to
1542 *   produce the appropriate op codes.
1543 * - Assembly is something that is avoided in Durango because it is not
1544 *   platform independent.  Some compilers do not support inline assembly.
1545 * - Therefore Durango cannot use the CPU_WRITE instruction.
1546 * - Therefore drivers using Durango must rely on the boot code to set
1547 *   the appropriate values.  Durango uses this routine to check where
1548 *   the base addresses have been set.
1549 * - Unfortunately, it is not as simple as using IO to check for 2K or 3K
1550 *   scratchpad size.  In VSA1, even though the boot code may set it for
1551 *   3K, SoftVGA comes along and resets it to 2K for it's use in text
1552 *   redraws.  It used to be that the display driver would set it back
1553 *   to 3K.
1554 * - So, the Durango code was changed to just always use 2K.
1555 * - But, the XpressROM code sets it for 3K, and the newer versions of
1556 *   SoftVGA do not interfere with that, so then Durango needs to use
1557 *   the 3K values to work properly.
1558 * - Therefore, Durango does somewhat of a kludge by writing to directly
1559 *   to the scratchpad at both the 2K and 3K locations, then performing
1560 *   a unobtrusive BLT that loads data into BB0 (the graphics engine
1561 *   always knows the true base).  After the BLT, Durango looks to see
1562 *   which location changed to know where the base address is.
1563 * - This is a relatively simple way to allow Durango to work on old
1564 *   and new platforms without using theCPU_WRITE instructions.
1565 *
1566 * To summarize, the BLT buffers are one of the most painful aspects of
1567 * the GX graphics unit design, and have been removed from future designs
1568 * (the graphics unit has its own dedicated RAM).  Durango has tried to
1569 * hide the BLT buffer use from the drivers.
1570 *---------------------------------------------------------------------------
1571 */
1572void
1573gu1_detect_blt_buffer_base(void)
1574{
1575    /* ASSUME 2K */
1576
1577    GFXbb0Base = BB0_BASE_2K;
1578    GFXbb1Base = BB1_BASE_2K;
1579
1580    /* CHECK IF SCRATCHPAD IS SET TO 3K OR 4K */
1581    /* Boot code should still set 3K values for 4K. */
1582
1583    if (gfx_gxm_config_read(GXM_CONFIG_GCR) & 0x08) {
1584        /* WRITE DATA TO 3K LOCATION */
1585
1586        GFX_WAIT_BUSY;
1587        WRITE_SCRATCH32(BB0_BASE_3K, 0xFEEDFACE);
1588
1589        /* HAVE THE GRAPHICS UNIT STORE SOMETHING IN BB0 */
1590
1591        WRITE_REG32(GP_DST_XCOOR, 0x00000000);  /* AT (0,0)     */
1592        WRITE_REG32(GP_WIDTH, 0x00010004);      /* 4x1 BLT              */
1593        WRITE_REG16(GP_RASTER_MODE, 0x00AA);    /* KEEP DST     */
1594        WRITE_REG16(GP_BLIT_MODE, BM_READ_DST_FB0);     /* STORE IN BB0 */
1595
1596        /* CHECK 3K LOCATION */
1597        /* Breaks if data happened to be 0xFEEDFACE - unlikely. */
1598
1599        GFX_WAIT_BUSY;
1600        if (READ_SCRATCH32(BB0_BASE_3K) != 0xFEEDFACE) {
1601            GFXbb0Base = BB0_BASE_3K;
1602            GFXbb1Base = BB1_BASE_3K;
1603        }
1604    }
1605}
1606
1607/* END OF FILE */
1608