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