1 /*********************************************************************
2 * G450: This is for Dual Head.
3 * Matrox Graphics
4 * Author : Luugi Marsan
5 **********************************************************************/
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 /* All drivers should typically include these */
12 #include "xf86.h"
13 #include "xf86_OSproc.h"
14
15 /* Drivers that need to access the PCI config space directly need this */
16 #include "xf86Pci.h"
17
18 #include "mga_reg.h"
19 #include "mga.h"
20
21 #define MNP_TABLE_SIZE 64
22 #define CLKSEL_MGA 0x0c
23 #define PLLLOCK 0x40
24
25 /* Misc field*/
26 #define IOADDSEL 0x01
27 #define RAMMAPEN 0x02
28 #define CLKSEL_25175 0x00
29 #define CLKSEL_28322 0x04
30 #define CLKSEL_MGA 0x0c
31 #define VIDEODIS 0x10
32 #define HPGODDEV 0x20
33 #define HSYNCPOL 0x40
34 #define VSYNCPOL 0x80
35
36 /* XSYNCCTRL field */
37 #define XSYNCCTRL_DAC1HSPOL_SHIFT 2
38 #define XSYNCCTRL_DAC1HSPOL_MASK (1 << XSYNCCTRL_DAC1HSPOL_SHIFT)
39 #define XSYNCCTRL_DAC1HSPOL_NEG (1 << XSYNCCTRL_DAC1HSPOL_SHIFT)
40 #define XSYNCCTRL_DAC1HSPOL_POS 0
41 #define XSYNCCTRL_DAC1VSPOL_SHIFT 3
42 #define XSYNCCTRL_DAC1VSPOL_MASK (1 << XSYNCCTRL_DAC1VSPOL_SHIFT)
43 #define XSYNCCTRL_DAC1VSPOL_NEG (1 << XSYNCCTRL_DAC1VSPOL_SHIFT)
44 #define XSYNCCTRL_DAC1VSPOL_POS 0
45 #define XSYNCCTRL_DAC2HSPOL_SHIFT 6
46 #define XSYNCCTRL_DAC2HSPOL_MASK (1 << XSYNCCTRL_DAC2HSPOL_SHIFT)
47 #define XSYNCCTRL_DAC2HSPOL_NEG (1 << XSYNCCTRL_DAC2HSPOL_SHIFT)
48 #define XSYNCCTRL_DAC2HSPOL_POS 0
49 #define XSYNCCTRL_DAC2VSPOL_SHIFT 7
50 #define XSYNCCTRL_DAC2VSPOL_MASK (1 << XSYNCCTRL_DAC2VSPOL_SHIFT)
51 #define XSYNCCTRL_DAC2VSPOL_NEG (1 << XSYNCCTRL_DAC2VSPOL_SHIFT)
52 #define XSYNCCTRL_DAC2VSPOL_POS 0
53 #define XSYNCCTRL_DAC1HSOFF_SHIFT 0
54 #define XSYNCCTRL_DAC1HSOFF_MASK (1 << XSYNCCTRL_DAC1HSOFF_SHIFT)
55 #define XSYNCCTRL_DAC1HSOFF_OFF (1 << XSYNCCTRL_DAC1HSOFF_SHIFT)
56 #define XSYNCCTRL_DAC1HSOFF_ON 1
57 #define XSYNCCTRL_DAC1VSOFF_SHIFT 1
58 #define XSYNCCTRL_DAC1VSOFF_MASK (1 << XSYNCCTRL_DAC1VSOFF_SHIFT)
59 #define XSYNCCTRL_DAC1VSOFF_OFF (1 << XSYNCCTRL_DAC1VSOFF_SHIFT)
60 #define XSYNCCTRL_DAC1VSOFF_ON 0
61 #define XSYNCCTRL_DAC2HSOFF_SHIFT 4
62 #define XSYNCCTRL_DAC2HSOFF_MASK (1 << XSYNCCTRL_DAC2HSOFF_SHIFT)
63 #define XSYNCCTRL_DAC2HSOFF_OFF (1 << XSYNCCTRL_DAC2HSOFF_SHIFT)
64 #define XSYNCCTRL_DAC2HSOFF_ON 0
65 #define XSYNCCTRL_DAC2VSOFF_SHIFT 5
66 #define XSYNCCTRL_DAC2VSOFF_MASK (1 << XSYNCCTRL_DAC2VSOFF_SHIFT)
67 #define XSYNCCTRL_DAC2VSOFF_OFF (1 << XSYNCCTRL_DAC2VSOFF_SHIFT)
68 #define XSYNCCTRL_DAC2VSOFF_ON 0
69
70 #define POS_HSYNC 0x00000004
71 #define POS_VSYNC 0x00000008
72
73
74 /* Set CRTC 2*/
75 /* Uses the mode given by xfree86 to setup the registry */
76 /* Does not write to the hard yet */
MGACRTC2Get(ScrnInfoPtr pScrn,xMODEINFO * pModeInfo)77 void MGACRTC2Get(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo)
78 {
79
80
81 MGAPtr pMga = MGAPTR(pScrn);
82 MGARegPtr pReg = &pMga->ModeReg;
83
84 xMODEINFO tmpModeInfo;
85 CARD32 ulHTotal;
86 CARD32 ulHDispEnd;
87 CARD32 ulHBlkStr;
88 CARD32 ulHSyncStr;
89 CARD32 ulHSyncEnd;
90 CARD32 ulVTotal;
91 CARD32 ulVDispEnd;
92 CARD32 ulVBlkStr;
93 CARD32 ulVSyncStr;
94 CARD32 ulVSyncEnd;
95 CARD32 ulOffset;
96 CARD32 ulCtl2;
97 CARD32 ulDataCtl2;
98 CARD32 ulDispHeight = pModeInfo->ulDispHeight;
99
100 #ifdef DEBUG
101 ErrorF("ENTER MGACRTC2Get\n");
102 #endif
103
104 tmpModeInfo = *pModeInfo;
105
106
107 /* First compute the Values */
108
109 ulHTotal = tmpModeInfo.ulDispWidth +
110 tmpModeInfo.ulHFPorch +
111 tmpModeInfo.ulHBPorch +
112 tmpModeInfo.ulHSync;
113
114 ulHDispEnd = tmpModeInfo.ulDispWidth;
115 ulHBlkStr = ulHDispEnd;
116 ulHSyncStr = ulHBlkStr + tmpModeInfo.ulHFPorch;
117 ulHSyncEnd = ulHSyncStr + tmpModeInfo.ulHSync;
118
119 ulVTotal = ulDispHeight +
120 tmpModeInfo.ulVFPorch +
121 tmpModeInfo.ulVBPorch +
122 tmpModeInfo.ulVSync;
123
124
125 ulVDispEnd = ulDispHeight;
126 ulVBlkStr = ulVDispEnd;
127 ulVSyncStr = ulVBlkStr + tmpModeInfo.ulVFPorch;
128 ulVSyncEnd = ulVSyncStr + tmpModeInfo.ulVSync;
129
130 ulOffset = tmpModeInfo.ulFBPitch;
131
132
133
134 ulCtl2 = INREG(MGAREG_C2CTL);
135 ulDataCtl2 = INREG(MGAREG_C2DATACTL);
136
137 ulCtl2 &= 0xFF1FFFFF;
138 ulDataCtl2 &= 0xFFFFFF00;
139
140 switch (tmpModeInfo.ulBpp)
141 {
142 case 15: ulCtl2 |= 0x00200000;
143 ulOffset <<= 1;
144 break;
145 case 16: ulCtl2 |= 0x00400000;
146 ulOffset <<= 1;
147 break;
148 case 32: ulCtl2 |= 0x00800000;
149 ulOffset <<= 2;
150 break;
151 }
152
153
154 pReg->crtc2[ MGAREG2_C2CTL ] = ulCtl2;
155 pReg->crtc2[ MGAREG2_C2DATACTL ] = ulDataCtl2;
156
157 /* Horizontal Value*/
158 pReg->crtc2[MGAREG2_C2HPARAM] = (((ulHDispEnd-8) << 16) | (ulHTotal-8)) ;
159 pReg->crtc2[MGAREG2_C2HSYNC] = (((ulHSyncEnd-8) << 16) | (ulHSyncStr-8)) ;
160
161
162 /*Vertical Value*/
163 pReg->crtc2[MGAREG2_C2VPARAM] = (((ulVDispEnd-1) << 16) | (ulVTotal-1)) ;
164 pReg->crtc2[MGAREG2_C2VSYNC] = (((ulVSyncEnd-1) << 16) | (ulVSyncStr-1)) ;
165
166 /** Offset value*/
167
168 pReg->crtc2[MGAREG2_C2OFFSET] = ulOffset;
169
170 #ifdef DEBUG
171 ErrorF("EXIT MGACRTC2Get\n");
172 #endif
173
174 }
175
176 /* Set CRTC 2*/
177 /* Writes to the hardware */
MGACRTC2Set(ScrnInfoPtr pScrn,xMODEINFO * pModeInfo)178 void MGACRTC2Set(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo)
179 {
180
181
182 MGAPtr pMga = MGAPTR(pScrn);
183 MGARegPtr pReg = &pMga->ModeReg;
184
185 #ifdef DEBUG
186 ErrorF("ENTER MGACRTC2Set\n");
187 #endif
188
189
190 /* This writes to the registers manually */
191 OUTREG(MGAREG_C2CTL, pReg->crtc2[MGAREG2_C2CTL]);
192 OUTREG(MGAREG_C2DATACTL,pReg->crtc2[MGAREG2_C2DATACTL]);
193
194
195 /* Horizontal Value*/
196 OUTREG(MGAREG_C2HPARAM, pReg->crtc2[MGAREG2_C2HPARAM]);
197 OUTREG(MGAREG_C2HSYNC, pReg->crtc2[MGAREG2_C2HSYNC]);
198
199
200 /*Vertical Value*/
201 OUTREG(MGAREG_C2VPARAM, pReg->crtc2[MGAREG2_C2VPARAM]);
202 OUTREG(MGAREG_C2VSYNC, pReg->crtc2[MGAREG2_C2VSYNC]);
203
204 /** Offset value*/
205
206 OUTREG(MGAREG_C2OFFSET, pReg->crtc2[MGAREG2_C2OFFSET]);
207 #ifdef DEBUG
208 ErrorF("EXIT MGACRTC2Set\n");
209 #endif
210
211 }
212
213
214 /* Set CRTC2 on the right output */
MGAEnableSecondOutPut(ScrnInfoPtr pScrn,xMODEINFO * pModeInfo)215 void MGAEnableSecondOutPut(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo)
216 {
217 CARD8 ucByte, ucXDispCtrl;
218 CARD32 ulC2CTL;
219 MGAPtr pMga = MGAPTR(pScrn);
220 MGARegPtr pReg;
221 pReg = &pMga->ModeReg;
222 #ifdef DEBUG
223 ErrorF("ENTER MGAEnableSecondOutPut\n");
224 #endif
225
226
227 /* Route Video PLL on second CRTC */
228 ulC2CTL = INREG( MGAREG_C2CTL);
229
230 /*--- Disable Pixel clock oscillations On Crtc1 */
231 OUTREG( MGAREG_C2CTL, ulC2CTL | MGAREG_C2CTL_PIXCLKDIS_MASK);
232 /*--- Have to wait minimum time (2 acces will be ok) */
233 (void) INREG( MGAREG_Status);
234 (void) INREG( MGAREG_Status);
235
236
237 ulC2CTL &= ~MGAREG_C2CTL_PIXCLKSEL_MASK;
238 ulC2CTL &= ~MGAREG_C2CTL_PIXCLKSELH_MASK;
239
240 ulC2CTL |= MGAREG_C2CTL_PIXCLKSEL_VIDEOPLL;
241
242
243 OUTREG( MGAREG_C2CTL, ulC2CTL);
244
245 /*--- Enable Pixel clock oscillations on CRTC2*/
246 ulC2CTL &= ~MGAREG_C2CTL_PIXCLKDIS_MASK;
247 OUTREG( MGAREG_C2CTL, ulC2CTL);
248
249
250 /* We don't use MISC synch pol, must be 0*/
251 ucByte = INREG8( MGAREG_MEM_MISC_READ);
252
253 OUTREG8(MGAREG_MEM_MISC_WRITE, (CARD8)(ucByte & ~(HSYNCPOL| VSYNCPOL) ));
254
255
256
257
258 /* Set Rset to 0.7 V*/
259 ucByte = inMGAdac(MGA1064_GEN_IO_CTL);
260 ucByte &= ~0x40;
261 pReg->DacRegs[MGA1064_GEN_IO_CTL] = ucByte;
262 outMGAdac (MGA1064_GEN_IO_CTL, ucByte);
263
264 ucByte = inMGAdac( MGA1064_GEN_IO_DATA);
265 ucByte &= ~0x40;
266 pReg->DacRegs[MGA1064_GEN_IO_DATA]= ucByte;
267 outMGAdac (MGA1064_GEN_IO_DATA, ucByte);
268
269 /* Since G550 can swap outputs at BIOS initialisation, we must check which
270 * DAC is 'logically' used as the secondary (don't assume its DAC2 anymore) */
271
272 ulC2CTL = INREG(MGAREG_C2CTL);
273 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
274
275 ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
276
277 if (!pMga->SecondOutput) {
278 /* Route Crtc2 on Output1 */
279 ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
280 ulC2CTL |= MGAREG_C2CTL_CRTCDACSEL_CRTC2;
281 }
282 else {
283 /* Route Crtc2 on Output2*/
284 ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC2;
285 ulC2CTL &= ~MGAREG_C2CTL_CRTCDACSEL_MASK;
286 }
287
288 /* Enable CRTC2*/
289 ulC2CTL |= MGAREG_C2CTL_C2_EN;
290
291 pReg->dac2[ MGA1064_DISP_CTL - 0x80] = ucXDispCtrl;
292
293
294
295 OUTREG( MGAREG_C2CTL, ulC2CTL);
296
297 /* Set DAC2 Synch polarity*/
298 ucByte = inMGAdac( MGA1064_SYNC_CTL);
299 ucByte &= ~(XSYNCCTRL_DAC2HSPOL_MASK | XSYNCCTRL_DAC2VSPOL_MASK);
300 if ( !(pModeInfo->flSignalMode & POS_HSYNC) )
301 {
302 ucByte |= XSYNCCTRL_DAC2HSPOL_NEG;
303 }
304 if ( !(pModeInfo->flSignalMode & POS_VSYNC) )
305 {
306 ucByte |= XSYNCCTRL_DAC2VSPOL_NEG;
307 }
308
309 /* Enable synch output*/
310 ucByte &= ~(XSYNCCTRL_DAC2HSOFF_MASK | XSYNCCTRL_DAC2VSOFF_MASK);
311 pReg->dac2[ MGA1064_SYNC_CTL - 0x80] = ucByte;
312
313 /* Power up DAC2, Fifo.
314 * The TMDS is powered down here, which is likely wrong.
315 */
316 pReg->dac2[MGA1064_PWR_CTL - 0x80] =
317 MGA1064_PWR_CTL_DAC2_EN |
318 MGA1064_PWR_CTL_VID_PLL_EN |
319 MGA1064_PWR_CTL_RFIFO_EN |
320 MGA1064_PWR_CTL_CFIFO_EN;
321
322
323 #ifdef DEBUG
324 ErrorF("EXIT MGAEnableSecondOutPut\n");
325 #endif
326 }
327
328
329
330
331
MGACRTC2GetPitch(ScrnInfoPtr pScrn,xMODEINFO * pModeInfo)332 void MGACRTC2GetPitch (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo)
333 {
334 CARD32 ulOffset;
335 MGAPtr pMga = MGAPTR(pScrn);
336 MGARegPtr pReg;
337
338 pReg = &pMga->ModeReg;
339 #ifdef DEBUG
340 ErrorF("ENTER MGACRTC2GetPitch\n");
341 #endif
342
343
344 switch(pModeInfo->ulBpp)
345 {
346 case 15:
347 case 16:
348 ulOffset = pModeInfo->ulFBPitch * 2;
349 break;
350 case 32:
351 ulOffset = pModeInfo->ulFBPitch * 4;
352 break;
353 default: /* Muffle compiler */
354 ulOffset = pModeInfo->ulFBPitch;
355 break;
356 }
357
358 pReg->crtc2[MGAREG2_C2OFFSET] = ulOffset;
359
360 #ifdef DEBUG
361 ErrorF("EXIT MGACRTC2GetPitch\n");
362 #endif
363
364 }
365
MGACRTC2SetPitch(ScrnInfoPtr pScrn,xMODEINFO * pModeInfo)366 void MGACRTC2SetPitch (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo)
367 {
368
369 MGAPtr pMga = MGAPTR(pScrn);
370 MGARegPtr pReg;
371 pReg = &pMga->ModeReg;
372
373 #ifdef DEBUG
374 ErrorF("ENTER CRCT2SetPitch\n");
375 #endif
376
377
378 OUTREG(MGAREG_C2OFFSET, pReg->crtc2[MGAREG2_C2OFFSET]);
379 #ifdef DEBUG
380 ErrorF("EXIT CRCT2SetPitch\n");
381 #endif
382
383 }
384
385
386 /* Set Display Start*/
387 /* base in bytes*/
MGACRTC2GetDisplayStart(ScrnInfoPtr pScrn,xMODEINFO * pModeInfo,CARD32 base,CARD32 ulX,CARD32 ulY)388 void MGACRTC2GetDisplayStart (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo, CARD32 base, CARD32 ulX, CARD32 ulY)
389 {
390
391 CARD32 ulAddress;
392 MGAPtr pMga = MGAPTR(pScrn);
393 MGARegPtr pReg;
394 pReg = &pMga->ModeReg;
395
396 #ifdef DEBUG
397 ErrorF("ENTER MGACRTC2GetDisplayStart\n");
398 #endif
399
400
401 pReg = &pMga->ModeReg;
402
403 ulAddress = (pModeInfo->ulFBPitch * ulY + ulX);
404 switch(pModeInfo->ulBpp)
405 {
406 case 15:
407 case 16:
408 ulAddress <<= 1;
409 break;
410 case 32:
411 ulAddress <<= 2;
412 break;
413 }
414
415 pReg->crtc2[MGAREG2_C2STARTADD0] = ulAddress + base;
416 #ifdef DEBUG
417 ErrorF("EXIT MGACRTC2GetDisplayStart\n");
418 #endif
419
420 }
421
MGACRTC2SetDisplayStart(ScrnInfoPtr pScrn,xMODEINFO * pModeInfo,CARD32 base,CARD32 ulX,CARD32 ulY)422 void MGACRTC2SetDisplayStart (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo, CARD32 base, CARD32 ulX, CARD32 ulY)
423 {
424 MGAPtr pMga = MGAPTR(pScrn);
425 MGARegPtr pReg;
426 pReg = &pMga->ModeReg;
427 #ifdef DEBUG
428 ErrorF("ENTER MGACRTC2SetDisplayStart\n");
429 #endif
430
431 OUTREG(MGAREG_C2STARTADD0, pReg->crtc2[MGAREG2_C2STARTADD0]);
432 #ifdef DEBUG
433 ErrorF("EXIT MGACRTC2SetDisplayStart\n");
434 #endif
435
436 }
437
438
439
440
441
442
443
444
445
446
447
448