2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
37 #include "via_context.h"
39 #include "via_driver.h"
42 static void VIAEnableMMIO(DRIDriverContext
* ctx
);
43 static void VIADisableMMIO(DRIDriverContext
* ctx
);
44 static void VIADisableExtendedFIFO(DRIDriverContext
*ctx
);
45 static void VIAEnableExtendedFIFO(DRIDriverContext
*ctx
);
46 static void VIAInitialize2DEngine(DRIDriverContext
*ctx
);
47 static void VIAInitialize3DEngine(DRIDriverContext
*ctx
);
49 static int VIADRIScreenInit(DRIDriverContext
* ctx
);
50 static void VIADRICloseScreen(DRIDriverContext
* ctx
);
51 static int VIADRIFinishScreenInit(DRIDriverContext
* ctx
);
53 /* _SOLO : missing macros normally defined by X code */
54 #define xf86DrvMsg(a, b, ...) fprintf(stderr, __VA_ARGS__)
55 #define MMIO_IN8(base, addr) ((*(((volatile uint8_t*)base)+(addr)))+0)
56 #define MMIO_OUT8(base, addr, val) ((*(((volatile uint8_t*)base)+(addr)))=((uint8_t)val))
57 #define MMIO_OUT16(base, addr, val) ((*(volatile uint16_t*)(((uint8_t*)base)+(addr)))=((uint16_t)val))
61 #define AGP_PAGE_SIZE 4096
62 #define AGP_PAGES 8192
63 #define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES)
64 #define AGP_CMDBUF_PAGES 512
65 #define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES)
67 static char VIAKernelDriverName
[] = "via";
68 static char VIAClientDriverName
[] = "unichrome";
70 static int VIADRIAgpInit(const DRIDriverContext
*ctx
, VIAPtr pVia
);
71 static int VIADRIPciInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
72 static int VIADRIFBInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
73 static int VIADRIKernelInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
74 static int VIADRIMapInit(DRIDriverContext
* ctx
, VIAPtr pVia
);
76 static void VIADRIIrqInit( DRIDriverContext
*ctx
)
78 VIAPtr pVia
= VIAPTR(ctx
);
79 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
81 pVIADRI
->irqEnabled
= drmGetInterruptFromBusID(pVia
->drmFD
,
86 if ((drmCtlInstHandler(pVia
->drmFD
, pVIADRI
->irqEnabled
))) {
87 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
88 "[drm] Failure adding irq handler. "
89 "Falling back to irq-free operation.\n");
90 pVIADRI
->irqEnabled
= 0;
93 if (pVIADRI
->irqEnabled
)
94 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
95 "[drm] Irq handler installed, using IRQ %d.\n",
99 static void VIADRIIrqExit( DRIDriverContext
*ctx
) {
100 VIAPtr pVia
= VIAPTR(ctx
);
101 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
103 if (pVIADRI
->irqEnabled
) {
104 if (drmCtlUninstHandler(pVia
->drmFD
)) {
105 xf86DrvMsg(pScreen
-myNum
, X_INFO
,"[drm] Irq handler uninstalled.\n");
107 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
108 "[drm] Could not uninstall irq handler.\n");
113 static void VIADRIRingBufferCleanup(DRIDriverContext
*ctx
)
115 VIAPtr pVia
= VIAPTR(ctx
);
116 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
117 drm_via_dma_init_t ringBufInit
;
119 if (pVIADRI
->ringBufActive
) {
120 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
121 "[drm] Cleaning up DMA ring-buffer.\n");
122 ringBufInit
.func
= VIA_CLEANUP_DMA
;
123 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_DMA_INIT
, &ringBufInit
,
124 sizeof(ringBufInit
))) {
125 xf86DrvMsg(pScreen
->myNum
, X_WARNING
,
126 "[drm] Failed to clean up DMA ring-buffer: %d\n", errno
);
128 pVIADRI
->ringBufActive
= 0;
132 static int VIADRIRingBufferInit(DRIDriverContext
*ctx
)
134 VIAPtr pVia
= VIAPTR(ctx
);
135 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
136 drm_via_dma_init_t ringBufInit
;
137 drmVersionPtr drmVer
;
139 pVIADRI
->ringBufActive
= 0;
141 if (NULL
== (drmVer
= drmGetVersion(pVia
->drmFD
))) {
145 if (((drmVer
->version_major
<= 1) && (drmVer
->version_minor
<= 3))) {
150 * Info frome code-snippet on DRI-DEVEL list; Erdi Chen.
153 switch (pVia
->ChipId
) {
154 case PCI_CHIP_VT3259
:
155 ringBufInit
.reg_pause_addr
= 0x40c;
158 ringBufInit
.reg_pause_addr
= 0x418;
162 ringBufInit
.offset
= pVia
->agpSize
;
163 ringBufInit
.size
= AGP_CMDBUF_SIZE
;
164 ringBufInit
.func
= VIA_INIT_DMA
;
165 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_DMA_INIT
, &ringBufInit
,
166 sizeof(ringBufInit
))) {
167 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
168 "[drm] Failed to initialize DMA ring-buffer: %d\n", errno
);
171 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
172 "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP offset 0x%lx.\n",
173 ringBufInit
.size
, ringBufInit
.offset
);
175 pVIADRI
->ringBufActive
= 1;
179 static int VIADRIAgpInit(const DRIDriverContext
*ctx
, VIAPtr pVia
)
181 unsigned long agp_phys
;
184 pVIADRI
= pVia
->devPrivate
;
187 if (drmAgpAcquire(pVia
->drmFD
) < 0) {
188 xf86DrvMsg(pScreen
->myNum
, X_ERROR
, "[drm] drmAgpAcquire failed %d\n", errno
);
192 if (drmAgpEnable(pVia
->drmFD
, drmAgpGetMode(pVia
->drmFD
)&~0x0) < 0) {
193 xf86DrvMsg(pScreen
->myNum
, X_ERROR
, "[drm] drmAgpEnable failed\n");
197 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] drmAgpEnabled succeeded\n");
199 if (drmAgpAlloc(pVia
->drmFD
, AGP_SIZE
, 0, &agp_phys
, &pVia
->agpHandle
) < 0) {
200 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
201 "[drm] drmAgpAlloc failed\n");
202 drmAgpRelease(pVia
->drmFD
);
206 if (drmAgpBind(pVia
->drmFD
, pVia
->agpHandle
, 0) < 0) {
207 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
208 "[drm] drmAgpBind failed\n");
209 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
210 drmAgpRelease(pVia
->drmFD
);
216 * Place the ring-buffer last in the AGP region, and restrict the
217 * public map not to include the buffer for security reasons.
220 pVia
->agpSize
= AGP_SIZE
- AGP_CMDBUF_SIZE
;
221 pVia
->agpAddr
= drmAgpBase(pVia
->drmFD
);
222 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
223 "[drm] agpAddr = 0x%08lx\n",pVia
->agpAddr
);
225 pVIADRI
->agp
.size
= pVia
->agpSize
;
226 if (drmAddMap(pVia
->drmFD
, (drm_handle_t
)0,
227 pVIADRI
->agp
.size
, DRM_AGP
, 0,
228 &pVIADRI
->agp
.handle
) < 0) {
229 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
230 "[drm] Failed to map public agp area\n");
231 pVIADRI
->agp
.size
= 0;
234 /* Map AGP from kernel to Xserver - Not really needed */
235 drmMap(pVia
->drmFD
, pVIADRI
->agp
.handle
,pVIADRI
->agp
.size
, &agpaddr
);
237 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
238 "[drm] agpAddr = 0x%08lx\n", pVia
->agpAddr
);
239 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
240 "[drm] agpSize = 0x%08lx\n", pVia
->agpSize
);
241 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
242 "[drm] agp physical addr = 0x%08lx\n", agp_phys
);
247 agp
.size
= AGP_SIZE
-AGP_CMDBUF_SIZE
;
248 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_AGP_INIT
, &agp
,
249 sizeof(drm_via_agp_t
)) < 0) {
250 drmUnmap(&agpaddr
,pVia
->agpSize
);
251 drmRmMap(pVia
->drmFD
,pVIADRI
->agp
.handle
);
252 drmAgpUnbind(pVia
->drmFD
, pVia
->agpHandle
);
253 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
254 drmAgpRelease(pVia
->drmFD
);
262 static int VIADRIFBInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
264 int FBSize
= pVia
->FBFreeEnd
-pVia
->FBFreeStart
;
265 int FBOffset
= pVia
->FBFreeStart
;
266 VIADRIPtr pVIADRI
= pVia
->devPrivate
;
267 pVIADRI
->fbOffset
= FBOffset
;
268 pVIADRI
->fbSize
= pVia
->videoRambytes
;
272 fb
.offset
= FBOffset
;
275 if (drmCommandWrite(pVia
->drmFD
, DRM_VIA_FB_INIT
, &fb
,
276 sizeof(drm_via_fb_t
)) < 0) {
277 xf86DrvMsg(pScreen
->myNum
, X_ERROR
,
278 "[drm] failed to init frame buffer area\n");
281 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
282 "[drm] FBFreeStart= 0x%08x FBFreeEnd= 0x%08x "
284 pVia
->FBFreeStart
, pVia
->FBFreeEnd
, FBSize
);
290 static int VIADRIPciInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
295 static int VIADRIScreenInit(DRIDriverContext
* ctx
)
297 VIAPtr pVia
= VIAPTR(ctx
);
302 ctx
->shared
.SAREASize
= ((sizeof(drm_sarea_t
) + 0xfff) & 0x1000);
304 if (sizeof(drm_sarea_t
)+sizeof(drm_via_sarea_t
) > SAREA_MAX
) {
305 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
306 "Data does not fit in SAREA\n");
309 ctx
->shared
.SAREASize
= SAREA_MAX
;
312 ctx
->drmFD
= drmOpen(VIAKernelDriverName
, NULL
);
313 if (ctx
->drmFD
< 0) {
314 fprintf(stderr
, "[drm] drmOpen failed\n");
317 pVia
->drmFD
= ctx
->drmFD
;
319 err
= drmSetBusid(ctx
->drmFD
, ctx
->pciBusID
);
321 fprintf(stderr
, "[drm] drmSetBusid failed (%d, %s), %s\n",
322 ctx
->drmFD
, ctx
->pciBusID
, strerror(-err
));
326 err
= drmAddMap(ctx
->drmFD
, 0, ctx
->shared
.SAREASize
, DRM_SHM
,
327 DRM_CONTAINS_LOCK
, &ctx
->shared
.hSAREA
);
329 fprintf(stderr
, "[drm] drmAddMap failed\n");
332 fprintf(stderr
, "[drm] added %d byte SAREA at 0x%08lx\n",
333 ctx
->shared
.SAREASize
, ctx
->shared
.hSAREA
);
335 if (drmMap(ctx
->drmFD
,
337 ctx
->shared
.SAREASize
,
338 (drmAddressPtr
)(&ctx
->pSAREA
)) < 0)
340 fprintf(stderr
, "[drm] drmMap failed\n");
343 memset(ctx
->pSAREA
, 0, ctx
->shared
.SAREASize
);
344 fprintf(stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
345 ctx
->shared
.hSAREA
, ctx
->pSAREA
, ctx
->shared
.SAREASize
);
347 /* Need to AddMap the framebuffer and mmio regions here:
349 if (drmAddMap(ctx
->drmFD
,
350 (drm_handle_t
)ctx
->FBStart
,
358 &ctx
->shared
.hFrameBuffer
) < 0)
360 fprintf(stderr
, "[drm] drmAddMap framebuffer failed\n");
364 fprintf(stderr
, "[drm] framebuffer handle = 0x%08lx\n",
365 ctx
->shared
.hFrameBuffer
);
367 pVIADRI
= (VIADRIPtr
) CALLOC(sizeof(VIADRIRec
));
369 drmClose(ctx
->drmFD
);
372 pVia
->devPrivate
= pVIADRI
;
373 ctx
->driverClientMsg
= pVIADRI
;
374 ctx
->driverClientMsgSize
= sizeof(*pVIADRI
);
376 /* DRIScreenInit doesn't add all the common mappings. Add additional mappings here. */
377 if (!VIADRIMapInit(ctx
, pVia
)) {
378 VIADRICloseScreen(ctx
);
382 pVIADRI
->regs
.size
= VIA_MMIO_REGSIZE
;
383 pVIADRI
->regs
.handle
= pVia
->registerHandle
;
384 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] mmio Registers = 0x%08lx\n",
385 pVIADRI
->regs
.handle
);
387 if (drmMap(pVia
->drmFD
,
388 pVIADRI
->regs
.handle
,
390 (drmAddress
*)&pVia
->MapBase
) != 0)
392 VIADRICloseScreen(ctx
);
396 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] mmio mapped.\n" );
400 /* Get video memory clock. */
401 VGAOUT8(0x3D4, 0x3D);
402 pVia
->MemClk
= (VGAIN8(0x3D5) & 0xF0) >> 4;
403 xf86DrvMsg(0, X_INFO
, "[dri] MemClk (0x%x)\n", pVia
->MemClk
);
405 /* 3D rendering has noise if not enabled. */
406 VIAEnableExtendedFIFO(ctx
);
408 VIAInitialize2DEngine(ctx
);
410 /* Must disable MMIO or 3D won't work. */
413 VIAInitialize3DEngine(ctx
);
415 pVia
->IsPCI
= !VIADRIAgpInit(ctx
, pVia
);
418 VIADRIPciInit(ctx
, pVia
);
419 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] use pci.\n" );
422 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] use agp.\n" );
424 if (!(VIADRIFBInit(ctx
, pVia
))) {
425 VIADRICloseScreen(ctx
);
426 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "[dri] frame buffer initialize fail .\n" );
430 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "[dri] frame buffer initialized.\n" );
432 return VIADRIFinishScreenInit(ctx
);
436 VIADRICloseScreen(DRIDriverContext
* ctx
)
438 VIAPtr pVia
= VIAPTR(ctx
);
439 VIADRIPtr pVIADRI
=(VIADRIPtr
)pVia
->devPrivate
;
441 VIADRIRingBufferCleanup(ctx
);
444 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Unmapping MMIO registers\n");
445 drmUnmap(pVia
->MapBase
, pVIADRI
->regs
.size
);
449 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Freeing agp memory\n");
450 drmAgpFree(pVia
->drmFD
, pVia
->agpHandle
);
451 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[drm] Releasing agp module\n");
452 drmAgpRelease(pVia
->drmFD
);
456 if (pVia
->DRIIrqEnable
)
462 VIADRIFinishScreenInit(DRIDriverContext
* ctx
)
464 VIAPtr pVia
= VIAPTR(ctx
);
468 err
= drmCreateContext(ctx
->drmFD
, &ctx
->serverContext
);
470 fprintf(stderr
, "%s: drmCreateContext failed %d\n", __FUNCTION__
, err
);
474 DRM_LOCK(ctx
->drmFD
, ctx
->pSAREA
, ctx
->serverContext
, 0);
477 if (!VIADRIKernelInit(ctx
, pVia
)) {
478 VIADRICloseScreen(ctx
);
481 xf86DrvMsg(pScreen
->myNum
, X_INFO
, "[dri] kernel data initialized.\n");
483 /* set SAREA value */
485 drm_via_sarea_t
*saPriv
;
487 saPriv
=(drm_via_sarea_t
*)(((char*)ctx
->pSAREA
) +
488 sizeof(drm_sarea_t
));
490 memset(saPriv
, 0, sizeof(*saPriv
));
491 saPriv
->ctxOwner
= -1;
493 pVIADRI
=(VIADRIPtr
)pVia
->devPrivate
;
494 pVIADRI
->deviceID
=pVia
->Chipset
;
495 pVIADRI
->width
=ctx
->shared
.virtualWidth
;
496 pVIADRI
->height
=ctx
->shared
.virtualHeight
;
497 pVIADRI
->mem
=ctx
->shared
.fbSize
;
498 pVIADRI
->bytesPerPixel
= (ctx
->bpp
+7) / 8;
499 pVIADRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
501 pVIADRI
->scrnX
=pVIADRI
->width
;
502 pVIADRI
->scrnY
=pVIADRI
->height
;
506 if (pVia
->DRIIrqEnable
)
510 pVIADRI
->ringBufActive
= 0;
511 VIADRIRingBufferInit(ctx
);
516 /* Initialize the kernel data structures. */
517 static int VIADRIKernelInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
519 drm_via_init_t drmInfo
;
520 memset(&drmInfo
, 0, sizeof(drm_via_init_t
));
521 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
522 drmInfo
.func
= VIA_INIT_MAP
;
523 drmInfo
.fb_offset
= pVia
->FrameBufferBase
;
524 drmInfo
.mmio_offset
= pVia
->registerHandle
;
526 drmInfo
.agpAddr
= (uint32_t)NULL
;
528 drmInfo
.agpAddr
= (uint32_t)pVia
->agpAddr
;
530 if ((drmCommandWrite(pVia
->drmFD
, DRM_VIA_MAP_INIT
,&drmInfo
,
531 sizeof(drm_via_init_t
))) < 0)
536 /* Add a map for the MMIO registers */
537 static int VIADRIMapInit(DRIDriverContext
* ctx
, VIAPtr pVia
)
541 if (drmAddMap(pVia
->drmFD
, pVia
->MmioBase
, VIA_MMIO_REGSIZE
,
542 DRM_REGISTERS
, flags
, &pVia
->registerHandle
) < 0) {
546 xf86DrvMsg(pScreen
->myNum
, X_INFO
,
547 "[drm] register handle = 0x%08lx\n", pVia
->registerHandle
);
552 static int viaValidateMode(const DRIDriverContext
*ctx
)
554 VIAPtr pVia
= VIAPTR(ctx
);
559 static int viaPostValidateMode(const DRIDriverContext
*ctx
)
561 VIAPtr pVia
= VIAPTR(ctx
);
566 static void VIAEnableMMIO(DRIDriverContext
* ctx
)
568 /*vgaHWPtr hwp = VGAHWPTR(ctx);*/
569 VIAPtr pVia
= VIAPTR(ctx
);
573 if (xf86IsPrimaryPci(pVia
->PciInfo
)) {
574 /* If we are primary card, we still use std vga port. If we use
575 * MMIO, system will hang in vgaHWSave when our card used in
576 * PLE and KLE (integrated Trident MVP4)
578 vgaHWSetStdFuncs(hwp
);
581 vgaHWSetMmioFuncs(hwp
, pVia
->MapBase
, 0x8000);
586 VGAOUT8(0x3c3, val
| 0x01);
588 VGAOUT8(0x3c2, val
| 0x01);
590 /* Unlock Extended IO Space */
591 VGAOUT8(0x3c4, 0x10);
592 VGAOUT8(0x3c5, 0x01);
595 if(!pVia
->IsSecondary
) {
596 VGAOUT8(0x3c4, 0x1a);
599 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "primary val = %x\n", val
);
601 VGAOUT8(0x3c5, val
| 0x68);
604 VGAOUT8(0x3c4, 0x1a);
607 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
, "secondary val = %x\n", val
);
609 VGAOUT8(0x3c5, val
| 0x38);
612 /* Unlock CRTC registers */
613 VGAOUT8(0x3d4, 0x47);
614 VGAOUT8(0x3d5, 0x00);
619 static void VIADisableMMIO(DRIDriverContext
* ctx
)
621 VIAPtr pVia
= VIAPTR(ctx
);
624 VGAOUT8(0x3c4, 0x1a);
626 VGAOUT8(0x3c5, val
& 0x97);
631 static void VIADisableExtendedFIFO(DRIDriverContext
*ctx
)
633 VIAPtr pVia
= VIAPTR(ctx
);
634 uint32_t dwGE230
, dwGE298
;
636 /* Cause of exit XWindow will dump back register value, others chipset no
637 * need to set extended fifo value */
638 if (pVia
->Chipset
== VIA_CLE266
&& pVia
->ChipRev
< 15 &&
639 (ctx
->shared
.virtualWidth
> 1024 || pVia
->HasSecondary
)) {
640 /* Turn off Extend FIFO */
642 dwGE298
= VIAGETREG(0x298);
643 VIASETREG(0x298, dwGE298
| 0x20000000);
645 dwGE230
= VIAGETREG(0x230);
646 VIASETREG(0x230, dwGE230
& ~0x00200000);
648 dwGE298
= VIAGETREG(0x298);
649 VIASETREG(0x298, dwGE298
& ~0x20000000);
653 static void VIAEnableExtendedFIFO(DRIDriverContext
*ctx
)
655 VIAPtr pVia
= VIAPTR(ctx
);
657 uint32_t dwGE230
, dwGE298
;
659 switch (pVia
->Chipset
) {
661 if (pVia
->ChipRev
> 14) { /* For 3123Cx */
662 if (pVia
->HasSecondary
) { /* SAMM or DuoView case */
663 if (ctx
->shared
.virtualWidth
>= 1024)
666 VGAOUT8(0x3C4, 0x16);
667 bRegTemp
= VGAIN8(0x3C5);
670 VGAOUT8(0x3C5, bRegTemp
);
672 VGAOUT8(0x3C4, 0x17);
673 bRegTemp
= VGAIN8(0x3C5);
676 VGAOUT8(0x3C5, bRegTemp
);
677 pVia
->EnableExtendedFIFO
= GL_TRUE
;
680 else /* Single view or Simultaneoue case */
682 if (ctx
->shared
.virtualWidth
> 1024)
685 VGAOUT8(0x3C4, 0x16);
686 bRegTemp
= VGAIN8(0x3C5);
689 VGAOUT8(0x3C5, bRegTemp
);
691 VGAOUT8(0x3C4, 0x17);
692 bRegTemp
= VGAIN8(0x3C5);
695 VGAOUT8(0x3C5, bRegTemp
);
696 pVia
->EnableExtendedFIFO
= GL_TRUE
;
700 VGAOUT8(0x3C4, 0x18);
701 bRegTemp
= VGAIN8(0x3C5);
704 bRegTemp
|= 0x40; /* force the preq always higher than treq */
705 VGAOUT8(0x3C5, bRegTemp
);
707 else { /* for 3123Ax */
708 if (ctx
->shared
.virtualWidth
> 1024 || pVia
->HasSecondary
) {
709 /* Turn on Extend FIFO */
711 dwGE298
= VIAGETREG(0x298);
712 VIASETREG(0x298, dwGE298
| 0x20000000);
714 dwGE230
= VIAGETREG(0x230);
715 VIASETREG(0x230, dwGE230
| 0x00200000);
717 dwGE298
= VIAGETREG(0x298);
718 VIASETREG(0x298, dwGE298
& ~0x20000000);
721 VGAOUT8(0x3C4, 0x16);
722 bRegTemp
= VGAIN8(0x3C5);
725 /* bRegTemp |= 0x10; */
726 VGAOUT8(0x3C5, bRegTemp
);
728 VGAOUT8(0x3C4, 0x17);
729 bRegTemp
= VGAIN8(0x3C5);
732 /*bRegTemp |= 0x1F;*/
733 VGAOUT8(0x3C5, bRegTemp
);
735 VGAOUT8(0x3C4, 0x18);
736 bRegTemp
= VGAIN8(0x3C5);
739 bRegTemp
|= 0x40; /* force the preq always higher than treq */
740 VGAOUT8(0x3C5, bRegTemp
);
741 pVia
->EnableExtendedFIFO
= GL_TRUE
;
746 if (pVia
->HasSecondary
) { /* SAMM or DuoView case */
747 if ((ctx
->shared
.virtualWidth
>= 1600) &&
748 (pVia
->MemClk
<= VIA_MEM_DDR200
)) {
749 /* enable CRT extendded FIFO */
750 VGAOUT8(0x3C4, 0x17);
751 VGAOUT8(0x3C5, 0x1C);
752 /* revise second display queue depth and read threshold */
753 VGAOUT8(0x3C4, 0x16);
754 bRegTemp
= VGAIN8(0x3C5);
756 bRegTemp
= (bRegTemp
) | (0x09);
757 VGAOUT8(0x3C5, bRegTemp
);
760 /* enable CRT extendded FIFO */
761 VGAOUT8(0x3C4, 0x17);
763 /* revise second display queue depth and read threshold */
764 VGAOUT8(0x3C4, 0x16);
765 bRegTemp
= VGAIN8(0x3C5);
767 bRegTemp
= (bRegTemp
) | (0x1C);
768 VGAOUT8(0x3C5, bRegTemp
);
771 VGAOUT8(0x3C4, 0x18);
772 bRegTemp
= VGAIN8(0x3C5);
775 bRegTemp
|= 0x40; /* force the preq always higher than treq */
776 VGAOUT8(0x3C5, bRegTemp
);
777 pVia
->EnableExtendedFIFO
= GL_TRUE
;
780 if ( (ctx
->shared
.virtualWidth
> 1024) && (ctx
->shared
.virtualWidth
<= 1280) )
782 /* enable CRT extendded FIFO */
783 VGAOUT8(0x3C4, 0x17);
784 VGAOUT8(0x3C5, 0x3F);
785 /* revise second display queue depth and read threshold */
786 VGAOUT8(0x3C4, 0x16);
787 bRegTemp
= VGAIN8(0x3C5);
789 bRegTemp
= (bRegTemp
) | (0x17);
790 VGAOUT8(0x3C5, bRegTemp
);
791 pVia
->EnableExtendedFIFO
= GL_TRUE
;
793 else if ((ctx
->shared
.virtualWidth
> 1280))
795 /* enable CRT extendded FIFO */
796 VGAOUT8(0x3C4, 0x17);
797 VGAOUT8(0x3C5, 0x3F);
798 /* revise second display queue depth and read threshold */
799 VGAOUT8(0x3C4, 0x16);
800 bRegTemp
= VGAIN8(0x3C5);
802 bRegTemp
= (bRegTemp
) | (0x1C);
803 VGAOUT8(0x3C5, bRegTemp
);
804 pVia
->EnableExtendedFIFO
= GL_TRUE
;
808 /* enable CRT extendded FIFO */
809 VGAOUT8(0x3C4, 0x17);
810 VGAOUT8(0x3C5, 0x3F);
811 /* revise second display queue depth and read threshold */
812 VGAOUT8(0x3C4, 0x16);
813 bRegTemp
= VGAIN8(0x3C5);
815 bRegTemp
= (bRegTemp
) | (0x10);
816 VGAOUT8(0x3C5, bRegTemp
);
819 VGAOUT8(0x3C4, 0x18);
820 bRegTemp
= VGAIN8(0x3C5);
823 bRegTemp
|= 0x40; /* force the preq always higher than treq */
824 VGAOUT8(0x3C5, bRegTemp
);
828 /*=* R1 Display FIFO depth (384 /8 -1 -> 0xbf) SR17[7:0] (8bits) *=*/
829 VGAOUT8(0x3c4, 0x17);
830 VGAOUT8(0x3c5, 0xbf);
832 /*=* R2 Display fetch datum threshold value (328/4 -> 0x52)
833 SR16[5:0], SR16[7] (7bits) *=*/
834 VGAOUT8(0x3c4, 0x16);
835 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
836 bRegTemp
|= (0x52 & 0x3F);
837 bRegTemp
|= ((0x52 & 0x40) << 1);
838 VGAOUT8(0x3c5, bRegTemp
);
840 /*=* R3 Switch to the highest agent threshold value (74 -> 0x4a)
841 SR18[5:0], SR18[7] (7bits) *=*/
842 VGAOUT8(0x3c4, 0x18);
843 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
844 bRegTemp
|= (0x4a & 0x3F);
845 bRegTemp
|= ((0x4a & 0x40) << 1);
846 VGAOUT8(0x3c5, bRegTemp
);
848 /*=* R4 Fetch Number for a scan line (unit: 8 bytes)
849 SR1C[7:0], SR1D[1:0] (10bits) *=*/
850 wRegTemp
= (pBIOSInfo
->offsetWidthByQWord
>> 1) + 4;
851 VGAOUT8(0x3c4, 0x1c);
852 VGAOUT8(0x3c5, (uint8_t)(wRegTemp
& 0xFF));
853 VGAOUT8(0x3c4, 0x1d);
854 bRegTemp
= VGAIN8(0x3c5) & ~0x03;
855 VGAOUT8(0x3c5, bRegTemp
| ((wRegTemp
& 0x300) >> 8));
857 if (ctx
->shared
.virtualWidth
>= 1400 && ctx
->bpp
== 32)
859 /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/
860 VGAOUT8(0x3c4, 0x22);
861 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
862 VGAOUT8(0x3c5, bRegTemp
| 0x10);
866 /*=* Max. length for a request SR22[4:0]
867 (128/4 -> over flow 0x0) *=*/
868 VGAOUT8(0x3c4, 0x22);
869 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
870 VGAOUT8(0x3c5, bRegTemp
);
874 /*=* R1 Display FIFO depth (96-1 -> 0x5f) SR17[7:0] (8bits) *=*/
875 VGAOUT8(0x3c4, 0x17);
876 VGAOUT8(0x3c5, 0x5f);
878 /*=* R2 Display fetch datum threshold value (32 -> 0x20)
879 SR16[5:0], SR16[7] (7bits) *=*/
880 VGAOUT8(0x3c4, 0x16);
881 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
882 bRegTemp
|= (0x20 & 0x3F);
883 bRegTemp
|= ((0x20 & 0x40) << 1);
884 VGAOUT8(0x3c5, bRegTemp
);
886 /*=* R3 Switch to the highest agent threshold value (16 -> 0x10)
887 SR18[5:0], SR18[7] (7bits) *=*/
888 VGAOUT8(0x3c4, 0x18);
889 bRegTemp
= VGAIN8(0x3c5) & ~0xBF;
890 bRegTemp
|= (0x10 & 0x3F);
891 bRegTemp
|= ((0x10 & 0x40) << 1);
892 VGAOUT8(0x3c5, bRegTemp
);
894 /*=* R4 Fetch Number for a scan line (unit: 8 bytes)
895 SR1C[7:0], SR1D[1:0] (10bits) *=*/
896 wRegTemp
= (pBIOSInfo
->offsetWidthByQWord
>> 1) + 4;
897 VGAOUT8(0x3c4, 0x1c);
898 VGAOUT8(0x3c5, (uint8_t)(wRegTemp
& 0xFF));
899 VGAOUT8(0x3c4, 0x1d);
900 bRegTemp
= VGAIN8(0x3c5) & ~0x03;
901 VGAOUT8(0x3c5, bRegTemp
| ((wRegTemp
& 0x300) >> 8));
903 if (ctx
->shared
.virtualWidth
>= 1400 && ctx
->bpp
== 32)
905 /*=* Max. length for a request SR22[4:0] (64/4 -> 0x10) *=*/
906 VGAOUT8(0x3c4, 0x22);
907 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
908 VGAOUT8(0x3c5, bRegTemp
| 0x10);
912 /*=* Max. length for a request SR22[4:0] (0x1F) *=*/
913 VGAOUT8(0x3c4, 0x22);
914 bRegTemp
= VGAIN8(0x3c5) & ~0x1F;
915 VGAOUT8(0x3c5, bRegTemp
| 0x1F);
923 static void VIAInitialize2DEngine(DRIDriverContext
*ctx
)
925 VIAPtr pVia
= VIAPTR(ctx
);
926 uint32_t dwVQStartAddr
, dwVQEndAddr
;
927 uint32_t dwVQLen
, dwVQStartL
, dwVQEndL
, dwVQStartEndH
;
930 /* init 2D engine regs to reset 2D engine */
931 VIASETREG(0x04, 0x0);
932 VIASETREG(0x08, 0x0);
933 VIASETREG(0x0c, 0x0);
934 VIASETREG(0x10, 0x0);
935 VIASETREG(0x14, 0x0);
936 VIASETREG(0x18, 0x0);
937 VIASETREG(0x1c, 0x0);
938 VIASETREG(0x20, 0x0);
939 VIASETREG(0x24, 0x0);
940 VIASETREG(0x28, 0x0);
941 VIASETREG(0x2c, 0x0);
942 VIASETREG(0x30, 0x0);
943 VIASETREG(0x34, 0x0);
944 VIASETREG(0x38, 0x0);
945 VIASETREG(0x3c, 0x0);
946 VIASETREG(0x40, 0x0);
950 /* Init AGP and VQ regs */
951 VIASETREG(0x43c, 0x00100000);
952 VIASETREG(0x440, 0x00000000);
953 VIASETREG(0x440, 0x00333004);
954 VIASETREG(0x440, 0x60000000);
955 VIASETREG(0x440, 0x61000000);
956 VIASETREG(0x440, 0x62000000);
957 VIASETREG(0x440, 0x63000000);
958 VIASETREG(0x440, 0x64000000);
959 VIASETREG(0x440, 0x7D000000);
961 VIASETREG(0x43c, 0xfe020000);
962 VIASETREG(0x440, 0x00000000);
964 if (pVia
->VQStart
!= 0) {
966 dwVQStartAddr
= pVia
->VQStart
;
967 dwVQEndAddr
= pVia
->VQEnd
;
968 dwVQStartL
= 0x50000000 | (dwVQStartAddr
& 0xFFFFFF);
969 dwVQEndL
= 0x51000000 | (dwVQEndAddr
& 0xFFFFFF);
970 dwVQStartEndH
= 0x52000000 | ((dwVQStartAddr
& 0xFF000000) >> 24) |
971 ((dwVQEndAddr
& 0xFF000000) >> 16);
972 dwVQLen
= 0x53000000 | (VIA_VQ_SIZE
>> 3);
974 VIASETREG(0x43c, 0x00fe0000);
975 VIASETREG(0x440, 0x080003fe);
976 VIASETREG(0x440, 0x0a00027c);
977 VIASETREG(0x440, 0x0b000260);
978 VIASETREG(0x440, 0x0c000274);
979 VIASETREG(0x440, 0x0d000264);
980 VIASETREG(0x440, 0x0e000000);
981 VIASETREG(0x440, 0x0f000020);
982 VIASETREG(0x440, 0x1000027e);
983 VIASETREG(0x440, 0x110002fe);
984 VIASETREG(0x440, 0x200f0060);
986 VIASETREG(0x440, 0x00000006);
987 VIASETREG(0x440, 0x40008c0f);
988 VIASETREG(0x440, 0x44000000);
989 VIASETREG(0x440, 0x45080c04);
990 VIASETREG(0x440, 0x46800408);
992 VIASETREG(0x440, dwVQStartEndH
);
993 VIASETREG(0x440, dwVQStartL
);
994 VIASETREG(0x440, dwVQEndL
);
995 VIASETREG(0x440, dwVQLen
);
999 VIASETREG(0x43c, 0x00fe0000);
1000 VIASETREG(0x440, 0x00000004);
1001 VIASETREG(0x440, 0x40008c0f);
1002 VIASETREG(0x440, 0x44000000);
1003 VIASETREG(0x440, 0x45080c04);
1004 VIASETREG(0x440, 0x46800408);
1011 dwGEMode
|= VIA_GEM_16bpp
;
1014 dwGEMode
|= VIA_GEM_32bpp
;
1017 dwGEMode
|= VIA_GEM_8bpp
;
1022 switch (ctx
->shared
.virtualWidth
) {
1024 dwGEMode
|= VIA_GEM_800
;
1027 dwGEMode
|= VIA_GEM_1024
;
1030 dwGEMode
|= VIA_GEM_1280
;
1033 dwGEMode
|= VIA_GEM_1600
;
1036 dwGEMode
|= VIA_GEM_2048
;
1039 dwGEMode
|= VIA_GEM_640
;
1046 /* Set BPP and Pitch */
1047 VIASETREG(VIA_REG_GEMODE
, dwGEMode
);
1049 /* Set Src and Dst base address and pitch, pitch is qword */
1050 VIASETREG(VIA_REG_SRCBASE
, 0x0);
1051 VIASETREG(VIA_REG_DSTBASE
, 0x0);
1052 VIASETREG(VIA_REG_PITCH
, VIA_PITCH_ENABLE
|
1053 ((ctx
->shared
.virtualWidth
* ctx
->bpp
>> 3) >> 3) |
1054 (((ctx
->shared
.virtualWidth
* ctx
->bpp
>> 3) >> 3) << 16));
1057 static int b3DRegsInitialized
= 0;
1059 static void VIAInitialize3DEngine(DRIDriverContext
*ctx
)
1061 VIAPtr pVia
= VIAPTR(ctx
);
1064 if (!b3DRegsInitialized
)
1067 VIASETREG(0x43C, 0x00010000);
1069 for (i
= 0; i
<= 0x7D; i
++)
1071 VIASETREG(0x440, (uint32_t) i
<< 24);
1074 VIASETREG(0x43C, 0x00020000);
1076 for (i
= 0; i
<= 0x94; i
++)
1078 VIASETREG(0x440, (uint32_t) i
<< 24);
1081 VIASETREG(0x440, 0x82400000);
1083 VIASETREG(0x43C, 0x01020000);
1086 for (i
= 0; i
<= 0x94; i
++)
1088 VIASETREG(0x440, (uint32_t) i
<< 24);
1091 VIASETREG(0x440, 0x82400000);
1092 VIASETREG(0x43C, 0xfe020000);
1094 for (i
= 0; i
<= 0x03; i
++)
1096 VIASETREG(0x440, (uint32_t) i
<< 24);
1099 VIASETREG(0x43C, 0x00030000);
1101 for (i
= 0; i
<= 0xff; i
++)
1103 VIASETREG(0x440, 0);
1105 VIASETREG(0x43C, 0x00100000);
1106 VIASETREG(0x440, 0x00333004);
1107 VIASETREG(0x440, 0x10000002);
1108 VIASETREG(0x440, 0x60000000);
1109 VIASETREG(0x440, 0x61000000);
1110 VIASETREG(0x440, 0x62000000);
1111 VIASETREG(0x440, 0x63000000);
1112 VIASETREG(0x440, 0x64000000);
1114 VIASETREG(0x43C, 0x00fe0000);
1116 if (pVia
->ChipRev
>= 3 )
1117 VIASETREG(0x440,0x40008c0f);
1119 VIASETREG(0x440,0x4000800f);
1121 VIASETREG(0x440,0x44000000);
1122 VIASETREG(0x440,0x45080C04);
1123 VIASETREG(0x440,0x46800408);
1124 VIASETREG(0x440,0x50000000);
1125 VIASETREG(0x440,0x51000000);
1126 VIASETREG(0x440,0x52000000);
1127 VIASETREG(0x440,0x53000000);
1129 b3DRegsInitialized
= 1;
1130 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1131 "3D Engine has been initialized.\n");
1134 VIASETREG(0x43C,0x00fe0000);
1135 VIASETREG(0x440,0x08000001);
1136 VIASETREG(0x440,0x0A000183);
1137 VIASETREG(0x440,0x0B00019F);
1138 VIASETREG(0x440,0x0C00018B);
1139 VIASETREG(0x440,0x0D00019B);
1140 VIASETREG(0x440,0x0E000000);
1141 VIASETREG(0x440,0x0F000000);
1142 VIASETREG(0x440,0x10000000);
1143 VIASETREG(0x440,0x11000000);
1144 VIASETREG(0x440,0x20000000);
1148 WaitIdleCLE266(VIAPtr pVia
)
1154 while (!(VIAGETREG(VIA_REG_STATUS
) & VIA_VR_QUEUE_BUSY
) && (loop
++ < MAXLOOP
))
1157 while ((VIAGETREG(VIA_REG_STATUS
) &
1158 (VIA_CMD_RGTR_BUSY
| VIA_2D_ENG_BUSY
| VIA_3D_ENG_BUSY
)) &&
1162 return loop
>= MAXLOOP
;
1165 static int viaInitFBDev(DRIDriverContext
*ctx
)
1167 VIAPtr pVia
= CALLOC(sizeof(*pVia
));
1169 ctx
->driverPrivate
= (void *)pVia
;
1171 switch (ctx
->chipset
) {
1172 case PCI_CHIP_CLE3122
:
1173 case PCI_CHIP_CLE3022
:
1174 pVia
->Chipset
= VIA_CLE266
;
1176 case PCI_CHIP_VT7205
:
1177 case PCI_CHIP_VT3205
:
1178 pVia
->Chipset
= VIA_KM400
;
1180 case PCI_CHIP_VT3204
:
1181 case PCI_CHIP_VT3344
:
1182 pVia
->Chipset
= VIA_K8M800
;
1184 case PCI_CHIP_VT3259
:
1185 pVia
->Chipset
= VIA_PM800
;
1188 xf86DrvMsg(0, X_ERROR
, "VIA: Unknown device ID (0x%x)\n", ctx
->chipset
);
1191 /* _SOLO TODO XXX need to read ChipRev too */
1194 pVia
->videoRambytes
= ctx
->shared
.fbSize
;
1195 pVia
->MmioBase
= ctx
->MMIOStart
;
1196 pVia
->FrameBufferBase
= ctx
->FBStart
& 0xfc000000;
1198 pVia
->FBFreeStart
= ctx
->shared
.virtualWidth
* ctx
->cpp
*
1199 ctx
->shared
.virtualHeight
;
1202 /* Alloc a second framebuffer for the second head */
1203 pVia
->FBFreeStart
+= ctx
->shared
.virtualWidth
* ctx
->cpp
*
1204 ctx
->shared
.virtualHeight
;
1207 pVia
->VQStart
= pVia
->FBFreeStart
;
1208 pVia
->VQEnd
= pVia
->FBFreeStart
+ VIA_VQ_SIZE
- 1;
1210 pVia
->FBFreeStart
+= VIA_VQ_SIZE
;
1212 pVia
->FBFreeEnd
= pVia
->videoRambytes
;
1214 if (!VIADRIScreenInit(ctx
))
1220 static void viaHaltFBDev(DRIDriverContext
*ctx
)
1222 drmUnmap( ctx
->pSAREA
, ctx
->shared
.SAREASize
);
1223 drmClose(ctx
->drmFD
);
1225 if (ctx
->driverPrivate
) {
1226 free(ctx
->driverPrivate
);
1227 ctx
->driverPrivate
= 0;
1231 static int viaEngineShutdown(const DRIDriverContext
*ctx
)
1236 static int viaEngineRestore(const DRIDriverContext
*ctx
)
1241 const struct DRIDriverRec __driDriver
=
1244 viaPostValidateMode
,