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