Merge branch 'randr-1.2' into nv50-branch
[nouveau] / src / riva_dac.c
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 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_dac.c,v 1.1 2003/07/31 20:24:29 mvojkovi Exp $ */
27
28 #include "riva_include.h"
29
30 Bool
31 RivaDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
32 {
33     int i;
34     int horizDisplay    = (mode->CrtcHDisplay/8)   - 1;
35     int horizStart      = (mode->CrtcHSyncStart/8) - 1;
36     int horizEnd        = (mode->CrtcHSyncEnd/8)   - 1;
37     int horizTotal      = (mode->CrtcHTotal/8)     - 5;
38     int horizBlankStart = (mode->CrtcHDisplay/8)   - 1;
39     int horizBlankEnd   = (mode->CrtcHTotal/8)     - 1;
40     int vertDisplay     =  mode->CrtcVDisplay      - 1;
41     int vertStart       =  mode->CrtcVSyncStart    - 1;
42     int vertEnd         =  mode->CrtcVSyncEnd      - 1;
43     int vertTotal       =  mode->CrtcVTotal        - 2;
44     int vertBlankStart  =  mode->CrtcVDisplay      - 1;
45     int vertBlankEnd    =  mode->CrtcVTotal        - 1;
46    
47
48     RivaPtr pRiva = RivaPTR(pScrn);
49     RivaRegPtr rivaReg = &pRiva->ModeReg;
50     RivaFBLayout *pLayout = &pRiva->CurrentLayout;
51     vgaRegPtr   pVga;
52
53     /*
54      * This will initialize all of the generic VGA registers.
55      */
56     if (!vgaHWInit(pScrn, mode))
57         return(FALSE);
58
59     pVga = &VGAHWPTR(pScrn)->ModeReg;
60
61     /*
62      * Set all CRTC values.
63      */
64
65     if(mode->Flags & V_INTERLACE) 
66         vertTotal |= 1;
67
68     pVga->CRTC[0x0]  = Set8Bits(horizTotal);
69     pVga->CRTC[0x1]  = Set8Bits(horizDisplay);
70     pVga->CRTC[0x2]  = Set8Bits(horizBlankStart);
71     pVga->CRTC[0x3]  = SetBitField(horizBlankEnd,4:0,4:0) 
72                        | SetBit(7);
73     pVga->CRTC[0x4]  = Set8Bits(horizStart);
74     pVga->CRTC[0x5]  = SetBitField(horizBlankEnd,5:5,7:7)
75                        | SetBitField(horizEnd,4:0,4:0);
76     pVga->CRTC[0x6]  = SetBitField(vertTotal,7:0,7:0);
77     pVga->CRTC[0x7]  = SetBitField(vertTotal,8:8,0:0)
78                        | SetBitField(vertDisplay,8:8,1:1)
79                        | SetBitField(vertStart,8:8,2:2)
80                        | SetBitField(vertBlankStart,8:8,3:3)
81                        | SetBit(4)
82                        | SetBitField(vertTotal,9:9,5:5)
83                        | SetBitField(vertDisplay,9:9,6:6)
84                        | SetBitField(vertStart,9:9,7:7);
85     pVga->CRTC[0x9]  = SetBitField(vertBlankStart,9:9,5:5)
86                        | SetBit(6)
87                        | ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00);
88     pVga->CRTC[0x10] = Set8Bits(vertStart);
89     pVga->CRTC[0x11] = SetBitField(vertEnd,3:0,3:0) | SetBit(5);
90     pVga->CRTC[0x12] = Set8Bits(vertDisplay);
91     pVga->CRTC[0x13] = ((pLayout->displayWidth/8)*(pLayout->bitsPerPixel/8));
92     pVga->CRTC[0x15] = Set8Bits(vertBlankStart);
93     pVga->CRTC[0x16] = Set8Bits(vertBlankEnd);
94
95     pVga->Attribute[0x10] = 0x01;
96
97     rivaReg->screen = SetBitField(horizBlankEnd,6:6,4:4)
98                   | SetBitField(vertBlankStart,10:10,3:3)
99                   | SetBitField(vertStart,10:10,2:2)
100                   | SetBitField(vertDisplay,10:10,1:1)
101                   | SetBitField(vertTotal,10:10,0:0);
102
103     rivaReg->horiz  = SetBitField(horizTotal,8:8,0:0) 
104                   | SetBitField(horizDisplay,8:8,1:1)
105                   | SetBitField(horizBlankStart,8:8,2:2)
106                   | SetBitField(horizStart,8:8,3:3);
107
108     rivaReg->extra  = SetBitField(vertTotal,11:11,0:0)
109                     | SetBitField(vertDisplay,11:11,2:2)
110                     | SetBitField(vertStart,11:11,4:4)
111                     | SetBitField(vertBlankStart,11:11,6:6);
112
113     if(mode->Flags & V_INTERLACE) {
114        horizTotal = (horizTotal >> 1) & ~1;
115        rivaReg->interlace = Set8Bits(horizTotal);
116        rivaReg->horiz |= SetBitField(horizTotal,8:8,4:4);
117     } else {
118        rivaReg->interlace = 0xff;  /* interlace off */
119     }
120
121     /*
122      * Initialize DAC palette.
123      */
124     if(pLayout->bitsPerPixel != 8 )
125     {
126         for (i = 0; i < 256; i++)
127         {
128             pVga->DAC[i*3]     = i;
129             pVga->DAC[(i*3)+1] = i;
130             pVga->DAC[(i*3)+2] = i;
131         }
132     }
133     
134     /*
135      * Calculate the extended registers.
136      */
137
138     if(pLayout->depth < 24) 
139         i = pLayout->depth;
140     else i = 32;
141
142     pRiva->riva.CalcStateExt(&pRiva->riva, 
143                            rivaReg,
144                            i,
145                            pLayout->displayWidth,
146                            mode->CrtcHDisplay,
147                            pScrn->virtualY,
148                            mode->Clock,
149                            mode->Flags);
150
151     rivaReg->cursorConfig = 0x02000100;
152     if(mode->Flags & V_DBLSCAN)
153        rivaReg->cursorConfig |= (1 << 4);
154
155     return (TRUE);
156 }
157
158 void 
159 RivaDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, RivaRegPtr rivaReg,
160              Bool primary)
161 {
162     RivaPtr pRiva = RivaPTR(pScrn);
163     int restore = VGA_SR_MODE;
164
165     restore |= primary ? (VGA_SR_CMAP | VGA_SR_FONTS) : VGA_SR_CMAP;
166     pRiva->riva.LoadStateExt(&pRiva->riva, rivaReg);
167     vgaHWRestore(pScrn, vgaReg, restore);
168 }
169
170 /*
171  * RivaDACSave
172  *
173  * This function saves the video state.
174  */
175 void
176 RivaDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, RivaRegPtr rivaReg,
177           Bool saveFonts)
178 {
179     RivaPtr pRiva = RivaPTR(pScrn);
180
181     pRiva->riva.LockUnlock(&pRiva->riva, 0);
182
183     vgaHWSave(pScrn, vgaReg, VGA_SR_CMAP | VGA_SR_MODE | 
184                              (saveFonts? VGA_SR_FONTS : 0));
185     pRiva->riva.UnloadStateExt(&pRiva->riva, rivaReg);
186 }
187
188 #define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
189 #define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3)
190
191 void
192 RivaDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
193                  VisualPtr pVisual )
194 {
195     int i, index;
196     RivaPtr pRiva = RivaPTR(pScrn);
197     vgaRegPtr   pVga;
198
199     pVga = &VGAHWPTR(pScrn)->ModeReg;
200
201     if(pRiva->CurrentLayout.depth != 8)
202            return;
203
204     for(i = 0; i < numColors; i++) {
205         index = indices[i];
206         pVga->DAC[index*3]     = colors[index].red;
207         pVga->DAC[(index*3)+1] = colors[index].green;
208         pVga->DAC[(index*3)+2] = colors[index].blue;
209     }
210     vgaHWRestore(pScrn, pVga, VGA_SR_CMAP);
211 }
212
213 /*
214  * DDC1 support only requires DDC_SDA_MASK,
215  * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
216  */
217 #define DDC_SDA_READ_MASK  (1 << 3)
218 #define DDC_SCL_READ_MASK  (1 << 2)
219 #define DDC_SDA_WRITE_MASK (1 << 4)
220 #define DDC_SCL_WRITE_MASK (1 << 5)
221
222 static void
223 Riva_I2CGetBits(I2CBusPtr b, int *clock, int *data)
224 {
225     RivaPtr pRiva = RivaPTR(xf86Screens[b->scrnIndex]);
226     unsigned char val;
227
228     /* Get the result. */
229     VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase);
230     val = VGA_RD08(pRiva->riva.PCIO, 0x3d5);
231
232     *clock = (val & DDC_SCL_READ_MASK) != 0;
233     *data  = (val & DDC_SDA_READ_MASK) != 0;
234 }
235
236 static void
237 Riva_I2CPutBits(I2CBusPtr b, int clock, int data)
238 {
239     RivaPtr pRiva = RivaPTR(xf86Screens[b->scrnIndex]);
240     unsigned char val;
241
242     VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase + 1);
243     val = VGA_RD08(pRiva->riva.PCIO, 0x3d5) & 0xf0;
244     if (clock)
245         val |= DDC_SCL_WRITE_MASK;
246     else
247         val &= ~DDC_SCL_WRITE_MASK;
248
249     if (data)
250         val |= DDC_SDA_WRITE_MASK;
251     else
252         val &= ~DDC_SDA_WRITE_MASK;
253
254     VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase + 1);
255     VGA_WR08(pRiva->riva.PCIO, 0x3d5, val | 0x1);
256 }
257
258 Bool
259 RivaDACi2cInit(ScrnInfoPtr pScrn)
260 {
261     RivaPtr pRiva = RivaPTR(pScrn);
262     I2CBusPtr I2CPtr;
263
264     I2CPtr = xf86CreateI2CBusRec();
265     if(!I2CPtr) return FALSE;
266
267     pRiva->I2C = I2CPtr;
268
269     I2CPtr->BusName    = "DDC";
270     I2CPtr->scrnIndex  = pScrn->scrnIndex;
271     I2CPtr->I2CPutBits = Riva_I2CPutBits;
272     I2CPtr->I2CGetBits = Riva_I2CGetBits;
273     I2CPtr->AcknTimeout = 5;
274
275     if (!xf86I2CBusInit(I2CPtr)) {
276         return FALSE;
277     }
278     return TRUE;
279 }
280