132b578d3Smrg/*
232b578d3Smrg * Copyright 2001 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
332b578d3Smrg *
432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its
532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that
632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright
732b578d3Smrg * notice and this permission notice appear in supporting documentation, and
832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or
932b578d3Smrg * publicity pertaining to distribution of the software without specific,
1032b578d3Smrg * written prior permission.  Marc Aurele La France makes no representations
1132b578d3Smrg * about the suitability of this software for any purpose.  It is provided
1232b578d3Smrg * "as-is" without express or implied warranty.
1332b578d3Smrg *
1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE.
2132b578d3Smrg */
2232b578d3Smrg
2332b578d3Smrg#ifdef HAVE_CONFIG_H
2432b578d3Smrg#include "config.h"
2532b578d3Smrg#endif
2632b578d3Smrg
2732b578d3Smrg#include "ati.h"
2832b578d3Smrg#include "aticrtc.h"
2932b578d3Smrg#include "atimach64io.h"
3032b578d3Smrg#include "atirgb514.h"
3132b578d3Smrg
3232b578d3Smrg/*
3332b578d3Smrg * ATIRGB514PreInit --
3432b578d3Smrg *
3532b578d3Smrg * This function fills in the IBM RGB 514 portion of an ATIHWRec that is common
3632b578d3Smrg * to all video modes generated by the server.
3732b578d3Smrg */
3832b578d3Smrgvoid
3932b578d3SmrgATIRGB514PreInit
4032b578d3Smrg(
4132b578d3Smrg    ATIPtr   pATI,
4232b578d3Smrg    ATIHWPtr pATIHW
4332b578d3Smrg)
4432b578d3Smrg{
4532b578d3Smrg    /* Get a work copy of IBM RGB 514 registers */
4632b578d3Smrg    ATIRGB514Save(pATI, pATIHW);
4732b578d3Smrg
4832b578d3Smrg    /* Miscellaneous Clock Control */
4932b578d3Smrg    pATIHW->ibmrgb514[0x0002U] = 0x01U;
5032b578d3Smrg
5132b578d3Smrg    /* Sync Control */
5232b578d3Smrg    pATIHW->ibmrgb514[0x0003U] &= ~0x80U;
5332b578d3Smrg
5432b578d3Smrg    /* Horizontal Sync Control */
5532b578d3Smrg    pATIHW->ibmrgb514[0x0004U] = 0x00U;
5632b578d3Smrg
5732b578d3Smrg    /* Power Management */
5832b578d3Smrg    pATIHW->ibmrgb514[0x0005U] = 0x00U;
5932b578d3Smrg
6032b578d3Smrg    /* DAC Operation */
6132b578d3Smrg    pATIHW->ibmrgb514[0x0006U] &= ~0x04U;
6232b578d3Smrg
6332b578d3Smrg    /* Palette Control */
6432b578d3Smrg    pATIHW->ibmrgb514[0x0007U] = 0x00U;
6532b578d3Smrg
6632b578d3Smrg    /* PLL Control */
6732b578d3Smrg    pATIHW->ibmrgb514[0x0010U] = 0x01U;
6832b578d3Smrg
6932b578d3Smrg    /* Cursor control */
7032b578d3Smrg    pATIHW->ibmrgb514[0x0030U] &= ~0x03U;       /* For now */
7132b578d3Smrg
7232b578d3Smrg    /* Border (i.e. overscan) */
7332b578d3Smrg    pATIHW->ibmrgb514[0x0060U] = 0x00U;
7432b578d3Smrg    pATIHW->ibmrgb514[0x0061U] = 0x00U;
7532b578d3Smrg    pATIHW->ibmrgb514[0x0062U] = 0x00U;
7632b578d3Smrg
7732b578d3Smrg    /* Miscellaneous Control */
7832b578d3Smrg    pATIHW->ibmrgb514[0x0070U] &= ~0x20U;
7932b578d3Smrg    pATIHW->ibmrgb514[0x0071U] = 0x41U; /* See workaround in ATIRGB514Set() */
8032b578d3Smrg
8132b578d3Smrg#ifndef AVOID_CPIO
8232b578d3Smrg
8332b578d3Smrg    if (pATIHW->crtc == ATI_CRTC_VGA)
8432b578d3Smrg    {
8532b578d3Smrg        /* Pixel Format */
8632b578d3Smrg        pATIHW->ibmrgb514[0x000AU] = 0x03U;
8732b578d3Smrg
8832b578d3Smrg        /* Miscellaneous Control */
8932b578d3Smrg        pATIHW->ibmrgb514[0x0070U] |= 0x40U;
9032b578d3Smrg
9132b578d3Smrg        /* VRAM Mask */
9232b578d3Smrg        pATIHW->ibmrgb514[0x0090U] = 0x03U;
9332b578d3Smrg    }
9432b578d3Smrg    else
9532b578d3Smrg
9632b578d3Smrg#endif /* AVOID_CPIO */
9732b578d3Smrg
9832b578d3Smrg    {
9932b578d3Smrg        /* Miscellaneous Control */
10032b578d3Smrg        pATIHW->ibmrgb514[0x0070U] &= ~0x40U;
10132b578d3Smrg
10232b578d3Smrg        /* VRAM Mask */
10332b578d3Smrg        pATIHW->ibmrgb514[0x0090U] = 0x00U;
10432b578d3Smrg        pATIHW->ibmrgb514[0x0091U] = 0x00U;
10532b578d3Smrg
10632b578d3Smrg        /* Pixel Format */
10732b578d3Smrg        switch (pATI->depth)
10832b578d3Smrg        {
10932b578d3Smrg            case 8:
11032b578d3Smrg                pATIHW->ibmrgb514[0x000AU] = 0x03U;
11132b578d3Smrg                pATIHW->ibmrgb514[0x000BU] = 0x00U;
11232b578d3Smrg                break;
11332b578d3Smrg
11432b578d3Smrg            case 15:
11532b578d3Smrg                pATIHW->ibmrgb514[0x000AU] = 0x04U;
11632b578d3Smrg                pATIHW->ibmrgb514[0x000CU] = 0xC4U;
11732b578d3Smrg                break;
11832b578d3Smrg
11932b578d3Smrg            case 16:
12032b578d3Smrg                pATIHW->ibmrgb514[0x000AU] = 0x04U;
12132b578d3Smrg                pATIHW->ibmrgb514[0x000CU] = 0xC6U;
12232b578d3Smrg                break;
12332b578d3Smrg
12432b578d3Smrg            case 24:
12532b578d3Smrg                if (pATI->bitsPerPixel == 24)
12632b578d3Smrg                {
12732b578d3Smrg                    pATIHW->ibmrgb514[0x000AU] = 0x05U;
12832b578d3Smrg                    pATIHW->ibmrgb514[0x000DU] = 0x01U;
12932b578d3Smrg                }
13032b578d3Smrg                else
13132b578d3Smrg                {
13232b578d3Smrg                    pATIHW->ibmrgb514[0x000AU] = 0x06U;
13332b578d3Smrg                    pATIHW->ibmrgb514[0x000EU] = 0x03U;
13432b578d3Smrg                }
13532b578d3Smrg                break;
13632b578d3Smrg
13732b578d3Smrg            default:
13832b578d3Smrg                break;
13932b578d3Smrg        }
14032b578d3Smrg    }
14132b578d3Smrg
14232b578d3Smrg    if (pATI->rgbBits == 8)
14332b578d3Smrg        pATIHW->ibmrgb514[0x0071U] |= 0x04U;
14432b578d3Smrg}
14532b578d3Smrg
14632b578d3Smrg/*
14732b578d3Smrg * ATIRGB514Save --
14832b578d3Smrg *
14932b578d3Smrg * This function saves IBM RGB514 related data into an ATIHWRec.
15032b578d3Smrg */
15132b578d3Smrgvoid
15232b578d3SmrgATIRGB514Save
15332b578d3Smrg(
15432b578d3Smrg    ATIPtr   pATI,
15532b578d3Smrg    ATIHWPtr pATIHW
15632b578d3Smrg)
15732b578d3Smrg{
15832b578d3Smrg    CARD32 crtc_gen_cntl, dac_cntl;
15932b578d3Smrg    CARD8  index_lo, index_hi, index_ctl;
16032b578d3Smrg    int    Index;
16132b578d3Smrg
16232b578d3Smrg    /* Temporarily switch to Mach64 CRTC */
16332b578d3Smrg    crtc_gen_cntl = inr(CRTC_GEN_CNTL);
16432b578d3Smrg    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
16532b578d3Smrg        outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
16632b578d3Smrg
16732b578d3Smrg    /* Temporarily switch to IBM RGB 514 registers */
16832b578d3Smrg    dac_cntl = inr(DAC_CNTL) & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3);
16932b578d3Smrg    outr(DAC_CNTL, dac_cntl | DAC_EXT_SEL_RS2);
17032b578d3Smrg
17132b578d3Smrg    index_lo = in8(M64_DAC_WRITE);
17232b578d3Smrg    index_hi = in8(M64_DAC_DATA);
17332b578d3Smrg    index_ctl = in8(M64_DAC_READ);
17432b578d3Smrg
17532b578d3Smrg    out8(M64_DAC_WRITE, 0x00U);
17632b578d3Smrg    out8(M64_DAC_DATA, 0x00U);
17732b578d3Smrg    out8(M64_DAC_READ, 0x01U);  /* Auto-increment */
17832b578d3Smrg
17932b578d3Smrg    /* Save IBM RGB 514 registers */
18032b578d3Smrg    for (Index = 0;  Index < NumberOf(pATIHW->ibmrgb514);  Index++)
18132b578d3Smrg    {
18232b578d3Smrg        /* Need to rewrite the index every so often... */
18332b578d3Smrg        if ((Index == 0x0100) || (Index == 0x0500))
18432b578d3Smrg        {
18532b578d3Smrg            out8(M64_DAC_WRITE, 0);
18632b578d3Smrg            out8(M64_DAC_DATA, Index >> 8);
18732b578d3Smrg        }
18832b578d3Smrg        pATIHW->ibmrgb514[Index] = in8(M64_DAC_MASK);
18932b578d3Smrg    }
19032b578d3Smrg
19132b578d3Smrg    /* Restore registers */
19232b578d3Smrg    out8(M64_DAC_WRITE, index_lo);
19332b578d3Smrg    out8(M64_DAC_DATA, index_hi);
19432b578d3Smrg    out8(M64_DAC_READ, index_ctl);
19532b578d3Smrg    outr(DAC_CNTL, dac_cntl);
19632b578d3Smrg    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
19732b578d3Smrg        outr(CRTC_GEN_CNTL, crtc_gen_cntl);
19832b578d3Smrg}
19932b578d3Smrg
20032b578d3Smrg/*
20132b578d3Smrg * ATIRGB514Calculate --
20232b578d3Smrg *
20332b578d3Smrg * This function fills in the IBM RGB 514 portion of an ATIHWRec that is
20432b578d3Smrg * specific to a display mode.  pATIHW->ibmrgb514 has already been
20532b578d3Smrg * initialised by a previous call to ATIRGB514PreInit().
20632b578d3Smrg */
20732b578d3Smrgvoid
20832b578d3SmrgATIRGB514Calculate
20932b578d3Smrg(
21032b578d3Smrg    ATIPtr         pATI,
21132b578d3Smrg    ATIHWPtr       pATIHW,
21232b578d3Smrg    DisplayModePtr pMode
21332b578d3Smrg)
21432b578d3Smrg{
21532b578d3Smrg    if (pATI->OptionCSync || (pMode->Flags & (V_CSYNC | V_PCSYNC)))
21632b578d3Smrg        pATIHW->ibmrgb514[0x0006U] |= 0x08U;
21732b578d3Smrg    else
21832b578d3Smrg        pATIHW->ibmrgb514[0x0006U] &= ~0x08U;
21932b578d3Smrg
22032b578d3Smrg    if (pMode->Flags & V_INTERLACE)
22132b578d3Smrg        pATIHW->ibmrgb514[0x0071U] |= 0x20U;
22232b578d3Smrg    else
22332b578d3Smrg        pATIHW->ibmrgb514[0x0071U] &= ~0x20U;
22432b578d3Smrg}
22532b578d3Smrg
22632b578d3Smrg/*
22732b578d3Smrg * ATIRGB514Set --
22832b578d3Smrg *
22932b578d3Smrg * This function is called to set an IBM RGB514's registers.
23032b578d3Smrg */
23132b578d3Smrgvoid
23232b578d3SmrgATIRGB514Set
23332b578d3Smrg(
23432b578d3Smrg    ATIPtr   pATI,
23532b578d3Smrg    ATIHWPtr pATIHW
23632b578d3Smrg)
23732b578d3Smrg{
23832b578d3Smrg    CARD32 crtc_gen_cntl, dac_cntl;
23932b578d3Smrg    CARD8  index_lo, index_hi, index_ctl;
24032b578d3Smrg    int    Index;
24132b578d3Smrg
24232b578d3Smrg    /* Temporarily switch to Mach64 CRTC */
24332b578d3Smrg    crtc_gen_cntl = inr(CRTC_GEN_CNTL);
24432b578d3Smrg    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
24532b578d3Smrg        outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN);
24632b578d3Smrg
24732b578d3Smrg    /* Temporarily switch to IBM RGB 514 registers */
24832b578d3Smrg    dac_cntl = inr(DAC_CNTL) & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3);
24932b578d3Smrg    outr(DAC_CNTL, dac_cntl | DAC_EXT_SEL_RS2);
25032b578d3Smrg
25132b578d3Smrg    index_lo = in8(M64_DAC_WRITE);
25232b578d3Smrg    index_hi = in8(M64_DAC_DATA);
25332b578d3Smrg    index_ctl = in8(M64_DAC_READ);
25432b578d3Smrg
25532b578d3Smrg    out8(M64_DAC_WRITE, 0x00U);
25632b578d3Smrg    out8(M64_DAC_DATA, 0x00U);
25732b578d3Smrg    out8(M64_DAC_READ, 0x01U);  /* Auto-increment */
25832b578d3Smrg
25932b578d3Smrg    /* Load IBM RGB 514 registers */
26032b578d3Smrg    for (Index = 0;  Index < NumberOf(pATIHW->ibmrgb514);  Index++)
26132b578d3Smrg         out8(M64_DAC_MASK, pATIHW->ibmrgb514[Index]);
26232b578d3Smrg
26332b578d3Smrg#ifndef AVOID_CPIO
26432b578d3Smrg
26532b578d3Smrg    /* Deal with documented anomaly */
26632b578d3Smrg    if (pATIHW->crtc == ATI_CRTC_VGA)
26732b578d3Smrg    {
26832b578d3Smrg        /* Reset Miscellaneous Control 2 */
26932b578d3Smrg        out8(M64_DAC_WRITE, 0x71U);
27032b578d3Smrg        out8(M64_DAC_DATA, 0x00U);
27132b578d3Smrg        out8(M64_DAC_MASK, pATIHW->ibmrgb514[0x0071U] & ~0x41U);
27232b578d3Smrg    }
27332b578d3Smrg
27432b578d3Smrg#endif /* AVOID_CPIO */
27532b578d3Smrg
27632b578d3Smrg    /* Restore registers */
27732b578d3Smrg    out8(M64_DAC_WRITE, index_lo);
27832b578d3Smrg    out8(M64_DAC_DATA, index_hi);
27932b578d3Smrg    out8(M64_DAC_READ, index_ctl);
28032b578d3Smrg    outr(DAC_CNTL, dac_cntl);
28132b578d3Smrg    if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
28232b578d3Smrg        outr(CRTC_GEN_CNTL, crtc_gen_cntl);
28332b578d3Smrg}
284