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.
27 #include "xf86_OSproc.h"
28 #include "xf86_ansic.h"
31 #include "xf86PciInfo.h"
34 #define _XF86DRI_SERVER_
35 #include "GL/glxtokens.h"
52 #include "via_context.h"
54 #include "via_driver.h"
55 #include "via_common.h"
58 static void VIAEnableMMIO(DRIDriverContext
* ctx
);
59 static void VIADisableMMIO(DRIDriverContext
* ctx
);
60 static void VIADisableExtendedFIFO(DRIDriverContext
*ctx
);
61 static void VIAEnableExtendedFIFO(DRIDriverContext
*ctx
);
62 static void VIAInitialize2DEngine(DRIDriverContext
*ctx
);
63 static void VIAInitialize3DEngine(DRIDriverContext
*ctx
);
65 static int VIADRIScreenInit(DRIDriverContext
* ctx
);
66 static void VIADRICloseScreen(DRIDriverContext
* ctx
);
67 static int VIADRIFinishScreenInit(DRIDriverContext
* ctx
);
69 /* _SOLO : missing macros normally defined by X code */
70 #define xf86DrvMsg(a, b, ...) fprintf(stderr, __VA_ARGS__)
71 #define MMIO_IN8(base, addr) ((*(((volatile u_int8_t*)base)+(addr)))+0)
72 #define MMIO_OUT8(base, addr, val) ((*(((volatile u_int8_t*)base)+(addr)))=((u_int8_t)val))
73 #define MMIO_OUT16(base, addr, val) ((*(volatile u_int16_t*)(((u_int8_t*)base)+(addr)))=((u_int16_t)val))
77 #define AGP_PAGE_SIZE 4096
78 #define AGP_PAGES 8192
79 #define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES)
80 #define AGP_CMDBUF_PAGES 512
81 #define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES)
83 static char VIAKernelDriverName
[] = "via";
84 static char VIAClientDriverName
[] = "unichrome";
86 static int VIADRIAgpInit(const DRIDriverContext
*ctx
, VIAPtr pVia
);
87 static int VIADRIPciInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
88 static int VIADRIFBInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
89 static int VIADRIKernelInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
90 static int VIADRIMapInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
92 static void VIADRIIrqInit( DRIDriverContext
*ctx
)
94 VIAPtr pVia
= VIAPTR(ctx
);
95 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
97 pVIADRI
->irqEnabled
= drmGetInterruptFromBusID(pVia
->drmFD
,
102 if ((drmCtlInstHandler(pVia
->drmFD
, pVIADRI
->irqEnabled
))) {
103 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
104 "[drm] Failure adding irq handler. "
105 "Falling back to irq-free operation.\n");
106 pVIADRI
->irqEnabled
= 0;
109 if (pVIADRI
->irqEnabled
)
110 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
111 "[drm] Irq handler installed, using IRQ %d.\n",
112 pVIADRI
->irqEnabled
);
115 static void VIADRIIrqExit( DRIDriverContext
*ctx
) {
116 VIAPtr pVia
= VIAPTR(ctx
);
117 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
119 if (pVIADRI
->irqEnabled
) {
120 if (drmCtlUninstHandler(pVia
->drmFD
)) {
121 xf86DrvMsg(pScreen
-myNum
, X_INFO
,"[drm] Irq handler uninstalled.\n");
123 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
124 "[drm] Could not uninstall irq handler.\n");
129 static void VIADRIRingBufferCleanup(DRIDriverContext
*ctx
)
131 VIAPtr pVia
= VIAPTR(ctx
);
132 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
133 drm_via_dma_init_t ringBufInit
;
135 if (pVIADRI
->ringBufActive
) {
136 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
137 "[drm] Cleaning up DMA ring-buffer.\n");
138 ringBufInit
.func
= VIA_CLEANUP_DMA
;
139 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_DMA_INIT
, &ringBufInit
,
140 sizeof(ringBufInit
))) {
141 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
142 "[drm] Failed to clean up DMA ring-buffer: %d\n", errno
);
144 pVIADRI
->ringBufActive
= 0;
148 static int VIADRIRingBufferInit(DRIDriverContext
*ctx
)
150 VIAPtr pVia
= VIAPTR(ctx
);
151 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
152 drm_via_dma_init_t ringBufInit
;
153 drmVersionPtr drmVer
;
155 pVIADRI
->ringBufActive
= 0;
157 if (NULL
== (drmVer
= drmGetVersion(pVia
->drmFD
))) {
161 if (((drmVer
->version_major
<= 1) && (drmVer
->version_minor
<= 3))) {
166 * Info frome code-snippet on DRI-DEVEL list; Erdi Chen.
169 switch (pVia
->ChipId
) {
170 case PCI_CHIP_VT3259
:
171 ringBufInit
.reg_pause_addr
= 0x40c;
174 ringBufInit
.reg_pause_addr
= 0x418;
178 ringBufInit
.offset
= pVia
->agpSize
;
179 ringBufInit
.size
= AGP_CMDBUF_SIZE
;
180 ringBufInit
.func
= VIA_INIT_DMA
;
181 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_DMA_INIT
, &ringBufInit
,
182 sizeof(ringBufInit
))) {
183 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
184 "[drm] Failed to initialize DMA ring-buffer: %d\n", errno
);
187 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
188 "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP offset 0x%lx.\n",
189 ringBufInit
.size
, ringBufInit
.offset
);
191 pVIADRI
->ringBufActive
= 1;
195 static int VIADRIAgpInit(const DRIDriverContext
*ctx
, VIAPtr pVia
)
197 unsigned long agp_phys
;
200 pVIADRI
= pVia
->devPrivate
;
203 if (drmAgpAcquire(pVia
->drmFD
) < 0) {
204 xf86DrvMsg(pScreen
->myNum
, X_ERROR
, "[drm] drmAgpAcquire failed %d\n", errno
);
208 if (drmAgpEnable(pVia
->drmFD
, drmAgpGetMode(pVia
->drmFD
)&~0x0) < 0) {
209 xf86DrvMsg(pScreen
->myNum
, X_ERROR
, "[drm] drmAgpEnable failed\n");
213 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] drmAgpEnabled succeeded\n");
215 if (drmAgpAlloc(pVia
->drmFD
, AGP_SIZE
, 0, &agp_phys
, &pVia
->agpHandle
) < 0) {
216 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
217 "[drm] drmAgpAlloc failed\n");
218 drmAgpRelease(pVia
->drmFD
);
222 if (drmAgpBind(pVia
->drmFD
, pVia
->agpHandle
, 0) < 0) {
223 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
224 "[drm] drmAgpBind failed\n");
225 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
226 drmAgpRelease(pVia
->drmFD
);
232 * Place the ring-buffer last in the AGP region, and restrict the
233 * public map not to include the buffer for security reasons.
236 pVia
->agpSize
= AGP_SIZE
- AGP_CMDBUF_SIZE
;
237 pVia
->agpAddr
= drmAgpBase(pVia
->drmFD
);
238 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
239 "[drm] agpAddr = 0x%08lx\n",pVia
->agpAddr
);
241 pVIADRI
->agp
.size
= pVia
->agpSize
;
242 if (drmAddMap(pVia
->drmFD
, (drm_handle_t
)0,
243 pVIADRI
->agp
.size
, DRM_AGP
, 0,
244 &pVIADRI
->agp
.handle
) < 0) {
245 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
246 "[drm] Failed to map public agp area\n");
247 pVIADRI
->agp
.size
= 0;
250 /* Map AGP from kernel to Xserver - Not really needed */
251 drmMap(pVia
->drmFD
, pVIADRI
->agp
.handle
,pVIADRI
->agp
.size
, &agpaddr
);
253 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
254 "[drm] agpAddr = 0x%08lx\n", pVia
->agpAddr
);
255 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
256 "[drm] agpSize = 0x%08lx\n", pVia
->agpSize
);
257 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
258 "[drm] agp physical addr = 0x%08lx\n", agp_phys
);
263 agp
.size
= AGP_SIZE
-AGP_CMDBUF_SIZE
;
264 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_AGP_INIT
, &agp
,
265 sizeof(drm_via_agp_t
)) < 0) {
266 drmUnmap(&agpaddr
,pVia
->agpSize
);
267 drmRmMap(pVia
->drmFD
,pVIADRI
->agp
.handle
);
268 drmAgpUnbind(pVia
->drmFD
, pVia
->agpHandle
);
269 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
270 drmAgpRelease(pVia
->drmFD
);
278 static int VIADRIFBInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
280 int FBSize
= pVia
->FBFreeEnd
-pVia
->FBFreeStart
;
281 int FBOffset
= pVia
->FBFreeStart
;
282 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
283 pVIADRI
->fbOffset
= FBOffset
;
284 pVIADRI
->fbSize
= pVia
->videoRambytes
;
288 fb
.offset
= FBOffset
;
291 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_FB_INIT
, &fb
,
292 sizeof(drm_via_fb_t
)) < 0) {
293 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
294 "[drm] failed to init frame buffer area\n");
297 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
298 "[drm] FBFreeStart= 0x%08x FBFreeEnd= 0x%08x "
300 pVia
->FBFreeStart
, pVia
->FBFreeEnd
, FBSize
);
306 static int VIADRIPciInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
311 static int VIADRIScreenInit(DRIDriverContext
* ctx
)
313 VIAPtr pVia
= VIAPTR(ctx
);
318 ctx
->shared
.SAREASize
= ((sizeof(drm_sarea_t
) + 0xfff) & 0x1000);
320 if (sizeof(drm_sarea_t
)+sizeof(VIASAREAPriv
) > SAREA_MAX
) {
321 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
322 "Data does not fit in SAREA\n");
325 ctx
->shared
.SAREASize
= SAREA_MAX
;
328 ctx
->drmFD
= drmOpen(VIAKernelDriverName
, NULL
);
329 if (ctx
->drmFD
< 0) {
330 fprintf(stderr
, "[drm] drmOpen failed\n");
333 pVia
->drmFD
= ctx
->drmFD
;
335 err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
);
337 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
338 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
342 err
= drmAddMap(ctx
->drmFD
, 0, ctx
->shared
.SAREASize
, DRM_SHM
,
343 DRM_CONTAINS_LOCK
, &ctx
->shared
.hSAREA
);
345 fprintf(stderr
, "[drm] drmAddMap failed\n");
348 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
349 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
351 if (drmMap(ctx
->drmFD
,
353 ctx
->shared
.SAREASize
,
354 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
356 fprintf(stderr
, "[drm] drmMap failed\n");
359 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
360 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
361 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
363 /* Need to AddMap the framebuffer and mmio regions here:
365 if (drmAddMap(ctx
->drmFD
,
366 (drm_handle_t
)ctx
->FBStart
,
374 &ctx
->shared
.hFrameBuffer
) < 0)
376 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
380 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
381 ctx
->shared
.hFrameBuffer
);
383 pVIADRI
= (VIADRIPtr
) CALLOC(sizeof(VIADRIRec
));
385 drmClose(ctx
->drmFD
);
388 pVia
->devPrivate
= pVIADRI
;
389 ctx
->driverClientMsg
= pVIADRI
;
390 ctx
->driverClientMsgSize
= sizeof(*pVIADRI
);
392 /* DRIScreenInit doesn't add all the common mappings. Add additional mappings here. */
393 if (!VIADRIMapInit(ctx
, pVia
)) {
394 VIADRICloseScreen(ctx
);
398 pVIADRI
->regs
.size
= VIA_MMIO_REGSIZE
;
399 pVIADRI
->regs
.map
= 0;
400 pVIADRI
->regs
.handle
= pVia
->registerHandle
;
401 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] mmio Registers = 0x%08lx\n",
402 pVIADRI
->regs
.handle
);
404 if (drmMap(pVia
->drmFD
,
405 pVIADRI
->regs
.handle
,
407 (drmAddress
*)&pVia
->MapBase
) != 0)
409 VIADRICloseScreen(ctx
);
413 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] mmio mapped.\n" );
417 /* Get video memory clock. */
418 VGAOUT8(0x3D4, 0x3D);
419 pVia
->MemClk
= (VGAIN8(0x3D5) & 0xF0) >> 4;
420 xf86DrvMsg(0, X_INFO
, "[dri] MemClk (0x%x)\n", pVia
->MemClk
);
422 /* 3D rendering has noise if not enabled. */
423 VIAEnableExtendedFIFO(ctx
);
425 VIAInitialize2DEngine(ctx
);
427 /* Must disable MMIO or 3D won't work. */
430 VIAInitialize3DEngine(ctx
);
432 pVia
->IsPCI
= !VIADRIAgpInit(ctx
, pVia
);
435 VIADRIPciInit(ctx
, pVia
);
436 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] use pci.\n" );
439 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] use agp.\n" );
441 if (!(VIADRIFBInit(ctx
, pVia
))) {
442 VIADRICloseScreen(ctx
);
443 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "[dri] frame buffer initialize fail .\n" );
447 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] frame buffer initialized.\n" );
449 /*pVIADRI->drixinerama = pVia->drixinerama;*/
450 /*=* John Sheng [2003.12.9] Tuxracer & VQ *=*/
451 pVIADRI
->VQEnable
= pVia
->VQEnable
;
453 return VIADRIFinishScreenInit(ctx
);
457 VIADRICloseScreen(DRIDriverContext
* ctx
)
459 VIAPtr pVia
= VIAPTR(ctx
);
460 VIADRIPtr pVIADRI
=(VIADRIPtr
)pVia
->devPrivate
;
462 VIADRIRingBufferCleanup(ctx
);
465 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Unmapping MMIO registers\n");
466 drmUnmap(pVia
->MapBase
, pVIADRI
->regs
.size
);
470 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Freeing agp memory\n");
471 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
472 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Releasing agp module\n");
473 drmAgpRelease(pVia
->drmFD
);
477 if (pVia
->DRIIrqEnable
)
483 VIADRIFinishScreenInit(DRIDriverContext
* ctx
)
485 VIAPtr pVia
= VIAPTR(ctx
);
489 err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
);
491 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
495 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
498 if (!VIADRIKernelInit(ctx
, pVia
)) {
499 VIADRICloseScreen(ctx
);
502 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[dri] kernel data initialized.\n");
504 /* set SAREA value */
506 VIASAREAPriv
*saPriv
;
508 saPriv
=(VIASAREAPriv
*)(((char*)ctx
->pSAREA
) +
509 sizeof(drm_sarea_t
));
511 memset(saPriv
, 0, sizeof(*saPriv
));
512 saPriv
->CtxOwner
= -1;
514 pVIADRI
=(VIADRIPtr
)pVia
->devPrivate
;
515 pVIADRI
->deviceID
=pVia
->Chipset
;
516 pVIADRI
->width
=ctx
->shared
.virtualWidth
;
517 pVIADRI
->height
=ctx
->shared
.virtualHeight
;
518 pVIADRI
->mem
=ctx
->shared
.fbSize
;
519 pVIADRI
->bytesPerPixel
= (ctx
->bpp
+7) / 8;
520 pVIADRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
522 pVIADRI
->scrnX
=pVIADRI
->width
;
523 pVIADRI
->scrnY
=pVIADRI
->height
;
527 if (pVia
->DRIIrqEnable
)
531 pVIADRI
->ringBufActive
= 0;
532 VIADRIRingBufferInit(ctx
);
537 /* Initialize the kernel data structures. */
538 static int VIADRIKernelInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
540 drm_via_init_t drmInfo
;
541 memset(&drmInfo
, 0, sizeof(drm_via_init_t
));
542 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
543 drmInfo
.func
= VIA_INIT_MAP
;
544 drmInfo
.fb_offset
= pVia
->FrameBufferBase
;
545 drmInfo
.mmio_offset
= pVia
->registerHandle
;
547 drmInfo
.agpAddr
= (u_int32_t
)NULL
;
549 drmInfo
.agpAddr
= (u_int32_t
)pVia
->agpAddr
;
551 if ((drmCommandWrite(pVia
->drmFD
, DRM_VIA_MAP_INIT
,&drmInfo
,
552 sizeof(drm_via_init_t
))) < 0)
557 /* Add a map for the MMIO registers */
558 static int VIADRIMapInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
562 if (drmAddMap(pVia
->drmFD
, pVia
->MmioBase
, VIA_MMIO_REGSIZE
,
563 DRM_REGISTERS
, flags
, &pVia
->registerHandle
) < 0) {
567 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
568 "[drm] register handle = 0x%08lx\n", pVia
->registerHandle
);
573 static int viaValidateMode(const DRIDriverContext
*ctx
)
575 VIAPtr pVia
= VIAPTR(ctx
);
580 static int viaPostValidateMode(const DRIDriverContext
*ctx
)
582 VIAPtr pVia
= VIAPTR(ctx
);
587 static void VIAEnableMMIO(DRIDriverContext
* ctx
)
589 /*vgaHWPtr hwp = VGAHWPTR(ctx);*/
590 VIAPtr pVia
= VIAPTR(ctx
);
594 if (xf86IsPrimaryPci(pVia
->PciInfo
)) {
595 /* If we are primary card, we still use std vga port. If we use
596 * MMIO, system will hang in vgaHWSave when our card used in
597 * PLE and KLE (integrated Trident MVP4)
599 vgaHWSetStdFuncs(hwp
);
602 vgaHWSetMmioFuncs(hwp
, pVia
->MapBase
, 0x8000);
607 VGAOUT8(0x3c3, val
| 0x01);
609 VGAOUT8(0x3c2, val
| 0x01);
611 /* Unlock Extended IO Space */
612 VGAOUT8(0x3c4, 0x10);
613 VGAOUT8(0x3c5, 0x01);
616 if(!pVia
->IsSecondary
) {
617 VGAOUT8(0x3c4, 0x1a);
620 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "primary val = %x\n", val
);
622 VGAOUT8(0x3c5, val
| 0x68);
625 VGAOUT8(0x3c4, 0x1a);
628 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "secondary val = %x\n", val
);
630 VGAOUT8(0x3c5, val
| 0x38);
633 /* Unlock CRTC registers */
634 VGAOUT8(0x3d4, 0x47);
635 VGAOUT8(0x3d5, 0x00);
640 static void VIADisableMMIO(DRIDriverContext
* ctx
)
642 VIAPtr pVia
= VIAPTR(ctx
);
645 VGAOUT8(0x3c4, 0x1a);
647 VGAOUT8(0x3c5, val
& 0x97);
652 static void VIADisableExtendedFIFO(DRIDriverContext
*ctx
)
654 VIAPtr pVia
= VIAPTR(ctx
);
655 u_int32_t dwGE230
, dwGE298
;
657 /* Cause of exit XWindow will dump back register value, others chipset no
658 * need to set extended fifo value */
659 if (pVia
->Chipset
== VIA_CLE266
&& pVia
->ChipRev
< 15 &&
660 (ctx
->shared
.virtualWidth
> 1024 || pVia
->HasSecondary
)) {
661 /* Turn off Extend FIFO */
663 dwGE298
= VIAGETREG(0x298);
664 VIASETREG(0x298, dwGE298
| 0x20000000);
666 dwGE230
= VIAGETREG(0x230);
667 VIASETREG(0x230, dwGE230
& ~0x00200000);
669 dwGE298
= VIAGETREG(0x298);
670 VIASETREG(0x298, dwGE298
& ~0x20000000);
674 static void VIAEnableExtendedFIFO(DRIDriverContext
*ctx
)
676 VIAPtr pVia
= VIAPTR(ctx
);
678 u_int32_t dwGE230
, dwGE298
;
680 switch (pVia
->Chipset
) {
682 if (pVia
->ChipRev
> 14) { /* For 3123Cx */
683 if (pVia
->HasSecondary
) { /* SAMM or DuoView case */
684 if (ctx
->shared
.virtualWidth
>= 1024)
687 VGAOUT8(0x3C4, 0x16);
688 bRegTemp
= VGAIN8(0x3C5);
691 VGAOUT8(0x3C5, bRegTemp
);
693 VGAOUT8(0x3C4, 0x17);
694 bRegTemp
= VGAIN8(0x3C5);
697 VGAOUT8(0x3C5, bRegTemp
);
698 pVia
->EnableExtendedFIFO
= GL_TRUE
;
701 else /* Single view or Simultaneoue case */
703 if (ctx
->shared
.virtualWidth
> 1024)
706 VGAOUT8(0x3C4, 0x16);
707 bRegTemp
= VGAIN8(0x3C5);
710 VGAOUT8(0x3C5, bRegTemp
);
712 VGAOUT8(0x3C4, 0x17);
713 bRegTemp
= VGAIN8(0x3C5);
716 VGAOUT8(0x3C5, bRegTemp
);
717 pVia
->EnableExtendedFIFO
= GL_TRUE
;
721 VGAOUT8(0x3C4, 0x18);
722 bRegTemp
= VGAIN8(0x3C5);
725 bRegTemp
|= 0x40; /* force the preq always higher than treq */
726 VGAOUT8(0x3C5, bRegTemp
);
728 else { /* for 3123Ax */
729 if (ctx
->shared
.virtualWidth
> 1024 || pVia
->HasSecondary
) {
730 /* Turn on Extend FIFO */
732 dwGE298
= VIAGETREG(0x298);
733 VIASETREG(0x298, dwGE298
| 0x20000000);
735 dwGE230
= VIAGETREG(0x230);
736 VIASETREG(0x230, dwGE230
| 0x00200000);
738 dwGE298
= VIAGETREG(0x298);
739 VIASETREG(0x298, dwGE298
& ~0x20000000);
742 VGAOUT8(0x3C4, 0x16);
743 bRegTemp
= VGAIN8(0x3C5);
746 /* bRegTemp |= 0x10; */
747 VGAOUT8(0x3C5, bRegTemp
);
749 VGAOUT8(0x3C4, 0x17);
750 bRegTemp
= VGAIN8(0x3C5);
753 /*bRegTemp |= 0x1F;*/
754 VGAOUT8(0x3C5, bRegTemp
);
756 VGAOUT8(0x3C4, 0x18);
757 bRegTemp
= VGAIN8(0x3C5);
760 bRegTemp
|= 0x40; /* force the preq always higher than treq */
761 VGAOUT8(0x3C5, bRegTemp
);
762 pVia
->EnableExtendedFIFO
= GL_TRUE
;
767 if (pVia
->HasSecondary
) { /* SAMM or DuoView case */
768 if ((ctx
->shared
.virtualWidth
>= 1600) &&
769 (pVia
->MemClk
<= VIA_MEM_DDR200
)) {
770 /* enable CRT extendded FIFO */
771 VGAOUT8(0x3C4, 0x17);
772 VGAOUT8(0x3C5, 0x1C);
773 /* revise second display queue depth and read threshold */
774 VGAOUT8(0x3C4, 0x16);
775 bRegTemp
= VGAIN8(0x3C5);
777 bRegTemp
= (bRegTemp
) | (0x09);
778 VGAOUT8(0x3C5, bRegTemp
);
781 /* enable CRT extendded FIFO */
782 VGAOUT8(0x3C4, 0x17);
784 /* revise second display queue depth and read threshold */
785 VGAOUT8(0x3C4, 0x16);
786 bRegTemp
= VGAIN8(0x3C5);
788 bRegTemp
= (bRegTemp
) | (0x1C);
789 VGAOUT8(0x3C5, bRegTemp
);
792 VGAOUT8(0x3C4, 0x18);
793 bRegTemp
= VGAIN8(0x3C5);
796 bRegTemp
|= 0x40; /* force the preq always higher than treq */
797 VGAOUT8(0x3C5, bRegTemp
);
798 pVia
->EnableExtendedFIFO
= GL_TRUE
;
801 if ( (ctx
->shared
.virtualWidth
> 1024) && (ctx
->shared
.virtualWidth
<= 1280) )
803 /* enable CRT extendded FIFO */
804 VGAOUT8(0x3C4, 0x17);
805 VGAOUT8(0x3C5, 0x3F);
806 /* revise second display queue depth and read threshold */
807 VGAOUT8(0x3C4, 0x16);
808 bRegTemp
= VGAIN8(0x3C5);
810 bRegTemp
= (bRegTemp
) | (0x17);
811 VGAOUT8(0x3C5, bRegTemp
);
812 pVia
->EnableExtendedFIFO
= GL_TRUE
;
814 else if ((ctx
->shared
.virtualWidth
> 1280))
816 /* enable CRT extendded FIFO */
817 VGAOUT8(0x3C4, 0x17);
818 VGAOUT8(0x3C5, 0x3F);
819 /* revise second display queue depth and read threshold */
820 VGAOUT8(0x3C4, 0x16);
821 bRegTemp
= VGAIN8(0x3C5);
823 bRegTemp
= (bRegTemp
) | (0x1C);
824 VGAOUT8(0x3C5, bRegTemp
);
825 pVia
->EnableExtendedFIFO
= GL_TRUE
;
829 /* enable CRT extendded FIFO */
830 VGAOUT8(0x3C4, 0x17);
831 VGAOUT8(0x3C5, 0x3F);
832 /* revise second display queue depth and read threshold */
833 VGAOUT8(0x3C4, 0x16);
834 bRegTemp
= VGAIN8(0x3C5);
836 bRegTemp
= (bRegTemp
) | (0x10);
837 VGAOUT8(0x3C5, bRegTemp
);
840 VGAOUT8(0x3C4, 0x18);
841 bRegTemp
= VGAIN8(0x3C5);
844 bRegTemp
|= 0x40; /* force the preq always higher than treq */
845 VGAOUT8(0x3C5, bRegTemp
);
849 /*=* R1 Display FIFO depth (384 /8 -1 -> 0xbf) SR17[7:0] (8bits) *=*/
850 VGAOUT8(0x3c4, 0x17);
851 VGAOUT8(0x3c5, 0xbf);
853 /*=* R2 Display fetch datum threshold value (328/4 -> 0x52)
854 SR16[5:0], SR16[7] (7bits) *=*/
855 VGAOUT8(0x3c4, 0x16);
856 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
857 bRegTemp
|= (0x52 & 0x3F);
858 bRegTemp
|= ((0x52 & 0x40) << 1);
859 VGAOUT8(0x3c5, bRegTemp
);
861 /*=* R3 Switch to the highest agent threshold value (74 -> 0x4a)
862 SR18[5:0], SR18[7] (7bits) *=*/
863 VGAOUT8(0x3c4, 0x18);
864 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
865 bRegTemp
|= (0x4a & 0x3F);
866 bRegTemp
|= ((0x4a & 0x40) << 1);
867 VGAOUT8(0x3c5, bRegTemp
);
869 /*=* R4 Fetch Number for a scan line (unit: 8 bytes)
870 SR1C[7:0], SR1D[1:0] (10bits) *=*/
871 wRegTemp
= (pBIOSInfo
->offsetWidthByQWord
>> 1) + 4;
872 VGAOUT8(0x3c4, 0x1c);
873 VGAOUT8(0x3c5, (u_int8_t
)(wRegTemp
& 0xFF));
874 VGAOUT8(0x3c4, 0x1d);
875 bRegTemp
= VGAIN8(0x3c5) & ~0x03;
876 VGAOUT8(0x3c5, bRegTemp
| ((wRegTemp
& 0x300) >> 8));
878 if (ctx
->shared
.virtualWidth
>= 1400 && ctx
->bpp
== 32)
880 /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/
881 VGAOUT8(0x3c4, 0x22);
882 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
883 VGAOUT8(0x3c5, bRegTemp
| 0x10);
887 /*=* Max. length for a request SR22[4:0]
888 (128/4 -> over flow 0x0) *=*/
889 VGAOUT8(0x3c4, 0x22);
890 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
891 VGAOUT8(0x3c5, bRegTemp
);
895 /*=* R1 Display FIFO depth (96-1 -> 0x5f) SR17[7:0] (8bits) *=*/
896 VGAOUT8(0x3c4, 0x17);
897 VGAOUT8(0x3c5, 0x5f);
899 /*=* R2 Display fetch datum threshold value (32 -> 0x20)
900 SR16[5:0], SR16[7] (7bits) *=*/
901 VGAOUT8(0x3c4, 0x16);
902 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
903 bRegTemp
|= (0x20 & 0x3F);
904 bRegTemp
|= ((0x20 & 0x40) << 1);
905 VGAOUT8(0x3c5, bRegTemp
);
907 /*=* R3 Switch to the highest agent threshold value (16 -> 0x10)
908 SR18[5:0], SR18[7] (7bits) *=*/
909 VGAOUT8(0x3c4, 0x18);
910 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
911 bRegTemp
|= (0x10 & 0x3F);
912 bRegTemp
|= ((0x10 & 0x40) << 1);
913 VGAOUT8(0x3c5, bRegTemp
);
915 /*=* R4 Fetch Number for a scan line (unit: 8 bytes)
916 SR1C[7:0], SR1D[1:0] (10bits) *=*/
917 wRegTemp
= (pBIOSInfo
->offsetWidthByQWord
>> 1) + 4;
918 VGAOUT8(0x3c4, 0x1c);
919 VGAOUT8(0x3c5, (u_int8_t
)(wRegTemp
& 0xFF));
920 VGAOUT8(0x3c4, 0x1d);
921 bRegTemp
= VGAIN8(0x3c5) & ~0x03;
922 VGAOUT8(0x3c5, bRegTemp
| ((wRegTemp
& 0x300) >> 8));
924 if (ctx
->shared
.virtualWidth
>= 1400 && ctx
->bpp
== 32)
926 /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/
927 VGAOUT8(0x3c4, 0x22);
928 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
929 VGAOUT8(0x3c5, bRegTemp
| 0x10);
933 /*=* Max. length for a request SR22[4:0] (0x1F) *=*/
934 VGAOUT8(0x3c4, 0x22);
935 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
936 VGAOUT8(0x3c5, bRegTemp
| 0x1F);
944 static void VIAInitialize2DEngine(DRIDriverContext
*ctx
)
946 VIAPtr pVia
= VIAPTR(ctx
);
947 u_int32_t dwVQStartAddr
, dwVQEndAddr
;
948 u_int32_t dwVQLen
, dwVQStartL
, dwVQEndL
, dwVQStartEndH
;
951 /* init 2D engine regs to reset 2D engine */
952 VIASETREG(0x04, 0x0);
953 VIASETREG(0x08, 0x0);
954 VIASETREG(0x0c, 0x0);
955 VIASETREG(0x10, 0x0);
956 VIASETREG(0x14, 0x0);
957 VIASETREG(0x18, 0x0);
958 VIASETREG(0x1c, 0x0);
959 VIASETREG(0x20, 0x0);
960 VIASETREG(0x24, 0x0);
961 VIASETREG(0x28, 0x0);
962 VIASETREG(0x2c, 0x0);
963 VIASETREG(0x30, 0x0);
964 VIASETREG(0x34, 0x0);
965 VIASETREG(0x38, 0x0);
966 VIASETREG(0x3c, 0x0);
967 VIASETREG(0x40, 0x0);
971 /* Init AGP and VQ regs */
972 VIASETREG(0x43c, 0x00100000);
973 VIASETREG(0x440, 0x00000000);
974 VIASETREG(0x440, 0x00333004);
975 VIASETREG(0x440, 0x60000000);
976 VIASETREG(0x440, 0x61000000);
977 VIASETREG(0x440, 0x62000000);
978 VIASETREG(0x440, 0x63000000);
979 VIASETREG(0x440, 0x64000000);
980 VIASETREG(0x440, 0x7D000000);
982 VIASETREG(0x43c, 0xfe020000);
983 VIASETREG(0x440, 0x00000000);
985 if (pVia
->VQStart
!= 0) {
987 dwVQStartAddr
= pVia
->VQStart
;
988 dwVQEndAddr
= pVia
->VQEnd
;
989 dwVQStartL
= 0x50000000 | (dwVQStartAddr
& 0xFFFFFF);
990 dwVQEndL
= 0x51000000 | (dwVQEndAddr
& 0xFFFFFF);
991 dwVQStartEndH
= 0x52000000 | ((dwVQStartAddr
& 0xFF000000) >> 24) |
992 ((dwVQEndAddr
& 0xFF000000) >> 16);
993 dwVQLen
= 0x53000000 | (VIA_VQ_SIZE
>> 3);
995 VIASETREG(0x43c, 0x00fe0000);
996 VIASETREG(0x440, 0x080003fe);
997 VIASETREG(0x440, 0x0a00027c);
998 VIASETREG(0x440, 0x0b000260);
999 VIASETREG(0x440, 0x0c000274);
1000 VIASETREG(0x440, 0x0d000264);
1001 VIASETREG(0x440, 0x0e000000);
1002 VIASETREG(0x440, 0x0f000020);
1003 VIASETREG(0x440, 0x1000027e);
1004 VIASETREG(0x440, 0x110002fe);
1005 VIASETREG(0x440, 0x200f0060);
1007 VIASETREG(0x440, 0x00000006);
1008 VIASETREG(0x440, 0x40008c0f);
1009 VIASETREG(0x440, 0x44000000);
1010 VIASETREG(0x440, 0x45080c04);
1011 VIASETREG(0x440, 0x46800408);
1013 VIASETREG(0x440, dwVQStartEndH
);
1014 VIASETREG(0x440, dwVQStartL
);
1015 VIASETREG(0x440, dwVQEndL
);
1016 VIASETREG(0x440, dwVQLen
);
1020 VIASETREG(0x43c, 0x00fe0000);
1021 VIASETREG(0x440, 0x00000004);
1022 VIASETREG(0x440, 0x40008c0f);
1023 VIASETREG(0x440, 0x44000000);
1024 VIASETREG(0x440, 0x45080c04);
1025 VIASETREG(0x440, 0x46800408);
1032 dwGEMode
|= VIA_GEM_16bpp
;
1035 dwGEMode
|= VIA_GEM_32bpp
;
1038 dwGEMode
|= VIA_GEM_8bpp
;
1043 switch (ctx
->shared
.virtualWidth
) {
1045 dwGEMode
|= VIA_GEM_800
;
1048 dwGEMode
|= VIA_GEM_1024
;
1051 dwGEMode
|= VIA_GEM_1280
;
1054 dwGEMode
|= VIA_GEM_1600
;
1057 dwGEMode
|= VIA_GEM_2048
;
1060 dwGEMode
|= VIA_GEM_640
;
1067 /* Set BPP and Pitch */
1068 VIASETREG(VIA_REG_GEMODE
, dwGEMode
);
1070 /* Set Src and Dst base address and pitch, pitch is qword */
1071 VIASETREG(VIA_REG_SRCBASE
, 0x0);
1072 VIASETREG(VIA_REG_DSTBASE
, 0x0);
1073 VIASETREG(VIA_REG_PITCH
, VIA_PITCH_ENABLE
|
1074 ((ctx
->shared
.virtualWidth
* ctx
->bpp
>> 3) >> 3) |
1075 (((ctx
->shared
.virtualWidth
* ctx
->bpp
>> 3) >> 3) << 16));
1078 static int b3DRegsInitialized
= 0;
1080 static void VIAInitialize3DEngine(DRIDriverContext
*ctx
)
1082 VIAPtr pVia
= VIAPTR(ctx
);
1085 if (!b3DRegsInitialized
)
1088 VIASETREG(0x43C, 0x00010000);
1090 for (i
= 0; i
<= 0x7D; i
++)
1092 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1095 VIASETREG(0x43C, 0x00020000);
1097 for (i
= 0; i
<= 0x94; i
++)
1099 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1102 VIASETREG(0x440, 0x82400000);
1104 VIASETREG(0x43C, 0x01020000);
1107 for (i
= 0; i
<= 0x94; i
++)
1109 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1112 VIASETREG(0x440, 0x82400000);
1113 VIASETREG(0x43C, 0xfe020000);
1115 for (i
= 0; i
<= 0x03; i
++)
1117 VIASETREG(0x440, (u_int32_t
) i
<< 24);
1120 VIASETREG(0x43C, 0x00030000);
1122 for (i
= 0; i
<= 0xff; i
++)
1124 VIASETREG(0x440, 0);
1126 VIASETREG(0x43C, 0x00100000);
1127 VIASETREG(0x440, 0x00333004);
1128 VIASETREG(0x440, 0x10000002);
1129 VIASETREG(0x440, 0x60000000);
1130 VIASETREG(0x440, 0x61000000);
1131 VIASETREG(0x440, 0x62000000);
1132 VIASETREG(0x440, 0x63000000);
1133 VIASETREG(0x440, 0x64000000);
1135 VIASETREG(0x43C, 0x00fe0000);
1137 if (pVia
->ChipRev
>= 3 )
1138 VIASETREG(0x440,0x40008c0f);
1140 VIASETREG(0x440,0x4000800f);
1142 VIASETREG(0x440,0x44000000);
1143 VIASETREG(0x440,0x45080C04);
1144 VIASETREG(0x440,0x46800408);
1145 VIASETREG(0x440,0x50000000);
1146 VIASETREG(0x440,0x51000000);
1147 VIASETREG(0x440,0x52000000);
1148 VIASETREG(0x440,0x53000000);
1150 b3DRegsInitialized
= 1;
1151 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1152 "3D Engine has been initialized.\n");
1155 VIASETREG(0x43C,0x00fe0000);
1156 VIASETREG(0x440,0x08000001);
1157 VIASETREG(0x440,0x0A000183);
1158 VIASETREG(0x440,0x0B00019F);
1159 VIASETREG(0x440,0x0C00018B);
1160 VIASETREG(0x440,0x0D00019B);
1161 VIASETREG(0x440,0x0E000000);
1162 VIASETREG(0x440,0x0F000000);
1163 VIASETREG(0x440,0x10000000);
1164 VIASETREG(0x440,0x11000000);
1165 VIASETREG(0x440,0x20000000);
1169 WaitIdleCLE266(VIAPtr pVia
)
1175 while (!(VIAGETREG(VIA_REG_STATUS
) & VIA_VR_QUEUE_BUSY
) && (loop
++ < MAXLOOP
))
1178 while ((VIAGETREG(VIA_REG_STATUS
) &
1179 (VIA_CMD_RGTR_BUSY
| VIA_2D_ENG_BUSY
| VIA_3D_ENG_BUSY
)) &&
1183 return loop
>= MAXLOOP
;
1186 static int viaInitFBDev(DRIDriverContext
*ctx
)
1188 VIAPtr pVia
= CALLOC(sizeof(*pVia
));
1190 ctx
->driverPrivate
= (void *)pVia
;
1192 switch (ctx
->chipset
) {
1193 case PCI_CHIP_CLE3122
:
1194 case PCI_CHIP_CLE3022
:
1195 pVia
->Chipset
= VIA_CLE266
;
1197 case PCI_CHIP_VT7205
:
1198 case PCI_CHIP_VT3205
:
1199 pVia
->Chipset
= VIA_KM400
;
1201 case PCI_CHIP_VT3204
:
1202 pVia
->Chipset
= VIA_K8M800
;
1204 case PCI_CHIP_VT3259
:
1205 pVia
->Chipset
= VIA_PM800
;
1208 xf86DrvMsg(0, X_ERROR
, "VIA: Unknown device ID (0x%x)\n", ctx
->chipset
);
1211 /* _SOLO TODO XXX need to read ChipRev too */
1214 pVia
->videoRambytes
= ctx
->shared
.fbSize
;
1215 pVia
->MmioBase
= ctx
->MMIOStart
;
1216 pVia
->FrameBufferBase
= ctx
->FBStart
& 0xfc000000;
1218 pVia
->FBFreeStart
= ctx
->shared
.virtualWidth
* ctx
->cpp
*
1219 ctx
->shared
.virtualHeight
;
1222 /* Alloc a second framebuffer for the second head */
1223 pVia
->FBFreeStart
+= ctx
->shared
.virtualWidth
* ctx
->cpp
*
1224 ctx
->shared
.virtualHeight
;
1227 pVia
->VQStart
= pVia
->FBFreeStart
;
1228 pVia
->VQEnd
= pVia
->FBFreeStart
+ VIA_VQ_SIZE
- 1;
1230 pVia
->FBFreeStart
+= VIA_VQ_SIZE
;
1232 pVia
->FBFreeEnd
= pVia
->videoRambytes
;
1234 if (!VIADRIScreenInit(ctx
))
1240 static void viaHaltFBDev(DRIDriverContext
*ctx
)
1242 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
1243 drmClose(ctx
->drmFD
);
1245 if (ctx
->driverPrivate
) {
1246 free(ctx
->driverPrivate
);
1247 ctx
->driverPrivate
= 0;
1251 static int viaEngineShutdown(const DRIDriverContext
*ctx
)
1256 static int viaEngineRestore(const DRIDriverContext
*ctx
)
1261 const struct DRIDriverRec __driDriver
=
1264 viaPostValidateMode
,