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