190b17f1bSmrg/*
203bd066fSmrg * Copyright 2011-2016 The OpenChrome Project
31090d90aSmrg *                     [https://www.freedesktop.org/wiki/Openchrome]
490b17f1bSmrg *
590b17f1bSmrg * Permission is hereby granted, free of charge, to any person obtaining a
690b17f1bSmrg * copy of this software and associated documentation files (the "Software"),
790b17f1bSmrg * to deal in the Software without restriction, including without limitation
890b17f1bSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
990b17f1bSmrg * and/or sell copies of the Software, and to permit persons to whom the
1090b17f1bSmrg * Software is furnished to do so, subject to the following conditions:
1190b17f1bSmrg *
1290b17f1bSmrg * The above copyright notice and this permission notice (including the
1390b17f1bSmrg * next paragraph) shall be included in all copies or substantial portions
1490b17f1bSmrg * of the Software.
1590b17f1bSmrg *
1690b17f1bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1790b17f1bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1890b17f1bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
1990b17f1bSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2090b17f1bSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2190b17f1bSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2290b17f1bSmrg * DEALINGS IN THE SOFTWARE.
2390b17f1bSmrg */
2490b17f1bSmrg
2590b17f1bSmrg#ifdef HAVE_CONFIG_H
2690b17f1bSmrg#include "config.h"
2790b17f1bSmrg#endif
2890b17f1bSmrg
2990b17f1bSmrg#include "globals.h"
3090b17f1bSmrg#include "via_driver.h"
314dc64ea9Smrg#include "xf86fbman.h"
3290b17f1bSmrg
3390b17f1bSmrgstatic void
3403bd066fSmrgviaMMIOEnable(ScrnInfoPtr pScrn)
3590b17f1bSmrg{
3690b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
3790b17f1bSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3890b17f1bSmrg
3903bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4003bd066fSmrg                        "Entered viaMMIOEnable.\n"));
4103bd066fSmrg
4290b17f1bSmrg    switch (pVia->Chipset) {
4390b17f1bSmrg        case VIA_CX700:
44963d66acSmrg        case VIA_K8M890:
4590b17f1bSmrg        case VIA_P4M900:
4690b17f1bSmrg        case VIA_VX800:
4790b17f1bSmrg        case VIA_VX855:
4890b17f1bSmrg        case VIA_VX900:
4903bd066fSmrg            ViaSeqMask(hwp, 0x1A, 0x08, 0x08);
5090b17f1bSmrg            break;
5190b17f1bSmrg        default:
5203bd066fSmrg            if (pVia->IsSecondary)
5303bd066fSmrg                ViaSeqMask(hwp, 0x1A, 0x38, 0x38);
5403bd066fSmrg            else
5503bd066fSmrg                ViaSeqMask(hwp, 0x1A, 0x68, 0x68);
5690b17f1bSmrg            break;
5790b17f1bSmrg    }
5890b17f1bSmrg
59963d66acSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
6003bd066fSmrg                        "Exiting viaMMIOEnable.\n"));
6190b17f1bSmrg}
6290b17f1bSmrg
6390b17f1bSmrgstatic void
6403bd066fSmrgviaMMIODisable(ScrnInfoPtr pScrn)
6590b17f1bSmrg{
6690b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
6790b17f1bSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
6890b17f1bSmrg
6903bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7003bd066fSmrg                        "Entered viaMMIODisable.\n"));
7103bd066fSmrg
7290b17f1bSmrg    switch (pVia->Chipset) {
7390b17f1bSmrg        case VIA_CX700:
74963d66acSmrg        case VIA_K8M890:
7590b17f1bSmrg        case VIA_P4M900:
7690b17f1bSmrg        case VIA_VX800:
7790b17f1bSmrg        case VIA_VX855:
7890b17f1bSmrg        case VIA_VX900:
7903bd066fSmrg            ViaSeqMask(hwp, 0x1A, 0x00, 0x08);
8090b17f1bSmrg            break;
8190b17f1bSmrg        default:
8203bd066fSmrg            ViaSeqMask(hwp, 0x1A, 0x00, 0x60);
8390b17f1bSmrg            break;
8490b17f1bSmrg    }
8503bd066fSmrg
8603bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
8703bd066fSmrg                        "Exiting viaMMIODisable.\n"));
8890b17f1bSmrg}
8990b17f1bSmrg
9090b17f1bSmrgstatic Bool
9103bd066fSmrgviaMapMMIO(ScrnInfoPtr pScrn)
9290b17f1bSmrg{
9390b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
9403bd066fSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
9503bd066fSmrg    CARD8 val;
9603bd066fSmrg#ifdef HAVE_PCIACCESS
9703bd066fSmrg    int err;
9803bd066fSmrg#else
9903bd066fSmrg    unsigned char *tmp;
10003bd066fSmrg#endif
10103bd066fSmrg
10203bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10303bd066fSmrg                        "Entered viaMapMMIO.\n"));
10490b17f1bSmrg
10590b17f1bSmrg#ifdef HAVE_PCIACCESS
10690b17f1bSmrg    pVia->MmioBase = pVia->PciInfo->regions[1].base_addr;
10790b17f1bSmrg#else
10890b17f1bSmrg    pVia->MmioBase = pVia->PciInfo->memBase[1];
10990b17f1bSmrg#endif
11090b17f1bSmrg
11190b17f1bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
11203bd066fSmrg                "Mapping MMIO at address 0x%lX with "
11303bd066fSmrg                "size %u KB.\n",
11403bd066fSmrg                pVia->MmioBase, VIA_MMIO_REGSIZE / 1024);
11590b17f1bSmrg
11690b17f1bSmrg#ifdef HAVE_PCIACCESS
11790b17f1bSmrg    err = pci_device_map_range(pVia->PciInfo,
11890b17f1bSmrg                               pVia->MmioBase,
11903bd066fSmrg                               VIA_MMIO_REGSIZE, PCI_DEV_MAP_FLAG_WRITABLE,
12090b17f1bSmrg                               (void **)&pVia->MapBase);
12190b17f1bSmrg
12290b17f1bSmrg    if (err) {
12390b17f1bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12403bd066fSmrg                    "Unable to map MMIO.\n"
12503bd066fSmrg                    "Error: %s (%u)\n",
12603bd066fSmrg                    strerror(err), err);
12703bd066fSmrg        goto fail;
12890b17f1bSmrg    }
12990b17f1bSmrg#else
13003bd066fSmrg    pVia->MapBase = xf86MapPciMem(pScrn->scrnIndex,
13103bd066fSmrg                                    VIDMEM_MMIO, pVia->PciTag,
13203bd066fSmrg                                    pVia->MmioBase, VIA_MMIO_REGSIZE);
13303bd066fSmrg    if (!pVia->MapBase) {
13403bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
13503bd066fSmrg                   "Unable to map MMIO.\n");
13603bd066fSmrg        goto fail;
13703bd066fSmrg    }
13890b17f1bSmrg#endif
13990b17f1bSmrg
14090b17f1bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
14103bd066fSmrg               "Mapping 2D Host BitBLT space at address 0x%lX with "
14203bd066fSmrg               "size %u KB.\n",
14303bd066fSmrg               pVia->MmioBase + VIA_MMIO_BLTBASE, VIA_MMIO_BLTSIZE / 1024);
14490b17f1bSmrg
14590b17f1bSmrg#ifdef HAVE_PCIACCESS
14690b17f1bSmrg    err = pci_device_map_range(pVia->PciInfo,
14790b17f1bSmrg                               pVia->MmioBase + VIA_MMIO_BLTBASE,
14803bd066fSmrg                               VIA_MMIO_BLTSIZE, PCI_DEV_MAP_FLAG_WRITABLE,
14990b17f1bSmrg                               (void **)&pVia->BltBase);
15090b17f1bSmrg
15190b17f1bSmrg    if (err) {
15290b17f1bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
15303bd066fSmrg                    "Unable to map 2D Host BitBLT space.\n"
15403bd066fSmrg                    "Error: %s (%u)\n",
15503bd066fSmrg                    strerror(err), err);
15603bd066fSmrg        goto fail;
15790b17f1bSmrg    }
15890b17f1bSmrg#else
15903bd066fSmrg    pVia->BltBase = xf86MapPciMem(pScrn->scrnIndex,
16003bd066fSmrg                                    VIDMEM_MMIO, pVia->PciTag,
16103bd066fSmrg                                    pVia->MmioBase + VIA_MMIO_BLTBASE,
16203bd066fSmrg                                    VIA_MMIO_BLTSIZE);
16303bd066fSmrg    if (!pVia->BltBase) {
16490b17f1bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
16503bd066fSmrg                   "Unable to map 2D Host BitBLT space.\n");
16603bd066fSmrg        goto fail;
16790b17f1bSmrg    }
16803bd066fSmrg#endif
16990b17f1bSmrg
17003bd066fSmrg    if (!(pVia->videoRambytes)) {
17103bd066fSmrg        goto fail;
17203bd066fSmrg    }
17390b17f1bSmrg
17403bd066fSmrg#ifdef HAVE_PCIACCESS
17503bd066fSmrg    if (pVia->Chipset == VIA_VX900) {
17603bd066fSmrg        pVia->FrameBufferBase = pVia->PciInfo->regions[2].base_addr;
17703bd066fSmrg    } else {
17803bd066fSmrg        pVia->FrameBufferBase = pVia->PciInfo->regions[0].base_addr;
17903bd066fSmrg    }
18003bd066fSmrg#else
18103bd066fSmrg    if (pVia->Chipset == VIA_VX900) {
18203bd066fSmrg        pVia->FrameBufferBase = pVia->PciInfo->memBase[2];
18303bd066fSmrg    } else {
18403bd066fSmrg        pVia->FrameBufferBase = pVia->PciInfo->memBase[0];
18503bd066fSmrg    }
18603bd066fSmrg#endif
18790b17f1bSmrg
18803bd066fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
18903bd066fSmrg               "Mapping the frame buffer at address 0x%lX with "
190f4dbeecdSjakllsch               "size %lu KB.\n",
19103bd066fSmrg               pVia->FrameBufferBase, pVia->videoRambytes / 1024);
19290b17f1bSmrg
19303bd066fSmrg#ifdef HAVE_PCIACCESS
19403bd066fSmrg    err = pci_device_map_range(pVia->PciInfo, pVia->FrameBufferBase,
19503bd066fSmrg                               pVia->videoRambytes,
19603bd066fSmrg                               (PCI_DEV_MAP_FLAG_WRITABLE |
19703bd066fSmrg                                PCI_DEV_MAP_FLAG_WRITE_COMBINE),
19803bd066fSmrg                               (void **)&pVia->FBBase);
19903bd066fSmrg    if (err) {
20003bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
20103bd066fSmrg                    "Unable to map the frame buffer.\n"
20203bd066fSmrg                    "Error: %s (%u)\n",
20303bd066fSmrg                    strerror(err), err);
20403bd066fSmrg        goto fail;
20503bd066fSmrg    }
20603bd066fSmrg#else
20703bd066fSmrg    /*
20803bd066fSmrg     * FIXME: This is a hack to get rid of offending wrongly sized
20903bd066fSmrg     * MTRR regions set up by the VIA BIOS. Should be taken care of
21003bd066fSmrg     * in the OS support layer.
21103bd066fSmrg     */
21203bd066fSmrg    tmp = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pVia->PciTag,
21303bd066fSmrg                        pVia->FrameBufferBase, pVia->videoRambytes);
21403bd066fSmrg    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) tmp, pVia->videoRambytes);
21590b17f1bSmrg
21603bd066fSmrg    /*
21703bd066fSmrg     * And, as if this wasn't enough, 2.6 series kernels don't
21803bd066fSmrg     * remove MTRR regions on the first attempt. So try again.
21903bd066fSmrg     */
22003bd066fSmrg    tmp = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pVia->PciTag,
22103bd066fSmrg                        pVia->FrameBufferBase, pVia->videoRambytes);
22203bd066fSmrg    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) tmp, pVia->videoRambytes);
22303bd066fSmrg    /*
22403bd066fSmrg     * End of hack.
22503bd066fSmrg     */
22690b17f1bSmrg
22703bd066fSmrg    pVia->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
22803bd066fSmrg                                 pVia->PciTag, pVia->FrameBufferBase,
22903bd066fSmrg                                 pVia->videoRambytes);
23090b17f1bSmrg
23103bd066fSmrg    if (!pVia->FBBase) {
23203bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
23303bd066fSmrg                   "Unable to map the frame buffer.\n");
23403bd066fSmrg        goto fail;
23590b17f1bSmrg    }
23603bd066fSmrg#endif
23790b17f1bSmrg
23803bd066fSmrg    pVia->FBFreeStart = 0;
23903bd066fSmrg    pVia->FBFreeEnd = pVia->videoRambytes;
24003bd066fSmrg
24103bd066fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
24203bd066fSmrg               "Frame buffer start address: %p, free start: 0x%X end: 0x%X\n",
24303bd066fSmrg               pVia->FBBase, pVia->FBFreeStart, pVia->FBFreeEnd);
24490b17f1bSmrg
24590b17f1bSmrg#ifdef HAVE_PCIACCESS
24690b17f1bSmrg    if (pVia->Chipset == VIA_VX900) {
24703bd066fSmrg        pScrn->memPhysBase = pVia->PciInfo->regions[2].base_addr;
24890b17f1bSmrg    } else {
24903bd066fSmrg        pScrn->memPhysBase = pVia->PciInfo->regions[0].base_addr;
25090b17f1bSmrg    }
25190b17f1bSmrg#else
25290b17f1bSmrg    if (pVia->Chipset == VIA_VX900) {
25303bd066fSmrg        pScrn->memPhysBase = pVia->PciInfo->memBase[2];
25490b17f1bSmrg    } else {
25503bd066fSmrg        pScrn->memPhysBase = pVia->PciInfo->memBase[0];
25690b17f1bSmrg    }
25790b17f1bSmrg#endif
25890b17f1bSmrg
25903bd066fSmrg    pScrn->fbOffset = 0;
26003bd066fSmrg    if (pVia->IsSecondary) {
26103bd066fSmrg        pScrn->fbOffset = pScrn->videoRam << 10;
26203bd066fSmrg    }
26390b17f1bSmrg
26403bd066fSmrg    /* MMIO for MPEG engine. */
26503bd066fSmrg    pVia->MpegMapBase = pVia->MapBase + 0xc00;
26690b17f1bSmrg
26703bd066fSmrg    /* Set up MMIO vgaHW. */
26803bd066fSmrg    vgaHWSetMmioFuncs(hwp, pVia->MapBase, 0x8000);
26903bd066fSmrg
27003bd066fSmrg    val = hwp->readEnable(hwp);
27103bd066fSmrg    hwp->writeEnable(hwp, val | 0x01);
27203bd066fSmrg
27303bd066fSmrg    val = hwp->readMiscOut(hwp);
27403bd066fSmrg    hwp->writeMiscOut(hwp, val | 0x01);
27503bd066fSmrg
27603bd066fSmrg    /* Unlock extended I/O space. */
27703bd066fSmrg    ViaSeqMask(hwp, 0x10, 0x01, 0x01);
27803bd066fSmrg
27903bd066fSmrg    viaMMIOEnable(pScrn);
28003bd066fSmrg
28103bd066fSmrg    vgaHWGetIOBase(hwp);
28203bd066fSmrg
28303bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
28403bd066fSmrg                        "Exiting viaMapMMIO.\n"));
28503bd066fSmrg    return TRUE;
28603bd066fSmrg
28703bd066fSmrgfail:
28890b17f1bSmrg
28990b17f1bSmrg#ifdef HAVE_PCIACCESS
29003bd066fSmrg    if (pVia->FBBase) {
29103bd066fSmrg        pci_device_unmap_range(pVia->PciInfo, (pointer) pVia->FBBase,
29203bd066fSmrg                                pVia->videoRambytes);
29303bd066fSmrg    }
29403bd066fSmrg
29503bd066fSmrg    if (pVia->BltBase) {
29603bd066fSmrg        pci_device_unmap_range(pVia->PciInfo, (pointer) pVia->BltBase,
29703bd066fSmrg                               VIA_MMIO_BLTSIZE);
29803bd066fSmrg    }
29903bd066fSmrg
30003bd066fSmrg    if (pVia->MapBase) {
30103bd066fSmrg        pci_device_unmap_range(pVia->PciInfo, (pointer) pVia->MapBase,
30203bd066fSmrg                               VIA_MMIO_REGSIZE);
30303bd066fSmrg    }
30490b17f1bSmrg#else
30503bd066fSmrg    if (pVia->FBBase) {
30603bd066fSmrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pVia->FBBase,
30703bd066fSmrg                        pVia->videoRambytes);
30803bd066fSmrg    }
30990b17f1bSmrg
31003bd066fSmrg    if (pVia->BltBase) {
31103bd066fSmrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pVia->BltBase,
31203bd066fSmrg                        VIA_MMIO_BLTSIZE);
31303bd066fSmrg    }
31403bd066fSmrg
31503bd066fSmrg    if (pVia->MapBase) {
31603bd066fSmrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pVia->MapBase,
31703bd066fSmrg                        VIA_MMIO_REGSIZE);
31803bd066fSmrg    }
31990b17f1bSmrg#endif
32090b17f1bSmrg
32103bd066fSmrg    pVia->FBBase = NULL;
32203bd066fSmrg    pVia->BltBase = NULL;
32303bd066fSmrg    pVia->MapBase = NULL;
32490b17f1bSmrg
32503bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
32603bd066fSmrg                        "Exiting viaMapMMIO.\n"));
32703bd066fSmrg    return FALSE;
32803bd066fSmrg}
32903bd066fSmrg
33003bd066fSmrgvoid
33103bd066fSmrgviaUnmapMMIO(ScrnInfoPtr pScrn)
33203bd066fSmrg{
33303bd066fSmrg    VIAPtr pVia = VIAPTR(pScrn);
33403bd066fSmrg
33503bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
33603bd066fSmrg                        "Entered viaUnmapMMIO.\n"));
33703bd066fSmrg
33803bd066fSmrg    viaMMIODisable(pScrn);
33990b17f1bSmrg
34090b17f1bSmrg#ifdef HAVE_PCIACCESS
34103bd066fSmrg    if (pVia->FBBase) {
34203bd066fSmrg        pci_device_unmap_range(pVia->PciInfo, (pointer) pVia->FBBase,
34303bd066fSmrg                               pVia->videoRambytes);
34403bd066fSmrg    }
34503bd066fSmrg
34603bd066fSmrg    if (pVia->BltBase) {
34703bd066fSmrg        pci_device_unmap_range(pVia->PciInfo, (pointer) pVia->BltBase,
34803bd066fSmrg                               VIA_MMIO_BLTSIZE);
34903bd066fSmrg    }
35003bd066fSmrg
35103bd066fSmrg    if (pVia->MapBase) {
35203bd066fSmrg        pci_device_unmap_range(pVia->PciInfo, (pointer) pVia->MapBase,
35303bd066fSmrg                               VIA_MMIO_REGSIZE);
35403bd066fSmrg    }
35590b17f1bSmrg#else
35603bd066fSmrg    if (pVia->FBBase) {
35703bd066fSmrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pVia->FBBase,
35803bd066fSmrg                        pVia->videoRambytes);
35903bd066fSmrg    }
36003bd066fSmrg
36103bd066fSmrg    if (pVia->BltBase) {
36203bd066fSmrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pVia->BltBase,
36303bd066fSmrg                        VIA_MMIO_BLTSIZE);
36403bd066fSmrg    }
36503bd066fSmrg
36603bd066fSmrg    if (pVia->MapBase) {
36703bd066fSmrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pVia->MapBase,
36803bd066fSmrg                        VIA_MMIO_REGSIZE);
36903bd066fSmrg    }
37090b17f1bSmrg#endif
37190b17f1bSmrg
37203bd066fSmrg    pVia->FBBase = NULL;
37303bd066fSmrg    pVia->BltBase = NULL;
37403bd066fSmrg    pVia->MapBase = NULL;
37503bd066fSmrg
37603bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
37703bd066fSmrg                        "Exiting viaUnmapMMIO.\n"));
37890b17f1bSmrg}
37990b17f1bSmrg
38090b17f1bSmrg/*
38190b17f1bSmrg * Leftover from VIA's code.
38290b17f1bSmrg */
38390b17f1bSmrgstatic void
38490b17f1bSmrgviaInitPCIe(VIAPtr pVia)
38590b17f1bSmrg{
38690b17f1bSmrg    VIASETREG(0x41c, 0x00100000);
38790b17f1bSmrg    VIASETREG(0x420, 0x680A0000);
38890b17f1bSmrg    VIASETREG(0x420, 0x02000000);
38990b17f1bSmrg}
39090b17f1bSmrg
39190b17f1bSmrgstatic void
39203bd066fSmrgviaInitAGP(VIAPtr pVia)
39390b17f1bSmrg{
39490b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00100000);
39590b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x00000000);
39690b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x00333004);
39790b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x60000000);
39890b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x61000000);
39990b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x62000000);
40090b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x63000000);
40190b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x64000000);
40290b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x7D000000);
40390b17f1bSmrg
40490b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0xfe020000);
40590b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x00000000);
40690b17f1bSmrg}
40790b17f1bSmrg
40890b17f1bSmrg/*
40990b17f1bSmrg * Initialize the virtual command queue. Header-2 commands can be put
41090b17f1bSmrg * in this queue for buffering. AFAIK it doesn't handle Header-1
41190b17f1bSmrg * commands, which is really a pity, since it has to be idled before
41290b17f1bSmrg * issuing a Header-1 command.
41390b17f1bSmrg */
41490b17f1bSmrgstatic void
41503bd066fSmrgviaEnableAGPVQ(VIAPtr pVia)
41690b17f1bSmrg{
41790b17f1bSmrg   CARD32
41890b17f1bSmrg       vqStartAddr = pVia->VQStart,
41990b17f1bSmrg       vqEndAddr = pVia->VQEnd,
42090b17f1bSmrg       vqStartL = 0x50000000 | (vqStartAddr & 0xFFFFFF),
42190b17f1bSmrg       vqEndL = 0x51000000 | (vqEndAddr & 0xFFFFFF),
42290b17f1bSmrg       vqStartEndH = 0x52000000 | ((vqStartAddr & 0xFF000000) >> 24) |
42390b17f1bSmrg       ((vqEndAddr & 0xFF000000) >> 16),
42490b17f1bSmrg       vqLen = 0x53000000 | (VIA_VQ_SIZE >> 3);
42590b17f1bSmrg
42690b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00fe0000);
42790b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x080003fe);
42890b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0a00027c);
42990b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0b000260);
43090b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0c000274);
43190b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0d000264);
43290b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0e000000);
43390b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0f000020);
43490b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x1000027e);
43590b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x110002fe);
43690b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x200f0060);
43790b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x00000006);
43890b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x40008c0f);
43990b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x44000000);
44090b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x45080c04);
44190b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x46800408);
44290b17f1bSmrg
44390b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, vqStartEndH);
44490b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, vqStartL);
44590b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, vqEndL);
44690b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, vqLen);
44790b17f1bSmrg}
44890b17f1bSmrg
44990b17f1bSmrgstatic void
45090b17f1bSmrgviaEnablePCIeVQ(VIAPtr pVia)
45190b17f1bSmrg{
45290b17f1bSmrg   CARD32
45390b17f1bSmrg       vqStartAddr = pVia->VQStart,
45490b17f1bSmrg       vqEndAddr = pVia->VQEnd,
45590b17f1bSmrg       vqStartL = 0x70000000 | (vqStartAddr & 0xFFFFFF),
45690b17f1bSmrg       vqEndL = 0x71000000 | (vqEndAddr & 0xFFFFFF),
45790b17f1bSmrg       vqStartEndH = 0x72000000 | ((vqStartAddr & 0xFF000000) >> 24) |
45890b17f1bSmrg       ((vqEndAddr & 0xFF000000) >> 16),
45990b17f1bSmrg       vqLen = 0x73000000 | (VIA_VQ_SIZE >> 3);
46090b17f1bSmrg
46190b17f1bSmrg    VIASETREG(0x41c, 0x00100000);
46290b17f1bSmrg    VIASETREG(0x420, vqStartEndH);
46390b17f1bSmrg    VIASETREG(0x420, vqStartL);
46490b17f1bSmrg    VIASETREG(0x420, vqEndL);
46590b17f1bSmrg    VIASETREG(0x420, vqLen);
46690b17f1bSmrg    VIASETREG(0x420, 0x74301001);
46790b17f1bSmrg    VIASETREG(0x420, 0x00000000);
46890b17f1bSmrg}
46990b17f1bSmrg
47090b17f1bSmrg/*
47190b17f1bSmrg * Disable the virtual command queue.
47290b17f1bSmrg */
47390b17f1bSmrgvoid
47490b17f1bSmrgviaDisableVQ(ScrnInfoPtr pScrn)
47590b17f1bSmrg{
47690b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
47790b17f1bSmrg
47803bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
47903bd066fSmrg                        "Entered viaDisableVQ.\n"));
48003bd066fSmrg
48190b17f1bSmrg    switch (pVia->Chipset) {
48203bd066fSmrg    case VIA_K8M890:
48303bd066fSmrg    case VIA_P4M900:
48403bd066fSmrg    case VIA_VX800:
48503bd066fSmrg    case VIA_VX855:
48603bd066fSmrg    case VIA_VX900:
48703bd066fSmrg        VIASETREG(0x41c, 0x00100000);
48803bd066fSmrg        VIASETREG(0x420, 0x74301000);
48903bd066fSmrg        break;
49003bd066fSmrg    default:
49103bd066fSmrg        VIASETREG(VIA_REG_TRANSET, 0x00fe0000);
49203bd066fSmrg        VIASETREG(VIA_REG_TRANSPACE, 0x00000004);
49303bd066fSmrg        VIASETREG(VIA_REG_TRANSPACE, 0x40008c0f);
49403bd066fSmrg        VIASETREG(VIA_REG_TRANSPACE, 0x44000000);
49503bd066fSmrg        VIASETREG(VIA_REG_TRANSPACE, 0x45080c04);
49603bd066fSmrg        VIASETREG(VIA_REG_TRANSPACE, 0x46800408);
49703bd066fSmrg        break;
49890b17f1bSmrg    }
49903bd066fSmrg
50003bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
50103bd066fSmrg                        "Exiting viaDisableVQ.\n"));
50290b17f1bSmrg}
50390b17f1bSmrg
50490b17f1bSmrg/*
50590b17f1bSmrg * Initialize the 2D engine and set the 2D context mode to the
50690b17f1bSmrg * current screen depth. Also enable the virtual queue.
50790b17f1bSmrg */
50890b17f1bSmrgstatic void
50903bd066fSmrgviaInitialize2DEngine(ScrnInfoPtr pScrn)
51090b17f1bSmrg{
51190b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
51290b17f1bSmrg    ViaTwodContext *tdc = &pVia->td;
51390b17f1bSmrg    int i;
51490b17f1bSmrg
51590b17f1bSmrg    /* Initialize the 2D engine registers to reset the 2D engine. */
51690b17f1bSmrg    for (i = 0x04; i <= 0x40; i += 4) {
51790b17f1bSmrg        VIASETREG(i, 0x0);
51890b17f1bSmrg    }
51990b17f1bSmrg
52090b17f1bSmrg    if (pVia->Chipset == VIA_VX800 ||
52190b17f1bSmrg        pVia->Chipset == VIA_VX855 ||
52290b17f1bSmrg        pVia->Chipset == VIA_VX900) {
52390b17f1bSmrg        for (i = 0x44; i <= 0x5c; i += 4) {
52490b17f1bSmrg            VIASETREG(i, 0x0);
52590b17f1bSmrg        }
52690b17f1bSmrg    }
52790b17f1bSmrg
52890b17f1bSmrg    if (pVia->Chipset == VIA_VX900)
52990b17f1bSmrg    {
53090b17f1bSmrg        /*410 redefine 0x30 34 38*/
53190b17f1bSmrg        VIASETREG(0x60, 0x0); /*already useable here*/
53290b17f1bSmrg    }
53390b17f1bSmrg
53490b17f1bSmrg    switch (pVia->Chipset) {
53590b17f1bSmrg        case VIA_K8M890:
53690b17f1bSmrg        case VIA_P4M900:
53790b17f1bSmrg        case VIA_VX800:
53890b17f1bSmrg        case VIA_VX855:
53990b17f1bSmrg        case VIA_VX900:
54090b17f1bSmrg            viaInitPCIe(pVia);
54190b17f1bSmrg            break;
54290b17f1bSmrg        default:
54303bd066fSmrg            viaInitAGP(pVia);
54490b17f1bSmrg            break;
54590b17f1bSmrg    }
54690b17f1bSmrg
54790b17f1bSmrg    if (pVia->VQStart != 0) {
54890b17f1bSmrg        switch (pVia->Chipset) {
54990b17f1bSmrg            case VIA_K8M890:
55090b17f1bSmrg            case VIA_P4M900:
55190b17f1bSmrg            case VIA_VX800:
55290b17f1bSmrg            case VIA_VX855:
55390b17f1bSmrg            case VIA_VX900:
55490b17f1bSmrg                viaEnablePCIeVQ(pVia);
55590b17f1bSmrg                break;
55690b17f1bSmrg            default:
55703bd066fSmrg                viaEnableAGPVQ(pVia);
55890b17f1bSmrg                break;
55990b17f1bSmrg        }
56090b17f1bSmrg    } else {
56190b17f1bSmrg        viaDisableVQ(pScrn);
56290b17f1bSmrg    }
56390b17f1bSmrg
56490b17f1bSmrg    viaAccelSetMode(pScrn->bitsPerPixel, tdc);
56590b17f1bSmrg}
56690b17f1bSmrg
56790b17f1bSmrgstatic void
56803bd066fSmrgviaInitialize3DEngine(ScrnInfoPtr pScrn)
56990b17f1bSmrg{
57090b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
57190b17f1bSmrg    int i;
57290b17f1bSmrg
57390b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00010000);
57490b17f1bSmrg    for (i = 0; i <= 0x7D; i++)
57590b17f1bSmrg        VIASETREG(VIA_REG_TRANSPACE, (CARD32) i << 24);
57690b17f1bSmrg
57790b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00020000);
57890b17f1bSmrg    for (i = 0; i <= 0x94; i++)
57990b17f1bSmrg        VIASETREG(VIA_REG_TRANSPACE, (CARD32) i << 24);
58090b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x82400000);
58190b17f1bSmrg
58290b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x01020000);
58390b17f1bSmrg    for (i = 0; i <= 0x94; i++)
58490b17f1bSmrg        VIASETREG(VIA_REG_TRANSPACE, (CARD32) i << 24);
58590b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x82400000);
58690b17f1bSmrg
58790b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0xfe020000);
58890b17f1bSmrg    for (i = 0; i <= 0x03; i++)
58990b17f1bSmrg        VIASETREG(VIA_REG_TRANSPACE, (CARD32) i << 24);
59090b17f1bSmrg
59190b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00030000);
59290b17f1bSmrg    for (i = 0; i <= 0xff; i++)
59390b17f1bSmrg        VIASETREG(VIA_REG_TRANSPACE, 0);
59490b17f1bSmrg
59590b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00100000);
59690b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x00333004);
59790b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x10000002);
59890b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x60000000);
59990b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x61000000);
60090b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x62000000);
60190b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x63000000);
60290b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x64000000);
60390b17f1bSmrg
60490b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00fe0000);
60590b17f1bSmrg    if (pVia->Chipset == VIA_CLE266 && pVia->ChipRev >= 3)
60690b17f1bSmrg        VIASETREG(VIA_REG_TRANSPACE, 0x40008c0f);
60790b17f1bSmrg    else
60890b17f1bSmrg        VIASETREG(VIA_REG_TRANSPACE, 0x4000800f);
60990b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x44000000);
61090b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x45080C04);
61190b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x46800408);
61290b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x50000000);
61390b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x51000000);
61490b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x52000000);
61590b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x53000000);
61690b17f1bSmrg
61790b17f1bSmrg    VIASETREG(VIA_REG_TRANSET, 0x00fe0000);
61890b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x08000001);
61990b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0A000183);
62090b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0B00019F);
62190b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0C00018B);
62290b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0D00019B);
62390b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0E000000);
62490b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x0F000000);
62590b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x10000000);
62690b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x11000000);
62790b17f1bSmrg    VIASETREG(VIA_REG_TRANSPACE, 0x20000000);
62890b17f1bSmrg}
62990b17f1bSmrg
63090b17f1bSmrg/*
63190b17f1bSmrg * Acceleration initialization function. Sets up offscreen memory disposition,
63290b17f1bSmrg * and initializes engines and acceleration method.
63390b17f1bSmrg */
63490b17f1bSmrgBool
63503bd066fSmrgumsAccelInit(ScreenPtr pScreen)
63690b17f1bSmrg{
63790b17f1bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
63890b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
63990b17f1bSmrg    Bool ret = FALSE;
64090b17f1bSmrg
64103bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
64203bd066fSmrg                        "Entered umsAccelInit.\n"));
64303bd066fSmrg
64490b17f1bSmrg    pVia->VQStart = 0;
64590b17f1bSmrg    pVia->vq_bo = drm_bo_alloc(pScrn, VIA_VQ_SIZE, 16, TTM_PL_FLAG_VRAM);
64690b17f1bSmrg    if (!pVia->vq_bo)
64790b17f1bSmrg        goto err;
64890b17f1bSmrg
64990b17f1bSmrg    pVia->VQStart = pVia->vq_bo->offset;
65090b17f1bSmrg    pVia->VQEnd = pVia->vq_bo->offset + pVia->vq_bo->size;
65190b17f1bSmrg
65203bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
65303bd066fSmrg                        "Initializing the 2D engine.\n"));
65403bd066fSmrg    viaInitialize2DEngine(pScrn);
65503bd066fSmrg
65603bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
65703bd066fSmrg                        "Initializing the 3D engine.\n"));
65803bd066fSmrg    viaInitialize3DEngine(pScrn);
65990b17f1bSmrg
66090b17f1bSmrg    pVia->exa_sync_bo = drm_bo_alloc(pScrn, 32, 32, TTM_PL_FLAG_VRAM);
66190b17f1bSmrg    if (!pVia->exa_sync_bo)
66290b17f1bSmrg        goto err;
66390b17f1bSmrg
66490b17f1bSmrg    /* Sync marker space. */
66590b17f1bSmrg    pVia->exa_sync_bo = drm_bo_alloc(pScrn, 32, 32, TTM_PL_FLAG_VRAM);
66690b17f1bSmrg    if (!pVia->exa_sync_bo)
66790b17f1bSmrg        goto err;
66890b17f1bSmrg
66990b17f1bSmrg    pVia->markerOffset = pVia->exa_sync_bo->offset;
67090b17f1bSmrg    pVia->markerBuf = drm_bo_map(pScrn, pVia->exa_sync_bo);
67190b17f1bSmrg    if (!pVia->markerBuf)
67290b17f1bSmrg        goto err;
67390b17f1bSmrg    pVia->curMarker = 0;
67490b17f1bSmrg    pVia->lastMarkerRead = 0;
67590b17f1bSmrg
67690b17f1bSmrg#ifdef HAVE_DRI
67790b17f1bSmrg    pVia->dBounce = NULL;
67890b17f1bSmrg    pVia->scratchAddr = NULL;
67990b17f1bSmrg#endif /* HAVE_DRI */
68090b17f1bSmrg    ret = TRUE;
68190b17f1bSmrgerr:
68290b17f1bSmrg    if (!ret) {
68390b17f1bSmrg        if (pVia->markerBuf) {
68490b17f1bSmrg            drm_bo_unmap(pScrn, pVia->exa_sync_bo);
68590b17f1bSmrg            pVia->markerBuf = NULL;
68690b17f1bSmrg        }
68790b17f1bSmrg        if (pVia->exa_sync_bo)
68890b17f1bSmrg            drm_bo_free(pScrn, pVia->exa_sync_bo);
68990b17f1bSmrg        if (pVia->vq_bo)
69090b17f1bSmrg            drm_bo_free(pScrn, pVia->vq_bo);
69190b17f1bSmrg    }
69203bd066fSmrg
69303bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
69403bd066fSmrg                        "Exiting umsAccelInit.\n"));
69590b17f1bSmrg    return ret;
69690b17f1bSmrg}
69790b17f1bSmrg
69890b17f1bSmrgBool
69903bd066fSmrgumsCreate(ScrnInfoPtr pScrn)
70090b17f1bSmrg{
70190b17f1bSmrg    ScreenPtr pScreen = pScrn->pScreen;
70290b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
70390b17f1bSmrg    unsigned long offset;
70490b17f1bSmrg    BoxRec AvailFBArea;
70590b17f1bSmrg    Bool ret = TRUE;
70690b17f1bSmrg    long size;
70790b17f1bSmrg    int maxY;
70890b17f1bSmrg
70990b17f1bSmrg#ifdef HAVE_DRI
71090b17f1bSmrg    if (pVia->directRenderingType == DRI_1) {
71190b17f1bSmrg        pVia->driSize = (pVia->FBFreeEnd - pVia->FBFreeStart) >> 2;
71290b17f1bSmrg        if ((pVia->driSize > (pVia->maxDriSize * 1024)) && pVia->maxDriSize > 0)
71390b17f1bSmrg            pVia->driSize = pVia->maxDriSize * 1024;
71490b17f1bSmrg
71590b17f1bSmrg        /* In the case of DRI we handle all VRAM by the DRI ioctls */
71690b17f1bSmrg        if (pVia->useEXA)
71790b17f1bSmrg            return TRUE;
71890b17f1bSmrg
71990b17f1bSmrg        /* XAA has to use FBManager so we have to split the space with DRI */
72090b17f1bSmrg        maxY = pScrn->virtualY + (pVia->driSize / pVia->Bpl);
72190b17f1bSmrg    } else
72290b17f1bSmrg#endif
72390b17f1bSmrg        maxY = pVia->FBFreeEnd / pVia->Bpl;
72490b17f1bSmrg
72590b17f1bSmrg    /* FBManager can't handle more than 32767 scan lines */
72690b17f1bSmrg    if (maxY > 32767)
72790b17f1bSmrg        maxY = 32767;
72890b17f1bSmrg
72990b17f1bSmrg    AvailFBArea.x1 = 0;
73090b17f1bSmrg    AvailFBArea.y1 = 0;
73190b17f1bSmrg    AvailFBArea.x2 = pScrn->displayWidth;
73290b17f1bSmrg    AvailFBArea.y2 = maxY;
73390b17f1bSmrg    pVia->FBFreeStart = (AvailFBArea.y2 + 1) * pVia->Bpl;
73490b17f1bSmrg
73590b17f1bSmrg    /*
73690b17f1bSmrg     *   Initialization of the XFree86 framebuffer manager is done via
73790b17f1bSmrg     *   Bool xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox)
73890b17f1bSmrg     *   FullBox represents the area of the framebuffer that the manager
73990b17f1bSmrg     *   is allowed to manage. This is typically a box with a width
74090b17f1bSmrg     *   of pScrn->displayWidth and a height of as many lines as can be fit
74190b17f1bSmrg     *   within the total video memory
74290b17f1bSmrg     */
74390b17f1bSmrg    ret = xf86InitFBManager(pScreen, &AvailFBArea);
74490b17f1bSmrg    if (ret != TRUE)
74590b17f1bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86InitFBManager init failed\n");
74690b17f1bSmrg
74790b17f1bSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
74890b17f1bSmrg            "Frame Buffer From (%d,%d) To (%d,%d)\n",
74990b17f1bSmrg            AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2));
75090b17f1bSmrg
75190b17f1bSmrg    offset = (pVia->FBFreeStart + pVia->Bpp - 1) / pVia->Bpp;
75290b17f1bSmrg    size = pVia->FBFreeEnd / pVia->Bpp - offset;
75390b17f1bSmrg    if (size > 0)
75490b17f1bSmrg        xf86InitFBManagerLinear(pScreen, offset, size);
75590b17f1bSmrg
75690b17f1bSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
75790b17f1bSmrg            "Using %d lines for offscreen memory.\n",
75890b17f1bSmrg            AvailFBArea.y2 - pScrn->virtualY));
75990b17f1bSmrg    return TRUE;
76090b17f1bSmrg}
76190b17f1bSmrg
76290b17f1bSmrgBool
76303bd066fSmrgumsPreInit(ScrnInfoPtr pScrn)
76490b17f1bSmrg{
76590b17f1bSmrg    MessageType from = X_PROBED;
76690b17f1bSmrg    VIAPtr pVia = VIAPTR(pScrn);
76790b17f1bSmrg    CARD8 videoRam;
76890b17f1bSmrg    vgaHWPtr hwp;
76990b17f1bSmrg#ifdef HAVE_PCIACCESS
77090b17f1bSmrg    struct pci_device *vgaDevice = pci_device_find_by_slot(0, 0, 0, 3);
77190b17f1bSmrg    struct pci_device *bridge = pci_device_find_by_slot(0, 0, 0, 0);
77290b17f1bSmrg#endif
77390b17f1bSmrg    int bMemSize = 0;
77490b17f1bSmrg
77590b17f1bSmrg    if (!xf86LoadSubModule(pScrn, "vgahw"))
77690b17f1bSmrg        return FALSE;
77790b17f1bSmrg
77890b17f1bSmrg    if (!vgaHWGetHWRec(pScrn))
77990b17f1bSmrg        return FALSE;
78090b17f1bSmrg
78190b17f1bSmrg#if 0
78290b17f1bSmrg    /* Here we can alter the number of registers saved and restored by the
78390b17f1bSmrg     * standard vgaHWSave and Restore routines.
78490b17f1bSmrg     */
78590b17f1bSmrg    vgaHWSetRegCounts(pScrn, VGA_NUM_CRTC, VGA_NUM_SEQ, VGA_NUM_GFX,
78690b17f1bSmrg                      VGA_NUM_ATTR);
78790b17f1bSmrg#endif
78890b17f1bSmrg    hwp = VGAHWPTR(pScrn);
78990b17f1bSmrg
79090b17f1bSmrg    switch (pVia->Chipset) {
79190b17f1bSmrg        case VIA_CLE266:
79290b17f1bSmrg#ifdef HAVE_PCIACCESS
79390b17f1bSmrg            pci_device_cfg_read_u8(bridge, &videoRam, 0xE1);
79490b17f1bSmrg#else
79590b17f1bSmrg            videoRam = pciReadByte(pciTag(0, 0, 0), 0xE1) & 0x70;
79690b17f1bSmrg#endif
79790b17f1bSmrg            pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 10;
79890b17f1bSmrg            break;
79990b17f1bSmrg        case VIA_KM400:
80090b17f1bSmrg#ifdef HAVE_PCIACCESS
801963d66acSmrg            /* P4M800 Host Bridge PCI Device ID */
802963d66acSmrg            if (DEVICE_ID(bridge) == 0x0296) {
80390b17f1bSmrg                pci_device_cfg_read_u8(vgaDevice, &videoRam, 0xA1);
80490b17f1bSmrg            } else {
80590b17f1bSmrg                pci_device_cfg_read_u8(bridge, &videoRam, 0xE1);
806963d66acSmrg            }
80790b17f1bSmrg#else
808963d66acSmrg            /* P4M800 Host Bridge PCI Device ID */
809963d66acSmrg            if (pciReadWord(pciTag(0, 0, 0), 0x02) == 0x0296) {
810963d66acSmrg                videoRam = pciReadByte(pciTag(0, 0, 3), 0xA1) & 0x70;
811963d66acSmrg            } else {
81290b17f1bSmrg                videoRam = pciReadByte(pciTag(0, 0, 0), 0xE1) & 0x70;
81390b17f1bSmrg            }
814963d66acSmrg#endif
81590b17f1bSmrg            pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 10;
81690b17f1bSmrg            break;
81790b17f1bSmrg        case VIA_PM800:
818963d66acSmrg        case VIA_P4M800PRO:
81990b17f1bSmrg        case VIA_K8M800:
82090b17f1bSmrg#ifdef HAVE_PCIACCESS
82190b17f1bSmrg            pci_device_cfg_read_u8(vgaDevice, &videoRam, 0xA1);
82290b17f1bSmrg#else
82390b17f1bSmrg            videoRam = pciReadByte(pciTag(0, 0, 3), 0xA1) & 0x70;
82490b17f1bSmrg#endif
82590b17f1bSmrg            pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 10;
82690b17f1bSmrg            break;
82790b17f1bSmrg        case VIA_P4M890:
828963d66acSmrg        case VIA_K8M890:
82990b17f1bSmrg        case VIA_P4M900:
83090b17f1bSmrg        case VIA_CX700:
83190b17f1bSmrg        case VIA_VX800:
83290b17f1bSmrg        case VIA_VX855:
83390b17f1bSmrg        case VIA_VX900:
83490b17f1bSmrg#ifdef HAVE_PCIACCESS
83590b17f1bSmrg            pci_device_cfg_read_u8(vgaDevice, &videoRam, 0xA1);
83690b17f1bSmrg#else
83790b17f1bSmrg            videoRam = pciReadByte(pciTag(0, 0, 3), 0xA1) & 0x70;
83890b17f1bSmrg#endif
83990b17f1bSmrg            pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 12;
84090b17f1bSmrg            break;
84190b17f1bSmrg        default:
84290b17f1bSmrg            if (pScrn->videoRam < 16384 || pScrn->videoRam > 65536) {
84390b17f1bSmrg                xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
84490b17f1bSmrg                           "Using old memory-detection method.\n");
84590b17f1bSmrg                bMemSize = hwp->readSeq(hwp, 0x39);
84690b17f1bSmrg                if (bMemSize > 16 && bMemSize <= 128)
84790b17f1bSmrg                    pScrn->videoRam = (bMemSize + 1) << 9;
84890b17f1bSmrg                else if (bMemSize > 0 && bMemSize < 31)
84990b17f1bSmrg                    pScrn->videoRam = bMemSize << 12;
85090b17f1bSmrg                else {
85190b17f1bSmrg                    from = X_DEFAULT;
85290b17f1bSmrg                    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
85390b17f1bSmrg                               "Memory size detection failed: using 16 MB.\n");
85490b17f1bSmrg                    pScrn->videoRam = 16 << 10;
85590b17f1bSmrg                }
85690b17f1bSmrg            } else {
85790b17f1bSmrg                from = X_DEFAULT;
85890b17f1bSmrg                xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
85990b17f1bSmrg                           "No memory-detection done. Use VideoRAM option.\n");
86090b17f1bSmrg            }
86190b17f1bSmrg    }
86290b17f1bSmrg
86390b17f1bSmrg    /*
86490b17f1bSmrg     * PCI BAR are limited to 256 MB.
86590b17f1bSmrg     */
86690b17f1bSmrg    if (pScrn->videoRam > (256 << 10)) {
86790b17f1bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
86890b17f1bSmrg                    "Cannot use more than 256 MB of VRAM.\n");
86990b17f1bSmrg                    pScrn->videoRam = (256 << 10);
87090b17f1bSmrg    }
87190b17f1bSmrg
87290b17f1bSmrg    if (from == X_PROBED) {
87390b17f1bSmrg        xf86DrvMsg(pScrn->scrnIndex, from,
87490b17f1bSmrg                   "Probed amount of VideoRAM = %d kB\n", pScrn->videoRam);
87590b17f1bSmrg    }
87690b17f1bSmrg
87790b17f1bSmrg    /* Split the FB for SAMM. */
87890b17f1bSmrg    /* FIXME: For now, split the FB into two equal sections.
87990b17f1bSmrg     * This should be user-adjustable via a config option. */
88090b17f1bSmrg    if (pVia->IsSecondary) {
88190b17f1bSmrg        DevUnion *pPriv;
88290b17f1bSmrg        VIAEntPtr pVIAEnt;
88390b17f1bSmrg        VIAPtr pVia1;
88490b17f1bSmrg
88590b17f1bSmrg        pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gVIAEntityIndex);
88690b17f1bSmrg        pVIAEnt = pPriv->ptr;
88790b17f1bSmrg        pScrn->videoRam = pScrn->videoRam >> 1;
88890b17f1bSmrg        pVIAEnt->pPrimaryScrn->videoRam = pScrn->videoRam;
88990b17f1bSmrg        pVia1 = VIAPTR(pVIAEnt->pPrimaryScrn);
89090b17f1bSmrg        pVia1->videoRambytes = pScrn->videoRam << 10;
89190b17f1bSmrg        pVia->FrameBufferBase += (pScrn->videoRam << 10);
89290b17f1bSmrg    }
89390b17f1bSmrg
89490b17f1bSmrg    pVia->videoRambytes = pScrn->videoRam << 10;
89590b17f1bSmrg
89690b17f1bSmrg    /* maybe throw in some more sanity checks here */
89790b17f1bSmrg#ifndef HAVE_PCIACCESS
89890b17f1bSmrg    pVia->PciTag = pciTag(pVia->PciInfo->bus, pVia->PciInfo->device,
89990b17f1bSmrg                          pVia->PciInfo->func);
90090b17f1bSmrg#endif
90190b17f1bSmrg
90203bd066fSmrg    /* Map PCI hardware resources to the memory map. */
90303bd066fSmrg    if (!viaMapMMIO(pScrn)) {
90403bd066fSmrg        return FALSE;
90503bd066fSmrg    }
90603bd066fSmrg
90703bd066fSmrg    return TRUE;
90803bd066fSmrg}
90903bd066fSmrg
91003bd066fSmrgBool
91103bd066fSmrgumsCrtcInit(ScrnInfoPtr pScrn)
91203bd066fSmrg{
91303bd066fSmrg    drmmode_crtc_private_ptr iga1_rec = NULL, iga2_rec = NULL;
91403bd066fSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
91503bd066fSmrg    VIAPtr pVia = VIAPTR(pScrn);
91603bd066fSmrg#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,8,0,0,0)
91703bd066fSmrg    ClockRangePtr clockRanges;
91803bd066fSmrg#else
91903bd066fSmrg    ClockRangesPtr clockRanges;
92003bd066fSmrg#endif
92103bd066fSmrg    int max_pitch, max_height;
92203bd066fSmrg    VIABIOSInfoPtr pBIOSInfo;
92303bd066fSmrg    xf86CrtcPtr iga1, iga2;
92403bd066fSmrg
9251090d90aSmrg    /* 3X5.3B through 3X5.3F are scratch pad registers. */
9261090d90aSmrg    pVia->originalCR3B = hwp->readCrtc(hwp, 0x3B);
9271090d90aSmrg    pVia->originalCR3C = hwp->readCrtc(hwp, 0x3C);
9281090d90aSmrg    pVia->originalCR3D = hwp->readCrtc(hwp, 0x3D);
9291090d90aSmrg    pVia->originalCR3E = hwp->readCrtc(hwp, 0x3E);
9301090d90aSmrg    pVia->originalCR3F = hwp->readCrtc(hwp, 0x3F);
9311090d90aSmrg
93203bd066fSmrg    /* Read memory bandwidth from registers. */
93303bd066fSmrg    pVia->MemClk = hwp->readCrtc(hwp, 0x3D) >> 4;
93403bd066fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
93503bd066fSmrg                     "Detected MemClk %d\n", pVia->MemClk));
93603bd066fSmrg    if (pVia->MemClk >= VIA_MEM_END) {
93703bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
93803bd066fSmrg                   "Unknown Memory clock: %d\n", pVia->MemClk);
93903bd066fSmrg        pVia->MemClk = VIA_MEM_END - 1;
94003bd066fSmrg    }
94103bd066fSmrg    pBIOSInfo = pVia->pBIOSInfo;
94203bd066fSmrg    pBIOSInfo->Bandwidth = ViaGetMemoryBandwidth(pScrn);
94303bd066fSmrg
94403bd066fSmrg    if (pBIOSInfo->TVType == TVTYPE_NONE) {
94503bd066fSmrg        /* Use jumper to determine TV type. */
94603bd066fSmrg        if (hwp->readCrtc(hwp, 0x3B) & 0x02) {
94703bd066fSmrg            pBIOSInfo->TVType = TVTYPE_PAL;
94803bd066fSmrg            DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
94903bd066fSmrg                             "Detected TV standard: PAL.\n"));
95003bd066fSmrg        } else {
95103bd066fSmrg            pBIOSInfo->TVType = TVTYPE_NTSC;
95203bd066fSmrg            DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
95303bd066fSmrg                             "Detected TV standard: NTSC.\n"));
95403bd066fSmrg        }
95503bd066fSmrg    }
95603bd066fSmrg
95703bd066fSmrg    if (pVia->drmmode.hwcursor) {
95803bd066fSmrg        if (!xf86LoadSubModule(pScrn, "ramdac"))
95903bd066fSmrg            return FALSE;
96003bd066fSmrg    }
96103bd066fSmrg
96203bd066fSmrg    if (!xf86LoadSubModule(pScrn, "i2c"))
96303bd066fSmrg        return FALSE;
96403bd066fSmrg    else
96503bd066fSmrg        ViaI2CInit(pScrn);
96603bd066fSmrg
96703bd066fSmrg    if (!xf86LoadSubModule(pScrn, "ddc"))
96803bd066fSmrg        return FALSE;
96903bd066fSmrg
97003bd066fSmrg    /*
97103bd066fSmrg     * Set up ClockRanges, which describe what clock ranges are
97203bd066fSmrg     * available, and what sort of modes they can be used for.
97303bd066fSmrg     */
97403bd066fSmrg
97503bd066fSmrg#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,8,0,0,0)
97603bd066fSmrg    clockRanges = xnfalloc(sizeof(ClockRange));
97703bd066fSmrg#else
97803bd066fSmrg    clockRanges = xnfalloc(sizeof(ClockRanges));
97903bd066fSmrg#endif
98003bd066fSmrg    clockRanges->next = NULL;
98103bd066fSmrg    clockRanges->minClock = 20000;
98203bd066fSmrg    clockRanges->maxClock = 230000;
98303bd066fSmrg
98403bd066fSmrg    clockRanges->clockIndex = -1;
98503bd066fSmrg    clockRanges->interlaceAllowed = TRUE;
98603bd066fSmrg    clockRanges->doubleScanAllowed = FALSE;
98703bd066fSmrg    pScrn->clockRanges = clockRanges;
98803bd066fSmrg
98903bd066fSmrg    /*
99003bd066fSmrg     * Now handle the outputs
99103bd066fSmrg     */
99203bd066fSmrg    iga1_rec = (drmmode_crtc_private_ptr) xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
99303bd066fSmrg    if (!iga1_rec) {
99403bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "IGA1 Rec allocation failed.\n");
99590b17f1bSmrg        return FALSE;
99603bd066fSmrg    }
99703bd066fSmrg
99803bd066fSmrg    iga1 = xf86CrtcCreate(pScrn, &iga1_crtc_funcs);
99903bd066fSmrg    if (!iga1) {
100003bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86CrtcCreate failed.\n");
100103bd066fSmrg        free(iga1_rec);
100203bd066fSmrg        return FALSE;
100303bd066fSmrg    }
100403bd066fSmrg    iga1_rec->drmmode = &pVia->drmmode;
100503bd066fSmrg    iga1_rec->index = 0;
100603bd066fSmrg    iga1->driver_private = iga1_rec;
100703bd066fSmrg
100803bd066fSmrg    iga2_rec = (drmmode_crtc_private_ptr) xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
100903bd066fSmrg    if (!iga2_rec) {
101003bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "IGA1 Rec allocation failed.\n");
101103bd066fSmrg        xf86CrtcDestroy(iga1);
101203bd066fSmrg        return FALSE;
101303bd066fSmrg    }
101490b17f1bSmrg
101503bd066fSmrg    iga2 = xf86CrtcCreate(pScrn, &iga2_crtc_funcs);
101603bd066fSmrg    if (!iga2) {
101703bd066fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86CrtcCreate failed.\n");
101803bd066fSmrg        xf86CrtcDestroy(iga1);
101903bd066fSmrg        free(iga2_rec);
102090b17f1bSmrg        return FALSE;
102103bd066fSmrg    }
102203bd066fSmrg    iga2_rec->drmmode = &pVia->drmmode;
102303bd066fSmrg    iga2_rec->index = 1;
102403bd066fSmrg    iga2->driver_private = iga2_rec;
102503bd066fSmrg
10261090d90aSmrg    if (!pScrn->bitsPerPixel) {
10271090d90aSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
10281090d90aSmrg                    "Detected bitsPerPixel to be 0 bit.\n");
10291090d90aSmrg        xf86CrtcDestroy(iga2);
10301090d90aSmrg        xf86CrtcDestroy(iga1);
10311090d90aSmrg        return FALSE;
103203bd066fSmrg    }
103303bd066fSmrg
103403bd066fSmrg    /*
103503bd066fSmrg     * CLE266A:
103603bd066fSmrg     *   Max Line Pitch: 4080, (FB corruption when higher, driver problem?)
103703bd066fSmrg     *   Max Height: 4096 (and beyond)
103803bd066fSmrg     *
103903bd066fSmrg     * CLE266A: primary AdjustFrame can use only 24 bits, so we are limited
104003bd066fSmrg     * to 12x11 bits; 4080x2048 (~2:1), 3344x2508 (4:3), or 2896x2896 (1:1).
104103bd066fSmrg     * TODO Test CLE266Cx, KM400, KM400A, K8M800, CN400 please.
104203bd066fSmrg     *
104303bd066fSmrg     * We should be able to limit the memory available for a mode to 32 MB,
104403bd066fSmrg     * but miScanLineWidth fails to catch this properly (apertureSize).
104503bd066fSmrg     */
10461090d90aSmrg    max_pitch = (8192 / ((pScrn->bitsPerPixel + 7) >> 3)) - (16 / ((pScrn->bitsPerPixel + 7) >> 3));
10471090d90aSmrg    max_height = 8192 / ((pScrn->bitsPerPixel + 7) >> 3);
104803bd066fSmrg
104903bd066fSmrg    xf86CrtcSetSizeRange(pScrn, 320, 200, max_pitch, max_height);
105003bd066fSmrg
105103bd066fSmrg    viaOutputDetect(pScrn);
105203bd066fSmrg
105390b17f1bSmrg    return TRUE;
105490b17f1bSmrg}
1055