atirgb514.c revision 32b578d3
1/*
2 * Copyright 2001 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of Marc Aurele La France not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  Marc Aurele La France makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as-is" without express or implied warranty.
13 *
14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "ati.h"
28#include "aticrtc.h"
29#include "atimach64io.h"
30#include "atirgb514.h"
31
32/*
33 * ATIRGB514PreInit --
34 *
35 * This function fills in the IBM RGB 514 portion of an ATIHWRec that is common
36 * to all video modes generated by the server.
37 */
38void
39ATIRGB514PreInit
40(
41    ATIPtr   pATI,
42    ATIHWPtr pATIHW
43)
44{
45    /* Get a work copy of IBM RGB 514 registers */
46    ATIRGB514Save(pATI, pATIHW);
47
48    /* Miscellaneous Clock Control */
49    pATIHW->ibmrgb514[0x0002U] = 0x01U;
50
51    /* Sync Control */
52    pATIHW->ibmrgb514[0x0003U] &= ~0x80U;
53
54    /* Horizontal Sync Control */
55    pATIHW->ibmrgb514[0x0004U] = 0x00U;
56
57    /* Power Management */
58    pATIHW->ibmrgb514[0x0005U] = 0x00U;
59
60    /* DAC Operation */
61    pATIHW->ibmrgb514[0x0006U] &= ~0x04U;
62
63    /* Palette Control */
64    pATIHW->ibmrgb514[0x0007U] = 0x00U;
65
66    /* PLL Control */
67    pATIHW->ibmrgb514[0x0010U] = 0x01U;
68
69    /* Cursor control */
70    pATIHW->ibmrgb514[0x0030U] &= ~0x03U;       /* For now */
71
72    /* Border (i.e. overscan) */
73    pATIHW->ibmrgb514[0x0060U] = 0x00U;
74    pATIHW->ibmrgb514[0x0061U] = 0x00U;
75    pATIHW->ibmrgb514[0x0062U] = 0x00U;
76
77    /* Miscellaneous Control */
78    pATIHW->ibmrgb514[0x0070U] &= ~0x20U;
79    pATIHW->ibmrgb514[0x0071U] = 0x41U; /* See workaround in ATIRGB514Set() */
80
81#ifndef AVOID_CPIO
82
83    if (pATIHW->crtc == ATI_CRTC_VGA)
84    {
85        /* Pixel Format */
86        pATIHW->ibmrgb514[0x000AU] = 0x03U;
87
88        /* Miscellaneous Control */
89        pATIHW->ibmrgb514[0x0070U] |= 0x40U;
90
91        /* VRAM Mask */
92        pATIHW->ibmrgb514[0x0090U] = 0x03U;
93    }
94    else
95
96#endif /* AVOID_CPIO */
97
98    {
99        /* Miscellaneous Control */
100        pATIHW->ibmrgb514[0x0070U] &= ~0x40U;
101
102        /* VRAM Mask */
103        pATIHW->ibmrgb514[0x0090U] = 0x00U;
104        pATIHW->ibmrgb514[0x0091U] = 0x00U;
105
106        /* Pixel Format */
107        switch (pATI->depth)
108        {
109            case 8:
110                pATIHW->ibmrgb514[0x000AU] = 0x03U;
111                pATIHW->ibmrgb514[0x000BU] = 0x00U;
112                break;
113
114            case 15:
115                pATIHW->ibmrgb514[0x000AU] = 0x04U;
116                pATIHW->ibmrgb514[0x000CU] = 0xC4U;
117                break;
118
119            case 16:
120                pATIHW->ibmrgb514[0x000AU] = 0x04U;
121                pATIHW->ibmrgb514[0x000CU] = 0xC6U;
122                break;
123
124            case 24:
125                if (pATI->bitsPerPixel == 24)
126                {
127                    pATIHW->ibmrgb514[0x000AU] = 0x05U;
128                    pATIHW->ibmrgb514[0x000DU] = 0x01U;
129                }
130                else
131                {
132                    pATIHW->ibmrgb514[0x000AU] = 0x06U;
133                    pATIHW->ibmrgb514[0x000EU] = 0x03U;
134                }
135                break;
136
137            default:
138                break;
139        }
140    }
141
142    if (pATI->rgbBits == 8)
143        pATIHW->ibmrgb514[0x0071U] |= 0x04U;
144}
145
146/*
147 * ATIRGB514Save --
148 *
149 * This function saves IBM RGB514 related data into an ATIHWRec.
150 */
151void
152ATIRGB514Save
153(
154    ATIPtr   pATI,
155    ATIHWPtr pATIHW
156)
157{
158    CARD32 crtc_gen_cntl, dac_cntl;
159    CARD8  index_lo, index_hi, index_ctl;
160    int    Index;
161
162    /* Temporarily switch to Mach64 CRTC */
163    crtc_gen_cntl = inr(CRTC_GEN_CNTL);
164    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
165        outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
166
167    /* Temporarily switch to IBM RGB 514 registers */
168    dac_cntl = inr(DAC_CNTL) & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3);
169    outr(DAC_CNTL, dac_cntl | DAC_EXT_SEL_RS2);
170
171    index_lo = in8(M64_DAC_WRITE);
172    index_hi = in8(M64_DAC_DATA);
173    index_ctl = in8(M64_DAC_READ);
174
175    out8(M64_DAC_WRITE, 0x00U);
176    out8(M64_DAC_DATA, 0x00U);
177    out8(M64_DAC_READ, 0x01U);  /* Auto-increment */
178
179    /* Save IBM RGB 514 registers */
180    for (Index = 0;  Index < NumberOf(pATIHW->ibmrgb514);  Index++)
181    {
182        /* Need to rewrite the index every so often... */
183        if ((Index == 0x0100) || (Index == 0x0500))
184        {
185            out8(M64_DAC_WRITE, 0);
186            out8(M64_DAC_DATA, Index >> 8);
187        }
188        pATIHW->ibmrgb514[Index] = in8(M64_DAC_MASK);
189    }
190
191    /* Restore registers */
192    out8(M64_DAC_WRITE, index_lo);
193    out8(M64_DAC_DATA, index_hi);
194    out8(M64_DAC_READ, index_ctl);
195    outr(DAC_CNTL, dac_cntl);
196    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
197        outr(CRTC_GEN_CNTL, crtc_gen_cntl);
198}
199
200/*
201 * ATIRGB514Calculate --
202 *
203 * This function fills in the IBM RGB 514 portion of an ATIHWRec that is
204 * specific to a display mode.  pATIHW->ibmrgb514 has already been
205 * initialised by a previous call to ATIRGB514PreInit().
206 */
207void
208ATIRGB514Calculate
209(
210    ATIPtr         pATI,
211    ATIHWPtr       pATIHW,
212    DisplayModePtr pMode
213)
214{
215    if (pATI->OptionCSync || (pMode->Flags & (V_CSYNC | V_PCSYNC)))
216        pATIHW->ibmrgb514[0x0006U] |= 0x08U;
217    else
218        pATIHW->ibmrgb514[0x0006U] &= ~0x08U;
219
220    if (pMode->Flags & V_INTERLACE)
221        pATIHW->ibmrgb514[0x0071U] |= 0x20U;
222    else
223        pATIHW->ibmrgb514[0x0071U] &= ~0x20U;
224}
225
226/*
227 * ATIRGB514Set --
228 *
229 * This function is called to set an IBM RGB514's registers.
230 */
231void
232ATIRGB514Set
233(
234    ATIPtr   pATI,
235    ATIHWPtr pATIHW
236)
237{
238    CARD32 crtc_gen_cntl, dac_cntl;
239    CARD8  index_lo, index_hi, index_ctl;
240    int    Index;
241
242    /* Temporarily switch to Mach64 CRTC */
243    crtc_gen_cntl = inr(CRTC_GEN_CNTL);
244    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
245        outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
246
247    /* Temporarily switch to IBM RGB 514 registers */
248    dac_cntl = inr(DAC_CNTL) & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3);
249    outr(DAC_CNTL, dac_cntl | DAC_EXT_SEL_RS2);
250
251    index_lo = in8(M64_DAC_WRITE);
252    index_hi = in8(M64_DAC_DATA);
253    index_ctl = in8(M64_DAC_READ);
254
255    out8(M64_DAC_WRITE, 0x00U);
256    out8(M64_DAC_DATA, 0x00U);
257    out8(M64_DAC_READ, 0x01U);  /* Auto-increment */
258
259    /* Load IBM RGB 514 registers */
260    for (Index = 0;  Index < NumberOf(pATIHW->ibmrgb514);  Index++)
261         out8(M64_DAC_MASK, pATIHW->ibmrgb514[Index]);
262
263#ifndef AVOID_CPIO
264
265    /* Deal with documented anomaly */
266    if (pATIHW->crtc == ATI_CRTC_VGA)
267    {
268        /* Reset Miscellaneous Control 2 */
269        out8(M64_DAC_WRITE, 0x71U);
270        out8(M64_DAC_DATA, 0x00U);
271        out8(M64_DAC_MASK, pATIHW->ibmrgb514[0x0071U] & ~0x41U);
272    }
273
274#endif /* AVOID_CPIO */
275
276    /* Restore registers */
277    out8(M64_DAC_WRITE, index_lo);
278    out8(M64_DAC_DATA, index_hi);
279    out8(M64_DAC_READ, index_ctl);
280    outr(DAC_CNTL, dac_cntl);
281    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
282        outr(CRTC_GEN_CNTL, crtc_gen_cntl);
283}
284