132b578d3Smrg/*
232b578d3Smrg * Copyright 2003 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 <string.h>
2832b578d3Smrg
2932b578d3Smrg#include "ati.h"
3032b578d3Smrg#include "atichip.h"
3132b578d3Smrg#include "atimach64accel.h"
3232b578d3Smrg#include "atimach64io.h"
3332b578d3Smrg#include "atixv.h"
34d31dbc53Smrg#include "atimach64version.h"
3532b578d3Smrg
3632b578d3Smrg#include <X11/extensions/Xv.h>
3732b578d3Smrg#include "fourcc.h"
3832b578d3Smrg#include "xf86xv.h"
3932b578d3Smrg
4032b578d3Smrg#define MAKE_ATOM(string) MakeAtom(string, strlen(string), TRUE)
4132b578d3Smrg#define MaxScale          (CARD32)(CARD16)(-1)
4232b578d3Smrg
4332b578d3Smrgstatic unsigned long ATIMach64XVAtomGeneration = (unsigned long)(-1);
4432b578d3Smrg
4532b578d3Smrgstatic XF86VideoEncodingRec ATIMach64VideoEncoding[] =
4632b578d3Smrg{
4732b578d3Smrg    { 0, "XV_IMAGE", 720, 2048, {1, 1} }
4832b578d3Smrg};
4932b578d3Smrg#define nATIMach64VideoEncoding NumberOf(ATIMach64VideoEncoding)
5032b578d3Smrg
5132b578d3Smrgstatic XF86VideoFormatRec ATIMach64VideoFormat[] =
5232b578d3Smrg{
5332b578d3Smrg    { 8, TrueColor},
5432b578d3Smrg    { 8, DirectColor},
5532b578d3Smrg    { 8, PseudoColor},
5632b578d3Smrg    { 8, GrayScale},
5732b578d3Smrg    { 8, StaticGray},
5832b578d3Smrg    { 8, StaticColor},
5932b578d3Smrg    {15, TrueColor},
6032b578d3Smrg    {16, TrueColor},
6132b578d3Smrg    {24, TrueColor},
6232b578d3Smrg    {15, DirectColor},
6332b578d3Smrg    {16, DirectColor},
6432b578d3Smrg    {24, DirectColor}
6532b578d3Smrg};
6632b578d3Smrg#define nATIMach64VideoFormat NumberOf(ATIMach64VideoFormat)
6732b578d3Smrg
6832b578d3Smrgstatic XF86AttributeRec ATIMach64Attribute[] =
6932b578d3Smrg{
7032b578d3Smrg    /* These are only supported on the Rage Pro and later ... */
7132b578d3Smrg    {
7232b578d3Smrg        XvSettable | XvGettable,
7332b578d3Smrg        -1000, 1000,
7432b578d3Smrg        "XV_SATURATION"
7532b578d3Smrg    },
7632b578d3Smrg    {
7732b578d3Smrg        XvSettable | XvGettable,
7832b578d3Smrg        -1000, 1000,
7932b578d3Smrg        "XV_BRIGHTNESS"
8032b578d3Smrg    },
8132b578d3Smrg    {
8232b578d3Smrg        XvSettable | XvGettable,
8332b578d3Smrg        -1000, 1000,
8432b578d3Smrg        "XV_COLOUR"
8532b578d3Smrg    },
8632b578d3Smrg    {
8732b578d3Smrg        XvSettable | XvGettable,
8832b578d3Smrg        -1000, 1000,
8932b578d3Smrg        "XV_COLOR"
9032b578d3Smrg    },
9132b578d3Smrg
9232b578d3Smrg    /* Local attributes, odds and ends for compatibility, etc... */
9332b578d3Smrg    {
9432b578d3Smrg        XvSettable | XvGettable,
9532b578d3Smrg        0, 1,
9632b578d3Smrg        "XV_AUTOPAINT_COLOURKEY"
9732b578d3Smrg    },
9832b578d3Smrg    {
9932b578d3Smrg        XvSettable | XvGettable,
10032b578d3Smrg        0, 1,
10132b578d3Smrg        "XV_AUTOPAINT_COLORKEY"
10232b578d3Smrg    },
10332b578d3Smrg    {
10432b578d3Smrg        XvSettable | XvGettable,
10532b578d3Smrg        0, (1 << 24) - 1,
10632b578d3Smrg        "XV_COLOURKEY"
10732b578d3Smrg    },
10832b578d3Smrg    {
10932b578d3Smrg        XvSettable | XvGettable,
11032b578d3Smrg        0, (1 << 24) - 1,
11132b578d3Smrg        "XV_COLORKEY"
11232b578d3Smrg    },
11332b578d3Smrg    {
11432b578d3Smrg        XvSettable | XvGettable,
11532b578d3Smrg        0, (1 << 24) - 1,
11632b578d3Smrg        "XV_COLOURKEY_MASK"
11732b578d3Smrg    },
11832b578d3Smrg    {
11932b578d3Smrg        XvSettable | XvGettable,
12032b578d3Smrg        0, (1 << 24) - 1,
12132b578d3Smrg        "XV_COLORKEY_MASK"
12232b578d3Smrg    },
12332b578d3Smrg    {
12432b578d3Smrg        XvSettable,
12532b578d3Smrg        0, 0,
12632b578d3Smrg        "XV_SET_DEFAULTS"
12732b578d3Smrg    },
12832b578d3Smrg    {   /* Keep last */
12932b578d3Smrg        XvSettable | XvGettable,
13032b578d3Smrg        0, 1,
13132b578d3Smrg        "XV_DOUBLE_BUFFER"
13232b578d3Smrg    }
13332b578d3Smrg};
13432b578d3Smrg#define nATIMach64Attribute NumberOf(ATIMach64Attribute)
13532b578d3Smrg
13632b578d3Smrgstatic XF86ImageRec ATIMach64Image[] =
13732b578d3Smrg{
13832b578d3Smrg    XVIMAGE_YUY2,
13932b578d3Smrg    XVIMAGE_UYVY,
14032b578d3Smrg    XVIMAGE_YV12,
14132b578d3Smrg    XVIMAGE_I420
14232b578d3Smrg};
14332b578d3Smrg#define nATIMach64Image NumberOf(ATIMach64Image)
14432b578d3Smrg
14532b578d3Smrg/* A local XVideo adaptor attribute record */
14632b578d3Smrgtypedef struct _ATIMach64Attribute
14732b578d3Smrg{
14832b578d3Smrg    Atom  AttributeID;
14932b578d3Smrg    INT32 MaxValue;             /* ... for the hardware */
15032b578d3Smrg    void  (*SetAttribute) (ATIPtr, INT32);
15132b578d3Smrg    INT32 (*GetAttribute) (ATIPtr);
15232b578d3Smrg} ATIMach64AttributeRec, *ATIMach64AttributePtr;
15332b578d3Smrg
15432b578d3Smrg/* Functions to get/set XVideo adaptor attributes */
15532b578d3Smrg
15632b578d3Smrgstatic void
15732b578d3SmrgATIMach64SetSaturationAttribute
15832b578d3Smrg(
15932b578d3Smrg    ATIPtr pATI,
16032b578d3Smrg    INT32  Value
16132b578d3Smrg)
16232b578d3Smrg{
16332b578d3Smrg    /* Set the register */
16432b578d3Smrg    pATI->NewHW.scaler_colour_cntl &=
16532b578d3Smrg        ~(SCALE_SATURATION_U | SCALE_SATURATION_V);
16632b578d3Smrg    pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_SATURATION_U) |
16732b578d3Smrg        SetBits(Value, SCALE_SATURATION_V);
16832b578d3Smrg    outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl);
16932b578d3Smrg}
17032b578d3Smrg
17132b578d3Smrgstatic INT32
17232b578d3SmrgATIMach64GetSaturationAttribute
17332b578d3Smrg(
17432b578d3Smrg    ATIPtr pATI
17532b578d3Smrg)
17632b578d3Smrg{
17732b578d3Smrg    return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_SATURATION_U);
17832b578d3Smrg}
17932b578d3Smrg
18032b578d3Smrgstatic void
18132b578d3SmrgATIMach64SetBrightnessAttribute
18232b578d3Smrg(
18332b578d3Smrg    ATIPtr pATI,
18432b578d3Smrg    INT32  Value
18532b578d3Smrg)
18632b578d3Smrg{
18732b578d3Smrg    /* Set the register */
18832b578d3Smrg    pATI->NewHW.scaler_colour_cntl &= ~SCALE_BRIGHTNESS;
18932b578d3Smrg    pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_BRIGHTNESS);
19032b578d3Smrg    outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl);
19132b578d3Smrg}
19232b578d3Smrg
19332b578d3Smrgstatic INT32
19432b578d3SmrgATIMach64GetBrightnessAttribute
19532b578d3Smrg(
19632b578d3Smrg    ATIPtr pATI
19732b578d3Smrg)
19832b578d3Smrg{
19932b578d3Smrg    return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_BRIGHTNESS);
20032b578d3Smrg}
20132b578d3Smrg
20232b578d3Smrgstatic void
20332b578d3SmrgATIMach64SetDoubleBufferAttribute
20432b578d3Smrg(
20532b578d3Smrg    ATIPtr pATI,
20632b578d3Smrg    INT32  Value
20732b578d3Smrg)
20832b578d3Smrg{
20932b578d3Smrg    pATI->DoubleBuffer = Value;
21032b578d3Smrg}
21132b578d3Smrg
21232b578d3Smrgstatic INT32
21332b578d3SmrgATIMach64GetDoubleBufferAttribute
21432b578d3Smrg(
21532b578d3Smrg    ATIPtr pATI
21632b578d3Smrg)
21732b578d3Smrg{
21832b578d3Smrg    return (int)pATI->DoubleBuffer;
21932b578d3Smrg}
22032b578d3Smrg
22132b578d3Smrgstatic void
22232b578d3SmrgATIMach64SetAutoPaintAttribute
22332b578d3Smrg(
22432b578d3Smrg    ATIPtr pATI,
22532b578d3Smrg    INT32  Value
22632b578d3Smrg)
22732b578d3Smrg{
22832b578d3Smrg    pATI->AutoPaint = Value;
22932b578d3Smrg}
23032b578d3Smrg
23132b578d3Smrgstatic INT32
23232b578d3SmrgATIMach64GetAutoPaintAttribute
23332b578d3Smrg(
23432b578d3Smrg    ATIPtr pATI
23532b578d3Smrg)
23632b578d3Smrg{
23732b578d3Smrg    return (int)pATI->AutoPaint;
23832b578d3Smrg}
23932b578d3Smrg
24032b578d3Smrgstatic void
24132b578d3SmrgATIMach64SetColourKeyAttribute
24232b578d3Smrg(
24332b578d3Smrg    ATIPtr pATI,
24432b578d3Smrg    INT32  Value
24532b578d3Smrg)
24632b578d3Smrg{
24732b578d3Smrg    pATI->NewHW.overlay_graphics_key_clr =
24832b578d3Smrg        (CARD32)(Value & ((1 << pATI->depth) - 1));
24932b578d3Smrg    outf(OVERLAY_GRAPHICS_KEY_CLR, pATI->NewHW.overlay_graphics_key_clr);
25032b578d3Smrg}
25132b578d3Smrg
25232b578d3Smrgstatic INT32
25332b578d3SmrgATIMach64GetColourKeyAttribute
25432b578d3Smrg(
25532b578d3Smrg    ATIPtr pATI
25632b578d3Smrg)
25732b578d3Smrg{
25832b578d3Smrg    return (INT32)pATI->NewHW.overlay_graphics_key_clr;
25932b578d3Smrg}
26032b578d3Smrg
26132b578d3Smrgstatic void
26232b578d3SmrgATIMach64SetColourKeyMaskAttribute
26332b578d3Smrg(
26432b578d3Smrg    ATIPtr pATI,
26532b578d3Smrg    INT32  Value
26632b578d3Smrg)
26732b578d3Smrg{
26832b578d3Smrg    pATI->NewHW.overlay_graphics_key_msk =
26932b578d3Smrg        (CARD32)(Value & ((1 << pATI->depth) - 1));
27032b578d3Smrg    outf(OVERLAY_GRAPHICS_KEY_MSK, pATI->NewHW.overlay_graphics_key_msk);
27132b578d3Smrg}
27232b578d3Smrg
27332b578d3Smrgstatic INT32
27432b578d3SmrgATIMach64GetColourKeyMaskAttribute
27532b578d3Smrg(
27632b578d3Smrg    ATIPtr pATI
27732b578d3Smrg)
27832b578d3Smrg{
27932b578d3Smrg    return (INT32)pATI->NewHW.overlay_graphics_key_msk;
28032b578d3Smrg}
28132b578d3Smrg
28232b578d3Smrg/*
28332b578d3Smrg * ATIMach64SetDefaultAttributes --
28432b578d3Smrg *
28532b578d3Smrg * This function calls other functions to set default values for the various
28632b578d3Smrg * attributes of an XVideo port.
28732b578d3Smrg */
28832b578d3Smrgstatic void
28932b578d3SmrgATIMach64SetDefaultAttributes
29032b578d3Smrg(
29132b578d3Smrg    ATIPtr pATI,
29232b578d3Smrg    INT32  Value
29332b578d3Smrg)
29432b578d3Smrg{
29532b578d3Smrg    ATIMach64SetAutoPaintAttribute(pATI, TRUE);
29632b578d3Smrg    ATIMach64SetDoubleBufferAttribute(pATI, FALSE);
29732b578d3Smrg    ATIMach64SetColourKeyMaskAttribute(pATI, (1 << pATI->depth) - 1);
29832b578d3Smrg    ATIMach64SetColourKeyAttribute(pATI, (3 << ((2 * pATI->depth) / 3)) |
29932b578d3Smrg                                         (2 << ((1 * pATI->depth) / 3)) |
30032b578d3Smrg                                         (1 << ((0 * pATI->depth) / 3)));
30132b578d3Smrg
30232b578d3Smrg    if (pATI->Chip < ATI_CHIP_264GTPRO)
30332b578d3Smrg        return;
30432b578d3Smrg
30532b578d3Smrg    ATIMach64SetBrightnessAttribute(pATI, 32);
30632b578d3Smrg    ATIMach64SetSaturationAttribute(pATI, 16);
30732b578d3Smrg}
30832b578d3Smrg
30932b578d3Smrg/*
3100b0ce0bfSmrg * There is a one-to-one correspondence between elements of the following array
31132b578d3Smrg * and those of ATIMach64Attribute.
31232b578d3Smrg */
31332b578d3Smrgstatic ATIMach64AttributeRec ATIMach64AttributeInfo[nATIMach64Attribute] =
31432b578d3Smrg{
31532b578d3Smrg    {   /* SATURATION */
31632b578d3Smrg        0, 23,
31732b578d3Smrg        ATIMach64SetSaturationAttribute,
31832b578d3Smrg        ATIMach64GetSaturationAttribute
31932b578d3Smrg    },
32032b578d3Smrg    {   /* BRIGHTNESS */
32132b578d3Smrg        0, 63,
32232b578d3Smrg        ATIMach64SetBrightnessAttribute,
32332b578d3Smrg        ATIMach64GetBrightnessAttribute
32432b578d3Smrg    },
32532b578d3Smrg    {   /* COLOUR */
32632b578d3Smrg        0, 23,
32732b578d3Smrg        ATIMach64SetSaturationAttribute,
32832b578d3Smrg        ATIMach64GetSaturationAttribute
32932b578d3Smrg    },
33032b578d3Smrg    {   /* COLOR */
33132b578d3Smrg        0, 23,
33232b578d3Smrg        ATIMach64SetSaturationAttribute,
33332b578d3Smrg        ATIMach64GetSaturationAttribute
33432b578d3Smrg    },
33532b578d3Smrg    {   /* AUTOPAINT_COLOURKEY */
33632b578d3Smrg        0, 1,
33732b578d3Smrg        ATIMach64SetAutoPaintAttribute,
33832b578d3Smrg        ATIMach64GetAutoPaintAttribute
33932b578d3Smrg    },
34032b578d3Smrg    {   /* AUTOPAINT_COLORKEY */
34132b578d3Smrg        0, 1,
34232b578d3Smrg        ATIMach64SetAutoPaintAttribute,
34332b578d3Smrg        ATIMach64GetAutoPaintAttribute
34432b578d3Smrg    },
34532b578d3Smrg    {   /* COLOURKEY */
34632b578d3Smrg        0, (1 << 24) - 1,
34732b578d3Smrg        ATIMach64SetColourKeyAttribute,
34832b578d3Smrg        ATIMach64GetColourKeyAttribute
34932b578d3Smrg    },
35032b578d3Smrg    {   /* COLORKEY */
35132b578d3Smrg        0, (1 << 24) - 1,
35232b578d3Smrg        ATIMach64SetColourKeyAttribute,
35332b578d3Smrg        ATIMach64GetColourKeyAttribute
35432b578d3Smrg    },
35532b578d3Smrg    {   /* COLOURKEY_MASK */
35632b578d3Smrg        0, (1 << 24) - 1,
35732b578d3Smrg        ATIMach64SetColourKeyMaskAttribute,
35832b578d3Smrg        ATIMach64GetColourKeyMaskAttribute
35932b578d3Smrg    },
36032b578d3Smrg    {   /* COLORKEY_MASK */
36132b578d3Smrg        0, (1 << 24) - 1,
36232b578d3Smrg        ATIMach64SetColourKeyMaskAttribute,
36332b578d3Smrg        ATIMach64GetColourKeyMaskAttribute
36432b578d3Smrg    },
36532b578d3Smrg    {   /* SET_DEFAULTS */
36632b578d3Smrg        0, 0,
36732b578d3Smrg        ATIMach64SetDefaultAttributes,
36832b578d3Smrg        NULL
36932b578d3Smrg    },
37032b578d3Smrg    {   /* DOUBLE_BUFFER */
37132b578d3Smrg        0, 1,
37232b578d3Smrg        ATIMach64SetDoubleBufferAttribute,
37332b578d3Smrg        ATIMach64GetDoubleBufferAttribute
37432b578d3Smrg    }
37532b578d3Smrg};
37632b578d3Smrg
37732b578d3Smrg/*
37832b578d3Smrg * ATIMach64FindAttribute --
37932b578d3Smrg *
38032b578d3Smrg * This function is called to locate an Xv attribute's table entry.
38132b578d3Smrg */
38232b578d3Smrgstatic int
38332b578d3SmrgATIMach64FindPortAttribute
38432b578d3Smrg(
38532b578d3Smrg    ATIPtr pATI,
38632b578d3Smrg    Atom   AttributeID
38732b578d3Smrg)
38832b578d3Smrg{
38932b578d3Smrg    int iAttribute;
39032b578d3Smrg
39132b578d3Smrg    if (pATI->Chip < ATI_CHIP_264GTPRO)
39232b578d3Smrg        iAttribute = 4;
39332b578d3Smrg    else
39432b578d3Smrg        iAttribute = 0;
39532b578d3Smrg
39632b578d3Smrg    for (;  iAttribute < nATIMach64Attribute;  iAttribute++)
39732b578d3Smrg        if (AttributeID == ATIMach64AttributeInfo[iAttribute].AttributeID)
39832b578d3Smrg            return iAttribute;
39932b578d3Smrg
40032b578d3Smrg    return -1;
40132b578d3Smrg}
40232b578d3Smrg
40332b578d3Smrg/*
40432b578d3Smrg * ATIMach64SetPortAttribute --
40532b578d3Smrg *
40632b578d3Smrg * This function sets the value of a particular port's attribute.
40732b578d3Smrg */
40832b578d3Smrgstatic int
40932b578d3SmrgATIMach64SetPortAttribute
41032b578d3Smrg(
41132b578d3Smrg    ScrnInfoPtr pScreenInfo,
41232b578d3Smrg    Atom        AttributeID,
41332b578d3Smrg    INT32       Value,
41432b578d3Smrg    pointer     pATI
41532b578d3Smrg)
41632b578d3Smrg{
41732b578d3Smrg    INT32 Range;
41832b578d3Smrg    int   iAttribute;
41932b578d3Smrg
42032b578d3Smrg    if (((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) ||
42132b578d3Smrg        !ATIMach64AttributeInfo[iAttribute].SetAttribute)
42232b578d3Smrg        return BadMatch;
42332b578d3Smrg
42432b578d3Smrg    Range = ATIMach64Attribute[iAttribute].max_value -
42532b578d3Smrg        ATIMach64Attribute[iAttribute].min_value;
42632b578d3Smrg
42732b578d3Smrg    if (Range >= 0)
42832b578d3Smrg    {
42932b578d3Smrg        /* Limit and scale the value */
43032b578d3Smrg        Value -= ATIMach64Attribute[iAttribute].min_value;
43132b578d3Smrg
43232b578d3Smrg        if (Value < 0)
43332b578d3Smrg            Value = 0;
43432b578d3Smrg        else if (Value > Range)
43532b578d3Smrg            Value = Range;
43632b578d3Smrg
43732b578d3Smrg        if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue)
43832b578d3Smrg        {
43932b578d3Smrg            if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0)
44032b578d3Smrg                Value *= ATIMach64AttributeInfo[iAttribute].MaxValue;
44132b578d3Smrg            if (Range > 0)
44232b578d3Smrg                Value /= Range;
44332b578d3Smrg        }
44432b578d3Smrg    }
44532b578d3Smrg
44632b578d3Smrg    (*ATIMach64AttributeInfo[iAttribute].SetAttribute)(pATI, Value);
44732b578d3Smrg
44832b578d3Smrg    return Success;
44932b578d3Smrg}
45032b578d3Smrg
45132b578d3Smrg/*
45232b578d3Smrg * ATIMach64SetPortAttribute --
45332b578d3Smrg *
45432b578d3Smrg * This function retrieves the value of a particular port's attribute.
45532b578d3Smrg */
45632b578d3Smrgstatic int
45732b578d3SmrgATIMach64GetPortAttribute
45832b578d3Smrg(
45932b578d3Smrg    ScrnInfoPtr pScreenInfo,
46032b578d3Smrg    Atom        AttributeID,
46132b578d3Smrg    INT32       *Value,
46232b578d3Smrg    pointer     pATI
46332b578d3Smrg)
46432b578d3Smrg{
46532b578d3Smrg    INT32 Range;
46632b578d3Smrg    int   iAttribute;
46732b578d3Smrg
46832b578d3Smrg    if (!Value ||
46932b578d3Smrg        ((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) ||
47032b578d3Smrg        !ATIMach64AttributeInfo[iAttribute].GetAttribute)
47132b578d3Smrg        return BadMatch;
47232b578d3Smrg
47332b578d3Smrg    *Value = (*ATIMach64AttributeInfo[iAttribute].GetAttribute)(pATI);
47432b578d3Smrg
47532b578d3Smrg    Range = ATIMach64Attribute[iAttribute].max_value -
47632b578d3Smrg        ATIMach64Attribute[iAttribute].min_value;
47732b578d3Smrg
47832b578d3Smrg    if (Range >= 0)
47932b578d3Smrg    {
48032b578d3Smrg        if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue)
48132b578d3Smrg        {
48232b578d3Smrg            /* (Un-)scale the value */
48332b578d3Smrg            if (Range > 0)
48432b578d3Smrg                *Value *= Range;
48532b578d3Smrg            if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0)
48632b578d3Smrg                *Value /= ATIMach64AttributeInfo[iAttribute].MaxValue;
48732b578d3Smrg        }
48832b578d3Smrg
48932b578d3Smrg        *Value += ATIMach64Attribute[iAttribute].min_value;
49032b578d3Smrg    }
49132b578d3Smrg
49232b578d3Smrg    return Success;
49332b578d3Smrg}
49432b578d3Smrg
49532b578d3Smrgstatic pointer
49632b578d3SmrgATIMach64XVMemAlloc
49732b578d3Smrg(
49832b578d3Smrg    ScreenPtr pScreen,
49932b578d3Smrg    pointer   pVideo,
50032b578d3Smrg    int       size,
50132b578d3Smrg    int       *offset,
50232b578d3Smrg    ATIPtr    pATI
50332b578d3Smrg);
50432b578d3Smrg
50532b578d3Smrgstatic void
50632b578d3SmrgATIMach64XVMemFree
50732b578d3Smrg(
50832b578d3Smrg    ScreenPtr pScreen,
50932b578d3Smrg    pointer   pVideo,
51032b578d3Smrg    ATIPtr    pATI
51132b578d3Smrg);
51232b578d3Smrg
51332b578d3Smrg#ifdef USE_XAA
51432b578d3Smrg/*
51532b578d3Smrg * ATIMach64RemoveLinearCallback --
51632b578d3Smrg *
51732b578d3Smrg * This is called by the framebuffer manager to release the offscreen XVideo
51832b578d3Smrg * buffer after the video has been temporarily disabled due to its window being
51932b578d3Smrg * iconified or completely occluded.
52032b578d3Smrg */
52132b578d3Smrgstatic void
52232b578d3SmrgATIMach64RemoveLinearCallback
52332b578d3Smrg(
52432b578d3Smrg    FBLinearPtr pLinear
52532b578d3Smrg)
52632b578d3Smrg{
527e35d4d8eSmrg    ATIPtr pATI = ATIPTR(xf86ScreenToScrn(pLinear->pScreen));
52832b578d3Smrg
52932b578d3Smrg    pATI->pXVBuffer = NULL;
53032b578d3Smrg    outf(OVERLAY_SCALE_CNTL, SCALE_EN);
53132b578d3Smrg}
53232b578d3Smrg#endif /* USE_XAA */
53332b578d3Smrg
53432b578d3Smrg/*
53532b578d3Smrg * ATIMach64StopVideo --
53632b578d3Smrg *
53732b578d3Smrg * This is called to stop displaying a video.  Note that, to prevent jittering
53832b578d3Smrg * this doesn't actually turn off the overlay unless 'Cleanup' is TRUE, i.e.
53932b578d3Smrg * when the video is to be actually stopped rather than temporarily disabled.
54032b578d3Smrg */
54132b578d3Smrgstatic void
54232b578d3SmrgATIMach64StopVideo
54332b578d3Smrg(
54432b578d3Smrg    ScrnInfoPtr pScreenInfo,
54532b578d3Smrg    pointer     Data,
54632b578d3Smrg    Bool        Cleanup
54732b578d3Smrg)
54832b578d3Smrg{
54932b578d3Smrg    ScreenPtr pScreen = pScreenInfo->pScreen;
55032b578d3Smrg    ATIPtr    pATI    = Data;
55132b578d3Smrg
55232b578d3Smrg    if (pATI->ActiveSurface)
55332b578d3Smrg        return;
55432b578d3Smrg
55532b578d3Smrg    REGION_EMPTY(pScreen, &pATI->VideoClip);
55632b578d3Smrg
55732b578d3Smrg#ifdef USE_XAA
55832b578d3Smrg    if (!pATI->useEXA && !Cleanup)
55932b578d3Smrg    {
56032b578d3Smrg        /*
56132b578d3Smrg         * Free offscreen buffer if/when its allocation is needed by XAA's
56232b578d3Smrg         * pixmap cache.
56332b578d3Smrg         */
56432b578d3Smrg        FBLinearPtr linear = (FBLinearPtr)pATI->pXVBuffer;
56532b578d3Smrg        if (linear)
56632b578d3Smrg            linear->RemoveLinearCallback =
56732b578d3Smrg                ATIMach64RemoveLinearCallback;
56832b578d3Smrg        return;
56932b578d3Smrg    }
57032b578d3Smrg#endif /* USE_XAA */
57132b578d3Smrg
57232b578d3Smrg    ATIMach64XVMemFree(pScreen, pATI->pXVBuffer, pATI);
57332b578d3Smrg    pATI->pXVBuffer = NULL;
57432b578d3Smrg    outf(OVERLAY_SCALE_CNTL, SCALE_EN);
57532b578d3Smrg}
57632b578d3Smrg
57732b578d3Smrg/*
57832b578d3Smrg * ATIMach64QueryBestSize --
57932b578d3Smrg *
58032b578d3Smrg * Quoting XVideo docs:
58132b578d3Smrg *
58232b578d3Smrg * This function provides the client with a way to query what the destination
58332b578d3Smrg * dimensions would end up being if they were to request that an area
58432b578d3Smrg * VideoWidth by VideoHeight from the video stream be scaled to rectangle of
58532b578d3Smrg * DrawableWidth by DrawableHeight on the screen.  Since it is not expected
58632b578d3Smrg * that all hardware will be able to get the target dimensions exactly, it is
58732b578d3Smrg * important that the driver provide this function.
58832b578d3Smrg */
58932b578d3Smrgstatic void
59032b578d3SmrgATIMach64QueryBestSize
59132b578d3Smrg(
59232b578d3Smrg    ScrnInfoPtr  pScreenInfo,
59332b578d3Smrg    Bool         Motion,
59432b578d3Smrg    short        VideoWidth,
59532b578d3Smrg    short        VideoHeight,
59632b578d3Smrg    short        DrawableWidth,
59732b578d3Smrg    short        DrawableHeight,
59832b578d3Smrg    unsigned int *Width,
59932b578d3Smrg    unsigned int *Height,
60032b578d3Smrg    pointer      pATI
60132b578d3Smrg)
60232b578d3Smrg{
60332b578d3Smrg    *Width  = DrawableWidth;
60432b578d3Smrg    *Height = DrawableHeight;
60532b578d3Smrg}
60632b578d3Smrg
60732b578d3Smrg/*
60832b578d3Smrg * ATIMach64QueryImageAttributes --
60932b578d3Smrg *
61032b578d3Smrg * Quoting XVideo docs:
61132b578d3Smrg *
61232b578d3Smrg * This function is called to let the driver specify how data for a particular
61332b578d3Smrg * image of size Width by Height should be stored.  Sometimes only the size and
61432b578d3Smrg * corrected width and height are needed.  In that case pitches and offsets are
61532b578d3Smrg * NULL.  The size of the memory required for the image is returned by this
61632b578d3Smrg * function.  The width and height of the requested image can be altered by the
61732b578d3Smrg * driver to reflect format limitations (such as component sampling periods
61832b578d3Smrg * that are larger than one).  If pPitch and pOffset are not NULL, these will
61932b578d3Smrg * be arrays with as many elements in them as there are planes in the image
62032b578d3Smrg * format.  The driver should specify the pitch (in bytes) of each scanline in
62132b578d3Smrg * the particular plane as well as the offset to that plane (in bytes) from the
62232b578d3Smrg * beginning of the image.
62332b578d3Smrg */
62432b578d3Smrgstatic int
62532b578d3SmrgATIMach64QueryImageAttributes
62632b578d3Smrg(
62732b578d3Smrg    ScrnInfoPtr    pScreenInfo,
62832b578d3Smrg    int            ImageID,
62932b578d3Smrg    unsigned short *Width,
63032b578d3Smrg    unsigned short *Height,
63132b578d3Smrg    int            *pPitch,
63232b578d3Smrg    int            *pOffset
63332b578d3Smrg)
63432b578d3Smrg{
63532b578d3Smrg    int Size, tmp;
63632b578d3Smrg
63732b578d3Smrg    if (!Width || !Height)
63832b578d3Smrg        return 0;
63932b578d3Smrg
64032b578d3Smrg    if (*Width > 2048)
64132b578d3Smrg        *Width = 2048;
64232b578d3Smrg    else
64332b578d3Smrg        *Width = (*Width + 1) & ~1;
64432b578d3Smrg
64532b578d3Smrg    if (*Height > 2048)
64632b578d3Smrg        *Height = 2048;
64732b578d3Smrg
64832b578d3Smrg    if (pOffset)
64932b578d3Smrg        pOffset[0] = 0;
65032b578d3Smrg
65132b578d3Smrg    switch (ImageID)
65232b578d3Smrg    {
65332b578d3Smrg        case FOURCC_YV12:
65432b578d3Smrg        case FOURCC_I420:
65532b578d3Smrg            *Height = (*Height + 1) & ~1;
65632b578d3Smrg            Size = (*Width + 3) & ~3;
65732b578d3Smrg            if (pPitch)
65832b578d3Smrg                pPitch[0] = Size;
65932b578d3Smrg            Size *= *Height;
66032b578d3Smrg            if (pOffset)
66132b578d3Smrg                pOffset[1] = Size;
66232b578d3Smrg            tmp = ((*Width >> 1) + 3) & ~3;
66332b578d3Smrg            if (pPitch)
66432b578d3Smrg                pPitch[1] = pPitch[2] = tmp;
66532b578d3Smrg            tmp *= (*Height >> 1);
66632b578d3Smrg            Size += tmp;
66732b578d3Smrg            if (pOffset)
66832b578d3Smrg                pOffset[2] = Size;
66932b578d3Smrg            Size += tmp;
67032b578d3Smrg            break;
67132b578d3Smrg
67232b578d3Smrg        case FOURCC_UYVY:
67332b578d3Smrg        case FOURCC_YUY2:
67432b578d3Smrg            Size = *Width << 1;
67532b578d3Smrg            if (pPitch)
67632b578d3Smrg                pPitch[0] = Size;
67732b578d3Smrg            Size *= *Height;
67832b578d3Smrg            break;
67932b578d3Smrg
68032b578d3Smrg        default:
68132b578d3Smrg            Size = 0;
68232b578d3Smrg            break;
68332b578d3Smrg    }
68432b578d3Smrg
68532b578d3Smrg    return Size;
68632b578d3Smrg}
68732b578d3Smrg
68832b578d3Smrg/*
68932b578d3Smrg * ATIMach64ScaleVideo --
69032b578d3Smrg *
69132b578d3Smrg * This function is called to calculate overlay scaling factors.
69232b578d3Smrg */
69332b578d3Smrgstatic void
69432b578d3SmrgATIMach64ScaleVideo
69532b578d3Smrg(
69632b578d3Smrg    ATIPtr         pATI,
69732b578d3Smrg    DisplayModePtr pMode,
69832b578d3Smrg    int            SrcW,
69932b578d3Smrg    int            SrcH,
70032b578d3Smrg    int            DstW,
70132b578d3Smrg    int            DstH,
70232b578d3Smrg    CARD32         *pHScale,
70332b578d3Smrg    CARD32         *pVScale
70432b578d3Smrg)
70532b578d3Smrg{
70632b578d3Smrg    int Shift;
70732b578d3Smrg
70832b578d3Smrg    *pHScale = ATIDivide(SrcW, DstW,
70932b578d3Smrg        GetBits(pATI->NewHW.pll_vclk_cntl, PLL_ECP_DIV) + 12, 0);
71032b578d3Smrg
71132b578d3Smrg    Shift = 12;
71232b578d3Smrg    if (pMode->Flags & V_INTERLACE)
71332b578d3Smrg        Shift++;
71432b578d3Smrg
71532b578d3Smrg    if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
71632b578d3Smrg    {
71732b578d3Smrg        if (pMode->VDisplay < pATI->LCDVertical)
71832b578d3Smrg        {
71932b578d3Smrg            SrcH *= pMode->VDisplay;
72032b578d3Smrg            DstH *= pATI->LCDVertical;
72132b578d3Smrg        }
72232b578d3Smrg    }
72332b578d3Smrg    else
72432b578d3Smrg    {
72532b578d3Smrg        if (pMode->Flags & V_DBLSCAN)
72632b578d3Smrg            Shift--;
72732b578d3Smrg        if (pMode->VScan > 1)
72832b578d3Smrg            DstH *= pMode->VScan;
72932b578d3Smrg    }
73032b578d3Smrg
73132b578d3Smrg    *pVScale = ATIDivide(SrcH, DstH, Shift, 0);
73232b578d3Smrg}
73332b578d3Smrg
73432b578d3Smrg/*
73532b578d3Smrg * ATIMach64ClipVideo --
73632b578d3Smrg *
73732b578d3Smrg * Clip the video (both source and destination) and make various other
73832b578d3Smrg * adjustments.
73932b578d3Smrg */
74032b578d3Smrgstatic Bool
74132b578d3SmrgATIMach64ClipVideo
74232b578d3Smrg(
74332b578d3Smrg    ScrnInfoPtr pScreenInfo,
74432b578d3Smrg    ATIPtr      pATI,
74532b578d3Smrg    int         ImageID,
74632b578d3Smrg    short       SrcX,
74732b578d3Smrg    short       SrcY,
74832b578d3Smrg    short       SrcW,
74932b578d3Smrg    short       SrcH,
75032b578d3Smrg    short       DstX,
75132b578d3Smrg    short       DstY,
75232b578d3Smrg    short       *DstW,
75332b578d3Smrg    short       *DstH,
75432b578d3Smrg    short       Width,
75532b578d3Smrg    short       Height,
75632b578d3Smrg    RegionPtr   pClip,
75732b578d3Smrg    BoxPtr      pDstBox,
75832b578d3Smrg    INT32       *SrcX1,
75932b578d3Smrg    INT32       *SrcX2,
76032b578d3Smrg    INT32       *SrcY1,
76132b578d3Smrg    INT32       *SrcY2,
76232b578d3Smrg    int         *SrcLeft,
76332b578d3Smrg    int         *SrcTop
76432b578d3Smrg)
76532b578d3Smrg{
76632b578d3Smrg    CARD32 HScale, VScale;
76732b578d3Smrg
76832b578d3Smrg    /* Check hardware limits */
76932b578d3Smrg    if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 768) ||
77032b578d3Smrg        ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)) ||
77132b578d3Smrg        ((Width > 720) && (pATI->Chip < ATI_CHIP_264GTPRO ||
77232b578d3Smrg                           pATI->Chip > ATI_CHIP_264LTPRO)))
77332b578d3Smrg        return FALSE;
77432b578d3Smrg
77532b578d3Smrg    ATIMach64ScaleVideo(pATI, pScreenInfo->currentMode,
77632b578d3Smrg        SrcW, SrcH, *DstW, *DstH, &HScale, &VScale);
77732b578d3Smrg    if (!HScale || !VScale)
77832b578d3Smrg        return FALSE;
77932b578d3Smrg    if (HScale > MaxScale)
78032b578d3Smrg        *DstW = (*DstW * HScale) / MaxScale;
78132b578d3Smrg    if (VScale > MaxScale)
78232b578d3Smrg        *DstH = (*DstH * HScale) / MaxScale;
78332b578d3Smrg
78432b578d3Smrg    /* Clip both the source and the destination */
78532b578d3Smrg    *SrcX1 = SrcX;
78632b578d3Smrg    *SrcX2 = SrcX + SrcW;
78732b578d3Smrg    *SrcY1 = SrcY;
78832b578d3Smrg    *SrcY2 = SrcY + SrcH;
78932b578d3Smrg
79032b578d3Smrg    pDstBox->x1 = DstX;
79132b578d3Smrg    pDstBox->x2 = DstX + *DstW;
79232b578d3Smrg    pDstBox->y1 = DstY;
79332b578d3Smrg    pDstBox->y2 = DstY + *DstH;
79432b578d3Smrg
79532b578d3Smrg    if (!xf86XVClipVideoHelper(pDstBox, SrcX1, SrcX2, SrcY1, SrcY2,
79632b578d3Smrg                               pClip, Width, Height))
79732b578d3Smrg        return FALSE;
79832b578d3Smrg
79932b578d3Smrg    /*
80032b578d3Smrg     * Reset overlay scaler origin.  This prevents jittering during
80132b578d3Smrg     * viewport panning or while the video is being moved or gradually
80232b578d3Smrg     * obscured/unobscured.
80332b578d3Smrg     */
80432b578d3Smrg    pDstBox->x1 = DstX;
80532b578d3Smrg    pDstBox->y1 = DstY;
80632b578d3Smrg
80732b578d3Smrg    /* Translate to the current viewport */
80832b578d3Smrg    pDstBox->x1 -= pScreenInfo->frameX0;
80932b578d3Smrg    pDstBox->x2 -= pScreenInfo->frameX0;
81032b578d3Smrg    pDstBox->y1 -= pScreenInfo->frameY0;
81132b578d3Smrg    pDstBox->y2 -= pScreenInfo->frameY0;
81232b578d3Smrg
81332b578d3Smrg    *SrcLeft = *SrcTop = 0;
81432b578d3Smrg
81532b578d3Smrg    /*
81632b578d3Smrg     * If the overlay scaler origin ends up outside the current viewport, move
81732b578d3Smrg     * it to the viewport's top left corner.  This unavoidably causes a slight
81832b578d3Smrg     * jittering in the image (even with double-buffering).
81932b578d3Smrg     */
82032b578d3Smrg    if (pDstBox->x1 < 0)
82132b578d3Smrg    {
82232b578d3Smrg        *SrcLeft = ((-pDstBox->x1 * SrcW) / *DstW) & ~1;
82332b578d3Smrg        pDstBox->x1 = 0;
82432b578d3Smrg    }
82532b578d3Smrg
82632b578d3Smrg    if (pDstBox->y1 < 0)
82732b578d3Smrg    {
82832b578d3Smrg        *SrcTop = (-pDstBox->y1 * SrcH) / *DstH;
82932b578d3Smrg        pDstBox->y1 = 0;
83032b578d3Smrg
83132b578d3Smrg        switch (ImageID)
83232b578d3Smrg        {
83332b578d3Smrg            case FOURCC_YV12:
83432b578d3Smrg            case FOURCC_I420:
83532b578d3Smrg                *SrcTop = (*SrcTop + 1) & ~1;
83632b578d3Smrg                break;
83732b578d3Smrg
83832b578d3Smrg            default:
83932b578d3Smrg                break;
84032b578d3Smrg        }
84132b578d3Smrg    }
84232b578d3Smrg
84332b578d3Smrg    return TRUE;
84432b578d3Smrg}
84532b578d3Smrg
84632b578d3Smrg#ifdef ATIMove32
84732b578d3Smrg
84832b578d3Smrg/* A faster intercept */
84932b578d3Smrg#undef  xf86XVCopyPacked
85032b578d3Smrg#define xf86XVCopyPacked ATIMach64XVCopyPacked
85132b578d3Smrg
85232b578d3Smrgstatic void
85332b578d3SmrgATIMach64XVCopyPacked
85432b578d3Smrg(
85532b578d3Smrg    const CARD8 *pSrc,
85632b578d3Smrg    CARD8       *pDst,
85732b578d3Smrg    int         SrcPitch,
85832b578d3Smrg    int         DstPitch,
85932b578d3Smrg    int         Height,
86032b578d3Smrg    int         Width
86132b578d3Smrg)
86232b578d3Smrg{
86332b578d3Smrg    Width >>= 1;
86432b578d3Smrg    while (--Height >= 0)
86532b578d3Smrg    {
86632b578d3Smrg        ATIMove32(pDst, pSrc, Width);
86732b578d3Smrg        pSrc += SrcPitch;
86832b578d3Smrg        pDst += DstPitch;
86932b578d3Smrg    }
87032b578d3Smrg}
87132b578d3Smrg
87232b578d3Smrg#endif
87332b578d3Smrg
87432b578d3Smrg/*
87532b578d3Smrg * ATIMach64DisplayVideo --
87632b578d3Smrg *
87732b578d3Smrg * This function programmes Mach64 registers needed to display a video.
87832b578d3Smrg */
87932b578d3Smrgstatic void
88032b578d3SmrgATIMach64DisplayVideo
88132b578d3Smrg(
88232b578d3Smrg    ScrnInfoPtr pScreenInfo,
88332b578d3Smrg    ATIPtr      pATI,
88432b578d3Smrg    BoxPtr      pDstBox,
88532b578d3Smrg    int         ImageID,
88632b578d3Smrg    int         Offset,
88732b578d3Smrg    int         Pitch,
88832b578d3Smrg    short       SrcW,
88932b578d3Smrg    short       SrcH,
89032b578d3Smrg    short       DstW,
89132b578d3Smrg    short       DstH,
89232b578d3Smrg    short       Width,
89332b578d3Smrg    short       Height
89432b578d3Smrg)
89532b578d3Smrg{
89632b578d3Smrg    DisplayModePtr pMode = pScreenInfo->currentMode;
89732b578d3Smrg    CARD32         HScale, VScale;
89832b578d3Smrg
89932b578d3Smrg    if (pMode->VScan > 1)
90032b578d3Smrg    {
90132b578d3Smrg        pDstBox->y1 *= pMode->VScan;
90232b578d3Smrg        pDstBox->y2 *= pMode->VScan;
90332b578d3Smrg    }
90432b578d3Smrg    if (pMode->Flags & V_DBLSCAN)
90532b578d3Smrg    {
90632b578d3Smrg        pDstBox->y1 <<= 1;
90732b578d3Smrg        pDstBox->y2 <<= 1;
90832b578d3Smrg    }
90932b578d3Smrg
91032b578d3Smrg    /* Recalculate overlay scale factors */
91132b578d3Smrg    ATIMach64ScaleVideo(pATI, pMode, SrcW, SrcH, DstW, DstH, &HScale, &VScale);
91232b578d3Smrg
91332b578d3Smrg    pATI->NewHW.video_format &= ~SCALER_IN;
91432b578d3Smrg    if (ImageID == FOURCC_UYVY)
91532b578d3Smrg        pATI->NewHW.video_format |= SCALER_IN_YVYU422;
91632b578d3Smrg    else
91732b578d3Smrg        pATI->NewHW.video_format |= SCALER_IN_VYUY422;
91832b578d3Smrg
91932b578d3Smrg    ATIMach64WaitForFIFO(pATI, 8);
92032b578d3Smrg    outq(OVERLAY_Y_X_START, OVERLAY_Y_X_END, OVERLAY_LOCK_START |
92132b578d3Smrg        SetWord(pDstBox->x1, 1) | SetWord(pDstBox->y1, 0),
92232b578d3Smrg        SetWord(pDstBox->x2 - 1, 1) | SetWord(pDstBox->y2 - 1, 0));
92332b578d3Smrg    outf(OVERLAY_SCALE_INC, SetWord(HScale, 1) | SetWord(VScale, 0));
92432b578d3Smrg    outf(SCALER_HEIGHT_WIDTH, SetWord(Width, 1) | SetWord(Height, 0));
92532b578d3Smrg    outf(VIDEO_FORMAT, pATI->NewHW.video_format);
92632b578d3Smrg
92732b578d3Smrg    if (pATI->Chip < ATI_CHIP_264VTB)
92832b578d3Smrg    {
92932b578d3Smrg        outf(BUF0_OFFSET, Offset);
93032b578d3Smrg        outf(BUF0_PITCH, Pitch);
93132b578d3Smrg    }
93232b578d3Smrg    else
93332b578d3Smrg    {
93432b578d3Smrg        outf(SCALER_BUF0_OFFSET, Offset);
93532b578d3Smrg        outf(SCALER_BUF_PITCH, Pitch);
93632b578d3Smrg    }
93732b578d3Smrg
93832b578d3Smrg    outf(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN);
93932b578d3Smrg}
94032b578d3Smrg
94132b578d3Smrg/*
94232b578d3Smrg * ATIMach64PutImage --
94332b578d3Smrg *
94432b578d3Smrg * This function is called to put a video image on the screen.
94532b578d3Smrg */
94632b578d3Smrgstatic int
94732b578d3SmrgATIMach64PutImage
94832b578d3Smrg(
94932b578d3Smrg    ScrnInfoPtr   pScreenInfo,
95032b578d3Smrg    short         SrcX,
95132b578d3Smrg    short         SrcY,
95232b578d3Smrg    short         DstX,
95332b578d3Smrg    short         DstY,
95432b578d3Smrg    short         SrcW,
95532b578d3Smrg    short         SrcH,
95632b578d3Smrg    short         DstW,
95732b578d3Smrg    short         DstH,
95832b578d3Smrg    int           ImageID,
95932b578d3Smrg    unsigned char *Buffer,
96032b578d3Smrg    short         Width,
96132b578d3Smrg    short         Height,
96232b578d3Smrg    Bool          Synchronise,
96332b578d3Smrg    RegionPtr     pClip,
96432b578d3Smrg    pointer       Data,
96532b578d3Smrg    DrawablePtr   pDraw
96632b578d3Smrg)
96732b578d3Smrg{
96832b578d3Smrg    ATIPtr    pATI    = Data;
96932b578d3Smrg    ScreenPtr pScreen;
97032b578d3Smrg    INT32     SrcX1, SrcX2, SrcY1, SrcY2;
97132b578d3Smrg    BoxRec    DstBox;
97232b578d3Smrg    int       SrcPitch, SrcPitchUV, DstPitch, DstSize;
97332b578d3Smrg    int       SrcTop, SrcLeft, DstWidth, DstHeight;
97432b578d3Smrg    int       Top, Bottom, Left, Right, nLine, nPixel, Offset;
97532b578d3Smrg    int       OffsetV, OffsetU;
97632b578d3Smrg    int       XVOffset;
97732b578d3Smrg    int       tmp;
97832b578d3Smrg    CARD8     *pDst;
97932b578d3Smrg
98032b578d3Smrg    if (pATI->ActiveSurface)
98132b578d3Smrg        return Success;
98232b578d3Smrg
98332b578d3Smrg    if (DstH < 16)
98432b578d3Smrg	return Success;
98532b578d3Smrg
98632b578d3Smrg    if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID,
98732b578d3Smrg                            SrcX, SrcY, SrcW, SrcH,
98832b578d3Smrg                            DstX, DstY, &DstW, &DstH,
98932b578d3Smrg                            Width, Height, pClip, &DstBox,
99032b578d3Smrg                            &SrcX1, &SrcX2, &SrcY1, &SrcY2,
99132b578d3Smrg                            &SrcLeft, &SrcTop))
99232b578d3Smrg        return Success;
99332b578d3Smrg
99432b578d3Smrg    pScreen = pScreenInfo->pScreen;
99532b578d3Smrg
99632b578d3Smrg    DstWidth = Width - SrcLeft;
99732b578d3Smrg    DstHeight = Height - SrcTop;
99832b578d3Smrg
99932b578d3Smrg    /*
100032b578d3Smrg     * Allocate an offscreen buffer for the entire source, even though only a
100132b578d3Smrg     * subset of the source will be copied into it.
100232b578d3Smrg     */
100332b578d3Smrg    DstPitch = /* bytes */
100432b578d3Smrg        (DstWidth + DstWidth + 15) & ~15;
100532b578d3Smrg    DstSize =  /* bytes */
100632b578d3Smrg        (DstPitch * DstHeight);
100732b578d3Smrg
100832b578d3Smrg    pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer,
100932b578d3Smrg        (pATI->DoubleBuffer + 1) * DstSize, &XVOffset, pATI);
101032b578d3Smrg
101132b578d3Smrg    if (!pATI->pXVBuffer)
101232b578d3Smrg    {
101332b578d3Smrg        if (!pATI->DoubleBuffer)
101432b578d3Smrg            return BadAlloc;
101532b578d3Smrg
101632b578d3Smrg        pATI->pXVBuffer =
101732b578d3Smrg            ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, DstSize, &XVOffset, pATI);
101832b578d3Smrg
101932b578d3Smrg        if (!pATI->pXVBuffer)
102032b578d3Smrg            return BadAlloc;
102132b578d3Smrg
102232b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
102332b578d3Smrg            "Video image double-buffering downgraded to single-buffering\n due"
102432b578d3Smrg            " to insufficient video memory.\n");
102532b578d3Smrg        pATI->DoubleBuffer = pATI->CurrentBuffer = 0;
102632b578d3Smrg    }
102732b578d3Smrg    else
102832b578d3Smrg    {
102932b578d3Smrg        /* Possibly switch buffers */
103032b578d3Smrg        pATI->CurrentBuffer = pATI->DoubleBuffer - pATI->CurrentBuffer;
103132b578d3Smrg    }
103232b578d3Smrg
103332b578d3Smrg    /* Synchronise video memory accesses */
103432b578d3Smrg    ATIMach64Sync(pScreenInfo);
103532b578d3Smrg
103632b578d3Smrg    Offset = XVOffset + pATI->CurrentBuffer * DstSize;
103732b578d3Smrg    pDst = pATI->pMemoryLE;
103832b578d3Smrg    pDst += Offset;
103932b578d3Smrg
104032b578d3Smrg    switch (ImageID)
104132b578d3Smrg    {
104232b578d3Smrg        case FOURCC_YV12:
104332b578d3Smrg        case FOURCC_I420:
104432b578d3Smrg            Left = (SrcX1 >> 16) & ~1;
104532b578d3Smrg            Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1;
104632b578d3Smrg            Top = (SrcY1 >> 16) & ~1;
104732b578d3Smrg            Bottom = ((SrcY2 + 0x1FFFF) >> 16) & ~1;
104832b578d3Smrg
104932b578d3Smrg            if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF)))
105032b578d3Smrg                Right += 2;
105132b578d3Smrg            if ((Bottom < Height) && ((SrcY1 & 0x1FFFF) <= (SrcY2 & 0x1FFFF)))
105232b578d3Smrg                Bottom += 2;
105332b578d3Smrg
105432b578d3Smrg            nPixel = Right - Left;
105532b578d3Smrg            nLine = Bottom - Top;
105632b578d3Smrg
105732b578d3Smrg            SrcPitch = (Width + 3) & ~3;
105832b578d3Smrg            OffsetV = SrcPitch * Height;
105932b578d3Smrg            SrcPitchUV = ((Width >> 1) + 3) & ~3;
106032b578d3Smrg            OffsetU = ((Height >> 1) * SrcPitchUV) + OffsetV;
106132b578d3Smrg
106232b578d3Smrg            tmp = ((Top >> 1) * SrcPitchUV) + (Left >> 1);
106332b578d3Smrg            OffsetV += tmp;
106432b578d3Smrg            OffsetU += tmp;
106532b578d3Smrg
106632b578d3Smrg            if (ImageID == FOURCC_I420)
106732b578d3Smrg            {
106832b578d3Smrg                tmp = OffsetV;
106932b578d3Smrg                OffsetV = OffsetU;
107032b578d3Smrg                OffsetU = tmp;
107132b578d3Smrg            }
107232b578d3Smrg
107332b578d3Smrg            pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1);
107432b578d3Smrg
107532b578d3Smrg            xf86XVCopyYUV12ToPacked(Buffer + (Top * SrcPitch) + Left,
107632b578d3Smrg                Buffer + OffsetV, Buffer + OffsetU, pDst, SrcPitch, SrcPitchUV,
107732b578d3Smrg                DstPitch, nLine, nPixel);
107832b578d3Smrg            break;
107932b578d3Smrg
108032b578d3Smrg        case FOURCC_UYVY:
108132b578d3Smrg        case FOURCC_YUY2:
108232b578d3Smrg        default:
108332b578d3Smrg            Left = (SrcX1 >> 16) & ~1;
108432b578d3Smrg            Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1;
108532b578d3Smrg            Top = SrcY1 >> 16;
108632b578d3Smrg            Bottom = (SrcY2 + 0x0FFFF) >> 16;
108732b578d3Smrg
108832b578d3Smrg            if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF)))
108932b578d3Smrg                Right += 2;
109032b578d3Smrg            if ((Bottom < Height) && ((SrcY1 & 0x0FFFF) <= (SrcY2 & 0x0FFFF)))
109132b578d3Smrg                Bottom++;
109232b578d3Smrg
109332b578d3Smrg            nPixel = Right - Left;
109432b578d3Smrg            nLine = Bottom - Top;
109532b578d3Smrg
109632b578d3Smrg            SrcPitch = Width << 1;
109732b578d3Smrg            Buffer += (Top * SrcPitch) + (Left << 1);
109832b578d3Smrg            pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1);
109932b578d3Smrg
110032b578d3Smrg            xf86XVCopyPacked(Buffer, pDst, SrcPitch, DstPitch, nLine, nPixel);
110132b578d3Smrg            break;
110232b578d3Smrg    }
110332b578d3Smrg
110432b578d3Smrg    if (!REGION_EQUAL(pScreen, &pATI->VideoClip, pClip))
110532b578d3Smrg    {
110632b578d3Smrg        REGION_COPY(pScreen, &pATI->VideoClip, pClip);
110732b578d3Smrg        if (pATI->AutoPaint)
110832b578d3Smrg            xf86XVFillKeyHelper(pScreen, pATI->NewHW.overlay_graphics_key_clr,
110932b578d3Smrg                pClip);
111032b578d3Smrg    }
111132b578d3Smrg
111232b578d3Smrg    ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID,
111332b578d3Smrg        Offset, DstPitch / 2, SrcW, SrcH, DstW, DstH, DstWidth, DstHeight);
111432b578d3Smrg
111532b578d3Smrg    return Success;
111632b578d3Smrg}
111732b578d3Smrg
111832b578d3Smrg/*
111932b578d3Smrg * ATIMach64AllocateSurface --
112032b578d3Smrg *
112132b578d3Smrg * This function allocates an offscreen buffer (called a "surface") for use by
112232b578d3Smrg * an external driver such as 'v4l'.
112332b578d3Smrg */
112432b578d3Smrgstatic int
112532b578d3SmrgATIMach64AllocateSurface
112632b578d3Smrg(
112732b578d3Smrg    ScrnInfoPtr    pScreenInfo,
112832b578d3Smrg    int            ImageID,
112932b578d3Smrg    unsigned short Width,
113032b578d3Smrg    unsigned short Height,
113132b578d3Smrg    XF86SurfacePtr pSurface
113232b578d3Smrg)
113332b578d3Smrg{
113432b578d3Smrg    ScreenPtr pScreen;
113532b578d3Smrg    ATIPtr    pATI = ATIPTR(pScreenInfo);
113632b578d3Smrg    int       XVOffset;
113732b578d3Smrg
113832b578d3Smrg    if (pATI->ActiveSurface)
113932b578d3Smrg        return BadAlloc;
114032b578d3Smrg
114132b578d3Smrg    if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 768) ||
114232b578d3Smrg        ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)) ||
114332b578d3Smrg        ((Width > 720) && (pATI->Chip < ATI_CHIP_264GTPRO ||
114432b578d3Smrg                           pATI->Chip > ATI_CHIP_264LTPRO)))
114532b578d3Smrg        return BadValue;
114632b578d3Smrg
114732b578d3Smrg    Width = (Width + 1) & ~1;
114832b578d3Smrg    pATI->SurfacePitch = ((Width << 1) + 15) & ~15;
114932b578d3Smrg
115032b578d3Smrg    pScreen = pScreenInfo->pScreen;
115132b578d3Smrg
115232b578d3Smrg    pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer,
115332b578d3Smrg        Height * pATI->SurfacePitch, &XVOffset, pATI);
115432b578d3Smrg    if (!pATI->pXVBuffer)
115532b578d3Smrg        return BadAlloc;
115632b578d3Smrg
115732b578d3Smrg    pATI->SurfaceOffset = XVOffset;
115832b578d3Smrg
115932b578d3Smrg    pSurface->pScrn = pScreenInfo;
116032b578d3Smrg    pSurface->id = ImageID;
116132b578d3Smrg    pSurface->width = Width;
116232b578d3Smrg    pSurface->height = Height;
116332b578d3Smrg    pSurface->pitches = &pATI->SurfacePitch;
116432b578d3Smrg    pSurface->offsets = &pATI->SurfaceOffset;
116532b578d3Smrg    pSurface->devPrivate.ptr = pATI;
116632b578d3Smrg
116732b578d3Smrg    /* Stop the video */
116832b578d3Smrg    outf(OVERLAY_SCALE_CNTL, SCALE_EN);
116932b578d3Smrg    REGION_EMPTY(pScreen, &pATI->VideoClip);
117032b578d3Smrg    pATI->ActiveSurface = TRUE;
117132b578d3Smrg
117232b578d3Smrg    return Success;
117332b578d3Smrg}
117432b578d3Smrg
117532b578d3Smrg/*
117632b578d3Smrg * ATIMach64FreeSurface --
117732b578d3Smrg *
117832b578d3Smrg * This function called to free a surface's offscreen buffer.
117932b578d3Smrg */
118032b578d3Smrgstatic int
118132b578d3SmrgATIMach64FreeSurface
118232b578d3Smrg(
118332b578d3Smrg    XF86SurfacePtr pSurface
118432b578d3Smrg)
118532b578d3Smrg{
118632b578d3Smrg    ATIPtr pATI = pSurface->devPrivate.ptr;
118732b578d3Smrg
118832b578d3Smrg    if (!pATI->ActiveSurface)
118932b578d3Smrg        return Success;
119032b578d3Smrg
119132b578d3Smrg    outf(OVERLAY_SCALE_CNTL, SCALE_EN);
119232b578d3Smrg    ATIMach64XVMemFree(pSurface->pScrn->pScreen, pATI->pXVBuffer, pATI);
119332b578d3Smrg    pATI->pXVBuffer = NULL;
119432b578d3Smrg    pATI->ActiveSurface = FALSE;
119532b578d3Smrg
119632b578d3Smrg    return Success;
119732b578d3Smrg}
119832b578d3Smrg
119932b578d3Smrg/*
120032b578d3Smrg * ATIMach64DisplaySurface --
120132b578d3Smrg *
120232b578d3Smrg * This function is called to display a video surface.
120332b578d3Smrg */
120432b578d3Smrgstatic int
120532b578d3SmrgATIMach64DisplaySurface
120632b578d3Smrg(
120732b578d3Smrg    XF86SurfacePtr pSurface,
120832b578d3Smrg    short          SrcX,
120932b578d3Smrg    short          SrcY,
121032b578d3Smrg    short          DstX,
121132b578d3Smrg    short          DstY,
121232b578d3Smrg    short          SrcW,
121332b578d3Smrg    short          SrcH,
121432b578d3Smrg    short          DstW,
121532b578d3Smrg    short          DstH,
121632b578d3Smrg    RegionPtr      pClip
121732b578d3Smrg)
121832b578d3Smrg{
121932b578d3Smrg    ATIPtr      pATI = pSurface->devPrivate.ptr;
122032b578d3Smrg    ScrnInfoPtr pScreenInfo;
122132b578d3Smrg    int         ImageID;
122232b578d3Smrg    short       Width, Height;
122332b578d3Smrg    BoxRec      DstBox;
122432b578d3Smrg    INT32       SrcX1, SrcX2, SrcY1, SrcY2;
122532b578d3Smrg    int         SrcLeft, SrcTop, SrcPitch, Offset;
122632b578d3Smrg
122732b578d3Smrg    if (!pATI->ActiveSurface)
122832b578d3Smrg        return Success;
122932b578d3Smrg
123032b578d3Smrg    pScreenInfo = pSurface->pScrn;
123132b578d3Smrg    ImageID = pSurface->id;
123232b578d3Smrg    Width = pSurface->width;
123332b578d3Smrg    Height = pSurface->height;
123432b578d3Smrg
123532b578d3Smrg    if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID,
123632b578d3Smrg                            SrcX, SrcY, SrcW, SrcH,
123732b578d3Smrg                            DstX, DstY, &DstW, &DstH,
123832b578d3Smrg                            Width, Height, pClip, &DstBox,
123932b578d3Smrg                            &SrcX1, &SrcX2, &SrcY1, &SrcY2,
124032b578d3Smrg                            &SrcLeft, &SrcTop))
124132b578d3Smrg        return Success;
124232b578d3Smrg
124332b578d3Smrg    xf86XVFillKeyHelper(pScreenInfo->pScreen,
124432b578d3Smrg        pATI->NewHW.overlay_graphics_key_clr, pClip);
124532b578d3Smrg
124632b578d3Smrg    SrcPitch = pSurface->pitches[0];
124732b578d3Smrg    Offset = pSurface->offsets[0] + (SrcTop * SrcPitch) + (SrcLeft << 1);
124832b578d3Smrg    ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID,
124932b578d3Smrg        Offset, SrcPitch, SrcW, SrcH, DstW, DstH, Width, Height);
125032b578d3Smrg
125132b578d3Smrg    return Success;
125232b578d3Smrg}
125332b578d3Smrg
125432b578d3Smrg/*
125532b578d3Smrg * ATIMach64StopSurface --
125632b578d3Smrg *
125732b578d3Smrg * This function is called to stop the overlaid display of a video surface.
125832b578d3Smrg */
125932b578d3Smrgstatic int
126032b578d3SmrgATIMach64StopSurface
126132b578d3Smrg(
126232b578d3Smrg    XF86SurfacePtr pSurface
126332b578d3Smrg)
126432b578d3Smrg{
126532b578d3Smrg    ATIPtr pATI = pSurface->devPrivate.ptr;
126632b578d3Smrg
126732b578d3Smrg    if (pATI->ActiveSurface)
126832b578d3Smrg        outf(OVERLAY_SCALE_CNTL, SCALE_EN);
126932b578d3Smrg
127032b578d3Smrg    return Success;
127132b578d3Smrg}
127232b578d3Smrg
127332b578d3Smrg/*
127432b578d3Smrg * ATIMach64GetSurfaceAttribute --
127532b578d3Smrg *
127632b578d3Smrg * Retrieve the value of an XVideo attribute.
127732b578d3Smrg */
127832b578d3Smrgstatic int
127932b578d3SmrgATIMach64GetSurfaceAttribute
128032b578d3Smrg(
128132b578d3Smrg    ScrnInfoPtr pScreenInfo,
128232b578d3Smrg    Atom        AttributeID,
128332b578d3Smrg    INT32       *Value
128432b578d3Smrg)
128532b578d3Smrg{
128632b578d3Smrg    return ATIMach64GetPortAttribute(pScreenInfo, AttributeID, Value,
128732b578d3Smrg                                     ATIPTR(pScreenInfo));
128832b578d3Smrg}
128932b578d3Smrg
129032b578d3Smrg/*
129132b578d3Smrg * ATIMach64SetSurfaceAttribute
129232b578d3Smrg *
129332b578d3Smrg * Set the value of an XVideo attribute.
129432b578d3Smrg */
129532b578d3Smrgstatic int
129632b578d3SmrgATIMach64SetSurfaceAttribute
129732b578d3Smrg(
129832b578d3Smrg    ScrnInfoPtr pScreenInfo,
129932b578d3Smrg    Atom        AttributeID,
130032b578d3Smrg    INT32       Value
130132b578d3Smrg)
130232b578d3Smrg{
130332b578d3Smrg    return ATIMach64SetPortAttribute(pScreenInfo, AttributeID, Value,
130432b578d3Smrg                                     ATIPTR(pScreenInfo));
130532b578d3Smrg}
130632b578d3Smrg
130732b578d3Smrg/* XVideo surface registration data */
130832b578d3Smrgstatic XF86OffscreenImageRec ATIMach64Surface[] =
130932b578d3Smrg{
131032b578d3Smrg    {
131132b578d3Smrg        &ATIMach64Image[0],             /* YUY2 */
131232b578d3Smrg        VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
131332b578d3Smrg        ATIMach64AllocateSurface,
131432b578d3Smrg        ATIMach64FreeSurface,
131532b578d3Smrg        ATIMach64DisplaySurface,
131632b578d3Smrg        ATIMach64StopSurface,
131732b578d3Smrg        ATIMach64GetSurfaceAttribute,
131832b578d3Smrg        ATIMach64SetSurfaceAttribute,
131932b578d3Smrg        720, 2048,
132032b578d3Smrg        nATIMach64Attribute - 1,        /* No double-buffering */
132132b578d3Smrg        ATIMach64Attribute
132232b578d3Smrg    },
132332b578d3Smrg    {
132432b578d3Smrg        &ATIMach64Image[1],             /* UYVY */
132532b578d3Smrg        VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
132632b578d3Smrg        ATIMach64AllocateSurface,
132732b578d3Smrg        ATIMach64FreeSurface,
132832b578d3Smrg        ATIMach64DisplaySurface,
132932b578d3Smrg        ATIMach64StopSurface,
133032b578d3Smrg        ATIMach64GetSurfaceAttribute,
133132b578d3Smrg        ATIMach64SetSurfaceAttribute,
133232b578d3Smrg        720, 2048,
133332b578d3Smrg        nATIMach64Attribute - 1,        /* No double-buffering */
133432b578d3Smrg        ATIMach64Attribute
133532b578d3Smrg    }
133632b578d3Smrg};
133732b578d3Smrg#define nATIMach64Surface NumberOf(ATIMach64Surface)
133832b578d3Smrg
133932b578d3Smrg/*
134032b578d3Smrg * ATIMach64XVInitialiseAdaptor --
134132b578d3Smrg *
134232b578d3Smrg * This function is called to make a Mach64's hardware overlay support
134332b578d3Smrg * available as an XVideo adaptor.
134432b578d3Smrg */
134532b578d3Smrgstatic int
134632b578d3SmrgATIMach64XVInitialiseAdaptor
134732b578d3Smrg(
134832b578d3Smrg    ScrnInfoPtr         pScreenInfo,
134932b578d3Smrg    XF86VideoAdaptorPtr **pppAdaptor
135032b578d3Smrg)
135132b578d3Smrg{
1352e35d4d8eSmrg    ScreenPtr           pScreen    = xf86ScrnToScreen(pScreenInfo);
135332b578d3Smrg    ATIPtr              pATI       = ATIPTR(pScreenInfo);
135432b578d3Smrg    XF86VideoAdaptorPtr *ppAdaptor = NULL;
135532b578d3Smrg    XF86VideoAdaptorPtr pAdaptor;
135632b578d3Smrg    int                 Index;
135732b578d3Smrg
135832b578d3Smrg    XF86VideoEncodingPtr  enc = &(ATIMach64VideoEncoding[0]);
135932b578d3Smrg    XF86OffscreenImagePtr surf0 = &(ATIMach64Surface[0]);
136032b578d3Smrg    XF86OffscreenImagePtr surf1 = &(ATIMach64Surface[1]);
136132b578d3Smrg
1362d31dbc53Smrg    if (xf86NameCmp(pScreenInfo->driverName, MACH64_DRIVER_NAME) != 0)
1363d31dbc53Smrg	return 0;
1364d31dbc53Smrg
136532b578d3Smrg    if (pppAdaptor)
136632b578d3Smrg        *pppAdaptor = NULL;
136732b578d3Smrg
136832b578d3Smrg    if (!pATI->Block1Base)
136932b578d3Smrg        return 0;
137032b578d3Smrg
137132b578d3Smrg    if (!(pAdaptor = xf86XVAllocateVideoAdaptorRec(pScreenInfo)))
137232b578d3Smrg        return 0;
137332b578d3Smrg
137432b578d3Smrg    ppAdaptor = xnfalloc(sizeof(pAdaptor));
137532b578d3Smrg    ppAdaptor[0] = pAdaptor;
137632b578d3Smrg
137732b578d3Smrg    pAdaptor->nPorts = 1;
137832b578d3Smrg    pAdaptor->pPortPrivates = pATI->XVPortPrivate;
137932b578d3Smrg    pATI->XVPortPrivate[0].ptr = pATI;
138032b578d3Smrg
138132b578d3Smrg    pAdaptor->type = XvInputMask | XvImageMask | XvWindowMask;
138232b578d3Smrg    pAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
138332b578d3Smrg    pAdaptor->name = "ATI Mach64 Back-end Overlay Scaler";
138432b578d3Smrg
138532b578d3Smrg    if (pATI->Chip < ATI_CHIP_264VTB)
138632b578d3Smrg    {
138732b578d3Smrg        enc->width = 384;
138832b578d3Smrg    }
138932b578d3Smrg    else if (pATI->Chip < ATI_CHIP_264GTPRO ||
139032b578d3Smrg             pATI->Chip > ATI_CHIP_264LTPRO)
139132b578d3Smrg    {
139232b578d3Smrg        enc->width = 720; /* default */
139332b578d3Smrg    }
139432b578d3Smrg    else
139532b578d3Smrg    {
139632b578d3Smrg        enc->width = 768;
139732b578d3Smrg    }
139832b578d3Smrg    pAdaptor->nEncodings = nATIMach64VideoEncoding;
139932b578d3Smrg    pAdaptor->pEncodings = ATIMach64VideoEncoding;
140032b578d3Smrg
140132b578d3Smrg    pAdaptor->nFormats = nATIMach64VideoFormat;
140232b578d3Smrg    pAdaptor->pFormats = ATIMach64VideoFormat;
140332b578d3Smrg
140432b578d3Smrg    pAdaptor->nAttributes = nATIMach64Attribute;
140532b578d3Smrg    pAdaptor->pAttributes = ATIMach64Attribute;
140632b578d3Smrg
140732b578d3Smrg    if (pATI->Chip < ATI_CHIP_264GTPRO)
140832b578d3Smrg    {
140932b578d3Smrg        /* Older controllers don't have brightness or saturation controls */
141032b578d3Smrg        pAdaptor->nAttributes -= 4;
141132b578d3Smrg        pAdaptor->pAttributes += 4;
141232b578d3Smrg    }
141332b578d3Smrg
141432b578d3Smrg    pAdaptor->nImages = nATIMach64Image;
141532b578d3Smrg    pAdaptor->pImages = ATIMach64Image;
141632b578d3Smrg
141732b578d3Smrg    pAdaptor->StopVideo            = ATIMach64StopVideo;
141832b578d3Smrg    pAdaptor->SetPortAttribute     = ATIMach64SetPortAttribute;
141932b578d3Smrg    pAdaptor->GetPortAttribute     = ATIMach64GetPortAttribute;
142032b578d3Smrg    pAdaptor->QueryBestSize        = ATIMach64QueryBestSize;
142132b578d3Smrg    pAdaptor->PutImage             = ATIMach64PutImage;
142232b578d3Smrg    pAdaptor->QueryImageAttributes = ATIMach64QueryImageAttributes;
142332b578d3Smrg
142432b578d3Smrg    REGION_NULL(pScreen, &pATI->VideoClip);
142532b578d3Smrg    pATI->ActiveSurface = FALSE;
142632b578d3Smrg
142732b578d3Smrg    if (ATIMach64XVAtomGeneration != serverGeneration)
142832b578d3Smrg    {
142932b578d3Smrg        /* Refresh static data */
143032b578d3Smrg        ATIMach64XVAtomGeneration = serverGeneration;
143132b578d3Smrg
143232b578d3Smrg        Index = nATIMach64Attribute - pAdaptor->nAttributes;
143332b578d3Smrg        for (;  Index < nATIMach64Attribute;  Index++)
143432b578d3Smrg            ATIMach64AttributeInfo[Index].AttributeID =
143532b578d3Smrg                MAKE_ATOM(ATIMach64Attribute[Index].name);
143632b578d3Smrg    }
143732b578d3Smrg
143832b578d3Smrg    ATIMach64SetDefaultAttributes(pATI, 0);
143932b578d3Smrg
144032b578d3Smrg    if (pATI->Chip < ATI_CHIP_264VTB)
144132b578d3Smrg    {
144232b578d3Smrg        surf0->max_width = 384;
144332b578d3Smrg        surf1->max_width = 384;
144432b578d3Smrg    }
144532b578d3Smrg    else if (pATI->Chip < ATI_CHIP_264GTPRO ||
144632b578d3Smrg             pATI->Chip > ATI_CHIP_264LTPRO)
144732b578d3Smrg    {
144832b578d3Smrg        surf0->max_width = 720; /* default */
144932b578d3Smrg        surf1->max_width = 720;
145032b578d3Smrg    }
145132b578d3Smrg    else
145232b578d3Smrg    {
145332b578d3Smrg        surf0->max_width = 768;
145432b578d3Smrg        surf1->max_width = 768;
145532b578d3Smrg    }
145632b578d3Smrg
145732b578d3Smrg    if (pATI->Chip < ATI_CHIP_264GTPRO)
145832b578d3Smrg    {
145932b578d3Smrg        /* No saturation nor brightness */
146032b578d3Smrg        surf0->num_attributes -= 4;
146132b578d3Smrg        surf1->num_attributes -= 4;
146232b578d3Smrg        surf0->attributes += 4;
146332b578d3Smrg        surf1->attributes += 4;
146432b578d3Smrg    }
146532b578d3Smrg    xf86XVRegisterOffscreenImages(pScreen, ATIMach64Surface, nATIMach64Surface);
146632b578d3Smrg
146732b578d3Smrg    if (pppAdaptor)
146832b578d3Smrg        *pppAdaptor = ppAdaptor;
146932b578d3Smrg    else {
14701b12faf6Smrg        free(ppAdaptor[0]);
14711b12faf6Smrg        free(ppAdaptor);
147232b578d3Smrg    }
147332b578d3Smrg
147432b578d3Smrg    return 1;
147532b578d3Smrg}
147632b578d3Smrg
147732b578d3Smrg/*
147832b578d3Smrg * ATIXVPreInit --
147932b578d3Smrg *
148032b578d3Smrg * This function is called by ATIPreInit() to set up the environment required
148132b578d3Smrg * to support the XVideo extension.
148232b578d3Smrg */
148332b578d3Smrgvoid
148432b578d3SmrgATIXVPreInit
148532b578d3Smrg(
148632b578d3Smrg    ATIPtr      pATI
148732b578d3Smrg)
148832b578d3Smrg{
148932b578d3Smrg    (void)xf86XVRegisterGenericAdaptorDriver(ATIMach64XVInitialiseAdaptor);
149032b578d3Smrg}
149132b578d3Smrg
149232b578d3Smrg/*
149332b578d3Smrg * ATIXVFreeAdaptorInfo --
149432b578d3Smrg *
149532b578d3Smrg * Free XVideo adaptor information.
149632b578d3Smrg */
149732b578d3Smrgstatic void
149832b578d3SmrgATIXVFreeAdaptorInfo
149932b578d3Smrg(
150032b578d3Smrg    XF86VideoAdaptorPtr *ppAdaptor,
150132b578d3Smrg    int                 nAdaptor
150232b578d3Smrg)
150332b578d3Smrg{
150432b578d3Smrg    if (!ppAdaptor)
150532b578d3Smrg        return;
150632b578d3Smrg
150732b578d3Smrg    while (nAdaptor > 0)
15081b12faf6Smrg        free(ppAdaptor[--nAdaptor]);
150932b578d3Smrg
15101b12faf6Smrg    free(ppAdaptor);
151132b578d3Smrg}
151232b578d3Smrg
151332b578d3Smrg/*
151432b578d3Smrg * ATIInitializeXVideo --
151532b578d3Smrg *
151632b578d3Smrg * This function is called to initialise XVideo extension support on a screen.
151732b578d3Smrg */
151832b578d3SmrgBool
151932b578d3SmrgATIInitializeXVideo
152032b578d3Smrg(
152132b578d3Smrg    ScreenPtr   pScreen,
152232b578d3Smrg    ScrnInfoPtr pScreenInfo,
152332b578d3Smrg    ATIPtr      pATI
152432b578d3Smrg)
152532b578d3Smrg{
152632b578d3Smrg    XF86VideoAdaptorPtr *ppAdaptor;
152732b578d3Smrg    int                 nAdaptor;
152832b578d3Smrg    Bool                result;
152932b578d3Smrg
153032b578d3Smrg    pScreenInfo->memPhysBase = pATI->LinearBase;
153132b578d3Smrg    pScreenInfo->fbOffset = 0;
153232b578d3Smrg
153332b578d3Smrg    nAdaptor = xf86XVListGenericAdaptors(pScreenInfo, &ppAdaptor);
153432b578d3Smrg    result = xf86XVScreenInit(pScreen, ppAdaptor, nAdaptor);
153532b578d3Smrg
153632b578d3Smrg    ATIXVFreeAdaptorInfo(ppAdaptor, nAdaptor);
153732b578d3Smrg
153832b578d3Smrg    return result;
153932b578d3Smrg}
154032b578d3Smrg
154132b578d3Smrg/*
154232b578d3Smrg * ATIMach64CloseXVideo --
154332b578d3Smrg *
154432b578d3Smrg * This function is called during screen termination to clean up after
154532b578d3Smrg * initialisation of Mach64 XVideo support.
154632b578d3Smrg */
154732b578d3Smrgvoid
154832b578d3SmrgATICloseXVideo
154932b578d3Smrg(
155032b578d3Smrg    ScreenPtr   pScreen,
155132b578d3Smrg    ScrnInfoPtr pScreenInfo,
155232b578d3Smrg    ATIPtr      pATI
155332b578d3Smrg)
155432b578d3Smrg{
15551b12faf6Smrg    if (!pATI->Block1Base)
15561b12faf6Smrg        return;
15571b12faf6Smrg
155832b578d3Smrg    ATIMach64StopVideo(pScreenInfo, pATI, TRUE);
155932b578d3Smrg
156032b578d3Smrg    REGION_UNINIT(pScreen, &pATI->VideoClip);
156132b578d3Smrg}
156232b578d3Smrg
156332b578d3Smrg/* Functions for offscreen memory management */
156432b578d3Smrg
156532b578d3Smrg#ifdef USE_XAA
156632b578d3Smrgstatic FBLinearPtr
156732b578d3SmrgATIResizeOffscreenLinear
156832b578d3Smrg(
156932b578d3Smrg    ScreenPtr   pScreen,
157032b578d3Smrg    FBLinearPtr pLinear,
157132b578d3Smrg    int         Size
157232b578d3Smrg)
157332b578d3Smrg{
157432b578d3Smrg    if (Size <= 0)
157532b578d3Smrg    {
157632b578d3Smrg        xf86FreeOffscreenLinear(pLinear);
157732b578d3Smrg        return NULL;
157832b578d3Smrg    }
157932b578d3Smrg
158032b578d3Smrg    if (pLinear)
158132b578d3Smrg    {
158232b578d3Smrg        if ((pLinear->size >= Size) ||
158332b578d3Smrg            xf86ResizeOffscreenLinear(pLinear, Size))
158432b578d3Smrg        {
158532b578d3Smrg            pLinear->MoveLinearCallback = NULL;
158632b578d3Smrg            pLinear->RemoveLinearCallback = NULL;
158732b578d3Smrg            return pLinear;
158832b578d3Smrg        }
158932b578d3Smrg
159032b578d3Smrg        xf86FreeOffscreenLinear(pLinear);
159132b578d3Smrg    }
159232b578d3Smrg
159332b578d3Smrg    pLinear = xf86AllocateOffscreenLinear(pScreen, Size, 16, NULL, NULL, NULL);
159432b578d3Smrg
159532b578d3Smrg    if (!pLinear)
159632b578d3Smrg    {
159732b578d3Smrg        int maxSize;
159832b578d3Smrg
159932b578d3Smrg        xf86QueryLargestOffscreenLinear(pScreen, &maxSize, 16,
160032b578d3Smrg            PRIORITY_EXTREME);
160132b578d3Smrg
160232b578d3Smrg        if (maxSize < Size)
160332b578d3Smrg            return NULL;
160432b578d3Smrg
160532b578d3Smrg        xf86PurgeUnlockedOffscreenAreas(pScreen);
160632b578d3Smrg        pLinear =
160732b578d3Smrg            xf86AllocateOffscreenLinear(pScreen, Size, 16, NULL, NULL, NULL);
160832b578d3Smrg    }
160932b578d3Smrg
161032b578d3Smrg    return pLinear;
161132b578d3Smrg}
161232b578d3Smrg#endif /* USE_XAA */
161332b578d3Smrg
161432b578d3Smrgstatic pointer
161532b578d3SmrgATIMach64XVMemAlloc
161632b578d3Smrg(
161732b578d3Smrg    ScreenPtr pScreen,
161832b578d3Smrg    pointer   pVideo,
161932b578d3Smrg    int       size,
162032b578d3Smrg    int       *offset,
162132b578d3Smrg    ATIPtr    pATI
162232b578d3Smrg)
162332b578d3Smrg{
162432b578d3Smrg#ifdef USE_EXA
162532b578d3Smrg    if (pATI->useEXA) {
162632b578d3Smrg        ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo;
162732b578d3Smrg
162832b578d3Smrg        if (area != NULL) {
162932b578d3Smrg            if (area->size >= size) {
163032b578d3Smrg                *offset = area->offset;
163132b578d3Smrg                return area;
163232b578d3Smrg            }
163332b578d3Smrg
163432b578d3Smrg            exaOffscreenFree(pScreen, area);
163532b578d3Smrg        }
163632b578d3Smrg
163732b578d3Smrg        area = exaOffscreenAlloc(pScreen, size, 64, TRUE, NULL, NULL);
163832b578d3Smrg        if (area != NULL) {
163932b578d3Smrg            *offset = area->offset;
164032b578d3Smrg            return area;
164132b578d3Smrg        }
164232b578d3Smrg    }
164332b578d3Smrg#endif /* USE_EXA */
164432b578d3Smrg
164532b578d3Smrg#ifdef USE_XAA
164632b578d3Smrg    if (!pATI->useEXA) {
164732b578d3Smrg        FBLinearPtr linear = (FBLinearPtr)pVideo;
164832b578d3Smrg        int cpp = pATI->AdjustDepth;
164932b578d3Smrg
165032b578d3Smrg        /* XAA allocates in units of pixels at the screen bpp, so adjust size
165132b578d3Smrg         * appropriately.
165232b578d3Smrg         */
165332b578d3Smrg        size = (size + cpp - 1) / cpp;
165432b578d3Smrg
165532b578d3Smrg        linear = ATIResizeOffscreenLinear(pScreen, linear, size);
165632b578d3Smrg        if (linear != NULL) {
165732b578d3Smrg            *offset = linear->offset * cpp;
165832b578d3Smrg            return linear;
165932b578d3Smrg        }
166032b578d3Smrg    }
166132b578d3Smrg#endif /* USE_XAA */
166232b578d3Smrg
166332b578d3Smrg    *offset = 0;
166432b578d3Smrg    return NULL;
166532b578d3Smrg}
166632b578d3Smrg
166732b578d3Smrgstatic void
166832b578d3SmrgATIMach64XVMemFree
166932b578d3Smrg(
167032b578d3Smrg    ScreenPtr pScreen,
167132b578d3Smrg    pointer   pVideo,
167232b578d3Smrg    ATIPtr    pATI
167332b578d3Smrg)
167432b578d3Smrg{
167532b578d3Smrg#ifdef USE_EXA
167632b578d3Smrg    if (pATI->useEXA) {
167732b578d3Smrg        ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo;
167832b578d3Smrg
167932b578d3Smrg        if (area != NULL)
168032b578d3Smrg            exaOffscreenFree(pScreen, area);
168132b578d3Smrg    }
168232b578d3Smrg#endif /* USE_EXA */
168332b578d3Smrg
168432b578d3Smrg#ifdef USE_XAA
168532b578d3Smrg    if (!pATI->useEXA) {
168632b578d3Smrg        FBLinearPtr linear = (FBLinearPtr)pVideo;
168732b578d3Smrg
168832b578d3Smrg        if (linear != NULL)
168932b578d3Smrg            ATIResizeOffscreenLinear(pScreen, linear, 0);
169032b578d3Smrg    }
169132b578d3Smrg#endif /* USE_XAA */
169232b578d3Smrg}
169332b578d3Smrg
1694