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