lx_driver.c revision e831b51b
1/* Copyright (c) 2003-2008 Advanced Micro Devices, Inc.
2 *
3 * Portioned modeled from xf86-video-intel/src/i830_driver.c
4 * Copyright 2001 VA Linux Systems Inc., Fremont, California.
5 * Copyright \ufffd 2002 by David Dawes
6
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to
9 * deal in the Software without restriction, including without limitation the
10 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
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 NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
24 *
25 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
26 * contributors may be used to endorse or promote products derived from this
27 * software without specific prior written permission.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <stdio.h>
35#include <string.h>
36#include <fcntl.h>
37#include <unistd.h>
38#include <sys/mman.h>
39
40#include "xf86.h"
41#include "xf86_OSproc.h"
42#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
43#include "xf86Resources.h"
44#endif
45#include "xf86i2c.h"
46#include "xf86Crtc.h"
47#include "xf86cmap.h"
48#include "compiler.h"
49#include "mipointer.h"
50#include "fb.h"
51#include "miscstruct.h"
52#include "micmap.h"
53#include "vbe.h"
54#include "fb.h"
55#include "cim_defs.h"
56#include "cim_regs.h"
57#include "geode.h"
58
59/* Bring in VGA functions */
60#include "lx_vga.c"
61
62#define LX_MAX_WIDTH  1940
63#define LX_MAX_HEIGHT 1600
64
65/* Size of the register blocks */
66
67#define LX_GP_REG_SIZE  0x4000
68#define LX_VG_REG_SIZE  0x4000
69#define LX_VID_REG_SIZE 0x4000
70#define LX_VIP_REG_SIZE 0x4000
71
72/* Size of the Cimarron command buffer */
73#define CIM_CMD_BFR_SZ 0x200000
74
75extern OptionInfoRec LX_GeodeOptions[];
76
77unsigned char *XpressROMPtr;
78
79static Bool
80LXSaveScreen(ScreenPtr pScrn, int mode)
81{
82    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
83    GeodePtr pGeode = GEODEPTR(pScrni);
84
85    if (pGeode->useVGA && !pScrni->vtSema)
86        return vgaHWSaveScreen(pScrn, mode);
87
88    return TRUE;
89}
90
91/* This is an overly complex MSR read mechanism */
92
93/* From Cimarron - the VSAII read/write methods - we use these as fallback */
94
95#define LX_MSR_READ(adr,lo,hi)              \
96     __asm__ __volatile__(                      \
97        " mov $0x0AC1C, %%edx\n"                \
98        " mov $0xFC530007, %%eax\n"             \
99        " out %%eax,%%dx\n"                     \
100        " add $2,%%dl\n"                        \
101        " in %%dx, %%ax"                        \
102        : "=a" (lo), "=d" (hi)                  \
103        : "c" (adr))
104
105#define LX_MSR_WRITE(adr,low,high) \
106  { int d0, d1, d2, d3, d4;        \
107  __asm__ __volatile__(            \
108    " push %%ebx\n"                \
109    " mov $0x0AC1C, %%edx\n"       \
110    " mov $0xFC530007, %%eax\n"    \
111    " out %%eax,%%dx\n"            \
112    " add $2,%%dl\n"               \
113    " mov %6, %%ebx\n"             \
114    " mov %7, %0\n"                \
115    " mov %5, %3\n"                \
116    " xor %2, %2\n"                \
117    " xor %1, %1\n"                \
118    " out %%ax, %%dx\n"            \
119    " pop %%ebx\n"                 \
120    : "=a"(d0),"=&D"(d1),"=&S"(d2), \
121      "=c"(d3),"=d"(d4)  \
122    : "1"(adr),"2"(high),"3"(low)); \
123  }
124
125static void
126LXReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi)
127{
128    if (GeodeReadMSR(addr, lo, hi) == -1) {
129        unsigned int l, h;
130
131        LX_MSR_READ(addr, l, h);
132        *lo = l;
133        *hi = h;
134    }
135}
136
137static void
138LXWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi)
139{
140    if (GeodeWriteMSR(addr, lo, hi) == -1)
141        LX_MSR_WRITE(addr, lo, hi);
142}
143
144static unsigned int
145LXCalcPitch(ScrnInfoPtr pScrni)
146{
147    GeodeRec *pGeode = GEODEPTR(pScrni);
148
149    if (pGeode->tryCompression)
150        return GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
151    else
152        return ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
153}
154
155#ifdef XSERVER_LIBPCIACCESS
156static inline void *
157map_pci_mem(ScrnInfoPtr pScrni, int vram,
158            struct pci_device *dev, int bar, int size)
159{
160    void *ptr;
161    int map_size = size ? size : dev->regions[bar].size;
162
163    int err = pci_device_map_range(dev,
164                                   dev->regions[bar].base_addr,
165                                   map_size,
166                                   PCI_DEV_MAP_FLAG_WRITABLE |
167                                   (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
168                                   &ptr);
169
170    if (err)
171        return NULL;
172    return ptr;
173}
174
175static inline int
176unmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size)
177{
178    return pci_device_unmap_range(dev, ptr, size);
179}
180
181#endif
182
183static Bool
184LXMapMem(ScrnInfoPtr pScrni)
185{
186    GeodeRec *pGeode = GEODEPTR(pScrni);
187    int index = pScrni->scrnIndex;
188    unsigned long cmd_bfr_phys;
189
190    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
191
192#ifndef XSERVER_LIBPCIACCESS
193    PCITAG tag;
194
195    tag = pciTag(pci->bus, pci->device, pci->func);
196
197    cim_gp_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
198                                                 tag, pci->memBase[1],
199                                                 LX_GP_REG_SIZE);
200
201    cim_vg_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
202                                                 tag, pci->memBase[2],
203                                                 LX_VG_REG_SIZE);
204
205    cim_vid_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
206                                                  tag, pci->memBase[3],
207                                                  LX_VID_REG_SIZE);
208
209    cim_vip_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
210                                                  tag, pci->memBase[4],
211                                                  LX_VIP_REG_SIZE);
212
213    cim_fb_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_FRAMEBUFFER,
214                                                 tag, pci->memBase[0],
215                                                 pGeode->FBAvail +
216                                                 CIM_CMD_BFR_SZ);
217#else
218    cim_gp_ptr = map_pci_mem(pScrni, 0, pci, 1, LX_GP_REG_SIZE);
219    cim_vg_ptr = map_pci_mem(pScrni, 0, pci, 2, LX_VG_REG_SIZE);
220    cim_vid_ptr = map_pci_mem(pScrni, 0, pci, 3, LX_VID_REG_SIZE);
221    cim_vip_ptr = map_pci_mem(pScrni, 0, pci, 4, LX_VIP_REG_SIZE);
222    cim_fb_ptr =
223        map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail + CIM_CMD_BFR_SZ);
224#endif
225
226    if (pScrni->memPhysBase == 0)
227        pScrni->memPhysBase = PCI_REGION_BASE(pci, 0, REGION_MEM);
228
229    cmd_bfr_phys = PCI_REGION_BASE(pci, 0, REGION_MEM) + pGeode->CmdBfrOffset;
230    cim_cmd_base_ptr = cim_fb_ptr + pGeode->CmdBfrOffset;
231
232    if (!cim_gp_ptr || !cim_vg_ptr || !cim_vid_ptr || !cim_fb_ptr ||
233        !cim_vip_ptr)
234        return FALSE;
235
236    gp_set_frame_buffer_base(PCI_REGION_BASE(pci, 0, REGION_MEM),
237                             pGeode->FBAvail);
238    gp_set_command_buffer_base(cmd_bfr_phys, 0, pGeode->CmdBfrSize);
239
240#ifndef XSERVER_LIBPCIACCESS
241    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
242#else
243    {
244        int fd = open("/dev/mem", O_RDWR);
245        if (fd < 0) {
246            xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n");
247            return FALSE;
248        }
249        XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000);
250        close(fd);
251    }
252#endif
253
254    pGeode->FBBase = cim_fb_ptr;
255
256    if (!pGeode->NoAccel)
257        pGeode->pExa->memoryBase = pGeode->FBBase;
258
259    xf86DrvMsg(index, X_INFO, "Geode LX video memory %x bytes at %p\n",
260               pGeode->FBAvail, pGeode->FBBase);
261
262    return TRUE;
263}
264
265/* Check to see if VGA exists - we map the space and look for a
266   signature - if it doesn't match exactly, then we assume no VGA.
267*/
268
269static Bool
270LXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt)
271{
272#ifndef XSERVER_LIBPCIACCESS
273    unsigned char *ptr;
274    const char *vgasig = "IBM VGA Compatible";
275    int ret;
276
277    ptr =
278        xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
279                      strlen(vgasig));
280
281    if (ptr == NULL)
282        return FALSE;
283
284    ret = memcmp(ptr, vgasig, strlen(vgasig));
285    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
286
287    return ret ? FALSE : TRUE;
288#else
289    pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index);
290
291    return pci_device_is_boot_vga(pci);
292#endif
293}
294
295static Bool
296LXCrtcResize(ScrnInfoPtr pScrni, int width, int height)
297{
298    return TRUE;
299}
300
301static const xf86CrtcConfigFuncsRec lx_xf86crtc_config_funcs = {
302    LXCrtcResize,
303};
304
305static Bool
306LXPreInit(ScrnInfoPtr pScrni, int flags)
307{
308    GeodePtr pGeode;
309    EntityInfoPtr pEnt;
310    OptionInfoRec *GeodeOptions = &LX_GeodeOptions[0];
311    rgb defaultWeight = { 0, 0, 0 };
312    const char *s;
313
314    if (pScrni->numEntities != 1)
315        return FALSE;
316
317    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
318#ifndef XSERVER_LIBPCIACCESS
319    if (pEnt->resources)
320        return FALSE;
321#endif
322    if (flags & PROBE_DETECT) {
323        GeodeProbeDDC(pScrni, pEnt->index);
324        return TRUE;
325    }
326
327    pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec));
328
329    if (pGeode == NULL)
330        return FALSE;
331
332    pGeode->useVGA = LXCheckVGA(pScrni, pEnt);
333    pGeode->VGAActive = FALSE;
334    pGeode->pEnt = pEnt;
335
336    if (pGeode->useVGA) {
337        if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
338            pGeode->useVGA = FALSE;
339        else
340            vgaHWSetStdFuncs(VGAHWPTR(pScrni));
341
342        pGeode->vesa = calloc(1, sizeof(VESARec));
343    }
344
345    cim_rdmsr = LXReadMSR;
346    cim_wrmsr = LXWriteMSR;
347
348    /* Set up the Cimarron MSR tables */
349    msr_init_table();
350
351    /* By default, we support panel and CRT - the config file should
352     * disable the ones we don't want
353     */
354
355    pGeode->Output = OUTPUT_PANEL | OUTPUT_CRT;
356
357    /* Fill in the monitor information */
358    pScrni->monitor = pScrni->confScreen->monitor;
359
360    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
361        return FALSE;
362
363    switch (pScrni->depth) {
364    case 8:
365        pScrni->rgbBits = 8;
366    case 16:
367    case 24:
368    case 32:
369        break;
370    default:
371        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
372                   "The driver does not support %d as a depth.\n",
373                   pScrni->depth);
374        return FALSE;
375    }
376
377    xf86PrintDepthBpp(pScrni);
378
379    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
380        return FALSE;
381
382    if (!xf86SetDefaultVisual(pScrni, -1))
383        return FALSE;
384
385    /*
386     * If the driver can do gamma correction, it should call xf86SetGamma()
387     * here.
388     */
389    {
390        Gamma zeros = { 0.0, 0.0, 0.0 };
391
392        if (!xf86SetGamma(pScrni, zeros)) {
393            return FALSE;
394        }
395    }
396
397    pScrni->progClock = TRUE;
398    xf86CollectOptions(pScrni, NULL);
399    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
400
401    /* Set up our various options that may get reversed as we go on */
402
403    pGeode->tryHWCursor = TRUE;
404    pGeode->tryCompression = TRUE;
405
406    /* Protect against old versions of EXA */
407
408#if (EXA_VERSION_MAJOR < 2)
409    pGeode->NoAccel = TRUE;
410    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
411               "*** This driver was compiled with EXA version %d\n");
412    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
413               "*** we need version 2 or greater\n");
414    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
415               "*** All accelerations are being turned off.\n");
416#else
417    pGeode->NoAccel = FALSE;
418#endif
419
420    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
421
422    xf86GetOptValBool(GeodeOptions, LX_OPTION_HW_CURSOR, &pGeode->tryHWCursor);
423
424    if (!xf86GetOptValInteger(GeodeOptions, LX_OPTION_FBSIZE,
425                              (int *) &(pGeode->FBAvail)))
426        pGeode->FBAvail = 0;
427
428    /* For compatability - allow SWCursor too */
429
430    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_SW_CURSOR, FALSE))
431        pGeode->tryHWCursor = FALSE;
432
433    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOCOMPRESSION, FALSE))
434        pGeode->tryCompression = FALSE;
435
436    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOACCEL, FALSE))
437        pGeode->NoAccel = TRUE;
438
439    pGeode->rotation = RR_Rotate_0;
440
441    if ((s = xf86GetOptValString(GeodeOptions, LX_OPTION_ROTATE))) {
442
443        if (!xf86NameCmp(s, "LEFT"))
444            pGeode->rotation = RR_Rotate_90;
445        else if (!xf86NameCmp(s, "INVERT"))
446            pGeode->rotation = RR_Rotate_180;
447        else if (!xf86NameCmp(s, "CCW"))
448            pGeode->rotation = RR_Rotate_270;
449        else
450            xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s);
451    }
452
453    xf86GetOptValInteger(GeodeOptions, LX_OPTION_EXA_SCRATCH_BFRSZ,
454                         (int *) &(pGeode->exaBfrSz));
455
456    if (pGeode->exaBfrSz <= 0)
457        pGeode->exaBfrSz = 0;
458
459    if (pGeode->Output & OUTPUT_PANEL) {
460        if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOPANEL, FALSE))
461            pGeode->Output &= ~OUTPUT_PANEL;
462    }
463
464    /* Panel detection code -
465     * 1.  See if an OLPC DCON is attached - we can make some assumptions
466     * about the panel if so.
467     * 2.  Use panel mode specified in the config
468     * 3.  "Autodetect" the panel through VSA
469     */
470
471    if (dcon_init(pScrni)) {
472        pGeode->Output = OUTPUT_PANEL | OUTPUT_DCON;
473    }
474    else if (pGeode->Output & OUTPUT_PANEL) {
475        char *pmode = xf86GetOptValString(GeodeOptions, LX_OPTION_PANEL_MODE);
476
477        if (pmode != NULL)
478            pGeode->panelMode = LXGetManualPanelMode(pmode);
479
480        if (pGeode->panelMode == NULL)
481            pGeode->panelMode = LXGetLegacyPanelMode(pScrni);
482
483        if (pGeode->panelMode == NULL)
484            pGeode->Output &= ~OUTPUT_PANEL;
485    }
486
487    /* Default to turn scaling on for panels */
488
489    if (pGeode->Output & OUTPUT_PANEL)
490        pGeode->Scale = TRUE;
491
492    xf86DrvMsg(pScrni->scrnIndex, X_INFO, "LX output options:\n");
493    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " CRT: %s\n",
494               pGeode->Output & OUTPUT_CRT ? "YES" : "NO");
495
496    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " PANEL: %s\n",
497               pGeode->Output & OUTPUT_PANEL ? "YES" : "NO");
498
499    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " DCON: %s\n",
500               pGeode->Output & OUTPUT_DCON ? "YES" : "NO");
501
502    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " VGA: %s\n",
503               pGeode->useVGA ? "YES" : "NO");
504
505    /* Set up VGA */
506
507    if (pGeode->useVGA) {
508        VESARec *pVesa;
509
510        if (!xf86LoadSubModule(pScrni, "int10"))
511            return FALSE;
512
513        pVesa = pGeode->vesa;
514
515        if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
516            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
517                       "Unable to initialize 1NT10 support\n");
518            pGeode->useVGA = FALSE;
519        }
520    }
521
522    /* Read the amount of framebuffer memory */
523    /* First try to read it from the framebuffer, and if that fails,
524     * do it the legacy way
525     */
526
527    if (pGeode->FBAvail == 0) {
528        if (GeodeGetSizeFromFB(&pGeode->FBAvail)) {
529            unsigned long value;
530
531            cim_outw(0xAC1C, 0xFC53);
532            cim_outw(0xAC1C, 0x0200);
533
534            value = (unsigned long) (cim_inw(0xAC1E)) & 0xFE;
535            pGeode->FBAvail = value << 20;
536        }
537    }
538
539    pScrni->fbOffset = 0;
540
541    if (pGeode->pEnt->device->videoRam == 0)
542        pScrni->videoRam = pGeode->FBAvail / 1024;
543    else {
544        pScrni->videoRam = pGeode->pEnt->device->videoRam;
545        pGeode->FBAvail = pScrni->videoRam << 10;
546    }
547
548    /* If we have <= 16Mb of memory then compression is going
549       to hurt - so warn and disable */
550
551    if (pGeode->tryCompression && pGeode->FBAvail <= 0x1000000) {
552        xf86DrvMsg(pScrni->scrnIndex, X_INFO,
553                   "%x bytes of video memory is less then optimal\n",
554                   pGeode->FBAvail);
555        xf86DrvMsg(pScrni->scrnIndex, X_INFO,
556                   "when compression is on. Disabling compression.\n");
557        pGeode->tryCompression = FALSE;
558    }
559
560    /* Carve out some memory for the command buffer */
561
562    pGeode->CmdBfrSize = CIM_CMD_BFR_SZ;
563    pGeode->FBAvail -= CIM_CMD_BFR_SZ;
564
565    pGeode->CmdBfrOffset = pGeode->FBAvail;
566
567    /* Allocate a a CRTC config structure */
568    xf86CrtcConfigInit(pScrni, &lx_xf86crtc_config_funcs);
569
570    /* Set up the GPU CRTC */
571    LXSetupCrtc(pScrni);
572
573    xf86CrtcSetSizeRange(pScrni, 320, 200, LX_MAX_WIDTH, LX_MAX_HEIGHT);
574
575    /* Setup the output */
576    LXSetupOutput(pScrni);
577
578    if (!xf86InitialConfiguration(pScrni, FALSE)) {
579        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes.\n");
580        return FALSE;
581    }
582
583    xf86PrintModes(pScrni);
584
585    pScrni->currentMode = pScrni->modes;
586
587    pGeode->Pitch = LXCalcPitch(pScrni);
588
589    xf86SetDpi(pScrni, 0, 0);
590
591    /* Load the modules we'll need */
592
593    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
594        return FALSE;
595    }
596
597    if (!pGeode->NoAccel) {
598        if (!xf86LoadSubModule(pScrni, "exa"))
599            return FALSE;
600    }
601#ifndef XSERVER_LIBPCIACCESS
602    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
603        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
604                   "Couldn't register the resources.\n");
605        return FALSE;
606    }
607#endif
608    return TRUE;
609}
610
611static void
612LXRestore(ScrnInfoPtr pScrni)
613{
614    GeodeRec *pGeode = GEODEPTR(pScrni);
615
616    if (pGeode->useVGA) {
617        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
618
619        vgaHWProtect(pScrni, TRUE);
620        vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
621        vgaHWProtect(pScrni, FALSE);
622    }
623}
624
625static Bool
626LXUnmapMem(ScrnInfoPtr pScrni)
627{
628#ifndef XSERVER_LIBPCIACCESS
629    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_gp_ptr, LX_GP_REG_SIZE);
630    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vg_ptr, LX_VG_REG_SIZE);
631    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vid_ptr, LX_VID_REG_SIZE);
632    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vip_ptr, LX_VIP_REG_SIZE);
633
634    xf86UnMapVidMem(pScrni->scrnIndex, XpressROMPtr, 0x10000);
635#else
636    GeodeRec *pGeode = GEODEPTR(pScrni);
637    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
638
639    unmap_pci_mem(pScrni, pci, cim_gp_ptr, LX_GP_REG_SIZE);
640    unmap_pci_mem(pScrni, pci, cim_vg_ptr, LX_VG_REG_SIZE);
641    unmap_pci_mem(pScrni, pci, cim_vid_ptr, LX_VID_REG_SIZE);
642    unmap_pci_mem(pScrni, pci, cim_vip_ptr, LX_VIP_REG_SIZE);
643    unmap_pci_mem(pScrni, pci, cim_fb_ptr, pGeode->FBAvail + CIM_CMD_BFR_SZ);
644
645    munmap(XpressROMPtr, 0x10000);
646#endif
647
648    return TRUE;
649}
650
651/* These should be correctly accounted for rotation */
652
653void
654LXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
655{
656    SCRN_INFO_PTR(arg);
657    GeodeRec *pGeode = GEODEPTR(pScrni);
658
659    unsigned long offset;
660
661    offset = (y * pGeode->Pitch);
662    offset += x * (pScrni->bitsPerPixel >> 3);
663
664    vg_set_display_offset(offset);
665}
666
667static Bool
668LXSwitchMode(SWITCH_MODE_ARGS_DECL)
669{
670    SCRN_INFO_PTR(arg);
671    GeodeRec *pGeode = GEODEPTR(pScrni);
672
673    /* Set the new mode */
674    return xf86SetSingleMode(pScrni, pMode, pGeode->rotation);
675}
676
677static void
678LXLeaveGraphics(ScrnInfoPtr pScrni)
679{
680    GeodeRec *pGeode = GEODEPTR(pScrni);
681    VG_PANNING_COORDINATES panning;
682
683    gp_wait_until_idle();
684
685    lx_disable_dac_power(pScrni, DF_CRT_DISABLE);
686
687    vg_set_custom_mode(&(pGeode->FBcimdisplaytiming.vgDisplayMode),
688                       pGeode->FBcimdisplaytiming.wBpp);
689
690    vg_set_compression_enable(0);
691
692    /* Restore the previous Compression state */
693    if (pGeode->FBCompressionEnable) {
694        vg_configure_compression(&(pGeode->FBCBData));
695        vg_set_compression_enable(1);
696    }
697
698    vg_set_display_pitch(pGeode->FBcimdisplaytiming.wPitch);
699    vg_set_display_offset(pGeode->FBDisplayOffset);
700
701    /* Restore Cursor */
702    vg_set_cursor_position(pGeode->FBCursor.cursor_x,
703                           pGeode->FBCursor.cursor_y, &panning);
704
705    LXRestore(pScrni);
706
707    if (pGeode->useVGA && pGeode->VGAActive) {
708        pGeode->vesa->pInt->num = 0x10;
709        pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
710        pGeode->vesa->pInt->bx = 0;
711        xf86ExecX86int10(pGeode->vesa->pInt);
712        vg_delay_milliseconds(3);
713    }
714
715    lx_enable_dac_power(pScrni, 1);
716    pScrni->vtSema = FALSE;
717}
718
719static Bool
720LXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
721{
722    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
723    GeodeRec *pGeode = GEODEPTR(pScrni);
724
725    if (pScrni->vtSema)
726        LXLeaveGraphics(pScrni);
727
728    if (pGeode->pExa) {
729        exaDriverFini(pScrn);
730        free(pGeode->pExa);
731        pGeode->pExa = NULL;
732    }
733
734    /* Unmap the offscreen allocations */
735    GeodeCloseOffscreen(pScrni);
736
737    LXUnmapMem(pScrni);
738
739    if (pGeode->useVGA)
740        vgaHWUnmapMem(pScrni);
741
742    pScrni->PointerMoved = pGeode->PointerMoved;
743    pScrn->CloseScreen = pGeode->CloseScreen;
744
745    if (pScrn->CloseScreen)
746        return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS);
747
748    return TRUE;
749}
750
751static Bool
752LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
753{
754    int bpp;
755    GeodeRec *pGeode = GEODEPTR(pScrni);
756
757    pGeode->VGAActive = gu3_get_vga_active();
758
759    gp_wait_until_idle();
760
761    vg_get_current_display_mode(&pGeode->FBcimdisplaytiming.vgDisplayMode,
762                                &bpp);
763
764    pGeode->FBcimdisplaytiming.wBpp = bpp;
765    pGeode->FBcimdisplaytiming.wPitch = vg_get_display_pitch();
766
767    pGeode->FBDisplayOffset = vg_get_display_offset();
768
769    if (pGeode->useVGA && pGeode->VGAActive) {
770        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
771
772        pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
773    }
774
775    pGeode->FBCompressionEnable = vg_get_compression_enable();
776    vg_get_compression_info(&(pGeode->FBCBData));
777
778    /* Save Cursor offset */
779    vg_get_cursor_info(&pGeode->FBCursor);
780
781    /* Turn off the VGA */
782
783    if (pGeode->useVGA) {
784        unsigned short sequencer;
785        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
786
787        /* Unlock VGA registers */
788        vgaHWUnlock(pvgaHW);
789
790        /* Save the current state and setup the current mode */
791        vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
792
793        /* DISABLE VGA SEQUENCER */
794        /* This allows the VGA state machine to terminate. We must delay */
795        /* such that there are no pending MBUS requests.  */
796
797        cim_outb(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_CLK_MODE);
798        sequencer = cim_inb(DC3_SEQUENCER_DATA);
799        sequencer |= DC3_CLK_MODE_SCREEN_OFF;
800        cim_outb(DC3_SEQUENCER_DATA, sequencer);
801
802        vg_delay_milliseconds(1);
803
804        /* BLANK THE VGA DISPLAY */
805        cim_outw(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_RESET);
806        sequencer = cim_inb(DC3_SEQUENCER_DATA);
807        sequencer &= ~DC3_RESET_VGA_DISP_ENABLE;
808        cim_outb(DC3_SEQUENCER_DATA, sequencer);
809
810        vg_delay_milliseconds(1);
811    }
812
813    /* Clear the framebuffer */
814    memset(pGeode->FBBase, 0, pGeode->displaySize);
815
816    /* Set the modes */
817    if (!xf86SetDesiredModes(pScrni))
818        return FALSE;
819
820    pScrni->vtSema = TRUE;
821
822    return TRUE;
823}
824
825static void
826LXLoadPalette(ScrnInfoPtr pScrni,
827              int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
828{
829    int i, index, color;
830
831    for (i = 0; i < numColors; i++) {
832        index = indizes[i] & 0xFF;
833        color = (((unsigned long) (colors[index].red & 0xFF)) << 16) |
834            (((unsigned long) (colors[index].green & 0xFF)) << 8) |
835            ((unsigned long) (colors[index].blue & 0xFF));
836
837        vg_set_display_palette_entry(index, color);
838    }
839}
840
841static Bool
842LXScreenInit(SCREEN_INIT_ARGS_DECL)
843{
844    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
845    GeodeRec *pGeode = GEODEPTR(pScrni);
846    int ret;
847    unsigned int dwidth;
848
849    pGeode->starting = TRUE;
850
851    /* If we are using VGA then go ahead and map the memory */
852
853    if (pGeode->useVGA) {
854
855        if (!vgaHWMapMem(pScrni))
856            return FALSE;
857
858        vgaHWGetIOBase(VGAHWPTR(pScrni));
859    }
860
861    if (!pGeode->NoAccel) {
862
863        pGeode->pExa = exaDriverAlloc();
864
865        if (pGeode->pExa) {
866
867            pGeode->pExa->memoryBase = 0;
868            pGeode->pExa->memorySize = 0;
869
870            pGeode->pExa->pixmapOffsetAlign = 32;
871            pGeode->pExa->pixmapPitchAlign = 32;
872            pGeode->pExa->flags = EXA_OFFSCREEN_PIXMAPS;
873            pGeode->pExa->maxX = LX_MAX_WIDTH - 1;
874            pGeode->pExa->maxY = LX_MAX_HEIGHT - 1;
875        }
876        else {
877            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
878                       "Couldn't allocate the EXA structure.\n");
879            pGeode->NoAccel = TRUE;
880        }
881    }
882
883    /* Map the memory here before doing anything else */
884
885    if (!LXMapMem(pScrni))
886        return FALSE;
887
888    LXInitOffscreen(pScrni);
889
890    /* XXX FIXME - Take down any of the structures on failure? */
891    if (!LXEnterGraphics(pScrn, pScrni))
892        return FALSE;
893
894    miClearVisualTypes();
895
896    /* XXX Again - take down anything? */
897
898    if (pScrni->bitsPerPixel > 8) {
899        if (!miSetVisualTypes(pScrni->depth,
900                              TrueColorMask, pScrni->rgbBits,
901                              pScrni->defaultVisual)) {
902            return FALSE;
903        }
904    }
905    else {
906        if (!miSetVisualTypes(pScrni->depth,
907                              miGetDefaultVisualMask(pScrni->depth),
908                              pScrni->rgbBits, pScrni->defaultVisual)) {
909            return FALSE;
910        }
911    }
912
913    miSetPixmapDepths();
914
915    if (pScrni->virtualX > pScrni->displayWidth)
916        pScrni->displayWidth = pScrni->virtualX;
917
918    /* Point at the visible area to start */
919
920    /* fbScreenInit assumes that the stride is display width *
921     * bytes per pixel.  If compression is on, then our stride might
922     * be completely different, so we divide the pitch by the
923     * bytes per pixel to fake fbScreenInit into doing the right thing */
924
925    dwidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
926
927    ret = fbScreenInit(pScrn, pGeode->FBBase,
928                       pScrni->virtualX, pScrni->virtualY,
929                       pScrni->xDpi, pScrni->yDpi, dwidth,
930                       pScrni->bitsPerPixel);
931
932    if (!ret)
933        return FALSE;
934
935    xf86SetBlackWhitePixels(pScrn);
936
937    /* Set up the color ordering */
938    if (pScrni->bitsPerPixel > 8) {
939        VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
940
941        while (--visual >= pScrn->visuals) {
942            if ((visual->class | DynamicClass) == DirectColor) {
943                visual->offsetRed = pScrni->offset.red;
944                visual->offsetGreen = pScrni->offset.green;
945                visual->offsetBlue = pScrni->offset.blue;
946                visual->redMask = pScrni->mask.red;
947                visual->greenMask = pScrni->mask.green;
948                visual->blueMask = pScrni->mask.blue;
949            }
950        }
951    }
952
953    /* Must follow the color ordering */
954    fbPictureInit(pScrn, 0, 0);
955
956    if (!pGeode->NoAccel)
957        pGeode->NoAccel = LXExaInit(pScrn) ? FALSE : TRUE;
958
959    xf86SetBackingStore(pScrn);
960
961    /* Set up the soft cursor */
962    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
963
964    /* Set up the HW cursor - must follow the soft cursor init */
965
966    if (pGeode->tryHWCursor) {
967        if (!LXCursorInit(pScrn))
968            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
969                       "Hardware cursor initialization failed.\n");
970    }
971
972    /* Set up the color map */
973
974    if (!miCreateDefColormap(pScrn))
975        return FALSE;
976
977    if (pScrni->bitsPerPixel == 8) {
978        /* Must follow initialization of the default colormap */
979
980        if (!xf86HandleColormaps(pScrn, 256, 8,
981                                 LXLoadPalette, NULL,
982                                 CMAP_PALETTED_TRUECOLOR |
983                                 CMAP_RELOAD_ON_MODE_SWITCH)) {
984            return FALSE;
985        }
986    }
987    xf86DPMSInit(pScrn, xf86DPMSSet, 0);
988
989    LXInitVideo(pScrn);
990
991    pGeode->PointerMoved = pScrni->PointerMoved;
992    pScrni->PointerMoved = GeodePointerMoved;
993
994    pGeode->CloseScreen = pScrn->CloseScreen;
995    pScrn->CloseScreen = LXCloseScreen;
996    pScrn->SaveScreen = LXSaveScreen;
997
998    if (!xf86CrtcScreenInit(pScrn)) {
999        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "CRTCScreenInit failed.\n");
1000        return FALSE;
1001    }
1002
1003    if (serverGeneration == 1)
1004        xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
1005
1006    pGeode->starting = FALSE;
1007
1008    return TRUE;
1009}
1010
1011static int
1012LXValidMode(VALID_MODE_ARGS_DECL)
1013{
1014    return MODE_OK;
1015}
1016
1017static Bool
1018LXEnterVT(VT_FUNC_ARGS_DECL)
1019{
1020    SCRN_INFO_PTR(arg);
1021    return LXEnterGraphics(NULL, pScrni);
1022}
1023
1024static void
1025LXLeaveVT(VT_FUNC_ARGS_DECL)
1026{
1027    SCRN_INFO_PTR(arg);
1028    GeodeRec *pGeode = GEODEPTR(pScrni);
1029
1030    pGeode->PrevDisplayOffset = vg_get_display_offset();
1031    LXLeaveGraphics(pScrni);
1032}
1033
1034void
1035LXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1036{
1037    pScrn->PreInit = LXPreInit;
1038    pScrn->ScreenInit = LXScreenInit;
1039    pScrn->SwitchMode = LXSwitchMode;
1040    pScrn->AdjustFrame = LXAdjustFrame;
1041    pScrn->EnterVT = LXEnterVT;
1042    pScrn->LeaveVT = LXLeaveVT;
1043    pScrn->FreeScreen = GeodeFreeScreen;
1044    pScrn->ValidMode = LXValidMode;
1045}
1046