171d7fec4Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/rndr_gu1.c,v 1.2 2003/01/14 09:34:34 alanh Exp $ */
271d7fec4Smrg/*
371d7fec4Smrg * $Workfile: rndr_gu1.c $
471d7fec4Smrg *
571d7fec4Smrg * This file contains routines to program the 2D acceleration hardware for
671d7fec4Smrg * the first generation graphics unit (GXLV, SC1200).
771d7fec4Smrg *
871d7fec4Smrg *    gfx_set_bpp
971d7fec4Smrg *    gfx_set_solid_pattern
1071d7fec4Smrg *    gfx_set_mono_pattern
1171d7fec4Smrg *    gfx_set_color_pattern
1271d7fec4Smrg *    gfx_set_solid_source
1371d7fec4Smrg *    gfx_set_mono_source
1471d7fec4Smrg *    gfx_set_raster_operation
1571d7fec4Smrg *    gfx_pattern_fill
1671d7fec4Smrg *    gfx_screen_to_screen_blt
1771d7fec4Smrg *    gfx_screen_to_screen_xblt
1871d7fec4Smrg *    gfx_color_bitmap_to_screen_blt
1971d7fec4Smrg *    gfx_color_bitmap_to_screen_xblt
2071d7fec4Smrg *    gfx_mono_bitmap_to_screen_blt
2171d7fec4Smrg *    gfx_bresenham_line
2271d7fec4Smrg *    gfx_wait_until_idle
2371d7fec4Smrg *
2471d7fec4Smrg * NSC_LIC_ALTERNATIVE_PREAMBLE
2571d7fec4Smrg *
2671d7fec4Smrg * Revision 1.0
2771d7fec4Smrg *
2871d7fec4Smrg * National Semiconductor Alternative GPL-BSD License
2971d7fec4Smrg *
3071d7fec4Smrg * National Semiconductor Corporation licenses this software
3171d7fec4Smrg * ("Software"):
3271d7fec4Smrg *
3371d7fec4Smrg *      Durango
3471d7fec4Smrg *
3571d7fec4Smrg * under one of the two following licenses, depending on how the
3671d7fec4Smrg * Software is received by the Licensee.
3771d7fec4Smrg *
3871d7fec4Smrg * If this Software is received as part of the Linux Framebuffer or
3971d7fec4Smrg * other GPL licensed software, then the GPL license designated
4071d7fec4Smrg * NSC_LIC_GPL applies to this Software; in all other circumstances
4171d7fec4Smrg * then the BSD-style license designated NSC_LIC_BSD shall apply.
4271d7fec4Smrg *
4371d7fec4Smrg * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
4471d7fec4Smrg
4571d7fec4Smrg/* NSC_LIC_BSD
4671d7fec4Smrg *
4771d7fec4Smrg * National Semiconductor Corporation Open Source License for Durango
4871d7fec4Smrg *
4971d7fec4Smrg * (BSD License with Export Notice)
5071d7fec4Smrg *
5171d7fec4Smrg * Copyright (c) 1999-2001
5271d7fec4Smrg * National Semiconductor Corporation.
5371d7fec4Smrg * All rights reserved.
5471d7fec4Smrg *
5571d7fec4Smrg * Redistribution and use in source and binary forms, with or without
5671d7fec4Smrg * modification, are permitted provided that the following conditions
5771d7fec4Smrg * are met:
5871d7fec4Smrg *
5971d7fec4Smrg *   * Redistributions of source code must retain the above copyright
6071d7fec4Smrg *     notice, this list of conditions and the following disclaimer.
6171d7fec4Smrg *
6271d7fec4Smrg *   * Redistributions in binary form must reproduce the above
6371d7fec4Smrg *     copyright notice, this list of conditions and the following
6471d7fec4Smrg *     disclaimer in the documentation and/or other materials provided
6571d7fec4Smrg *     with the distribution.
6671d7fec4Smrg *
6771d7fec4Smrg *   * Neither the name of the National Semiconductor Corporation nor
6871d7fec4Smrg *     the names of its contributors may be used to endorse or promote
6971d7fec4Smrg *     products derived from this software without specific prior
7071d7fec4Smrg *     written permission.
7171d7fec4Smrg *
7271d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7371d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7471d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
7571d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
7671d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
7771d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7871d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
7971d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
8071d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
8171d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
8271d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
8371d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
8471d7fec4Smrg * OF SUCH DAMAGE.
8571d7fec4Smrg *
8671d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
8771d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with
8871d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under
8971d7fec4Smrg * CURRENT (2001) U.S. export regulations this software
9071d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or
9171d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
9271d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
9371d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S.
9471d7fec4Smrg * has embargoed goods and services.
9571d7fec4Smrg *
9671d7fec4Smrg * END_NSC_LIC_BSD */
9771d7fec4Smrg
9871d7fec4Smrg/* NSC_LIC_GPL
9971d7fec4Smrg *
10071d7fec4Smrg * National Semiconductor Corporation Gnu General Public License for Durango
10171d7fec4Smrg *
10271d7fec4Smrg * (GPL License with Export Notice)
10371d7fec4Smrg *
10471d7fec4Smrg * Copyright (c) 1999-2001
10571d7fec4Smrg * National Semiconductor Corporation.
10671d7fec4Smrg * All rights reserved.
10771d7fec4Smrg *
10871d7fec4Smrg * Redistribution and use in source and binary forms, with or without
10971d7fec4Smrg * modification, are permitted under the terms of the GNU General
11071d7fec4Smrg * Public License as published by the Free Software Foundation; either
11171d7fec4Smrg * version 2 of the License, or (at your option) any later version
11271d7fec4Smrg *
11371d7fec4Smrg * In addition to the terms of the GNU General Public License, neither
11471d7fec4Smrg * the name of the National Semiconductor Corporation nor the names of
11571d7fec4Smrg * its contributors may be used to endorse or promote products derived
11671d7fec4Smrg * from this software without specific prior written permission.
11771d7fec4Smrg *
11871d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
11971d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12071d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12171d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
12271d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
12371d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12471d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
12571d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
12671d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
12771d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
12871d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
12971d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
13071d7fec4Smrg * OF SUCH DAMAGE. See the GNU General Public License for more details.
13171d7fec4Smrg *
13271d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
13371d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with
13471d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under
13571d7fec4Smrg * CURRENT (2001) U.S. export regulations this software
13671d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or
13771d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
13871d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
13971d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S.
14071d7fec4Smrg * has embargoed goods and services.
14171d7fec4Smrg *
14271d7fec4Smrg * You should have received a copy of the GNU General Public License
14371d7fec4Smrg * along with this file; if not, write to the Free Software Foundation,
14471d7fec4Smrg * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14571d7fec4Smrg *
14671d7fec4Smrg * END_NSC_LIC_GPL */
14771d7fec4Smrg
14871d7fec4Smrgvoid gu1_set_bpp(unsigned short bpp);
14971d7fec4Smrgvoid gu1_set_solid_pattern(unsigned long color);
15071d7fec4Smrgvoid gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
15171d7fec4Smrg			  unsigned long data0, unsigned long data1,
15271d7fec4Smrg			  unsigned char transparency);
15371d7fec4Smrgvoid gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
15471d7fec4Smrg			   unsigned long data0, unsigned long data1,
15571d7fec4Smrg			   unsigned long data2, unsigned long data3,
15671d7fec4Smrg			   unsigned char transparency);
15771d7fec4Smrgvoid gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8);
15871d7fec4Smrgvoid gu1_set_solid_source(unsigned long color);
15971d7fec4Smrgvoid gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
16071d7fec4Smrg			 unsigned short transparent);
16171d7fec4Smrgvoid gu1_set_pattern_flags(unsigned short flags);
16271d7fec4Smrgvoid gu1_set_raster_operation(unsigned char rop);
16371d7fec4Smrgvoid gu1_pattern_fill(unsigned short x, unsigned short y,
16471d7fec4Smrg		      unsigned short width, unsigned short height);
16571d7fec4Smrgvoid gu1_color_pattern_fill(unsigned short x, unsigned short y,
16671d7fec4Smrg			    unsigned short width, unsigned short height,
16771d7fec4Smrg			    unsigned long *pattern);
16871d7fec4Smrgvoid gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
16971d7fec4Smrg			      unsigned short dstx, unsigned short dsty,
17071d7fec4Smrg			      unsigned short width, unsigned short height);
17171d7fec4Smrgvoid gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
17271d7fec4Smrg			       unsigned short dstx, unsigned short dsty,
17371d7fec4Smrg			       unsigned short width, unsigned short height,
17471d7fec4Smrg			       unsigned long color);
17571d7fec4Smrgvoid gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
17671d7fec4Smrg				    unsigned short dstx, unsigned short dsty,
17771d7fec4Smrg				    unsigned short width,
17871d7fec4Smrg				    unsigned short height,
17971d7fec4Smrg				    unsigned char *data, long pitch);
18071d7fec4Smrgvoid gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
18171d7fec4Smrg				     unsigned short dstx, unsigned short dsty,
18271d7fec4Smrg				     unsigned short width,
18371d7fec4Smrg				     unsigned short height,
18471d7fec4Smrg				     unsigned char *data, long pitch,
18571d7fec4Smrg				     unsigned long color);
18671d7fec4Smrgvoid gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
18771d7fec4Smrg				   unsigned short dstx, unsigned short dsty,
18871d7fec4Smrg				   unsigned short width,
18971d7fec4Smrg				   unsigned short height, unsigned char *data,
19071d7fec4Smrg				   short pitch);
19171d7fec4Smrgvoid gu1_text_blt(unsigned short dstx, unsigned short dsty,
19271d7fec4Smrg		  unsigned short width, unsigned short height,
19371d7fec4Smrg		  unsigned char *data);
19471d7fec4Smrgvoid gu1_bresenham_line(unsigned short x, unsigned short y,
19571d7fec4Smrg			unsigned short length, unsigned short initerr,
19671d7fec4Smrg			unsigned short axialerr, unsigned short diagerr,
19771d7fec4Smrg			unsigned short flags);
19871d7fec4Smrgvoid gu1_wait_until_idle(void);
19971d7fec4Smrg
20071d7fec4Smrg#if GFX_NO_IO_IN_WAIT_MACROS
20171d7fec4Smrg#define GFX_WAIT_PENDING while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { ; }
20271d7fec4Smrg#define GFX_WAIT_BUSY while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { ; }
20371d7fec4Smrg#define GFX_WAIT_PIPELINE while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { ; }
20471d7fec4Smrg#else
20571d7fec4Smrg#define GFX_WAIT_PENDING while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { INB (0x80); }
20671d7fec4Smrg#define GFX_WAIT_BUSY while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { INB (0x80); }
20771d7fec4Smrg#define GFX_WAIT_PIPELINE while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { INB (0x80); }
20871d7fec4Smrg#endif
20971d7fec4Smrg
21071d7fec4Smrgvoid gu1_detect_blt_buffer_base(void);
21171d7fec4Smrgint gu1_test_blt_pending(void);
21271d7fec4Smrgvoid gu1_solid_fill(unsigned short x, unsigned short y,
21371d7fec4Smrg		    unsigned short width, unsigned short height,
21471d7fec4Smrg		    unsigned long color);
21571d7fec4Smrg
21671d7fec4Smrg/*---------------------------------------------------------------------------
21771d7fec4Smrg * GFX_SET_BPP
21871d7fec4Smrg *
21971d7fec4Smrg * This routine sets the bits per pixel value in the graphics engine.
22071d7fec4Smrg * It is also stored in a static variable to use in the future calls to
22171d7fec4Smrg * the rendering routines.
22271d7fec4Smrg *---------------------------------------------------------------------------
22371d7fec4Smrg */
22471d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
22571d7fec4Smrgvoid
22671d7fec4Smrggu1_set_bpp(unsigned short bpp)
22771d7fec4Smrg#else
22871d7fec4Smrgvoid
22971d7fec4Smrggfx_set_bpp(unsigned short bpp)
23071d7fec4Smrg#endif
23171d7fec4Smrg{
23271d7fec4Smrg   int control = 0;
23371d7fec4Smrg   unsigned short pitch = gfx_get_display_pitch();
23471d7fec4Smrg
23571d7fec4Smrg   GFXbpp = bpp;
23671d7fec4Smrg
23771d7fec4Smrg   /* DETECT BASE ADDRESSES FOR BLT BUFFERS */
23871d7fec4Smrg   /* Different for 2K or 3K of scratchpad.  Also need to calculate */
23971d7fec4Smrg   /* the number of pixels that can fit in a BLT buffer - need to */
24071d7fec4Smrg   /* subtract 16 for alignment considerations.  The 2K case, for */
24171d7fec4Smrg   /* example, is 816 bytes wide, allowing 800 pixels in 8 BPP, which */
24271d7fec4Smrg   /* means rendering operations won't be split for 800x600. */
24371d7fec4Smrg
24471d7fec4Smrg   gu1_detect_blt_buffer_base();
24571d7fec4Smrg   GFXbufferWidthPixels = GFXbb1Base - GFXbb0Base - 16;
24671d7fec4Smrg   if (bpp > 8) {
24771d7fec4Smrg      /* If 16bpp, divide GFXbufferWidthPixels by 2 */
24871d7fec4Smrg      GFXbufferWidthPixels >>= 1;
24971d7fec4Smrg   }
25071d7fec4Smrg
25171d7fec4Smrg   /* SET THE GRAPHICS CONTROLLER BPP AND PITCH */
25271d7fec4Smrg   if (bpp > 8) {
25371d7fec4Smrg      /* Set the 16bpp bit if necessary */
25471d7fec4Smrg      control = BC_16BPP;
25571d7fec4Smrg   }
25671d7fec4Smrg   if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) {
25771d7fec4Smrg      control |= BC_FB_WIDTH_4096;
25871d7fec4Smrg   } else if (pitch > 1024) {
25971d7fec4Smrg      control |= BC_FB_WIDTH_2048;
26071d7fec4Smrg   }
26171d7fec4Smrg   GFX_WAIT_BUSY;
26271d7fec4Smrg   WRITE_REG32(GP_BLIT_STATUS, control);
26371d7fec4Smrg}
26471d7fec4Smrg
26571d7fec4Smrg/*
26671d7fec4Smrg//---------------------------------------------------------------------------
26771d7fec4Smrg// GFX_SET_SOLID_SOURCE
26871d7fec4Smrg//
26971d7fec4Smrg// This routine is used to specify a solid source color.  For the Xfree96
27071d7fec4Smrg// display driver, the source color is used to specify a planemask and the
27171d7fec4Smrg// ROP is adjusted accordingly.
27271d7fec4Smrg//---------------------------------------------------------------------------
27371d7fec4Smrg*/
27471d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
27571d7fec4Smrgvoid
27671d7fec4Smrggu1_set_solid_source(unsigned long color)
27771d7fec4Smrg#else
27871d7fec4Smrgvoid
27971d7fec4Smrggfx_set_solid_source(unsigned long color)
28071d7fec4Smrg#endif
28171d7fec4Smrg{
28271d7fec4Smrg   /* CLEAR TRANSPARENCY FLAG */
28371d7fec4Smrg
28471d7fec4Smrg   GFXsourceFlags = 0;
28571d7fec4Smrg
28671d7fec4Smrg   /* FORMAT 8 BPP COLOR */
28771d7fec4Smrg   /* GX requires 8BPP color data be duplicated into bits [15:8]. */
28871d7fec4Smrg
28971d7fec4Smrg   if (GFXbpp == 8) {
29071d7fec4Smrg      color &= 0x00FF;
29171d7fec4Smrg      color |= (color << 8);
29271d7fec4Smrg   }
29371d7fec4Smrg
29471d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
29571d7fec4Smrg
29671d7fec4Smrg   GFX_WAIT_PENDING;
29771d7fec4Smrg   WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)color);
29871d7fec4Smrg   WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)color);
29971d7fec4Smrg}
30071d7fec4Smrg
30171d7fec4Smrg/*
30271d7fec4Smrg//---------------------------------------------------------------------------
30371d7fec4Smrg// GFX_SET_MONO_SOURCE
30471d7fec4Smrg//
30571d7fec4Smrg// This routine is used to specify the monochrome source colors.
30671d7fec4Smrg// It must be called *after* loading any pattern data (those routines
30771d7fec4Smrg// clear the source flags).
30871d7fec4Smrg//---------------------------------------------------------------------------
30971d7fec4Smrg*/
31071d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
31171d7fec4Smrgvoid
31271d7fec4Smrggu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
31371d7fec4Smrg		    unsigned short transparent)
31471d7fec4Smrg#else
31571d7fec4Smrgvoid
31671d7fec4Smrggfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
31771d7fec4Smrg		    unsigned short transparent)
31871d7fec4Smrg#endif
31971d7fec4Smrg{
32071d7fec4Smrg   /* SET TRANSPARENCY FLAG */
32171d7fec4Smrg
32271d7fec4Smrg   GFXsourceFlags = transparent ? RM_SRC_TRANSPARENT : 0;
32371d7fec4Smrg
32471d7fec4Smrg   /* FORMAT 8 BPP COLOR */
32571d7fec4Smrg   /* GX requires 8BPP color data be duplicated into bits [15:8]. */
32671d7fec4Smrg
32771d7fec4Smrg   if (GFXbpp == 8) {
32871d7fec4Smrg      bgcolor &= 0x00FF;
32971d7fec4Smrg      bgcolor |= (bgcolor << 8);
33071d7fec4Smrg      fgcolor &= 0x00FF;
33171d7fec4Smrg      fgcolor |= (fgcolor << 8);
33271d7fec4Smrg   }
33371d7fec4Smrg
33471d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */
33571d7fec4Smrg
33671d7fec4Smrg   GFX_WAIT_PENDING;
33771d7fec4Smrg   WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)bgcolor);
33871d7fec4Smrg   WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)fgcolor);
33971d7fec4Smrg}
34071d7fec4Smrg
34171d7fec4Smrg/*
34271d7fec4Smrg//---------------------------------------------------------------------------
34371d7fec4Smrg// GFX_SET_SOLID_PATTERN
34471d7fec4Smrg//
34571d7fec4Smrg// This routine is used to specify a solid pattern color.  It is called
34671d7fec4Smrg// before performing solid rectangle fills or more complicated BLTs that
34771d7fec4Smrg// use a solid pattern color.
34871d7fec4Smrg//
34971d7fec4Smrg// The driver should always call "gfx_load_raster_operation" after a call
35071d7fec4Smrg// to this routine to make sure that the pattern flags are set appropriately.
35171d7fec4Smrg//---------------------------------------------------------------------------
35271d7fec4Smrg*/
35371d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
35471d7fec4Smrgvoid
35571d7fec4Smrggu1_set_solid_pattern(unsigned long color)
35671d7fec4Smrg#else
35771d7fec4Smrgvoid
35871d7fec4Smrggfx_set_solid_pattern(unsigned long color)
35971d7fec4Smrg#endif
36071d7fec4Smrg{
36171d7fec4Smrg   /* CLEAR TRANSPARENCY FLAG */
36271d7fec4Smrg
36371d7fec4Smrg   GFXsourceFlags = 0;
36471d7fec4Smrg
36571d7fec4Smrg   /* SET PATTERN FLAGS */
36671d7fec4Smrg
36771d7fec4Smrg   GFXpatternFlags = 0;
36871d7fec4Smrg
36971d7fec4Smrg   /* FORMAT 8 BPP COLOR */
37071d7fec4Smrg   /* GX requires 8BPP color data be duplicated into bits [15:8]. */
37171d7fec4Smrg
37271d7fec4Smrg   if (GFXbpp == 8) {
37371d7fec4Smrg      color &= 0x00FF;
37471d7fec4Smrg      color |= (color << 8);
37571d7fec4Smrg   }
37671d7fec4Smrg
37771d7fec4Smrg   /* SAVE THE REFORMATTED COLOR FOR LATER */
37871d7fec4Smrg   /* Used to call the "GFX_solid_fill" routine for special cases. */
37971d7fec4Smrg
38071d7fec4Smrg   GFXsavedColor = color;
38171d7fec4Smrg
38271d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
38371d7fec4Smrg
38471d7fec4Smrg   GFX_WAIT_PENDING;
38571d7fec4Smrg   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color);
38671d7fec4Smrg}
38771d7fec4Smrg
38871d7fec4Smrg/*
38971d7fec4Smrg//---------------------------------------------------------------------------
39071d7fec4Smrg// GFX_SET_MONO_PATTERN
39171d7fec4Smrg//
39271d7fec4Smrg// This routine is used to specify a monochrome pattern.
39371d7fec4Smrg//---------------------------------------------------------------------------
39471d7fec4Smrg*/
39571d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
39671d7fec4Smrgvoid
39771d7fec4Smrggu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
39871d7fec4Smrg		     unsigned long data0, unsigned long data1,
39971d7fec4Smrg		     unsigned char transparent)
40071d7fec4Smrg#else
40171d7fec4Smrgvoid
40271d7fec4Smrggfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
40371d7fec4Smrg		     unsigned long data0, unsigned long data1,
40471d7fec4Smrg		     unsigned char transparent)
40571d7fec4Smrg#endif
40671d7fec4Smrg{
40771d7fec4Smrg   /* CLEAR TRANSPARENCY FLAG */
40871d7fec4Smrg
40971d7fec4Smrg   GFXsourceFlags = 0;
41071d7fec4Smrg
41171d7fec4Smrg   /* SET PATTERN FLAGS */
41271d7fec4Smrg
41371d7fec4Smrg   GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
41471d7fec4Smrg	 RM_PAT_MONO;
41571d7fec4Smrg
41671d7fec4Smrg   /* FORMAT 8 BPP COLOR */
41771d7fec4Smrg   /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
41871d7fec4Smrg
41971d7fec4Smrg   if (GFXbpp == 8) {
42071d7fec4Smrg      bgcolor &= 0x00FF;
42171d7fec4Smrg      bgcolor |= (bgcolor << 8);
42271d7fec4Smrg      fgcolor &= 0x00FF;
42371d7fec4Smrg      fgcolor |= (fgcolor << 8);
42471d7fec4Smrg   }
42571d7fec4Smrg
42671d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
42771d7fec4Smrg
42871d7fec4Smrg   GFX_WAIT_PENDING;
42971d7fec4Smrg   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor);
43071d7fec4Smrg   WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor);
43171d7fec4Smrg   WRITE_REG32(GP_PAT_DATA_0, data0);
43271d7fec4Smrg   WRITE_REG32(GP_PAT_DATA_1, data1);
43371d7fec4Smrg}
43471d7fec4Smrg
43571d7fec4Smrg/*
43671d7fec4Smrg//---------------------------------------------------------------------------
43771d7fec4Smrg// GFX_SET_COLOR_PATTERN
43871d7fec4Smrg//
43971d7fec4Smrg// This routine is used to specify a color pattern.
44071d7fec4Smrg//---------------------------------------------------------------------------
44171d7fec4Smrg*/
44271d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
44371d7fec4Smrgvoid
44471d7fec4Smrggu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
44571d7fec4Smrg		      unsigned long data0, unsigned long data1,
44671d7fec4Smrg		      unsigned long data2, unsigned long data3,
44771d7fec4Smrg		      unsigned char transparent)
44871d7fec4Smrg#else
44971d7fec4Smrgvoid
45071d7fec4Smrggfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor,
45171d7fec4Smrg		      unsigned long data0, unsigned long data1,
45271d7fec4Smrg		      unsigned long data2, unsigned long data3,
45371d7fec4Smrg		      unsigned char transparent)
45471d7fec4Smrg#endif
45571d7fec4Smrg{
45671d7fec4Smrg   /* CLEAR TRANSPARENCY FLAG */
45771d7fec4Smrg
45871d7fec4Smrg   GFXsourceFlags = 0;
45971d7fec4Smrg
46071d7fec4Smrg   /* SET PATTERN FLAGS */
46171d7fec4Smrg
46271d7fec4Smrg   GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT :
46371d7fec4Smrg	 RM_PAT_MONO;
46471d7fec4Smrg
46571d7fec4Smrg   GFXpatternFlags |= RM_PAT_COLOR;
46671d7fec4Smrg   /* FORMAT 8 BPP COLOR */
46771d7fec4Smrg   /* GXm requires 8BPP color data be duplicated into bits [15:8]. */
46871d7fec4Smrg
46971d7fec4Smrg   if (GFXbpp == 8) {
47071d7fec4Smrg      bgcolor &= 0x00FF;
47171d7fec4Smrg      bgcolor |= (bgcolor << 8);
47271d7fec4Smrg      fgcolor &= 0x00FF;
47371d7fec4Smrg      fgcolor |= (fgcolor << 8);
47471d7fec4Smrg   }
47571d7fec4Smrg
47671d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
47771d7fec4Smrg
47871d7fec4Smrg   GFX_WAIT_PENDING;
47971d7fec4Smrg   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor);
48071d7fec4Smrg   WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor);
48171d7fec4Smrg   WRITE_REG32(GP_PAT_DATA_0, data0);
48271d7fec4Smrg   WRITE_REG32(GP_PAT_DATA_1, data1);
48371d7fec4Smrg   if (GFXbpp > 8) {
48471d7fec4Smrg      WRITE_REG32(GP_PAT_DATA_2, data2);
48571d7fec4Smrg      WRITE_REG32(GP_PAT_DATA_3, data3);
48671d7fec4Smrg   }
48771d7fec4Smrg}
48871d7fec4Smrg
48971d7fec4Smrg/*
49071d7fec4Smrg//---------------------------------------------------------------------------
49171d7fec4Smrg// GFX_LOAD_COLOR_PATTERN_LINE
49271d7fec4Smrg//
49371d7fec4Smrg// This routine is used to load a single line of a 8x8 color pattern.
49471d7fec4Smrg//---------------------------------------------------------------------------
49571d7fec4Smrg*/
49671d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
49771d7fec4Smrgvoid
49871d7fec4Smrggu1_load_color_pattern_line(short y, unsigned long *pattern_8x8)
49971d7fec4Smrg#else
50071d7fec4Smrgvoid
50171d7fec4Smrggfx_load_color_pattern_line(short y, unsigned long *pattern_8x8)
50271d7fec4Smrg#endif
50371d7fec4Smrg{
50471d7fec4Smrg   /* CLEAR TRANSPARENCY FLAG */
50571d7fec4Smrg
50671d7fec4Smrg   GFXsourceFlags = 0;
50771d7fec4Smrg
50871d7fec4Smrg   /* SET PATTERN FLAGS */
50971d7fec4Smrg
51071d7fec4Smrg   GFXpatternFlags = RM_PAT_COLOR;
51171d7fec4Smrg
51271d7fec4Smrg   y &= 7;
51371d7fec4Smrg
51471d7fec4Smrg   if (GFXbpp > 8)
51571d7fec4Smrg      pattern_8x8 += (y << 2);
51671d7fec4Smrg   else
51771d7fec4Smrg      pattern_8x8 += (y << 1);
51871d7fec4Smrg
51971d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */
52071d7fec4Smrg
52171d7fec4Smrg   GFX_WAIT_PENDING;
52271d7fec4Smrg   WRITE_REG32(GP_PAT_DATA_0, pattern_8x8[0]);
52371d7fec4Smrg   WRITE_REG32(GP_PAT_DATA_1, pattern_8x8[1]);
52471d7fec4Smrg   if (GFXbpp > 8) {
52571d7fec4Smrg      WRITE_REG32(GP_PAT_DATA_2, pattern_8x8[2]);
52671d7fec4Smrg      WRITE_REG32(GP_PAT_DATA_3, pattern_8x8[3]);
52771d7fec4Smrg   }
52871d7fec4Smrg}
52971d7fec4Smrg
53071d7fec4Smrg/*
53171d7fec4Smrg//---------------------------------------------------------------------------
53271d7fec4Smrg// GFX_SET_RASTER_OPERATION
53371d7fec4Smrg//
53471d7fec4Smrg// This routine loads the specified raster operation.  It sets the pattern
53571d7fec4Smrg// flags appropriately.
53671d7fec4Smrg//---------------------------------------------------------------------------
53771d7fec4Smrg*/
53871d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
53971d7fec4Smrgvoid
54071d7fec4Smrggu1_set_raster_operation(unsigned char rop)
54171d7fec4Smrg#else
54271d7fec4Smrgvoid
54371d7fec4Smrggfx_set_raster_operation(unsigned char rop)
54471d7fec4Smrg#endif
54571d7fec4Smrg{
54671d7fec4Smrg   unsigned short rop16;
54771d7fec4Smrg
54871d7fec4Smrg   /* GENERATE 16-BIT VERSION OF ROP WITH PATTERN FLAGS */
54971d7fec4Smrg
55071d7fec4Smrg   rop16 = (unsigned short)rop | GFXpatternFlags;
55171d7fec4Smrg   if ((rop & 0x33) ^ ((rop >> 2) & 0x33))
55271d7fec4Smrg      rop16 |= GFXsourceFlags;
55371d7fec4Smrg
55471d7fec4Smrg   /* SAVE ROP FOR LATER COMPARISONS */
55571d7fec4Smrg   /* Need to have the pattern flags included */
55671d7fec4Smrg
55771d7fec4Smrg   GFXsavedRop = rop16;
55871d7fec4Smrg
55971d7fec4Smrg   /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */
56071d7fec4Smrg   /* True if even bits (0:2:4:6) do not equal the correspinding */
56171d7fec4Smrg   /* even bits (1:3:5:7). */
56271d7fec4Smrg
56371d7fec4Smrg   GFXusesDstData = ((rop & 0x55) ^ ((rop >> 1) & 0x55));
56471d7fec4Smrg
56571d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */
56671d7fec4Smrg   /* Only one operation can be pending at a time. */
56771d7fec4Smrg
56871d7fec4Smrg   GFX_WAIT_PENDING;
56971d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE, rop16);
57071d7fec4Smrg}
57171d7fec4Smrg
57271d7fec4Smrg/*
57371d7fec4Smrg//---------------------------------------------------------------------------
57471d7fec4Smrg// GFX_SOLID_FILL
57571d7fec4Smrg//
57671d7fec4Smrg// This routine MUST be used when performing a solid rectangle fill with
57771d7fec4Smrg// the ROPs of PATCOPY (0xF0), BLACKNESS (0x00), WHITENESS (0xFF), or
57871d7fec4Smrg// PATINVERT (0x0F).  There is a bug in GXm for these cases that requires a
57971d7fec4Smrg// workaround.
58071d7fec4Smrg//
58171d7fec4Smrg// For BLACKNESS (ROP = 0x00), set the color to 0x0000.
58271d7fec4Smrg// For WHITENESS (ROP = 0xFF), set the color to 0xFFFF.
58371d7fec4Smrg// For PATINVERT (ROP = 0x0F), invert the desired color.
58471d7fec4Smrg//
58571d7fec4Smrg//      X               screen X position (left)
58671d7fec4Smrg//      Y               screen Y position (top)
58771d7fec4Smrg//      WIDTH           width of rectangle, in pixels
58871d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
58971d7fec4Smrg//      COLOR           fill color
59071d7fec4Smrg//
59171d7fec4Smrg// THIS ROUTINE SHOULD NOT BE DIRECTLY CALLED FROM THE DRIVER.  The driver
59271d7fec4Smrg// should always use GFX_pattern_fill and let that routine call this one
59371d7fec4Smrg// when approipriate.  This is to hide quirks specific to MediaGX hardware.
59471d7fec4Smrg//---------------------------------------------------------------------------
59571d7fec4Smrg*/
59671d7fec4Smrgvoid
59771d7fec4Smrggu1_solid_fill(unsigned short x, unsigned short y,
59871d7fec4Smrg	       unsigned short width, unsigned short height,
59971d7fec4Smrg	       unsigned long color)
60071d7fec4Smrg{
60171d7fec4Smrg   unsigned short section;
60271d7fec4Smrg
60371d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
60471d7fec4Smrg   /* Only one operation can be pending at a time. */
60571d7fec4Smrg
60671d7fec4Smrg   GFX_WAIT_PENDING;
60771d7fec4Smrg
60871d7fec4Smrg   /* SET REGISTERS TO DRAW RECTANGLE */
60971d7fec4Smrg
61071d7fec4Smrg   WRITE_REG16(GP_DST_XCOOR, x);
61171d7fec4Smrg   WRITE_REG16(GP_DST_YCOOR, y);
61271d7fec4Smrg   WRITE_REG16(GP_HEIGHT, height);
61371d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE, 0x00F0);	/* PATCOPY */
61471d7fec4Smrg   WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color);
61571d7fec4Smrg
61671d7fec4Smrg   /* CHECK WIDTH FOR GX BUG WORKAROUND */
61771d7fec4Smrg
61871d7fec4Smrg   if (width <= 16) {
61971d7fec4Smrg      /* OK TO DRAW SMALL RECTANGLE IN ONE PASS */
62071d7fec4Smrg
62171d7fec4Smrg      WRITE_REG16(GP_WIDTH, width);
62271d7fec4Smrg      WRITE_REG16(GP_BLIT_MODE, 0);
62371d7fec4Smrg   } else {
62471d7fec4Smrg      /* DRAW FIRST PART OF RECTANGLE */
62571d7fec4Smrg      /* Get to a 16 pixel boundary. */
62671d7fec4Smrg
62771d7fec4Smrg      section = 0x10 - (x & 0x0F);
62871d7fec4Smrg      WRITE_REG16(GP_WIDTH, section);
62971d7fec4Smrg      WRITE_REG16(GP_BLIT_MODE, 0);
63071d7fec4Smrg
63171d7fec4Smrg      /* POLL UNTIL ABLE TO LOAD THE SECOND RECTANGLE */
63271d7fec4Smrg
63371d7fec4Smrg      GFX_WAIT_PENDING;
63471d7fec4Smrg      WRITE_REG16(GP_DST_XCOOR, x + section);
63571d7fec4Smrg      WRITE_REG16(GP_DST_YCOOR, y);
63671d7fec4Smrg      WRITE_REG16(GP_WIDTH, width - section);
63771d7fec4Smrg      WRITE_REG16(GP_BLIT_MODE, 0);
63871d7fec4Smrg   }
63971d7fec4Smrg}
64071d7fec4Smrg
64171d7fec4Smrg/*
64271d7fec4Smrg//----------------------------------------------------------------------------
64371d7fec4Smrg// GFX_PATTERN_FILL
64471d7fec4Smrg//
64571d7fec4Smrg// This routine is used to fill a rectangular region.  The pattern must
64671d7fec4Smrg// be previously loaded using one of GFX_load_*_pattern routines.  Also, the
64771d7fec4Smrg// raster operation must be previously specified using the
64871d7fec4Smrg// "GFX_load_raster_operation" routine.
64971d7fec4Smrg//
65071d7fec4Smrg//      X               screen X position (left)
65171d7fec4Smrg//      Y               screen Y position (top)
65271d7fec4Smrg//      WIDTH           width of rectangle, in pixels
65371d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
65471d7fec4Smrg//----------------------------------------------------------------------------
65571d7fec4Smrg*/
65671d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
65771d7fec4Smrgvoid
65871d7fec4Smrggu1_pattern_fill(unsigned short x, unsigned short y,
65971d7fec4Smrg		 unsigned short width, unsigned short height)
66071d7fec4Smrg#else
66171d7fec4Smrgvoid
66271d7fec4Smrggfx_pattern_fill(unsigned short x, unsigned short y,
66371d7fec4Smrg		 unsigned short width, unsigned short height)
66471d7fec4Smrg#endif
66571d7fec4Smrg{
66671d7fec4Smrg   unsigned short section, buffer_width, blit_mode;
66771d7fec4Smrg
66871d7fec4Smrg   /* CHECK IF OPTIMIZED SOLID CASES */
66971d7fec4Smrg   /* Check all 16 bits of the ROP to include solid pattern flags. */
67071d7fec4Smrg
67171d7fec4Smrg   switch (GFXsavedRop) {
67271d7fec4Smrg      /* CHECK FOR SPECIAL CASES WITHOUT DESTINATION DATA */
67371d7fec4Smrg      /* Need hardware workaround for fast "burst write" cases. */
67471d7fec4Smrg
67571d7fec4Smrg   case 0x00F0:
67671d7fec4Smrg      gu1_solid_fill(x, y, width, height, (unsigned short)GFXsavedColor);
67771d7fec4Smrg      break;
67871d7fec4Smrg   case 0x000F:
67971d7fec4Smrg      gu1_solid_fill(x, y, width, height, (unsigned short)~GFXsavedColor);
68071d7fec4Smrg      break;
68171d7fec4Smrg   case 0x0000:
68271d7fec4Smrg      gu1_solid_fill(x, y, width, height, 0x0000);
68371d7fec4Smrg      break;
68471d7fec4Smrg   case 0x00FF:
68571d7fec4Smrg      gu1_solid_fill(x, y, width, height, 0xFFFF);
68671d7fec4Smrg      break;
68771d7fec4Smrg
68871d7fec4Smrg      /* REMAINING CASES REQUIRE DESTINATION DATA OR NOT SOLID COLOR */
68971d7fec4Smrg
69071d7fec4Smrg   default:
69171d7fec4Smrg
69271d7fec4Smrg      /* DETERMINE BLT MODE VALUE */
69371d7fec4Smrg      /* Still here for non-solid patterns without destination data. */
69471d7fec4Smrg
69571d7fec4Smrg      blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
69671d7fec4Smrg
69771d7fec4Smrg      /* SET SOURCE EXPANSION MODE */
69871d7fec4Smrg      /* If the ROP requires source data, then the source data is all 1's */
69971d7fec4Smrg      /* and then expanded into the desired color in GP_SRC_COLOR_1. */
70071d7fec4Smrg
70171d7fec4Smrg      blit_mode |= BM_SOURCE_EXPAND;
70271d7fec4Smrg
70371d7fec4Smrg      /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
70471d7fec4Smrg      /* Write the registers that do not change for each section. */
70571d7fec4Smrg
70671d7fec4Smrg      GFX_WAIT_PENDING;
70771d7fec4Smrg      WRITE_REG16(GP_HEIGHT, height);
70871d7fec4Smrg
70971d7fec4Smrg      /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
71071d7fec4Smrg      /* Therefore, width available = BLT buffer width * 2. */
71171d7fec4Smrg
71271d7fec4Smrg      buffer_width = GFXbufferWidthPixels << 1;
71371d7fec4Smrg
71471d7fec4Smrg      /* REPEAT UNTIL FINISHED WITH RECTANGLE */
71571d7fec4Smrg      /* Perform BLT in vertical sections, as wide as the BLT buffer */
71671d7fec4Smrg      /* allows.  Hardware does not split the operations, so */
71771d7fec4Smrg      /* software must do it to avoid large scanlines that would */
71871d7fec4Smrg      /* overflow the BLT buffers. */
71971d7fec4Smrg
72071d7fec4Smrg      while (width > 0) {
72171d7fec4Smrg	 /* DETERMINE WIDTH OF SECTION */
72271d7fec4Smrg
72371d7fec4Smrg	 if (width > buffer_width)
72471d7fec4Smrg	    section = buffer_width;
72571d7fec4Smrg	 else
72671d7fec4Smrg	    section = width;
72771d7fec4Smrg
72871d7fec4Smrg	 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
72971d7fec4Smrg
73071d7fec4Smrg	 GFX_WAIT_PENDING;
73171d7fec4Smrg	 WRITE_REG16(GP_DST_XCOOR, x);
73271d7fec4Smrg	 WRITE_REG16(GP_DST_YCOOR, y);
73371d7fec4Smrg	 WRITE_REG16(GP_WIDTH, section);
73471d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
73571d7fec4Smrg
73671d7fec4Smrg	 /* ADJUST PARAMETERS FOR NEXT SECTION */
73771d7fec4Smrg
73871d7fec4Smrg	 width -= section;
73971d7fec4Smrg	 x += section;
74071d7fec4Smrg      }
74171d7fec4Smrg      break;
74271d7fec4Smrg   }
74371d7fec4Smrg}
74471d7fec4Smrg
74571d7fec4Smrg/*
74671d7fec4Smrg//----------------------------------------------------------------------------
74771d7fec4Smrg// GFX_COLOR_PATTERN_FILL
74871d7fec4Smrg//
74971d7fec4Smrg// This routine is used to render a rectangle using the current raster
75071d7fec4Smrg// operation and the specified color pattern.  It allows an 8x8 color
75171d7fec4Smrg// pattern to be rendered without multiple calls to the gfx_set_color_pattern
75271d7fec4Smrg// and gfx_pattern_fill routines.
75371d7fec4Smrg//
75471d7fec4Smrg//      X               screen X position (left)
75571d7fec4Smrg//      Y               screen Y position (top)
75671d7fec4Smrg//      WIDTH           width of rectangle, in pixels
75771d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
75871d7fec4Smrg//      *PATTERN		pointer to 8x8 color pattern data
75971d7fec4Smrg//----------------------------------------------------------------------------
76071d7fec4Smrg*/
76171d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
76271d7fec4Smrgvoid
76371d7fec4Smrggu1_color_pattern_fill(unsigned short x, unsigned short y,
76471d7fec4Smrg		       unsigned short width, unsigned short height,
76571d7fec4Smrg		       unsigned long *pattern)
76671d7fec4Smrg#else
76771d7fec4Smrgvoid
76871d7fec4Smrggfx_color_pattern_fill(unsigned short x, unsigned short y,
76971d7fec4Smrg		       unsigned short width, unsigned short height,
77071d7fec4Smrg		       unsigned long *pattern)
77171d7fec4Smrg#endif
77271d7fec4Smrg{
77371d7fec4Smrg   unsigned short blit_mode, passes, cur_y, pat_y, i;
77471d7fec4Smrg   unsigned short buffer_width, line_width;
77571d7fec4Smrg   unsigned short bpp_shift, section, cur_x;
77671d7fec4Smrg
77771d7fec4Smrg   /* SET APPROPRIATE INCREMENT */
77871d7fec4Smrg
77971d7fec4Smrg   bpp_shift = (GFXbpp > 8) ? 2 : 1;
78071d7fec4Smrg
78171d7fec4Smrg   /* SET DESTINATION REQUIRED */
78271d7fec4Smrg
78371d7fec4Smrg   blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0;
78471d7fec4Smrg
78571d7fec4Smrg   /* SET SOURCE EXPANSION */
78671d7fec4Smrg
78771d7fec4Smrg   blit_mode |= BM_SOURCE_EXPAND;
78871d7fec4Smrg
78971d7fec4Smrg   /* OVERRIDE RASTER MODE TO FORCE A COLOR PATTERN */
79071d7fec4Smrg
79171d7fec4Smrg   GFX_WAIT_PENDING;
79271d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE,
79371d7fec4Smrg	       (GFXsavedRop & ~RM_PAT_MASK & ~RM_PAT_TRANSPARENT) |
79471d7fec4Smrg	       RM_PAT_COLOR);
79571d7fec4Smrg
79671d7fec4Smrg   /* WRITE THE REGISTERS THAT DO NOT CHANGE         */
79771d7fec4Smrg   /* If destination data is required, the width and */
79871d7fec4Smrg   /* x position will be overwritten.                */
79971d7fec4Smrg
80071d7fec4Smrg   WRITE_REG16(GP_HEIGHT, 1);
80171d7fec4Smrg   WRITE_REG16(GP_WIDTH, width);
80271d7fec4Smrg   WRITE_REG16(GP_DST_XCOOR, x);
80371d7fec4Smrg
80471d7fec4Smrg   /* THE ENTIRE PATTERN WILL NOT BE DRAWN IF THE HEIGHT IS LESS THAN 8 */
80571d7fec4Smrg
80671d7fec4Smrg   passes = (height < 8) ? height : 8;
80771d7fec4Smrg
80871d7fec4Smrg   /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */
80971d7fec4Smrg   /* Therefore, width available = BLT buffer width * 2. */
81071d7fec4Smrg
81171d7fec4Smrg   buffer_width = GFXbufferWidthPixels << 1;
81271d7fec4Smrg
81371d7fec4Smrg   for (i = 0; i < passes; i++) {
81471d7fec4Smrg      pat_y = ((y + i) & 7) << bpp_shift;
81571d7fec4Smrg      cur_y = y + i;
81671d7fec4Smrg
81771d7fec4Smrg      /* WRITE THE PATTERN DATA FOR THE ACTIVE LINE */
81871d7fec4Smrg
81971d7fec4Smrg      GFX_WAIT_PENDING;
82071d7fec4Smrg      WRITE_REG32(GP_PAT_DATA_0, pattern[pat_y]);
82171d7fec4Smrg      WRITE_REG32(GP_PAT_DATA_1, pattern[pat_y + 1]);
82271d7fec4Smrg
82371d7fec4Smrg      if (GFXbpp > 8) {
82471d7fec4Smrg	 WRITE_REG32(GP_PAT_DATA_2, pattern[pat_y + 2]);
82571d7fec4Smrg	 WRITE_REG32(GP_PAT_DATA_3, pattern[pat_y + 3]);
82671d7fec4Smrg      }
82771d7fec4Smrg
82871d7fec4Smrg      /* SPLIT BLT LINE INTO SECTIONS IF REQUIRED              */
82971d7fec4Smrg      /* If no destination data is required, we can ignore     */
83071d7fec4Smrg      /* the BLT buffers.  Otherwise, we must separate the BLT */
83171d7fec4Smrg      /* so as not to overflow the buffers                     */
83271d7fec4Smrg
83371d7fec4Smrg      if (blit_mode & BM_READ_DST_BB0) {
83471d7fec4Smrg	 line_width = width;
83571d7fec4Smrg	 cur_x = x;
83671d7fec4Smrg
83771d7fec4Smrg	 while (line_width) {
83871d7fec4Smrg	    section = (line_width > buffer_width) ? buffer_width : line_width;
83971d7fec4Smrg	    cur_y = y + i;
84071d7fec4Smrg
84171d7fec4Smrg	    GFX_WAIT_PENDING;
84271d7fec4Smrg	    WRITE_REG16(GP_DST_XCOOR, cur_x);
84371d7fec4Smrg	    WRITE_REG16(GP_WIDTH, section);
84471d7fec4Smrg
84571d7fec4Smrg	    while (cur_y < y + height) {
84671d7fec4Smrg	       GFX_WAIT_PENDING;
84771d7fec4Smrg	       WRITE_REG16(GP_DST_YCOOR, cur_y);
84871d7fec4Smrg	       WRITE_REG16(GP_BLIT_MODE, blit_mode);
84971d7fec4Smrg	       cur_y += 8;
85071d7fec4Smrg	    }
85171d7fec4Smrg
85271d7fec4Smrg	    cur_x += section;
85371d7fec4Smrg	    line_width -= section;
85471d7fec4Smrg	 }
85571d7fec4Smrg
85671d7fec4Smrg      } else {
85771d7fec4Smrg	 while (cur_y < y + height) {
85871d7fec4Smrg	    GFX_WAIT_PENDING;
85971d7fec4Smrg	    WRITE_REG16(GP_DST_YCOOR, cur_y);
86071d7fec4Smrg	    WRITE_REG16(GP_BLIT_MODE, blit_mode);
86171d7fec4Smrg	    cur_y += 8;
86271d7fec4Smrg	 }
86371d7fec4Smrg      }
86471d7fec4Smrg
86571d7fec4Smrg   }
86671d7fec4Smrg
86771d7fec4Smrg   /* RESTORE ORIGINAL ROP AND FLAGS */
86871d7fec4Smrg
86971d7fec4Smrg   GFX_WAIT_PENDING;
87071d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE, GFXsavedRop);
87171d7fec4Smrg
87271d7fec4Smrg}
87371d7fec4Smrg
87471d7fec4Smrg/*
87571d7fec4Smrg//----------------------------------------------------------------------------
87671d7fec4Smrg// SCREEN TO SCREEN BLT
87771d7fec4Smrg//
87871d7fec4Smrg// This routine should be used to perform a screen to screen BLT when the
87971d7fec4Smrg// ROP does not require destination data.
88071d7fec4Smrg//
88171d7fec4Smrg//      SRCX            screen X position to copy from
88271d7fec4Smrg//      SRCY            screen Y position to copy from
88371d7fec4Smrg//      DSTX            screen X position to copy to
88471d7fec4Smrg//      DSTY            screen Y position to copy to
88571d7fec4Smrg//      WIDTH           width of rectangle, in pixels
88671d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
88771d7fec4Smrg//----------------------------------------------------------------------------
88871d7fec4Smrg*/
88971d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
89071d7fec4Smrgvoid
89171d7fec4Smrggu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
89271d7fec4Smrg			 unsigned short dstx, unsigned short dsty,
89371d7fec4Smrg			 unsigned short width, unsigned short height)
89471d7fec4Smrg#else
89571d7fec4Smrgvoid
89671d7fec4Smrggfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy,
89771d7fec4Smrg			 unsigned short dstx, unsigned short dsty,
89871d7fec4Smrg			 unsigned short width, unsigned short height)
89971d7fec4Smrg#endif
90071d7fec4Smrg{
90171d7fec4Smrg   unsigned short section, buffer_width;
90271d7fec4Smrg   unsigned short blit_mode;
90371d7fec4Smrg
90471d7fec4Smrg   /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
90571d7fec4Smrg
90671d7fec4Smrg   blit_mode = GFXusesDstData ? BM_READ_DST_FB1 | BM_READ_SRC_FB :
90771d7fec4Smrg	 BM_READ_SRC_FB;
90871d7fec4Smrg
90971d7fec4Smrg   /* CHECK Y DIRECTION */
91071d7fec4Smrg   /* Hardware has support for negative Y direction. */
91171d7fec4Smrg
91271d7fec4Smrg   if (dsty > srcy) {
91371d7fec4Smrg      blit_mode |= BM_REVERSE_Y;
91471d7fec4Smrg      srcy += height - 1;
91571d7fec4Smrg      dsty += height - 1;
91671d7fec4Smrg   }
91771d7fec4Smrg
91871d7fec4Smrg   /* CHECK X DIRECTION */
91971d7fec4Smrg   /* Hardware does not support negative X direction since at the time */
92071d7fec4Smrg   /* of development all supported resolutions could fit a scanline of */
92171d7fec4Smrg   /* data at once into the BLT buffers (using both BB0 and BB1).  This */
92271d7fec4Smrg   /* code is more generic to allow for any size BLT buffer. */
92371d7fec4Smrg
92471d7fec4Smrg   if (dstx > srcx) {
92571d7fec4Smrg      srcx += width;
92671d7fec4Smrg      dstx += width;
92771d7fec4Smrg   }
92871d7fec4Smrg
92971d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
93071d7fec4Smrg   /* Write the registers that do not change for each section. */
93171d7fec4Smrg
93271d7fec4Smrg   GFX_WAIT_PENDING;
93371d7fec4Smrg   WRITE_REG16(GP_HEIGHT, height);
93471d7fec4Smrg
93571d7fec4Smrg   /* CHECK AVAILABLE BLT BUFFER SIZE */
93671d7fec4Smrg   /* Can use both BLT buffers if no destination data is required. */
93771d7fec4Smrg
93871d7fec4Smrg   buffer_width = GFXusesDstData ? GFXbufferWidthPixels :
93971d7fec4Smrg	 GFXbufferWidthPixels << 1;
94071d7fec4Smrg
94171d7fec4Smrg   /* REPEAT UNTIL FINISHED WITH RECTANGLE */
94271d7fec4Smrg   /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
94371d7fec4Smrg   /* Hardware does not split the operations, so software must do it to */
94471d7fec4Smrg   /* avoid large scanlines that would overflow the BLT buffers. */
94571d7fec4Smrg
94671d7fec4Smrg   while (width > 0) {
94771d7fec4Smrg      /* CHECK WIDTH OF CURRENT SECTION */
94871d7fec4Smrg
94971d7fec4Smrg      if (width > buffer_width)
95071d7fec4Smrg	 section = buffer_width;
95171d7fec4Smrg      else
95271d7fec4Smrg	 section = width;
95371d7fec4Smrg
95471d7fec4Smrg      /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
95571d7fec4Smrg
95671d7fec4Smrg      GFX_WAIT_PENDING;
95771d7fec4Smrg      WRITE_REG16(GP_SRC_YCOOR, srcy);
95871d7fec4Smrg      WRITE_REG16(GP_DST_YCOOR, dsty);
95971d7fec4Smrg      WRITE_REG16(GP_WIDTH, section);
96071d7fec4Smrg
96171d7fec4Smrg      /* CHECK X DIRECTION */
96271d7fec4Smrg
96371d7fec4Smrg      if (dstx > srcx) {
96471d7fec4Smrg	 /* NEGATIVE X DIRECTION */
96571d7fec4Smrg	 /* Still positive X direction within the section. */
96671d7fec4Smrg
96771d7fec4Smrg	 srcx -= section;
96871d7fec4Smrg	 dstx -= section;
96971d7fec4Smrg	 WRITE_REG16(GP_SRC_XCOOR, srcx);
97071d7fec4Smrg	 WRITE_REG16(GP_DST_XCOOR, dstx);
97171d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
97271d7fec4Smrg      } else {
97371d7fec4Smrg	 /* POSITIVE X DIRECTION */
97471d7fec4Smrg
97571d7fec4Smrg	 WRITE_REG16(GP_SRC_XCOOR, srcx);
97671d7fec4Smrg	 WRITE_REG16(GP_DST_XCOOR, dstx);
97771d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
97871d7fec4Smrg	 dstx += section;
97971d7fec4Smrg	 srcx += section;
98071d7fec4Smrg      }
98171d7fec4Smrg      width -= section;
98271d7fec4Smrg   }
98371d7fec4Smrg}
98471d7fec4Smrg
98571d7fec4Smrg/*
98671d7fec4Smrg//----------------------------------------------------------------------------
98771d7fec4Smrg// SCREEN TO SCREEN TRANSPARENT BLT
98871d7fec4Smrg//
98971d7fec4Smrg// This routine should be used to perform a screen to screen BLT when a
99071d7fec4Smrg// specified color should by transparent.  The only supported ROP is SRCCOPY.
99171d7fec4Smrg//
99271d7fec4Smrg//      SRCX            screen X position to copy from
99371d7fec4Smrg//      SRCY            screen Y position to copy from
99471d7fec4Smrg//      DSTX            screen X position to copy to
99571d7fec4Smrg//      DSTY            screen Y position to copy to
99671d7fec4Smrg//      WIDTH           width of rectangle, in pixels
99771d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
99871d7fec4Smrg//      COLOR           transparent color
99971d7fec4Smrg//----------------------------------------------------------------------------
100071d7fec4Smrg*/
100171d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
100271d7fec4Smrgvoid
100371d7fec4Smrggu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
100471d7fec4Smrg			  unsigned short dstx, unsigned short dsty,
100571d7fec4Smrg			  unsigned short width, unsigned short height,
100671d7fec4Smrg			  unsigned long color)
100771d7fec4Smrg#else
100871d7fec4Smrgvoid
100971d7fec4Smrggfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy,
101071d7fec4Smrg			  unsigned short dstx, unsigned short dsty,
101171d7fec4Smrg			  unsigned short width, unsigned short height,
101271d7fec4Smrg			  unsigned long color)
101371d7fec4Smrg#endif
101471d7fec4Smrg{
101571d7fec4Smrg   unsigned short section, buffer_width;
101671d7fec4Smrg   unsigned short blit_mode = BM_READ_SRC_FB;
101771d7fec4Smrg
101871d7fec4Smrg   /* CHECK Y DIRECTION */
101971d7fec4Smrg   /* Hardware has support for negative Y direction. */
102071d7fec4Smrg
102171d7fec4Smrg   if (dsty > srcy) {
102271d7fec4Smrg      blit_mode |= BM_REVERSE_Y;
102371d7fec4Smrg      srcy += height - 1;
102471d7fec4Smrg      dsty += height - 1;
102571d7fec4Smrg   }
102671d7fec4Smrg
102771d7fec4Smrg   /* CHECK X DIRECTION */
102871d7fec4Smrg   /* Hardware does not support negative X direction since at the time */
102971d7fec4Smrg   /* of development all supported resolutions could fit a scanline of */
103071d7fec4Smrg   /* data at once into the BLT buffers (using both BB0 and BB1).  This */
103171d7fec4Smrg   /* code is more generic to allow for any size BLT buffer. */
103271d7fec4Smrg
103371d7fec4Smrg   if (dstx > srcx) {
103471d7fec4Smrg      srcx += width;
103571d7fec4Smrg      dstx += width;
103671d7fec4Smrg   }
103771d7fec4Smrg
103871d7fec4Smrg   /* CALCULATE BLT BUFFER SIZE */
103971d7fec4Smrg   /* Need to use BB1 to store the BLT buffer data. */
104071d7fec4Smrg
104171d7fec4Smrg   buffer_width = GFXbufferWidthPixels;
104271d7fec4Smrg
104371d7fec4Smrg   /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
104471d7fec4Smrg
104571d7fec4Smrg   if (GFXbpp == 8) {
104671d7fec4Smrg      color &= 0x00FF;
104771d7fec4Smrg      color |= (color << 8);
104871d7fec4Smrg   }
104971d7fec4Smrg   color = (color & 0x0000FFFF) | (color << 16);
105071d7fec4Smrg
105171d7fec4Smrg   /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
105271d7fec4Smrg   /* Need to make sure any previous BLT using BB1 is complete. */
105371d7fec4Smrg   /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
105471d7fec4Smrg
105571d7fec4Smrg   GFX_WAIT_BUSY;
105671d7fec4Smrg   WRITE_SCRATCH32(GFXbb1Base, color);
105771d7fec4Smrg
105871d7fec4Smrg   /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
105971d7fec4Smrg   /* Already know graphics pipeline is idle. */
106071d7fec4Smrg   /* Only need to latch data into the holding registers for the current */
106171d7fec4Smrg   /* data from BB1.  A 1 pixel wide BLT will suffice. */
106271d7fec4Smrg
106371d7fec4Smrg   WRITE_REG32(GP_DST_XCOOR, 0);
106471d7fec4Smrg   WRITE_REG32(GP_SRC_XCOOR, 0);
106571d7fec4Smrg   WRITE_REG32(GP_WIDTH, 0x00010001);
106671d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE, 0x00CC);
106771d7fec4Smrg   WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
106871d7fec4Smrg
106971d7fec4Smrg   /* WRITE REGISTERS FOR REAL SCREEN TO SCREEN BLT */
107071d7fec4Smrg
107171d7fec4Smrg   GFX_WAIT_PENDING;
107271d7fec4Smrg   WRITE_REG16(GP_HEIGHT, height);
107371d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE, 0x10C6);
107471d7fec4Smrg   WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
107571d7fec4Smrg
107671d7fec4Smrg   /* REPEAT UNTIL FINISHED WITH RECTANGLE */
107771d7fec4Smrg   /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */
107871d7fec4Smrg   /* Hardware does not split the operations, so software must do it to */
107971d7fec4Smrg   /* avoid large scanlines that would overflow the BLT buffers. */
108071d7fec4Smrg
108171d7fec4Smrg   while (width > 0) {
108271d7fec4Smrg      /* CHECK WIDTH OF CURRENT SECTION */
108371d7fec4Smrg
108471d7fec4Smrg      if (width > buffer_width)
108571d7fec4Smrg	 section = buffer_width;
108671d7fec4Smrg      else
108771d7fec4Smrg	 section = width;
108871d7fec4Smrg
108971d7fec4Smrg      /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */
109071d7fec4Smrg
109171d7fec4Smrg      GFX_WAIT_PENDING;
109271d7fec4Smrg      WRITE_REG16(GP_SRC_YCOOR, srcy);
109371d7fec4Smrg      WRITE_REG16(GP_DST_YCOOR, dsty);
109471d7fec4Smrg      WRITE_REG16(GP_WIDTH, section);
109571d7fec4Smrg
109671d7fec4Smrg      /* CHECK X DIRECTION */
109771d7fec4Smrg      /* Again, this must be done in software, and can be removed if the */
109871d7fec4Smrg      /* display driver knows that the BLT buffers will always be large  */
109971d7fec4Smrg      /* enough to contain an entire scanline of a screen to screen BLT. */
110071d7fec4Smrg
110171d7fec4Smrg      if (dstx > srcx) {
110271d7fec4Smrg	 /* NEGATIVE X DIRECTION */
110371d7fec4Smrg	 /* Still positive X direction within the section. */
110471d7fec4Smrg
110571d7fec4Smrg	 srcx -= section;
110671d7fec4Smrg	 dstx -= section;
110771d7fec4Smrg	 WRITE_REG16(GP_SRC_XCOOR, srcx);
110871d7fec4Smrg	 WRITE_REG16(GP_DST_XCOOR, dstx);
110971d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
111071d7fec4Smrg      } else {
111171d7fec4Smrg	 /* POSITIVE X DIRECTION */
111271d7fec4Smrg
111371d7fec4Smrg	 WRITE_REG16(GP_SRC_XCOOR, srcx);
111471d7fec4Smrg	 WRITE_REG16(GP_DST_XCOOR, dstx);
111571d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
111671d7fec4Smrg	 dstx += section;
111771d7fec4Smrg	 srcx += section;
111871d7fec4Smrg      }
111971d7fec4Smrg      width -= section;
112071d7fec4Smrg   }
112171d7fec4Smrg}
112271d7fec4Smrg
112371d7fec4Smrg/*
112471d7fec4Smrg//----------------------------------------------------------------------------
112571d7fec4Smrg// COLOR BITMAP TO SCREEN BLT
112671d7fec4Smrg//
112771d7fec4Smrg// This routine transfers color bitmap data to the screen.  For most cases,
112871d7fec4Smrg// when the ROP is SRCCOPY, it may be faster to write a separate routine that
112971d7fec4Smrg// copies the data to the frame buffer directly.  This routine should be
113071d7fec4Smrg// used when the ROP requires destination data.
113171d7fec4Smrg//
113271d7fec4Smrg// Transparency is handled by another routine.
113371d7fec4Smrg//
113471d7fec4Smrg//      SRCX            X offset within source bitmap
113571d7fec4Smrg//      SRCY            Y offset within source bitmap
113671d7fec4Smrg//      DSTX            screen X position to render data
113771d7fec4Smrg//      DSTY            screen Y position to render data
113871d7fec4Smrg//      WIDTH           width of rectangle, in pixels
113971d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
114071d7fec4Smrg//      *DATA           pointer to bitmap data
114171d7fec4Smrg//      PITCH           pitch of bitmap data (bytes between scanlines)
114271d7fec4Smrg//----------------------------------------------------------------------------
114371d7fec4Smrg*/
114471d7fec4Smrg
114571d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
114671d7fec4Smrgvoid
114771d7fec4Smrggu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
114871d7fec4Smrg			       unsigned short dstx, unsigned short dsty,
114971d7fec4Smrg			       unsigned short width, unsigned short height,
115071d7fec4Smrg			       unsigned char *data, long pitch)
115171d7fec4Smrg#else
115271d7fec4Smrgvoid
115371d7fec4Smrggfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
115471d7fec4Smrg			       unsigned short dstx, unsigned short dsty,
115571d7fec4Smrg			       unsigned short width, unsigned short height,
115671d7fec4Smrg			       unsigned char *data, long pitch)
115771d7fec4Smrg#endif
115871d7fec4Smrg{
115971d7fec4Smrg   unsigned short section, buffer_width;
116071d7fec4Smrg   unsigned short blit_mode = BM_READ_SRC_BB0;
116171d7fec4Smrg   unsigned short temp_height;
116271d7fec4Smrg   unsigned long dword_bytes_needed, bytes_extra;
116371d7fec4Smrg   unsigned long bpp_shift;
116471d7fec4Smrg   long array_offset;
116571d7fec4Smrg
116671d7fec4Smrg   /* CHECK SIZE OF BLT BUFFER */
116771d7fec4Smrg
116871d7fec4Smrg   buffer_width = GFXbufferWidthPixels;
116971d7fec4Smrg
117071d7fec4Smrg   /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
117171d7fec4Smrg   /* If no destination data, we have twice the room for  */
117271d7fec4Smrg   /* source data.                                        */
117371d7fec4Smrg
117471d7fec4Smrg   if (GFXusesDstData)
117571d7fec4Smrg      blit_mode |= BM_READ_DST_FB1;
117671d7fec4Smrg   else
117771d7fec4Smrg      buffer_width <<= 1;
117871d7fec4Smrg
117971d7fec4Smrg   /* SET THE SCRATCHPAD BASE */
118071d7fec4Smrg
118171d7fec4Smrg   SET_SCRATCH_BASE(GFXbb0Base);
118271d7fec4Smrg
118371d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS                */
118471d7fec4Smrg   /* Write the registers that do not change for each section. */
118571d7fec4Smrg
118671d7fec4Smrg   GFX_WAIT_PENDING;
118771d7fec4Smrg   WRITE_REG16(GP_HEIGHT, 1);
118871d7fec4Smrg
118971d7fec4Smrg   bpp_shift = (GFXbpp + 7) >> 4;
119071d7fec4Smrg
119171d7fec4Smrg   while (width > 0) {
119271d7fec4Smrg      if (width > buffer_width)
119371d7fec4Smrg	 section = buffer_width;
119471d7fec4Smrg      else
119571d7fec4Smrg	 section = width;
119671d7fec4Smrg
119771d7fec4Smrg      dword_bytes_needed = (section << bpp_shift) & ~3l;
119871d7fec4Smrg      bytes_extra = (section << bpp_shift) & 3l;
119971d7fec4Smrg
120071d7fec4Smrg      temp_height = height;
120171d7fec4Smrg
120271d7fec4Smrg      /* WRITE THE REGISTERS FOR EACH SECTION                          */
120371d7fec4Smrg      /* The GX hardware will auto-increment the Y coordinate, meaning */
120471d7fec4Smrg      /* that we don't have to.                                        */
120571d7fec4Smrg
120671d7fec4Smrg      WRITE_REG16(GP_WIDTH, section);
120771d7fec4Smrg      WRITE_REG16(GP_DST_XCOOR, dstx);
120871d7fec4Smrg      WRITE_REG16(GP_DST_YCOOR, dsty);
120971d7fec4Smrg
121071d7fec4Smrg      /* CALCULATE THE BITMAP OFFSET */
121171d7fec4Smrg
121271d7fec4Smrg      array_offset =
121371d7fec4Smrg	    (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift);
121471d7fec4Smrg
121571d7fec4Smrg      while (temp_height--) {
121671d7fec4Smrg	 GFX_WAIT_PIPELINE;
121771d7fec4Smrg
121871d7fec4Smrg	 /* WRITE ALL DATA TO THE BLT BUFFERS */
121971d7fec4Smrg	 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
122071d7fec4Smrg	 /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
122171d7fec4Smrg
122271d7fec4Smrg	 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
122371d7fec4Smrg			      array_offset);
122471d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
122571d7fec4Smrg
122671d7fec4Smrg	 array_offset += pitch;
122771d7fec4Smrg      }
122871d7fec4Smrg
122971d7fec4Smrg      width -= section;
123071d7fec4Smrg      srcx += section;
123171d7fec4Smrg      dstx += section;
123271d7fec4Smrg   }
123371d7fec4Smrg}
123471d7fec4Smrg
123571d7fec4Smrg/*
123671d7fec4Smrg//----------------------------------------------------------------------------
123771d7fec4Smrg// COLOR BITMAP TO SCREEN TRANSPARENT BLT
123871d7fec4Smrg//
123971d7fec4Smrg// This routine transfers color bitmap data to the screen with transparency.
124071d7fec4Smrg// The transparent color is specified.  The only supported ROP is SRCCOPY,
124171d7fec4Smrg// meaning that transparency cannot be applied if the ROP requires
124271d7fec4Smrg// destination data (this is a hardware restriction).
124371d7fec4Smrg//
124471d7fec4Smrg//      SRCX            X offset within source bitmap
124571d7fec4Smrg//      SRCY            Y offset within source bitmap
124671d7fec4Smrg//      DSTX            screen X position to render data
124771d7fec4Smrg//      DSTY            screen Y position to render data
124871d7fec4Smrg//      WIDTH           width of rectangle, in pixels
124971d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
125071d7fec4Smrg//      *DATA           pointer to bitmap data
125171d7fec4Smrg//      PITCH           pitch of bitmap data (bytes between scanlines)
125271d7fec4Smrg//      COLOR           transparent color
125371d7fec4Smrg//----------------------------------------------------------------------------
125471d7fec4Smrg*/
125571d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
125671d7fec4Smrgvoid
125771d7fec4Smrggu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
125871d7fec4Smrg				unsigned short dstx, unsigned short dsty,
125971d7fec4Smrg				unsigned short width, unsigned short height,
126071d7fec4Smrg				unsigned char *data, long pitch,
126171d7fec4Smrg				unsigned long color)
126271d7fec4Smrg#else
126371d7fec4Smrgvoid
126471d7fec4Smrggfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy,
126571d7fec4Smrg				unsigned short dstx, unsigned short dsty,
126671d7fec4Smrg				unsigned short width, unsigned short height,
126771d7fec4Smrg				unsigned char *data, long pitch,
126871d7fec4Smrg				unsigned long color)
126971d7fec4Smrg#endif
127071d7fec4Smrg{
127171d7fec4Smrg   unsigned short section, buffer_width;
127271d7fec4Smrg   unsigned short temp_height;
127371d7fec4Smrg   unsigned long dword_bytes_needed, bytes_extra;
127471d7fec4Smrg   unsigned long bpp_shift;
127571d7fec4Smrg   long array_offset;
127671d7fec4Smrg
127771d7fec4Smrg   /* CHECK SIZE OF BLT BUFFER */
127871d7fec4Smrg
127971d7fec4Smrg   buffer_width = GFXbufferWidthPixels;
128071d7fec4Smrg
128171d7fec4Smrg   /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */
128271d7fec4Smrg
128371d7fec4Smrg   if (GFXbpp == 8) {
128471d7fec4Smrg      color &= 0x00FF;
128571d7fec4Smrg      color |= (color << 8);
128671d7fec4Smrg   }
128771d7fec4Smrg   color = (color & 0x0000FFFF) | (color << 16);
128871d7fec4Smrg
128971d7fec4Smrg   /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */
129071d7fec4Smrg   /* Need to make sure any previous BLT using BB1 is complete. */
129171d7fec4Smrg   /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */
129271d7fec4Smrg
129371d7fec4Smrg   GFX_WAIT_PIPELINE;
129471d7fec4Smrg   GFX_WAIT_PENDING;
129571d7fec4Smrg   WRITE_SCRATCH32(GFXbb1Base, color);
129671d7fec4Smrg
129771d7fec4Smrg   /* DO BOGUS BLT TO LATCH DATA FROM BB1 */
129871d7fec4Smrg   /* Already know graphics pipeline is idle. */
129971d7fec4Smrg   /* Only need to latch data into the holding registers for the current */
130071d7fec4Smrg   /* data from BB1.  A 1 pixel wide BLT will suffice. */
130171d7fec4Smrg
130271d7fec4Smrg   WRITE_REG32(GP_DST_XCOOR, 0);
130371d7fec4Smrg   WRITE_REG32(GP_SRC_XCOOR, 0);
130471d7fec4Smrg   WRITE_REG32(GP_WIDTH, 0x00010001);
130571d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE, 0x00CC);
130671d7fec4Smrg   WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1);
130771d7fec4Smrg
130871d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
130971d7fec4Smrg   /* Write the registers that do not change for each section. */
131071d7fec4Smrg
131171d7fec4Smrg   GFX_WAIT_PENDING;
131271d7fec4Smrg   WRITE_REG16(GP_HEIGHT, 1);
131371d7fec4Smrg   WRITE_REG16(GP_RASTER_MODE, 0x10C6);
131471d7fec4Smrg   WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF);
131571d7fec4Smrg
131671d7fec4Smrg   bpp_shift = (GFXbpp + 7) >> 4;
131771d7fec4Smrg
131871d7fec4Smrg   /* SET THE SCRATCHPAD BASE */
131971d7fec4Smrg
132071d7fec4Smrg   SET_SCRATCH_BASE(GFXbb0Base);
132171d7fec4Smrg
132271d7fec4Smrg   while (width > 0) {
132371d7fec4Smrg      if (width > buffer_width)
132471d7fec4Smrg	 section = buffer_width;
132571d7fec4Smrg      else
132671d7fec4Smrg	 section = width;
132771d7fec4Smrg
132871d7fec4Smrg      dword_bytes_needed = (section << bpp_shift) & ~3l;
132971d7fec4Smrg      bytes_extra = (section << bpp_shift) & 3l;
133071d7fec4Smrg
133171d7fec4Smrg      temp_height = height;
133271d7fec4Smrg
133371d7fec4Smrg      /* WRITE THE REGISTERS FOR EACH SECTION                          */
133471d7fec4Smrg      /* The GX hardware will auto-increment the Y coordinate, meaning */
133571d7fec4Smrg      /* that we don't have to.                                        */
133671d7fec4Smrg
133771d7fec4Smrg      WRITE_REG16(GP_WIDTH, section);
133871d7fec4Smrg      WRITE_REG16(GP_DST_XCOOR, dstx);
133971d7fec4Smrg      WRITE_REG16(GP_DST_YCOOR, dsty);
134071d7fec4Smrg
134171d7fec4Smrg      /* CALCULATE THE BITMAP OFFSET */
134271d7fec4Smrg
134371d7fec4Smrg      array_offset =
134471d7fec4Smrg	    (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift);
134571d7fec4Smrg
134671d7fec4Smrg      while (temp_height--) {
134771d7fec4Smrg	 GFX_WAIT_PIPELINE;
134871d7fec4Smrg
134971d7fec4Smrg	 /* WRITE ALL DATA TO THE BLT BUFFERS */
135071d7fec4Smrg	 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
135171d7fec4Smrg	 /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
135271d7fec4Smrg
135371d7fec4Smrg	 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
135471d7fec4Smrg			      array_offset);
135571d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0);
135671d7fec4Smrg
135771d7fec4Smrg	 array_offset += pitch;
135871d7fec4Smrg      }
135971d7fec4Smrg
136071d7fec4Smrg      width -= section;
136171d7fec4Smrg      srcx += section;
136271d7fec4Smrg      dstx += section;
136371d7fec4Smrg   }
136471d7fec4Smrg}
136571d7fec4Smrg
136671d7fec4Smrg/*
136771d7fec4Smrg//----------------------------------------------------------------------------
136871d7fec4Smrg// MONOCHROME BITMAP TO SCREEN BLT
136971d7fec4Smrg//
137071d7fec4Smrg// This routine transfers monochrome bitmap data to the screen.
137171d7fec4Smrg//
137271d7fec4Smrg//      SRCX            X offset within source bitmap
137371d7fec4Smrg//      SRCY            Y offset within source bitmap
137471d7fec4Smrg//      DSTX            screen X position to render data
137571d7fec4Smrg//      DSTY            screen Y position to render data
137671d7fec4Smrg//      WIDTH           width of rectangle, in pixels
137771d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
137871d7fec4Smrg//      *DATA           pointer to bitmap data
137971d7fec4Smrg//      PITCH           pitch of bitmap data (bytes between scanlines)
138071d7fec4Smrg//----------------------------------------------------------------------------
138171d7fec4Smrg*/
138271d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
138371d7fec4Smrgvoid
138471d7fec4Smrggu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
138571d7fec4Smrg			      unsigned short dstx, unsigned short dsty,
138671d7fec4Smrg			      unsigned short width, unsigned short height,
138771d7fec4Smrg			      unsigned char *data, short pitch)
138871d7fec4Smrg#else
138971d7fec4Smrgvoid
139071d7fec4Smrggfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
139171d7fec4Smrg			      unsigned short dstx, unsigned short dsty,
139271d7fec4Smrg			      unsigned short width, unsigned short height,
139371d7fec4Smrg			      unsigned char *data, short pitch)
139471d7fec4Smrg#endif
139571d7fec4Smrg{
139671d7fec4Smrg   unsigned short section, buffer_width;
139771d7fec4Smrg   unsigned short blit_mode = BM_READ_SRC_BB0 | BM_SOURCE_EXPAND;
139871d7fec4Smrg   unsigned short temp_height;
139971d7fec4Smrg   unsigned long dword_bytes_needed, bytes_extra;
140071d7fec4Smrg   long array_offset;
140171d7fec4Smrg
140271d7fec4Smrg   /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA        */
140371d7fec4Smrg   /* If no destination data, the source data will always fit.   */
140471d7fec4Smrg   /* So, in that event we will set the buffer width to a        */
140571d7fec4Smrg   /* fictitiously large value such that the BLT is never split. */
140671d7fec4Smrg
140771d7fec4Smrg   if (GFXusesDstData) {
140871d7fec4Smrg      buffer_width = GFXbufferWidthPixels;
140971d7fec4Smrg      blit_mode |= BM_READ_DST_FB1;
141071d7fec4Smrg   } else
141171d7fec4Smrg      buffer_width = 3200;
141271d7fec4Smrg
141371d7fec4Smrg   /* CHECK IF DATA ALREADY IN BLIT BUFFER */
141471d7fec4Smrg   /* If the pointer is NULL, data for the full BLT is already there */
141571d7fec4Smrg   /* WARNING: This could cause problems if destination data is */
141671d7fec4Smrg   /* involved and it overflows the BLT buffer.  Need to remove */
141771d7fec4Smrg   /* this option and change the drivers to use a temporary buffer. */
141871d7fec4Smrg
141971d7fec4Smrg   if (!data) {
142071d7fec4Smrg      GFX_WAIT_PENDING;
142171d7fec4Smrg      WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
142271d7fec4Smrg      WRITE_REG16(GP_DST_XCOOR, dstx);
142371d7fec4Smrg      WRITE_REG16(GP_DST_YCOOR, dsty);
142471d7fec4Smrg      WRITE_REG16(GP_WIDTH, width);
142571d7fec4Smrg      WRITE_REG16(GP_HEIGHT, height);
142671d7fec4Smrg      WRITE_REG16(GP_BLIT_MODE, blit_mode);
142771d7fec4Smrg      return;
142871d7fec4Smrg   }
142971d7fec4Smrg
143071d7fec4Smrg   /* SET THE SCRATCHPAD BASE */
143171d7fec4Smrg
143271d7fec4Smrg   SET_SCRATCH_BASE(GFXbb0Base);
143371d7fec4Smrg
143471d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
143571d7fec4Smrg   /* Write the registers that do not change for each section. */
143671d7fec4Smrg
143771d7fec4Smrg   GFX_WAIT_PENDING;
143871d7fec4Smrg   WRITE_REG16(GP_HEIGHT, 1);
143971d7fec4Smrg
144071d7fec4Smrg   while (width > 0) {
144171d7fec4Smrg      if (width > buffer_width)
144271d7fec4Smrg	 section = buffer_width;
144371d7fec4Smrg      else
144471d7fec4Smrg	 section = width;
144571d7fec4Smrg
144671d7fec4Smrg      /* CALCULATE BYTES NEEDED */
144771d7fec4Smrg      /* Add 1 for possible alignment issues. */
144871d7fec4Smrg
144971d7fec4Smrg      dword_bytes_needed = ((section + 7 + (srcx & 7)) >> 3) & ~3l;
145071d7fec4Smrg      bytes_extra = ((section + 7 + (srcx & 7)) >> 3) & 3l;
145171d7fec4Smrg
145271d7fec4Smrg      temp_height = height;
145371d7fec4Smrg
145471d7fec4Smrg      /* WRITE THE REGISTERS FOR EACH SECTION                          */
145571d7fec4Smrg      /* The GX hardware will auto-increment the Y coordinate, meaning */
145671d7fec4Smrg      /* that we don't have to.                                        */
145771d7fec4Smrg
145871d7fec4Smrg      WRITE_REG16(GP_WIDTH, section);
145971d7fec4Smrg      WRITE_REG16(GP_DST_XCOOR, dstx);
146071d7fec4Smrg      WRITE_REG16(GP_DST_YCOOR, dsty);
146171d7fec4Smrg      WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
146271d7fec4Smrg
146371d7fec4Smrg      /* CALCULATE THE BITMAP OFFSET */
146471d7fec4Smrg
146571d7fec4Smrg      array_offset = (unsigned long)srcy *(long)pitch + ((long)srcx >> 3);
146671d7fec4Smrg
146771d7fec4Smrg      while (temp_height--) {
146871d7fec4Smrg	 GFX_WAIT_PIPELINE;
146971d7fec4Smrg
147071d7fec4Smrg	 /* WRITE ALL DATA TO THE BLT BUFFERS */
147171d7fec4Smrg	 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
147271d7fec4Smrg	 /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
147371d7fec4Smrg
147471d7fec4Smrg	 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data,
147571d7fec4Smrg			      array_offset);
147671d7fec4Smrg	 WRITE_REG16(GP_BLIT_MODE, blit_mode);
147771d7fec4Smrg
147871d7fec4Smrg	 array_offset += pitch;
147971d7fec4Smrg      }
148071d7fec4Smrg
148171d7fec4Smrg      width -= section;
148271d7fec4Smrg      srcx += section;
148371d7fec4Smrg      dstx += section;
148471d7fec4Smrg   }
148571d7fec4Smrg}
148671d7fec4Smrg
148771d7fec4Smrg/*
148871d7fec4Smrg//----------------------------------------------------------------------------
148971d7fec4Smrg// MONOCHROME TEXT BLT
149071d7fec4Smrg//
149171d7fec4Smrg// This routine transfers contiguous monochrome text data to the screen.
149271d7fec4Smrg//
149371d7fec4Smrg//      DSTX            screen X position to render data
149471d7fec4Smrg//      DSTY            screen Y position to render data
149571d7fec4Smrg//      WIDTH           width of rectangle, in pixels
149671d7fec4Smrg//      HEIGHT          height of rectangle, in scanlines
149771d7fec4Smrg//      *DATA           pointer to bitmap data
149871d7fec4Smrg//----------------------------------------------------------------------------
149971d7fec4Smrg*/
150071d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
150171d7fec4Smrgvoid
150271d7fec4Smrggu1_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
150371d7fec4Smrg	     unsigned short height, unsigned char *data)
150471d7fec4Smrg#else
150571d7fec4Smrgvoid
150671d7fec4Smrggfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width,
150771d7fec4Smrg	     unsigned short height, unsigned char *data)
150871d7fec4Smrg#endif
150971d7fec4Smrg{
151071d7fec4Smrg   unsigned long dword_bytes_needed, bytes_extra;
151171d7fec4Smrg   long pitch, buffer_bytes, data_bytes;
151271d7fec4Smrg
151371d7fec4Smrg   /* CALCULATE DATA SIZE */
151471d7fec4Smrg
151571d7fec4Smrg   pitch = (width + 7) >> 3;
151671d7fec4Smrg   data_bytes = (long)height *pitch;
151771d7fec4Smrg
151871d7fec4Smrg   /* CHECK FOR SIMPLE CASE */
151971d7fec4Smrg   /* This routine is designed to render a source copy text glyph.  If destination */
152071d7fec4Smrg   /* data is required or the source data will not fit, we will punt the operation */
152171d7fec4Smrg   /* to the more versatile (and slow) mono bitmap routine.                        */
152271d7fec4Smrg
152371d7fec4Smrg   if (GFXbpp > 8)
152471d7fec4Smrg      buffer_bytes = GFXbufferWidthPixels << 1;
152571d7fec4Smrg   else
152671d7fec4Smrg      buffer_bytes = GFXbufferWidthPixels;
152771d7fec4Smrg
152871d7fec4Smrg   if (GFXusesDstData || data_bytes > buffer_bytes) {
152971d7fec4Smrg      gfx_mono_bitmap_to_screen_blt(0, 0, dstx, dsty, width, height, data,
153071d7fec4Smrg				    (short)pitch);
153171d7fec4Smrg      return;
153271d7fec4Smrg   }
153371d7fec4Smrg
153471d7fec4Smrg   /* SET THE SCRATCHPAD BASE */
153571d7fec4Smrg
153671d7fec4Smrg   SET_SCRATCH_BASE(GFXbb0Base);
153771d7fec4Smrg
153871d7fec4Smrg   /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
153971d7fec4Smrg
154071d7fec4Smrg   dword_bytes_needed = data_bytes & ~3l;
154171d7fec4Smrg   bytes_extra = data_bytes & 3l;
154271d7fec4Smrg
154371d7fec4Smrg   GFX_WAIT_PENDING;
154471d7fec4Smrg   WRITE_REG16(GP_HEIGHT, height);
154571d7fec4Smrg   WRITE_REG16(GP_WIDTH, width);
154671d7fec4Smrg   WRITE_REG16(GP_DST_XCOOR, dstx);
154771d7fec4Smrg   WRITE_REG16(GP_DST_YCOOR, dsty);
154871d7fec4Smrg   WRITE_REG16(GP_SRC_XCOOR, 0);
154971d7fec4Smrg
155071d7fec4Smrg   /* WRITE ALL DATA TO THE BLT BUFFERS */
155171d7fec4Smrg   /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */
155271d7fec4Smrg   /* scratchpad offset set by the SET_SCRATCH_BASE macro.               */
155371d7fec4Smrg
155471d7fec4Smrg   GFX_WAIT_PIPELINE;
155571d7fec4Smrg
155671d7fec4Smrg   WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 0);
155771d7fec4Smrg   WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_SOURCE_TEXT);
155871d7fec4Smrg}
155971d7fec4Smrg
156071d7fec4Smrg/*
156171d7fec4Smrg//----------------------------------------------------------------------------
156271d7fec4Smrg// BRESENHAM LINE
156371d7fec4Smrg//
156471d7fec4Smrg// This routine draws a vector using the specified Bresenham parameters.
156571d7fec4Smrg// Currently this file does not support a routine that accepts the two
156671d7fec4Smrg// endpoints of a vector and calculates the Bresenham parameters.  If it
156771d7fec4Smrg// ever does, this routine is still required for vectors that have been
156871d7fec4Smrg// clipped.
156971d7fec4Smrg//
157071d7fec4Smrg//      X               screen X position to start vector
157171d7fec4Smrg//      Y               screen Y position to start vector
157271d7fec4Smrg//      LENGTH          length of the vector, in pixels
157371d7fec4Smrg//      INITERR         Bresenham initial error term
157471d7fec4Smrg//      AXIALERR        Bresenham axial error term
157571d7fec4Smrg//      DIAGERR         Bresenham diagonal error term
157671d7fec4Smrg//      FLAGS           VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC
157771d7fec4Smrg//----------------------------------------------------------------------------
157871d7fec4Smrg*/
157971d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
158071d7fec4Smrgvoid
158171d7fec4Smrggu1_bresenham_line(unsigned short x, unsigned short y,
158271d7fec4Smrg		   unsigned short length, unsigned short initerr,
158371d7fec4Smrg		   unsigned short axialerr, unsigned short diagerr,
158471d7fec4Smrg		   unsigned short flags)
158571d7fec4Smrg#else
158671d7fec4Smrgvoid
158771d7fec4Smrggfx_bresenham_line(unsigned short x, unsigned short y,
158871d7fec4Smrg		   unsigned short length, unsigned short initerr,
158971d7fec4Smrg		   unsigned short axialerr, unsigned short diagerr,
159071d7fec4Smrg		   unsigned short flags)
159171d7fec4Smrg#endif
159271d7fec4Smrg{
159371d7fec4Smrg   unsigned short vector_mode = flags;
159471d7fec4Smrg
159571d7fec4Smrg   if (GFXusesDstData)
159671d7fec4Smrg      vector_mode |= VM_READ_DST_FB;
159771d7fec4Smrg
159871d7fec4Smrg   /* CHECK NULL LENGTH */
159971d7fec4Smrg
160071d7fec4Smrg   if (!length)
160171d7fec4Smrg      return;
160271d7fec4Smrg
160371d7fec4Smrg   /* LOAD THE REGISTERS FOR THE VECTOR */
160471d7fec4Smrg
160571d7fec4Smrg   GFX_WAIT_PENDING;
160671d7fec4Smrg   WRITE_REG16(GP_DST_XCOOR, x);
160771d7fec4Smrg   WRITE_REG16(GP_DST_YCOOR, y);
160871d7fec4Smrg   WRITE_REG16(GP_VECTOR_LENGTH, length);
160971d7fec4Smrg   WRITE_REG16(GP_INIT_ERROR, initerr);
161071d7fec4Smrg   WRITE_REG16(GP_AXIAL_ERROR, axialerr);
161171d7fec4Smrg   WRITE_REG16(GP_DIAG_ERROR, diagerr);
161271d7fec4Smrg   WRITE_REG16(GP_VECTOR_MODE, vector_mode);
161371d7fec4Smrg}
161471d7fec4Smrg
161571d7fec4Smrg/*---------------------------------------------------------------------------
161671d7fec4Smrg * GFX_WAIT_UNTIL_IDLE
161771d7fec4Smrg *
161871d7fec4Smrg * This routine waits until the graphics engine is idle.  This is required
161971d7fec4Smrg * before allowing direct access to the frame buffer.
162071d7fec4Smrg *---------------------------------------------------------------------------
162171d7fec4Smrg */
162271d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
162371d7fec4Smrgvoid
162471d7fec4Smrggu1_wait_until_idle(void)
162571d7fec4Smrg#else
162671d7fec4Smrgvoid
162771d7fec4Smrggfx_wait_until_idle(void)
162871d7fec4Smrg#endif
162971d7fec4Smrg{
163071d7fec4Smrg   GFX_WAIT_BUSY;
163171d7fec4Smrg}
163271d7fec4Smrg
163371d7fec4Smrg/*---------------------------------------------------------------------------
163471d7fec4Smrg * GFX_TEST_BLT_PENDING
163571d7fec4Smrg *
163671d7fec4Smrg * This routine returns 1 if a BLT is pending, meaning that a call to
163771d7fec4Smrg * perform a rendering operation would stall.  Otherwise it returns 0.
163871d7fec4Smrg * It is used by Darwin during random testing to only start a BLT
163971d7fec4Smrg * operation when it knows the Durango routines won't spin on graphics
164071d7fec4Smrg * (so Darwin can continue to do frame buffer reads and writes).
164171d7fec4Smrg *---------------------------------------------------------------------------
164271d7fec4Smrg */
164371d7fec4Smrg#if GFX_2DACCEL_DYNAMIC
164471d7fec4Smrgint
164571d7fec4Smrggu1_test_blt_pending(void)
164671d7fec4Smrg#else
164771d7fec4Smrgint
164871d7fec4Smrggfx_test_blt_pending(void)
164971d7fec4Smrg#endif
165071d7fec4Smrg{
165171d7fec4Smrg   if (READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING)
165271d7fec4Smrg      return (1);
165371d7fec4Smrg   else
165471d7fec4Smrg      return (0);
165571d7fec4Smrg}
165671d7fec4Smrg
165771d7fec4Smrg/*---------------------------------------------------------------------------
165871d7fec4Smrg * BLT BUFFERS!!!!!
165971d7fec4Smrg *---------------------------------------------------------------------------
166071d7fec4Smrg */
166171d7fec4Smrg
166271d7fec4Smrg/* THE BOOT CODE MUST SET THE BLT BUFFER BASES USING THE "CPU_WRITE" */
166371d7fec4Smrg/* INSTRUCTION TO ONE OF THE FOLLOWING VALUES: */
166471d7fec4Smrg
166571d7fec4Smrg#define BB0_BASE_2K		0x800
166671d7fec4Smrg#define BB1_BASE_2K		0xB30
166771d7fec4Smrg#define BB0_BASE_3K		0x400
166871d7fec4Smrg#define BB1_BASE_3K		0x930
166971d7fec4Smrg
167071d7fec4Smrg/*---------------------------------------------------------------------------
167171d7fec4Smrg * gu1_detect_blt_buffer_base
167271d7fec4Smrg *
167371d7fec4Smrg * This detection is hidden from the driver by being called from the
167471d7fec4Smrg * "gfx_set_bpp" routine.
167571d7fec4Smrg *
167671d7fec4Smrg * This is fairly ugly for the following reasons:
167771d7fec4Smrg *
167871d7fec4Smrg * - It is the boot code that must set the BLT buffer bases to the
167971d7fec4Smrg *   appropriate values and load the scratchpad tags.
168071d7fec4Smrg * - The old drivers would also set the base address values to what they
168171d7fec4Smrg *   knew they should be for the 2K or 3K scratchpad configuration.
168271d7fec4Smrg * - Unfortunately, to set the base addresses requires the use of the
168371d7fec4Smrg *   CPU_WRITE instruction, an instruction specific to GX.
168471d7fec4Smrg * - Using the CPU_WRITE instruction requires the use of assembly to
168571d7fec4Smrg *   produce the appropriate op codes.
168671d7fec4Smrg * - Assembly is something that is avoided in Durango because it is not
168771d7fec4Smrg *   platform independent.  Some compilers do not support inline assembly.
168871d7fec4Smrg * - Therefore Durango cannot use the CPU_WRITE instruction.
168971d7fec4Smrg * - Therefore drivers using Durango must rely on the boot code to set
169071d7fec4Smrg *   the appropriate values.  Durango uses this routine to check where
169171d7fec4Smrg *   the base addresses have been set.
169271d7fec4Smrg * - Unfortunately, it is not as simple as using IO to check for 2K or 3K
169371d7fec4Smrg *   scratchpad size.  In VSA1, even though the boot code may set it for
169471d7fec4Smrg *   3K, SoftVGA comes along and resets it to 2K for it's use in text
169571d7fec4Smrg *   redraws.  It used to be that the display driver would set it back
169671d7fec4Smrg *   to 3K.
169771d7fec4Smrg * - So, the Durango code was changed to just always use 2K.
169871d7fec4Smrg * - But, the XpressROM code sets it for 3K, and the newer versions of
169971d7fec4Smrg *   SoftVGA do not interfere with that, so then Durango needs to use
170071d7fec4Smrg *   the 3K values to work properly.
170171d7fec4Smrg * - Therefore, Durango does somewhat of a kludge by writing to directly
170271d7fec4Smrg *   to the scratchpad at both the 2K and 3K locations, then performing
170371d7fec4Smrg *   a unobtrusive BLT that loads data into BB0 (the graphics engine
170471d7fec4Smrg *   always knows the true base).  After the BLT, Durango looks to see
170571d7fec4Smrg *   which location changed to know where the base address is.
170671d7fec4Smrg * - This is a relatively simple way to allow Durango to work on old
170771d7fec4Smrg *   and new platforms without using theCPU_WRITE instructions.
170871d7fec4Smrg *
170971d7fec4Smrg * To summarize, the BLT buffers are one of the most painful aspects of
171071d7fec4Smrg * the GX graphics unit design, and have been removed from future designs
171171d7fec4Smrg * (the graphics unit has its own dedicated RAM).  Durango has tried to
171271d7fec4Smrg * hide the BLT buffer use from the drivers.
171371d7fec4Smrg *---------------------------------------------------------------------------
171471d7fec4Smrg */
171571d7fec4Smrgvoid
171671d7fec4Smrggu1_detect_blt_buffer_base(void)
171771d7fec4Smrg{
171871d7fec4Smrg   /* ASSUME 2K */
171971d7fec4Smrg
172071d7fec4Smrg   GFXbb0Base = BB0_BASE_2K;
172171d7fec4Smrg   GFXbb1Base = BB1_BASE_2K;
172271d7fec4Smrg
172371d7fec4Smrg   /* CHECK IF SCRATCHPAD IS SET TO 3K OR 4K */
172471d7fec4Smrg   /* Boot code should still set 3K values for 4K. */
172571d7fec4Smrg
172671d7fec4Smrg   if (gfx_gxm_config_read(GXM_CONFIG_GCR) & 0x08) {
172771d7fec4Smrg      /* WRITE DATA TO 3K LOCATION */
172871d7fec4Smrg
172971d7fec4Smrg      GFX_WAIT_BUSY;
173071d7fec4Smrg      WRITE_SCRATCH32(BB0_BASE_3K, 0xFEEDFACE);
173171d7fec4Smrg
173271d7fec4Smrg      /* HAVE THE GRAPHICS UNIT STORE SOMETHING IN BB0 */
173371d7fec4Smrg
173471d7fec4Smrg      WRITE_REG32(GP_DST_XCOOR, 0x00000000);	/* AT (0,0) */
173571d7fec4Smrg      WRITE_REG32(GP_WIDTH, 0x00010004);	/* 4x1 BLT */
173671d7fec4Smrg      WRITE_REG16(GP_RASTER_MODE, 0x00AA);	/* KEEP DST */
173771d7fec4Smrg      WRITE_REG16(GP_BLIT_MODE, BM_READ_DST_FB0);	/* STORE IN BB0 */
173871d7fec4Smrg
173971d7fec4Smrg      /* CHECK 3K LOCATION */
174071d7fec4Smrg      /* Breaks if data happened to be 0xFEEDFACE - unlikely. */
174171d7fec4Smrg
174271d7fec4Smrg      GFX_WAIT_BUSY;
174371d7fec4Smrg      if (READ_SCRATCH32(BB0_BASE_3K) != 0xFEEDFACE) {
174471d7fec4Smrg	 GFXbb0Base = BB0_BASE_3K;
174571d7fec4Smrg	 GFXbb1Base = BB1_BASE_3K;
174671d7fec4Smrg      }
174771d7fec4Smrg   }
174871d7fec4Smrg}
174971d7fec4Smrg
175071d7fec4Smrg/* END OF FILE */
1751