1706f2543Smrg/*
2706f2543Smrg * Copyright 1998 by Alan Hourihane, Wigan, England.
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Alan Hourihane not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Alan Hourihane makes no representations
11706f2543Smrg * about the suitability of this software for any purpose.  It is provided
12706f2543Smrg * "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg *
22706f2543Smrg * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23706f2543Smrg *
24706f2543Smrg * BT RAMDAC routines.
25706f2543Smrg */
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
28706f2543Smrg#include <xorg-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include "xf86.h"
32706f2543Smrg#include "xf86_OSproc.h"
33706f2543Smrg
34706f2543Smrg#define INIT_BT_RAMDAC_INFO
35706f2543Smrg#include "BTPriv.h"
36706f2543Smrg#include "xf86RamDacPriv.h"
37706f2543Smrg
38706f2543Smrgvoid
39706f2543SmrgBTramdacRestore(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
40706f2543Smrg				    RamDacRegRecPtr ramdacReg)
41706f2543Smrg{
42706f2543Smrg	int i;
43706f2543Smrg
44706f2543Smrg	/* Here we pass a short, so that we can evaluate a mask too */
45706f2543Smrg	/* So that the mask is the high byte and the data the low byte */
46706f2543Smrg	/* Just the command/status registers */
47706f2543Smrg	for (i=0x06;i<0x0A;i++)
48706f2543Smrg	    (*ramdacPtr->WriteDAC)
49706f2543Smrg	        (pScrn, i, (ramdacReg->DacRegs[i] & 0xFF00) >> 8,
50706f2543Smrg						ramdacReg->DacRegs[i]);
51706f2543Smrg}
52706f2543Smrg
53706f2543Smrgvoid
54706f2543SmrgBTramdacSave(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
55706f2543Smrg				 RamDacRegRecPtr ramdacReg)
56706f2543Smrg{
57706f2543Smrg	int i;
58706f2543Smrg
59706f2543Smrg	(*ramdacPtr->ReadAddress)(pScrn, 0); /* Start at index 0 */
60706f2543Smrg	for (i=0;i<768;i++)
61706f2543Smrg	    ramdacReg->DAC[i] = (*ramdacPtr->ReadData)(pScrn);
62706f2543Smrg
63706f2543Smrg	/* Just the command/status registers */
64706f2543Smrg	for (i=0x06;i<0x0A;i++)
65706f2543Smrg	    ramdacReg->DacRegs[i] = (*ramdacPtr->ReadDAC)(pScrn, i);
66706f2543Smrg}
67706f2543Smrg
68706f2543SmrgRamDacHelperRecPtr
69706f2543SmrgBTramdacProbe(ScrnInfoPtr pScrn, RamDacSupportedInfoRecPtr ramdacs/*, RamDacRecPtr ramdacPtr*/)
70706f2543Smrg{
71706f2543Smrg    RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
72706f2543Smrg    Bool RamDacIsSupported = FALSE;
73706f2543Smrg    RamDacHelperRecPtr ramdacHelperPtr = NULL;
74706f2543Smrg    int BTramdac_ID = -1;
75706f2543Smrg    int i, status, cmd0;
76706f2543Smrg
77706f2543Smrg    /* Save COMMAND Register 0 */
78706f2543Smrg    cmd0 = (*ramdacPtr->ReadDAC)(pScrn, BT_COMMAND_REG_0);
79706f2543Smrg    /* Ensure were going to access the STATUS Register on next read */
80706f2543Smrg    (*ramdacPtr->WriteDAC)(pScrn, BT_COMMAND_REG_0, 0x7F, 0x00);
81706f2543Smrg
82706f2543Smrg    status = (*ramdacPtr->ReadDAC)(pScrn, BT_STATUS_REG);
83706f2543Smrg    switch (status) {
84706f2543Smrg	case 0x40:
85706f2543Smrg		BTramdac_ID = ATT20C504_RAMDAC;
86706f2543Smrg		break;
87706f2543Smrg	case 0xD0:
88706f2543Smrg		BTramdac_ID = ATT20C505_RAMDAC;
89706f2543Smrg		break;
90706f2543Smrg	default:
91706f2543Smrg		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
92706f2543Smrg			   "Unknown BT RAMDAC type (0x%x), assuming BT485\n",
93706f2543Smrg			   status);
94706f2543Smrg	case 0x80:
95706f2543Smrg	case 0x90:
96706f2543Smrg	case 0xA0:
97706f2543Smrg	case 0xB0:
98706f2543Smrg	case 0x28: 	/* This is for the DEC TGA - Questionable ? */
99706f2543Smrg		BTramdac_ID = BT485_RAMDAC;
100706f2543Smrg		break;
101706f2543Smrg    }
102706f2543Smrg
103706f2543Smrg    /* Restore COMMAND Register 0 */
104706f2543Smrg    (*ramdacPtr->WriteDAC)(pScrn, BT_COMMAND_REG_0, 0x00, cmd0);
105706f2543Smrg
106706f2543Smrg    if (BTramdac_ID == -1) {
107706f2543Smrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
108706f2543Smrg		"Cannot determine BT RAMDAC type, aborting\n");
109706f2543Smrg	return NULL;
110706f2543Smrg    } else {
111706f2543Smrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
112706f2543Smrg		"Attached RAMDAC is %s\n", BTramdacDeviceInfo[BTramdac_ID&0xFFFF].DeviceName);
113706f2543Smrg    }
114706f2543Smrg
115706f2543Smrg    for (i=0;ramdacs[i].token != -1;i++) {
116706f2543Smrg	if (ramdacs[i].token == BTramdac_ID)
117706f2543Smrg	    RamDacIsSupported = TRUE;
118706f2543Smrg    }
119706f2543Smrg
120706f2543Smrg    if (!RamDacIsSupported) {
121706f2543Smrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
122706f2543Smrg		"This BT RAMDAC is NOT supported by this driver, aborting\n");
123706f2543Smrg	return NULL;
124706f2543Smrg    }
125706f2543Smrg
126706f2543Smrg    ramdacHelperPtr = RamDacHelperCreateInfoRec();
127706f2543Smrg    switch(BTramdac_ID) {
128706f2543Smrg	case BT485_RAMDAC:
129706f2543Smrg	    ramdacHelperPtr->SetBpp = BTramdacSetBpp;
130706f2543Smrg	    break;
131706f2543Smrg    }
132706f2543Smrg    ramdacPtr->RamDacType = BTramdac_ID;
133706f2543Smrg    ramdacHelperPtr->RamDacType = BTramdac_ID;
134706f2543Smrg    ramdacHelperPtr->Save = BTramdacSave;
135706f2543Smrg    ramdacHelperPtr->Restore = BTramdacRestore;
136706f2543Smrg
137706f2543Smrg    return ramdacHelperPtr;
138706f2543Smrg}
139706f2543Smrg
140706f2543Smrgvoid
141706f2543SmrgBTramdacSetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
142706f2543Smrg{
143706f2543Smrg    /* We need to deal with Direct Colour visuals for 8bpp and other
144706f2543Smrg     * good stuff for colours */
145706f2543Smrg    switch (pScrn->bitsPerPixel) {
146706f2543Smrg	case 32:
147706f2543Smrg	    ramdacReg->DacRegs[BT_COMMAND_REG_1] = 0x10;
148706f2543Smrg	    break;
149706f2543Smrg	case 24:
150706f2543Smrg	    ramdacReg->DacRegs[BT_COMMAND_REG_1] = 0x10;
151706f2543Smrg	    break;
152706f2543Smrg	case 16:
153706f2543Smrg	    ramdacReg->DacRegs[BT_COMMAND_REG_1] = 0x38;
154706f2543Smrg	    break;
155706f2543Smrg	case 15:
156706f2543Smrg	    ramdacReg->DacRegs[BT_COMMAND_REG_1] = 0x30;
157706f2543Smrg	    break;
158706f2543Smrg	case 8:
159706f2543Smrg	    ramdacReg->DacRegs[BT_COMMAND_REG_1] = 0x40;
160706f2543Smrg	    break;
161706f2543Smrg	case 4:
162706f2543Smrg	    ramdacReg->DacRegs[BT_COMMAND_REG_1] = 0x60;
163706f2543Smrg	    break;
164706f2543Smrg    }
165706f2543Smrg}
166