mga_dh.c revision d2b10af6
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 */
77void 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 */
178void 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 */
215void 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 access 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
332void 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
366void 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*/
388void 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
422void 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