1/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 * */ 25 26/* 27 * This is the main file used to add Durango graphics support to a software 28 * project. The main reason to have a single file include the other files 29 * is that it centralizes the location of the compiler options. This file 30 * should be tuned for a specific implementation, and then modified as needed 31 * for new Durango releases. The releases.txt file indicates any updates to 32 * this main file, such as a new definition for a new hardware platform. 33 * 34 * In other words, this file should be copied from the Durango source files 35 * once when a software project starts, and then maintained as necessary. 36 * It should not be recopied with new versions of Durango unless the 37 * developer is willing to tune the file again for the specific project. 38 * */ 39 40#ifdef HAVE_CONFIG_H 41#include "config.h" 42#endif 43 44#include "gfx_rtns.h" 45#include "gfx_defs.h" 46#include "gfx_regs.h" 47 48#define GU2_WAIT_PENDING \ 49 while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING) 50#define GU2_WAIT_HALF_EMPTY \ 51 while(!(READ_GP32(MGP_BLT_STATUS) & MGP_BS_HALF_EMPTY)) 52 53extern unsigned long gu2_pitch; 54extern unsigned long gu2_xshift; 55extern unsigned short GFXpatternFlags; 56extern unsigned long gu2_rop32; 57extern unsigned short gu2_blt_mode; 58 59void gfx_write_reg8(unsigned long offset, unsigned char value); 60void gfx_write_reg16(unsigned long offset, unsigned short value); 61void gfx_write_reg32(unsigned long offset, unsigned long value); 62unsigned short gfx_read_reg16(unsigned long offset); 63unsigned long gfx_read_reg32(unsigned long offset); 64void gfx_write_vid32(unsigned long offset, unsigned long value); 65unsigned long gfx_read_vid32(unsigned long offset); 66unsigned long gfx_read_vip32(unsigned long offset); 67void gfx_write_vip32(unsigned long offset, unsigned long value); 68void gfx_mono_bitmap_to_screen_blt_swp(unsigned short srcx, 69 unsigned short srcy, 70 unsigned short dstx, 71 unsigned short dsty, 72 unsigned short width, 73 unsigned short height, 74 unsigned char *data, short pitch); 75unsigned int GetVideoMemSize(void); 76 77/* ROUTINES added accessing hardware reg */ 78void 79gfx_write_reg8(unsigned long offset, unsigned char value) 80{ 81 WRITE_REG8(offset, value); 82} 83 84void 85gfx_write_reg16(unsigned long offset, unsigned short value) 86{ 87 WRITE_REG16(offset, value); 88} 89 90void 91gfx_write_reg32(unsigned long offset, unsigned long value) 92{ 93 WRITE_REG32(offset, value); 94} 95 96unsigned short 97gfx_read_reg16(unsigned long offset) 98{ 99 unsigned short value; 100 101 value = READ_REG16(offset); 102 return value; 103} 104 105unsigned long 106gfx_read_reg32(unsigned long offset) 107{ 108 unsigned long value; 109 110 value = READ_REG32(offset); 111 return value; 112} 113 114void 115gfx_write_vid32(unsigned long offset, unsigned long value) 116{ 117 WRITE_VID32(offset, value); 118} 119 120unsigned long 121gfx_read_vid32(unsigned long offset) 122{ 123 unsigned long value; 124 125 value = READ_VID32(offset); 126 return value; 127} 128 129/*Addition for the VIP code */ 130unsigned long 131gfx_read_vip32(unsigned long offset) 132{ 133 unsigned long value; 134 135 value = READ_VIP32(offset); 136 return value; 137} 138 139void 140gfx_write_vip32(unsigned long offset, unsigned long value) 141{ 142 WRITE_VIP32(offset, value); 143} 144 145#define SWAP_BITS_IN_BYTES(v) \ 146 (((0x01010101 & (v)) << 7) | ((0x02020202 & (v)) << 5) | \ 147 ((0x04040404 & (v)) << 3) | ((0x08080808 & (v)) << 1) | \ 148 ((0x10101010 & (v)) >> 1) | ((0x20202020 & (v)) >> 3) | \ 149 ((0x40404040 & (v)) >> 5) | ((0x80808080 & (v)) >> 7)) 150 151#define WRITE_GPREG_STRING32_SWP(regoffset, dwords, \ 152 counter, array, array_offset, temp) \ 153{ \ 154 temp = (unsigned long)array + (array_offset); \ 155 for (counter = 0; counter < dwords; counter++) \ 156 WRITE_GP32 (regoffset, \ 157 SWAP_BITS_IN_BYTES(*((unsigned long *)temp + counter))); \ 158} 159 160void 161gfx_mono_bitmap_to_screen_blt_swp(unsigned short srcx, unsigned short srcy, 162 unsigned short dstx, unsigned short dsty, 163 unsigned short width, unsigned short height, 164 unsigned char *data, short pitch) 165{ 166 unsigned long dstoffset, size, bytes; 167 unsigned long offset, temp_offset, temp1 = 0, temp2 = 0; 168 unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; 169 unsigned long shift = 0; 170 171 size = (((unsigned long) width) << 16) | height; 172 173 /* CALCULATE STARTING OFFSETS */ 174 175 offset = (unsigned long) srcy *pitch + ((unsigned long) srcx >> 3); 176 177 dstoffset = (unsigned long) dsty *gu2_pitch + 178 (((unsigned long) dstx) << gu2_xshift); 179 180 /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ 181 182 if (GFXpatternFlags) { 183 /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ 184 185 dstoffset |= ((unsigned long) (dstx & 7)) << 26; 186 dstoffset |= ((unsigned long) (dsty & 7)) << 29; 187 } 188 189 bytes = ((srcx & 7) + width + 7) >> 3; 190 fifo_lines = bytes >> 5; 191 dwords_extra = (bytes & 0x0000001Cl) >> 2; 192 bytes_extra = bytes & 0x00000003l; 193 194 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 195 /* Put off poll for as long as possible (do most calculations first). */ 196 /* The source offset is always 0 since we allow misaligned dword reads. */ 197 /* Need to wait for busy instead of pending, since hardware clears */ 198 /* the host data FIFO at the beginning of a BLT. */ 199 200 GU2_WAIT_PENDING; 201 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); 202 WRITE_GP32(MGP_SRC_OFFSET, ((unsigned long) srcx & 7) << 26); 203 WRITE_GP32(MGP_DST_OFFSET, dstoffset); 204 WRITE_GP32(MGP_WID_HEIGHT, size); 205 WRITE_GP32(MGP_STRIDE, gu2_pitch); 206 WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | MGP_BM_SRC_HOST | MGP_BM_SRC_MONO); 207 208 /* WAIT FOR BLT TO BE LATCHED */ 209 210 GU2_WAIT_PENDING; 211 212 /* WRITE ALL OF THE DATA TO THE HOST SOURCE REGISTER */ 213 214 while (height--) { 215 temp_offset = offset; 216 217 /* WRITE ALL FULL FIFO LINES */ 218 219 for (i = 0; i < fifo_lines; i++) { 220 GU2_WAIT_HALF_EMPTY; 221 WRITE_GPREG_STRING32_SWP(MGP_HST_SOURCE, 8, j, data, temp_offset, 222 temp1); 223 temp_offset += 32; 224 } 225 226 /* WRITE ALL FULL DWORDS */ 227 228 GU2_WAIT_HALF_EMPTY; 229 if (dwords_extra) { 230 WRITE_GPREG_STRING32_SWP(MGP_HST_SOURCE, dwords_extra, i, data, 231 temp_offset, temp1); 232 temp_offset += (dwords_extra << 2); 233 } 234 235 /* WRITE REMAINING BYTES */ 236 237 shift = 0; 238 if (bytes_extra) 239 WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, 240 temp_offset, temp1, temp2); 241 242 offset += pitch; 243 } 244} 245 246unsigned int 247GetVideoMemSize(void) 248{ 249 unsigned int graphicsMemBaseAddr; 250 unsigned int totalMem = 0; 251 int i; 252 unsigned int graphicsMemMask, graphicsMemShift; 253 unsigned int mcBankCfg = gfx_read_reg32(0x8408); 254 unsigned int dimmShift = 4; 255 256 /* Read graphics base address. */ 257 258 graphicsMemBaseAddr = gfx_read_reg32(0x8414); 259 260 graphicsMemMask = 0x7FF; 261 graphicsMemShift = 19; 262 263 /* Calculate total memory size for GXm. */ 264 265 for (i = 0; i < 2; i++) { 266 if (((mcBankCfg >> dimmShift) & 0x7) != 0x7) { 267 switch ((mcBankCfg >> (dimmShift + 4)) & 0x7) { 268 case 0: 269 totalMem += 0x400000; 270 break; 271 case 1: 272 totalMem += 0x800000; 273 break; 274 case 2: 275 totalMem += 0x1000000; 276 break; 277 case 3: 278 totalMem += 0x2000000; 279 break; 280 case 4: 281 totalMem += 0x4000000; 282 break; 283 case 5: 284 totalMem += 0x8000000; 285 break; 286 case 6: 287 totalMem += 0x10000000; 288 break; 289 case 7: 290 totalMem += 0x20000000; 291 break; 292 default: 293 break; 294 } 295 } 296 dimmShift += 16; 297 } 298 299 /* Calculate graphics memory base address */ 300 301 graphicsMemBaseAddr &= graphicsMemMask; 302 graphicsMemBaseAddr <<= graphicsMemShift; 303 304 return (totalMem - graphicsMemBaseAddr); 305} 306 307/* END OF FILE */ 308