1/*
2 * Copyright 1996-1997  David J. McKay
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
24   <jpaana@s2.org> */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include "riva_include.h"
31
32Bool
33RivaDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
34{
35    int i;
36    int horizDisplay    = (mode->CrtcHDisplay/8)   - 1;
37    int horizStart      = (mode->CrtcHSyncStart/8) - 1;
38    int horizEnd        = (mode->CrtcHSyncEnd/8)   - 1;
39    int horizTotal      = (mode->CrtcHTotal/8)     - 5;
40    int horizBlankStart = (mode->CrtcHDisplay/8)   - 1;
41    int horizBlankEnd   = (mode->CrtcHTotal/8)     - 1;
42    int vertDisplay     =  mode->CrtcVDisplay      - 1;
43    int vertStart       =  mode->CrtcVSyncStart    - 1;
44    int vertEnd         =  mode->CrtcVSyncEnd      - 1;
45    int vertTotal       =  mode->CrtcVTotal        - 2;
46    int vertBlankStart  =  mode->CrtcVDisplay      - 1;
47    int vertBlankEnd    =  mode->CrtcVTotal        - 1;
48
49
50    RivaPtr pRiva = RivaPTR(pScrn);
51    RivaRegPtr rivaReg = &pRiva->ModeReg;
52    RivaFBLayout *pLayout = &pRiva->CurrentLayout;
53    vgaRegPtr   pVga;
54
55    /*
56     * This will initialize all of the generic VGA registers.
57     */
58    if (!vgaHWInit(pScrn, mode))
59        return(FALSE);
60
61    pVga = &VGAHWPTR(pScrn)->ModeReg;
62
63    /*
64     * Set all CRTC values.
65     */
66
67    if(mode->Flags & V_INTERLACE)
68        vertTotal |= 1;
69
70    pVga->CRTC[0x0]  = RIVA_Set8Bits(horizTotal);
71    pVga->CRTC[0x1]  = RIVA_Set8Bits(horizDisplay);
72    pVga->CRTC[0x2]  = RIVA_Set8Bits(horizBlankStart);
73    pVga->CRTC[0x3]  = RIVA_SetBitField(horizBlankEnd,4:0,4:0)
74                       | RIVA_SetBit(7);
75    pVga->CRTC[0x4]  = RIVA_Set8Bits(horizStart);
76    pVga->CRTC[0x5]  = RIVA_SetBitField(horizBlankEnd,5:5,7:7)
77                       | RIVA_SetBitField(horizEnd,4:0,4:0);
78    pVga->CRTC[0x6]  = RIVA_SetBitField(vertTotal,7:0,7:0);
79    pVga->CRTC[0x7]  = RIVA_SetBitField(vertTotal,8:8,0:0)
80                       | RIVA_SetBitField(vertDisplay,8:8,1:1)
81                       | RIVA_SetBitField(vertStart,8:8,2:2)
82                       | RIVA_SetBitField(vertBlankStart,8:8,3:3)
83                       | RIVA_SetBit(4)
84                       | RIVA_SetBitField(vertTotal,9:9,5:5)
85                       | RIVA_SetBitField(vertDisplay,9:9,6:6)
86                       | RIVA_SetBitField(vertStart,9:9,7:7);
87    pVga->CRTC[0x9]  = RIVA_SetBitField(vertBlankStart,9:9,5:5)
88                       | RIVA_SetBit(6)
89                       | ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00);
90    pVga->CRTC[0x10] = RIVA_Set8Bits(vertStart);
91    pVga->CRTC[0x11] = RIVA_SetBitField(vertEnd,3:0,3:0) | RIVA_SetBit(5);
92    pVga->CRTC[0x12] = RIVA_Set8Bits(vertDisplay);
93    pVga->CRTC[0x13] = ((pLayout->displayWidth/8)*(pLayout->bitsPerPixel/8));
94    pVga->CRTC[0x15] = RIVA_Set8Bits(vertBlankStart);
95    pVga->CRTC[0x16] = RIVA_Set8Bits(vertBlankEnd);
96
97    pVga->Attribute[0x10] = 0x01;
98
99    rivaReg->screen = RIVA_SetBitField(horizBlankEnd,6:6,4:4)
100                  | RIVA_SetBitField(vertBlankStart,10:10,3:3)
101                  | RIVA_SetBitField(vertStart,10:10,2:2)
102                  | RIVA_SetBitField(vertDisplay,10:10,1:1)
103                  | RIVA_SetBitField(vertTotal,10:10,0:0);
104
105    rivaReg->horiz  = RIVA_SetBitField(horizTotal,8:8,0:0)
106                  | RIVA_SetBitField(horizDisplay,8:8,1:1)
107                  | RIVA_SetBitField(horizBlankStart,8:8,2:2)
108                  | RIVA_SetBitField(horizStart,8:8,3:3);
109
110    rivaReg->extra  = RIVA_SetBitField(vertTotal,11:11,0:0)
111                    | RIVA_SetBitField(vertDisplay,11:11,2:2)
112                    | RIVA_SetBitField(vertStart,11:11,4:4)
113                    | RIVA_SetBitField(vertBlankStart,11:11,6:6);
114
115    if(mode->Flags & V_INTERLACE) {
116       horizTotal = (horizTotal >> 1) & ~1;
117       rivaReg->interlace = RIVA_Set8Bits(horizTotal);
118       rivaReg->horiz |= RIVA_SetBitField(horizTotal,8:8,4:4);
119    } else {
120       rivaReg->interlace = 0xff;  /* interlace off */
121    }
122
123    /*
124     * Initialize DAC palette.
125     */
126    if(pLayout->bitsPerPixel != 8 )
127    {
128        for (i = 0; i < 256; i++)
129        {
130            pVga->DAC[i*3]     = i;
131            pVga->DAC[(i*3)+1] = i;
132            pVga->DAC[(i*3)+2] = i;
133        }
134    }
135
136    /*
137     * Calculate the extended registers.
138     */
139
140    if(pLayout->depth < 24)
141	i = pLayout->depth;
142    else i = 32;
143
144    pRiva->riva.CalcStateExt(&pRiva->riva,
145                           rivaReg,
146                           i,
147                           pLayout->displayWidth,
148                           mode->CrtcHDisplay,
149                           pScrn->virtualY,
150                           mode->Clock,
151			   mode->Flags);
152
153    rivaReg->cursorConfig = 0x02000100;
154    if(mode->Flags & V_DBLSCAN)
155       rivaReg->cursorConfig |= (1 << 4);
156
157    return (TRUE);
158}
159
160void
161RivaDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, RivaRegPtr rivaReg,
162             Bool primary)
163{
164    RivaPtr pRiva = RivaPTR(pScrn);
165    int restore = VGA_SR_MODE;
166
167    restore |= primary ? (VGA_SR_CMAP | VGA_SR_FONTS) : VGA_SR_CMAP;
168    pRiva->riva.LoadStateExt(&pRiva->riva, rivaReg);
169    vgaHWRestore(pScrn, vgaReg, restore);
170}
171
172/*
173 * RivaDACSave
174 *
175 * This function saves the video state.
176 */
177void
178RivaDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, RivaRegPtr rivaReg,
179          Bool saveFonts)
180{
181    RivaPtr pRiva = RivaPTR(pScrn);
182
183    pRiva->riva.LockUnlock(&pRiva->riva, 0);
184
185    vgaHWSave(pScrn, vgaReg, VGA_SR_CMAP | VGA_SR_MODE |
186                             (saveFonts? VGA_SR_FONTS : 0));
187    pRiva->riva.UnloadStateExt(&pRiva->riva, rivaReg);
188}
189
190#define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
191#define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3)
192
193void
194RivaDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
195                 VisualPtr pVisual )
196{
197    int i, index;
198    RivaPtr pRiva = RivaPTR(pScrn);
199    vgaRegPtr   pVga;
200
201    pVga = &VGAHWPTR(pScrn)->ModeReg;
202
203    if(pRiva->CurrentLayout.depth != 8)
204           return;
205
206    for(i = 0; i < numColors; i++) {
207        index = indices[i];
208        pVga->DAC[index*3]     = colors[index].red;
209        pVga->DAC[(index*3)+1] = colors[index].green;
210        pVga->DAC[(index*3)+2] = colors[index].blue;
211    }
212    vgaHWRestore(pScrn, pVga, VGA_SR_CMAP);
213}
214
215/*
216 * DDC1 support only requires DDC_SDA_MASK,
217 * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
218 */
219#define DDC_SDA_READ_MASK  (1 << 3)
220#define DDC_SCL_READ_MASK  (1 << 2)
221#define DDC_SDA_WRITE_MASK (1 << 4)
222#define DDC_SCL_WRITE_MASK (1 << 5)
223
224static void
225Riva_I2CGetBits(I2CBusPtr b, int *clock, int *data)
226{
227#ifdef XF86_SCRN_INTERFACE
228    RivaPtr pRiva = RivaPTR(b->pScrn);
229#else
230    RivaPtr pRiva = RivaPTR(xf86Screens[b->scrnIndex]);
231#endif
232    unsigned char val;
233
234    /* Get the result. */
235    VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase);
236    val = VGA_RD08(pRiva->riva.PCIO, 0x3d5);
237
238    *clock = (val & DDC_SCL_READ_MASK) != 0;
239    *data  = (val & DDC_SDA_READ_MASK) != 0;
240}
241
242static void
243Riva_I2CPutBits(I2CBusPtr b, int clock, int data)
244{
245#ifdef XF86_SCRN_INTERFACE
246    RivaPtr pRiva = RivaPTR(b->pScrn);
247#else
248    RivaPtr pRiva = RivaPTR(xf86Screens[b->scrnIndex]);
249#endif
250    unsigned char val;
251
252    VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase + 1);
253    val = VGA_RD08(pRiva->riva.PCIO, 0x3d5) & 0xf0;
254    if (clock)
255        val |= DDC_SCL_WRITE_MASK;
256    else
257        val &= ~DDC_SCL_WRITE_MASK;
258
259    if (data)
260        val |= DDC_SDA_WRITE_MASK;
261    else
262        val &= ~DDC_SDA_WRITE_MASK;
263
264    VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase + 1);
265    VGA_WR08(pRiva->riva.PCIO, 0x3d5, val | 0x1);
266}
267
268Bool
269RivaDACi2cInit(ScrnInfoPtr pScrn)
270{
271    RivaPtr pRiva = RivaPTR(pScrn);
272    I2CBusPtr I2CPtr;
273
274    I2CPtr = xf86CreateI2CBusRec();
275    if(!I2CPtr) return FALSE;
276
277    pRiva->I2C = I2CPtr;
278
279    I2CPtr->BusName    = "DDC";
280    I2CPtr->scrnIndex  = pScrn->scrnIndex;
281#ifdef XF86_SCRN_INTERFACE
282    I2CPtr->pScrn = pScrn;
283#endif
284    I2CPtr->I2CPutBits = Riva_I2CPutBits;
285    I2CPtr->I2CGetBits = Riva_I2CGetBits;
286    I2CPtr->AcknTimeout = 5;
287
288    if (!xf86I2CBusInit(I2CPtr)) {
289        return FALSE;
290    }
291    return TRUE;
292}
293