1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/via/via_dri.c,v 1.4 2003/09/24 02:43:30 dawes Exp $ */
3 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
4 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sub license,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
36 typedef int Bool
; /* via_dri.h makes use of this */
40 #include "via_context.h"
42 #include "via_driver.h"
43 #include "via_common.h"
46 static void VIAEnableMMIO(DRIDriverContext
* ctx
);
47 static void VIADisableMMIO(DRIDriverContext
* ctx
);
48 static void VIADisableExtendedFIFO(DRIDriverContext
*ctx
);
49 static void VIAEnableExtendedFIFO(DRIDriverContext
*ctx
);
50 static void VIAInitialize2DEngine(DRIDriverContext
*ctx
);
51 static void VIAInitialize3DEngine(DRIDriverContext
*ctx
);
53 static int VIADRIScreenInit(DRIDriverContext
* ctx
);
54 static void VIADRICloseScreen(DRIDriverContext
* ctx
);
55 static int VIADRIFinishScreenInit(DRIDriverContext
* ctx
);
57 /* _SOLO : missing macros normally defined by X code */
58 #define xf86DrvMsg(a, b, ...) fprintf(stderr, __VA_ARGS__)
59 #define MMIO_IN8(base, addr) ((*(((volatile u_int8_t*)base)+(addr)))+0)
60 #define MMIO_OUT8(base, addr, val) ((*(((volatile u_int8_t*)base)+(addr)))=((u_int8_t)val))
61 #define MMIO_OUT16(base, addr, val) ((*(volatile u_int16_t*)(((u_int8_t*)base)+(addr)))=((u_int16_t)val))
65 #define AGP_PAGE_SIZE 4096
66 #define AGP_PAGES 8192
67 #define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES)
68 #define AGP_CMDBUF_PAGES 512
69 #define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES)
71 static char VIAKernelDriverName
[] = "via";
72 static char VIAClientDriverName
[] = "unichrome";
74 static int VIADRIAgpInit(const DRIDriverContext
*ctx
, VIAPtr pVia
);
75 static int VIADRIPciInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
76 static int VIADRIFBInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
77 static int VIADRIKernelInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
78 static int VIADRIMapInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
80 static void VIADRIIrqInit( DRIDriverContext
*ctx
)
82 VIAPtr pVia
= VIAPTR(ctx
);
83 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
85 pVIADRI
->irqEnabled
= drmGetInterruptFromBusID(pVia
->drmFD
,
90 if ((drmCtlInstHandler(pVia
->drmFD
, pVIADRI
->irqEnabled
))) {
91 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
92 "[drm] Failure adding irq handler. "
93 "Falling back to irq-free operation.\n");
94 pVIADRI
->irqEnabled
= 0;
97 if (pVIADRI
->irqEnabled
)
98 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
99 "[drm] Irq handler installed, using IRQ %d.\n",
100 pVIADRI
->irqEnabled
);
103 static void VIADRIIrqExit( DRIDriverContext
*ctx
) {
104 VIAPtr pVia
= VIAPTR(ctx
);
105 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
107 if (pVIADRI
->irqEnabled
) {
108 if (drmCtlUninstHandler(pVia
->drmFD
)) {
109 xf86DrvMsg(pScreen
-myNum
, X_INFO
,"[drm] Irq handler uninstalled.\n");
111 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
112 "[drm] Could not uninstall irq handler.\n");
117 static void VIADRIRingBufferCleanup(DRIDriverContext
*ctx
)
119 VIAPtr pVia
= VIAPTR(ctx
);
120 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
121 drm_via_dma_init_t ringBufInit
;
123 if (pVIADRI
->ringBufActive
) {
124 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
125 "[drm] Cleaning up DMA ring-buffer.\n");
126 ringBufInit
.func
= VIA_CLEANUP_DMA
;
127 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_DMA_INIT
, &ringBufInit
,
128 sizeof(ringBufInit
))) {
129 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
130 "[drm] Failed to clean up DMA ring-buffer: %d\n", errno
);
132 pVIADRI
->ringBufActive
= 0;
136 static int VIADRIRingBufferInit(DRIDriverContext
*ctx
)
138 VIAPtr pVia
= VIAPTR(ctx
);
139 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
140 drm_via_dma_init_t ringBufInit
;
141 drmVersionPtr drmVer
;
143 pVIADRI
->ringBufActive
= 0;
145 if (NULL
== (drmVer
= drmGetVersion(pVia
->drmFD
))) {
149 if (((drmVer
->version_major
<= 1) && (drmVer
->version_minor
<= 3))) {
154 * Info frome code-snippet on DRI-DEVEL list; Erdi Chen.
157 switch (pVia
->ChipId
) {
158 case PCI_CHIP_VT3259
:
159 ringBufInit
.reg_pause_addr
= 0x40c;
162 ringBufInit
.reg_pause_addr
= 0x418;
166 ringBufInit
.offset
= pVia
->agpSize
;
167 ringBufInit
.size
= AGP_CMDBUF_SIZE
;
168 ringBufInit
.func
= VIA_INIT_DMA
;
169 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_DMA_INIT
, &ringBufInit
,
170 sizeof(ringBufInit
))) {
171 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
172 "[drm] Failed to initialize DMA ring-buffer: %d\n", errno
);
175 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
176 "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP offset 0x%lx.\n",
177 ringBufInit
.size
, ringBufInit
.offset
);
179 pVIADRI
->ringBufActive
= 1;
183 static int VIADRIAgpInit(const DRIDriverContext
*ctx
, VIAPtr pVia
)
185 unsigned long agp_phys
;
188 pVIADRI
= pVia
->devPrivate
;
191 if (drmAgpAcquire(pVia
->drmFD
) < 0) {
192 xf86DrvMsg(pScreen
->myNum
, X_ERROR
, "[drm] drmAgpAcquire failed %d\n", errno
);
196 if (drmAgpEnable(pVia
->drmFD
, drmAgpGetMode(pVia
->drmFD
)&~0x0) < 0) {
197 xf86DrvMsg(pScreen
->myNum
, X_ERROR
, "[drm] drmAgpEnable failed\n");
201 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] drmAgpEnabled succeeded\n");
203 if (drmAgpAlloc(pVia
->drmFD
, AGP_SIZE
, 0, &agp_phys
, &pVia
->agpHandle
) < 0) {
204 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
205 "[drm] drmAgpAlloc failed\n");
206 drmAgpRelease(pVia
->drmFD
);
210 if (drmAgpBind(pVia
->drmFD
, pVia
->agpHandle
, 0) < 0) {
211 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
212 "[drm] drmAgpBind failed\n");
213 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
214 drmAgpRelease(pVia
->drmFD
);
220 * Place the ring-buffer last in the AGP region, and restrict the
221 * public map not to include the buffer for security reasons.
224 pVia
->agpSize
= AGP_SIZE
- AGP_CMDBUF_SIZE
;
225 pVia
->agpAddr
= drmAgpBase(pVia
->drmFD
);
226 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
227 "[drm] agpAddr = 0x%08lx\n",pVia
->agpAddr
);
229 pVIADRI
->agp
.size
= pVia
->agpSize
;
230 if (drmAddMap(pVia
->drmFD
, (drm_handle_t
)0,
231 pVIADRI
->agp
.size
, DRM_AGP
, 0,
232 &pVIADRI
->agp
.handle
) < 0) {
233 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
234 "[drm] Failed to map public agp area\n");
235 pVIADRI
->agp
.size
= 0;
238 /* Map AGP from kernel to Xserver - Not really needed */
239 drmMap(pVia
->drmFD
, pVIADRI
->agp
.handle
,pVIADRI
->agp
.size
, &agpaddr
);
241 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
242 "[drm] agpAddr = 0x%08lx\n", pVia
->agpAddr
);
243 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
244 "[drm] agpSize = 0x%08lx\n", pVia
->agpSize
);
245 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
246 "[drm] agp physical addr = 0x%08lx\n", agp_phys
);
251 agp
.size
= AGP_SIZE
-AGP_CMDBUF_SIZE
;
252 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_AGP_INIT
, &agp
,
253 sizeof(drm_via_agp_t
)) < 0) {
254 drmUnmap(&agpaddr
,pVia
->agpSize
);
255 drmRmMap(pVia
->drmFD
,pVIADRI
->agp
.handle
);
256 drmAgpUnbind(pVia
->drmFD
, pVia
->agpHandle
);
257 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
258 drmAgpRelease(pVia
->drmFD
);
266 static int VIADRIFBInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
268 int FBSize
= pVia
->FBFreeEnd
-pVia
->FBFreeStart
;
269 int FBOffset
= pVia
->FBFreeStart
;
270 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
271 pVIADRI
->fbOffset
= FBOffset
;
272 pVIADRI
->fbSize
= pVia
->videoRambytes
;
276 fb
.offset
= FBOffset
;
279 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_FB_INIT
, &fb
,
280 sizeof(drm_via_fb_t
)) < 0) {
281 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
282 "[drm] failed to init frame buffer area\n");
285 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
286 "[drm] FBFreeStart= 0x%08x FBFreeEnd= 0x%08x "
288 pVia
->FBFreeStart
, pVia
->FBFreeEnd
, FBSize
);
294 static int VIADRIPciInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
299 static int VIADRIScreenInit(DRIDriverContext
* ctx
)
301 VIAPtr pVia
= VIAPTR(ctx
);
306 ctx
->shared
.SAREASize
= ((sizeof(drm_sarea_t
) + 0xfff) & 0x1000);
308 if (sizeof(drm_sarea_t
)+sizeof(drm_via_sarea_t
) > SAREA_MAX
) {
309 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
310 "Data does not fit in SAREA\n");
313 ctx
->shared
.SAREASize
= SAREA_MAX
;
316 ctx
->drmFD
= drmOpen(VIAKernelDriverName
, NULL
);
317 if (ctx
->drmFD
< 0) {
318 fprintf(stderr
, "[drm] drmOpen failed\n");
321 pVia
->drmFD
= ctx
->drmFD
;
323 err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
);
325 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
326 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
330 err
= drmAddMap(ctx
->drmFD
, 0, ctx
->shared
.SAREASize
, DRM_SHM
,
331 DRM_CONTAINS_LOCK
, &ctx
->shared
.hSAREA
);
333 fprintf(stderr
, "[drm] drmAddMap failed\n");
336 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
337 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
339 if (drmMap(ctx
->drmFD
,
341 ctx
->shared
.SAREASize
,
342 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
344 fprintf(stderr
, "[drm] drmMap failed\n");
347 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
348 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
349 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
351 /* Need to AddMap the framebuffer and mmio regions here:
353 if (drmAddMap(ctx
->drmFD
,
354 (drm_handle_t
)ctx
->FBStart
,
362 &ctx
->shared
.hFrameBuffer
) < 0)
364 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
368 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
369 ctx
->shared
.hFrameBuffer
);
371 pVIADRI
= (VIADRIPtr
) CALLOC(sizeof(VIADRIRec
));
373 drmClose(ctx
->drmFD
);
376 pVia
->devPrivate
= pVIADRI
;
377 ctx
->driverClientMsg
= pVIADRI
;
378 ctx
->driverClientMsgSize
= sizeof(*pVIADRI
);
380 /* DRIScreenInit doesn't add all the common mappings. Add additional mappings here. */
381 if (!VIADRIMapInit(ctx
, pVia
)) {
382 VIADRICloseScreen(ctx
);
386 pVIADRI
->regs
.size
= VIA_MMIO_REGSIZE
;
387 pVIADRI
->regs
.map
= 0;
388 pVIADRI
->regs
.handle
= pVia
->registerHandle
;
389 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] mmio Registers = 0x%08lx\n",
390 pVIADRI
->regs
.handle
);
392 if (drmMap(pVia
->drmFD
,
393 pVIADRI
->regs
.handle
,
395 (drmAddress
*)&pVia
->MapBase
) != 0)
397 VIADRICloseScreen(ctx
);
401 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] mmio mapped.\n" );
405 /* Get video memory clock. */
406 VGAOUT8(0x3D4, 0x3D);
407 pVia
->MemClk
= (VGAIN8(0x3D5) & 0xF0) >> 4;
408 xf86DrvMsg(0, X_INFO
, "[dri] MemClk (0x%x)\n", pVia
->MemClk
);
410 /* 3D rendering has noise if not enabled. */
411 VIAEnableExtendedFIFO(ctx
);
413 VIAInitialize2DEngine(ctx
);
415 /* Must disable MMIO or 3D won't work. */
418 VIAInitialize3DEngine(ctx
);
420 pVia
->IsPCI
= !VIADRIAgpInit(ctx
, pVia
);
423 VIADRIPciInit(ctx
, pVia
);
424 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] use pci.\n" );
427 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] use agp.\n" );
429 if (!(VIADRIFBInit(ctx
, pVia
))) {
430 VIADRICloseScreen(ctx
);
431 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "[dri] frame buffer initialize fail .\n" );
435 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] frame buffer initialized.\n" );
437 return VIADRIFinishScreenInit(ctx
);
441 VIADRICloseScreen(DRIDriverContext
* ctx
)
443 VIAPtr pVia
= VIAPTR(ctx
);
444 VIADRIPtr pVIADRI
=(VIADRIPtr
)pVia
->devPrivate
;
446 VIADRIRingBufferCleanup(ctx
);
449 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Unmapping MMIO registers\n");
450 drmUnmap(pVia
->MapBase
, pVIADRI
->regs
.size
);
454 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Freeing agp memory\n");
455 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
456 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Releasing agp module\n");
457 drmAgpRelease(pVia
->drmFD
);
461 if (pVia
->DRIIrqEnable
)
467 VIADRIFinishScreenInit(DRIDriverContext
* ctx
)
469 VIAPtr pVia
= VIAPTR(ctx
);
473 err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
);
475 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
479 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
482 if (!VIADRIKernelInit(ctx
, pVia
)) {
483 VIADRICloseScreen(ctx
);
486 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[dri] kernel data initialized.\n");
488 /* set SAREA value */
490 drm_via_sarea_t
*saPriv
;
492 saPriv
=(drm_via_sarea_t
*)(((char*)ctx
->pSAREA
) +
493 sizeof(drm_sarea_t
));
495 memset(saPriv
, 0, sizeof(*saPriv
));
496 saPriv
->ctxOwner
= -1;
498 pVIADRI
=(VIADRIPtr
)pVia
->devPrivate
;
499 pVIADRI
->deviceID
=pVia
->Chipset
;
500 pVIADRI
->width
=ctx
->shared
.virtualWidth
;
501 pVIADRI
->height
=ctx
->shared
.virtualHeight
;
502 pVIADRI
->mem
=ctx
->shared
.fbSize
;
503 pVIADRI
->bytesPerPixel
= (ctx
->bpp
+7) / 8;
504 pVIADRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
506 pVIADRI
->scrnX
=pVIADRI
->width
;
507 pVIADRI
->scrnY
=pVIADRI
->height
;
511 if (pVia
->DRIIrqEnable
)
515 pVIADRI
->ringBufActive
= 0;
516 VIADRIRingBufferInit(ctx
);
521 /* Initialize the kernel data structures. */
522 static int VIADRIKernelInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
524 drm_via_init_t drmInfo
;
525 memset(&drmInfo
, 0, sizeof(drm_via_init_t
));
526 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
527 drmInfo
.func
= VIA_INIT_MAP
;
528 drmInfo
.fb_offset
= pVia
->FrameBufferBase
;
529 drmInfo
.mmio_offset
= pVia
->registerHandle
;
531 drmInfo
.agpAddr
= (u_int32_t
)NULL
;
533 drmInfo
.agpAddr
= (u_int32_t
)pVia
->agpAddr
;
535 if ((drmCommandWrite(pVia
->drmFD
, DRM_VIA_MAP_INIT
,&drmInfo
,
536 sizeof(drm_via_init_t
))) < 0)
541 /* Add a map for the MMIO registers */
542 static int VIADRIMapInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
546 if (drmAddMap(pVia
->drmFD
, pVia
->MmioBase
, VIA_MMIO_REGSIZE
,
547 DRM_REGISTERS
, flags
, &pVia
->registerHandle
) < 0) {
551 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
552 "[drm] register handle = 0x%08lx\n", pVia
->registerHandle
);
557 static int viaValidateMode(const DRIDriverContext
*ctx
)
559 VIAPtr pVia
= VIAPTR(ctx
);
564 static int viaPostValidateMode(const DRIDriverContext
*ctx
)
566 VIAPtr pVia
= VIAPTR(ctx
);
571 static void VIAEnableMMIO(DRIDriverContext
* ctx
)
573 /*vgaHWPtr hwp = VGAHWPTR(ctx);*/
574 VIAPtr pVia
= VIAPTR(ctx
);
578 if (xf86IsPrimaryPci(pVia
->PciInfo
)) {
579 /* If we are primary card, we still use std vga port. If we use
580 * MMIO, system will hang in vgaHWSave when our card used in
581 * PLE and KLE (integrated Trident MVP4)
583 vgaHWSetStdFuncs(hwp
);
586 vgaHWSetMmioFuncs(hwp
, pVia
->MapBase
, 0x8000);
591 VGAOUT8(0x3c3, val
| 0x01);
593 VGAOUT8(0x3c2, val
| 0x01);
595 /* Unlock Extended IO Space */
596 VGAOUT8(0x3c4, 0x10);
597 VGAOUT8(0x3c5, 0x01);
600 if(!pVia
->IsSecondary
) {
601 VGAOUT8(0x3c4, 0x1a);
604 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "primary val = %x\n", val
);
606 VGAOUT8(0x3c5, val
| 0x68);
609 VGAOUT8(0x3c4, 0x1a);
612 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "secondary val = %x\n", val
);
614 VGAOUT8(0x3c5, val
| 0x38);
617 /* Unlock CRTC registers */
618 VGAOUT8(0x3d4, 0x47);
619 VGAOUT8(0x3d5, 0x00);
624 static void VIADisableMMIO(DRIDriverContext
* ctx
)
626 VIAPtr pVia
= VIAPTR(ctx
);
629 VGAOUT8(0x3c4, 0x1a);
631 VGAOUT8(0x3c5, val
& 0x97);
636 static void VIADisableExtendedFIFO(DRIDriverContext
*ctx
)
638 VIAPtr pVia
= VIAPTR(ctx
);
639 u_int32_t dwGE230
, dwGE298
;
641 /* Cause of exit XWindow will dump back register value, others chipset no
642 * need to set extended fifo value */
643 if (pVia
->Chipset
== VIA_CLE266
&& pVia
->ChipRev
< 15 &&
644 (ctx
->shared
.virtualWidth
> 1024 || pVia
->HasSecondary
)) {
645 /* Turn off Extend FIFO */
647 dwGE298
= VIAGETREG(0x298);
648 VIASETREG(0x298, dwGE298
| 0x20000000);
650 dwGE230
= VIAGETREG(0x230);
651 VIASETREG(0x230, dwGE230
& ~0x00200000);
653 dwGE298
= VIAGETREG(0x298);
654 VIASETREG(0x298, dwGE298
& ~0x20000000);
658 static void VIAEnableExtendedFIFO(DRIDriverContext
*ctx
)
660 VIAPtr pVia
= VIAPTR(ctx
);
662 u_int32_t dwGE230
, dwGE298
;
664 switch (pVia
->Chipset
) {
666 if (pVia
->ChipRev
> 14) { /* For 3123Cx */
667 if (pVia
->HasSecondary
) { /* SAMM or DuoView case */
668 if (ctx
->shared
.virtualWidth
>= 1024)
671 VGAOUT8(0x3C4, 0x16);
672 bRegTemp
= VGAIN8(0x3C5);
675 VGAOUT8(0x3C5, bRegTemp
);
677 VGAOUT8(0x3C4, 0x17);
678 bRegTemp
= VGAIN8(0x3C5);
681 VGAOUT8(0x3C5, bRegTemp
);
682 pVia
->EnableExtendedFIFO
= GL_TRUE
;
685 else /* Single view or Simultaneoue case */
687 if (ctx
->shared
.virtualWidth
> 1024)
690 VGAOUT8(0x3C4, 0x16);
691 bRegTemp
= VGAIN8(0x3C5);
694 VGAOUT8(0x3C5, bRegTemp
);
696 VGAOUT8(0x3C4, 0x17);
697 bRegTemp
= VGAIN8(0x3C5);
700 VGAOUT8(0x3C5, bRegTemp
);
701 pVia
->EnableExtendedFIFO
= GL_TRUE
;
705 VGAOUT8(0x3C4, 0x18);
706 bRegTemp
= VGAIN8(0x3C5);
709 bRegTemp
|= 0x40; /* force the preq always higher than treq */
710 VGAOUT8(0x3C5, bRegTemp
);
712 else { /* for 3123Ax */
713 if (ctx
->shared
.virtualWidth
> 1024 || pVia
->HasSecondary
) {
714 /* Turn on Extend FIFO */
716 dwGE298
= VIAGETREG(0x298);
717 VIASETREG(0x298, dwGE298
| 0x20000000);
719 dwGE230
= VIAGETREG(0x230);
720 VIASETREG(0x230, dwGE230
| 0x00200000);
722 dwGE298
= VIAGETREG(0x298);
723 VIASETREG(0x298, dwGE298
& ~0x20000000);
726 VGAOUT8(0x3C4, 0x16);
727 bRegTemp
= VGAIN8(0x3C5);
730 /* bRegTemp |= 0x10; */
731 VGAOUT8(0x3C5, bRegTemp
);
733 VGAOUT8(0x3C4, 0x17);
734 bRegTemp
= VGAIN8(0x3C5);
737 /*bRegTemp |= 0x1F;*/
738 VGAOUT8(0x3C5, bRegTemp
);
740 VGAOUT8(0x3C4, 0x18);
741 bRegTemp
= VGAIN8(0x3C5);
744 bRegTemp
|= 0x40; /* force the preq always higher than treq */
745 VGAOUT8(0x3C5, bRegTemp
);
746 pVia
->EnableExtendedFIFO
= GL_TRUE
;
751 if (pVia
->HasSecondary
) { /* SAMM or DuoView case */
752 if ((ctx
->shared
.virtualWidth
>= 1600) &&
753 (pVia
->MemClk
<= VIA_MEM_DDR200
)) {
754 /* enable CRT extendded FIFO */
755 VGAOUT8(0x3C4, 0x17);
756 VGAOUT8(0x3C5, 0x1C);
757 /* revise second display queue depth and read threshold */
758 VGAOUT8(0x3C4, 0x16);
759 bRegTemp
= VGAIN8(0x3C5);
761 bRegTemp
= (bRegTemp
) | (0x09);
762 VGAOUT8(0x3C5, bRegTemp
);
765 /* enable CRT extendded FIFO */
766 VGAOUT8(0x3C4, 0x17);
768 /* revise second display queue depth and read threshold */
769 VGAOUT8(0x3C4, 0x16);
770 bRegTemp
= VGAIN8(0x3C5);
772 bRegTemp
= (bRegTemp
) | (0x1C);
773 VGAOUT8(0x3C5, bRegTemp
);
776 VGAOUT8(0x3C4, 0x18);
777 bRegTemp
= VGAIN8(0x3C5);
780 bRegTemp
|= 0x40; /* force the preq always higher than treq */
781 VGAOUT8(0x3C5, bRegTemp
);
782 pVia
->EnableExtendedFIFO
= GL_TRUE
;
785 if ( (ctx
->shared
.virtualWidth
> 1024) && (ctx
->shared
.virtualWidth
<= 1280) )
787 /* enable CRT extendded FIFO */
788 VGAOUT8(0x3C4, 0x17);
789 VGAOUT8(0x3C5, 0x3F);
790 /* revise second display queue depth and read threshold */
791 VGAOUT8(0x3C4, 0x16);
792 bRegTemp
= VGAIN8(0x3C5);
794 bRegTemp
= (bRegTemp
) | (0x17);
795 VGAOUT8(0x3C5, bRegTemp
);
796 pVia
->EnableExtendedFIFO
= GL_TRUE
;
798 else if ((ctx
->shared
.virtualWidth
> 1280))
800 /* enable CRT extendded FIFO */
801 VGAOUT8(0x3C4, 0x17);
802 VGAOUT8(0x3C5, 0x3F);
803 /* revise second display queue depth and read threshold */
804 VGAOUT8(0x3C4, 0x16);
805 bRegTemp
= VGAIN8(0x3C5);
807 bRegTemp
= (bRegTemp
) | (0x1C);
808 VGAOUT8(0x3C5, bRegTemp
);
809 pVia
->EnableExtendedFIFO
= GL_TRUE
;
813 /* enable CRT extendded FIFO */
814 VGAOUT8(0x3C4, 0x17);
815 VGAOUT8(0x3C5, 0x3F);
816 /* revise second display queue depth and read threshold */
817 VGAOUT8(0x3C4, 0x16);
818 bRegTemp
= VGAIN8(0x3C5);
820 bRegTemp
= (bRegTemp
) | (0x10);
821 VGAOUT8(0x3C5, bRegTemp
);
824 VGAOUT8(0x3C4, 0x18);
825 bRegTemp
= VGAIN8(0x3C5);
828 bRegTemp
|= 0x40; /* force the preq always higher than treq */
829 VGAOUT8(0x3C5, bRegTemp
);
833 /*=* R1 Display FIFO depth (384 /8 -1 -> 0xbf) SR17[7:0] (8bits) *=*/
834 VGAOUT8(0x3c4, 0x17);
835 VGAOUT8(0x3c5, 0xbf);
837 /*=* R2 Display fetch datum threshold value (328/4 -> 0x52)
838 SR16[5:0], SR16[7] (7bits) *=*/
839 VGAOUT8(0x3c4, 0x16);
840 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
841 bRegTemp
|= (0x52 & 0x3F);
842 bRegTemp
|= ((0x52 & 0x40) << 1);
843 VGAOUT8(0x3c5, bRegTemp
);
845 /*=* R3 Switch to the highest agent threshold value (74 -> 0x4a)
846 SR18[5:0], SR18[7] (7bits) *=*/
847 VGAOUT8(0x3c4, 0x18);
848 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
849 bRegTemp
|= (0x4a & 0x3F);
850 bRegTemp
|= ((0x4a & 0x40) << 1);
851 VGAOUT8(0x3c5, bRegTemp
);
853 /*=* R4 Fetch Number for a scan line (unit: 8 bytes)
854 SR1C[7:0], SR1D[1:0] (10bits) *=*/
855 wRegTemp
= (pBIOSInfo
->offsetWidthByQWord
>> 1) + 4;
856 VGAOUT8(0x3c4, 0x1c);
857 VGAOUT8(0x3c5, (u_int8_t
)(wRegTemp
& 0xFF));
858 VGAOUT8(0x3c4, 0x1d);
859 bRegTemp
= VGAIN8(0x3c5) & ~0x03;
860 VGAOUT8(0x3c5, bRegTemp
| ((wRegTemp
& 0x300) >> 8));
862 if (ctx
->shared
.virtualWidth
>= 1400 && ctx
->bpp
== 32)
864 /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/
865 VGAOUT8(0x3c4, 0x22);
866 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
867 VGAOUT8(0x3c5, bRegTemp
| 0x10);
871 /*=* Max. length for a request SR22[4:0]
872 (128/4 -> over flow 0x0) *=*/
873 VGAOUT8(0x3c4, 0x22);
874 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
875 VGAOUT8(0x3c5, bRegTemp
);
879 /*=* R1 Display FIFO depth (96-1 -> 0x5f) SR17[7:0] (8bits) *=*/
880 VGAOUT8(0x3c4, 0x17);
881 VGAOUT8(0x3c5, 0x5f);
883 /*=* R2 Display fetch datum threshold value (32 -> 0x20)
884 SR16[5:0], SR16[7] (7bits) *=*/
885 VGAOUT8(0x3c4, 0x16);
886 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
887 bRegTemp
|= (0x20 & 0x3F);
888 bRegTemp
|= ((0x20 & 0x40) << 1);
889 VGAOUT8(0x3c5, bRegTemp
);
891 /*=* R3 Switch to the highest agent threshold value (16 -> 0x10)
892 SR18[5:0], SR18[7] (7bits) *=*/
893 VGAOUT8(0x3c4, 0x18);
894 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
895 bRegTemp
|= (0x10 & 0x3F);
896 bRegTemp
|= ((0x10 & 0x40) << 1);
897 VGAOUT8(0x3c5, bRegTemp
);
899 /*=* R4 Fetch Number for a scan line (unit: 8 bytes)
900 SR1C[7:0], SR1D[1:0] (10bits) *=*/
901 wRegTemp
= (pBIOSInfo
->offsetWidthByQWord
>> 1) + 4;
902 VGAOUT8(0x3c4, 0x1c);
903 VGAOUT8(0x3c5, (u_int8_t
)(wRegTemp
& 0xFF));
904 VGAOUT8(0x3c4, 0x1d);
905 bRegTemp
= VGAIN8(0x3c5) & ~0x03;
906 VGAOUT8(0x3c5, bRegTemp
| ((wRegTemp
& 0x300) >> 8));
908 if (ctx
->shared
.virtualWidth
>= 1400 && ctx
->bpp
== 32)
910 /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/
911 VGAOUT8(0x3c4, 0x22);
912 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
913 VGAOUT8(0x3c5, bRegTemp
| 0x10);
917 /*=* Max. length for a request SR22[4:0] (0x1F) *=*/
918 VGAOUT8(0x3c4, 0x22);
919 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
920 VGAOUT8(0x3c5, bRegTemp
| 0x1F);
928 static void VIAInitialize2DEngine(DRIDriverContext
*ctx
)
930 VIAPtr pVia
= VIAPTR(ctx
);
931 u_int32_t dwVQStartAddr
, dwVQEndAddr
;
932 u_int32_t dwVQLen
, dwVQStartL
, dwVQEndL
, dwVQStartEndH
;
935 /* init 2D engine regs to reset 2D engine */
936 VIASETREG(0x04, 0x0);
937 VIASETREG(0x08, 0x0);
938 VIASETREG(0x0c, 0x0);
939 VIASETREG(0x10, 0x0);
940 VIASETREG(0x14, 0x0);
941 VIASETREG(0x18, 0x0);
942 VIASETREG(0x1c, 0x0);
943 VIASETREG(0x20, 0x0);
944 VIASETREG(0x24, 0x0);
945 VIASETREG(0x28, 0x0);
946 VIASETREG(0x2c, 0x0);
947 VIASETREG(0x30, 0x0);
948 VIASETREG(0x34, 0x0);
949 VIASETREG(0x38, 0x0);
950 VIASETREG(0x3c, 0x0);
951 VIASETREG(0x40, 0x0);
955 /* Init AGP and VQ regs */
956 VIASETREG(0x43c, 0x00100000);
957 VIASETREG(0x440, 0x00000000);
958 VIASETREG(0x440, 0x00333004);
959 VIASETREG(0x440, 0x60000000);
960 VIASETREG(0x440, 0x61000000);
961 VIASETREG(0x440, 0x62000000);
962 VIASETREG(0x440, 0x63000000);
963 VIASETREG(0x440, 0x64000000);
964 VIASETREG(0x440, 0x7D000000);
966 VIASETREG(0x43c, 0xfe020000);
967 VIASETREG(0x440, 0x00000000);
969 if (pVia
->VQStart
!= 0) {
971 dwVQStartAddr
= pVia
->VQStart
;
972 dwVQEndAddr
= pVia
->VQEnd
;
973 dwVQStartL
= 0x50000000 | (dwVQStartAddr
& 0xFFFFFF);
974 dwVQEndL
= 0x51000000 | (dwVQEndAddr
& 0xFFFFFF);
975 dwVQStartEndH
= 0x52000000 | ((dwVQStartAddr
& 0xFF000000) >> 24) |
976 ((dwVQEndAddr
& 0xFF000000) >> 16);
977 dwVQLen
= 0x53000000 | (VIA_VQ_SIZE
>> 3);
979 VIASETREG(0x43c, 0x00fe0000);
980 VIASETREG(0x440, 0x080003fe);
981 VIASETREG(0x440, 0x0a00027c);
982 VIASETREG(0x440, 0x0b000260);
983 VIASETREG(0x440, 0x0c000274);
984 VIASETREG(0x440, 0x0d000264);
985 VIASETREG(0x440, 0x0e000000);
986 VIASETREG(0x440, 0x0f000020);
987 VIASETREG(0x440, 0x1000027e);
988 VIASETREG(0x440, 0x110002fe);
989 VIASETREG(0x440, 0x200f0060);
991 VIASETREG(0x440, 0x00000006);
992 VIASETREG(0x440, 0x40008c0f);
993 VIASETREG(0x440, 0x44000000);
994 VIASETREG(0x440, 0x45080c04);
995 VIASETREG(0x440, 0x46800408);
997 VIASETREG(0x440, dwVQStartEndH
);
998 VIASETREG(0x440, dwVQStartL
);
999 VIASETREG(0x440, dwVQEndL
);
1000 VIASETREG(0x440, dwVQLen
);
1004 VIASETREG(0x43c, 0x00fe0000);
1005 VIASETREG(0x440, 0x00000004);
1006 VIASETREG(0x440, 0x40008c0f);
1007 VIASETREG(0x440, 0x44000000);
1008 VIASETREG(0x440, 0x45080c04);
1009 VIASETREG(0x440, 0x46800408);
1016 dwGEMode
|= VIA_GEM_16bpp
;
1019 dwGEMode
|= VIA_GEM_32bpp
;
1022 dwGEMode
|= VIA_GEM_8bpp
;
1027 switch (ctx
->shared
.virtualWidth
) {
1029 dwGEMode
|= VIA_GEM_800
;
1032 dwGEMode
|= VIA_GEM_1024
;
1035 dwGEMode
|= VIA_GEM_1280
;
1038 dwGEMode
|= VIA_GEM_1600
;
1041 dwGEMode
|= VIA_GEM_2048
;
1044 dwGEMode
|= VIA_GEM_640
;
1051 /* Set BPP and Pitch */
1052 VIASETREG(VIA_REG_GEMODE
, dwGEMode
);
1054 /* Set Src and Dst base address and pitch, pitch is qword */
1055 VIASETREG(VIA_REG_SRCBASE
, 0x0);
1056 VIASETREG(VIA_REG_DSTBASE
, 0x0);
1057 VIASETREG(VIA_REG_PITCH
, VIA_PITCH_ENABLE
|
1058 ((ctx
->shared
.virtualWidth
* ctx
->bpp
>> 3) >> 3) |
1059 (((ctx
->shared
.virtualWidth
* ctx
->bpp
>> 3) >> 3) << 16));
1062 static int b3DRegsInitialized
= 0;
1064 static void VIAInitialize3DEngine(DRIDriverContext
*ctx
)
1066 VIAPtr pVia
= VIAPTR(ctx
);
1069 if (!b3DRegsInitialized
)
1072 VIASETREG(0x43C, 0x00010000);
1074 for (i
= 0; i
<= 0x7D; i
++)
1076 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1079 VIASETREG(0x43C, 0x00020000);
1081 for (i
= 0; i
<= 0x94; i
++)
1083 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1086 VIASETREG(0x440, 0x82400000);
1088 VIASETREG(0x43C, 0x01020000);
1091 for (i
= 0; i
<= 0x94; i
++)
1093 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1096 VIASETREG(0x440, 0x82400000);
1097 VIASETREG(0x43C, 0xfe020000);
1099 for (i
= 0; i
<= 0x03; i
++)
1101 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1104 VIASETREG(0x43C, 0x00030000);
1106 for (i
= 0; i
<= 0xff; i
++)
1108 VIASETREG(0x440, 0);
1110 VIASETREG(0x43C, 0x00100000);
1111 VIASETREG(0x440, 0x00333004);
1112 VIASETREG(0x440, 0x10000002);
1113 VIASETREG(0x440, 0x60000000);
1114 VIASETREG(0x440, 0x61000000);
1115 VIASETREG(0x440, 0x62000000);
1116 VIASETREG(0x440, 0x63000000);
1117 VIASETREG(0x440, 0x64000000);
1119 VIASETREG(0x43C, 0x00fe0000);
1121 if (pVia
->ChipRev
>= 3 )
1122 VIASETREG(0x440,0x40008c0f);
1124 VIASETREG(0x440,0x4000800f);
1126 VIASETREG(0x440,0x44000000);
1127 VIASETREG(0x440,0x45080C04);
1128 VIASETREG(0x440,0x46800408);
1129 VIASETREG(0x440,0x50000000);
1130 VIASETREG(0x440,0x51000000);
1131 VIASETREG(0x440,0x52000000);
1132 VIASETREG(0x440,0x53000000);
1134 b3DRegsInitialized
= 1;
1135 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1136 "3D Engine has been initialized.\n");
1139 VIASETREG(0x43C,0x00fe0000);
1140 VIASETREG(0x440,0x08000001);
1141 VIASETREG(0x440,0x0A000183);
1142 VIASETREG(0x440,0x0B00019F);
1143 VIASETREG(0x440,0x0C00018B);
1144 VIASETREG(0x440,0x0D00019B);
1145 VIASETREG(0x440,0x0E000000);
1146 VIASETREG(0x440,0x0F000000);
1147 VIASETREG(0x440,0x10000000);
1148 VIASETREG(0x440,0x11000000);
1149 VIASETREG(0x440,0x20000000);
1153 WaitIdleCLE266(VIAPtr pVia
)
1159 while (!(VIAGETREG(VIA_REG_STATUS
) & VIA_VR_QUEUE_BUSY
) && (loop
++ < MAXLOOP
))
1162 while ((VIAGETREG(VIA_REG_STATUS
) &
1163 (VIA_CMD_RGTR_BUSY
| VIA_2D_ENG_BUSY
| VIA_3D_ENG_BUSY
)) &&
1167 return loop
>= MAXLOOP
;
1170 static int viaInitFBDev(DRIDriverContext
*ctx
)
1172 VIAPtr pVia
= CALLOC(sizeof(*pVia
));
1174 ctx
->driverPrivate
= (void *)pVia
;
1176 switch (ctx
->chipset
) {
1177 case PCI_CHIP_CLE3122
:
1178 case PCI_CHIP_CLE3022
:
1179 pVia
->Chipset
= VIA_CLE266
;
1181 case PCI_CHIP_VT7205
:
1182 case PCI_CHIP_VT3205
:
1183 pVia
->Chipset
= VIA_KM400
;
1185 case PCI_CHIP_VT3204
:
1186 pVia
->Chipset
= VIA_K8M800
;
1188 case PCI_CHIP_VT3259
:
1189 pVia
->Chipset
= VIA_PM800
;
1192 xf86DrvMsg(0, X_ERROR
, "VIA: Unknown device ID (0x%x)\n", ctx
->chipset
);
1195 /* _SOLO TODO XXX need to read ChipRev too */
1198 pVia
->videoRambytes
= ctx
->shared
.fbSize
;
1199 pVia
->MmioBase
= ctx
->MMIOStart
;
1200 pVia
->FrameBufferBase
= ctx
->FBStart
& 0xfc000000;
1202 pVia
->FBFreeStart
= ctx
->shared
.virtualWidth
* ctx
->cpp
*
1203 ctx
->shared
.virtualHeight
;
1206 /* Alloc a second framebuffer for the second head */
1207 pVia
->FBFreeStart
+= ctx
->shared
.virtualWidth
* ctx
->cpp
*
1208 ctx
->shared
.virtualHeight
;
1211 pVia
->VQStart
= pVia
->FBFreeStart
;
1212 pVia
->VQEnd
= pVia
->FBFreeStart
+ VIA_VQ_SIZE
- 1;
1214 pVia
->FBFreeStart
+= VIA_VQ_SIZE
;
1216 pVia
->FBFreeEnd
= pVia
->videoRambytes
;
1218 if (!VIADRIScreenInit(ctx
))
1224 static void viaHaltFBDev(DRIDriverContext
*ctx
)
1226 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
1227 drmClose(ctx
->drmFD
);
1229 if (ctx
->driverPrivate
) {
1230 free(ctx
->driverPrivate
);
1231 ctx
->driverPrivate
= 0;
1235 static int viaEngineShutdown(const DRIDriverContext
*ctx
)
1240 static int viaEngineRestore(const DRIDriverContext
*ctx
)
1245 const struct DRIDriverRec __driDriver
=
1248 viaPostValidateMode
,