vramdac.c revision bdcaa8d0
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/rendition/vramdac.c,v 1.18 2002/12/11 17:23:33 dawes Exp $ */ 2/* 3 * includes 4 */ 5 6#ifdef HAVE_CONFIG_H 7#include "config.h" 8#endif 9 10#include "rendition.h" 11#include "vramdac.h" 12#include "vos.h" 13#include "v1kregs.h" 14#include "v2kregs.h" 15 16/* 17 * defines 18 */ 19 20#undef DEBUG 21 22/* directly accessable RAMDAC registers */ 23#define BT485_WRITE_ADDR 0x00 24#define BT485_RAMDAC_DATA 0x01 25#define BT485_PIXEL_MASK 0x02 26#define BT485_READ_ADDR 0x03 27#define BT485_CURS_WR_ADDR 0x04 28#define BT485_CURS_DATA 0x05 29#define BT485_COMMAND_REG_0 0x06 30#define BT485_CURS_RD_ADDR 0x07 31#define BT485_COMMAND_REG_1 0x08 32#define BT485_COMMAND_REG_2 0x09 33#define BT485_STATUS_REG 0x0a 34#define BT485_CURS_RAM_DATA 0x0b 35#define BT485_CURS_X_LOW 0x0c 36#define BT485_CURS_X_HIGH 0x0d 37#define BT485_CURS_Y_LOW 0x0e 38#define BT485_CURS_Y_HIGH 0x0f 39 40/* indirectly accessable ramdac registers */ 41#define BT485_COMMAND_REG_3 0x01 42 43/* bits in command register 0 */ 44#define BT485_CR0_EXTENDED_REG_ACCESS 0x80 45#define BT485_CR0_SCLK_SLEEP_DISABLE 0x40 46#define BT485_CR0_BLANK_PEDESTAL 0x20 47#define BT485_CR0_SYNC_ON_BLUE 0x10 48#define BT485_CR0_SYNC_ON_GREEN 0x08 49#define BT485_CR0_SYNC_ON_RED 0x04 50#define BT485_CR0_8_BIT_DAC 0x02 51#define BT485_CR0_SLEEP_ENABLE 0x01 52 53/* bits in command register 1 */ 54#define BT485_CR1_24BPP 0x00 55#define BT485_CR1_16BPP 0x20 56#define BT485_CR1_8BPP 0x40 57#define BT485_CR1_4BPP 0x60 58#define BT485_CR1_1BPP 0x80 59#define BT485_CR1_BYPASS_CLUT 0x10 60#define BT485_CR1_565_16BPP 0x08 61#define BT485_CR1_555_16BPP 0x00 62#define BT485_CR1_1_TO_1_16BPP 0x04 63#define BT485_CR1_2_TO_1_16BPP 0x00 64#define BT485_CR1_PD7_PIXEL_SWITCH 0x02 65#define BT485_CR1_PIXEL_PORT_CD 0x01 66#define BT485_CR1_PIXEL_PORT_AB 0x00 67 68/* bits in command register 2 */ 69#define BT485_CR2_SCLK_DISABLE 0x80 70#define BT485_TEST_PATH_SELECT 0x40 71#define BT485_PIXEL_INPUT_GATE 0x20 72#define BT485_PIXEL_CLK_SELECT 0x10 73#define BT485_INTERLACE_SELECT 0x08 74#define BT485_16BPP_CLUT_PACKED 0x04 75#define BT485_X_WINDOW_CURSOR 0x03 76#define BT485_2_COLOR_CURSOR 0x02 77#define BT485_3_COLOR_CURSOR 0x01 78#define BT485_DISABLE_CURSOR 0x00 79#define BT485_CURSOR_MASK 0x03 80 81/* bits in command register 3 */ 82#define BT485_4BPP_NIBBLE_SWAP 0x10 83#define BT485_CLOCK_DOUBLER 0x08 84#define BT485_64_BY_64_CURSOR 0x04 85#define BT485_32_BY_32_CURSOR 0x00 86#define BT485_SIZE_MASK 0x04 87 88/* special constants for the Brooktree BT485 RAMDAC */ 89#define BT485_INPUT_LIMIT 110000000 90 91 92 93/* 94 * local function prototypes 95 */ 96 97static void Bt485_write_masked(IOADDRESS port, vu8 reg, vu8 mask, vu8 data); 98static void Bt485_write_cmd3_masked(IOADDRESS port, vu8 mask, vu8 data); 99#if 0 100static vu8 Bt485_read_masked(IOADDRESS port, vu8 reg, vu8 mask); 101static vu8 Bt485_read_cmd3_masked(IOADDRESS port, vu8 mask); 102#endif 103 104/* 105 * local data 106 */ 107 108static int Cursor_size=0; 109 110 111 112/* 113 * functions 114 */ 115 116/* 117 * int verite_initdac(ScrnInfoPtr pScreenInfo, vu8 bpp, vu8 doubleclock) 118 * 119 * Used to initialize the ramdac. Palette-bypass is dis-/enabled with respect 120 * to the color depth, the cursor is disabled by default. If needed (i.e. if 121 * the corresponding field in the verite_board_t struct is set), the clock doubling 122 * is turned on. 123 */ 124 125void 126verite_savedac (ScrnInfoPtr pScreenInfo) 127{ 128 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 129 int iob=pRendition->board.io_base + RAMDACBASEADDR; 130 RenditionRegPtr reg = &pRendition->saveRegs; 131 132 reg->daccmd0 = verite_in8(iob+BT485_COMMAND_REG_0); 133 reg->daccmd1 = verite_in8(iob+BT485_COMMAND_REG_1); 134 reg->daccmd2 = verite_in8(iob+BT485_COMMAND_REG_2); 135 verite_out8(iob+BT485_COMMAND_REG_0,reg->daccmd0 136 | BT485_CR0_EXTENDED_REG_ACCESS); 137 verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3); 138 reg->daccmd3 = verite_in8(iob+BT485_STATUS_REG); 139 verite_out8(iob+BT485_COMMAND_REG_0,reg->daccmd0); 140} 141 142 143void 144verite_restoredac (ScrnInfoPtr pScreenInfo, RenditionRegPtr reg) 145{ 146 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 147 int iob=pRendition->board.io_base + RAMDACBASEADDR; 148 149 verite_out8(iob+BT485_COMMAND_REG_0, reg->daccmd0 150 | BT485_CR0_EXTENDED_REG_ACCESS); 151 verite_out8(iob+BT485_COMMAND_REG_1, reg->daccmd1); 152 verite_out8(iob+BT485_COMMAND_REG_2, reg->daccmd2); 153 verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3); 154 verite_out8(iob+BT485_STATUS_REG, reg->daccmd3); 155 verite_out8(iob+BT485_COMMAND_REG_0, reg->daccmd0); 156 157} 158 159int 160verite_initdac(ScrnInfoPtr pScreenInfo, vu8 bpp, vu8 doubleclock) 161{ 162 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 163 IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR; 164 vu8 cmd0,cmd1,cmd2; 165 vu8 cmd3_data=0; 166 167#ifdef DEBUG 168 ErrorF ("Rendition: Debug verite_initdac called\n"); 169#endif 170 171 if (doubleclock) 172 cmd3_data|=BT485_CLOCK_DOUBLER; 173 174 switch (bpp) { 175 case 1: 176 case 4: 177 xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG, 178 "color depth %d not (yet ?) supported\n", 179 bpp); 180 return -1; 181 182 case 8: 183 cmd0 = BT485_CR0_EXTENDED_REG_ACCESS | 184 BT485_CR0_8_BIT_DAC; 185 186 cmd1 = BT485_CR1_8BPP | 187 BT485_CR1_PIXEL_PORT_AB; 188 189 cmd2 = BT485_PIXEL_INPUT_GATE | 190 BT485_DISABLE_CURSOR; 191 192 verite_out8(iob+BT485_COMMAND_REG_0, cmd0); 193 verite_out8(iob+BT485_COMMAND_REG_1, cmd1); 194 verite_out8(iob+BT485_COMMAND_REG_2, cmd2); 195 break; 196 197 case 16: 198 cmd0 = BT485_CR0_EXTENDED_REG_ACCESS | 199 BT485_CR0_8_BIT_DAC; 200 201 cmd1 = BT485_CR1_16BPP | 202 BT485_CR1_2_TO_1_16BPP | 203 BT485_CR1_PIXEL_PORT_AB; 204 205 cmd2 = BT485_PIXEL_INPUT_GATE | 206 BT485_DISABLE_CURSOR; 207 208 if (pScreenInfo->defaultVisual == TrueColor) 209 cmd1 |= BT485_CR1_BYPASS_CLUT; 210 211 if (pScreenInfo->weight.green == 5) 212 cmd1 |= BT485_CR1_555_16BPP; 213 else 214 cmd1 |= BT485_CR1_565_16BPP; 215 216 verite_out8(iob+BT485_COMMAND_REG_0,cmd0); 217 verite_out8(iob+BT485_COMMAND_REG_1,cmd1); 218 verite_out8(iob+BT485_COMMAND_REG_2,cmd2); 219 break; 220 221 case 32: 222 cmd0 = BT485_CR0_EXTENDED_REG_ACCESS | 223 BT485_CR0_8_BIT_DAC; 224 225 cmd1 = BT485_CR1_24BPP | 226 BT485_CR1_PIXEL_PORT_AB; 227 228 cmd2 = BT485_PIXEL_INPUT_GATE | 229 BT485_DISABLE_CURSOR; 230 231 if (pScreenInfo->defaultVisual == TrueColor) 232 cmd1 |= BT485_CR1_BYPASS_CLUT; 233 234 verite_out8(iob+BT485_COMMAND_REG_0,cmd0); 235 verite_out8(iob+BT485_COMMAND_REG_1,cmd1); 236 verite_out8(iob+BT485_COMMAND_REG_2,cmd2); 237 break; 238 239 default: 240 xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG, 241 "Color depth not supported (%d bpp)\n", bpp); 242 return -1; 243 break; 244 } 245 246 verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3); 247 verite_out8(iob+BT485_STATUS_REG, cmd3_data); 248/* 249 Bt485_write_masked(iob, BT485_COMMAND_REG_0, 0x7f, 0x00); 250*/ 251 verite_out8(iob+BT485_PIXEL_MASK, 0xff); 252 253 return 0; 254} 255 256 257 258/* 259 * void verite_enablecursor(ScrnInfoPtr pScreenInfo, int type, int size) 260 * 261 * Used to enable the hardware cursor. Size indicates, whether to use no cursor 262 * at all, a 32x32 or a 64x64 cursor. The type selects a two-color, three-color 263 * or X-window-like cursor. Valid values are defined in vramdac.h. 264 * 265 */ 266void 267verite_enablecursor(ScrnInfoPtr pScreenInfo, int type, int size) 268{ 269 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 270 271 static vu8 ctypes[]={ BT485_DISABLE_CURSOR, BT485_2_COLOR_CURSOR, 272 BT485_3_COLOR_CURSOR, BT485_X_WINDOW_CURSOR }; 273 static vu8 csizes[]={ BT485_32_BY_32_CURSOR, BT485_64_BY_64_CURSOR }; 274 275 IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR; 276 277#ifdef DEBUG 278 ErrorF ("Rendition: Debug verite_enablecursor called type=0x%x\n",type); 279#endif 280 281 /* type goes to command register 2 */ 282 Bt485_write_masked(iob, BT485_COMMAND_REG_2, ~BT485_CURSOR_MASK, 283 ctypes[type]); 284 285 /* size is in command register 3 */ 286 Bt485_write_cmd3_masked(iob, ~BT485_SIZE_MASK, csizes[size]); 287 288 if (type) 289 Cursor_size=(size ? 64 : 32); 290 291#ifdef DEBUG 292 ErrorF ("Rendition: Debug verite_enablecursor Exit\n"); 293#endif 294 295} 296 297/* 298 * void verite_movecursor(ScrnInfoPtr pScreenInfo, vu16 x, vu16 y, vu8 xo, vu8 yo) 299 * 300 * Moves the cursor to the specified location. To hide the cursor, call 301 * this routine with x=0x0 and y=0x0. 302 * 303 */ 304void 305verite_movecursor(ScrnInfoPtr pScreenInfo, vu16 x, vu16 y, vu8 xo, vu8 yo) 306{ 307 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 308 IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR; 309 310 x+=Cursor_size-xo; 311 y+=Cursor_size-yo; 312 313 verite_out8(iob+BT485_CURS_X_LOW, x&0xff); 314 verite_out8(iob+BT485_CURS_X_HIGH, (x>>8)&0x0f); 315 verite_out8(iob+BT485_CURS_Y_LOW, y&0xff); 316 verite_out8(iob+BT485_CURS_Y_HIGH, (y>>8)&0x0f); 317} 318 319 320 321/* 322 * void verite_setcursorcolor(ScrnInfoPtr pScreenInfo, vu32 bg, vu32 fg) 323 * 324 * Sets the color of the cursor -- should be revised for use with 3 colors! 325 * 326 */ 327void 328verite_setcursorcolor(ScrnInfoPtr pScreenInfo, vu32 fg, vu32 bg) 329{ 330 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 331 IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR; 332 333#ifdef DEBUG 334 ErrorF ("Rendition: Debug verite_setcursorcolor called FG=0x%x BG=0x%x\n", 335 fg,bg); 336#endif 337 338 verite_out8(iob+BT485_CURS_WR_ADDR, 0x00); 339 340 /* load the cursor color 0 */ 341 verite_out8(iob+BT485_CURS_DATA, 0x00); 342 verite_out8(iob+BT485_CURS_DATA, 0x00); 343 verite_out8(iob+BT485_CURS_DATA, 0x00); 344 345 /* load the cursor color 1 */ 346 verite_out8(iob+BT485_CURS_DATA, (fg>>16) & 0xff); 347 verite_out8(iob+BT485_CURS_DATA, (fg>>8) & 0xff); 348 verite_out8(iob+BT485_CURS_DATA, fg&0xff ); 349 350 /* 351 * The V2xxx and the V1xxx with external BT485 behave differently. 352 * If we set color 2 to fg both work correctly. 353 */ 354 /* load the cursor color 2 */ 355 verite_out8(iob+BT485_CURS_DATA, (fg>>16) & 0xff); 356 verite_out8(iob+BT485_CURS_DATA, (fg>>8) & 0xff); 357 verite_out8(iob+BT485_CURS_DATA, fg & 0xff); 358 359 /* load the cursor color 3 */ 360 verite_out8(iob+BT485_CURS_DATA, (bg>>16)&0xff ); 361 verite_out8(iob+BT485_CURS_DATA, (bg>>8)&0xff ); 362 verite_out8(iob+BT485_CURS_DATA, bg&0xff ); 363} 364 365 366 367/* 368 * Oh god, this code is quite a mess ... should be re-written soon. 369 * But for now I'm happy it works ;) <ml> 370 * 371 */ 372void 373verite_loadcursor(ScrnInfoPtr pScreenInfo, vu8 size, vu8 *cursorimage) 374{ 375 int c, bytes, row; 376 vu8 *src = cursorimage; 377 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 378 IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR; 379 vu8 tmp; 380 vu8 memend; /* Added for byte-swap fix */ 381 382#ifdef DEBUG 383 ErrorF ("Rendition: Debug verite_loadcursor called\n"); 384#endif 385 386 if (NULL == cursorimage) 387 return; 388 389 /* Following two lines added for the byte-swap fix */ 390 memend = verite_in8(pRendition->board.io_base + MEMENDIAN); 391 verite_out8(pRendition->board.io_base + MEMENDIAN, MEMENDIAN_HW); 392 393 size&=1; 394 if (size) 395 bytes=64; 396 else 397 bytes=32; 398 bytes=(bytes*bytes)>>3; 399 400 if (pRendition->board.chip == V1000_DEVICE) { 401 /* now load the cursor data into the cursor ram */ 402 403 tmp=verite_in8(iob+BT485_COMMAND_REG_0)&0x7f; 404 verite_out8(iob+BT485_COMMAND_REG_0, tmp|0x80); 405 406 verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3); 407 408 tmp=verite_in8(iob+BT485_STATUS_REG)&0xf8; 409 verite_out8(iob+BT485_STATUS_REG, tmp|(size<<2)); 410 verite_out8(iob+BT485_WRITE_ADDR, 0x00); 411 412 /* output cursor image */ 413 src=cursorimage; 414 415 /* First plane data */ 416 for (c=0; c<bytes; c++) { 417 verite_out8(iob+BT485_CURS_RAM_DATA, *src); 418 src+=2; 419 } 420 421 /* Second plane data */ 422 src=cursorimage+1; 423 for (c=0; c<bytes; c++) { 424 verite_out8(iob+BT485_CURS_RAM_DATA, *src); 425 src+=2; 426 } 427 } 428 else { 429 /* V2x00 HW-Cursor, supports only 64x64x2 size */ 430 431 verite_out32(iob+CURSORBASE, pRendition->board.hwcursor_membase); 432 433 /* First plane data */ 434 for (row=0; row<64; row++) 435 for (c=0, src=cursorimage+1+16*row; c<8; c++, src+=2) 436 verite_write_memory8(pRendition->board.vmem_base, 16*(63-row)+c, 437 (c&1)?(*(src-2)):(*(src+2))); 438 /* Second plane data */ 439 for (row=0; row<64; row++) 440 for (c=0, src=cursorimage+16*row; c<8; c++, src+=2) 441 verite_write_memory8(pRendition->board.vmem_base, 8+16*(63-row)+c, 442 (c&1)?(*(src-2)):(*(src+2))); 443 444 } 445 /* Following line added for the byte-swap fix */ 446 verite_out8(pRendition->board.io_base + MEMENDIAN, memend); 447} 448 449 450 451/* NOTE: count is the actual number of colors decremented by 1 */ 452 453void 454verite_setpalette(ScrnInfoPtr pScreenInfo, int numColors, int *indices, 455 LOCO *colors, VisualPtr pVisual) 456{ 457 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 458 IOADDRESS iob=pRendition->board.io_base; 459 vu32 crtc_status; 460 int i, index; 461 462#ifdef DEBUG 463 ErrorF ("Rendition: Debug verite_setpalette called\n"); 464#endif 465 466 while (1) { 467 crtc_status=verite_in32(iob+CRTCSTATUS); 468 if (crtc_status & CRTCSTATUS_VERT_SYNC) 469 break; 470 }; 471 472 iob+=RAMDACBASEADDR; 473 474 for (i = 0; i < numColors; i++) { 475 index = indices[i]; 476 verite_out8(iob+BT485_WRITE_ADDR, index); 477 478 verite_out8(iob+BT485_RAMDAC_DATA, colors[index].red); 479 verite_out8(iob+BT485_RAMDAC_DATA, colors[index].green); 480 verite_out8(iob+BT485_RAMDAC_DATA, colors[index].blue); 481 } 482} 483 484/* 485 * local functions 486 */ 487 488/* 489 * static void Bt485_write_masked(IOADDRESS port, vu8 reg, vu8 mask, vu8 data) 490 * 491 * 492 */ 493static void 494Bt485_write_masked(IOADDRESS port, vu8 reg, vu8 mask, vu8 data) 495{ 496 vu8 tmp; 497 498 tmp=verite_in8(port+reg)&mask; 499 verite_out8(port+reg, tmp|data); 500} 501 502 503 504/* 505 * static void Bt485_write_cmd3_masked(IOADDRESS port, vu8 mask, vu8 data) 506 * 507 * 508 */ 509static void 510Bt485_write_cmd3_masked(IOADDRESS port, vu8 mask, vu8 data) 511{ 512/* 513 * Bt485_write_masked(port, BT485_COMMAND_REG_0, 0x7f, 0x80); 514 */ 515 verite_out8(port+BT485_WRITE_ADDR, BT485_COMMAND_REG_3); 516 Bt485_write_masked(port, BT485_STATUS_REG, mask, data); 517/* 518 * Bt485_write_masked(port, BT485_COMMAND_REG_0, 0x7f, 0x00); 519 */ 520} 521 522 523 524#if 0 525/* 526 * static vu8 Bt485_read_masked(IOADDRESS port, vu8 reg, vu8 mask) 527 * 528 * 529 */ 530static vu8 531Bt485_read_masked(IOADDRESS port, vu8 reg, vu8 mask) 532{ 533 return verite_in8(port+reg)&mask; 534} 535 536 537/* 538 * static vu8 Bt485_read_cmd3_masked(IOADDRESS port, vu8 mask) 539 * 540 * 541 */ 542static vu8 543Bt485_read_cmd3_masked(IOADDRESS port, vu8 mask) 544{ 545 vu8 value; 546 547 Bt485_write_masked(port, BT485_COMMAND_REG_0, 0x7f, 0x80); 548 verite_out8(port+BT485_WRITE_ADDR, BT485_COMMAND_REG_3); 549 value=Bt485_read_masked(port, BT485_STATUS_REG, mask); 550 Bt485_write_masked(port, BT485_COMMAND_REG_0, 0x7f, 0x00); 551 552 return value; 553} 554#endif 555 556 557/* 558 * end of file vramdac.c 559 */ 560