cim_gp.c revision 04007eba
1f29dbc25Smrg/*
2f29dbc25Smrg * Copyright (c) 2006 Advanced Micro Devices, Inc.
3f29dbc25Smrg *
4f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5f29dbc25Smrg * copy of this software and associated documentation files (the "Software"),
6f29dbc25Smrg * to deal in the Software without restriction, including without limitation
7f29dbc25Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f29dbc25Smrg * and/or sell copies of the Software, and to permit persons to whom the
9f29dbc25Smrg * Software is furnished to do so, subject to the following conditions:
10f29dbc25Smrg *
11f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
12f29dbc25Smrg * all copies or substantial portions of the Software.
13f29dbc25Smrg *
14f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20f29dbc25Smrg * DEALINGS IN THE SOFTWARE.
21f29dbc25Smrg *
22f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
23f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
24f29dbc25Smrg * software without specific prior written permission.
25f29dbc25Smrg */
26f29dbc25Smrg
27f29dbc25Smrg /*
28f29dbc25Smrg  * Cimarron graphics processor routines.  These routines program the graphics
29f29dbc25Smrg  * hardware using the graphics command buffer.
30f29dbc25Smrg  */
31f29dbc25Smrg
32f29dbc25Smrg/*---------------------*/
33f29dbc25Smrg/* CIMARRON GP GLOBALS */
34f29dbc25Smrg/*---------------------*/
35f29dbc25Smrg
36f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_bpp = 0;
37f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_ch3_bpp = 0;
38f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_pat_origin = 0;
39f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_buffer_lead = 0;
40f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_cmd_header;
41f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_cmd_top;
42f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_cmd_bottom;
43f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_cmd_current;
44f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_cmd_next;
45f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_blt_mode;
46f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_vec_mode;
47f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_raster_mode;
48f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_pix_shift;
49f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_ch3_pat;
50f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_blt;
51f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_blt_flags;
52f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_src_stride;
53f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_dst_stride;
54f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_src_format;
55f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_src_pix_shift;
56f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_pat_format;
57f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_pat_pix_shift;
58f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_fb_base;
59f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_vector_pattern_color;
60f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_scratch_base;
61f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_base_register;
62f29dbc25SmrgCIMARRON_STATIC unsigned long gp3_vec_pat;
63f29dbc25Smrg
64f29dbc25Smrg/*---------------------------------------------------------------------------
65f29dbc25Smrg * gp_set_limit_on_buffer_lead
66f29dbc25Smrg *
67f29dbc25Smrg * This routine is used to specify the maximum number of bytes in the command
68f29dbc25Smrg * buffer by which software can lead the graphics processor.  When declaring
69f29dbc25Smrg * a BLT with the CIMGP_BLTFLAGS_LIMITBUFFER flag set, Cimarron will wait
70f29dbc25Smrg * until the command buffer read and write pointers differ by no more than
71f29dbc25Smrg * 'lead' bytes.  This can be useful to limit the time lag possible when
72f29dbc25Smrg * creating a command buffer full of simple BLT commands.
73f29dbc25Smrg *-------------------------------------------------------------------------*/
74f29dbc25Smrg
75f29dbc25Smrgvoid
76f29dbc25Smrggp_set_limit_on_buffer_lead(unsigned long lead)
77f29dbc25Smrg{
78f29dbc25Smrg    gp3_buffer_lead = lead;
79f29dbc25Smrg}
80f29dbc25Smrg
81f29dbc25Smrg/*---------------------------------------------------------------------------
82f29dbc25Smrg * gp_set_command_buffer_base
83f29dbc25Smrg *
84f29dbc25Smrg * This routine is used to program the command buffer region in physical
85f29dbc25Smrg * memory.  The command buffer start address must be 1MB aligned. start and
86f29dbc25Smrg * stop refer to endpoints within the associated 16MB region.  Command buffers
87f29dbc25Smrg * larger than 16MB are not supported.
88f29dbc25Smrg *-------------------------------------------------------------------------*/
89f29dbc25Smrg
90f29dbc25Smrgvoid
91f29dbc25Smrggp_set_command_buffer_base(unsigned long address, unsigned long start,
9204007ebaSmrg                           unsigned long stop)
93f29dbc25Smrg{
94f29dbc25Smrg    Q_WORD msr_value;
95f29dbc25Smrg
96f29dbc25Smrg    /* WAIT FOR IDLE */
97f29dbc25Smrg    /* Obviously, we cannot change the command buffer pointer while the GP */
98f29dbc25Smrg    /* is currently fetching commands.                                     */
99f29dbc25Smrg
100f29dbc25Smrg    gp_wait_until_idle();
101f29dbc25Smrg
102f29dbc25Smrg    /* WRITE THE COMMAND BUFFER BASE */
103f29dbc25Smrg
104f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
105f29dbc25Smrg    msr_value.low &= 0xF000FFFF;
106f29dbc25Smrg    msr_value.low |= (address >> 4) & 0x0FFF0000;
107f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
108f29dbc25Smrg
109f29dbc25Smrg    /* WRITE THE BASE OFFSETS */
110f29dbc25Smrg    /* We also reset the write and read pointers.  The hardware will */
111f29dbc25Smrg    /* automatically update the write pointer when the read pointer  */
112f29dbc25Smrg    /* is updated to prevent the hardware from getting confused when */
113f29dbc25Smrg    /* initializing a new command buffer.                            */
114f29dbc25Smrg
115f29dbc25Smrg    WRITE_GP32(GP3_CMD_TOP, start);
116f29dbc25Smrg    WRITE_GP32(GP3_CMD_BOT, stop);
117f29dbc25Smrg    WRITE_GP32(GP3_CMD_READ, start);
118f29dbc25Smrg
119f29dbc25Smrg    /* SAVE THE BASE ADDRESSES */
120f29dbc25Smrg    /* These are used to determine the appropriate wrap point. */
121f29dbc25Smrg
122f29dbc25Smrg    gp3_cmd_current = gp3_cmd_top = start;
123f29dbc25Smrg    gp3_cmd_bottom = stop;
124f29dbc25Smrg}
125f29dbc25Smrg
126f29dbc25Smrg/*---------------------------------------------------------------------------
127f29dbc25Smrg * gp_set_frame_buffer_base
128f29dbc25Smrg *
129f29dbc25Smrg * This routine is used to program the base address of the frame buffer in
130f29dbc25Smrg * physical memory.  The frame buffer address must be 16MB aligned.  Cimarron
131f29dbc25Smrg * tracks the base address because the maximum frame buffer size may exceed
132f29dbc25Smrg * 16MB. Any primitive will thus program the corresponding 16MB region into
133f29dbc25Smrg * all base offset registers as well as program the offset into the 16MB
134f29dbc25Smrg * region.  The size parameter is provided to allow Cimarron to claim the
135f29dbc25Smrg * last 1MB of space to be used as a scratch area for workarounds or
136f29dbc25Smrg * expanded functionality.
137f29dbc25Smrg *-------------------------------------------------------------------------*/
138f29dbc25Smrg
139f29dbc25Smrgvoid
140f29dbc25Smrggp_set_frame_buffer_base(unsigned long address, unsigned long size)
141f29dbc25Smrg{
142f29dbc25Smrg    gp3_scratch_base = size - GP3_SCRATCH_BUFFER_SIZE;
143f29dbc25Smrg    gp3_fb_base = address >> 24;
144f29dbc25Smrg    gp3_base_register =
145f29dbc25Smrg        (gp3_fb_base << 24) | (gp3_fb_base << 14) | (gp3_fb_base << 4);
146f29dbc25Smrg    WRITE_GP32(GP3_BASE_OFFSET, gp3_base_register);
147f29dbc25Smrg}
148f29dbc25Smrg
149f29dbc25Smrg/*---------------------------------------------------------------------------
150f29dbc25Smrg * gp_set_bpp
151f29dbc25Smrg *
152f29dbc25Smrg * This routine sets the output BPP of the GP.  The BPP used by the GP does
153f29dbc25Smrg * not have to match the display BPP, but that is usually the case.  The
154f29dbc25Smrg * supported BPP values are as follows:
155f29dbc25Smrg *
156f29dbc25Smrg *    8  - palettized 8BPP
157f29dbc25Smrg *    12 - 4:4:4:4
158f29dbc25Smrg *    15 - 1:5:5:5
159f29dbc25Smrg *    16 - 0:5:6:5
160f29dbc25Smrg *    32 - 8:8:8:8
161f29dbc25Smrg *-------------------------------------------------------------------------*/
162f29dbc25Smrg
163f29dbc25Smrgvoid
164f29dbc25Smrggp_set_bpp(int bpp)
165f29dbc25Smrg{
166f29dbc25Smrg    /* STORE BPP */
167f29dbc25Smrg    /* The bpp is not updated until the next call to gp_set_raster_mode. */
168f29dbc25Smrg    /* This allows the gp_set_bpp call to happen outside of a BLT.  It   */
169f29dbc25Smrg    /* also implies that no registers need be written in this routine.   */
170f29dbc25Smrg
171f29dbc25Smrg    switch (bpp) {
172f29dbc25Smrg    case 8:
173f29dbc25Smrg        gp3_bpp = GP3_RM_BPPFMT_332;
174f29dbc25Smrg        gp3_ch3_bpp = GP3_CH3_SRC_3_3_2;
175f29dbc25Smrg        gp3_pix_shift = 0;
176f29dbc25Smrg        break;
177f29dbc25Smrg    case 12:
178f29dbc25Smrg        gp3_bpp = GP3_RM_BPPFMT_4444;
179f29dbc25Smrg        gp3_ch3_bpp = GP3_CH3_SRC_4_4_4_4;
180f29dbc25Smrg        gp3_pix_shift = 1;
181f29dbc25Smrg        break;
182f29dbc25Smrg    case 15:
183f29dbc25Smrg        gp3_bpp = GP3_RM_BPPFMT_1555;
184f29dbc25Smrg        gp3_ch3_bpp = GP3_CH3_SRC_1_5_5_5;
185f29dbc25Smrg        gp3_pix_shift = 1;
186f29dbc25Smrg        break;
187f29dbc25Smrg    case 16:
188f29dbc25Smrg        gp3_bpp = GP3_RM_BPPFMT_565;
189f29dbc25Smrg        gp3_ch3_bpp = GP3_CH3_SRC_0_5_6_5;
190f29dbc25Smrg        gp3_pix_shift = 1;
191f29dbc25Smrg        break;
192f29dbc25Smrg    case 24:
193f29dbc25Smrg    case 32:
194f29dbc25Smrg        gp3_bpp = GP3_RM_BPPFMT_8888;
195f29dbc25Smrg        gp3_ch3_bpp = GP3_CH3_SRC_8_8_8_8;
196f29dbc25Smrg        gp3_pix_shift = 2;
197f29dbc25Smrg        break;
198f29dbc25Smrg    default:
199f29dbc25Smrg        gp3_bpp = GP3_RM_BPPFMT_332;
200f29dbc25Smrg        gp3_ch3_bpp = GP3_CH3_SRC_3_3_2;
201f29dbc25Smrg        gp3_pix_shift = 0;
202f29dbc25Smrg        break;
203f29dbc25Smrg    }
204f29dbc25Smrg}
205f29dbc25Smrg
206f29dbc25Smrg/*---------------------------------------------------------------------------
207f29dbc25Smrg * gp_declare_blt
208f29dbc25Smrg *
209f29dbc25Smrg * This routine is used to prepare for a 2D BLT.  Its primary function
210f29dbc25Smrg * is to verify that enough room is available in the command buffer
211f29dbc25Smrg * to hold a BLT command.  This command can be called multiple times if
212f29dbc25Smrg * necessary.  For example, if a function calls this routine on entry, but
213f29dbc25Smrg * later realizes that a LUT load command must be executed before the BLT,
214f29dbc25Smrg * the application could call gp_set_color_pattern and then call
215f29dbc25Smrg * gp_declare_blt to declare the BLT.  This is possible because the hardware
216f29dbc25Smrg * buffer pointer is not updated until a new BLT is actually executed.  An
217f29dbc25Smrg * application must take care not to call any routines that perform a buffer
218f29dbc25Smrg * command, (such as gp_set_color_pattern) between gp_declare_blt and the
219f29dbc25Smrg * routines used to program the BLT parameters.  In addition to checking for
220f29dbc25Smrg * available space, this routine also performs the following actions:
221f29dbc25Smrg *    - Sets the wrap bit if this BLT will pass close to the end of the
222f29dbc25Smrg *		buffer.
223f29dbc25Smrg *    - Writes the command header.
224f29dbc25Smrg *
225f29dbc25Smrg * The available flags are defined as follows:
226f29dbc25Smrg *   0x01 - Preserve the LUT
227f29dbc25Smrg *   0x02 - Preserve the color pattern.
228f29dbc25Smrg *   0x04 - Enable prefetch.
229f29dbc25Smrg *-------------------------------------------------------------------------*/
230f29dbc25Smrg
231f29dbc25Smrgvoid
232f29dbc25Smrggp_declare_blt(unsigned long flags)
233f29dbc25Smrg{
234f29dbc25Smrg    unsigned long temp;
235f29dbc25Smrg
236f29dbc25Smrg    gp3_blt = 1;
237f29dbc25Smrg    gp3_blt_flags = flags;
238f29dbc25Smrg
239f29dbc25Smrg    /* SET ADDRESS OF NEXT COMMAND */
240f29dbc25Smrg    /* A summary of the command buffer logic is as follows:           */
241f29dbc25Smrg    /*  - If after a basic BLT we will not have room for the largest  */
242f29dbc25Smrg    /*    command (a full line of host source data), we set the wrap  */
243f29dbc25Smrg    /*    bit.  This will waste up to a whopping 8K of command buffer */
244f29dbc25Smrg    /*    space, but it simplifies the logic for all commands.        */
245f29dbc25Smrg    /* -  If we are wrapping, we have extra logic to ensure that we   */
246f29dbc25Smrg    /*    don't skip over the current GP read pointer.                */
247f29dbc25Smrg
248f29dbc25Smrg    gp3_cmd_next = gp3_cmd_current + GP3_BLT_COMMAND_SIZE;
249f29dbc25Smrg
250f29dbc25Smrg    /* CHECK WRAP CONDITION */
251f29dbc25Smrg
252f29dbc25Smrg    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
253f29dbc25Smrg        gp3_cmd_next = gp3_cmd_top;
254f29dbc25Smrg        gp3_cmd_header = GP3_BLT_HDR_TYPE | GP3_BLT_HDR_WRAP;
255f29dbc25Smrg
256f29dbc25Smrg        /* WAIT FOR HARDWARE */
257f29dbc25Smrg        /* When wrapping, we must take steps to ensure that we do not    */
258f29dbc25Smrg        /* wrap over the current hardware read pointer.  We do this by   */
259f29dbc25Smrg        /* verifying that the hardware is not between us and the end of  */
260f29dbc25Smrg        /* the command buffer.  We also have a special case to make sure */
261f29dbc25Smrg        /* that the hardware is not currently reading the top of the     */
262f29dbc25Smrg        /* command buffer.                                               */
263f29dbc25Smrg
264f29dbc25Smrg        GP3_WAIT_WRAP(temp);
26504007ebaSmrg    }
26604007ebaSmrg    else {
267f29dbc25Smrg        gp3_cmd_header = GP3_BLT_HDR_TYPE;
268f29dbc25Smrg
269f29dbc25Smrg        /* WAIT FOR AVAILABLE SPACE */
270f29dbc25Smrg
271f29dbc25Smrg        GP3_WAIT_PRIMITIVE(temp);
272f29dbc25Smrg    }
273f29dbc25Smrg
274f29dbc25Smrg    if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) {
275f29dbc25Smrg        while (1) {
276f29dbc25Smrg            temp = READ_GP32(GP3_CMD_READ);
277f29dbc25Smrg            if (((gp3_cmd_current >= temp)
27804007ebaSmrg                 && ((gp3_cmd_current - temp) <= gp3_buffer_lead))
279f29dbc25Smrg                || ((gp3_cmd_current < temp)
280f29dbc25Smrg                    && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <=
281f29dbc25Smrg                        gp3_buffer_lead))) {
282f29dbc25Smrg                break;
283f29dbc25Smrg            }
284f29dbc25Smrg        }
285f29dbc25Smrg    }
286f29dbc25Smrg
287f29dbc25Smrg    /* SET THE CURRENT BUFFER POINTER */
288f29dbc25Smrg    /* We initialize a pointer to the current buffer base to avoid an */
289f29dbc25Smrg    /* extra addition for every buffer write.                         */
290f29dbc25Smrg
291f29dbc25Smrg    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
292f29dbc25Smrg
293f29dbc25Smrg    /* SET THE HAZARD BIT */
294f29dbc25Smrg
295f29dbc25Smrg    if (flags & CIMGP_BLTFLAGS_HAZARD)
296f29dbc25Smrg        gp3_cmd_header |= GP3_BLT_HDR_HAZARD_ENABLE;
297f29dbc25Smrg}
298f29dbc25Smrg
299f29dbc25Smrg/*---------------------------------------------------------------------------
300f29dbc25Smrg * gp_declare_vector
301f29dbc25Smrg *
302f29dbc25Smrg * This routine is used to prepare for a 2D vector.  It has no other function
303f29dbc25Smrg * except to verify that enough room is available in the command buffer
304f29dbc25Smrg * to hold a vector command.  The same rules that apply to BLTs apply to
305f29dbc25Smrg * vectors. (See the documentation for gp_declare_blt).
306f29dbc25Smrg *-------------------------------------------------------------------------*/
307f29dbc25Smrg
308f29dbc25Smrgvoid
309f29dbc25Smrggp_declare_vector(unsigned long flags)
310f29dbc25Smrg{
311f29dbc25Smrg    unsigned long temp;
312f29dbc25Smrg
313f29dbc25Smrg    gp3_blt = 0;
314f29dbc25Smrg    gp3_blt_flags = flags;
315f29dbc25Smrg
316f29dbc25Smrg    /* SET ADDRESS OF NEXT COMMAND                            */
317f29dbc25Smrg    /* The logic to force a wrap during a vector is identical */
318f29dbc25Smrg    /* to the BLT logic.                                      */
319f29dbc25Smrg
320f29dbc25Smrg    /* ALLOCATE SPACE FOR AN ADDITIONAL VECTOR TO CLEAR THE BYTE ENABLES */
321f29dbc25Smrg
322f29dbc25Smrg    gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_COMMAND_SIZE +
323f29dbc25Smrg        GP3_VECTOR_COMMAND_SIZE + 32;
324f29dbc25Smrg
325f29dbc25Smrg    /* CHECK WRAP CONDITION */
326f29dbc25Smrg
327f29dbc25Smrg    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
328f29dbc25Smrg        gp3_cmd_next = gp3_cmd_top;
329f29dbc25Smrg        gp3_cmd_header = GP3_VEC_HDR_TYPE | GP3_VEC_HDR_WRAP;
330f29dbc25Smrg
331f29dbc25Smrg        /* CHECK WRAP CONDITION */
332f29dbc25Smrg
333f29dbc25Smrg        GP3_WAIT_WRAP(temp);
33404007ebaSmrg    }
33504007ebaSmrg    else {
336f29dbc25Smrg        gp3_cmd_header = GP3_VEC_HDR_TYPE;
337f29dbc25Smrg
338f29dbc25Smrg        /* WAIT FOR AVAILABLE SPACE */
339f29dbc25Smrg
340f29dbc25Smrg        GP3_WAIT_PRIMITIVE(temp);
341f29dbc25Smrg
342f29dbc25Smrg        gp3_cmd_next -= GP3_VECTOR_COMMAND_SIZE + 32;
343f29dbc25Smrg    }
344f29dbc25Smrg
345f29dbc25Smrg    if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) {
346f29dbc25Smrg        while (1) {
347f29dbc25Smrg            temp = READ_GP32(GP3_CMD_READ);
348f29dbc25Smrg            if (((gp3_cmd_current >= temp)
34904007ebaSmrg                 && ((gp3_cmd_current - temp) <= gp3_buffer_lead))
350f29dbc25Smrg                || ((gp3_cmd_current < temp)
351f29dbc25Smrg                    && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <=
352f29dbc25Smrg                        gp3_buffer_lead))) {
353f29dbc25Smrg                break;
354f29dbc25Smrg            }
355f29dbc25Smrg        }
356f29dbc25Smrg    }
357f29dbc25Smrg
358f29dbc25Smrg    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
359f29dbc25Smrg
360f29dbc25Smrg    /* SET THE HAZARD BIT */
361f29dbc25Smrg
362f29dbc25Smrg    if (flags & CIMGP_BLTFLAGS_HAZARD)
363f29dbc25Smrg        gp3_cmd_header |= GP3_VEC_HDR_HAZARD_ENABLE;
364f29dbc25Smrg}
365f29dbc25Smrg
366f29dbc25Smrg/*---------------------------------------------------------------------------
367f29dbc25Smrg * gp_write_parameters
368f29dbc25Smrg *
369f29dbc25Smrg * This routine is called to write all recent parameters to the hardware.
370f29dbc25Smrg * This routine is necessary for any implementation that performs the setup
371f29dbc25Smrg * for a BLT separate from the actual BLT.  An example would be a driver
372f29dbc25Smrg * that prepares for multiple pattern fills by programming the ROP,
373f29dbc25Smrg * pattern color and destination stride.  The driver might then perform
374f29dbc25Smrg * repeated pattern fills with minimal effort.
375f29dbc25Smrg *-------------------------------------------------------------------------*/
376f29dbc25Smrg
377f29dbc25Smrgvoid
378f29dbc25Smrggp_write_parameters(void)
379f29dbc25Smrg{
380f29dbc25Smrg    /* WRITE THE COMMAND HEADER */
381f29dbc25Smrg    /* Command header is at offset 0 for BLTs and vectors */
382f29dbc25Smrg
383f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
384f29dbc25Smrg
385f29dbc25Smrg    /* INCREMENT THE CURRENT WRITE POINTER */
386f29dbc25Smrg
387f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
388f29dbc25Smrg
389f29dbc25Smrg    /* UPDATE THE GP WRITE POINTER */
390f29dbc25Smrg
391f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_current);
392f29dbc25Smrg}
393f29dbc25Smrg
394f29dbc25Smrg/*---------------------------------------------------------------------------
395f29dbc25Smrg * gp_set_raster_operation
396f29dbc25Smrg *
397f29dbc25Smrg * This is generally the first routine called when programming a BLT.  This
398f29dbc25Smrg * routine performs the following functions:
399f29dbc25Smrg *   - Sets the initial value of the GP3_RASTER_MODE register in the buffer.
400f29dbc25Smrg *   - Clears any 8x8 pattern if the ROP does not involve pattern data.
401f29dbc25Smrg *-------------------------------------------------------------------------*/
402f29dbc25Smrg
403f29dbc25Smrgvoid
404f29dbc25Smrggp_set_raster_operation(unsigned char ROP)
405f29dbc25Smrg{
406f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
407f29dbc25Smrg
408f29dbc25Smrg    /* WRITE THE RASTER MODE REGISTER                                   */
409f29dbc25Smrg    /* This register is in the same location in BLT and vector commands */
410f29dbc25Smrg
41104007ebaSmrg    gp3_raster_mode = gp3_bpp | (unsigned long) ROP;
412f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
413f29dbc25Smrg
414f29dbc25Smrg    /* CHECK IF DESTINATION IS REQUIRED */
415f29dbc25Smrg
416f29dbc25Smrg    if ((ROP & 0x55) ^ ((ROP >> 1) & 0x55)) {
417f29dbc25Smrg        gp3_blt_mode = GP3_BM_DST_REQ;
418f29dbc25Smrg        gp3_vec_mode = GP3_VM_DST_REQ;
41904007ebaSmrg    }
42004007ebaSmrg    else {
421f29dbc25Smrg        gp3_blt_mode = gp3_vec_mode = 0;
422f29dbc25Smrg    }
423f29dbc25Smrg}
424f29dbc25Smrg
425f29dbc25Smrg/*----------------------------------------------------------------------------
426f29dbc25Smrg * gp_set_alpha_operation
427f29dbc25Smrg *
428f29dbc25Smrg * BLTs are generally one of two types, a ROPed BLT or a BLT composited using
429f29dbc25Smrg * alpha blending.  For the latter, this routine is used to configure the
430f29dbc25Smrg * mathematical function used to create the blended output.  This routine
431f29dbc25Smrg * should generally be called first when programming a BLT.  The available
432f29dbc25Smrg * parameters mirror the hardware and are described as follows:
433f29dbc25Smrg *
434f29dbc25Smrg * alpha_operation =
435f29dbc25Smrg *   0 - alpha * A
436f29dbc25Smrg *   1 - (1 - alpha) * B
437f29dbc25Smrg *   2 - A + (1 - alpha)*B
438f29dbc25Smrg *   3 - alpha*A + (1 - alpha)*B
439f29dbc25Smrg *
440f29dbc25Smrg * alpha_type =
441f29dbc25Smrg *   0 - alpha component of channel A
442f29dbc25Smrg *   1 - alpha component of channel B
443f29dbc25Smrg *   2 - Constant alpha
444f29dbc25Smrg *   3 - Constant 1
445f29dbc25Smrg *   4 - The color components of channel A
446f29dbc25Smrg *   5 - The color components of channel B
447f29dbc25Smrg *   6 - Alpha comes from the alpha channel of the source before the source
448f29dbc25Smrg *		 undergoes color conversion.
449f29dbc25Smrg *
450f29dbc25Smrg * channel =
451f29dbc25Smrg *   0 - Channel A = source, channel B = destination
452f29dbc25Smrg *   1 - Channel B = source, channel A = destination
453f29dbc25Smrg *
454f29dbc25Smrg * apply_alpha =
455f29dbc25Smrg *   1 - Apply alpha blend to only the RGB portion of the pixel.  This must be
456f29dbc25Smrg *       set when the source or destination format do not include an alpha
457f29dbc25Smrg *		 channel.
458f29dbc25Smrg *   2 - Apply alpha blend only to the alpha portion of the pixel.  This
459f29dbc25Smrg *		 implies that both destination and source include an alpha channel.
460f29dbc25Smrg *   3 - Apply alpha blend to both the RGB and alpha portions of the pixel.
461f29dbc25Smrg *
462f29dbc25Smrg * Alpha-blended vectors are not currently supported.
463f29dbc25Smrg *-------------------------------------------------------------------------*/
464f29dbc25Smrg
465f29dbc25Smrgvoid
466f29dbc25Smrggp_set_alpha_operation(int alpha_operation, int alpha_type, int channel,
46704007ebaSmrg                       int apply_alpha, unsigned char alpha)
468f29dbc25Smrg{
469f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
470f29dbc25Smrg
471f29dbc25Smrg    /* THE AVAILABLE ALPHA DEFINITIONS FOLLOW THE HARDWARE       */
472f29dbc25Smrg    /* This allows us to avoid giant switch structures, but it   */
473f29dbc25Smrg    /* also implies that there is no mechanism to detect invalid */
474f29dbc25Smrg    /* parameters.                                               */
475f29dbc25Smrg
47604007ebaSmrg    gp3_raster_mode = gp3_bpp | (unsigned long) alpha |
47704007ebaSmrg        ((unsigned long) apply_alpha << 22) |
47804007ebaSmrg        ((unsigned long) alpha_operation << 20) |
47904007ebaSmrg        ((unsigned long) alpha_type << 17) | ((unsigned long) channel << 16);
480f29dbc25Smrg
481f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
482f29dbc25Smrg
483f29dbc25Smrg    /* CHECK IF DESTINATION IS REQUIRED */
484f29dbc25Smrg
485f29dbc25Smrg    if ((alpha_operation == CIMGP_ALPHA_TIMES_A &&
48604007ebaSmrg         channel == CIMGP_CHANNEL_A_SOURCE &&
48704007ebaSmrg         alpha_type != CIMGP_CHANNEL_B_ALPHA &&
48804007ebaSmrg         alpha_type != CIMGP_ALPHA_FROM_RGB_B) ||
489f29dbc25Smrg        (alpha_operation == CIMGP_BETA_TIMES_B &&
49004007ebaSmrg         channel == CIMGP_CHANNEL_A_DEST &&
49104007ebaSmrg         alpha_type != CIMGP_CHANNEL_A_ALPHA &&
49204007ebaSmrg         alpha_type != CIMGP_ALPHA_FROM_RGB_A)) {
493f29dbc25Smrg        gp3_blt_mode = 0;
49404007ebaSmrg    }
49504007ebaSmrg    else
496f29dbc25Smrg        gp3_blt_mode = GP3_BM_DST_REQ;
497f29dbc25Smrg}
498f29dbc25Smrg
499f29dbc25Smrg/*---------------------------------------------------------------------------
500f29dbc25Smrg * gp_set_solid_pattern
501f29dbc25Smrg *
502f29dbc25Smrg * This routine is called to program the hardware for a solid pattern.  It
503f29dbc25Smrg * need not be called for any other reason.  As a side effect, this routine
504f29dbc25Smrg * will clear any 8x8 pattern data.
505f29dbc25Smrg *-------------------------------------------------------------------------*/
506f29dbc25Smrg
507f29dbc25Smrgvoid
508f29dbc25Smrggp_set_solid_pattern(unsigned long color)
509f29dbc25Smrg{
510f29dbc25Smrg    /* CHANNEL 3 IS NOT NEEDED FOR SOLID PATTERNS */
511f29dbc25Smrg
512f29dbc25Smrg    gp3_ch3_pat = 0;
513f29dbc25Smrg
514f29dbc25Smrg    /* SET SOLID PATTERN IN COMMAND BUFFER */
515f29dbc25Smrg    /* We are assuming that only one pattern type is ever set for a */
516f29dbc25Smrg    /* BLT.  We are also assuming that gp_set_raster_operation will */
517f29dbc25Smrg    /* be called before this routine.  With these assumptions, we   */
518f29dbc25Smrg    /* will thus never have to change the raster mode register for  */
519f29dbc25Smrg    /* solid patterns.                                              */
520f29dbc25Smrg
521f29dbc25Smrg    if (gp3_blt) {
522f29dbc25Smrg        gp3_cmd_header |= GP3_BLT_HDR_PAT_CLR0_ENABLE;
523f29dbc25Smrg
524f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, color);
52504007ebaSmrg    }
52604007ebaSmrg    else {
527f29dbc25Smrg        gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
528f29dbc25Smrg
529f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, color);
530f29dbc25Smrg    }
531f29dbc25Smrg}
532f29dbc25Smrg
533f29dbc25Smrg/*---------------------------------------------------------------------------
534f29dbc25Smrg * gp_set_mono_pattern
535f29dbc25Smrg *
536f29dbc25Smrg * This routine is called to program the hardware for a monochrome pattern.
537f29dbc25Smrg * As a side effect, this routine will clear any 8x8 pattern data.
538f29dbc25Smrg *-------------------------------------------------------------------------*/
539f29dbc25Smrg
540f29dbc25Smrgvoid
541f29dbc25Smrggp_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor,
54204007ebaSmrg                    unsigned long data0, unsigned long data1, int transparent,
54304007ebaSmrg                    int x, int y)
544f29dbc25Smrg{
545f29dbc25Smrg    /* CHANNEL 3 IS NOT NEEDED FOR MONOCHROME PATTERNS */
546f29dbc25Smrg
547f29dbc25Smrg    gp3_ch3_pat = 0;
548f29dbc25Smrg
549f29dbc25Smrg    /* UPDATE RASTER MODE REGISTER */
550f29dbc25Smrg
551f29dbc25Smrg    if (transparent)
552f29dbc25Smrg        gp3_raster_mode |= GP3_RM_PAT_MONO | GP3_RM_PAT_TRANS;
553f29dbc25Smrg    else
554f29dbc25Smrg        gp3_raster_mode |= GP3_RM_PAT_MONO;
555f29dbc25Smrg
556f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
557f29dbc25Smrg
558f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
559f29dbc25Smrg
560f29dbc25Smrg    /* SET MONOCHROME PATTERN DATA AND COLORS */
561f29dbc25Smrg
562f29dbc25Smrg    if (gp3_blt) {
563f29dbc25Smrg        gp3_cmd_header |=
564f29dbc25Smrg            (GP3_BLT_HDR_PAT_CLR0_ENABLE | GP3_BLT_HDR_PAT_CLR1_ENABLE |
56504007ebaSmrg             GP3_BLT_HDR_PAT_DATA0_ENABLE | GP3_BLT_HDR_PAT_DATA1_ENABLE);
566f29dbc25Smrg
567f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, bgcolor);
568f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_PAT_COLOR_1, fgcolor);
569f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_PAT_DATA_0, data0);
570f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_PAT_DATA_1, data1);
57104007ebaSmrg    }
57204007ebaSmrg    else {
573f29dbc25Smrg        gp3_cmd_header |=
574f29dbc25Smrg            (GP3_VEC_HDR_PAT_CLR0_ENABLE | GP3_VEC_HDR_PAT_CLR1_ENABLE |
57504007ebaSmrg             GP3_VEC_HDR_PAT_DATA0_ENABLE | GP3_VEC_HDR_PAT_DATA1_ENABLE);
576f29dbc25Smrg
577f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, bgcolor);
578f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_1, fgcolor);
579f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_0, data0);
580f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_1, data1);
581f29dbc25Smrg    }
582f29dbc25Smrg
583f29dbc25Smrg    /* SAVE PATTERN ORIGIN */
584f29dbc25Smrg
58504007ebaSmrg    gp3_pat_origin = ((unsigned long) y << 29) |
58604007ebaSmrg        (((unsigned long) x & 7) << 26);
587f29dbc25Smrg}
588f29dbc25Smrg
589f29dbc25Smrg/*---------------------------------------------------------------------------
590f29dbc25Smrg * gp_set_pattern_origin
591f29dbc25Smrg *
592f29dbc25Smrg * This routine overrides the pattern origins set in gp_set_mono_pattern or
593f29dbc25Smrg * gp_set_color_pattern.  It is generally used to override the original
594f29dbc25Smrg * pattern origin due to a change in clipping.
595f29dbc25Smrg *-------------------------------------------------------------------------*/
596f29dbc25Smrg
597f29dbc25Smrgvoid
598f29dbc25Smrggp_set_pattern_origin(int x, int y)
599f29dbc25Smrg{
600f29dbc25Smrg    /* SAVE PATTERN ORIGIN */
601f29dbc25Smrg
60204007ebaSmrg    gp3_pat_origin = ((unsigned long) y << 29) |
60304007ebaSmrg        (((unsigned long) x & 7) << 26);
604f29dbc25Smrg}
605f29dbc25Smrg
606f29dbc25Smrg/*---------------------------------------------------------------------------
607f29dbc25Smrg * gp_set_color_pattern
608f29dbc25Smrg *
609f29dbc25Smrg * This routine is called to program a 8x8 color pattern into the LUT
610f29dbc25Smrg * hardware.  Unlike the other pattern routines, this routine must be called
611f29dbc25Smrg * before any gp_declare_xxxx routines.  The pattern that is programmed into
612f29dbc25Smrg * the hardware will stay persistent for all subsequent primitives until one
613f29dbc25Smrg * of the following conditions happens.
614f29dbc25Smrg *   - Another pattern type is programmed.
615f29dbc25Smrg *   - A color-conversion BLT rotation BLT.
616f29dbc25Smrg *-------------------------------------------------------------------------*/
617f29dbc25Smrg
618f29dbc25Smrgvoid
619f29dbc25Smrggp_set_color_pattern(unsigned long *pattern, int format, int x, int y)
620f29dbc25Smrg{
621f29dbc25Smrg    unsigned long size_dwords, temp;
622f29dbc25Smrg
623f29dbc25Smrg    gp3_ch3_pat = 1;
624f29dbc25Smrg
625f29dbc25Smrg    /* SAVE COLOR PATTERN SOURCE INFO
626f29dbc25Smrg     * Color patterns can be in a format different than the primary display.
627f29dbc25Smrg     * 4BPP patterns are not supported.
628f29dbc25Smrg     */
629f29dbc25Smrg
63004007ebaSmrg    gp3_pat_pix_shift = (unsigned long) ((format >> 2) & 3);
63104007ebaSmrg    gp3_pat_format = (((unsigned long) format & 0xF) << 24) |
63204007ebaSmrg        (((unsigned long) format & 0x10) << 17) |
633f29dbc25Smrg        GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_C3EN;
634f29dbc25Smrg
635f29dbc25Smrg    size_dwords = (64 << gp3_pat_pix_shift) >> 2;
636f29dbc25Smrg
637f29dbc25Smrg    /* CHECK FOR WRAP AFTER LUT LOAD                 */
638f29dbc25Smrg    /* Primitive size is 12 plus the amount of data. */
639f29dbc25Smrg
640f29dbc25Smrg    gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12;
641f29dbc25Smrg
642f29dbc25Smrg    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
643f29dbc25Smrg        gp3_cmd_next = gp3_cmd_top;
644f29dbc25Smrg        gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP |
645f29dbc25Smrg            GP3_LUT_HDR_DATA_ENABLE;
646f29dbc25Smrg
647f29dbc25Smrg        /* WAIT FOR HARDWARE           */
648f29dbc25Smrg        /* Same logic as BLT wrapping. */
649f29dbc25Smrg
650f29dbc25Smrg        GP3_WAIT_WRAP(temp);
65104007ebaSmrg    }
65204007ebaSmrg    else {
653f29dbc25Smrg        gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
654f29dbc25Smrg
655f29dbc25Smrg        /* WAIT FOR AVAILABLE SPACE */
656f29dbc25Smrg
657f29dbc25Smrg        GP3_WAIT_PRIMITIVE(temp);
658f29dbc25Smrg    }
659f29dbc25Smrg
660f29dbc25Smrg    /* SAVE CURRENT BUFFER POINTER */
661f29dbc25Smrg
662f29dbc25Smrg    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
663f29dbc25Smrg
664f29dbc25Smrg    /* PREPARE FOR COMMAND BUFFER DATA WRITES                 */
665f29dbc25Smrg    /* Pattern data is contiguous DWORDs at LUT address 0x100 */
666f29dbc25Smrg
667f29dbc25Smrg    WRITE_COMMAND32(0, gp3_cmd_header);
668f29dbc25Smrg    WRITE_COMMAND32(4, 0x100);
669f29dbc25Smrg    WRITE_COMMAND32(8, size_dwords | GP3_LUT_DATA_TYPE);
670f29dbc25Smrg
671f29dbc25Smrg    /* WRITE ALL DATA */
672f29dbc25Smrg
673f29dbc25Smrg    WRITE_COMMAND_STRING32(12, pattern, 0, size_dwords);
674f29dbc25Smrg
675f29dbc25Smrg    /* START OPERATION */
676f29dbc25Smrg
677f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
678f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
679f29dbc25Smrg
680f29dbc25Smrg    /* SAVE PATTERN ORIGIN */
681f29dbc25Smrg
68204007ebaSmrg    gp3_pat_origin = ((unsigned long) y << 29) |
68304007ebaSmrg        (((unsigned long) x & 7) << 26);
684f29dbc25Smrg}
685f29dbc25Smrg
686f29dbc25Smrg/*---------------------------------------------------------------------------
687f29dbc25Smrg * gp_set_mono_source
688f29dbc25Smrg *
689f29dbc25Smrg * This routine is called to program the colors for monochrome source data.
690f29dbc25Smrg *-------------------------------------------------------------------------*/
691f29dbc25Smrg
692f29dbc25Smrgvoid
693f29dbc25Smrggp_set_mono_source(unsigned long bgcolor, unsigned long fgcolor,
69404007ebaSmrg                   int transparent)
695f29dbc25Smrg{
696f29dbc25Smrg    /* UPDATE RASTER MODE REGISTER IF TRANSPARENT */
697f29dbc25Smrg
698f29dbc25Smrg    if (transparent) {
699f29dbc25Smrg        gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE;
700f29dbc25Smrg        gp3_raster_mode |= GP3_RM_SRC_TRANS;
701f29dbc25Smrg
702f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
703f29dbc25Smrg    }
704f29dbc25Smrg
705f29dbc25Smrg    /* SET MONOCHROME SOURCE COLORS */
706f29dbc25Smrg    /* Note that this routine only sets the colors.  The actual */
707f29dbc25Smrg    /* source type is determined by the final output routine    */
708f29dbc25Smrg    /* (gp_mono_bitmap_xxx, gp_color_bitmap_xxx, etc.)          */
709f29dbc25Smrg
710f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE | GP3_BLT_HDR_SRC_BG_ENABLE;
711f29dbc25Smrg
712f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, fgcolor);
713f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, bgcolor);
714f29dbc25Smrg}
715f29dbc25Smrg
716f29dbc25Smrg/*---------------------------------------------------------------------------
717f29dbc25Smrg * gp_set_solid_source
718f29dbc25Smrg *
719f29dbc25Smrg * This routine is called to program a solid source color.  A solid source
720f29dbc25Smrg * color is used primarily for vectors or antialiased text.
721f29dbc25Smrg *-------------------------------------------------------------------------*/
722f29dbc25Smrg
723f29dbc25Smrgvoid
724f29dbc25Smrggp_set_solid_source(unsigned long color)
725f29dbc25Smrg{
726f29dbc25Smrg    /* SET SOLID SOURCE COLOR */
727f29dbc25Smrg    /* The solid source register is in the same place for both BLTs and */
728f29dbc25Smrg    /* vectors.                                                         */
729f29dbc25Smrg
730f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE;
731f29dbc25Smrg
732f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color);
733f29dbc25Smrg}
734f29dbc25Smrg
735f29dbc25Smrg/*---------------------------------------------------------------------------
736f29dbc25Smrg * gp_set_source_transparency
737f29dbc25Smrg *
738f29dbc25Smrg * This routine sets the source transparency and mask to be used in future
739f29dbc25Smrg * rendering operations.  Transparency is cleared by gp_set_raster_operation,
740f29dbc25Smrg * so this routine should never be called first.
741f29dbc25Smrg *-------------------------------------------------------------------------*/
742f29dbc25Smrg
743f29dbc25Smrgvoid
744f29dbc25Smrggp_set_source_transparency(unsigned long color, unsigned long mask)
745f29dbc25Smrg{
746f29dbc25Smrg    gp3_raster_mode |= GP3_RM_SRC_TRANS;
747f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_SRC_FG_ENABLE |
748f29dbc25Smrg        GP3_BLT_HDR_SRC_BG_ENABLE;
749f29dbc25Smrg
750f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode);
751f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color);
752f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, mask);
753f29dbc25Smrg}
754f29dbc25Smrg
755f29dbc25Smrg/*---------------------------------------------------------------------------
756f29dbc25Smrg * gp_program_lut
757f29dbc25Smrg *
758f29dbc25Smrg * This routine is called to program the hardware LUT with color-conversion
759f29dbc25Smrg * information.  This routine should be called before any gp_declare_xxxx
760f29dbc25Smrg * routines.
761f29dbc25Smrg *
762f29dbc25Smrg * colors   - Pointer to an array of DWORDs for color expansion.
763f29dbc25Smrg *
764f29dbc25Smrg * full_lut - Selector between 4BPP and 8BPP expansion. The hardware is
765f29dbc25Smrg *            initialized with 16 dwords for 4BPP expansion and 256 dwords
766f29dbc25Smrg *            for 8BPP expansion.
767f29dbc25Smrg *-------------------------------------------------------------------------*/
768f29dbc25Smrg
769f29dbc25Smrgvoid
770f29dbc25Smrggp_program_lut(unsigned long *colors, int full_lut)
771f29dbc25Smrg{
772f29dbc25Smrg    unsigned long size_dwords, temp;
773f29dbc25Smrg
774f29dbc25Smrg    /* SIZE IS EITHER 16 DWORDS (4BPP) or 256 DWORDS (8BPP) */
775f29dbc25Smrg
776f29dbc25Smrg    if (full_lut)
777f29dbc25Smrg        size_dwords = 256;
778f29dbc25Smrg    else
779f29dbc25Smrg        size_dwords = 16;
780f29dbc25Smrg
781f29dbc25Smrg    /* CHECK FOR WRAP AFTER LUT LOAD                 */
782f29dbc25Smrg    /* Primitive size is 12 plus the amount of data. */
783f29dbc25Smrg
784f29dbc25Smrg    gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12;
785f29dbc25Smrg
786f29dbc25Smrg    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
787f29dbc25Smrg        gp3_cmd_next = gp3_cmd_top;
788f29dbc25Smrg        gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP |
789f29dbc25Smrg            GP3_LUT_HDR_DATA_ENABLE;
790f29dbc25Smrg
791f29dbc25Smrg        /* WAIT FOR HARDWARE           */
792f29dbc25Smrg        /* Same logic as BLT wrapping. */
793f29dbc25Smrg
794f29dbc25Smrg        GP3_WAIT_WRAP(temp);
79504007ebaSmrg    }
79604007ebaSmrg    else {
797f29dbc25Smrg        gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
798f29dbc25Smrg
799f29dbc25Smrg        /* WAIT FOR AVAILABLE SPACE */
800f29dbc25Smrg
801f29dbc25Smrg        GP3_WAIT_PRIMITIVE(temp);
802f29dbc25Smrg    }
803f29dbc25Smrg
804f29dbc25Smrg    /* SAVE CURRENT BUFFER POINTER */
805f29dbc25Smrg
806f29dbc25Smrg    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
807f29dbc25Smrg
808f29dbc25Smrg    /* PREPARE FOR COMMAND BUFFER DATA WRITES             */
809f29dbc25Smrg    /* Pattern data is contiguous DWORDs at LUT address 0 */
810f29dbc25Smrg
811f29dbc25Smrg    WRITE_COMMAND32(0, gp3_cmd_header);
812f29dbc25Smrg    WRITE_COMMAND32(4, 0);
813f29dbc25Smrg    WRITE_COMMAND32(8, (size_dwords | GP3_LUT_DATA_TYPE));
814f29dbc25Smrg
815f29dbc25Smrg    /* WRITE ALL DATA */
816f29dbc25Smrg
817f29dbc25Smrg    WRITE_COMMAND_STRING32(12, colors, 0, size_dwords);
818f29dbc25Smrg
819f29dbc25Smrg    /* START OPERATION */
820f29dbc25Smrg
821f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
822f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
823f29dbc25Smrg}
824f29dbc25Smrg
825f29dbc25Smrg/*---------------------------------------------------------------------------
826f29dbc25Smrg * gp_set_vector_pattern
827f29dbc25Smrg *
828f29dbc25Smrg * This routine is called to program the hardware LUT with a vector pattern.
829f29dbc25Smrg * A vector pattern is programmed as a 32-bit mask that specifies a
830f29dbc25Smrg * transparency pattern.  A length parameter is used to specify patterns
831f29dbc25Smrg * smaller than 32.  Note that vectors in Geode LX do not continue across
832f29dbc25Smrg * corners.  The beginning of each vector will always begin with bit 0 of the
833f29dbc25Smrg * vector pattern.  It is the responsibility of the caller to update the
834f29dbc25Smrg * pattern if an alternate behavior is desired.
835f29dbc25Smrg *
836f29dbc25Smrg * This routine faces the same restrictions of all routines that program
837f29dbc25Smrg * the LUT, in that it must be called before any gp_declare_xxxx routines,
838f29dbc25Smrg * it cannot be combined with an 8x8 color pattern, color conversion or
839f29dbc25Smrg * rotation.
840f29dbc25Smrg *-------------------------------------------------------------------------*/
841f29dbc25Smrg
842f29dbc25Smrgvoid
843f29dbc25Smrggp_set_vector_pattern(unsigned long pattern, unsigned long color, int length)
844f29dbc25Smrg{
845f29dbc25Smrg    unsigned long temp, mask;
846f29dbc25Smrg
847f29dbc25Smrg    gp3_ch3_pat = 1;
848f29dbc25Smrg    gp3_vector_pattern_color = color;
849f29dbc25Smrg
850f29dbc25Smrg    /* CREATE SUITABLE PATTERN MASK */
851f29dbc25Smrg    /* The GP requires a minimum of four pixels in a vector pattern.  We */
852f29dbc25Smrg    /* can get around this restriction by doubling any patterns smaller  */
853f29dbc25Smrg    /* than 4 pixels.                                                    */
854f29dbc25Smrg
855f29dbc25Smrg    while (length < 4) {
856f29dbc25Smrg        mask = 0xFFFFFFFF >> (32 - length);
857f29dbc25Smrg        pattern = (pattern << length) | (pattern & mask);
858f29dbc25Smrg        length <<= 1;
859f29dbc25Smrg    }
860f29dbc25Smrg    mask = 0xFFFFFFFF >> (32 - length);
861f29dbc25Smrg
862f29dbc25Smrg    gp3_vec_pat = pattern;
863f29dbc25Smrg
864f29dbc25Smrg    /* CHECK FOR WRAP AFTER LUT LOAD */
865f29dbc25Smrg
866f29dbc25Smrg    gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_PATTERN_COMMAND_SIZE;
867f29dbc25Smrg
868f29dbc25Smrg    if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
869f29dbc25Smrg        gp3_cmd_next = gp3_cmd_top;
870f29dbc25Smrg        gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP |
871f29dbc25Smrg            GP3_LUT_HDR_DATA_ENABLE;
872f29dbc25Smrg
873f29dbc25Smrg        /* WAIT FOR HARDWARE           */
874f29dbc25Smrg        /* Same logic as BLT wrapping. */
875f29dbc25Smrg
876f29dbc25Smrg        GP3_WAIT_WRAP(temp);
87704007ebaSmrg    }
87804007ebaSmrg    else {
879f29dbc25Smrg        gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
880f29dbc25Smrg
881f29dbc25Smrg        /* WAIT FOR AVAILABLE SPACE */
882f29dbc25Smrg
883f29dbc25Smrg        GP3_WAIT_PRIMITIVE(temp);
884f29dbc25Smrg    }
885f29dbc25Smrg
886f29dbc25Smrg    /* SAVE CURRENT BUFFER POINTER */
887f29dbc25Smrg
888f29dbc25Smrg    cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
889f29dbc25Smrg
890f29dbc25Smrg    /* PREPARE FOR COMMAND BUFFER DATA WRITES      */
891f29dbc25Smrg    /* Pattern data is 2 DWORDs at 0x100 and 0x101 */
892f29dbc25Smrg
893f29dbc25Smrg    WRITE_COMMAND32(0, gp3_cmd_header);
894f29dbc25Smrg    WRITE_COMMAND32(4, 0x100);
895f29dbc25Smrg    WRITE_COMMAND32(8, (2 | GP3_LUT_DATA_TYPE));
896f29dbc25Smrg    WRITE_COMMAND32(12, pattern);
897f29dbc25Smrg    WRITE_COMMAND32(16, mask);
898f29dbc25Smrg
899f29dbc25Smrg    /* START OPERATION */
900f29dbc25Smrg
901f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
902f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
903f29dbc25Smrg}
904f29dbc25Smrg
905f29dbc25Smrg/*---------------------------------------------------------------------------
906f29dbc25Smrg * gp_set_strides
907f29dbc25Smrg *
908f29dbc25Smrg * This routine is called to program the pitch between successive lines of
909f29dbc25Smrg * data in the frame buffer.  The strides should be DWORD aligned and less
910f29dbc25Smrg * than 64K.  These restrictions are not checked by the API.
911f29dbc25Smrg *-------------------------------------------------------------------------*/
912f29dbc25Smrg
913f29dbc25Smrgvoid
914f29dbc25Smrggp_set_strides(unsigned long dst_stride, unsigned long src_stride)
915f29dbc25Smrg{
916f29dbc25Smrg    /* SAVE STRIDES */
917f29dbc25Smrg    /* The source stride may be needed later for channel 3 source data and */
918f29dbc25Smrg    /* we may need to use these strides in calculations.                   */
919f29dbc25Smrg
920f29dbc25Smrg    gp3_src_stride = src_stride;
921f29dbc25Smrg    gp3_dst_stride = dst_stride;
922f29dbc25Smrg
923f29dbc25Smrg    /* ENABLE STRIDES */
924f29dbc25Smrg    /* The stride register is in the same place for BLTs and vectors */
925f29dbc25Smrg
926f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_STRIDE_ENABLE;
927f29dbc25Smrg
928f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_STRIDE, ((src_stride << 16) | dst_stride));
929f29dbc25Smrg}
930f29dbc25Smrg
931f29dbc25Smrg/*---------------------------------------------------------------------------
932f29dbc25Smrg * gp_set_source_format
933f29dbc25Smrg *
934f29dbc25Smrg * This routine is used to program the format of source data used in
935f29dbc25Smrg * subsequent color-conversion or rotation operations.  Note that 4BPP
936f29dbc25Smrg * indexed and 8BPP indexed source formats cannot be used when rotating, as
937f29dbc25Smrg * the LUT will be destroyed.  These formats also cannot be combined with an
938f29dbc25Smrg * 8x8 color pattern.  The supported formats mirror the hardware and are
939f29dbc25Smrg * described as follows:
940f29dbc25Smrg *
941f29dbc25Smrg * 0  - 8BPP 3:3:2
942f29dbc25Smrg * 1  - 8BPP indexed
943f29dbc25Smrg * 4  - 16BPP 4:4:4:4
944f29dbc25Smrg * 5  - 16BPP 1:5:5:5
945f29dbc25Smrg * 6  - 16BPP 5:6:5
946f29dbc25Smrg * 7  - 16BPP YUV
947f29dbc25Smrg * 8  - 32BPP 8:8:8:8
948f29dbc25Smrg * 13 - 4BPP indexed
949f29dbc25Smrg * 20 - 16BPP 4:4:4:4 BGR
950f29dbc25Smrg * 21 - 16BPP 1:5:5:5 BGR
951f29dbc25Smrg * 22 - 16BPP 0:5:6:5 BGR
952f29dbc25Smrg * 24 - 32BPP 8:8:8:8 BGR
953f29dbc25Smrg *-------------------------------------------------------------------------*/
954f29dbc25Smrg
955f29dbc25Smrgvoid
956f29dbc25Smrggp_set_source_format(int format)
957f29dbc25Smrg{
958f29dbc25Smrg    /* SAVE FORMAT */
959f29dbc25Smrg    /* We will combine the source format later when doing color conversion. */
960f29dbc25Smrg    /* We also save the pixel size for host source calculations.            */
961f29dbc25Smrg    /* Conveniently, the source formats are organized such that the upper   */
962f29dbc25Smrg    /* two bits of the nibble represent the pixel shift, with a pixel shift */
963f29dbc25Smrg    /* of 3 being a special case for 4BPP data.  Clever, yes?  Even more    */
964f29dbc25Smrg    /* clever, bit 4 indicates BGR ordering.                                */
965f29dbc25Smrg
96604007ebaSmrg    gp3_src_pix_shift = (unsigned long) ((format >> 2) & 3);
96704007ebaSmrg    gp3_src_format = (((unsigned long) format & 0xF) << 24) |
96804007ebaSmrg        (((unsigned long) format & 0x10) << 18);
969f29dbc25Smrg}
970f29dbc25Smrg
971f29dbc25Smrg/*---------------------------------------------------------------------------
972f29dbc25Smrg * gp_pattern_fill
973f29dbc25Smrg *
974f29dbc25Smrg * This routine is called to perform a simple pattern fill.  The pattern
975f29dbc25Smrg * can be solid, monochrome or a preprogrammed 8x8 color pattern.  If
976f29dbc25Smrg * the ROP involves source data, that source data will be constant.
977f29dbc25Smrg *-------------------------------------------------------------------------*/
978f29dbc25Smrg
979f29dbc25Smrgvoid
980f29dbc25Smrggp_pattern_fill(unsigned long dstoffset, unsigned long width,
98104007ebaSmrg                unsigned long height)
982f29dbc25Smrg{
983f29dbc25Smrg    unsigned long base_register;
984f29dbc25Smrg
985f29dbc25Smrg    base_register = (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK) |
986f29dbc25Smrg        ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000));
987f29dbc25Smrg
988f29dbc25Smrg    /* ENABLE RELEVANT REGISTERS */
989f29dbc25Smrg    /* Note that we always enable and write the channel 3 mode, if only */
990f29dbc25Smrg    /* to turn it off.   Cimarron also always writes the base offset    */
991f29dbc25Smrg    /* register to allow operation with frame buffers larger than 16MB. */
992f29dbc25Smrg
993f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
994f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
995f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE |
996f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
997f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
998f29dbc25Smrg
999f29dbc25Smrg    /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
1000f29dbc25Smrg    /* The destination base is the frame buffer base plus whatever */
1001f29dbc25Smrg    /* 4MB segment we happen to be BLTing to.                      */
1002f29dbc25Smrg
1003f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, ((width << 16) | height));
1004f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base_register);
1005f29dbc25Smrg
1006f29dbc25Smrg    /* CHECK 8X8 COLOR PATTERN CASE */
1007f29dbc25Smrg
1008f29dbc25Smrg    if (gp3_ch3_pat) {
1009f29dbc25Smrg        /* SET CHANNEL 3 PATTERN ORIGINS */
1010f29dbc25Smrg
1011f29dbc25Smrg        gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE;
1012f29dbc25Smrg
1013f29dbc25Smrg        /* INITIALIZE CHANNEL 3 PARAMETERS */
1014f29dbc25Smrg
1015f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ((width << 16) | height));
1016f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
1017f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
1018f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
101904007ebaSmrg    }
102004007ebaSmrg    else {
1021f29dbc25Smrg        /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
1022f29dbc25Smrg
1023f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
1024f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
102504007ebaSmrg                        ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
1026f29dbc25Smrg    }
1027f29dbc25Smrg
1028f29dbc25Smrg    /* START THE BLT */
1029f29dbc25Smrg
1030f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1031f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
1032f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1033f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1034f29dbc25Smrg}
1035f29dbc25Smrg
1036f29dbc25Smrg/*---------------------------------------------------------------------------
1037f29dbc25Smrg * gp_screen_to_screen_blt
1038f29dbc25Smrg *
1039f29dbc25Smrg * This routine is called to perform a BLT from one location inside video
1040f29dbc25Smrg * memory to another location inside video memory.  The source and destination
1041f29dbc25Smrg * formats are assumed to be the current BPP.  Whenever possible, this routine
1042f29dbc25Smrg * tries to use channel 3 to fetch source data.  The BLT flags can affect this
1043f29dbc25Smrg * behavior in the following ways:
1044f29dbc25Smrg *   CIMGP_BLTFLAGS_PRES_COLOR_PAT
1045f29dbc25Smrg *      A color pattern is being stored in the channel 3 buffer.  It is either
1046f29dbc25Smrg *      being stored for a later BLT or being combined with the current source
1047f29dbc25Smrg *      data.  Channel 3 cannot be used to fetch source data or the pattern
1048f29dbc25Smrg *      will be overwritten.
1049f29dbc25Smrg *   CIMGP_BLTFLAGS_PRES_LUT
1050f29dbc25Smrg *      If the first flag is not set, this flag will limit the use of the
1051f29dbc25Smrg *      channel 3 buffer to 1K.
1052f29dbc25Smrg *-------------------------------------------------------------------------*/
1053f29dbc25Smrg
1054f29dbc25Smrgvoid
1055f29dbc25Smrggp_screen_to_screen_blt(unsigned long dstoffset, unsigned long srcoffset,
105604007ebaSmrg                        unsigned long width, unsigned long height, int flags)
1057f29dbc25Smrg{
1058f29dbc25Smrg    unsigned long base;
1059f29dbc25Smrg    unsigned long ch3_flags = 0;
1060f29dbc25Smrg    unsigned long blt_mode = gp3_blt_mode;
1061f29dbc25Smrg    unsigned long size = ((width << 16) | height);
1062f29dbc25Smrg    unsigned long dstbase, srcbase;
1063f29dbc25Smrg
1064f29dbc25Smrg    /* CALCULATE BASE OFFSETS                                             */
1065f29dbc25Smrg    /* We need to set the 4MB aligned base offsets before we add offsets  */
1066f29dbc25Smrg    /* for negative BLTs.                                                 */
1067f29dbc25Smrg
1068f29dbc25Smrg    srcbase = srcoffset & 0xFFC00000;
1069f29dbc25Smrg    dstbase = dstoffset & 0xFFC00000;
1070f29dbc25Smrg    srcoffset &= 0x3FFFFF;
1071f29dbc25Smrg    dstoffset &= 0x3FFFFF;
1072f29dbc25Smrg
1073f29dbc25Smrg    /* ADJUST OFFSETS BASED ON FLAGS */
1074f29dbc25Smrg    /* We adjust the source and destination offsets to point to the first */
1075f29dbc25Smrg    /* byte of the first pixel of the BLT.  This routine assumes that the */
1076f29dbc25Smrg    /* source and destination regions do not wrap past the end of a 16MB  */
1077f29dbc25Smrg    /* region.                                                            */
1078f29dbc25Smrg
1079f29dbc25Smrg    if (flags & CIMGP_NEGXDIR) {
1080f29dbc25Smrg        srcoffset += (width << gp3_pix_shift) - 1;
1081f29dbc25Smrg        dstoffset += (width << gp3_pix_shift) - 1;
1082f29dbc25Smrg        blt_mode |= GP3_BM_NEG_XDIR;
1083f29dbc25Smrg        ch3_flags |= GP3_CH3_NEG_XDIR;
1084f29dbc25Smrg    }
1085f29dbc25Smrg    if (flags & CIMGP_NEGYDIR) {
1086f29dbc25Smrg        srcoffset += (height - 1) * gp3_src_stride;
1087f29dbc25Smrg        dstoffset += (height - 1) * gp3_dst_stride;
1088f29dbc25Smrg        blt_mode |= GP3_BM_NEG_YDIR;
1089f29dbc25Smrg        ch3_flags |= GP3_CH3_NEG_YDIR;
1090f29dbc25Smrg    }
1091f29dbc25Smrg
1092f29dbc25Smrg    /* BRANCH BASED ON CHANNEL 3                                     */
1093f29dbc25Smrg    /* If a color pattern is not being saved or used, channel 3 will */
1094f29dbc25Smrg    /* be used to fetch source for maximum throughput.   Channel 3   */
1095f29dbc25Smrg    /* is not used if transparency or alpha blending is enabled.     */
1096f29dbc25Smrg
1097f29dbc25Smrg    if (!(gp3_blt_flags & CIMGP_BLTFLAGS_PRES_COLOR_PAT) &&
1098f29dbc25Smrg        !(gp3_raster_mode & GP3_RM_SRC_TRANS) && !(flags & CIMGP_NEGYDIR)) {
1099f29dbc25Smrg        base = ((gp3_fb_base << 24) + dstbase) |
1100f29dbc25Smrg            ((gp3_fb_base << 4) + (srcbase >> 20)) |
1101f29dbc25Smrg            (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
1102f29dbc25Smrg
1103f29dbc25Smrg        gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
1104f29dbc25Smrg            GP3_BLT_HDR_WIDHI_ENABLE |
1105f29dbc25Smrg            GP3_BLT_HDR_CH3_STR_ENABLE |
1106f29dbc25Smrg            GP3_BLT_HDR_CH3_WIDHI_ENABLE |
1107f29dbc25Smrg            GP3_BLT_HDR_CH3_OFF_ENABLE |
1108f29dbc25Smrg            GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1109f29dbc25Smrg
1110f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset | gp3_pat_origin));
1111f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset);
1112f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
1113f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
1114f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
1115f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR,
111604007ebaSmrg                        GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
111704007ebaSmrg                        gp3_ch3_bpp | gp3_src_stride | ch3_flags |
111804007ebaSmrg                        ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) |
111904007ebaSmrg                        ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
112004007ebaSmrg    }
112104007ebaSmrg    else {
1122f29dbc25Smrg        /* CALCULATE BASE OFFSET REGISTER */
1123f29dbc25Smrg
1124f29dbc25Smrg        base = ((gp3_fb_base << 24) + dstbase) |
1125f29dbc25Smrg            ((gp3_fb_base << 14) + (srcbase >> 10)) |
1126f29dbc25Smrg            (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
1127f29dbc25Smrg
1128f29dbc25Smrg        /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
1129f29dbc25Smrg        /* We assume that a color pattern is being ROPed with source  */
1130f29dbc25Smrg        /* data if the pattern type is color and the preserve pattern */
1131f29dbc25Smrg        /* was set.                                                   */
1132f29dbc25Smrg
1133f29dbc25Smrg        blt_mode |= GP3_BM_SRC_FB;
1134f29dbc25Smrg
1135f29dbc25Smrg        gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
1136f29dbc25Smrg            GP3_BLT_HDR_DST_OFF_ENABLE |
1137f29dbc25Smrg            GP3_BLT_HDR_WIDHI_ENABLE |
1138f29dbc25Smrg            GP3_BLT_HDR_CH3_WIDHI_ENABLE |
1139f29dbc25Smrg            GP3_BLT_HDR_CH3_STR_ENABLE |
1140f29dbc25Smrg            GP3_BLT_HDR_CH3_OFF_ENABLE |
1141f29dbc25Smrg            GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1142f29dbc25Smrg
1143f29dbc25Smrg        if (gp3_ch3_pat) {
1144f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
1145f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset);
1146f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format | ch3_flags);
1147f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
114804007ebaSmrg        }
114904007ebaSmrg        else {
1150f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset | gp3_pat_origin);
1151f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
1152f29dbc25Smrg        }
1153f29dbc25Smrg
1154f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, srcoffset);
1155f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
1156f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
1157f29dbc25Smrg    }
1158f29dbc25Smrg
1159f29dbc25Smrg    /* START THE BLT */
1160f29dbc25Smrg
1161f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1162f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
1163f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1164f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1165f29dbc25Smrg}
1166f29dbc25Smrg
1167f29dbc25Smrg/*---------------------------------------------------------------------------
1168f29dbc25Smrg * gp_screen_to_screen_convert
1169f29dbc25Smrg *
1170f29dbc25Smrg * This routine is called to color-convert a rectangular region of the frame
1171f29dbc25Smrg * buffer into the current BPP. The format of the source region is programmed
1172f29dbc25Smrg * by gp_set_source_format.
1173f29dbc25Smrg *-------------------------------------------------------------------------*/
1174f29dbc25Smrg
1175f29dbc25Smrgvoid
1176f29dbc25Smrggp_screen_to_screen_convert(unsigned long dstoffset, unsigned long srcoffset,
117704007ebaSmrg                            unsigned long width, unsigned long height,
117804007ebaSmrg                            int nibble)
1179f29dbc25Smrg{
1180f29dbc25Smrg    unsigned long size = ((width << 16) | height);
1181f29dbc25Smrg    unsigned long ch3_offset = srcoffset & 0x3FFFFF;
1182f29dbc25Smrg    unsigned long ch3_size, base;
1183f29dbc25Smrg
1184f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
1185f29dbc25Smrg        ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) |
1186f29dbc25Smrg        (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
1187f29dbc25Smrg
1188f29dbc25Smrg    /* SET NIBBLE FOR 4BPP */
1189f29dbc25Smrg    /* 4BPP is a special case in that it requires subpixel addressing.  The */
1190f29dbc25Smrg    /* user must supply this information via the nibble parameter.  This    */
1191f29dbc25Smrg    /* parameter is ignored for every other source format.                  */
1192f29dbc25Smrg
1193f29dbc25Smrg    ch3_size = size;
1194f29dbc25Smrg    if (gp3_src_pix_shift == 3)
1195f29dbc25Smrg        ch3_offset |= ((nibble & 1) << 25);
1196f29dbc25Smrg    else if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED)
1197f29dbc25Smrg        ch3_size = ((((width * 3) + 3) >> 2) << 16) | height;
1198f29dbc25Smrg
1199f29dbc25Smrg    /* SET APPROPRIATE ENABLES */
1200f29dbc25Smrg
1201f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
1202f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
1203f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE |
1204f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
1205f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
1206f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1207f29dbc25Smrg
1208f29dbc25Smrg    /* WRITE ALL BLT REGISTERS */
1209f29dbc25Smrg
1210f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
121104007ebaSmrg                    (dstoffset & 0x3FFFFF) | gp3_pat_origin);
1212f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
1213f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size);
1214f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
1215f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR,
121604007ebaSmrg                    GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | gp3_src_format |
121704007ebaSmrg                    ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) |
121804007ebaSmrg                    ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) |
121904007ebaSmrg                    gp3_src_stride);
1220f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
1221f29dbc25Smrg
1222f29dbc25Smrg    /* START THE BLT */
1223f29dbc25Smrg
1224f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1225f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
1226f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1227f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1228f29dbc25Smrg}
1229f29dbc25Smrg
1230f29dbc25Smrg/*---------------------------------------------------------------------------
1231f29dbc25Smrg * gp_color_bitmap_to_screen_blt
1232f29dbc25Smrg *
1233f29dbc25Smrg * This routine is called to BLT data from system memory into the frame
1234f29dbc25Smrg * buffer.  'srcy' is deliberately omitted to prevent extra calculations for
1235f29dbc25Smrg * simple applications that have no source indexes.
1236f29dbc25Smrg *-------------------------------------------------------------------------*/
1237f29dbc25Smrg
1238f29dbc25Smrgvoid
1239f29dbc25Smrggp_color_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx,
124004007ebaSmrg                              unsigned long width, unsigned long height,
124104007ebaSmrg                              unsigned char *data, long pitch)
1242f29dbc25Smrg{
1243f29dbc25Smrg    unsigned long indent, temp;
1244f29dbc25Smrg    unsigned long total_dwords, size_dwords;
1245f29dbc25Smrg    unsigned long dword_count, byte_count;
1246f29dbc25Smrg    unsigned long size = ((width << 16) | height);
1247f29dbc25Smrg    unsigned long srcoffset;
1248f29dbc25Smrg
1249f29dbc25Smrg    /* ASSUME BITMAPS ARE DWORD ALIGNED */
1250f29dbc25Smrg    /* We will offset into the source data in DWORD increments.  We */
1251f29dbc25Smrg    /* set the source index to the remaining byte offset and        */
1252f29dbc25Smrg    /* increment the size of each line to account for the dont-care */
1253f29dbc25Smrg    /* pixel(s).                                                    */
1254f29dbc25Smrg
1255f29dbc25Smrg    indent = srcx << gp3_pix_shift;
1256f29dbc25Smrg    srcoffset = (indent & ~3L);
1257f29dbc25Smrg    indent &= 3;
1258f29dbc25Smrg
1259f29dbc25Smrg    /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
1260f29dbc25Smrg    /* We assume that a color pattern is being ROPed with source  */
1261f29dbc25Smrg    /* data if the pattern type is color and the preserve pattern */
1262f29dbc25Smrg    /* was set.                                                   */
1263f29dbc25Smrg
1264f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
1265f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE |
1266f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
1267f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
1268f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1269f29dbc25Smrg
1270f29dbc25Smrg    if (gp3_ch3_pat) {
1271f29dbc25Smrg        gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE |
1272f29dbc25Smrg            GP3_BLT_HDR_CH3_WIDHI_ENABLE;
1273f29dbc25Smrg
1274f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
1275f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
1276f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
1277f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
127804007ebaSmrg    }
127904007ebaSmrg    else {
1280f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
128104007ebaSmrg                        ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
1282f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
1283f29dbc25Smrg    }
1284f29dbc25Smrg
1285f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, indent);
1286f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
1287f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET,
128804007ebaSmrg                    ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
1289f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_HOST);
1290f29dbc25Smrg
1291f29dbc25Smrg    /* START THE BLT */
1292f29dbc25Smrg
1293f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1294f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1295f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1296f29dbc25Smrg
1297f29dbc25Smrg    /* CALCULATE THE SIZE OF ONE LINE */
1298f29dbc25Smrg
1299f29dbc25Smrg    size = (width << gp3_pix_shift) + indent;
1300f29dbc25Smrg    total_dwords = (size + 3) >> 2;
1301f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
1302f29dbc25Smrg    dword_count = (size >> 2);
1303f29dbc25Smrg    byte_count = (size & 3);
1304f29dbc25Smrg
1305f29dbc25Smrg    /* CHECK FOR SMALL BLT CASE */
1306f29dbc25Smrg
1307f29dbc25Smrg    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
1308f29dbc25Smrg        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
1309f29dbc25Smrg        /* UPDATE THE COMMAND POINTER */
1310f29dbc25Smrg
1311f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
1312f29dbc25Smrg
1313f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
1314f29dbc25Smrg
1315f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
1316f29dbc25Smrg
1317f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
1318f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
1319f29dbc25Smrg
1320f29dbc25Smrg            GP3_WAIT_WRAP(temp);
1321f29dbc25Smrg            WRITE_COMMAND32(0,
132204007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
132304007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
132404007ebaSmrg        }
132504007ebaSmrg        else {
1326f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
1327f29dbc25Smrg            WRITE_COMMAND32(0,
132804007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
1329f29dbc25Smrg        }
1330f29dbc25Smrg
1331f29dbc25Smrg        /* WRITE DWORD COUNT */
1332f29dbc25Smrg
1333f29dbc25Smrg        WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height));
1334f29dbc25Smrg
1335f29dbc25Smrg        while (height--) {
1336f29dbc25Smrg            /* WRITE DATA */
1337f29dbc25Smrg
1338f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
1339f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
134004007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
1341f29dbc25Smrg
1342f29dbc25Smrg            srcoffset += pitch;
1343f29dbc25Smrg            cim_cmd_ptr += total_dwords << 2;
1344f29dbc25Smrg        }
1345f29dbc25Smrg
1346f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1347f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
134804007ebaSmrg    }
134904007ebaSmrg    else {
1350f29dbc25Smrg        /*
1351f29dbc25Smrg         * Each line will be created as a separate command buffer entry to
1352f29dbc25Smrg         * allow line-by-line wrapping and to allow simultaneous rendering
1353f29dbc25Smrg         * by the HW.
1354f29dbc25Smrg         */
1355f29dbc25Smrg
1356f29dbc25Smrg        while (height--) {
1357f29dbc25Smrg            /* UPDATE THE COMMAND POINTER
1358f29dbc25Smrg             * The WRITE_COMMANDXX macros use a pointer to the current buffer
1359f29dbc25Smrg             * space.  This is created by adding gp3_cmd_current to the base
1360f29dbc25Smrg             * pointer.
1361f29dbc25Smrg             */
1362f29dbc25Smrg
1363f29dbc25Smrg            cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
1364f29dbc25Smrg
1365f29dbc25Smrg            /* CHECK IF A WRAP WILL BE NEEDED */
1366f29dbc25Smrg
1367f29dbc25Smrg            gp3_cmd_next = gp3_cmd_current + size_dwords;
1368f29dbc25Smrg            if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
1369f29dbc25Smrg                gp3_cmd_next = gp3_cmd_top;
1370f29dbc25Smrg
1371f29dbc25Smrg                /* WAIT FOR HARDWARE */
1372f29dbc25Smrg
1373f29dbc25Smrg                GP3_WAIT_WRAP(temp);
1374f29dbc25Smrg                WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
137504007ebaSmrg                                GP3_DATA_LOAD_HDR_WRAP |
137604007ebaSmrg                                GP3_DATA_LOAD_HDR_ENABLE);
137704007ebaSmrg            }
137804007ebaSmrg            else {
1379f29dbc25Smrg                /* WAIT FOR AVAILABLE SPACE */
1380f29dbc25Smrg
1381f29dbc25Smrg                GP3_WAIT_PRIMITIVE(temp);
1382f29dbc25Smrg                WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
138304007ebaSmrg                                GP3_DATA_LOAD_HDR_ENABLE);
1384f29dbc25Smrg            }
1385f29dbc25Smrg
1386f29dbc25Smrg            /* WRITE DWORD COUNT */
1387f29dbc25Smrg
1388f29dbc25Smrg            WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords);
1389f29dbc25Smrg
1390f29dbc25Smrg            /* WRITE DATA */
1391f29dbc25Smrg
1392f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
1393f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
139404007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
1395f29dbc25Smrg
1396f29dbc25Smrg            /* UPDATE POINTERS */
1397f29dbc25Smrg
1398f29dbc25Smrg            srcoffset += pitch;
1399f29dbc25Smrg            WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1400f29dbc25Smrg            gp3_cmd_current = gp3_cmd_next;
1401f29dbc25Smrg        }
1402f29dbc25Smrg    }
1403f29dbc25Smrg}
1404f29dbc25Smrg
1405f29dbc25Smrg/*---------------------------------------------------------------------------
1406f29dbc25Smrg * gp_color_convert_blt
1407f29dbc25Smrg *
1408f29dbc25Smrg * This routine is called to convert data that is stored in system memory
1409f29dbc25Smrg * into the current graphics BPP.  The source format is programmed in
1410f29dbc25Smrg * gp_set_source_format.
1411f29dbc25Smrg *-------------------------------------------------------------------------*/
1412f29dbc25Smrg
1413f29dbc25Smrgvoid
1414f29dbc25Smrggp_color_convert_blt(unsigned long dstoffset, unsigned long srcx,
141504007ebaSmrg                     unsigned long width, unsigned long height,
141604007ebaSmrg                     unsigned char *data, long pitch)
1417f29dbc25Smrg{
1418f29dbc25Smrg    unsigned long indent, temp;
1419f29dbc25Smrg    unsigned long total_dwords, size_dwords;
1420f29dbc25Smrg    unsigned long dword_count, byte_count;
1421f29dbc25Smrg    unsigned long size = ((width << 16) | height);
1422f29dbc25Smrg    unsigned long ch3_size;
1423f29dbc25Smrg    unsigned long ch3_offset, srcoffset;
1424f29dbc25Smrg    unsigned long base;
1425f29dbc25Smrg
1426f29dbc25Smrg    /* ASSUME BITMAPS ARE DWORD ALIGNED */
1427f29dbc25Smrg    /* We will offset into the source data in DWORD increments.  We  */
1428f29dbc25Smrg    /* set the source index to the remaining byte offset and         */
1429f29dbc25Smrg    /* increment the size of each line to account for the dont-care  */
1430f29dbc25Smrg    /* pixel(s).   For 4BPP source data, we also set the appropriate */
1431f29dbc25Smrg    /* nibble index.                                                 */
1432f29dbc25Smrg
1433f29dbc25Smrg    /* CALCULATE THE SIZE OF ONE LINE */
1434f29dbc25Smrg
1435f29dbc25Smrg    if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) {
1436f29dbc25Smrg        /* HANDLE 24BPP
1437f29dbc25Smrg         * Note that we do not do anything to guarantee that the source data
1438f29dbc25Smrg         * is DWORD aligned.  The logic here is that the source data will be
1439f29dbc25Smrg         * cacheable, in which case Geode LX will not lose any clocks for
1440f29dbc25Smrg         * unaligned moves.  Also note that the channel 3 width is
1441f29dbc25Smrg         * programmed as the number of dwords, while the normal width is
1442f29dbc25Smrg         * programmed as the number of pixels.
1443f29dbc25Smrg         */
1444f29dbc25Smrg
1445f29dbc25Smrg        srcoffset = srcx * 3;
1446f29dbc25Smrg        ch3_offset = 0;
1447f29dbc25Smrg        temp = width * 3;
1448f29dbc25Smrg        ch3_size = (((temp + 3) >> 2) << 16) | height;
144904007ebaSmrg    }
145004007ebaSmrg    else {
1451f29dbc25Smrg        ch3_size = size;
1452f29dbc25Smrg
1453f29dbc25Smrg        if (gp3_src_pix_shift == 3) {
1454f29dbc25Smrg            /* CALCULATE INDENT AND SOURCE OFFSET */
1455f29dbc25Smrg
1456f29dbc25Smrg            indent = (srcx >> 1);
1457f29dbc25Smrg            srcoffset = (indent & ~3L);
1458f29dbc25Smrg            indent &= 3;
1459f29dbc25Smrg            ch3_offset = indent | ((srcx & 1) << 25);
1460f29dbc25Smrg
1461f29dbc25Smrg            temp = ((width + (srcx & 1) + 1) >> 1) + indent;
146204007ebaSmrg        }
146304007ebaSmrg        else {
1464f29dbc25Smrg            indent = (srcx << gp3_src_pix_shift);
1465f29dbc25Smrg            srcoffset = (indent & ~3L);
1466f29dbc25Smrg            indent &= 3;
1467f29dbc25Smrg            ch3_offset = indent;
1468f29dbc25Smrg
1469f29dbc25Smrg            temp = (width << gp3_src_pix_shift) + indent;
1470f29dbc25Smrg        }
1471f29dbc25Smrg    }
1472f29dbc25Smrg
1473f29dbc25Smrg    total_dwords = (temp + 3) >> 2;
1474f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
1475f29dbc25Smrg    dword_count = (temp >> 2);
1476f29dbc25Smrg    byte_count = (temp & 3);
1477f29dbc25Smrg
1478f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
1479f29dbc25Smrg        (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
1480f29dbc25Smrg
1481f29dbc25Smrg    /* SET APPROPRIATE ENABLES */
1482f29dbc25Smrg
1483f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
1484f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
1485f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
1486f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE |
1487f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
1488f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1489f29dbc25Smrg
1490f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
149104007ebaSmrg                    (dstoffset & 0x3FFFFF) | gp3_pat_origin);
1492f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
1493f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
1494f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size);
1495f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
1496f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
149704007ebaSmrg                    GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
149804007ebaSmrg                    gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
149904007ebaSmrg                                      << 20));
1500f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
1501f29dbc25Smrg
1502f29dbc25Smrg    /* START THE BLT */
1503f29dbc25Smrg
1504f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1505f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1506f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1507f29dbc25Smrg
1508f29dbc25Smrg    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
1509f29dbc25Smrg        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
1510f29dbc25Smrg        /* UPDATE THE COMMAND POINTER */
1511f29dbc25Smrg
1512f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
1513f29dbc25Smrg
1514f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
1515f29dbc25Smrg
1516f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
1517f29dbc25Smrg
1518f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
1519f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
1520f29dbc25Smrg
1521f29dbc25Smrg            GP3_WAIT_WRAP(temp);
1522f29dbc25Smrg            WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
152304007ebaSmrg                            GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE);
152404007ebaSmrg        }
152504007ebaSmrg        else {
1526f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
1527f29dbc25Smrg            WRITE_COMMAND32(0,
152804007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
1529f29dbc25Smrg        }
1530f29dbc25Smrg
1531f29dbc25Smrg        /* WRITE DWORD COUNT */
1532f29dbc25Smrg
153304007ebaSmrg        WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
1534f29dbc25Smrg
1535f29dbc25Smrg        while (height--) {
1536f29dbc25Smrg            /* WRITE DATA */
1537f29dbc25Smrg
1538f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
1539f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
154004007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
1541f29dbc25Smrg
1542f29dbc25Smrg            srcoffset += pitch;
1543f29dbc25Smrg            cim_cmd_ptr += total_dwords << 2;
1544f29dbc25Smrg        }
1545f29dbc25Smrg
1546f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1547f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
154804007ebaSmrg    }
154904007ebaSmrg    else {
1550f29dbc25Smrg        /* WRITE DATA LINE BY LINE
1551f29dbc25Smrg         * Each line will be created as a separate command buffer entry to
1552f29dbc25Smrg         * allow line-by-line wrapping and to allow simultaneous rendering
1553f29dbc25Smrg         * by the HW.
1554f29dbc25Smrg         */
1555f29dbc25Smrg
1556f29dbc25Smrg        while (height--) {
1557f29dbc25Smrg            /* UPDATE THE COMMAND POINTER
1558f29dbc25Smrg             * The WRITE_COMMANDXX macros use a pointer to the current buffer
1559f29dbc25Smrg             * space. This is created by adding gp3_cmd_current to the base
1560f29dbc25Smrg             * pointer.
1561f29dbc25Smrg             */
1562f29dbc25Smrg
1563f29dbc25Smrg            cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
1564f29dbc25Smrg
1565f29dbc25Smrg            /* CHECK IF A WRAP WILL BE NEEDED */
1566f29dbc25Smrg
1567f29dbc25Smrg            gp3_cmd_next = gp3_cmd_current + size_dwords;
1568f29dbc25Smrg            if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
1569f29dbc25Smrg                gp3_cmd_next = gp3_cmd_top;
1570f29dbc25Smrg
1571f29dbc25Smrg                /* WAIT FOR HARDWARE */
1572f29dbc25Smrg
1573f29dbc25Smrg                GP3_WAIT_WRAP(temp);
1574f29dbc25Smrg                WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
157504007ebaSmrg                                GP3_DATA_LOAD_HDR_WRAP |
157604007ebaSmrg                                GP3_DATA_LOAD_HDR_ENABLE);
157704007ebaSmrg            }
157804007ebaSmrg            else {
1579f29dbc25Smrg                /* WAIT FOR AVAILABLE SPACE */
1580f29dbc25Smrg
1581f29dbc25Smrg                GP3_WAIT_PRIMITIVE(temp);
1582f29dbc25Smrg                WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
158304007ebaSmrg                                GP3_DATA_LOAD_HDR_ENABLE);
1584f29dbc25Smrg            }
1585f29dbc25Smrg
1586f29dbc25Smrg            /* WRITE DWORD COUNT */
1587f29dbc25Smrg
1588f29dbc25Smrg            WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
1589f29dbc25Smrg
1590f29dbc25Smrg            /* WRITE DATA */
1591f29dbc25Smrg
1592f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
1593f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
159404007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
1595f29dbc25Smrg
1596f29dbc25Smrg            /* UPDATE POINTERS */
1597f29dbc25Smrg
1598f29dbc25Smrg            srcoffset += pitch;
1599f29dbc25Smrg            WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1600f29dbc25Smrg            gp3_cmd_current = gp3_cmd_next;
1601f29dbc25Smrg        }
1602f29dbc25Smrg    }
1603f29dbc25Smrg}
1604f29dbc25Smrg
1605f29dbc25Smrg/*---------------------------------------------------------------------------
1606f29dbc25Smrg * gp_custom_convert_blt
1607f29dbc25Smrg *
1608f29dbc25Smrg * This routine is identical to gp_color_convert_blt, except that the macro
1609f29dbc25Smrg * to write data to the frame buffer has been replaced with a new macro.  This
1610f29dbc25Smrg * allows a user to implement custom behavior when sending data, such as
1611f29dbc25Smrg * manually converting 24BPP to 32BPP, converting 2BPP to 4BPP or
1612f29dbc25Smrg * premultiplying alpha data.
1613f29dbc25Smrg *-------------------------------------------------------------------------*/
1614f29dbc25Smrg
1615f29dbc25Smrgvoid
1616f29dbc25Smrggp_custom_convert_blt(unsigned long dstoffset, unsigned long srcx,
161704007ebaSmrg                      unsigned long width, unsigned long height,
161804007ebaSmrg                      unsigned char *data, long pitch)
1619f29dbc25Smrg{
1620f29dbc25Smrg    unsigned long indent, temp;
1621f29dbc25Smrg    unsigned long total_dwords, size_dwords;
1622f29dbc25Smrg    unsigned long dword_count, byte_count;
1623f29dbc25Smrg    unsigned long size = ((width << 16) | height);
1624f29dbc25Smrg    unsigned long ch3_offset, srcoffset;
1625f29dbc25Smrg    unsigned long ch3_size, base;
1626f29dbc25Smrg
1627f29dbc25Smrg    /* ASSUME BITMAPS ARE DWORD ALIGNED */
1628f29dbc25Smrg    /* We will offset into the source data in DWORD increments.  We  */
1629f29dbc25Smrg    /* set the source index to the remaining byte offset and         */
1630f29dbc25Smrg    /* increment the size of each line to account for the dont-care  */
1631f29dbc25Smrg    /* pixel(s).   For 4BPP source data, we also set the appropriate */
1632f29dbc25Smrg    /* nibble index.                                                 */
1633f29dbc25Smrg
1634f29dbc25Smrg    /* CALCULATE THE SIZE OF ONE LINE */
1635f29dbc25Smrg
1636f29dbc25Smrg    if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) {
1637f29dbc25Smrg        /* HANDLE 24BPP
1638f29dbc25Smrg         * Note that we do not do anything to guarantee that the source data
1639f29dbc25Smrg         * is DWORD aligned.  The logic here is that the source data will be
1640f29dbc25Smrg         * cacheable, in which case Geode LX will not lose any clocks for
1641f29dbc25Smrg         * unaligned moves.  Also note that the channel 3 width is programmed
1642f29dbc25Smrg         * as the number of dwords, while the normal width is programmed as
1643f29dbc25Smrg         * the number of pixels.
1644f29dbc25Smrg         */
1645f29dbc25Smrg
1646f29dbc25Smrg        srcoffset = srcx * 3;
1647f29dbc25Smrg        ch3_offset = 0;
1648f29dbc25Smrg        temp = width * 3;
1649f29dbc25Smrg        ch3_size = (((temp + 3) >> 2) << 16) | height;
165004007ebaSmrg    }
165104007ebaSmrg    else {
1652f29dbc25Smrg        ch3_size = size;
1653f29dbc25Smrg
1654f29dbc25Smrg        if (gp3_src_pix_shift == 3) {
1655f29dbc25Smrg            /* CALCULATE INDENT AND SOURCE OFFSET */
1656f29dbc25Smrg
1657f29dbc25Smrg            indent = (srcx >> 1);
1658f29dbc25Smrg            srcoffset = (indent & ~3L);
1659f29dbc25Smrg            indent &= 3;
1660f29dbc25Smrg            ch3_offset = indent | ((srcx & 1) << 25);
1661f29dbc25Smrg
1662f29dbc25Smrg            temp = ((width + (srcx & 1) + 1) >> 1) + indent;
166304007ebaSmrg        }
166404007ebaSmrg        else {
1665f29dbc25Smrg            indent = (srcx << gp3_src_pix_shift);
1666f29dbc25Smrg            srcoffset = (indent & ~3L);
1667f29dbc25Smrg            indent &= 3;
1668f29dbc25Smrg            ch3_offset = indent;
1669f29dbc25Smrg
1670f29dbc25Smrg            temp = (width << gp3_src_pix_shift) + indent;
1671f29dbc25Smrg        }
1672f29dbc25Smrg    }
1673f29dbc25Smrg
1674f29dbc25Smrg    total_dwords = (temp + 3) >> 2;
1675f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
1676f29dbc25Smrg    dword_count = (temp >> 2);
1677f29dbc25Smrg    byte_count = (temp & 3);
1678f29dbc25Smrg
1679f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
1680f29dbc25Smrg        (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
1681f29dbc25Smrg
1682f29dbc25Smrg    /* SET APPROPRIATE ENABLES */
1683f29dbc25Smrg
1684f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
1685f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
1686f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
1687f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE |
1688f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
1689f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1690f29dbc25Smrg
1691f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
169204007ebaSmrg                    (dstoffset & 0x3FFFFF) | gp3_pat_origin);
1693f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
1694f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
1695f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size);
1696f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
1697f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
169804007ebaSmrg                    GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
169904007ebaSmrg                    gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
170004007ebaSmrg                                      << 20));
1701f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
1702f29dbc25Smrg
1703f29dbc25Smrg    /* START THE BLT */
1704f29dbc25Smrg
1705f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1706f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1707f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1708f29dbc25Smrg
1709f29dbc25Smrg    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
1710f29dbc25Smrg        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
1711f29dbc25Smrg        /* UPDATE THE COMMAND POINTER */
1712f29dbc25Smrg
1713f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
1714f29dbc25Smrg
1715f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
1716f29dbc25Smrg
1717f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
1718f29dbc25Smrg
1719f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
1720f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
1721f29dbc25Smrg
1722f29dbc25Smrg            GP3_WAIT_WRAP(temp);
1723f29dbc25Smrg            WRITE_COMMAND32(0,
172404007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
172504007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
172604007ebaSmrg        }
172704007ebaSmrg        else {
1728f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
1729f29dbc25Smrg            WRITE_COMMAND32(0,
173004007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
1731f29dbc25Smrg        }
1732f29dbc25Smrg
1733f29dbc25Smrg        /* WRITE DWORD COUNT */
1734f29dbc25Smrg
173504007ebaSmrg        WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
1736f29dbc25Smrg
1737f29dbc25Smrg        while (height--) {
1738f29dbc25Smrg            /* WRITE DATA */
1739f29dbc25Smrg
1740f29dbc25Smrg            WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count);
1741f29dbc25Smrg            WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data,
174204007ebaSmrg                                         srcoffset + (dword_count << 2),
174304007ebaSmrg                                         byte_count);
1744f29dbc25Smrg
1745f29dbc25Smrg            srcoffset += pitch;
1746f29dbc25Smrg            cim_cmd_ptr += total_dwords << 2;
1747f29dbc25Smrg        }
1748f29dbc25Smrg
1749f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1750f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
175104007ebaSmrg    }
175204007ebaSmrg    else {
1753f29dbc25Smrg        /* WRITE DATA LINE BY LINE
1754f29dbc25Smrg         * Each line will be created as a separate command buffer entry to
1755f29dbc25Smrg         * allow line-by-line wrapping and to allow simultaneous rendering
1756f29dbc25Smrg         * by the HW.
1757f29dbc25Smrg         */
1758f29dbc25Smrg
1759f29dbc25Smrg        while (height--) {
1760f29dbc25Smrg            /* UPDATE THE COMMAND POINTER
1761f29dbc25Smrg             * The WRITE_COMMANDXX macros use a pointer to the current buffer
1762f29dbc25Smrg             * space. This is created by adding gp3_cmd_current to the base
1763f29dbc25Smrg             * pointer.
1764f29dbc25Smrg             */
1765f29dbc25Smrg
1766f29dbc25Smrg            cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
1767f29dbc25Smrg
1768f29dbc25Smrg            /* CHECK IF A WRAP WILL BE NEEDED */
1769f29dbc25Smrg
1770f29dbc25Smrg            gp3_cmd_next = gp3_cmd_current + size_dwords;
1771f29dbc25Smrg            if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
1772f29dbc25Smrg                gp3_cmd_next = gp3_cmd_top;
1773f29dbc25Smrg
1774f29dbc25Smrg                /* WAIT FOR HARDWARE */
1775f29dbc25Smrg
1776f29dbc25Smrg                GP3_WAIT_WRAP(temp);
1777f29dbc25Smrg                WRITE_COMMAND32(0,
177804007ebaSmrg                                GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP
177904007ebaSmrg                                | GP3_DATA_LOAD_HDR_ENABLE);
178004007ebaSmrg            }
178104007ebaSmrg            else {
1782f29dbc25Smrg                /* WAIT FOR AVAILABLE SPACE */
1783f29dbc25Smrg
1784f29dbc25Smrg                GP3_WAIT_PRIMITIVE(temp);
1785f29dbc25Smrg                WRITE_COMMAND32(0,
178604007ebaSmrg                                GP3_DATA_LOAD_HDR_TYPE |
178704007ebaSmrg                                GP3_DATA_LOAD_HDR_ENABLE);
1788f29dbc25Smrg            }
1789f29dbc25Smrg
1790f29dbc25Smrg            /* WRITE DWORD COUNT */
1791f29dbc25Smrg
1792f29dbc25Smrg            WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
1793f29dbc25Smrg
1794f29dbc25Smrg            /* WRITE DATA */
1795f29dbc25Smrg
1796f29dbc25Smrg            WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count);
1797f29dbc25Smrg            WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data,
179804007ebaSmrg                                         srcoffset + (dword_count << 2),
179904007ebaSmrg                                         byte_count);
1800f29dbc25Smrg
1801f29dbc25Smrg            /* UPDATE POINTERS */
1802f29dbc25Smrg
1803f29dbc25Smrg            srcoffset += pitch;
1804f29dbc25Smrg            WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1805f29dbc25Smrg            gp3_cmd_current = gp3_cmd_next;
1806f29dbc25Smrg        }
1807f29dbc25Smrg    }
1808f29dbc25Smrg}
1809f29dbc25Smrg
1810f29dbc25Smrg/*---------------------------------------------------------------------------
1811f29dbc25Smrg * gp_rotate_blt
1812f29dbc25Smrg *
1813f29dbc25Smrg * This routine is called to rotate a rectangular area of video memory.  The
1814f29dbc25Smrg * data may be color converted during the rotation.  'Degrees' must be a
1815f29dbc25Smrg * multiple of 90 and indicates a clockwise rotation.  Width and height
1816f29dbc25Smrg * refer to the width and the height of the source.  The output
1817f29dbc25Smrg * destinations will be equal to the rotated dimensions.
1818f29dbc25Smrg *-------------------------------------------------------------------------*/
1819f29dbc25Smrg
1820f29dbc25Smrgvoid
1821f29dbc25Smrggp_rotate_blt(unsigned long dstoffset, unsigned long srcoffset,
182204007ebaSmrg              unsigned long width, unsigned long height, int degrees)
1823f29dbc25Smrg{
1824f29dbc25Smrg    unsigned long sizein, sizeout;
1825f29dbc25Smrg    unsigned long ch3_flags;
1826f29dbc25Smrg    unsigned long base;
1827f29dbc25Smrg
1828f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
1829f29dbc25Smrg        ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) |
1830f29dbc25Smrg        (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
1831f29dbc25Smrg
1832f29dbc25Smrg    srcoffset &= 0x3FFFFF;
1833f29dbc25Smrg    dstoffset &= 0x3FFFFF;
1834f29dbc25Smrg
1835f29dbc25Smrg    /* SET ROTATION PARAMETERS */
1836f29dbc25Smrg
1837f29dbc25Smrg    switch (degrees) {
1838f29dbc25Smrg    case 90:
1839f29dbc25Smrg        srcoffset += (height - 1) * gp3_src_stride;
1840f29dbc25Smrg        sizein = ((width << 16) | height);
1841f29dbc25Smrg        sizeout = ((height << 16) | width);
1842f29dbc25Smrg        ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
1843f29dbc25Smrg            GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_YDIR;
1844f29dbc25Smrg        break;
1845f29dbc25Smrg
1846f29dbc25Smrg    case 180:
1847f29dbc25Smrg        srcoffset += (height - 1) * gp3_src_stride;
1848f29dbc25Smrg        srcoffset += (width << gp3_src_pix_shift) - 1;
1849f29dbc25Smrg        sizein = sizeout = ((width << 16) | height);
1850f29dbc25Smrg        ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
1851f29dbc25Smrg            GP3_CH3_NEG_YDIR | GP3_CH3_NEG_XDIR;
1852f29dbc25Smrg        break;
1853f29dbc25Smrg
1854f29dbc25Smrg    case 270:
1855f29dbc25Smrg        srcoffset += (width << gp3_src_pix_shift) - 1;
1856f29dbc25Smrg        sizein = ((width << 16) | height);
1857f29dbc25Smrg        sizeout = ((height << 16) | width);
1858f29dbc25Smrg        ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
1859f29dbc25Smrg            GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_XDIR;
1860f29dbc25Smrg        break;
1861f29dbc25Smrg
1862f29dbc25Smrg    default:
1863f29dbc25Smrg        sizein = sizeout = ((width << 16) | height);
1864f29dbc25Smrg        ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE;
1865f29dbc25Smrg        break;
1866f29dbc25Smrg    }
1867f29dbc25Smrg
1868f29dbc25Smrg    /* SET APPROPRIATE ENABLES                           */
1869f29dbc25Smrg    /* We override the raster mode setting with a source */
1870f29dbc25Smrg    /* copy ROP.                                         */
1871f29dbc25Smrg
1872f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
1873f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE |
1874f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
1875f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE |
1876f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
1877f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
1878f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1879f29dbc25Smrg
1880f29dbc25Smrg    /* WRITE ALL BLT REGISTERS */
1881f29dbc25Smrg
1882f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_bpp | 0xCC);
1883f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset);
1884f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, sizeout);
1885f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, sizein);
1886f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset);
1887f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, ch3_flags | gp3_src_format |
188804007ebaSmrg                    ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) |
188904007ebaSmrg                    ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) |
189004007ebaSmrg                    gp3_src_stride);
1891f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
1892f29dbc25Smrg
1893f29dbc25Smrg    /* START THE BLT */
1894f29dbc25Smrg
1895f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1896f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode);
1897f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1898f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1899f29dbc25Smrg}
1900f29dbc25Smrg
1901f29dbc25Smrg/*---------------------------------------------------------------------------
1902f29dbc25Smrg * gp_mono_bitmap_to_screen_blt
1903f29dbc25Smrg *
1904f29dbc25Smrg * This routine expands and BLTs a monchrome bitmap that is stored in system
1905f29dbc25Smrg * memory into the framebuffer.  'data' points to an array of monochrome data.
1906f29dbc25Smrg * 'stride' indicates the pitch between successive lines of monochrome data.
1907f29dbc25Smrg * 'srcx' indicates the x coordinate within each line of blend data
1908f29dbc25Smrg * corresponding to the first pixel.  A y coordinate for the source is
1909f29dbc25Smrg * deliberately omitted to avoid extra calculation for simple cases that have
1910f29dbc25Smrg * no y index.  The calling program must adjust the data pointer accordingly.
1911f29dbc25Smrg *-------------------------------------------------------------------------*/
1912f29dbc25Smrg
1913f29dbc25Smrgvoid
1914f29dbc25Smrggp_mono_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx,
191504007ebaSmrg                             unsigned long width, unsigned long height,
191604007ebaSmrg                             unsigned char *data, long stride)
1917f29dbc25Smrg{
1918f29dbc25Smrg    unsigned long indent, temp;
1919f29dbc25Smrg    unsigned long total_dwords, size_dwords;
1920f29dbc25Smrg    unsigned long dword_count, byte_count;
1921f29dbc25Smrg    unsigned long size = ((width << 16) | height);
1922f29dbc25Smrg    unsigned long srcoffset, src_value;
1923f29dbc25Smrg
1924f29dbc25Smrg    /* ASSUME BITMAPS ARE DWORD ALIGNED */
1925f29dbc25Smrg    /* We will offset into the source data in DWORD increments.  We */
1926f29dbc25Smrg    /* set the source index to the remaining byte offset and        */
1927f29dbc25Smrg    /* increment the size of each line to account for the dont-care */
1928f29dbc25Smrg    /* pixel(s).                                                    */
1929f29dbc25Smrg
1930f29dbc25Smrg    indent = (srcx >> 3);
1931f29dbc25Smrg    srcoffset = (indent & ~3L);
1932f29dbc25Smrg    indent &= 3;
1933f29dbc25Smrg    src_value = (indent | ((srcx & 7) << 26));
1934f29dbc25Smrg
1935f29dbc25Smrg    /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
1936f29dbc25Smrg    /* We assume that a color pattern is being ROPed with source  */
1937f29dbc25Smrg    /* data if the pattern type is color and the preserve pattern */
1938f29dbc25Smrg    /* was set.                                                   */
1939f29dbc25Smrg
1940f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
1941f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE |
1942f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
1943f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
1944f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE |
1945f29dbc25Smrg        GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
1946f29dbc25Smrg
1947f29dbc25Smrg    if (gp3_ch3_pat) {
1948f29dbc25Smrg        gp3_cmd_header |=
1949f29dbc25Smrg            GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
1950f29dbc25Smrg
1951f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
1952f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
1953f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
1954f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
195504007ebaSmrg    }
195604007ebaSmrg    else {
1957f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
195804007ebaSmrg                        ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
1959f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
1960f29dbc25Smrg    }
1961f29dbc25Smrg    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) {
1962f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
196304007ebaSmrg                        gp3_raster_mode | GP3_RM_SOURCE_INVERT);
196404007ebaSmrg    }
196504007ebaSmrg    else {
1966f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
196704007ebaSmrg                        gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
1968f29dbc25Smrg    }
1969f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, src_value);
1970f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
1971f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET,
197204007ebaSmrg                    ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
1973f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE,
197404007ebaSmrg                    gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_MONO);
1975f29dbc25Smrg
1976f29dbc25Smrg    /* START THE BLT */
1977f29dbc25Smrg
1978f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
1979f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
1980f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
1981f29dbc25Smrg
1982f29dbc25Smrg    /* CALCULATE THE SIZE OF ONE LINE */
1983f29dbc25Smrg
1984f29dbc25Smrg    size = ((width + (srcx & 7) + 7) >> 3) + indent;
1985f29dbc25Smrg    total_dwords = (size + 3) >> 2;
1986f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
1987f29dbc25Smrg    dword_count = (size >> 2);
1988f29dbc25Smrg    byte_count = (size & 3);
1989f29dbc25Smrg
1990f29dbc25Smrg    /* CHECK FOR SMALL BLT CASE */
1991f29dbc25Smrg    /* If the total amount of monochrome data is less than 50K and we have */
1992f29dbc25Smrg    /* room in the command buffer, we will do all data writes in a single  */
1993f29dbc25Smrg    /* data packet.                                                        */
1994f29dbc25Smrg
1995f29dbc25Smrg    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
1996f29dbc25Smrg        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
1997f29dbc25Smrg        /* UPDATE THE COMMAND POINTER */
1998f29dbc25Smrg
1999f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2000f29dbc25Smrg
2001f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
2002f29dbc25Smrg
2003f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
2004f29dbc25Smrg
2005f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2006f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
2007f29dbc25Smrg
2008f29dbc25Smrg            GP3_WAIT_WRAP(temp);
2009f29dbc25Smrg            WRITE_COMMAND32(0,
201004007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
201104007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
201204007ebaSmrg        }
201304007ebaSmrg        else {
2014f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
2015f29dbc25Smrg            WRITE_COMMAND32(0,
201604007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
2017f29dbc25Smrg        }
2018f29dbc25Smrg
2019f29dbc25Smrg        /* WRITE DWORD COUNT */
2020f29dbc25Smrg
2021f29dbc25Smrg        WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height));
2022f29dbc25Smrg
2023f29dbc25Smrg        while (height--) {
2024f29dbc25Smrg            /* WRITE DATA */
2025f29dbc25Smrg
2026f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
2027f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
202804007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
2029f29dbc25Smrg
2030f29dbc25Smrg            srcoffset += stride;
2031f29dbc25Smrg            cim_cmd_ptr += total_dwords << 2;
2032f29dbc25Smrg        }
2033f29dbc25Smrg
2034f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2035f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
203604007ebaSmrg    }
203704007ebaSmrg    else {
2038f29dbc25Smrg        /* WRITE DATA LINE BY LINE
2039f29dbc25Smrg         * Each line will be created as a separate command buffer entry to
2040f29dbc25Smrg         * allow line-by-line wrapping and to allow simultaneous rendering
2041f29dbc25Smrg         * by the HW.
2042f29dbc25Smrg         */
2043f29dbc25Smrg
2044f29dbc25Smrg        while (height--) {
2045f29dbc25Smrg            /* UPDATE THE COMMAND POINTER
2046f29dbc25Smrg             * The WRITE_COMMANDXX macros use a pointer to the current buffer
2047f29dbc25Smrg             * space.  This is created by adding gp3_cmd_current to the base
2048f29dbc25Smrg             * pointer.
2049f29dbc25Smrg             */
2050f29dbc25Smrg
2051f29dbc25Smrg            cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2052f29dbc25Smrg
2053f29dbc25Smrg            /* CHECK IF A WRAP WILL BE NEEDED */
2054f29dbc25Smrg
2055f29dbc25Smrg            gp3_cmd_next = gp3_cmd_current + size_dwords;
2056f29dbc25Smrg            if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2057f29dbc25Smrg                gp3_cmd_next = gp3_cmd_top;
2058f29dbc25Smrg
2059f29dbc25Smrg                /* WAIT FOR HARDWARE */
2060f29dbc25Smrg
2061f29dbc25Smrg                GP3_WAIT_WRAP(temp);
2062f29dbc25Smrg                WRITE_COMMAND32(0,
206304007ebaSmrg                                GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP
206404007ebaSmrg                                | GP3_DATA_LOAD_HDR_ENABLE);
206504007ebaSmrg            }
206604007ebaSmrg            else {
2067f29dbc25Smrg                /* WAIT FOR AVAILABLE SPACE */
2068f29dbc25Smrg
2069f29dbc25Smrg                GP3_WAIT_PRIMITIVE(temp);
2070f29dbc25Smrg                WRITE_COMMAND32(0,
207104007ebaSmrg                                GP3_DATA_LOAD_HDR_TYPE |
207204007ebaSmrg                                GP3_DATA_LOAD_HDR_ENABLE);
2073f29dbc25Smrg            }
2074f29dbc25Smrg
2075f29dbc25Smrg            /* WRITE DWORD COUNT */
2076f29dbc25Smrg
2077f29dbc25Smrg            WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords);
2078f29dbc25Smrg
2079f29dbc25Smrg            /* WRITE DATA */
2080f29dbc25Smrg
2081f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
2082f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
208304007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
2084f29dbc25Smrg
2085f29dbc25Smrg            /* UPDATE POINTERS */
2086f29dbc25Smrg
2087f29dbc25Smrg            srcoffset += stride;
2088f29dbc25Smrg            WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2089f29dbc25Smrg            gp3_cmd_current = gp3_cmd_next;
2090f29dbc25Smrg        }
2091f29dbc25Smrg    }
2092f29dbc25Smrg}
2093f29dbc25Smrg
2094f29dbc25Smrg/*---------------------------------------------------------------------------
2095f29dbc25Smrg * gp_text_blt
2096f29dbc25Smrg *
2097f29dbc25Smrg * This routine expands and BLTs byte-packed monochrome data to the screen.
2098f29dbc25Smrg * There is assumed to be no x clipping involved in the BLT.
2099f29dbc25Smrg *-------------------------------------------------------------------------*/
2100f29dbc25Smrg
2101f29dbc25Smrgvoid
2102f29dbc25Smrggp_text_blt(unsigned long dstoffset, unsigned long width,
210304007ebaSmrg            unsigned long height, unsigned char *data)
2104f29dbc25Smrg{
2105f29dbc25Smrg    unsigned long temp, dwords_total;
2106f29dbc25Smrg    unsigned long dword_count, byte_count;
2107f29dbc25Smrg    unsigned long size = ((width << 16) | height);
2108f29dbc25Smrg    unsigned long srcoffset = 0;
2109f29dbc25Smrg
2110f29dbc25Smrg    /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS                */
2111f29dbc25Smrg    /* We assume that a color pattern is being ROPed with source  */
2112f29dbc25Smrg    /* data if the pattern type is color and the preserve pattern */
2113f29dbc25Smrg    /* was set.                                                   */
2114f29dbc25Smrg
2115f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
2116f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE |
2117f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
2118f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
2119f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE |
2120f29dbc25Smrg        GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
2121f29dbc25Smrg
2122f29dbc25Smrg    if (gp3_ch3_pat) {
2123f29dbc25Smrg        gp3_cmd_header |=
2124f29dbc25Smrg            GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
2125f29dbc25Smrg
2126f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
2127f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
2128f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
2129f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
213004007ebaSmrg    }
213104007ebaSmrg    else {
2132f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
213304007ebaSmrg                        ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
2134f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
2135f29dbc25Smrg    }
2136f29dbc25Smrg    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) {
2137f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
213804007ebaSmrg                        gp3_raster_mode | GP3_RM_SOURCE_INVERT);
213904007ebaSmrg    }
214004007ebaSmrg    else {
2141f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
214204007ebaSmrg                        gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
2143f29dbc25Smrg    }
2144f29dbc25Smrg
2145f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 0);
2146f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
2147f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET,
214804007ebaSmrg                    ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)));
2149f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE,
215004007ebaSmrg                    gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_BP_MONO);
2151f29dbc25Smrg
2152f29dbc25Smrg    /* START THE BLT */
2153f29dbc25Smrg
2154f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2155f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2156f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
2157f29dbc25Smrg
2158f29dbc25Smrg    /* CALCULATE THE TOTAL NUMBER OF BYTES */
2159f29dbc25Smrg
2160f29dbc25Smrg    size = ((width + 7) >> 3) * height;
2161f29dbc25Smrg
2162f29dbc25Smrg    /* WRITE ALL DATA IN CHUNKS */
2163f29dbc25Smrg
2164f29dbc25Smrg    do {
2165f29dbc25Smrg        /* UPDATE THE COMMAND POINTER */
2166f29dbc25Smrg
2167f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2168f29dbc25Smrg
2169f29dbc25Smrg        if (size > 8192) {
2170f29dbc25Smrg            dword_count = 2048;
2171f29dbc25Smrg            byte_count = 0;
2172f29dbc25Smrg            dwords_total = 2048;
2173f29dbc25Smrg            size -= 8192;
217404007ebaSmrg        }
217504007ebaSmrg        else {
2176f29dbc25Smrg            dword_count = (size >> 2);
2177f29dbc25Smrg            byte_count = (size & 3);
2178f29dbc25Smrg            dwords_total = (size + 3) >> 2;
2179f29dbc25Smrg            size = 0;
2180f29dbc25Smrg        }
2181f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + (dwords_total << 2) + 8;
2182f29dbc25Smrg
2183f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
2184f29dbc25Smrg
2185f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2186f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
2187f29dbc25Smrg
2188f29dbc25Smrg            /* WAIT FOR HARDWARE */
2189f29dbc25Smrg
2190f29dbc25Smrg            GP3_WAIT_WRAP(temp);
2191f29dbc25Smrg            WRITE_COMMAND32(0,
219204007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
219304007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
219404007ebaSmrg        }
219504007ebaSmrg        else {
2196f29dbc25Smrg            /* WAIT FOR AVAILABLE SPACE */
2197f29dbc25Smrg
2198f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
2199f29dbc25Smrg            WRITE_COMMAND32(0,
220004007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
2201f29dbc25Smrg        }
2202f29dbc25Smrg
2203f29dbc25Smrg        /* WRITE DWORD COUNT */
2204f29dbc25Smrg
2205f29dbc25Smrg        WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | dwords_total);
2206f29dbc25Smrg
2207f29dbc25Smrg        /* WRITE DATA */
2208f29dbc25Smrg
2209f29dbc25Smrg        WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
2210f29dbc25Smrg        WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
221104007ebaSmrg                              srcoffset + (dword_count << 2), byte_count);
2212f29dbc25Smrg
2213f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2214f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
2215f29dbc25Smrg
2216f29dbc25Smrg        /* UPDATE THE SOURCE OFFSET */
2217f29dbc25Smrg        /* We add a constant value because the code will loop only if the */
2218f29dbc25Smrg        /* data exceeds 8192 bytes.                                       */
2219f29dbc25Smrg
2220f29dbc25Smrg        srcoffset += 8192;
2221f29dbc25Smrg
2222f29dbc25Smrg    } while (size);
2223f29dbc25Smrg}
2224f29dbc25Smrg
2225f29dbc25Smrg/*---------------------------------------------------------------------------
2226f29dbc25Smrg * gp_mono_expand_blt
2227f29dbc25Smrg *
2228f29dbc25Smrg * This routine expands monochrome data that is stored in video memory into
2229f29dbc25Smrg * the current BPP.  The source and destination regions are assumed not to
2230f29dbc25Smrg * overlap.  The pitch of the source data is specified in gp_set_strides.
2231f29dbc25Smrg * 'srcy' is deliberately omitted to prevent extra calculations for simple
2232f29dbc25Smrg * applications that have no source indexes.
2233f29dbc25Smrg *-------------------------------------------------------------------------*/
2234f29dbc25Smrg
2235f29dbc25Smrgvoid
2236f29dbc25Smrggp_mono_expand_blt(unsigned long dstoffset, unsigned long srcoffset,
223704007ebaSmrg                   unsigned long srcx, unsigned long width,
223804007ebaSmrg                   unsigned long height, int byte_packed)
2239f29dbc25Smrg{
2240f29dbc25Smrg    unsigned long base;
2241f29dbc25Smrg    unsigned long blt_mode;
2242f29dbc25Smrg    unsigned long size = ((width << 16) | height);
2243f29dbc25Smrg
2244f29dbc25Smrg    /* ADJUST SOURCE OFFSET */
2245f29dbc25Smrg
2246f29dbc25Smrg    srcoffset += (srcx >> 3);
2247f29dbc25Smrg    srcx &= 7;
2248f29dbc25Smrg
2249f29dbc25Smrg    /* CALCULATE BASE OFFSET REGISTER */
2250f29dbc25Smrg
2251f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
2252f29dbc25Smrg        ((gp3_fb_base << 14) + ((srcoffset & 0xFFC00000) >> 10)) |
2253f29dbc25Smrg        (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
2254f29dbc25Smrg
2255f29dbc25Smrg    /* SET THE SOURCE TYPE */
2256f29dbc25Smrg
2257f29dbc25Smrg    if (byte_packed)
2258f29dbc25Smrg        blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_BP_MONO;
2259f29dbc25Smrg    else
2260f29dbc25Smrg        blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_MONO;
2261f29dbc25Smrg
2262f29dbc25Smrg    /* SET HEADER ENABLES */
2263f29dbc25Smrg
2264f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
2265f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE |
2266f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
2267f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
2268f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE |
2269f29dbc25Smrg        GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
2270f29dbc25Smrg
2271f29dbc25Smrg    /* ENABLE COLOR PATTERN IF APPLICABLE */
2272f29dbc25Smrg
2273f29dbc25Smrg    if (gp3_ch3_pat) {
2274f29dbc25Smrg        gp3_cmd_header |=
2275f29dbc25Smrg            GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
2276f29dbc25Smrg
2277f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin);
2278f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
2279f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format);
2280f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
228104007ebaSmrg    }
228204007ebaSmrg    else {
2283f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_DST_OFFSET,
228404007ebaSmrg                        ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
2285f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0);
2286f29dbc25Smrg    }
2287f29dbc25Smrg    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) {
2288f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
228904007ebaSmrg                        gp3_raster_mode | GP3_RM_SOURCE_INVERT);
229004007ebaSmrg    }
229104007ebaSmrg    else {
2292f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
229304007ebaSmrg                        gp3_raster_mode & ~GP3_RM_SOURCE_INVERT);
2294f29dbc25Smrg    }
2295f29dbc25Smrg
2296f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
229704007ebaSmrg    WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, (srcoffset & 0x3FFFFF) | (srcx << 26));
2298f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
2299f29dbc25Smrg
2300f29dbc25Smrg    /* WORKAROUND FOR SIBZ #3744
2301f29dbc25Smrg     * Under extremely rare conditions, very narrow byte-packed mono BLTs
2302f29dbc25Smrg     * can hang the GP.  Even under the rare case, the bad condition will
2303f29dbc25Smrg     * only happen once every 16 lines.  The workaround is to break the
2304f29dbc25Smrg     * offending BLT into a series of safer BLTs.  This method is preferred
2305f29dbc25Smrg     * over a two-pass approach because it does not require saving and
2306f29dbc25Smrg     * restoring any GP state, such as the ROP or mono colors.
2307f29dbc25Smrg     */
2308f29dbc25Smrg
2309f29dbc25Smrg    if ((gp3_blt_mode & GP3_BM_DST_REQ) && byte_packed && (gp3_pix_shift < 2)
2310f29dbc25Smrg        && (width < 5) && ((srcoffset & 0x1F) == 0x1F)
2311f29dbc25Smrg        && ((srcx + width) > 8)) {
2312f29dbc25Smrg        unsigned long dstoff1, size1, org1;
2313f29dbc25Smrg        unsigned long dstoff2, size2, org2;
2314f29dbc25Smrg        unsigned long tempheight;
2315f29dbc25Smrg
2316f29dbc25Smrg        size1 = ((8 - srcx) << 16) | 1;
2317f29dbc25Smrg        size2 = ((width + srcx - 8) << 16) | 1;
2318f29dbc25Smrg        org1 = gp3_pat_origin;
231904007ebaSmrg        org2 = (org1 & 0xE0000000) | ((org1 + ((8 - srcx) << 26)) & 0x1C000000);
2320f29dbc25Smrg        dstoff1 = dstoffset & 0x3FFFFF;
2321f29dbc25Smrg        dstoff2 = (dstoff1 + 8 - srcx) << gp3_pix_shift;
2322f29dbc25Smrg
2323f29dbc25Smrg        while (height) {
2324f29dbc25Smrg            /* DIVIDE THE FIRST LINE INTO TWO SINGLE LINE BLTS */
2325f29dbc25Smrg
2326f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size1);
2327f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size1);
2328f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
232904007ebaSmrg                            (srcoffset & 0x3FFFFF) | (srcx << 26));
2330f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1);
2331f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1);
2332f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2333f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
2334f29dbc25Smrg            WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2335f29dbc25Smrg            gp3_cmd_current = gp3_cmd_next;
2336f29dbc25Smrg            gp_wait_until_idle();
2337f29dbc25Smrg
2338f29dbc25Smrg            gp_declare_blt(gp3_blt_flags);
2339f29dbc25Smrg            gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
2340f29dbc25Smrg                GP3_BLT_HDR_DST_OFF_ENABLE |
2341f29dbc25Smrg                GP3_BLT_HDR_WIDHI_ENABLE |
2342f29dbc25Smrg                GP3_BLT_HDR_BLT_MODE_ENABLE |
2343f29dbc25Smrg                GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
2344f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size2);
2345f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size2);
2346f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, ((srcoffset + 1) & 0x3FFFFF));
2347f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff2 | org2);
2348f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org2);
2349f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2350f29dbc25Smrg            WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
2351f29dbc25Smrg            WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2352f29dbc25Smrg            gp3_cmd_current = gp3_cmd_next;
2353f29dbc25Smrg            gp_wait_until_idle();
2354f29dbc25Smrg
2355f29dbc25Smrg            if (--height) {
2356f29dbc25Smrg                org1 += 0x20000000;
2357f29dbc25Smrg                org2 += 0x20000000;
2358f29dbc25Smrg                dstoff1 += gp3_dst_stride;
2359f29dbc25Smrg                dstoff2 += gp3_dst_stride;
2360f29dbc25Smrg                srcoffset += 2;
2361f29dbc25Smrg
2362f29dbc25Smrg                /* THE NEXT 15 LINES ARE NOW 'SAFE' - THEY DO NOT SHOW THE
2363f29dbc25Smrg                 * PROBLEM */
2364f29dbc25Smrg
2365f29dbc25Smrg                tempheight = 15;
2366f29dbc25Smrg                if (tempheight > height)
2367f29dbc25Smrg                    tempheight = height;
2368f29dbc25Smrg
2369f29dbc25Smrg                gp_declare_blt(gp3_blt_flags);
2370f29dbc25Smrg                gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
2371f29dbc25Smrg                    GP3_BLT_HDR_DST_OFF_ENABLE |
2372f29dbc25Smrg                    GP3_BLT_HDR_WIDHI_ENABLE |
2373f29dbc25Smrg                    GP3_BLT_HDR_BLT_MODE_ENABLE |
2374f29dbc25Smrg                    GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE;
237504007ebaSmrg                WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | tempheight);
237604007ebaSmrg                WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | tempheight);
2377f29dbc25Smrg                WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
237804007ebaSmrg                                (srcoffset & 0x3FFFFF) | (srcx << 26));
2379f29dbc25Smrg                WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1);
2380f29dbc25Smrg                WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1);
2381f29dbc25Smrg                WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2382f29dbc25Smrg                WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
2383f29dbc25Smrg                WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2384f29dbc25Smrg                gp3_cmd_current = gp3_cmd_next;
2385f29dbc25Smrg                gp_wait_until_idle();
2386f29dbc25Smrg
2387f29dbc25Smrg                height -= tempheight;
2388f29dbc25Smrg
2389f29dbc25Smrg                if (height) {
2390f29dbc25Smrg                    gp_declare_blt(gp3_blt_flags);
2391f29dbc25Smrg                    gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
2392f29dbc25Smrg                        GP3_BLT_HDR_DST_OFF_ENABLE |
2393f29dbc25Smrg                        GP3_BLT_HDR_WIDHI_ENABLE |
2394f29dbc25Smrg                        GP3_BLT_HDR_BLT_MODE_ENABLE |
2395f29dbc25Smrg                        GP3_BLT_HDR_CH3_OFF_ENABLE |
2396f29dbc25Smrg                        GP3_BLT_HDR_CH3_WIDHI_ENABLE;
2397f29dbc25Smrg
2398f29dbc25Smrg                    /* ADJUST ORIGIN */
2399f29dbc25Smrg                    /* If we get here, we added a full 15 lines which is
2400f29dbc25Smrg                     * equivalent to subtracting one from the pattern y origin
2401f29dbc25Smrg                     * (adding 15). */
2402f29dbc25Smrg
2403f29dbc25Smrg                    org1 -= 0x20000000;
2404f29dbc25Smrg                    org2 -= 0x20000000;
2405f29dbc25Smrg                    dstoff1 += (gp3_dst_stride * 15);
2406f29dbc25Smrg                    dstoff2 += (gp3_dst_stride * 15);
2407f29dbc25Smrg                    srcoffset += 30;
2408f29dbc25Smrg                }
2409f29dbc25Smrg            }
2410f29dbc25Smrg        }
2411f29dbc25Smrg        return;
2412f29dbc25Smrg    }
2413f29dbc25Smrg
2414f29dbc25Smrg    /* START THE BLT */
2415f29dbc25Smrg
2416f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2417f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, blt_mode);
2418f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2419f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
2420f29dbc25Smrg}
2421f29dbc25Smrg
2422f29dbc25Smrg/*---------------------------------------------------------------------------
2423f29dbc25Smrg * gp_antialiased_text
2424f29dbc25Smrg *
2425f29dbc25Smrg * This routine implements alpha blending between a constant source color and
2426f29dbc25Smrg * a destination region.  The degree of the blend is controlled by an array
2427f29dbc25Smrg * of 4BPP/8BPP values specified in 'data'.  'stride' indicates the pitch
2428f29dbc25Smrg * between successive lines of blend data.  'srcx' indicates the x
2429f29dbc25Smrg * coordinate within each line of blend data corresponding to the first
2430f29dbc25Smrg * pixel.  A y coordinate for the source is deliberately omitted to avoid
2431f29dbc25Smrg * extra calculation for simple cases that have no y index.  The calling
2432f29dbc25Smrg * program must adjust the data pointer accordingly.  'fourbpp' selects
2433f29dbc25Smrg * between 4BPP and 8BPP alpha.
2434f29dbc25Smrg *-------------------------------------------------------------------------*/
2435f29dbc25Smrg
2436f29dbc25Smrgvoid
2437f29dbc25Smrggp_antialiased_text(unsigned long dstoffset, unsigned long srcx,
243804007ebaSmrg                    unsigned long width, unsigned long height,
243904007ebaSmrg                    unsigned char *data, long stride, int fourbpp)
2440f29dbc25Smrg{
2441f29dbc25Smrg    unsigned long indent, temp;
2442f29dbc25Smrg    unsigned long total_dwords, size_dwords;
2443f29dbc25Smrg    unsigned long dword_count, byte_count;
2444f29dbc25Smrg    unsigned long size = ((width << 16) | height);
2445f29dbc25Smrg    unsigned long ch3_offset, srcoffset;
2446f29dbc25Smrg    unsigned long base, depth_flag;
2447f29dbc25Smrg
2448f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
2449f29dbc25Smrg        (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
2450f29dbc25Smrg
2451f29dbc25Smrg    /* ENABLE ALL RELEVANT REGISTERS */
2452f29dbc25Smrg    /* We override the raster mode register to force the */
2453f29dbc25Smrg    /* correct alpha blend                               */
2454f29dbc25Smrg
2455f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
2456f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE |
2457f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
2458f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE |
2459f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
2460f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
2461f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
2462f29dbc25Smrg
2463f29dbc25Smrg    /* CALCULATIONS BASED ON ALPHA DEPTH */
2464f29dbc25Smrg    /* Although most antialiased text is 4BPP, the hardware supports */
2465f29dbc25Smrg    /* a full 8BPP.  Either case is supported by this routine.       */
2466f29dbc25Smrg
2467f29dbc25Smrg    if (fourbpp) {
2468f29dbc25Smrg        depth_flag = GP3_CH3_SRC_4BPP_ALPHA;
2469f29dbc25Smrg        indent = (srcx >> 1);
2470f29dbc25Smrg        srcoffset = (indent & ~3L);
2471f29dbc25Smrg        indent &= 3;
2472f29dbc25Smrg        ch3_offset = indent | ((srcx & 1) << 25);
2473f29dbc25Smrg
2474f29dbc25Smrg        temp = ((width + (srcx & 1) + 1) >> 1) + indent;
247504007ebaSmrg    }
247604007ebaSmrg    else {
2477f29dbc25Smrg        depth_flag = GP3_CH3_SRC_8BPP_ALPHA;
2478f29dbc25Smrg        indent = srcx;
2479f29dbc25Smrg        srcoffset = (indent & ~3L);
2480f29dbc25Smrg        indent &= 3;
2481f29dbc25Smrg        ch3_offset = indent;
2482f29dbc25Smrg
2483f29dbc25Smrg        temp = width + indent;
2484f29dbc25Smrg    }
2485f29dbc25Smrg
2486f29dbc25Smrg    total_dwords = (temp + 3) >> 2;
2487f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
2488f29dbc25Smrg    dword_count = (temp >> 2);
2489f29dbc25Smrg    byte_count = (temp & 3);
2490f29dbc25Smrg
2491f29dbc25Smrg    /* SET RASTER MODE REGISTER */
2492f29dbc25Smrg    /* Alpha blending will only apply to RGB when no alpha component is present. */
2493f29dbc25Smrg    /* As 8BPP is not supported for this routine, the only alpha-less mode is    */
2494f29dbc25Smrg    /* 5:6:5.                                                                    */
2495f29dbc25Smrg
2496f29dbc25Smrg    if (gp3_bpp == GP3_RM_BPPFMT_565) {
2497f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
249804007ebaSmrg                        gp3_bpp |
249904007ebaSmrg                        GP3_RM_ALPHA_TO_RGB |
250004007ebaSmrg                        GP3_RM_ALPHA_A_PLUS_BETA_B |
250104007ebaSmrg                        GP3_RM_SELECT_ALPHA_CHAN_3);
250204007ebaSmrg    }
250304007ebaSmrg    else {
2504f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
250504007ebaSmrg                        gp3_bpp |
250604007ebaSmrg                        GP3_RM_ALPHA_ALL |
250704007ebaSmrg                        GP3_RM_ALPHA_A_PLUS_BETA_B |
250804007ebaSmrg                        GP3_RM_SELECT_ALPHA_CHAN_3);
2509f29dbc25Smrg    }
2510f29dbc25Smrg
2511f29dbc25Smrg    /* WRITE ALL REMAINING REGISTERS */
2512f29dbc25Smrg
2513f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
2514f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
2515f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
2516f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
2517f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
2518f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
251904007ebaSmrg                    GP3_CH3_HST_SRC_ENABLE |
252004007ebaSmrg                    depth_flag | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) <<
252104007ebaSmrg                                  20));
2522f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_DST_REQ);
2523f29dbc25Smrg
2524f29dbc25Smrg    /* START THE BLT */
2525f29dbc25Smrg
2526f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2527f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2528f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
2529f29dbc25Smrg
2530f29dbc25Smrg    /* WRITE DATA LINE BY LINE
2531f29dbc25Smrg     * Each line will be created as a separate command buffer entry to allow
2532f29dbc25Smrg     * line-by-line wrapping and to allow simultaneous rendering by the HW.
2533f29dbc25Smrg     */
2534f29dbc25Smrg
2535f29dbc25Smrg    if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
2536f29dbc25Smrg        (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) {
2537f29dbc25Smrg        /* UPDATE THE COMMAND POINTER */
2538f29dbc25Smrg
2539f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2540f29dbc25Smrg
2541f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
2542f29dbc25Smrg
2543f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
2544f29dbc25Smrg
2545f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2546f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
2547f29dbc25Smrg
2548f29dbc25Smrg            GP3_WAIT_WRAP(temp);
2549f29dbc25Smrg            WRITE_COMMAND32(0,
255004007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
255104007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
255204007ebaSmrg        }
255304007ebaSmrg        else {
2554f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
2555f29dbc25Smrg            WRITE_COMMAND32(0,
255604007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
2557f29dbc25Smrg        }
2558f29dbc25Smrg
2559f29dbc25Smrg        /* WRITE DWORD COUNT */
2560f29dbc25Smrg
256104007ebaSmrg        WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
2562f29dbc25Smrg
2563f29dbc25Smrg        while (height--) {
2564f29dbc25Smrg            /* WRITE DATA */
2565f29dbc25Smrg
2566f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
2567f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
256804007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
2569f29dbc25Smrg
2570f29dbc25Smrg            srcoffset += stride;
2571f29dbc25Smrg            cim_cmd_ptr += total_dwords << 2;
2572f29dbc25Smrg        }
2573f29dbc25Smrg
2574f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2575f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
257604007ebaSmrg    }
257704007ebaSmrg    else {
2578f29dbc25Smrg        while (height--) {
2579f29dbc25Smrg            /* UPDATE THE COMMAND POINTER
2580f29dbc25Smrg             * The WRITE_COMMANDXX macros use a pointer to the current buffer
2581f29dbc25Smrg             * space.  This is created by adding gp3_cmd_current to the base
2582f29dbc25Smrg             * pointer.
2583f29dbc25Smrg             */
2584f29dbc25Smrg
2585f29dbc25Smrg            cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2586f29dbc25Smrg
2587f29dbc25Smrg            /* CHECK IF A WRAP WILL BE NEEDED */
2588f29dbc25Smrg
2589f29dbc25Smrg            gp3_cmd_next = gp3_cmd_current + size_dwords;
2590f29dbc25Smrg            if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2591f29dbc25Smrg                gp3_cmd_next = gp3_cmd_top;
2592f29dbc25Smrg
2593f29dbc25Smrg                /* WAIT FOR HARDWARE */
2594f29dbc25Smrg
2595f29dbc25Smrg                GP3_WAIT_WRAP(temp);
2596f29dbc25Smrg                WRITE_COMMAND32(0,
259704007ebaSmrg                                GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP
259804007ebaSmrg                                | GP3_DATA_LOAD_HDR_ENABLE);
259904007ebaSmrg            }
260004007ebaSmrg            else {
2601f29dbc25Smrg                /* WAIT FOR AVAILABLE SPACE */
2602f29dbc25Smrg
2603f29dbc25Smrg                GP3_WAIT_PRIMITIVE(temp);
2604f29dbc25Smrg                WRITE_COMMAND32(0,
260504007ebaSmrg                                GP3_DATA_LOAD_HDR_TYPE |
260604007ebaSmrg                                GP3_DATA_LOAD_HDR_ENABLE);
2607f29dbc25Smrg            }
2608f29dbc25Smrg
2609f29dbc25Smrg            /* WRITE DWORD COUNT */
2610f29dbc25Smrg
2611f29dbc25Smrg            WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
2612f29dbc25Smrg
2613f29dbc25Smrg            /* WRITE DATA */
2614f29dbc25Smrg
2615f29dbc25Smrg            WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count);
2616f29dbc25Smrg            WRITE_COMMAND_STRING8(8 + (dword_count << 2), data,
261704007ebaSmrg                                  srcoffset + (dword_count << 2), byte_count);
2618f29dbc25Smrg
2619f29dbc25Smrg            /* UPDATE POINTERS */
2620f29dbc25Smrg
2621f29dbc25Smrg            srcoffset += stride;
2622f29dbc25Smrg            WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2623f29dbc25Smrg            gp3_cmd_current = gp3_cmd_next;
2624f29dbc25Smrg        }
2625f29dbc25Smrg    }
2626f29dbc25Smrg}
2627f29dbc25Smrg
2628f29dbc25Smrg/*---------------------------------------------------------------------------
2629f29dbc25Smrg * gp_masked_blt
2630f29dbc25Smrg *
2631f29dbc25Smrg * This routine copies source data to the screen.  A monochrome mask is used
2632f29dbc25Smrg * to specify source transparency.
2633f29dbc25Smrg *-------------------------------------------------------------------------*/
2634f29dbc25Smrg
2635f29dbc25Smrgvoid
2636f29dbc25Smrggp_masked_blt(unsigned long dstoffset, unsigned long width,
263704007ebaSmrg              unsigned long height, unsigned long mono_srcx,
263804007ebaSmrg              unsigned long color_srcx, unsigned char *mono_mask,
263904007ebaSmrg              unsigned char *color_data, long mono_pitch, long color_pitch)
2640f29dbc25Smrg{
2641f29dbc25Smrg    unsigned long indent, temp;
2642f29dbc25Smrg    unsigned long total_dwords, size_dwords;
2643f29dbc25Smrg    unsigned long dword_count, byte_count;
2644f29dbc25Smrg    unsigned long srcoffset, size;
2645f29dbc25Smrg    unsigned long i, ch3_offset, base;
2646f29dbc25Smrg    unsigned long flags = 0;
2647f29dbc25Smrg
2648f29dbc25Smrg    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
2649f29dbc25Smrg        flags = GP3_RM_SOURCE_INVERT;
2650f29dbc25Smrg
2651f29dbc25Smrg    /* MONO CALCULATIONS */
2652f29dbc25Smrg
2653f29dbc25Smrg    indent = (mono_srcx >> 3);
2654f29dbc25Smrg    srcoffset = (indent & ~3L);
2655f29dbc25Smrg    indent &= 3;
2656f29dbc25Smrg
2657f29dbc25Smrg    size = ((width + (mono_srcx & 7) + 7) >> 3) + indent;
2658f29dbc25Smrg    total_dwords = (size + 3) >> 2;
2659f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
2660f29dbc25Smrg    dword_count = (size >> 2);
2661f29dbc25Smrg    byte_count = (size & 3);
2662f29dbc25Smrg
2663f29dbc25Smrg    base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) |
2664f29dbc25Smrg        (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
2665f29dbc25Smrg
2666f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
2667f29dbc25Smrg        GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE |
2668f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE | GP3_BLT_HDR_CH3_STR_ENABLE |
2669f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE |
2670f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
2671f29dbc25Smrg
2672f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC);
2673f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2));
2674f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF);
2675f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height);
2676f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height);
2677f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0);
2678f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
2679f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
268004007ebaSmrg                    GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
268104007ebaSmrg                    GP3_CH3_SRC_8_8_8_8 |
268204007ebaSmrg                    ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
2683f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, 0);
2684f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2685f29dbc25Smrg
2686f29dbc25Smrg    /* START THE BLT */
2687f29dbc25Smrg
2688f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2689f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
2690f29dbc25Smrg
2691f29dbc25Smrg    for (i = 0; i < height; i++) {
2692f29dbc25Smrg        /* UPDATE THE COMMAND POINTER
2693f29dbc25Smrg         * The WRITE_COMMANDXX macros use a pointer to the current buffer
2694f29dbc25Smrg         * space.  This is created by adding gp3_cmd_current to the base
2695f29dbc25Smrg         * pointer.
2696f29dbc25Smrg         */
2697f29dbc25Smrg
2698f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2699f29dbc25Smrg
2700f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
2701f29dbc25Smrg
2702f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + size_dwords;
2703f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2704f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
2705f29dbc25Smrg
2706f29dbc25Smrg            /* WAIT FOR HARDWARE */
2707f29dbc25Smrg
2708f29dbc25Smrg            GP3_WAIT_WRAP(temp);
2709f29dbc25Smrg            WRITE_COMMAND32(0,
271004007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
271104007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
271204007ebaSmrg        }
271304007ebaSmrg        else {
2714f29dbc25Smrg            /* WAIT FOR AVAILABLE SPACE */
2715f29dbc25Smrg
2716f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
2717f29dbc25Smrg            WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
271804007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
2719f29dbc25Smrg        }
2720f29dbc25Smrg
2721f29dbc25Smrg        /* WRITE DWORD COUNT */
2722f29dbc25Smrg
2723f29dbc25Smrg        WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
2724f29dbc25Smrg
2725f29dbc25Smrg        /* WRITE DATA */
2726f29dbc25Smrg
2727f29dbc25Smrg        WRITE_COMMAND_STRING32(8, mono_mask, srcoffset, dword_count);
2728f29dbc25Smrg        WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask,
272904007ebaSmrg                              srcoffset + (dword_count << 2), byte_count);
2730f29dbc25Smrg
2731f29dbc25Smrg        /* UPDATE POINTERS */
2732f29dbc25Smrg
2733f29dbc25Smrg        srcoffset += mono_pitch;
2734f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2735f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
2736f29dbc25Smrg    }
2737f29dbc25Smrg
2738f29dbc25Smrg    /* SECOND BLT */
2739f29dbc25Smrg
2740f29dbc25Smrg    gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD);
2741f29dbc25Smrg
2742f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
2743f29dbc25Smrg        ((gp3_fb_base << 14) + (((gp3_scratch_base +
274404007ebaSmrg                                  indent) & 0xFFC00000) >> 10)) |
274504007ebaSmrg        (gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
2746f29dbc25Smrg
2747f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
2748f29dbc25Smrg        GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE |
2749f29dbc25Smrg        GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE |
2750f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
2751f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
2752f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE |
2753f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
2754f29dbc25Smrg
2755f29dbc25Smrg    /* ENABLE TRANSPARENCY AND PATTERN COPY ROP
2756f29dbc25Smrg     * The monochrome data is used as a mask but is otherwise not involved in
2757f29dbc25Smrg     * the BLT.  The color data is routed through the pattern channel.
2758f29dbc25Smrg     */
2759f29dbc25Smrg
2760f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
276104007ebaSmrg                    gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags);
2762f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride);
2763f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
2764f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
276504007ebaSmrg                    ((gp3_scratch_base +
276604007ebaSmrg                      indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26));
2767f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height);
2768f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height);
2769f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
2770f29dbc25Smrg
2771f29dbc25Smrg    /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA        */
2772f29dbc25Smrg    /* Data may be color converted along the way.      */
2773f29dbc25Smrg
2774f29dbc25Smrg    if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) {
2775f29dbc25Smrg        srcoffset = color_srcx * 3;
2776f29dbc25Smrg        ch3_offset = 0;
2777f29dbc25Smrg        size = width * 3;
2778f29dbc25Smrg
277904007ebaSmrg        WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (((size + 3) >> 2) << 16) | height);
278004007ebaSmrg    }
278104007ebaSmrg    else if (gp3_src_pix_shift == 3) {
2782f29dbc25Smrg        /* CALCULATE INDENT AND SOURCE OFFSET */
2783f29dbc25Smrg
2784f29dbc25Smrg        indent = (color_srcx >> 1);
2785f29dbc25Smrg        srcoffset = (indent & ~3L);
2786f29dbc25Smrg        indent &= 3;
2787f29dbc25Smrg        ch3_offset = indent | ((color_srcx & 1) << 25);
2788f29dbc25Smrg
2789f29dbc25Smrg        size = ((width + (color_srcx & 1) + 1) >> 1) + indent;
279004007ebaSmrg    }
279104007ebaSmrg    else {
2792f29dbc25Smrg        indent = (color_srcx << gp3_src_pix_shift);
2793f29dbc25Smrg        srcoffset = (indent & ~3L);
2794f29dbc25Smrg        indent &= 3;
2795f29dbc25Smrg        ch3_offset = indent;
2796f29dbc25Smrg
2797f29dbc25Smrg        size = (width << gp3_src_pix_shift) + indent;
2798f29dbc25Smrg    }
2799f29dbc25Smrg
2800f29dbc25Smrg    total_dwords = (size + 3) >> 2;
2801f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
2802f29dbc25Smrg    dword_count = (size >> 2);
2803f29dbc25Smrg    byte_count = (size & 3);
2804f29dbc25Smrg
2805f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset);
2806f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
280704007ebaSmrg                    GP3_CH3_HST_SRC_ENABLE |
280804007ebaSmrg                    gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
280904007ebaSmrg                                      << 20));
2810f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE,
281104007ebaSmrg                    gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB);
2812f29dbc25Smrg
2813f29dbc25Smrg    /* START THE BLT */
2814f29dbc25Smrg
2815f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2816f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2817f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
2818f29dbc25Smrg
2819f29dbc25Smrg    /* WRITE DATA LINE BY LINE */
2820f29dbc25Smrg
2821f29dbc25Smrg    while (height--) {
2822f29dbc25Smrg        /* UPDATE THE COMMAND POINTER */
2823f29dbc25Smrg
2824f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2825f29dbc25Smrg
2826f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
2827f29dbc25Smrg
2828f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + size_dwords;
2829f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2830f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
2831f29dbc25Smrg
2832f29dbc25Smrg            GP3_WAIT_WRAP(temp);
2833f29dbc25Smrg            WRITE_COMMAND32(0,
283404007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
283504007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
283604007ebaSmrg        }
283704007ebaSmrg        else {
2838f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
2839f29dbc25Smrg            WRITE_COMMAND32(0,
284004007ebaSmrg                            GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
2841f29dbc25Smrg        }
2842f29dbc25Smrg
2843f29dbc25Smrg        /* WRITE DWORD COUNT */
2844f29dbc25Smrg
2845f29dbc25Smrg        WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
2846f29dbc25Smrg
2847f29dbc25Smrg        /* WRITE COLOR DATA TO THE COMMAND BUFFER */
2848f29dbc25Smrg
2849f29dbc25Smrg        WRITE_COMMAND_STRING32(8, color_data, srcoffset, dword_count);
2850f29dbc25Smrg        WRITE_COMMAND_STRING8(8 + (dword_count << 2), color_data,
285104007ebaSmrg                              srcoffset + (dword_count << 2), byte_count);
2852f29dbc25Smrg
2853f29dbc25Smrg        /* UPDATE COMMAND BUFFER POINTERS */
2854f29dbc25Smrg        /* We do this before writing the monochrome data because otherwise */
2855f29dbc25Smrg        /* the GP could throttle the writes to the host source register    */
2856f29dbc25Smrg        /* waiting for color data.  If the command buffer has not been     */
2857f29dbc25Smrg        /* updated to load the color data...                               */
2858f29dbc25Smrg
2859f29dbc25Smrg        srcoffset += color_pitch;
2860f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2861f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
2862f29dbc25Smrg    }
2863f29dbc25Smrg}
2864f29dbc25Smrg
2865f29dbc25Smrg/*---------------------------------------------------------------------------
2866f29dbc25Smrg * gp_screen_to_screen_masked
2867f29dbc25Smrg *
2868f29dbc25Smrg * This routine performs a screen to screen BLT, using a monochrome mask to
2869f29dbc25Smrg * specify source transparency.  The source data is assumed to be in the
2870f29dbc25Smrg * current destination format and to not overlap the destination.
2871f29dbc25Smrg *-------------------------------------------------------------------------*/
2872f29dbc25Smrg
2873f29dbc25Smrgvoid
2874f29dbc25Smrggp_screen_to_screen_masked(unsigned long dstoffset, unsigned long srcoffset,
287504007ebaSmrg                           unsigned long width, unsigned long height,
287604007ebaSmrg                           unsigned long mono_srcx, unsigned char *mono_mask,
287704007ebaSmrg                           long mono_pitch)
2878f29dbc25Smrg{
2879f29dbc25Smrg    unsigned long indent, temp;
2880f29dbc25Smrg    unsigned long total_dwords, size_dwords;
2881f29dbc25Smrg    unsigned long dword_count, byte_count;
2882f29dbc25Smrg    unsigned long srcoff, size;
2883f29dbc25Smrg    unsigned long i, base;
2884f29dbc25Smrg    unsigned long flags = 0;
2885f29dbc25Smrg
2886f29dbc25Smrg    if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO)
2887f29dbc25Smrg        flags = GP3_RM_SOURCE_INVERT;
2888f29dbc25Smrg
2889f29dbc25Smrg    /* MONO CALCULATIONS */
2890f29dbc25Smrg
2891f29dbc25Smrg    indent = (mono_srcx >> 3);
2892f29dbc25Smrg    srcoff = (indent & ~3L);
2893f29dbc25Smrg    indent &= 3;
2894f29dbc25Smrg
2895f29dbc25Smrg    size = ((width + (mono_srcx & 7) + 7) >> 3) + indent;
2896f29dbc25Smrg    total_dwords = (size + 3) >> 2;
2897f29dbc25Smrg    size_dwords = (total_dwords << 2) + 8;
2898f29dbc25Smrg    dword_count = (size >> 2);
2899f29dbc25Smrg    byte_count = (size & 3);
2900f29dbc25Smrg
2901f29dbc25Smrg    base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) |
2902f29dbc25Smrg        (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
2903f29dbc25Smrg
2904f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_STRIDE_ENABLE |
2905f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE |
2906f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE | GP3_BLT_HDR_CH3_OFF_ENABLE |
2907f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
2908f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
2909f29dbc25Smrg
2910f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC);
2911f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2));
2912f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF);
2913f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height);
2914f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height);
2915f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0);
2916f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
2917f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN |
291804007ebaSmrg                    GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE |
291904007ebaSmrg                    GP3_CH3_SRC_8_8_8_8 |
292004007ebaSmrg                    ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
2921f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, 0);
2922f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
2923f29dbc25Smrg
2924f29dbc25Smrg    /* START THE BLT */
2925f29dbc25Smrg
2926f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2927f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
2928f29dbc25Smrg
2929f29dbc25Smrg    for (i = 0; i < height; i++) {
2930f29dbc25Smrg        /* UPDATE THE COMMAND POINTER
2931f29dbc25Smrg         * The WRITE_COMMANDXX macros use a pointer to the current buffer
2932f29dbc25Smrg         * space. This is created by adding gp3_cmd_current to the base
2933f29dbc25Smrg         * pointer.
2934f29dbc25Smrg         */
2935f29dbc25Smrg
2936f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
2937f29dbc25Smrg
2938f29dbc25Smrg        /* CHECK IF A WRAP WILL BE NEEDED */
2939f29dbc25Smrg
2940f29dbc25Smrg        gp3_cmd_next = gp3_cmd_current + size_dwords;
2941f29dbc25Smrg        if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) {
2942f29dbc25Smrg            gp3_cmd_next = gp3_cmd_top;
2943f29dbc25Smrg
2944f29dbc25Smrg            /* WAIT FOR HARDWARE */
2945f29dbc25Smrg
2946f29dbc25Smrg            GP3_WAIT_WRAP(temp);
2947f29dbc25Smrg            WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
294804007ebaSmrg                            GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE);
294904007ebaSmrg        }
295004007ebaSmrg        else {
2951f29dbc25Smrg            /* WAIT FOR AVAILABLE SPACE */
2952f29dbc25Smrg
2953f29dbc25Smrg            GP3_WAIT_PRIMITIVE(temp);
2954f29dbc25Smrg            WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE |
295504007ebaSmrg                            GP3_DATA_LOAD_HDR_ENABLE);
2956f29dbc25Smrg        }
2957f29dbc25Smrg
2958f29dbc25Smrg        /* WRITE DWORD COUNT */
2959f29dbc25Smrg
2960f29dbc25Smrg        WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
2961f29dbc25Smrg
2962f29dbc25Smrg        /* WRITE DATA */
2963f29dbc25Smrg
2964f29dbc25Smrg        WRITE_COMMAND_STRING32(8, mono_mask, srcoff, dword_count);
2965f29dbc25Smrg        WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask,
296604007ebaSmrg                              srcoff + (dword_count << 2), byte_count);
2967f29dbc25Smrg
2968f29dbc25Smrg        /* UPDATE POINTERS */
2969f29dbc25Smrg
2970f29dbc25Smrg        srcoff += mono_pitch;
2971f29dbc25Smrg        WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
2972f29dbc25Smrg        gp3_cmd_current = gp3_cmd_next;
2973f29dbc25Smrg    }
2974f29dbc25Smrg
2975f29dbc25Smrg    /* SECOND BLT */
2976f29dbc25Smrg
2977f29dbc25Smrg    gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD);
2978f29dbc25Smrg
2979f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
2980f29dbc25Smrg        ((gp3_fb_base << 14) + (((gp3_scratch_base +
298104007ebaSmrg                                  indent) & 0xFFC00000) >> 10)) | ((gp3_fb_base
298204007ebaSmrg                                                                    << 4) +
298304007ebaSmrg                                                                   ((srcoffset &
298404007ebaSmrg                                                                     0xFFC00000)
298504007ebaSmrg                                                                    >> 20));
2986f29dbc25Smrg
2987f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
2988f29dbc25Smrg        GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE |
2989f29dbc25Smrg        GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE |
2990f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
2991f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
2992f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE |
2993f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
2994f29dbc25Smrg
2995f29dbc25Smrg    /* ENABLE TRANSPARENCY AND PATTERN COPY ROP
2996f29dbc25Smrg     * The monochrome data is used as a mask but is otherwise not involved
2997f29dbc25Smrg     * in the BLT.  The color data is routed through the pattern channel.
2998f29dbc25Smrg     */
2999f29dbc25Smrg
3000f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
300104007ebaSmrg                    gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags);
3002f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride);
3003f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
3004f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_SRC_OFFSET,
300504007ebaSmrg                    ((gp3_scratch_base +
300604007ebaSmrg                      indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26));
3007f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height);
3008f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height);
3009f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
3010f29dbc25Smrg
3011f29dbc25Smrg    /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA  */
3012f29dbc25Smrg
3013f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset & 0x3FFFFF);
3014f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | gp3_ch3_bpp |
301504007ebaSmrg                    gp3_src_stride | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT)
301604007ebaSmrg                                      << 20));
3017f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE,
301804007ebaSmrg                    gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB);
3019f29dbc25Smrg
3020f29dbc25Smrg    /* START THE BLT */
3021f29dbc25Smrg
3022f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
3023f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
3024f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
3025f29dbc25Smrg}
3026f29dbc25Smrg
3027f29dbc25Smrg/*---------------------------------------------------------------------------
3028f29dbc25Smrg * gp_bresenham_line
3029f29dbc25Smrg *
3030f29dbc25Smrg * This routine draws a vector using the specified Bresenham parameters.
3031f29dbc25Smrg * Currently this file does not support a routine that accepts the two
3032f29dbc25Smrg * endpoints of a vector and calculates the Bresenham parameters.  If it
3033f29dbc25Smrg * ever does, this routine is still required for vectors that have been
3034f29dbc25Smrg * clipped.
3035f29dbc25Smrg *-------------------------------------------------------------------------*/
3036f29dbc25Smrg
3037f29dbc25Smrgvoid
3038f29dbc25Smrggp_bresenham_line(unsigned long dstoffset, unsigned short length,
303904007ebaSmrg                  unsigned short initerr, unsigned short axialerr,
304004007ebaSmrg                  unsigned short diagerr, unsigned long flags)
3041f29dbc25Smrg{
3042f29dbc25Smrg    unsigned long base;
3043f29dbc25Smrg    long offset;
3044f29dbc25Smrg
3045f29dbc25Smrg    /* HANDLE NEGATIVE VECTORS */
3046f29dbc25Smrg    /* We have to be very careful with vectors that increment negatively   */
3047f29dbc25Smrg    /* Our framebuffer scheme tries to align the destination of every      */
3048f29dbc25Smrg    /* BLT or vector to the nearest 4MB-aligned boundary.  This is         */
3049f29dbc25Smrg    /* necessary because the GP only supports offsets up to 16MB, but the  */
3050f29dbc25Smrg    /* framebuffer can be over 128MB.  To solve this problem, the GP       */
3051f29dbc25Smrg    /* base address registers are alignable to 4MB regions.  However, we   */
3052f29dbc25Smrg    /* cannot simply align the dest offset when the vector goes negative.  */
3053f29dbc25Smrg    /* The vector offset could underflow, causing the offset to jump from  */
3054f29dbc25Smrg    /* near 0 to 16MB.  As we cannot accurately determine the last address */
3055f29dbc25Smrg    /* that will be written in a vector short of walking the algorithm in  */
3056f29dbc25Smrg    /* software, we do a worst case approximation.                         */
3057f29dbc25Smrg
3058f29dbc25Smrg    offset = dstoffset;
3059f29dbc25Smrg    if (!(flags & CIMGP_POSMAJOR)) {
3060f29dbc25Smrg        if (flags & CIMGP_YMAJOR)
3061f29dbc25Smrg            offset -= length * gp3_dst_stride;
3062f29dbc25Smrg        else
3063f29dbc25Smrg            offset -= (length << gp3_pix_shift);
3064f29dbc25Smrg
3065f29dbc25Smrg        if (offset < 0)
3066f29dbc25Smrg            offset = 0;
3067f29dbc25Smrg    }
3068f29dbc25Smrg    if (!(flags & CIMGP_POSMINOR)) {
3069f29dbc25Smrg        if (flags & CIMGP_YMAJOR)
3070f29dbc25Smrg            offset -= (length << gp3_pix_shift);
3071f29dbc25Smrg        else
3072f29dbc25Smrg            offset -= length * gp3_dst_stride;
3073f29dbc25Smrg
3074f29dbc25Smrg        if (offset < 0)
3075f29dbc25Smrg            offset = 0;
3076f29dbc25Smrg    }
3077f29dbc25Smrg
3078f29dbc25Smrg    offset &= 0xFFC00000;
3079f29dbc25Smrg    dstoffset -= offset;
3080f29dbc25Smrg
3081f29dbc25Smrg    base = ((gp3_fb_base << 24) + offset) |
3082f29dbc25Smrg        (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
3083f29dbc25Smrg
3084f29dbc25Smrg    /* ENABLE RELEVANT REGISTERS */
3085f29dbc25Smrg    /* Note that we always enable and write the channel 3 mode, if only */
3086f29dbc25Smrg    /* to turn it off.   Cimarron also always writes the base offset    */
3087f29dbc25Smrg    /* register to allow operation with frame buffers larger than 16MB. */
3088f29dbc25Smrg
3089f29dbc25Smrg    gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE |
3090f29dbc25Smrg        GP3_VEC_HDR_VEC_ERR_ENABLE |
3091f29dbc25Smrg        GP3_VEC_HDR_VEC_LEN_ENABLE |
3092f29dbc25Smrg        GP3_VEC_HDR_BASE_OFFSET_ENABLE |
3093f29dbc25Smrg        GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE;
3094f29dbc25Smrg
3095f29dbc25Smrg    /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
3096f29dbc25Smrg    /* The destination base is the frame buffer base plus whatever */
3097f29dbc25Smrg    /* 4MB segment we happen to be drawing to.                     */
3098f29dbc25Smrg
3099f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_VEC_ERR,
310004007ebaSmrg                    (((unsigned long) axialerr << 16) | (unsigned long)
310104007ebaSmrg                     diagerr));
3102f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_VEC_LEN,
310304007ebaSmrg                    (((unsigned long) length << 16) | (unsigned long) initerr));
3104f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base);
3105f29dbc25Smrg
3106f29dbc25Smrg    /* CHECK VECTOR PATTERN CASE */
3107f29dbc25Smrg
3108f29dbc25Smrg    if (gp3_ch3_pat) {
3109f29dbc25Smrg        /* SET THE SOLID COLOR */
3110f29dbc25Smrg        /* The color for vector patterns from channel 3 comes from */
3111f29dbc25Smrg        /* the regular pattern registers.                          */
3112f29dbc25Smrg
3113f29dbc25Smrg        gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
3114f29dbc25Smrg
3115f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color);
3116f29dbc25Smrg
3117f29dbc25Smrg        /* INITIALIZE CHANNEL 3 PARAMETERS
3118f29dbc25Smrg         * We route the channel 3 output to the old source channel.  If the
3119f29dbc25Smrg         * user sets a ROP that involves source, they will get unexpected
3120f29dbc25Smrg         * results.
3121f29dbc25Smrg         */
3122f29dbc25Smrg
3123f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset);
3124f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR,
312504007ebaSmrg                        GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
312604007ebaSmrg                        GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8);
312704007ebaSmrg    }
312804007ebaSmrg    else {
3129f29dbc25Smrg        /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
3130f29dbc25Smrg
3131f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0);
3132f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin));
3133f29dbc25Smrg    }
3134f29dbc25Smrg
3135f29dbc25Smrg    /* START THE VECTOR */
3136f29dbc25Smrg
3137f29dbc25Smrg    WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header);
3138f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags));
3139f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
3140f29dbc25Smrg
3141f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
3142f29dbc25Smrg
3143f29dbc25Smrg    /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES            */
3144f29dbc25Smrg    /* We set a transparent pattern to clear the byte enables.  */
3145f29dbc25Smrg    /* We then restore the previous pattern. (SiBZ #4001)       */
3146f29dbc25Smrg
3147f29dbc25Smrg    if (gp3_ch3_pat) {
3148f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
3149f29dbc25Smrg
3150f29dbc25Smrg        WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
3151f29dbc25Smrg        WRITE_COMMAND32(4, 0x100);
3152f29dbc25Smrg        WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE));
3153f29dbc25Smrg        WRITE_COMMAND32(12, 0);
3154f29dbc25Smrg
3155f29dbc25Smrg        /* DUMMY VECTOR */
3156f29dbc25Smrg        /* We shouldn't need to write anything but vector mode and the length
3157f29dbc25Smrg         */
3158f29dbc25Smrg
3159f29dbc25Smrg        WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE |
316004007ebaSmrg                        GP3_VEC_HDR_VEC_LEN_ENABLE);
3161f29dbc25Smrg        WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags));
3162f29dbc25Smrg        WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN,
316304007ebaSmrg                        (1 << 16) | (unsigned long) initerr);
3164f29dbc25Smrg
3165f29dbc25Smrg        WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE,
316604007ebaSmrg                        GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
3167f29dbc25Smrg        WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100);
316804007ebaSmrg        WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE));
3169f29dbc25Smrg        WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat);
3170f29dbc25Smrg
3171f29dbc25Smrg        gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE;
3172f29dbc25Smrg    }
3173f29dbc25Smrg}
3174f29dbc25Smrg
3175f29dbc25Smrg/*---------------------------------------------------------------------------
3176f29dbc25Smrg * gp_line_from_endpoints
3177f29dbc25Smrg *
3178f29dbc25Smrg * This routine draws a vector from a set of rectangular coordinates.  The
3179f29dbc25Smrg * rectangle is assumed to use the currently specified destination stride.
3180f29dbc25Smrg *-------------------------------------------------------------------------*/
3181f29dbc25Smrg
3182f29dbc25Smrgvoid
3183f29dbc25Smrggp_line_from_endpoints(unsigned long dstoffset, unsigned long x0,
318404007ebaSmrg                       unsigned long y0, unsigned long x1, unsigned long y1,
318504007ebaSmrg                       int inclusive)
3186f29dbc25Smrg{
3187f29dbc25Smrg    unsigned long base;
3188f29dbc25Smrg    unsigned long length;
3189f29dbc25Smrg    unsigned long flags;
3190f29dbc25Smrg    unsigned short initerr, axialerr, diagerr;
3191f29dbc25Smrg    long dx, dy, dmaj, dmin;
3192f29dbc25Smrg    long offset;
3193f29dbc25Smrg
3194f29dbc25Smrg    /* ADJUST DESTINATION OFFSET BASED ON STARTING COORDINATE */
3195f29dbc25Smrg
3196f29dbc25Smrg    dstoffset += (x0 << gp3_pix_shift) + (y0 * gp3_dst_stride);
3197f29dbc25Smrg
3198f29dbc25Smrg    /* CALCULATE BRESENHAM TERMS */
3199f29dbc25Smrg
320004007ebaSmrg    dx = (long) x1 - (long) x0;
320104007ebaSmrg    dy = (long) y1 - (long) y0;
3202f29dbc25Smrg    if (dx < 0)
3203f29dbc25Smrg        dx = -dx;
3204f29dbc25Smrg    if (dy < 0)
3205f29dbc25Smrg        dy = -dy;
3206f29dbc25Smrg
3207f29dbc25Smrg    if (dx >= dy) {
3208f29dbc25Smrg        dmaj = dx;
3209f29dbc25Smrg        dmin = dy;
3210f29dbc25Smrg        flags = 0;
3211f29dbc25Smrg        if (x1 > x0)
3212f29dbc25Smrg            flags |= CIMGP_POSMAJOR;
3213f29dbc25Smrg        if (y1 > y0)
3214f29dbc25Smrg            flags |= CIMGP_POSMINOR;
321504007ebaSmrg    }
321604007ebaSmrg    else {
3217f29dbc25Smrg        dmaj = dy;
3218f29dbc25Smrg        dmin = dx;
3219f29dbc25Smrg        flags = CIMGP_YMAJOR;
3220f29dbc25Smrg        if (x1 > x0)
3221f29dbc25Smrg            flags |= CIMGP_POSMINOR;
3222f29dbc25Smrg        if (y1 > y0)
3223f29dbc25Smrg            flags |= CIMGP_POSMAJOR;
3224f29dbc25Smrg    }
3225f29dbc25Smrg
322604007ebaSmrg    axialerr = (unsigned short) (dmin << 1);
322704007ebaSmrg    diagerr = (unsigned short) ((dmin - dmaj) << 1);
322804007ebaSmrg    initerr = (unsigned short) ((dmin << 1) - dmaj);
3229f29dbc25Smrg    if (!(flags & CIMGP_POSMINOR))
3230f29dbc25Smrg        initerr--;
3231f29dbc25Smrg
3232f29dbc25Smrg    /* CHECK FOR NO WORK */
3233f29dbc25Smrg
3234f29dbc25Smrg    if (!dmaj)
3235f29dbc25Smrg        return;
3236f29dbc25Smrg
3237f29dbc25Smrg    /* CHECK INCLUSIVE OR EXCLUSIVE */
3238f29dbc25Smrg    /* An inclusive line can be accomplished by simply adding 1 to the */
3239f29dbc25Smrg    /* line length.                                                    */
3240f29dbc25Smrg
3241f29dbc25Smrg    length = dmaj;
3242f29dbc25Smrg    if (inclusive)
3243f29dbc25Smrg        length++;
3244f29dbc25Smrg
3245f29dbc25Smrg    /* HANDLE NEGATIVE VECTORS */
3246f29dbc25Smrg
3247f29dbc25Smrg    offset = dstoffset;
3248f29dbc25Smrg    if (!(flags & CIMGP_POSMAJOR)) {
3249f29dbc25Smrg        if (flags & CIMGP_YMAJOR)
3250f29dbc25Smrg            offset -= length * gp3_dst_stride;
3251f29dbc25Smrg        else
3252f29dbc25Smrg            offset -= (length << gp3_pix_shift);
3253f29dbc25Smrg
3254f29dbc25Smrg        if (offset < 0)
3255f29dbc25Smrg            offset = 0;
3256f29dbc25Smrg    }
3257f29dbc25Smrg    if (!(flags & CIMGP_POSMINOR)) {
3258f29dbc25Smrg        if (flags & CIMGP_YMAJOR)
3259f29dbc25Smrg            offset -= (length << gp3_pix_shift);
3260f29dbc25Smrg        else
3261f29dbc25Smrg            offset -= length * gp3_dst_stride;
3262f29dbc25Smrg
3263f29dbc25Smrg        if (offset < 0)
3264f29dbc25Smrg            offset = 0;
3265f29dbc25Smrg    }
3266f29dbc25Smrg
3267f29dbc25Smrg    offset &= 0xFFC00000;
3268f29dbc25Smrg    dstoffset -= offset;
3269f29dbc25Smrg
3270f29dbc25Smrg    base = ((gp3_fb_base << 24) + offset) |
3271f29dbc25Smrg        (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
3272f29dbc25Smrg
3273f29dbc25Smrg    /* ENABLE RELEVANT REGISTERS */
3274f29dbc25Smrg    /* Note that we always enable and write the channel 3 mode, if only */
3275f29dbc25Smrg    /* to turn it off.   Cimarron also always writes the base offset    */
3276f29dbc25Smrg    /* register to allow operation with frame buffers larger than 16MB. */
3277f29dbc25Smrg
3278f29dbc25Smrg    gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE |
3279f29dbc25Smrg        GP3_VEC_HDR_VEC_ERR_ENABLE |
3280f29dbc25Smrg        GP3_VEC_HDR_VEC_LEN_ENABLE |
3281f29dbc25Smrg        GP3_VEC_HDR_BASE_OFFSET_ENABLE |
3282f29dbc25Smrg        GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE;
3283f29dbc25Smrg
3284f29dbc25Smrg    /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
3285f29dbc25Smrg    /* The destination base is the frame buffer base plus whatever */
3286f29dbc25Smrg    /* 4MB segment we happen to be drawing to.                     */
3287f29dbc25Smrg
3288f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_VEC_ERR,
328904007ebaSmrg                    (((unsigned long) axialerr << 16) | (unsigned long)
329004007ebaSmrg                     diagerr));
3291f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_VEC_LEN,
329204007ebaSmrg                    (((unsigned long) length << 16) | (unsigned long) initerr));
3293f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base);
3294f29dbc25Smrg
3295f29dbc25Smrg    /* CHECK VECTOR PATTERN CASE */
3296f29dbc25Smrg
3297f29dbc25Smrg    if (gp3_ch3_pat) {
3298f29dbc25Smrg        /* SET THE SOLID COLOR */
3299f29dbc25Smrg        /* The color for vector patterns from channel 3 comes from */
3300f29dbc25Smrg        /* the regular pattern registers.                          */
3301f29dbc25Smrg
3302f29dbc25Smrg        gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE;
3303f29dbc25Smrg
3304f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color);
3305f29dbc25Smrg
3306f29dbc25Smrg        /* INITIALIZE CHANNEL 3 PARAMETERS */
3307f29dbc25Smrg        /* We route the channel 3 output to the old source channel.  If the
3308f29dbc25Smrg         * user sets a ROP that involves source, they will get unexpected
3309f29dbc25Smrg         * results.
3310f29dbc25Smrg         */
3311f29dbc25Smrg
3312f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset);
3313f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR,
331404007ebaSmrg                        GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE |
331504007ebaSmrg                        GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8);
331604007ebaSmrg    }
331704007ebaSmrg    else {
3318f29dbc25Smrg        /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
3319f29dbc25Smrg
3320f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0);
3321f29dbc25Smrg        WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin));
3322f29dbc25Smrg    }
3323f29dbc25Smrg
3324f29dbc25Smrg    /* START THE VECTOR */
3325f29dbc25Smrg
3326f29dbc25Smrg    WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header);
3327f29dbc25Smrg    WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags));
3328f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
3329f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
3330f29dbc25Smrg
3331f29dbc25Smrg    /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES            */
3332f29dbc25Smrg    /* We set a transparent pattern to clear the byte enables.  */
3333f29dbc25Smrg    /* We then restore the previous pattern.  (SiBZ #4001)      */
3334f29dbc25Smrg
3335f29dbc25Smrg    if (gp3_ch3_pat) {
3336f29dbc25Smrg        cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
3337f29dbc25Smrg
3338f29dbc25Smrg        WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
3339f29dbc25Smrg        WRITE_COMMAND32(4, 0x100);
3340f29dbc25Smrg        WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE));
3341f29dbc25Smrg        WRITE_COMMAND32(12, 0);
3342f29dbc25Smrg
3343f29dbc25Smrg        /* DUMMY VECTOR */
3344f29dbc25Smrg        /* We shouldn't need to write anything but vector mode and the length
3345f29dbc25Smrg         */
3346f29dbc25Smrg
3347f29dbc25Smrg        WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE |
334804007ebaSmrg                        GP3_VEC_HDR_VEC_LEN_ENABLE);
3349f29dbc25Smrg        WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags));
3350f29dbc25Smrg        WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN,
335104007ebaSmrg                        (1 << 16) | (unsigned long) initerr);
3352f29dbc25Smrg
3353f29dbc25Smrg        WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE,
335404007ebaSmrg                        GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE);
3355f29dbc25Smrg        WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100);
335604007ebaSmrg        WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, (1 | GP3_LUT_DATA_TYPE));
3357f29dbc25Smrg        WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat);
3358f29dbc25Smrg
3359f29dbc25Smrg        gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE;
3360f29dbc25Smrg    }
3361f29dbc25Smrg}
3362f29dbc25Smrg
3363f29dbc25Smrg/*---------------------------------------------------------------------------
3364f29dbc25Smrg * gp_wait_until_idle
3365f29dbc25Smrg *
3366f29dbc25Smrg * This routine stalls execution until the GP is no longer actively rendering.
3367f29dbc25Smrg *-------------------------------------------------------------------------*/
3368f29dbc25Smrg
3369f29dbc25Smrgvoid
3370f29dbc25Smrggp_wait_until_idle(void)
3371f29dbc25Smrg{
3372f29dbc25Smrg    unsigned long temp;
3373f29dbc25Smrg
3374f29dbc25Smrg    while (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||
337504007ebaSmrg           !(temp & GP3_BS_CB_EMPTY)) {
3376f29dbc25Smrg        ;
3377f29dbc25Smrg    }
3378f29dbc25Smrg}
3379f29dbc25Smrg
3380f29dbc25Smrg/*---------------------------------------------------------------------------
3381f29dbc25Smrg * gp_test_blt_busy
3382f29dbc25Smrg *-------------------------------------------------------------------------*/
3383f29dbc25Smrg
3384f29dbc25Smrgint
3385f29dbc25Smrggp_test_blt_busy(void)
3386f29dbc25Smrg{
3387f29dbc25Smrg    unsigned long temp;
3388f29dbc25Smrg
3389f29dbc25Smrg    if (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) ||
3390f29dbc25Smrg        !(temp & GP3_BS_CB_EMPTY))
3391f29dbc25Smrg        return 1;
3392f29dbc25Smrg
3393f29dbc25Smrg    return 0;
3394f29dbc25Smrg}
3395f29dbc25Smrg
3396f29dbc25Smrg/*---------------------------------------------------------------------------
3397f29dbc25Smrg * gp_test_blt_pending
3398f29dbc25Smrg *-------------------------------------------------------------------------*/
3399f29dbc25Smrg
3400f29dbc25Smrgint
3401f29dbc25Smrggp_test_blt_pending(void)
3402f29dbc25Smrg{
3403f29dbc25Smrg    if ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING)
3404f29dbc25Smrg        return 1;
3405f29dbc25Smrg
3406f29dbc25Smrg    return 0;
3407f29dbc25Smrg}
3408f29dbc25Smrg
3409f29dbc25Smrg/*---------------------------------------------------------------------------
3410f29dbc25Smrg * gp_wait_blt_pending
3411f29dbc25Smrg *-------------------------------------------------------------------------*/
3412f29dbc25Smrg
3413f29dbc25Smrgvoid
3414f29dbc25Smrggp_wait_blt_pending(void)
3415f29dbc25Smrg{
341604007ebaSmrg    while ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING);
3417f29dbc25Smrg}
3418f29dbc25Smrg
3419f29dbc25Smrg/*---------------------------------------------------------------------------
3420f29dbc25Smrg * gp_save_state
3421f29dbc25Smrg *
3422f29dbc25Smrg * This routine saves all persistent GP information.
3423f29dbc25Smrg *-------------------------------------------------------------------------*/
3424f29dbc25Smrg
3425f29dbc25Smrgvoid
3426f29dbc25Smrggp_save_state(GP_SAVE_RESTORE * gp_state)
3427f29dbc25Smrg{
3428f29dbc25Smrg    Q_WORD msr_value;
3429f29dbc25Smrg
3430f29dbc25Smrg    gp_wait_until_idle();
3431f29dbc25Smrg
3432f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
3433f29dbc25Smrg    gp_state->cmd_bottom = READ_GP32(GP3_CMD_BOT) & 0xFFFFFF;
3434f29dbc25Smrg    gp_state->cmd_top = READ_GP32(GP3_CMD_TOP) & 0xFFFFFF;
3435f29dbc25Smrg    gp_state->cmd_base = (msr_value.low << 4) & 0xFFF00000;
3436f29dbc25Smrg    gp_state->base_offset = READ_GP32(GP3_BASE_OFFSET);
3437f29dbc25Smrg
3438f29dbc25Smrg    /* RESET THE READ POINTER */
3439f29dbc25Smrg
3440f29dbc25Smrg    gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top,
344104007ebaSmrg                               gp_state->cmd_bottom);
3442f29dbc25Smrg}
3443f29dbc25Smrg
3444f29dbc25Smrg/*---------------------------------------------------------------------------
3445f29dbc25Smrg * gp_restore_state
3446f29dbc25Smrg *
3447f29dbc25Smrg * This routine restores all persistent GP information.
3448f29dbc25Smrg *-------------------------------------------------------------------------*/
3449f29dbc25Smrg
3450f29dbc25Smrgvoid
3451f29dbc25Smrggp_restore_state(GP_SAVE_RESTORE * gp_state)
3452f29dbc25Smrg{
3453f29dbc25Smrg    gp_wait_until_idle();
3454f29dbc25Smrg
3455f29dbc25Smrg    WRITE_GP32(GP3_BASE_OFFSET, gp_state->base_offset);
3456f29dbc25Smrg
3457f29dbc25Smrg    gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top,
345804007ebaSmrg                               gp_state->cmd_bottom);
3459f29dbc25Smrg}
3460f29dbc25Smrg
3461f29dbc25Smrg/* This is identical to gp_antialiased_text, except we support all one
3462f29dbc25Smrg   pass alpha operations similar to gp_set_alpha_operation */
3463f29dbc25Smrg
3464f29dbc25Smrgvoid
3465f29dbc25Smrggp_blend_mask_blt(unsigned long dstoffset, unsigned long srcx,
346604007ebaSmrg                  unsigned long width, unsigned long height,
346704007ebaSmrg                  unsigned long dataoffset, long stride, int operation,
346804007ebaSmrg                  int fourbpp)
3469f29dbc25Smrg{
3470f29dbc25Smrg    unsigned long indent;
3471f29dbc25Smrg    unsigned long size = ((width << 16) | height);
3472f29dbc25Smrg    unsigned long base, depth_flag;
3473f29dbc25Smrg
3474f29dbc25Smrg    base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
347504007ebaSmrg        ((gp3_fb_base << 4) + (dataoffset >> 20)) |
347604007ebaSmrg        (gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
3477f29dbc25Smrg
3478f29dbc25Smrg    /* ENABLE ALL RELEVANT REGISTERS */
3479f29dbc25Smrg    /* We override the raster mode register to force the */
3480f29dbc25Smrg    /* correct alpha blend                               */
3481f29dbc25Smrg
3482f29dbc25Smrg    gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
3483f29dbc25Smrg        GP3_BLT_HDR_DST_OFF_ENABLE |
3484f29dbc25Smrg        GP3_BLT_HDR_WIDHI_ENABLE |
3485f29dbc25Smrg        GP3_BLT_HDR_CH3_OFF_ENABLE |
3486f29dbc25Smrg        GP3_BLT_HDR_CH3_STR_ENABLE |
3487f29dbc25Smrg        GP3_BLT_HDR_CH3_WIDHI_ENABLE |
3488f29dbc25Smrg        GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE;
3489f29dbc25Smrg
3490f29dbc25Smrg    /* CALCULATIONS BASED ON ALPHA DEPTH */
3491f29dbc25Smrg    /* Although most antialiased text is 4BPP, the hardware supports */
3492f29dbc25Smrg    /* a full 8BPP.  Either case is supported by this routine.       */
3493f29dbc25Smrg
3494f29dbc25Smrg    if (fourbpp) {
3495f29dbc25Smrg        depth_flag = GP3_CH3_SRC_4BPP_ALPHA;
3496f29dbc25Smrg        indent = (srcx >> 1) & 3;
3497f29dbc25Smrg        dataoffset += indent | ((srcx & 1) << 25);
349804007ebaSmrg    }
349904007ebaSmrg    else {
3500f29dbc25Smrg        depth_flag = GP3_CH3_SRC_8BPP_ALPHA;
3501f29dbc25Smrg        indent = srcx & 3;
3502f29dbc25Smrg        dataoffset += indent;
3503f29dbc25Smrg    }
3504f29dbc25Smrg
3505f29dbc25Smrg    /* SET RASTER MODE REGISTER */
3506f29dbc25Smrg    /* Alpha blending will only apply to RGB when no alpha component is present. */
3507f29dbc25Smrg    /* As 8BPP is not supported for this routine, the only alpha-less mode is    */
3508f29dbc25Smrg    /* 5:6:5.                                                                    */
3509f29dbc25Smrg
3510f29dbc25Smrg    if (gp3_bpp == GP3_RM_BPPFMT_565) {
3511f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
351204007ebaSmrg                        gp3_bpp |
351304007ebaSmrg                        GP3_RM_ALPHA_TO_RGB |
351404007ebaSmrg                        ((unsigned long) (operation << 20)) |
351504007ebaSmrg                        GP3_RM_SELECT_ALPHA_CHAN_3);
351604007ebaSmrg    }
351704007ebaSmrg    else {
3518f29dbc25Smrg        WRITE_COMMAND32(GP3_BLT_RASTER_MODE,
351904007ebaSmrg                        gp3_bpp |
352004007ebaSmrg                        GP3_RM_ALPHA_ALL | ((unsigned long) (operation << 20)) |
352104007ebaSmrg                        GP3_RM_SELECT_ALPHA_CHAN_3);
3522f29dbc25Smrg    }
3523f29dbc25Smrg
3524f29dbc25Smrg    /* WRITE ALL REMAINING REGISTERS */
3525f29dbc25Smrg
3526f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF));
3527f29dbc25Smrg
3528f29dbc25Smrg    /* Set the offset of the CH3 data in memory */
3529f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, dataoffset & 0x3FFFFF);
3530f29dbc25Smrg
3531f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size);
3532f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size);
3533f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base);
3534f29dbc25Smrg
3535f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | (stride & 0xFFFF) |
353604007ebaSmrg                    depth_flag | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) <<
353704007ebaSmrg                                  20));
3538f29dbc25Smrg
3539f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_MODE, GP3_BM_DST_REQ);
3540f29dbc25Smrg
3541f29dbc25Smrg    /* START THE BLT */
3542f29dbc25Smrg
3543f29dbc25Smrg    WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header);
3544f29dbc25Smrg    WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next);
3545f29dbc25Smrg    gp3_cmd_current = gp3_cmd_next;
3546f29dbc25Smrg}
3547