/*
 * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting documentation, and
 * that the name of Marc Aurele La France not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  Marc Aurele La France makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as-is" without express or implied warranty.
 *
 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */
#include "config.h"

#include "ati.h"
#include "atichip.h"
#include "atistruct.h"
#include "ativga.h"
#include "ativgaio.h"

#ifndef AVOID_CPIO

/*
 * ATIVGAPreInit --
 *
 * This function is called to set up VGA-related data that is common to all
 * video modes generated by the driver.
 */
void
ATIVGAPreInit
(
    ATIPtr      pATI,
    ATIHWPtr    pATIHW
)
{
    /* Initialise sequencer register values */
    pATIHW->seq[0] = 0x03U;
    pATIHW->seq[2] = 0x0FU;
    pATIHW->seq[4] = 0x0AU;

    /* Initialise CRTC register values */
    if (((pATI->Chip >= ATI_CHIP_264CT)))
        pATIHW->crt[19] = pATI->displayWidth >> 3;
    else
        pATIHW->crt[19] = pATI->displayWidth >> 4;

    pATIHW->crt[23] = 0xE3U;
    pATIHW->crt[24] = 0xFFU;

    /* Initialise attribute controller register values */
    {
        for (int Index = 0;  Index < 16;  Index++)
            pATIHW->attr[Index] = Index;

        pATIHW->attr[16] = 0x01U;
        pATIHW->attr[17] = 0xFFU;
    }
    pATIHW->attr[18] = 0x0FU;

    /* Initialise graphics controller register values */
    if (pATI->Chip >= ATI_CHIP_264CT)
        pATIHW->gra[5] = 0x40U;
    if (pATI->Chip >= ATI_CHIP_264VT)
        pATIHW->gra[6] = 0x01U;         /* 128kB aperture */
    else
        pATIHW->gra[6] = 0x05U;         /* 64kB aperture */
    pATIHW->gra[7] = 0x0FU;
    pATIHW->gra[8] = 0xFFU;
}

/*
 * ATIVGASave --
 *
 * This function is called to save the VGA portion of the current video state.
 */
void
ATIVGASave
(
    ATIPtr      pATI,
    ATIHWPtr    pATIHW
)
{
    int Index;

    /* Save miscellaneous output register */
    pATIHW->genmo = inb(R_GENMO);
    ATISetVGAIOBase(pATI, pATIHW->genmo);

    /* Save sequencer registers */
    for (Index = 0;  Index < NumberOf(pATIHW->seq);  Index++)
        pATIHW->seq[Index] = GetReg(SEQX, Index);

    /* Save CRTC registers */
    for (Index = 0;  Index < NumberOf(pATIHW->crt);  Index++)
        pATIHW->crt[Index] = GetReg(CRTX(pATI->CPIO_VGABase), Index);

    /* Save attribute controller registers */
    for (Index = 0;  Index < NumberOf(pATIHW->attr);  Index++)
    {
        (void)inb(GENS1(pATI->CPIO_VGABase));   /* Reset flip-flop */
        pATIHW->attr[Index] = GetReg(ATTRX, Index);
    }

    /* Save graphics controller registers */
    for (Index = 0;  Index < NumberOf(pATIHW->gra);  Index++)
        pATIHW->gra[Index] = GetReg(GRAX, Index);
}

/*
 * ATIVGASet --
 *
 * This function is called to load the VGA portion of a video state.
 */
void
ATIVGASet
(
    ATIPtr      pATI,
    ATIHWPtr    pATIHW
)
{
    int Index;

    /* Set VGA I/O base */
    ATISetVGAIOBase(pATI, pATIHW->genmo);

    /* Load miscellaneous output register */
    outb(GENMO, pATIHW->genmo);

    /* Load sequencer in reverse index order;  this also ends its reset */
    for (Index = NumberOf(pATIHW->seq);  --Index >= 0;  )
        PutReg(SEQX, Index, pATIHW->seq[Index]);

    /* Load CRTC registers */
    for (Index = 0;  Index < NumberOf(pATIHW->crt);  Index++)
        PutReg(CRTX(pATI->CPIO_VGABase), Index, pATIHW->crt[Index]);

    /* Load attribute controller registers */
    for (Index = 0;  Index < NumberOf(pATIHW->attr);  Index++)
    {
        (void)inb(GENS1(pATI->CPIO_VGABase));   /* Reset flip-flop & delay */
        outb(ATTRX, Index);
        outb(ATTRX, pATIHW->attr[Index]);
    }

    /* Load graphics controller registers */
    for (Index = 0;  Index < NumberOf(pATIHW->gra);  Index++)
        PutReg(GRAX, Index, pATIHW->gra[Index]);
}

/*
 * ATIVGASaveScreen --
 *
 * This function blanks or unblanks a VGA screen.
 */
void
ATIVGASaveScreen
(
    ATIPtr pATI,
    int    Mode
)
{
    (void)inb(GENS1(pATI->CPIO_VGABase));       /* Reset flip-flop */

    switch (Mode)
    {
        case SCREEN_SAVER_OFF:
        case SCREEN_SAVER_FORCER:
            outb(ATTRX, 0x20U);                /* Turn PAS on */
            break;

        case SCREEN_SAVER_ON:
        case SCREEN_SAVER_CYCLE:
            outb(ATTRX, 0x00U);                /* Turn PAS off */
            break;

        default:
            break;
    }
}

#endif /* AVOID_CPIO */
