109885543Smrg/*
209885543SmrgCopyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
37104f784SmrgCopyright (C) 2000,2008 Silicon Motion, Inc.  All Rights Reserved.
409885543SmrgCopyright (C) 2001 Corvin Zahn.  All Rights Reserved.
57104f784SmrgCopyright (C) 2008 Mandriva Linux.  All Rights Reserved.
609885543Smrg
709885543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
809885543Smrgthis software and associated documentation files (the "Software"), to deal in
909885543Smrgthe Software without restriction, including without limitation the rights to
1009885543Smrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1109885543Smrgof the Software, and to permit persons to whom the Software is furnished to do
1209885543Smrgso, subject to the following conditions:
1309885543Smrg
1409885543SmrgThe above copyright notice and this permission notice shall be included in all
1509885543Smrgcopies or substantial portions of the Software.
1609885543Smrg
1709885543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1809885543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
1909885543SmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2009885543SmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2109885543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2209885543SmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2309885543Smrg
2409885543SmrgExcept as contained in this notice, the names of the XFree86 Project and
2509885543SmrgSilicon Motion shall not be used in advertising or otherwise to promote the
2609885543Smrgsale, use or other dealings in this Software without prior written
2709885543Smrgauthorization from the XFree86 Project and silicon Motion.
2809885543Smrg*/
2909885543Smrg
307104f784Smrg
3109885543Smrg/*
327104f784Smrg  Corvin Zahn <zahn@zac.de>	Date:   2.11.2001
337104f784Smrg    - SAA7111 support
347104f784Smrg    - supports attributes: XV_ENCODING, XV_BRIGHTNESS, XV_CONTRAST,
357104f784Smrg      XV_SATURATION, XV_HUE, XV_COLORKEY, XV_INTERLACED
367104f784Smrg      XV_CAPTURE_BRIGHTNESS can be used to set brightness in the capture device
377104f784Smrg    - bug fixes
387104f784Smrg    - tries not to use acceleration functions
397104f784Smrg    - interlaced video for double vertical resolution
407104f784Smrg	XV_INTERLACED = 0: only one field of an interlaced video signal is
417104f784Smrg			   displayed:
427104f784Smrg			-> half vertical resolution, but no comb like artifacts
437104f784Smrg			   from moving vertical edges
447104f784Smrg	XV_INTERLACED = 1: both fields of an interlaced video signal are
457104f784Smrg			   displayed:
467104f784Smrg			-> full vertical resolution, but comb like artifacts from
477104f784Smrg			   moving vertical edges
487104f784Smrg	The default value can be set with the driver option Interlaced
4909885543Smrg*/
5009885543Smrg
5109885543Smrg
5209885543Smrg#ifdef HAVE_CONFIG_H
5309885543Smrg#include "config.h"
5409885543Smrg#endif
5509885543Smrg
5609885543Smrg#include "smi.h"
5709885543Smrg#include "smi_video.h"
5809885543Smrg
597104f784Smrg#include "xf86Crtc.h"
6009885543Smrg
6109885543Smrg#undef MIN
6209885543Smrg#undef ABS
6309885543Smrg#undef CLAMP
6409885543Smrg#undef ENTRIES
6509885543Smrg
6609885543Smrg#define MIN(a, b) (((a) < (b)) ? (a) : (b))
6709885543Smrg#define ABS(n) (((n) < 0) ? -(n) : (n))
6809885543Smrg#define CLAMP(v, min, max) (((v) < (min)) ? (min) : MIN(v, max))
6909885543Smrg
7009885543Smrg#define ENTRIES(array) (sizeof(array) / sizeof((array)[0]))
7109885543Smrg#define nElems(x)		(sizeof(x) / sizeof(x[0]))
7209885543Smrg
7309885543Smrg#define MAKE_ATOM(a)	MakeAtom(a, sizeof(a) - 1, TRUE)
7409885543Smrg
7509885543Smrg#if SMI_USE_VIDEO
7609885543Smrg#include "dixstruct.h"
7709885543Smrg
7809885543Smrg
7909885543Smrgstatic int SMI_AddEncoding(XF86VideoEncodingPtr enc, int i,
8009885543Smrg			   int norm, int input, int channel);
8109885543Smrgstatic void SMI_BuildEncodings(SMI_PortPtr p);
8209885543Smrg
8309885543Smrgstatic XF86VideoAdaptorPtr SMI_SetupVideo(ScreenPtr pScreen);
8409885543Smrgstatic void SMI_ResetVideo(ScrnInfoPtr pScrn);
8509885543Smrg
8609885543Smrg#if SMI_USE_CAPTURE
8709885543Smrgstatic int SMI_PutVideo(ScrnInfoPtr pScrn,
8809885543Smrg		short vid_x, short vid_y, short drw_x, short drw_y,
8909885543Smrg		short vid_w, short vid_h, short drw_w, short drw_h,
9009885543Smrg		RegionPtr clipBoxes, pointer data, DrawablePtr);
9109885543Smrg#endif
9209885543Smrgstatic void SMI_StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown);
9309885543Smrgstatic int SMI_SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
9409885543Smrg		INT32 value, pointer data);
9509885543Smrgstatic int SMI_GetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
9609885543Smrg		INT32 *value, pointer data);
9709885543Smrgstatic void SMI_QueryBestSize(ScrnInfoPtr pScrn, Bool motion,
9809885543Smrg		short vid_w, short vid_h, short drw_w, short drw_h,
9909885543Smrg		unsigned int *p_w, unsigned int *p_h, pointer data);
10009885543Smrgstatic int SMI_PutImage(ScrnInfoPtr pScrn,
10109885543Smrg		short src_x, short src_y, short drw_x, short drw_y,
10209885543Smrg		short src_w, short src_h, short drw_w, short drw_h,
10309885543Smrg		int id, unsigned char *buf, short width, short height, Bool sync,
10409885543Smrg		RegionPtr clipBoxes, pointer data, DrawablePtr);
10509885543Smrgstatic int SMI_QueryImageAttributes(ScrnInfoPtr pScrn,
10609885543Smrg		int id, unsigned short *width, unsigned short *height,
10709885543Smrg		int *picthes, int *offsets);
10809885543Smrg
10909885543Smrgstatic void SMI_DisplayVideo(ScrnInfoPtr pScrn, int id, int offset,
11009885543Smrg		short width, short height, int pitch, int x1, int y1, int x2, int y2,
11109885543Smrg		BoxPtr dstBox, short vid_w, short vid_h, short drw_w, short drw_h);
1127104f784Smrgstatic void SMI_DisplayVideo0501_CSC(ScrnInfoPtr pScrn, int id, int offset,
1137104f784Smrg				     short width, short height, int pitch,
1147104f784Smrg				     int x1, int y1, int x2, int y2,
1157104f784Smrg				     BoxPtr dstBox, short vid_w, short vid_h,
1167104f784Smrg				     short drw_w, short drw_h,
1177104f784Smrg				     RegionPtr clipboxes);
1187104f784Smrgstatic void SMI_DisplayVideo0501(ScrnInfoPtr pScrn, int id, int offset,
1197104f784Smrg				 short width, short height, int pitch,
1207104f784Smrg				 int x1, int y1, int x2, int y2,
1217104f784Smrg				 BoxPtr dstBox, short vid_w, short vid_h,
1227104f784Smrg				 short drw_w, short drw_h);
12309885543Smrgstatic void SMI_DisplayVideo0730(ScrnInfoPtr pScrn, int id, int offset,
12409885543Smrg		short width, short height, int pitch, int x1, int y1, int x2, int y2,
12509885543Smrg		BoxPtr dstBox, short vid_w, short vid_h, short drw_w, short drw_h);
126b12e5c03Smrgstatic void SMI_BlockHandler(BLOCKHANDLER_ARGS_DECL);
12709885543Smrg/*static int SMI_SendI2C(ScrnInfoPtr pScrn, CARD8 device, char *devName,
12809885543Smrg        SMI_I2CDataPtr i2cData);*/
12909885543Smrg
13009885543Smrgstatic void SMI_InitOffscreenImages(ScreenPtr pScreen);
13109885543Smrgstatic void SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area);
13209885543Smrg
1337104f784Smrgstatic void CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2,
1347104f784Smrg			       unsigned char *src3, unsigned char *dst,
1357104f784Smrg			       int src1Pitch, int src23Pitch, int dstPitch,
1367104f784Smrg			       int height, int width);
13709885543Smrgstatic int SMI_AllocSurface(ScrnInfoPtr pScrn,
13809885543Smrg		int id, unsigned short width, unsigned short height,
13909885543Smrg		XF86SurfacePtr surface);
14009885543Smrgstatic int SMI_FreeSurface(XF86SurfacePtr surface);
14109885543Smrgstatic int SMI_DisplaySurface(XF86SurfacePtr surface,
14209885543Smrg		short vid_x, short vid_y, short drw_x, short drw_y,
14309885543Smrg		short vid_w, short vid_h, short drw_w, short drw_h,
14409885543Smrg		RegionPtr clipBoxes);
14509885543Smrgstatic int SMI_StopSurface(XF86SurfacePtr surface);
14609885543Smrgstatic int SMI_GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value);
14709885543Smrgstatic int SMI_SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value);
14809885543Smrg
14909885543Smrgstatic int SetAttr(ScrnInfoPtr pScrn, int i, int value);
15009885543Smrgstatic int SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value);
15109885543Smrgstatic int SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value);
15209885543Smrgstatic void SetKeyReg(SMIPtr pSmi, int reg, int value);
15309885543Smrg
15409885543Smrg/**
15509885543Smrg * Atoms
15609885543Smrg */
15709885543Smrg
15809885543Smrgstatic Atom xvColorKey;
15909885543Smrgstatic Atom xvEncoding;
16009885543Smrgstatic Atom xvBrightness,xvCapBrightness, xvContrast, xvSaturation, xvHue;
16109885543Smrgstatic Atom xvInterlaced;
16209885543Smrg
16309885543Smrg
16409885543Smrg/******************************************************************************\
16509885543Smrg**																			  **
16609885543Smrg**                           C A P A B I L I T I E S                          **
16709885543Smrg**																			  **
16809885543Smrg\******************************************************************************/
16909885543Smrg
17009885543Smrg
17109885543Smrg/**************************************************************************/
17209885543Smrg/* input channels */
17309885543Smrg
17409885543Smrg#define N_COMPOSITE_CHANNELS 4
17509885543Smrg#define N_SVIDEO_CHANNELS 2
17609885543Smrg
17709885543Smrg#define N_VIDEO_INPUTS 2
17809885543Smrgtypedef enum _VideoInput { VID_COMPOSITE, VID_SVIDEO } VideoInput;
17909885543Smrg
18009885543Smrg
18109885543Smrg/**************************************************************************/
18209885543Smrg/* video input formats */
18309885543Smrg
18409885543Smrgtypedef struct _VideoInputDataRec {
185beef1b22Smrg    const char* name;
18609885543Smrg} VideoInputDataRec;
18709885543Smrg
18809885543Smrgstatic VideoInputDataRec VideoInputs[] = {
18909885543Smrg    { "composite" },
19009885543Smrg    { "svideo" }
19109885543Smrg};
19209885543Smrg
19309885543Smrg
19409885543Smrg/**************************************************************************/
19509885543Smrg/* video norms */
19609885543Smrg
19709885543Smrg#define N_VIDEO_NORMS 3
19809885543Smrgtypedef enum _VideoNorm { PAL, NTSC, SECAM } VideoNorm;
19909885543Smrg
20009885543Smrgtypedef struct _VideoNormDataRec {
201beef1b22Smrg    const char* name;
20209885543Smrg    unsigned long Wt;
20309885543Smrg    unsigned long Wa;
20409885543Smrg    unsigned long Ht;
20509885543Smrg    unsigned long Ha;
20609885543Smrg    unsigned long HStart;
20709885543Smrg    unsigned long VStart;
20809885543Smrg    XvRationalRec rate;
20909885543Smrg} VideoNormDataRec;
21009885543Smrg
21109885543Smrg
21209885543Smrgstatic VideoNormDataRec VideoNorms[] =
21309885543Smrg{
21409885543Smrg    /* PAL-BDGHI */
21509885543Smrg    {"pal", 864, 704, 625, 576, 16, 16, { 1, 50 }},
21609885543Smrg    /* NTSC */
21709885543Smrg    {"ntsc", 858, 704, 525, 480, 21, 8, { 1001, 60000 }},
21809885543Smrg    /* SECAM (not tested) */
21909885543Smrg    {"secam", 864, 7040, 625, 576, 31, 16, { 1, 50 }},
22009885543Smrg};
22109885543Smrg
22209885543Smrg
22309885543Smrg/**************************************************************************/
22409885543Smrg/* number of (generated) XV_ENCODING vaulues */
22509885543Smrg#define N_ENCODINGS ((N_VIDEO_NORMS) * (N_COMPOSITE_CHANNELS + N_SVIDEO_CHANNELS))
22609885543Smrg
22709885543Smrg
22809885543Smrg/**************************************************************************/
22909885543Smrg
23009885543Smrgstatic XF86VideoFormatRec SMI_VideoFormats[] =
23109885543Smrg{
23209885543Smrg    { 15, TrueColor },	/* depth, class				*/
23309885543Smrg    { 16, TrueColor },	/* depth, class				*/
23409885543Smrg    { 24, TrueColor },	/* depth, class				*/
23509885543Smrg};
23609885543Smrg
23709885543Smrg
23809885543Smrg/**************************************************************************/
23909885543Smrg
24009885543Smrg/**
24109885543Smrg * Attributes
24209885543Smrg */
24309885543Smrg
24409885543Smrg#define XV_ENCODING_NAME        "XV_ENCODING"
24509885543Smrg#define XV_BRIGHTNESS_NAME      "XV_BRIGHTNESS"
24609885543Smrg#define XV_CAPTURE_BRIGHTNESS_NAME      "XV_CAPTURE_BRIGHTNESS"
24709885543Smrg#define XV_CONTRAST_NAME        "XV_CONTRAST"
24809885543Smrg#define XV_SATURATION_NAME      "XV_SATURATION"
24909885543Smrg#define XV_HUE_NAME             "XV_HUE"
25009885543Smrg#define XV_COLORKEY_NAME        "XV_COLORKEY"
25109885543Smrg#define XV_INTERLACED_NAME      "XV_INTERLACED"
25209885543Smrg
25309885543Smrg
25409885543Smrg/* fixed order! */
25509885543Smrgstatic XF86AttributeRec SMI_VideoAttributesSAA711x[N_ATTRS] = {
25609885543Smrg    {XvSettable | XvGettable,        0, N_ENCODINGS-1, XV_ENCODING_NAME},
25709885543Smrg    {XvSettable | XvGettable,        0,           255, XV_BRIGHTNESS_NAME},
25809885543Smrg    {XvSettable | XvGettable,        0,           255, XV_CAPTURE_BRIGHTNESS_NAME},
25909885543Smrg    {XvSettable | XvGettable,        0,           127, XV_CONTRAST_NAME},
26009885543Smrg    {XvSettable | XvGettable,        0,           127, XV_SATURATION_NAME},
26109885543Smrg    {XvSettable | XvGettable,     -128,           127, XV_HUE_NAME},
26209885543Smrg    {XvSettable | XvGettable, 0x000000,      0xFFFFFF, XV_COLORKEY_NAME},
26309885543Smrg    {XvSettable | XvGettable,        0,             1, XV_INTERLACED_NAME},
26409885543Smrg};
26509885543Smrg
26609885543Smrgstatic XF86AttributeRec SMI_VideoAttributes[2] = {
26709885543Smrg    {XvSettable | XvGettable,        0,           255, XV_BRIGHTNESS_NAME},
26809885543Smrg    {XvSettable | XvGettable, 0x000000,      0xFFFFFF, XV_COLORKEY_NAME},
26909885543Smrg};
27009885543Smrg
27109885543Smrg
27209885543Smrg/**************************************************************************/
27309885543Smrgstatic XF86ImageRec SMI_VideoImages[] =
27409885543Smrg{
27509885543Smrg    XVIMAGE_YUY2,
27609885543Smrg    XVIMAGE_YV12,
27709885543Smrg    XVIMAGE_I420,
27809885543Smrg    {
27909885543Smrg	FOURCC_RV15,			/* id				*/
28009885543Smrg	XvRGB,				/* type				*/
28109885543Smrg	LSBFirst,			/* byte_order			*/
28209885543Smrg	{ 'R', 'V' ,'1', '5',
28309885543Smrg	  0x00, '5',  0x00, 0x00,
28409885543Smrg	  0x00, 0x00, 0x00, 0x00,
28509885543Smrg	  0x00, 0x00, 0x00, 0x00 },	/* guid				*/
28609885543Smrg	16,				/* bits_per_pixel		*/
28709885543Smrg	XvPacked,			/* format			*/
28809885543Smrg	1,				/* num_planes			*/
28909885543Smrg	15,				/* depth			*/
29009885543Smrg	0x001F, 0x03E0, 0x7C00,		/* red_mask, green, blue	*/
29109885543Smrg	0, 0, 0,			/* y_sample_bits, u, v		*/
29209885543Smrg	0, 0, 0,			/* horz_y_period, u, v		*/
29309885543Smrg	0, 0, 0,			/* vert_y_period, u, v		*/
29409885543Smrg	{ 'R', 'V', 'B' },		/* component_order		*/
29509885543Smrg	XvTopToBottom			/* scaline_order		*/
29609885543Smrg    },
29709885543Smrg    {
29809885543Smrg	FOURCC_RV16,			/* id				*/
29909885543Smrg	XvRGB,				/* type				*/
30009885543Smrg	LSBFirst,			/* byte_order			*/
30109885543Smrg	{ 'R', 'V' ,'1', '6',
30209885543Smrg	  0x00, 0x00, 0x00, 0x00,
30309885543Smrg	  0x00, 0x00, 0x00, 0x00,
30409885543Smrg	  0x00, 0x00, 0x00, 0x00 },	/* guid				*/
30509885543Smrg	16,				/* bits_per_pixel		*/
30609885543Smrg	XvPacked,			/* format			*/
30709885543Smrg	1,				/* num_planes			*/
30809885543Smrg	16,				/* depth			*/
30909885543Smrg	0x001F, 0x07E0, 0xF800,		/* red_mask, green, blue	*/
31009885543Smrg	0, 0, 0,			/* y_sample_bits, u, v		*/
31109885543Smrg	0, 0, 0,			/* horz_y_period, u, v		*/
31209885543Smrg	0, 0, 0,			/* vert_y_period, u, v		*/
31309885543Smrg	{ 'R', 'V', 'B' },		/* component_order		*/
31409885543Smrg	XvTopToBottom			/* scaline_order		*/
31509885543Smrg    },
31609885543Smrg    {
31709885543Smrg	FOURCC_RV24,			/* id				*/
31809885543Smrg	XvRGB,				/* type				*/
31909885543Smrg	LSBFirst,			/* byte_order			*/
32009885543Smrg	{ 'R', 'V' ,'2', '4',
32109885543Smrg	  0x00, 0x00, 0x00, 0x00,
32209885543Smrg	  0x00, 0x00, 0x00, 0x00,
32309885543Smrg	  0x00, 0x00, 0x00, 0x00 },	/* guid				*/
32409885543Smrg	24,				/* bits_per_pixel		*/
32509885543Smrg	XvPacked,			/* format			*/
32609885543Smrg	1,				/* num_planes			*/
32709885543Smrg	24,				/* depth			*/
32809885543Smrg	0x0000FF, 0x00FF00, 0xFF0000,	/* red_mask, green, blue	*/
32909885543Smrg	0, 0, 0,			/* y_sample_bits, u, v		*/
33009885543Smrg	0, 0, 0,			/* horz_y_period, u, v		*/
33109885543Smrg	0, 0, 0,			/* vert_y_period, u, v		*/
33209885543Smrg	{ 'R', 'V', 'B' },		/* component_order			*/
33309885543Smrg	XvTopToBottom			/* scaline_order			*/
33409885543Smrg    },
33509885543Smrg    {
33609885543Smrg	FOURCC_RV32,			/* id				*/
33709885543Smrg	XvRGB,				/* type				*/
33809885543Smrg	LSBFirst,			/* byte_order			*/
33909885543Smrg	{ 'R', 'V' ,'3', '2',
34009885543Smrg	  0x00, 0x00, 0x00, 0x00,
34109885543Smrg	  0x00, 0x00, 0x00, 0x00,
34209885543Smrg	  0x00, 0x00, 0x00, 0x00 },	/* guid				*/
34309885543Smrg	32,				/* bits_per_pixel		*/
34409885543Smrg	XvPacked,			/* format			*/
34509885543Smrg	1,				/* num_planes			*/
34609885543Smrg	24,				/* depth			*/
34709885543Smrg	0x0000FF, 0x00FF00, 0xFF0000,	/* red_mask, green, blue	*/
34809885543Smrg	0, 0, 0,			/* y_sample_bits, u, v		*/
34909885543Smrg	0, 0, 0,			/* horz_y_period, u, v		*/
35009885543Smrg	0, 0, 0,			/* vert_y_period, u, v		*/
35109885543Smrg	{ 'R', 'V', 'B' },		/* component_order			*/
35209885543Smrg	XvTopToBottom			/* scaline_order			*/
35309885543Smrg    },
35409885543Smrg};
35509885543Smrg
35609885543Smrg
3577104f784Smrg/**************************************************************************/
3587104f784Smrgstatic XF86ImageRec SMI501_VideoImages[] = {
3597104f784Smrg    XVIMAGE_YUY2,
3607104f784Smrg    XVIMAGE_YV12,
3617104f784Smrg    XVIMAGE_I420,
3627104f784Smrg    {
3637104f784Smrg     FOURCC_RV16,		/* id                                           */
3647104f784Smrg     XvRGB,			/* type                                         */
3657104f784Smrg     LSBFirst,			/* byte_order                           */
3667104f784Smrg     {'R', 'V', '1', '6',
3677104f784Smrg      0x00, 0x00, 0x00, 0x00,
3687104f784Smrg      0x00, 0x00, 0x00, 0x00,
3697104f784Smrg      0x00, 0x00, 0x00, 0x00},	/* guid                                         */
3707104f784Smrg     16,			/* bits_per_pixel                       */
3717104f784Smrg     XvPacked,			/* format                                       */
3727104f784Smrg     1,				/* num_planes                           */
3737104f784Smrg     16,			/* depth                                        */
3747104f784Smrg     0x001F, 0x07E0, 0xF800,	/* red_mask, green, blue        */
3757104f784Smrg     0, 0, 0,			/* y_sample_bits, u, v          */
3767104f784Smrg     0, 0, 0,			/* horz_y_period, u, v          */
3777104f784Smrg     0, 0, 0,			/* vert_y_period, u, v          */
3787104f784Smrg     {'R', 'V', 'B'},		/* component_order                      */
3797104f784Smrg     XvTopToBottom		/* scaline_order                        */
3807104f784Smrg     },
3817104f784Smrg    {
3827104f784Smrg     FOURCC_RV32,		/* id                                           */
3837104f784Smrg     XvRGB,			/* type                                         */
3847104f784Smrg     LSBFirst,			/* byte_order                           */
3857104f784Smrg     {'R', 'V', '3', '2',
3867104f784Smrg      0x00, 0x00, 0x00, 0x00,
3877104f784Smrg      0x00, 0x00, 0x00, 0x00,
3887104f784Smrg      0x00, 0x00, 0x00, 0x00},	/* guid                                         */
3897104f784Smrg     32,			/* bits_per_pixel                       */
3907104f784Smrg     XvPacked,			/* format                                       */
3917104f784Smrg     1,				/* num_planes                           */
3927104f784Smrg     24,			/* depth                                        */
3937104f784Smrg     0x0000FF, 0x00FF00, 0xFF0000,	/* red_mask, green, blue        */
3947104f784Smrg     0, 0, 0,			/* y_sample_bits, u, v          */
3957104f784Smrg     0, 0, 0,			/* horz_y_period, u, v          */
3967104f784Smrg     0, 0, 0,			/* vert_y_period, u, v          */
3977104f784Smrg     {'R', 'V', 'B'},		/* component_order                      */
3987104f784Smrg     XvTopToBottom		/* scaline_order                        */
3997104f784Smrg     },
4007104f784Smrg};
4017104f784Smrg
40209885543Smrg/**************************************************************************/
40309885543Smrg
40409885543Smrg/**
40509885543Smrg * SAA7111 video decoder register values
40609885543Smrg */
40709885543Smrg
40809885543Smrg
40909885543Smrg/** SAA7111 control sequences for selecting one out of four
41009885543Smrg    composite input channels */
41109885543Smrgstatic I2CByte SAA7111CompositeChannelSelect[N_COMPOSITE_CHANNELS][4] = {
41209885543Smrg    { 0x02, 0xC0, 0x09, 0x4A}, /* CVBS AI11 */
41309885543Smrg    { 0x02, 0xC1, 0x09, 0x4A}, /* CVBS AI12 */
41409885543Smrg    { 0x02, 0xC2, 0x09, 0x4A}, /* CVBS AI21 */
41509885543Smrg    { 0x02, 0xC3, 0x09, 0x4A}, /* CVBS AI22 */
41609885543Smrg};
41709885543Smrg
41809885543Smrg
41909885543Smrg/** SAA7111 control sequences for selecting one out of two
42009885543Smrg    s-video input channels */
42109885543Smrgstatic I2CByte SAA7111SVideoChannelSelect[N_SVIDEO_CHANNELS][4] = {
42209885543Smrg    { 0x02, 0xC6, 0x09, 0xCA}, /* Y/C AI11/AI21 */
42309885543Smrg    { 0x02, 0xC7, 0x09, 0xCA}, /* Y/C AI12/AI22 */
42409885543Smrg};
42509885543Smrg
42609885543Smrg
42709885543Smrg/** SAA7111 control sequences for selecting one out of three
42809885543Smrg    video norms */
42909885543Smrgstatic I2CByte SAA7111VideoStd[3][8] = {
43009885543Smrg    {0x06, 108, 0x07, 108, 0x08, 0x09, 0x0E, 0x01}, /* PAL */
43109885543Smrg    {0x06, 107, 0x07, 107, 0x08, 0x49, 0x0E, 0x01}, /* NTSC */
43209885543Smrg    {0x06, 108, 0x07, 108, 0x08, 0x01, 0x0E, 0x51}  /* SECAM */
43309885543Smrg};
43409885543Smrg
43509885543Smrg
43609885543Smrg#if 0
43709885543Smrgstatic I2CByte SAA7110InitData[] =
43809885543Smrg{
43909885543Smrg	/* Configuration */
44009885543Smrg    0x00, 0x4C, 0x01, 0x3C, 0x02, 0x00, 0x03, 0xEF,
44109885543Smrg    0x04, 0xBD, 0x05, 0xE2, 0x06, 0x00, 0x07, 0x00,
44209885543Smrg    0x08, 0xF8, 0x09, 0xF8, 0x0A, 0x60, 0x0B, 0x60,
44309885543Smrg    0x0C, 0x00, 0x0D, 0x80, 0x0E, 0x18, 0x0F, 0xD9,
44409885543Smrg    0x10, 0x00, 0x11, 0x2B, 0x12, 0x40, 0x13, 0x40,
44509885543Smrg    0x14, 0x42, 0x15, 0x1A, 0x16, 0xFF, 0x17, 0xDA,
44609885543Smrg    0x18, 0xE6, 0x19, 0x90, 0x20, 0xD9, 0x21, 0x16,
44709885543Smrg    0x22, 0x40, 0x23, 0x40, 0x24, 0x80, 0x25, 0x40,
44809885543Smrg    0x26, 0x80, 0x27, 0x4F, 0x28, 0xFE, 0x29, 0x01,
44909885543Smrg    0x2A, 0xCF, 0x2B, 0x0F, 0x2C, 0x03, 0x2D, 0x01,
45009885543Smrg    0x2E, 0x83, 0x2F, 0x03, 0x30, 0x40, 0x31, 0x35,
45109885543Smrg    0x32, 0x02, 0x33, 0x8C, 0x34, 0x03,
45209885543Smrg
45309885543Smrg	/* NTSC */
45409885543Smrg    0x11, 0x2B, 0x0F, 0xD9,
45509885543Smrg
45609885543Smrg	/* RCA input connector */
45709885543Smrg    0x06, 0x00, 0x0E, 0x18, 0x20, 0xD9, 0x21, 0x16,
45809885543Smrg    0x22, 0x40, 0x2C, 0x03,
45909885543Smrg
46009885543Smrg};
46109885543Smrg#endif
46209885543Smrg
46309885543Smrgstatic I2CByte SAA7111InitData[] =
46409885543Smrg{
46509885543Smrg    0x11, 0x1D, /* 0D D0=1: automatic colour killer off
46609885543Smrg		   D1=0: DMSD data to YUV output
46709885543Smrg		   D2=1: output enable H/V sync on
46809885543Smrg		   D3=1: output enable YUV data on */
46909885543Smrg    0x02, 0xC0, /* Mode 0 */
47009885543Smrg    0x03, 0x23, /* automatic gain */
47109885543Smrg    0x04, 0x00, /*  */
47209885543Smrg    0x05, 0x00, /*  */
47309885543Smrg    0x06, 108,  /* hor sync begin */
47409885543Smrg    0x07, 108,  /* hor sync stop */
47509885543Smrg    0x08, 0x88, /* sync control:
47609885543Smrg		   D1-0=00: VNOI = normal mode
47709885543Smrg		   D2=0: PLL closed
47809885543Smrg		   D3=1: VTR mode
47909885543Smrg		   D7=1: automatic field detection */
48009885543Smrg    0x09, 0x41, /* 4A luminance control */
48109885543Smrg    0x0A, 0x80, /* brightness = 128 (CCIR level) */
48209885543Smrg    0x0B, 0x40, /* contrast = 1.0 */
48309885543Smrg    0x0C, 0x40, /* crominance = 1.0 (CCIR level) */
48409885543Smrg    0x0D, 0x00, /* hue = 0 */
48509885543Smrg    0x0E, 0x01, /* chroma bandwidth = nominal
48609885543Smrg		   fast colour time constant = nominal
48709885543Smrg		   chrom comp filter on
48809885543Smrg		   colour standard PAL BGHI, NTSC M */
48909885543Smrg    0x10, 0x48, /* luminance delay compensation = 0
49009885543Smrg		   VRLN = 1
49109885543Smrg		   fine pos of hs = 0
49209885543Smrg		   output format = YUV 422 */
49309885543Smrg    0x12, 0x00, /* 20 D5=1: VPO in tristate */
49409885543Smrg    0x13, 0x00,
49509885543Smrg    0x15, 0x00,
49609885543Smrg    0x16, 0x00,
49709885543Smrg    0x17, 0x00,
49809885543Smrg
49909885543Smrg};
50009885543Smrg
50109885543Smrg
50209885543Smrg/**************************************************************************/
50309885543Smrg
50409885543Smrg/**
50509885543Smrg * generates XF86VideoEncoding[i] with video norm norm, video input format
50609885543Smrg * input and video input channel channel
50709885543Smrg */
50809885543Smrgstatic int
50909885543SmrgSMI_AddEncoding(XF86VideoEncodingPtr enc, int i,
51009885543Smrg		int norm, int input, int channel)
51109885543Smrg{
512beef1b22Smrg    const char* norm_string;
513beef1b22Smrg    const char* input_string;
51409885543Smrg    char channel_string[20];
515beef1b22Smrg    char* name_string;
51609885543Smrg
5177104f784Smrg    ENTER();
51809885543Smrg
51909885543Smrg    norm_string = VideoNorms[norm].name;
52009885543Smrg    input_string = VideoInputs[input].name;
521beef1b22Smrg    snprintf(channel_string, sizeof(channel_string), "%d", channel);
52209885543Smrg    enc[i].id     = i;
523beef1b22Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
524beef1b22Smrg    if (Xasprintf(&name_string, "%s-%s-%s",
525beef1b22Smrg                  norm_string, input_string, channel_string) < 0)
526beef1b22Smrg        LEAVE(-1);
527beef1b22Smrg#else
528beef1b22Smrg    name_string = Xprintf("%s-%s-%s",
529beef1b22Smrg                          norm_string, input_string, channel_string);
530beef1b22Smrg    if (NULL == name_string)
5317104f784Smrg	LEAVE(-1);
532beef1b22Smrg#endif
533beef1b22Smrg    enc[i].name   = name_string;
5347104f784Smrg
53509885543Smrg    enc[i].width  = VideoNorms[norm].Wa;
53609885543Smrg    enc[i].height = VideoNorms[norm].Ha;
53709885543Smrg    enc[i].rate   = VideoNorms[norm].rate;
53809885543Smrg
5397104f784Smrg    LEAVE(0);
54009885543Smrg}
54109885543Smrg
54209885543Smrg
54309885543Smrg/**
54409885543Smrg * builds XF86VideoEncodings with all legal combinations of video norm,
54509885543Smrg * video input format and video input channel
54609885543Smrg */
54709885543Smrgstatic void
54809885543SmrgSMI_BuildEncodings(SMI_PortPtr p)
54909885543Smrg{
55009885543Smrg    int ch, n;
55109885543Smrg
5527104f784Smrg    ENTER();
55309885543Smrg
55409885543Smrg    /* allocate memory for encoding array */
555beef1b22Smrg    p->enc = calloc(N_ENCODINGS, sizeof(XF86VideoEncodingRec));
55609885543Smrg    if (NULL == p->enc)
55709885543Smrg	goto fail;
558beef1b22Smrg
55909885543Smrg    /* allocate memory for video norm array */
560beef1b22Smrg    p->norm = calloc(N_ENCODINGS, sizeof(int));
56109885543Smrg    if (NULL == p->norm)
56209885543Smrg	goto fail;
563beef1b22Smrg
56409885543Smrg    /* allocate memory for video input format array */
565beef1b22Smrg    p->input = calloc(N_ENCODINGS, sizeof(int));
56609885543Smrg    if (NULL == p->input)
56709885543Smrg	goto fail;
568beef1b22Smrg
56909885543Smrg    /* allocate memory for video channel number array */
570beef1b22Smrg    p->channel = calloc(N_ENCODINGS, sizeof(int));
57109885543Smrg    if (NULL == p->channel)
57209885543Smrg	goto fail;
57309885543Smrg
57409885543Smrg    /* fill arrays */
57509885543Smrg    p->nenc = 0;
57609885543Smrg    for (ch = 0; ch < N_COMPOSITE_CHANNELS; ch++) {
57709885543Smrg	for (n = 0; n < N_VIDEO_NORMS; n++) {
57809885543Smrg	    SMI_AddEncoding(p->enc, p->nenc, n, VID_COMPOSITE, ch);
57909885543Smrg	    p->norm[p->nenc]  = n;
58009885543Smrg	    p->input[p->nenc] = VID_COMPOSITE;
58109885543Smrg	    p->channel[p->nenc] = ch;
58209885543Smrg	    p->nenc++;
58309885543Smrg	}
58409885543Smrg    }
58509885543Smrg    for (ch = 0; ch < N_SVIDEO_CHANNELS; ch++) {
58609885543Smrg	for (n = 0; n < N_VIDEO_NORMS; n++) {
58709885543Smrg	    SMI_AddEncoding(p->enc, p->nenc, n, VID_SVIDEO, ch);
58809885543Smrg	    p->norm[p->nenc]  = n;
58909885543Smrg	    p->input[p->nenc] = VID_SVIDEO;
59009885543Smrg	    p->channel[p->nenc] = ch;
59109885543Smrg	    p->nenc++;
59209885543Smrg	}
59309885543Smrg    }
5947104f784Smrg    LEAVE();
59509885543Smrg
59609885543Smrg fail:
5977b58d2e0Smrg    free(p->input);
59809885543Smrg    p->input = NULL;
5997b58d2e0Smrg    free(p->norm);
60009885543Smrg    p->norm = NULL;
6017b58d2e0Smrg    free(p->channel);
60209885543Smrg    p->channel = NULL;
6037b58d2e0Smrg    free(p->enc);
60409885543Smrg    p->enc = NULL;
60509885543Smrg    p->nenc = 0;
6067104f784Smrg    LEAVE();
60709885543Smrg}
60809885543Smrg
60909885543Smrg
61009885543Smrg/******************************************************************************\
61109885543Smrg**                                                                            **
61209885543Smrg**                  X V E X T E N S I O N   I N T E R F A C E                 **
61309885543Smrg**                                                                            **
61409885543Smrg\******************************************************************************/
61509885543Smrg
61609885543Smrgvoid
61709885543SmrgSMI_InitVideo(ScreenPtr pScreen)
61809885543Smrg{
619b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
62009885543Smrg    XF86VideoAdaptorPtr *ptrAdaptors, *newAdaptors = NULL;
62109885543Smrg    XF86VideoAdaptorPtr newAdaptor = NULL;
62209885543Smrg    int numAdaptors;
62309885543Smrg
6247104f784Smrg    ENTER();
62509885543Smrg
62609885543Smrg    numAdaptors = xf86XVListGenericAdaptors(pScrn, &ptrAdaptors);
62709885543Smrg
6287104f784Smrg    DEBUG("numAdaptors=%d\n", numAdaptors);
62909885543Smrg
6307104f784Smrg    newAdaptor = SMI_SetupVideo(pScreen);
6317104f784Smrg    DEBUG("newAdaptor=%p\n", newAdaptor);
6327104f784Smrg    SMI_InitOffscreenImages(pScreen);
63309885543Smrg
63409885543Smrg    if (newAdaptor != NULL) {
63509885543Smrg        if (numAdaptors == 0) {
63609885543Smrg            numAdaptors = 1;
63709885543Smrg            ptrAdaptors = &newAdaptor;
63809885543Smrg        } else {
6397b58d2e0Smrg            newAdaptors = malloc((numAdaptors + 1) *
64009885543Smrg                    sizeof(XF86VideoAdaptorPtr*));
64109885543Smrg            if (newAdaptors != NULL) {
64209885543Smrg                memcpy(newAdaptors, ptrAdaptors,
64309885543Smrg                        numAdaptors * sizeof(XF86VideoAdaptorPtr));
64409885543Smrg                newAdaptors[numAdaptors++] = newAdaptor;
64509885543Smrg                ptrAdaptors = newAdaptors;
64609885543Smrg            }
64709885543Smrg        }
64809885543Smrg    }
64909885543Smrg
65009885543Smrg    if (numAdaptors != 0) {
6517104f784Smrg        DEBUG("ScreenInit %i\n",numAdaptors);
65209885543Smrg        xf86XVScreenInit(pScreen, ptrAdaptors, numAdaptors);
65309885543Smrg    }
65409885543Smrg
6557b58d2e0Smrg    free(newAdaptors);
65609885543Smrg
6577104f784Smrg    LEAVE();
65809885543Smrg}
65909885543Smrg
66009885543Smrg
66109885543Smrg/*************************************************************************/
66209885543Smrg
66309885543Smrg/*
66409885543Smrg *  Video codec controls
66509885543Smrg */
66609885543Smrg
66709885543Smrg#if 0
66809885543Smrg/**
66909885543Smrg * scales value value of attribute i to range min, max
67009885543Smrg */
67109885543Smrgstatic int
67209885543SmrgScale(int i, int value, int min, int max)
67309885543Smrg{
67409885543Smrg    return min + (value - SMI_VideoAttributes[i].min_value) * (max - min) /
67509885543Smrg	(SMI_VideoAttributes[i].max_value - SMI_VideoAttributes[i].min_value);
67609885543Smrg}
67709885543Smrg#endif
67809885543Smrg/**
67909885543Smrg * sets video decoder attributes channel, encoding, brightness, contrast, saturation, hue
68009885543Smrg */
68109885543Smrgstatic int
68209885543SmrgSetAttr(ScrnInfoPtr pScrn, int i, int value)
68309885543Smrg{
68409885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
68509885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
68609885543Smrg
68709885543Smrg    if (i < XV_ENCODING || i > XV_HUE)
68809885543Smrg	return BadMatch;
68909885543Smrg
69009885543Smrg    /* clamps value to attribute range */
69109885543Smrg    value = CLAMP(value, SMI_VideoAttributes[i].min_value,
69209885543Smrg		  SMI_VideoAttributes[i].max_value);
69309885543Smrg
69409885543Smrg    if (i == XV_BRIGHTNESS) {
69509885543Smrg	int my_value = (value <= 128? value + 128 : value - 128);
69609885543Smrg	SetKeyReg(pSmi, 0x5C, 0xEDEDED | (my_value << 24));
69709885543Smrg    } else if (pPort->I2CDev.SlaveAddr == SAA7110) {
69809885543Smrg	return SetAttrSAA7110(pScrn, i, value);
69909885543Smrg    } else if (pPort->I2CDev.SlaveAddr == SAA7111) {
70009885543Smrg	return SetAttrSAA7111(pScrn, i, value);
70109885543Smrg    }
70209885543Smrg#if 0
70309885543Smrg    else {
70409885543Smrg	return XvBadAlloc;
70509885543Smrg    }
70609885543Smrg#endif
70709885543Smrg
70809885543Smrg    return Success;
70909885543Smrg}
71009885543Smrg
71109885543Smrg
71209885543Smrg/**
71309885543Smrg * sets SAA7110 video decoder attributes channel, encoding, brightness, contrast, saturation, hue
71409885543Smrg */
71509885543Smrgstatic int
71609885543SmrgSetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value)
71709885543Smrg{
71809885543Smrg    /* not supported */
71909885543Smrg    return XvBadAlloc;
72009885543Smrg}
72109885543Smrg
72209885543Smrg
72309885543Smrg/**
72409885543Smrg * sets SAA7111 video decoder attributes channel, encoding,
72509885543Smrg * brightness, contrast, saturation, hue
72609885543Smrg */
72709885543Smrgstatic int
72809885543SmrgSetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value)
72909885543Smrg{
73009885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
73109885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
73209885543Smrg
73309885543Smrg    if (i == XV_ENCODING) {
73409885543Smrg	int norm;
73509885543Smrg	int input;
73609885543Smrg	int channel;
73709885543Smrg	norm = pPort->norm[value];
73809885543Smrg	input = pPort->input[value];
73909885543Smrg	channel = pPort->channel[value];
74009885543Smrg
7417104f784Smrg	DEBUG("SetAttribute XV_ENCODING: %d. norm=%d input=%d channel=%d\n",
7427104f784Smrg	      value, norm, input, channel);
74309885543Smrg
74409885543Smrg	/* set video norm */
74509885543Smrg	if (!xf86I2CWriteVec(&(pPort->I2CDev), SAA7111VideoStd[norm],
74609885543Smrg			     ENTRIES(SAA7111VideoStd[norm]) / 2)) {
74709885543Smrg	    return XvBadAlloc;
74809885543Smrg	}
74909885543Smrg	/* set video input format and channel */
75009885543Smrg	if (input == VID_COMPOSITE) {
75109885543Smrg	    if (!xf86I2CWriteVec(&(pPort->I2CDev),
75209885543Smrg				 SAA7111CompositeChannelSelect[channel],
75309885543Smrg				 ENTRIES(SAA7111CompositeChannelSelect[channel]) / 2)) {
75409885543Smrg		return XvBadAlloc;
75509885543Smrg	    }
75609885543Smrg	} else {
75709885543Smrg	    if (!xf86I2CWriteVec(&(pPort->I2CDev),
75809885543Smrg				 SAA7111SVideoChannelSelect[channel],
75909885543Smrg				 ENTRIES(SAA7111SVideoChannelSelect[channel]) / 2)) {
76009885543Smrg		return XvBadAlloc;
76109885543Smrg	    }
76209885543Smrg	}
76309885543Smrg    } else if (i >= XV_CAPTURE_BRIGHTNESS && i <= XV_HUE) {
76409885543Smrg	int slave_adr = 0;
76509885543Smrg
76609885543Smrg	switch (i) {
76709885543Smrg
76809885543Smrg	case XV_CAPTURE_BRIGHTNESS:
7697104f784Smrg	    DEBUG("SetAttribute XV_BRIGHTNESS: %d\n", value);
77009885543Smrg	    slave_adr = 0x0a;
77109885543Smrg	    break;
77209885543Smrg
77309885543Smrg	case XV_CONTRAST:
7747104f784Smrg	    DEBUG("SetAttribute XV_CONTRAST: %d\n", value);
77509885543Smrg	    slave_adr = 0x0b;
77609885543Smrg	    break;
77709885543Smrg
77809885543Smrg	case XV_SATURATION:
7797104f784Smrg	    DEBUG("SetAttribute XV_SATURATION: %d\n", value);
78009885543Smrg	    slave_adr = 0x0c;
78109885543Smrg	    break;
78209885543Smrg
78309885543Smrg	case XV_HUE:
7847104f784Smrg	    DEBUG("SetAttribute XV_HUE: %d\n", value);
78509885543Smrg	    slave_adr = 0x0d;
78609885543Smrg	    break;
78709885543Smrg
78809885543Smrg	default:
78909885543Smrg	    return XvBadAlloc;
79009885543Smrg	}
79109885543Smrg	if (!xf86I2CWriteByte(&(pPort->I2CDev), slave_adr, (value & 0xff)))
79209885543Smrg	    return XvBadAlloc;
79309885543Smrg    } else {
79409885543Smrg	return BadMatch;
79509885543Smrg    }
79609885543Smrg
79709885543Smrg    /* debug: show registers */
79809885543Smrg    {
79909885543Smrg	I2CByte i2c_bytes[32];
800df9ffc95Smrg	int j;
80109885543Smrg	xf86I2CReadBytes(&(pPort->I2CDev), 0, i2c_bytes, 32);
8027104f784Smrg	DEBUG("SAA7111 Registers\n");
803df9ffc95Smrg	for (j=0; j<32; j++) {
804df9ffc95Smrg	    DEBUG("%02X=%02X ", j, i2c_bytes[j]);
805beef1b22Smrg	    if ((j&7) == 7) {
806beef1b22Smrg		DEBUG("\n");
807beef1b22Smrg	    }
80809885543Smrg	}
80909885543Smrg    }
81009885543Smrg
81109885543Smrg    return Success;
81209885543Smrg}
81309885543Smrg
81409885543Smrg
81509885543Smrg/******************************************************************************\
81609885543Smrg**									      **
81709885543Smrg**	V I D E O   M A N A G E M E N T					      **
81809885543Smrg**									      **
81909885543Smrg\******************************************************************************/
82009885543Smrg
82109885543Smrgstatic XF86VideoAdaptorPtr
82209885543SmrgSMI_SetupVideo(ScreenPtr pScreen)
82309885543Smrg{
824b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
82509885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
82609885543Smrg    SMI_PortPtr smiPortPtr;
82709885543Smrg    XF86VideoAdaptorPtr ptrAdaptor;
82809885543Smrg
8297104f784Smrg    ENTER();
83009885543Smrg
8317b58d2e0Smrg    ptrAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) +
83209885543Smrg		 sizeof(DevUnion) + sizeof(SMI_PortRec));
8337104f784Smrg    if (ptrAdaptor == NULL)
8347104f784Smrg	LEAVE(NULL);
83509885543Smrg
83609885543Smrg    ptrAdaptor->type = XvInputMask
83709885543Smrg#if SMI_USE_CAPTURE
83809885543Smrg		     | XvOutputMask
83909885543Smrg		     | XvVideoMask
84009885543Smrg#endif
84109885543Smrg		     | XvImageMask
84209885543Smrg		     | XvWindowMask
84309885543Smrg		     ;
84409885543Smrg
8457104f784Smrg    ptrAdaptor->flags = VIDEO_OVERLAID_IMAGES;
8467104f784Smrg    if (IS_MSOC(pSmi)) {
8477104f784Smrg	ptrAdaptor->name = "Silicon Motion MSOC Series Video Engine";
8487104f784Smrg    }
8497104f784Smrg    else
8507104f784Smrg	ptrAdaptor->name = "Silicon Motion Lynx Series Video Engine";
85109885543Smrg
85209885543Smrg    ptrAdaptor->nPorts = 1;
85309885543Smrg    ptrAdaptor->pPortPrivates = (DevUnion*) &ptrAdaptor[1];
85409885543Smrg    ptrAdaptor->pPortPrivates[0].ptr = (pointer) &ptrAdaptor->pPortPrivates[1];
85509885543Smrg
85609885543Smrg    smiPortPtr = (SMI_PortPtr) ptrAdaptor->pPortPrivates[0].ptr;
85709885543Smrg
85809885543Smrg    SMI_BuildEncodings(smiPortPtr);
85909885543Smrg    ptrAdaptor->nEncodings = smiPortPtr->nenc;
86009885543Smrg    ptrAdaptor->pEncodings = smiPortPtr->enc;
86109885543Smrg#if 0
862beef1b22Smrg    /* aaa what's this? */
86309885543Smrg	for (i = 0; i < nElems(SMI_VideoEncodings); i++)
86409885543Smrg	{
86509885543Smrg		SMI_VideoEncodings[i].width = pSmi->lcdWidth;
86609885543Smrg		SMI_VideoEncodings[i].height = pSmi->lcdHeight;
86709885543Smrg	}
86809885543Smrg#endif
86909885543Smrg
87009885543Smrg    ptrAdaptor->nFormats = nElems(SMI_VideoFormats);
87109885543Smrg    ptrAdaptor->pFormats = SMI_VideoFormats;
87209885543Smrg
87309885543Smrg    ptrAdaptor->nAttributes = nElems(SMI_VideoAttributes);
87409885543Smrg    ptrAdaptor->pAttributes = SMI_VideoAttributes;
87509885543Smrg
8767104f784Smrg    if (IS_MSOC(pSmi)) {
8777104f784Smrg	ptrAdaptor->nImages = nElems(SMI501_VideoImages);
8787104f784Smrg	ptrAdaptor->pImages = SMI501_VideoImages;
8797104f784Smrg    }
8807104f784Smrg    else {
8817104f784Smrg	ptrAdaptor->nImages = nElems(SMI_VideoImages);
8827104f784Smrg	ptrAdaptor->pImages = SMI_VideoImages;
8837104f784Smrg    }
88409885543Smrg
88509885543Smrg#if SMI_USE_CAPTURE
8867104f784Smrg    if (pSmi->Chipset == SMI_COUGAR3DR || IS_MSOC(pSmi))
88709885543Smrg	ptrAdaptor->PutVideo = NULL;
88809885543Smrg    else
88909885543Smrg	ptrAdaptor->PutVideo = SMI_PutVideo;
89009885543Smrg    ptrAdaptor->PutStill = NULL;
89109885543Smrg    ptrAdaptor->GetVideo = NULL;
89209885543Smrg    ptrAdaptor->GetStill = NULL;
89309885543Smrg#else
89409885543Smrg    ptrAdaptor->PutVideo = NULL;
89509885543Smrg    ptrAdaptor->PutStill = NULL;
89609885543Smrg    ptrAdaptor->GetVideo = NULL;
89709885543Smrg    ptrAdaptor->GetStill = NULL;
89809885543Smrg#endif
89909885543Smrg    ptrAdaptor->StopVideo = SMI_StopVideo;
90009885543Smrg    ptrAdaptor->SetPortAttribute = SMI_SetPortAttribute;
90109885543Smrg    ptrAdaptor->GetPortAttribute = SMI_GetPortAttribute;
90209885543Smrg    ptrAdaptor->QueryBestSize = SMI_QueryBestSize;
90309885543Smrg    ptrAdaptor->PutImage = SMI_PutImage;
90409885543Smrg    ptrAdaptor->QueryImageAttributes = SMI_QueryImageAttributes;
90509885543Smrg
90609885543Smrg    smiPortPtr->Attribute[XV_COLORKEY] = pSmi->videoKey;
90709885543Smrg    smiPortPtr->Attribute[XV_INTERLACED] = pSmi->interlaced;
90809885543Smrg    smiPortPtr->videoStatus = 0;
90909885543Smrg
91009885543Smrg#if 0
91109885543Smrg    /* aaa does not work ? */
91209885543Smrg    if (xf86I2CProbeAddress(pSmi->I2C, SAA7111))
9137104f784Smrg        LEAVE(NULL);
9147104f784Smrg    DEBUG("SAA7111 detected\n");
91509885543Smrg#endif
91609885543Smrg
91709885543Smrg    smiPortPtr->I2CDev.DevName = "SAA 7111A";
91809885543Smrg    smiPortPtr->I2CDev.SlaveAddr = SAA7111;
91909885543Smrg    smiPortPtr->I2CDev.pI2CBus = pSmi->I2C;
92009885543Smrg
9217104f784Smrg
9227104f784Smrg    if (!IS_MSOC(pSmi) && xf86I2CDevInit(&(smiPortPtr->I2CDev))) {
92309885543Smrg
92409885543Smrg	if (xf86I2CWriteVec(&(smiPortPtr->I2CDev), SAA7111InitData, ENTRIES(SAA7111InitData) / 2)) {
92509885543Smrg	    xvEncoding   = MAKE_ATOM(XV_ENCODING_NAME);
92609885543Smrg	    xvHue        = MAKE_ATOM(XV_HUE_NAME);
92709885543Smrg	    xvSaturation = MAKE_ATOM(XV_SATURATION_NAME);
92809885543Smrg	    xvContrast   = MAKE_ATOM(XV_CONTRAST_NAME);
92909885543Smrg
93009885543Smrg	    xvInterlaced = MAKE_ATOM(XV_INTERLACED_NAME);
931beef1b22Smrg	    DEBUG("SAA7111 initialized\n");
93209885543Smrg
93309885543Smrg	} else {
93409885543Smrg	    xf86DestroyI2CDevRec(&(smiPortPtr->I2CDev),FALSE);
93509885543Smrg	    smiPortPtr->I2CDev.SlaveAddr = 0;
93609885543Smrg	}
93709885543Smrg    } else
93809885543Smrg	smiPortPtr->I2CDev.SlaveAddr = 0;
93909885543Smrg
94009885543Smrg#if defined(REGION_NULL)
94109885543Smrg    REGION_NULL(pScreen, &smiPortPtr->clip);
94209885543Smrg#else
94309885543Smrg    REGION_INIT(pScreen, &smiPortPtr->clip, NullBox, 0);
94409885543Smrg#endif
94509885543Smrg
94609885543Smrg    pSmi->ptrAdaptor = ptrAdaptor;
94709885543Smrg    pSmi->BlockHandler = pScreen->BlockHandler;
94809885543Smrg    pScreen->BlockHandler = SMI_BlockHandler;
94909885543Smrg
95009885543Smrg    xvColorKey   = MAKE_ATOM(XV_COLORKEY_NAME);
95109885543Smrg    xvBrightness = MAKE_ATOM(XV_BRIGHTNESS_NAME);
95209885543Smrg    xvCapBrightness = MAKE_ATOM(XV_CAPTURE_BRIGHTNESS_NAME);
95309885543Smrg
95409885543Smrg    SMI_ResetVideo(pScrn);
9557104f784Smrg
9567104f784Smrg    LEAVE(ptrAdaptor);
95709885543Smrg}
95809885543Smrg
95909885543Smrg
96009885543Smrgstatic void
96109885543SmrgSMI_ResetVideo(ScrnInfoPtr pScrn)
96209885543Smrg{
96309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
96409885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
96509885543Smrg    int r, g, b;
96609885543Smrg
9677104f784Smrg    ENTER();
96809885543Smrg
96909885543Smrg    SetAttr(pScrn, XV_ENCODING, 0);     /* Encoding = pal-composite-0 */
97009885543Smrg    SetAttr(pScrn, XV_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */
97109885543Smrg    SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */
97209885543Smrg    SetAttr(pScrn, XV_CONTRAST, 71);    /* Contrast = 71 (CCIR level) */
97309885543Smrg    SetAttr(pScrn, XV_SATURATION, 64);  /* Color saturation = 64 (CCIR level) */
97409885543Smrg    SetAttr(pScrn, XV_HUE, 0);          /* Hue = 0 */
97509885543Smrg
97609885543Smrg    switch (pScrn->depth) {
97709885543Smrg    case 8:
97809885543Smrg	SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0x00FF);
97909885543Smrg	SetKeyReg(pSmi, FPR08, 0);
98009885543Smrg	break;
98109885543Smrg    case 15:
98209885543Smrg    case 16:
98309885543Smrg	SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0xFFFF);
98409885543Smrg	SetKeyReg(pSmi, FPR08, 0);
98509885543Smrg	break;
98609885543Smrg    default:
98709885543Smrg        r = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.red) >> pScrn->offset.red;
98809885543Smrg        g = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.green) >> pScrn->offset.green;
98909885543Smrg        b = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.blue) >> pScrn->offset.blue;
99009885543Smrg	SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3));
99109885543Smrg	SetKeyReg(pSmi, FPR08, 0);
99209885543Smrg	break;
99309885543Smrg    }
99409885543Smrg
99509885543Smrg    SetKeyReg(pSmi, FPR5C, 0xEDEDED | (pPort->Attribute[XV_BRIGHTNESS] << 24));
99609885543Smrg
9977104f784Smrg    LEAVE();
99809885543Smrg}
99909885543Smrg
100009885543Smrg
100109885543Smrg#if SMI_USE_CAPTURE
100209885543Smrgstatic int
100309885543SmrgSMI_PutVideo(
100409885543Smrg	ScrnInfoPtr	pScrn,
100509885543Smrg	short		vid_x,
100609885543Smrg	short		vid_y,
100709885543Smrg	short		drw_x,
100809885543Smrg	short		drw_y,
100909885543Smrg	short		vid_w,
101009885543Smrg	short		vid_h,
101109885543Smrg	short		drw_w,
101209885543Smrg	short		drw_h,
101309885543Smrg	RegionPtr	clipBoxes,
101409885543Smrg	pointer		data,
101509885543Smrg	DrawablePtr	pDraw
101609885543Smrg)
101709885543Smrg{
101809885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) data;
101909885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
102009885543Smrg    CARD32 vid_pitch, vid_address;
102109885543Smrg    CARD32 vpr00, cpr00;
102209885543Smrg    int xscale, yscale;
102309885543Smrg    BoxRec dstBox;
102409885543Smrg    INT32 x1, y1, x2, y2;
102509885543Smrg    int norm;
102609885543Smrg    int size, width, height, fbPitch;
102709885543Smrg    int top, left;
10287104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
10297104f784Smrg    xf86CrtcPtr crtc;
103009885543Smrg
10317104f784Smrg    ENTER();
103209885543Smrg
10337104f784Smrg    DEBUG("Interlaced Video %d\n", pPort->Attribute[XV_INTERLACED]);
103409885543Smrg
103509885543Smrg    if (!pPort->Attribute[XV_INTERLACED]) {
103609885543Smrg	/* no interlace: lines will be doubled */
103709885543Smrg	vid_h /= 2;
103809885543Smrg    }
103909885543Smrg
104009885543Smrg    /* field start aaa*/
104109885543Smrg    norm = pPort->norm[pPort->Attribute[XV_ENCODING]];
104209885543Smrg    vid_x += VideoNorms[norm].HStart;
104309885543Smrg    vid_y += VideoNorms[norm].VStart;
104409885543Smrg    /* only even values allowed (UV-phase) */
104509885543Smrg    vid_x &= ~1;
104609885543Smrg
10477104f784Smrg    DEBUG("vid_x=%d vid_y=%d drw_x=%d drw_y=%d  "
10487104f784Smrg	  "vid_w=%d vid_h=%d drw_w=%d drw_h=%d\n",
10497104f784Smrg	  vid_x, vid_y, drw_x, drw_y, vid_w, vid_h, drw_w, drw_h);
105009885543Smrg
105109885543Smrg    x1 = vid_x;
105209885543Smrg    y1 = vid_y;
105309885543Smrg    x2 = vid_x + vid_w;
105409885543Smrg    y2 = vid_y + vid_h;
105509885543Smrg
105609885543Smrg    width = vid_w;
105709885543Smrg    height = vid_h;
105809885543Smrg
105909885543Smrg    dstBox.x1 = drw_x;
106009885543Smrg    dstBox.y1 = drw_y;
106109885543Smrg    dstBox.x2 = drw_x + drw_w;
106209885543Smrg    dstBox.y2 = drw_y + drw_h;
106309885543Smrg
10647104f784Smrg    if(!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
10657104f784Smrg	LEAVE(Success);
10667104f784Smrg
10677b58d2e0Smrg    if (crtc != crtcConf->crtc[0])
10687104f784Smrg	LEAVE(Success);
106909885543Smrg
10707104f784Smrg    /* Transform dstBox to the CRTC coordinates */
10717104f784Smrg    dstBox.x1 -= crtc->x;
10727104f784Smrg    dstBox.y1 -= crtc->y;
10737104f784Smrg    dstBox.x2 -= crtc->x;
10747104f784Smrg    dstBox.y2 -= crtc->y;
107509885543Smrg
10767104f784Smrg    DEBUG("Clip: x1=%d y1=%d x2=%d y2=%d\n",  x1 >> 16, y1 >> 16, x2 >> 16, y2 >> 16);
107709885543Smrg
107809885543Smrg    vid_pitch = (vid_w * 2 + 7) & ~7;
107909885543Smrg
108009885543Smrg    vpr00 = READ_VPR(pSmi, 0x00) & ~0x0FF000FF;
108109885543Smrg    cpr00 = READ_CPR(pSmi, 0x00) & ~0x000FFF00;
108209885543Smrg
108309885543Smrg    /* vpr00:
108409885543Smrg       Bit 2..0   = 6: Video Window I Format                    = YUV4:2:2
108509885543Smrg       Bit 3      = 1: Video Window I Enable                    = enabled
108609885543Smrg       Bit 4      = 0: Video Window I YUV Averaging             = disabled
108709885543Smrg       Bit 5      = 0: Video Window I Hor. Replication          = disabled
108809885543Smrg       Bit 6      = 0: Video Window I data doubling             = disabled
108909885543Smrg       Bit 14..8  = 0: Video Window II                          = disabled
109009885543Smrg       Bit 18..16 = 0: Graphics Data Format                     = 8-bit index
109109885543Smrg       Bit 19     = 0: Top Video Window Select                  = window I
109209885543Smrg       Bit 20     = 1: Color Key for Window I                   = enabled
109309885543Smrg       Bit 21     = 0: Vertical Interpolation                   = s. below
109409885543Smrg       Bit 22     = 0: Flicker Reduction for TV Modes           = disabled
109509885543Smrg       Bit 23     = 0: Fixed Vertical Interpolation             = disabled
109609885543Smrg       Bit 24     = 1: Select Video Window I Source Addr        =
109709885543Smrg       Bit 25     = 0: Enable V0FIFO to fetch 8-Bit color data  = disabled
109809885543Smrg       Bit 26     = 0:
109909885543Smrg       Bit 27     = 1: Color Key for Window II                  = disabled
110009885543Smrg       Bit 31..28 = reserved
110109885543Smrg    */
110209885543Smrg    if (pPort->Attribute[XV_INTERLACED]) {
110309885543Smrg	/*
110409885543Smrg	  Bit 21     = 0: Vertical Interpolation                   = disabled
110509885543Smrg	  Bit 24     = 0: Select Video Window I Source Addr        = 0
110609885543Smrg	*/
110709885543Smrg	vpr00 |= 0x0010000E;
110809885543Smrg    } else {
110909885543Smrg	/*
1110e4f6584cSmrg	  Bit 21     = 1: Vertical Interpolation                   = enabled
111109885543Smrg	  Bit 24     = 1: Select Video Window I Source Addr        = 1
111209885543Smrg	  1= Video window I source addr = capture port buffer ?
111309885543Smrg	*/
111409885543Smrg	vpr00 |= 0x0130000E;
111509885543Smrg    }
111609885543Smrg
111709885543Smrg    /* cpr00:
111809885543Smrg       Bit 0      = 1: Video Capture Enable                     = enabled
1119beef1b22Smrg       Bit 8      = 0: Capture Control                          = continuous
112009885543Smrg       Bit 9      = 0: Double Buffer Enable                     = s. below
112109885543Smrg       Bit 10     = 0: Interlace Data Capture                   = s. below
112209885543Smrg       Bit 13..11 = 0: Frame Skip Enable                        = s. below
112309885543Smrg       Bit 15..14 = 0: Video Capture Input Format               = YUV4:2:2
112409885543Smrg       Bit 17..16 = 0: Enable Hor. Reduction                    = s. below
112509885543Smrg       Bit 19..18 = 0: Enable Vert. Reduction                   = s. below
112609885543Smrg       Bit 21..20 = 0: Enable Hor. Filtering                    = s. below
112709885543Smrg       Bit 22     = 0: HREF Polarity                            = high active
112809885543Smrg       Bit 23     = 0: VREF Polarity                            = high active
112909885543Smrg       Bit 24     = 1: Field Detection Method VSYNC edge        = rising
113009885543Smrg    */
113109885543Smrg    if (pPort->Attribute[XV_INTERLACED]) {
113209885543Smrg	/*
113309885543Smrg	  Bit 9      = 1: Double Buffer Enable                  = enabled
113409885543Smrg	  Bit 10     = 1: Interlace Data Capture                = enabled
113509885543Smrg	  Bit 13..11 = 0: Frame Skip Enable                     = no skip
113609885543Smrg	*/
113709885543Smrg	cpr00 |= 0x01000601;
113809885543Smrg    } else {
113909885543Smrg	/*
114009885543Smrg	  Bit 9      = 0: Double Buffer Enable                  = disabled
114109885543Smrg	  Bit 10     = 0: Interlace Data Capture                = disabled
114209885543Smrg	  Bit 13..11 = 010: Frame Skip Enable                   = skip every other frame
114309885543Smrg	*/
11447104f784Smrg	cpr00 |= 0x01001001;
114509885543Smrg    }
114609885543Smrg
114709885543Smrg    if (pSmi->ByteSwap)
114809885543Smrg	cpr00 |= 0x00004000;
114909885543Smrg
11507104f784Smrg    fbPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15;
115109885543Smrg
115209885543Smrg    if (vid_w <= drw_w) {
115309885543Smrg	xscale = (256 * vid_w / drw_w) & 0xFF;
115409885543Smrg    } else if (vid_w / 2 <= drw_w) {
115509885543Smrg	xscale = (128 * vid_w / drw_w) & 0xFF;
115609885543Smrg	width /= 2;
115709885543Smrg	vid_pitch /= 2;
115809885543Smrg	cpr00 |= 0x00010000;
115909885543Smrg    } else if (vid_w / 4 <= drw_w) {
116009885543Smrg	xscale = (64 * vid_w / drw_w) & 0xFF;
116109885543Smrg	width /= 4;
116209885543Smrg	vid_pitch /= 4;
116309885543Smrg	cpr00 |= 0x00020000;
116409885543Smrg    } else {
116509885543Smrg	xscale = 0;
116609885543Smrg	width /= 4;
116709885543Smrg	vid_pitch /= 4;
116809885543Smrg	cpr00 |= 0x00020000;
116909885543Smrg    }
117009885543Smrg
117109885543Smrg    if (vid_h <= drw_h) {
117209885543Smrg	yscale = (256 * vid_h / drw_h) & 0xFF;
117309885543Smrg    } else if (vid_h / 2 <= drw_h) {
117409885543Smrg	yscale = (128 * vid_h / drw_h) & 0xFF;
117509885543Smrg	height /= 2;
117609885543Smrg	cpr00 |= 0x00040000;
117709885543Smrg    } else if (vid_h / 4 <= drw_h) {
117809885543Smrg	yscale = (64 * vid_h / drw_h) & 0xFF;
117909885543Smrg	height /= 4;
118009885543Smrg	cpr00 |= 0x00080000;
118109885543Smrg    } else {
118209885543Smrg	yscale = 0;
118309885543Smrg	height /= 4;
118409885543Smrg	cpr00 |= 0x00080000;
118509885543Smrg    }
118609885543Smrg
118709885543Smrg    do {
118809885543Smrg	size = vid_pitch * height;
11897104f784Smrg	DEBUG("SMI_AllocateMemory: vid_pitch=%d height=%d size=%d\n",
11907104f784Smrg	      vid_pitch, height, size);
119109885543Smrg	pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size);
119209885543Smrg        if (pPort->video_offset == 0) {
119309885543Smrg	    if ((cpr00 & 0x000C0000) == 0) {
119409885543Smrg		/* height -> 1/2 height */
119509885543Smrg		yscale = (128 * vid_h / drw_h) & 0xFF;
119609885543Smrg		height = vid_h / 2;
119709885543Smrg		cpr00 |= 0x00040000;
119809885543Smrg	    } else if (cpr00 & 0x00040000) {
119909885543Smrg		/* 1/2 height -> 1/4 height */
120009885543Smrg		yscale = (64 * vid_h / drw_h) & 0xFF;
120109885543Smrg		height = vid_h / 4;
120209885543Smrg		cpr00 ^= 0x000C0000;
120309885543Smrg	    } else {
120409885543Smrg		/* 1/4 height */
120509885543Smrg		if ((cpr00 & 0x00030000) == 0) {
120609885543Smrg		    /* width -> 1/2 width */
120709885543Smrg		    xscale = (128 * vid_w / drw_w) & 0xFF;
120809885543Smrg		    width = vid_w / 2;
120909885543Smrg		    cpr00 |= 0x00010000;
121009885543Smrg		} else if (cpr00 & 0x00010000) {
121109885543Smrg		    /* 1/2 width -> 1/4 width */
121209885543Smrg		    xscale = (64 * vid_w / drw_w) & 0xFF;
121309885543Smrg		    width = vid_w / 4;
121409885543Smrg		    cpr00 ^= 0x00030000;
121509885543Smrg		} else {
12167104f784Smrg		    DEBUG("allocate error\n");
12177104f784Smrg		    LEAVE(BadAlloc);
121809885543Smrg		}
121909885543Smrg	    }
122009885543Smrg	}
122109885543Smrg    } while (pPort->video_offset == 0);
122209885543Smrg
12237104f784Smrg    DEBUG("xscale==%d yscale=%d width=%d height=%d\n",
12247104f784Smrg	  xscale, yscale, width, height);
122509885543Smrg
1226beef1b22Smrg    /* aaa what's this                    ----------------------v ?
122709885543Smrg    vid_address = (pPort->area->box.y1 * fbPitch) + ((y1 >> 16) * vid_pitch);*/
122809885543Smrg    vid_address = pPort->video_offset;
122909885543Smrg
12307104f784Smrg    DEBUG("test RegionsEqual\n");
123109885543Smrg    if (!REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes))
123209885543Smrg    {
123309885543Smrg	DEBUG((VERBLEV, "RegionCopy\n"));
123409885543Smrg        REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes);
12357104f784Smrg	DEBUG("FillKey\n");
123609885543Smrg	xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], clipBoxes);
123709885543Smrg
123809885543Smrg    }
123909885543Smrg
124009885543Smrg    left = x1 >> 16;
124109885543Smrg    top = y1 >> 16;
124209885543Smrg    width = (x2 - x1) >> 16;
124309885543Smrg    height = (y2 - y1) >> 16;
124409885543Smrg
12457104f784Smrg    if (!IS_MSOC(pSmi))
12467104f784Smrg	VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
12477104f784Smrg		      0x21,
12487104f784Smrg		      VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
12497104f784Smrg				   0x21) & ~0x04);
125009885543Smrg    WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) | 0x00200000);
125109885543Smrg    /* Video Window I Left and Top Boundaries */
125209885543Smrg    WRITE_VPR(pSmi, 0x14, dstBox.x1 + (dstBox.y1 << 16));
125309885543Smrg    /* Video Window I Right and Bottom Boundaries */
125409885543Smrg    WRITE_VPR(pSmi, 0x18, dstBox.x2 + (dstBox.y2 << 16));
125509885543Smrg    /* Video Window I Source Width and Offset */
125609885543Smrg    WRITE_VPR(pSmi, 0x20, (vid_pitch / 8) + ((vid_pitch / 8) << 16));
125709885543Smrg    /* Video Window I Stretch Factor */
125809885543Smrg    WRITE_VPR(pSmi, 0x24, (xscale << 8) + yscale);
125909885543Smrg
126009885543Smrg    if (pPort->Attribute[XV_INTERLACED]) {
126109885543Smrg	/* Video Window II Left and Top Boundaries */
126209885543Smrg	WRITE_VPR(pSmi, 0x28, dstBox.x1 + (dstBox.y1 << 16));
126309885543Smrg	/* Video Window II Right and Bottom Boundaries */
126409885543Smrg	WRITE_VPR(pSmi, 0x2C, dstBox.x2 + (dstBox.y2 << 16));
126509885543Smrg	/* Video Window II Source Width and Offset */
126609885543Smrg	WRITE_VPR(pSmi, 0x34, (vid_pitch / 8) + ((vid_pitch / 8) << 16));
126709885543Smrg	/* Video Window II Stretch Factor */
126809885543Smrg	WRITE_VPR(pSmi, 0x38, (xscale << 8) + yscale);
126909885543Smrg
127009885543Smrg	/* Video Window I Source Start Address */
127109885543Smrg	WRITE_VPR(pSmi, 0x1C, vid_address / 8);
127209885543Smrg	/* Video Window II Source Start Address */
127309885543Smrg	WRITE_VPR(pSmi, 0x30, vid_address / 8);
127409885543Smrg
127509885543Smrg	/* Video Window I Source Start Address */
127609885543Smrg	WRITE_VPR(pSmi, 0x48, vid_address / 8);
127709885543Smrg	/* Video Window II Source Start Address */
127809885543Smrg	WRITE_VPR(pSmi, 0x4C, vid_address / 8 + vid_pitch / 8);
127909885543Smrg
128009885543Smrg	/* Video Source Clipping Control */
128109885543Smrg	WRITE_CPR(pSmi, 0x04, left + ((top/2) << 16));
128209885543Smrg	/* Video Source Capture Size Control */
128309885543Smrg	WRITE_CPR(pSmi, 0x08, width + ((height/2) << 16));
128409885543Smrg	/* Capture Port Buffer I Source Start Address */
128509885543Smrg	WRITE_CPR(pSmi, 0x0C, vid_address / 8);
128609885543Smrg	/* Capture Port Buffer II Source Start Address */
128709885543Smrg	WRITE_CPR(pSmi, 0x10, vid_address / 8 + vid_pitch / 8);
128809885543Smrg	/* Capture Port Source Offset Address */
128909885543Smrg	WRITE_CPR(pSmi, 0x14, 2*(vid_pitch / 8) + ((2*(vid_pitch / 8)) << 16));
129009885543Smrg    } else {
129109885543Smrg	/* Video Source Clipping Control */
129209885543Smrg	WRITE_CPR(pSmi, 0x04, left + (top << 16));
129309885543Smrg	/* Video Source Capture Size Control */
129409885543Smrg	WRITE_CPR(pSmi, 0x08, width + (height << 16));
129509885543Smrg	/* Capture Port Buffer I Source Start Address */
129609885543Smrg	WRITE_CPR(pSmi, 0x0C, vid_address / 8);
129709885543Smrg	/* Capture Port Buffer II Source Start Address */
129809885543Smrg	WRITE_CPR(pSmi, 0x10, vid_address / 8);
129909885543Smrg	/* Capture Port Source Offset Address */
130009885543Smrg	WRITE_CPR(pSmi, 0x14, (vid_pitch / 8) + ((vid_pitch / 8) << 16));
130109885543Smrg    }
130209885543Smrg
130309885543Smrg    WRITE_CPR(pSmi, 0x00, cpr00);
130409885543Smrg    WRITE_VPR(pSmi, 0x00, vpr00);
130509885543Smrg
130609885543Smrg    pPort->videoStatus = CLIENT_VIDEO_ON;
13077104f784Smrg    DEBUG("SMI_PutVideo success\n");
13087104f784Smrg
13097104f784Smrg    LEAVE(Success);
131009885543Smrg}
131109885543Smrg#endif
131209885543Smrg
131309885543Smrg
131409885543Smrgstatic void
131509885543SmrgSMI_StopVideo(
131609885543Smrg	ScrnInfoPtr	pScrn,
131709885543Smrg	pointer		data,
131809885543Smrg	Bool		shutdown
131909885543Smrg)
132009885543Smrg{
132109885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) data;
132209885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
132309885543Smrg
13247104f784Smrg    ENTER();
132509885543Smrg
132609885543Smrg    REGION_EMPTY(pScrn->pScreen, &pPort->clip);
132709885543Smrg
132809885543Smrg    if (shutdown) {
132909885543Smrg	if (pPort->videoStatus & CLIENT_VIDEO_ON) {
13307104f784Smrg	    if (pSmi->Chipset == SMI_COUGAR3DR)
133109885543Smrg		WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE));
13327104f784Smrg	    else if (IS_MSOC(pSmi))
13337104f784Smrg		WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004);
13347104f784Smrg	    else
133509885543Smrg		WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x01000008);
133609885543Smrg#if SMI_USE_CAPTURE
13377104f784Smrg	    if (!IS_MSOC(pSmi) && pSmi->Chipset != SMI_COUGAR3DR) {
133809885543Smrg		WRITE_CPR(pSmi, 0x00, READ_CPR(pSmi, 0x00) & ~0x00000001);
133909885543Smrg		WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) & ~0x00F00000);
134009885543Smrg	    }
134109885543Smrg#endif
134209885543Smrg	}
134309885543Smrg        if (pPort->video_memory != NULL) {
134409885543Smrg            SMI_FreeMemory(pScrn, pPort->video_memory);
134509885543Smrg            pPort->video_memory = NULL;
134609885543Smrg	}
134709885543Smrg        pPort->videoStatus = 0;
134809885543Smrg        /* pPort->i2cDevice = 0;aaa*/
134909885543Smrg    } else {
135009885543Smrg        if (pPort->videoStatus & CLIENT_VIDEO_ON) {
135109885543Smrg            pPort->videoStatus |= OFF_TIMER;
135209885543Smrg            pPort->offTime = currentTime.milliseconds + OFF_DELAY;
135309885543Smrg	}
135409885543Smrg    }
135509885543Smrg
13567104f784Smrg    LEAVE();
135709885543Smrg}
135809885543Smrg
135909885543Smrgstatic int
136009885543SmrgSMI_SetPortAttribute(
136109885543Smrg	ScrnInfoPtr	pScrn,
136209885543Smrg	Atom		attribute,
136309885543Smrg	INT32		value,
136409885543Smrg	pointer		data
136509885543Smrg)
136609885543Smrg{
136709885543Smrg    int res;
136809885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) data;
136909885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
137009885543Smrg
13717104f784Smrg    ENTER();
137209885543Smrg
137309885543Smrg    if (attribute == xvColorKey) {
137409885543Smrg	int r, g, b;
137509885543Smrg
137609885543Smrg        pPort->Attribute[XV_COLORKEY] = value;
137709885543Smrg	switch (pScrn->depth) {
137809885543Smrg	case 8:
137909885543Smrg	    SetKeyReg(pSmi, FPR04, value & 0x00FF);
138009885543Smrg	    break;
138109885543Smrg	case 15:
138209885543Smrg	case 16:
138309885543Smrg	    SetKeyReg(pSmi, FPR04, value & 0xFFFF);
138409885543Smrg	    break;
138509885543Smrg	default:
138609885543Smrg	    r = (value & pScrn->mask.red) >> pScrn->offset.red;
138709885543Smrg	    g = (value & pScrn->mask.green) >> pScrn->offset.green;
138809885543Smrg	    b = (value & pScrn->mask.blue) >> pScrn->offset.blue;
138909885543Smrg	    SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3));
139009885543Smrg	    break;
139109885543Smrg	}
139209885543Smrg	res = Success;
139309885543Smrg    } else if (attribute == xvInterlaced) {
139409885543Smrg        pPort->Attribute[XV_INTERLACED] = (value != 0);
139509885543Smrg	res = Success;
139609885543Smrg    } else if (attribute == xvEncoding) {
139709885543Smrg        res = SetAttr(pScrn, XV_ENCODING, value);
139809885543Smrg    } else if (attribute == xvBrightness) {
139909885543Smrg        res = SetAttr(pScrn, XV_BRIGHTNESS, value);
140009885543Smrg    } else if (attribute == xvCapBrightness) {
140109885543Smrg        res = SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, value);
140209885543Smrg    } else if (attribute == xvContrast) {
140309885543Smrg        res = SetAttr(pScrn, XV_CONTRAST, value);
140409885543Smrg    } else if (attribute == xvSaturation) {
140509885543Smrg        res = SetAttr(pScrn, XV_SATURATION, value);
140609885543Smrg    } else if (attribute == xvHue) {
140709885543Smrg        res = SetAttr(pScrn, XV_HUE, value);
140809885543Smrg    } else {
140909885543Smrg        res = BadMatch;
141009885543Smrg    }
141109885543Smrg
14127104f784Smrg    LEAVE(res);
141309885543Smrg}
141409885543Smrg
141509885543Smrg
141609885543Smrgstatic int
141709885543SmrgSMI_GetPortAttribute(
141809885543Smrg	ScrnInfoPtr	pScrn,
141909885543Smrg	Atom		attribute,
142009885543Smrg	INT32		*value,
142109885543Smrg	pointer		data
142209885543Smrg)
142309885543Smrg{
142409885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) data;
142509885543Smrg
14267104f784Smrg    ENTER();
142709885543Smrg    if (attribute == xvEncoding)
142809885543Smrg        *value = pPort->Attribute[XV_ENCODING];
142909885543Smrg    else if (attribute == xvBrightness)
143009885543Smrg        *value = pPort->Attribute[XV_BRIGHTNESS];
143109885543Smrg    else if (attribute == xvCapBrightness)
143209885543Smrg        *value = pPort->Attribute[XV_CAPTURE_BRIGHTNESS];
143309885543Smrg    else if (attribute == xvContrast)
143409885543Smrg        *value = pPort->Attribute[XV_CONTRAST];
143509885543Smrg    else if (attribute == xvSaturation)
143609885543Smrg        *value = pPort->Attribute[XV_SATURATION];
143709885543Smrg    else if (attribute == xvHue)
143809885543Smrg        *value = pPort->Attribute[XV_HUE];
143909885543Smrg    else if (attribute == xvColorKey)
144009885543Smrg        *value = pPort->Attribute[XV_COLORKEY];
14417104f784Smrg    else
14427104f784Smrg	LEAVE(BadMatch);
144309885543Smrg
14447104f784Smrg    LEAVE(Success);
144509885543Smrg}
144609885543Smrg
144709885543Smrg
144809885543Smrgstatic void
144909885543SmrgSMI_QueryBestSize(
145009885543Smrg	ScrnInfoPtr		pScrn,
145109885543Smrg	Bool			motion,
145209885543Smrg	short			vid_w,
145309885543Smrg	short			vid_h,
145409885543Smrg	short			drw_w,
145509885543Smrg	short			drw_h,
145609885543Smrg	unsigned int	*p_w,
145709885543Smrg	unsigned int	*p_h,
145809885543Smrg	pointer			data
145909885543Smrg)
146009885543Smrg{
146109885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
146209885543Smrg
14637104f784Smrg    ENTER();
146409885543Smrg
146509885543Smrg    *p_w = min(drw_w, pSmi->lcdWidth);
146609885543Smrg    *p_h = min(drw_h, pSmi->lcdHeight);
146709885543Smrg
14687104f784Smrg    LEAVE();
146909885543Smrg}
147009885543Smrg
147109885543Smrg
147209885543Smrgstatic int
147309885543SmrgSMI_PutImage(
147409885543Smrg	ScrnInfoPtr		pScrn,
147509885543Smrg	short			src_x,
147609885543Smrg	short			src_y,
147709885543Smrg	short			drw_x,
147809885543Smrg	short			drw_y,
147909885543Smrg	short			src_w,
148009885543Smrg	short			src_h,
148109885543Smrg	short			drw_w,
148209885543Smrg	short			drw_h,
14837104f784Smrg	int			id,
14847104f784Smrg	unsigned char		*buf,
148509885543Smrg	short			width,
148609885543Smrg	short			height,
148709885543Smrg	Bool			sync,
148809885543Smrg	RegionPtr		clipBoxes,
148909885543Smrg	pointer			data,
149009885543Smrg	DrawablePtr		pDraw
149109885543Smrg)
149209885543Smrg{
149309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
149409885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
149509885543Smrg    INT32 x1, y1, x2, y2;
149609885543Smrg    int bpp = 0;
149709885543Smrg    int srcPitch, srcPitch2 = 0, dstPitch, size;
149809885543Smrg    BoxRec dstBox;
149909885543Smrg    CARD32 offset, offset2 = 0, offset3 = 0, tmp;
150009885543Smrg    int left, top, nPixels, nLines;
150109885543Smrg    unsigned char *dstStart;
15027104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
15037104f784Smrg    xf86CrtcPtr crtc;
150409885543Smrg
15057104f784Smrg    ENTER();
150609885543Smrg
150709885543Smrg    x1 = src_x;
150809885543Smrg    y1 = src_y;
150909885543Smrg    x2 = src_x + src_w;
151009885543Smrg    y2 = src_y + src_h;
151109885543Smrg
151209885543Smrg    dstBox.x1 = drw_x;
151309885543Smrg    dstBox.y1 = drw_y;
151409885543Smrg    dstBox.x2 = drw_x + drw_w;
151509885543Smrg    dstBox.y2 = drw_y + drw_h;
151609885543Smrg
15177104f784Smrg    if (pSmi->CSCVideo) {
15187104f784Smrg	if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
15197104f784Smrg				   width, height))
15207104f784Smrg	    LEAVE(Success);
152109885543Smrg    }
15227104f784Smrg    else {
15237104f784Smrg	if (!xf86_crtc_clip_video_helper(pScrn, &crtc, crtcConf->crtc[0], &dstBox,
15247104f784Smrg					 &x1, &x2, &y1, &y2, clipBoxes,
15257104f784Smrg					 width, height))
15267104f784Smrg	    LEAVE(Success);
152709885543Smrg
15287b58d2e0Smrg	if (!crtc)
15297b58d2e0Smrg	    LEAVE(Success);
15307b58d2e0Smrg
15317104f784Smrg	/* Transform dstBox to the CRTC coordinates */
15327104f784Smrg	dstBox.x1 -= crtc->x;
15337104f784Smrg	dstBox.y1 -= crtc->y;
15347104f784Smrg	dstBox.x2 -= crtc->x;
15357104f784Smrg	dstBox.y2 -= crtc->y;
15367104f784Smrg    }
153709885543Smrg
153809885543Smrg    switch (id) {
153909885543Smrg    case FOURCC_YV12:
15407104f784Smrg    case FOURCC_I420:
154109885543Smrg	srcPitch  = (width + 3) & ~3;
154209885543Smrg	offset2   = srcPitch * height;
154309885543Smrg	srcPitch2 = ((width >> 1) + 3) & ~3;
154409885543Smrg	offset3   = offset2 + (srcPitch2 * (height >> 1));
15457104f784Smrg	if (pSmi->CSCVideo)
15467104f784Smrg	    dstPitch  = (((width >> 1) + 15) & ~15) << 1;
15477104f784Smrg	else
15487104f784Smrg	    dstPitch  = ((width << 1) + 15) & ~15;
154909885543Smrg	break;
155009885543Smrg    case FOURCC_RV24:
155109885543Smrg	bpp = 3;
155209885543Smrg	srcPitch = width * bpp;
155309885543Smrg	dstPitch = (srcPitch + 15) & ~15;
155409885543Smrg	break;
155509885543Smrg    case FOURCC_RV32:
155609885543Smrg	bpp = 4;
155709885543Smrg	srcPitch = width * bpp;
155809885543Smrg	dstPitch = (srcPitch + 15) & ~15;
155909885543Smrg	break;
156009885543Smrg    case FOURCC_YUY2:
156109885543Smrg    case FOURCC_RV15:
156209885543Smrg    case FOURCC_RV16:
156309885543Smrg    default:
156409885543Smrg	bpp = 2;
156509885543Smrg	srcPitch = width * bpp;
156609885543Smrg	dstPitch = (srcPitch + 15) & ~15;
156709885543Smrg	break;
156809885543Smrg    }
156909885543Smrg
157009885543Smrg    size = dstPitch * height;
157109885543Smrg    pPort->video_offset = SMI_AllocateMemory(pScrn, &pPort->video_memory, size);
15727104f784Smrg    if (pPort->video_memory == NULL)
15737104f784Smrg	LEAVE(BadAlloc);
157409885543Smrg
157509885543Smrg    top = y1 >> 16;
157609885543Smrg    left = (x1 >> 16) & ~1;
157709885543Smrg    nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left;
157809885543Smrg    left *= bpp;
157909885543Smrg
158009885543Smrg    offset = pPort->video_offset + (top * dstPitch);
158109885543Smrg    dstStart = pSmi->FBBase + offset + left;
158209885543Smrg
158309885543Smrg    switch(id) {
158409885543Smrg    case FOURCC_YV12:
158509885543Smrg    case FOURCC_I420:
158609885543Smrg	top &= ~1;
158709885543Smrg	tmp = ((top >> 1) * srcPitch2) + (left >> 2);
158809885543Smrg	offset2 += tmp;
158909885543Smrg	offset3 += tmp;
15907104f784Smrg	if (pSmi->CSCVideo)
15917104f784Smrg	    CopyYV12ToVideoMem(buf,
15927104f784Smrg			       buf + offset2, buf + offset3,
15937104f784Smrg			       dstStart, srcPitch, srcPitch2, dstPitch,
15947104f784Smrg			       height, width);
15957104f784Smrg	else {
15967104f784Smrg	    if (id == FOURCC_I420) {
15977104f784Smrg		tmp = offset2;
15987104f784Smrg		offset2 = offset3;
15997104f784Smrg		offset3 = tmp;
16007104f784Smrg	    }
16017104f784Smrg	    nLines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
16027104f784Smrg	    xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1),
16037104f784Smrg				    buf + offset2, buf + offset3, dstStart,
16047104f784Smrg				    srcPitch, srcPitch2, dstPitch, nLines,
16057104f784Smrg				    nPixels);
160609885543Smrg	}
160709885543Smrg	break;
160809885543Smrg    case FOURCC_UYVY:
160909885543Smrg    case FOURCC_YUY2:
161009885543Smrg    default:
161109885543Smrg	buf += (top * srcPitch) + left;
161209885543Smrg	nLines = ((y2 + 0xffff) >> 16) - top;
161309885543Smrg	xf86XVCopyPacked(buf, dstStart, srcPitch, dstPitch, nLines, nPixels);
161409885543Smrg        break;
161509885543Smrg    }
161609885543Smrg
16177104f784Smrg    if (IS_MSOC(pSmi) ||
16187104f784Smrg	!REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) {
16197104f784Smrg	REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes);
16207104f784Smrg	if (!pSmi->CSCVideo)
16217104f784Smrg	    xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY],
16227104f784Smrg				clipBoxes);
162309885543Smrg    }
162409885543Smrg
16257104f784Smrg    if (pSmi->Chipset == SMI_COUGAR3DR)
162609885543Smrg	SMI_DisplayVideo0730(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2,
162709885543Smrg			     &dstBox, src_w, src_h, drw_w, drw_h);
16287104f784Smrg    else if (IS_MSOC(pSmi)) {
16297104f784Smrg	if (pSmi->CSCVideo)
16307104f784Smrg	    SMI_DisplayVideo0501_CSC(pScrn, id, offset, width, height, dstPitch,
16317104f784Smrg				     x1, y1, x2, y2, &dstBox,
16327104f784Smrg				     src_w, src_h, drw_w, drw_h, clipBoxes);
16337104f784Smrg	else
16347104f784Smrg	    SMI_DisplayVideo0501(pScrn, id, offset, width, height, dstPitch,
16357104f784Smrg				 x1, y1, x2, y2, &dstBox, src_w, src_h,
16367104f784Smrg				 drw_w, drw_h);
16377104f784Smrg    }
16387104f784Smrg    else{
16397104f784Smrg	if(crtc == crtcConf->crtc[0])
16407104f784Smrg	    SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2,
16417104f784Smrg			     &dstBox, src_w, src_h, drw_w, drw_h);
16427104f784Smrg    }
164309885543Smrg    pPort->videoStatus = CLIENT_VIDEO_ON;
16447104f784Smrg
16457104f784Smrg    LEAVE(Success);
164609885543Smrg
164709885543Smrg}
164809885543Smrg
164909885543Smrg
165009885543Smrgstatic int
165109885543SmrgSMI_QueryImageAttributes(
165209885543Smrg	ScrnInfoPtr	pScrn,
165309885543Smrg	int		id,
165409885543Smrg	unsigned short	*width,
165509885543Smrg	unsigned short	*height,
165609885543Smrg	int		*pitches,
165709885543Smrg	int		*offsets
165809885543Smrg)
165909885543Smrg{
166009885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
166109885543Smrg    int size, tmp;
166209885543Smrg
16637104f784Smrg    ENTER();
166409885543Smrg
166509885543Smrg    if (*width > pSmi->lcdWidth) {
166609885543Smrg	*width = pSmi->lcdWidth;
166709885543Smrg    }
166809885543Smrg    if (*height > pSmi->lcdHeight) {
166909885543Smrg	*height = pSmi->lcdHeight;
167009885543Smrg    }
167109885543Smrg
167209885543Smrg    *width = (*width + 1) & ~1;
167309885543Smrg    if (offsets != NULL) {
167409885543Smrg	offsets[0] = 0;
167509885543Smrg    }
167609885543Smrg
167709885543Smrg    switch (id) {
167809885543Smrg    case FOURCC_YV12:
167909885543Smrg    case FOURCC_I420:
168009885543Smrg	*height = (*height + 1) & ~1;
168109885543Smrg	size = (*width + 3) & ~3;
168209885543Smrg	if (pitches != NULL) {
168309885543Smrg	    pitches[0] = size;
168409885543Smrg	}
168509885543Smrg	size *= *height;
168609885543Smrg	if (offsets != NULL) {
168709885543Smrg	    offsets[1] = size;
168809885543Smrg	}
168909885543Smrg	tmp = ((*width >> 1) + 3) & ~3;
169009885543Smrg	if (pitches != NULL) {
169109885543Smrg	    pitches[1] = pitches[2] = tmp;
169209885543Smrg	}
169309885543Smrg	tmp *= (*height >> 1);
169409885543Smrg	size += tmp;
169509885543Smrg	if (offsets != NULL) {
169609885543Smrg	    offsets[2] = size;
169709885543Smrg	}
169809885543Smrg	size += tmp;
169909885543Smrg	break;
170009885543Smrg    case FOURCC_YUY2:
170109885543Smrg    case FOURCC_RV15:
170209885543Smrg    case FOURCC_RV16:
170309885543Smrg    default:
170409885543Smrg	size = *width * 2;
170509885543Smrg	if (pitches != NULL) {
170609885543Smrg	    pitches[0] = size;
170709885543Smrg	}
170809885543Smrg	size *= *height;
170909885543Smrg	break;
171009885543Smrg    case FOURCC_RV24:
171109885543Smrg	size = *width * 3;
171209885543Smrg	if (pitches != NULL) {
171309885543Smrg	    pitches[0] = size;
171409885543Smrg	}
171509885543Smrg	size *= *height;
171609885543Smrg	break;
171709885543Smrg    case FOURCC_RV32:
171809885543Smrg	size = *width * 4;
171909885543Smrg	if (pitches != NULL) {
172009885543Smrg	    pitches[0] = size;
172109885543Smrg	}
172209885543Smrg	size *= *height;
172309885543Smrg	break;
172409885543Smrg    }
172509885543Smrg
17267104f784Smrg    LEAVE(size);
172709885543Smrg}
172809885543Smrg
172909885543Smrg
173009885543Smrg/******************************************************************************\
173109885543Smrg**									      **
173209885543Smrg**	S U P P O R T   F U N C T I O N S				      **
173309885543Smrg**									      **
173409885543Smrg\******************************************************************************/
173509885543Smrg
173609885543Smrgstatic void
173709885543SmrgSMI_DisplayVideo(
173809885543Smrg	ScrnInfoPtr	pScrn,
173909885543Smrg	int		id,
174009885543Smrg	int		offset,
174109885543Smrg	short		width,
174209885543Smrg	short		height,
174309885543Smrg	int		pitch,
174409885543Smrg	int		x1,
174509885543Smrg	int		y1,
174609885543Smrg	int		x2,
174709885543Smrg	int		y2,
174809885543Smrg	BoxPtr		dstBox,
174909885543Smrg	short		vid_w,
175009885543Smrg	short		vid_h,
175109885543Smrg	short		drw_w,
175209885543Smrg	short		drw_h
175309885543Smrg)
175409885543Smrg{
175509885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
175609885543Smrg    CARD32 vpr00;
1757e4f6584cSmrg    uint32_t hstretch, vstretch;
175809885543Smrg
17597104f784Smrg    ENTER();
176009885543Smrg
176109885543Smrg    vpr00 = READ_VPR(pSmi, 0x00) & ~0x0CB800FF;
176209885543Smrg
176309885543Smrg    switch (id) {
176409885543Smrg    case FOURCC_YV12:
176509885543Smrg    case FOURCC_I420:
176609885543Smrg    case FOURCC_YUY2:
176709885543Smrg	vpr00 |= 0x6;
176809885543Smrg	break;
176909885543Smrg    case FOURCC_RV15:
177009885543Smrg	vpr00 |= 0x1;
177109885543Smrg	break;
177209885543Smrg    case FOURCC_RV16:
177309885543Smrg	vpr00 |= 0x2;
177409885543Smrg	break;
177509885543Smrg    case FOURCC_RV24:
177609885543Smrg	vpr00 |= 0x4;
177709885543Smrg	break;
177809885543Smrg    case FOURCC_RV32:
177909885543Smrg	vpr00 |= 0x3;
178009885543Smrg	break;
178109885543Smrg    }
178209885543Smrg
178309885543Smrg    if (drw_w > vid_w) {
1784e4f6584cSmrg	hstretch = ((uint32_t)(vid_w - 1) << 16) / (drw_w - 1);
178509885543Smrg    } else {
178609885543Smrg	hstretch = 0;
178709885543Smrg    }
178809885543Smrg
178909885543Smrg    if (drw_h > vid_h) {
1790e4f6584cSmrg	vstretch = ((uint32_t)(vid_h - 1) << 16) / (drw_h - 1);
179109885543Smrg	vpr00 |= 1 << 21;
179209885543Smrg    } else {
179309885543Smrg	vstretch = 0;
179409885543Smrg    }
17957104f784Smrg
179609885543Smrg    WRITE_VPR(pSmi, 0x00, vpr00 | (1 << 3) | (1 << 20));
179709885543Smrg    WRITE_VPR(pSmi, 0x14, (dstBox->x1) | (dstBox->y1 << 16));
179809885543Smrg    WRITE_VPR(pSmi, 0x18, (dstBox->x2) | (dstBox->y2 << 16));
179909885543Smrg    WRITE_VPR(pSmi, 0x1C, offset >> 3);
180009885543Smrg    WRITE_VPR(pSmi, 0x20, (pitch >> 3) | ((pitch >> 3) << 16));
1801e4f6584cSmrg    WRITE_VPR(pSmi, 0x24, (hstretch & 0xff00) | ((vstretch & 0xff00) >> 8));
1802e4f6584cSmrg    if (pSmi->Chipset == SMI_LYNXEMplus) {	/* This one can store additional precision */
1803e4f6584cSmrg	WRITE_VPR(pSmi, 0x68, ((hstretch & 0xff) << 8) | (vstretch & 0xff));
1804e4f6584cSmrg    }
180509885543Smrg
18067104f784Smrg    LEAVE();
18077104f784Smrg}
18087104f784Smrg
18097104f784Smrgstatic void
18107104f784SmrgSMI_DisplayVideo0501_CSC(ScrnInfoPtr pScrn, int id, int offset,
18117104f784Smrg			 short width, short height, int pitch,
18127104f784Smrg			 int x1, int y1, int x2, int y2, BoxPtr dstBox,
18137104f784Smrg			 short vid_w, short vid_h, short drw_w, short drw_h,
18147104f784Smrg			 RegionPtr clipboxes)
18157104f784Smrg{
18167104f784Smrg    int32_t	ScaleXn, ScaleXd, ScaleYn, ScaleYd;
18177104f784Smrg    int32_t	SrcTn, SrcTd, SrcLn, SrcLd;
18187104f784Smrg    int32_t	SrcRn, SrcBn;
18197104f784Smrg    int32_t	SrcDimX, SrcDimY;
18207104f784Smrg    int32_t	SrcYBase, SrcUBase, SrcVBase, SrcYPitch, SrcUVPitch;
18217104f784Smrg    int32_t	DestPitch;
18227104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
18237104f784Smrg    BoxPtr	pbox = REGION_RECTS(clipboxes);
18247104f784Smrg    int		i, nbox = REGION_NUM_RECTS(clipboxes);
18257104f784Smrg    int32_t	rect_x, rect_y, rect_w, rect_h, csc;
18267104f784Smrg    float	Hscale, Vscale;
18277104f784Smrg
18287104f784Smrg    ENTER();
18297104f784Smrg
18307104f784Smrg    SrcYBase = offset;
18317104f784Smrg    SrcYPitch = pitch;
18327104f784Smrg
18337104f784Smrg    DestPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15;
18347104f784Smrg
18357104f784Smrg    Hscale = (vid_w - 1) / (float)(drw_w - 1);
18367104f784Smrg    ScaleXn = Hscale;
18377104f784Smrg    ScaleXd = ((vid_w - 1) << 13) / (drw_w - 1) - (ScaleXn << 13);
18387104f784Smrg
18397104f784Smrg    Vscale = (vid_h - 1) / (float)(drw_h - 1);
18407104f784Smrg    ScaleYn = Vscale;
18417104f784Smrg    ScaleYd = ((vid_h - 1) << 13) / (drw_h - 1) - (ScaleYn << 13);
18427104f784Smrg
18437104f784Smrg    /* CSC constants */
18447104f784Smrg    WRITE_DPR(pSmi, 0xcc, 0);
18457104f784Smrg    /* Use start of framebuffer as base offset */
18467104f784Smrg    WRITE_DPR(pSmi, 0xf8, 0);
18477104f784Smrg
18487104f784Smrg    csc = (1 << 31) | (1 << 25);
18497104f784Smrg    if (pSmi->Bpp > 2)
18507104f784Smrg	csc |= 1 << 26;
18517104f784Smrg
18527104f784Smrg    switch (id) {
18537104f784Smrg	case FOURCC_YV12:
18547104f784Smrg	    SrcUVPitch = SrcYPitch / 2;
18557104f784Smrg	    SrcVBase = SrcYBase + SrcYPitch * height;
18567104f784Smrg	    SrcUBase = SrcVBase + SrcUVPitch * height / 2;
18577104f784Smrg	    csc |= 2 << 28;
18587104f784Smrg	    break;
18597104f784Smrg
18607104f784Smrg	case FOURCC_I420:
18617104f784Smrg	    SrcUVPitch = SrcYPitch / 2;
18627104f784Smrg	    SrcUBase = SrcYBase + SrcYPitch * height;
18637104f784Smrg	    SrcVBase = SrcUBase + SrcUVPitch * height / 2;
18647104f784Smrg	    csc |= 2 << 28;
18657104f784Smrg	    break;
18667104f784Smrg
18677104f784Smrg	case FOURCC_YUY2:
18687104f784Smrg	case FOURCC_RV16:
18697104f784Smrg	case FOURCC_RV32:
18707104f784Smrg	    SrcUBase = SrcVBase = SrcYBase;
18717104f784Smrg	    SrcUVPitch = SrcYPitch;
18727104f784Smrg	    break;
18737104f784Smrg
18747104f784Smrg	default:
18757104f784Smrg	    LEAVE();
18767104f784Smrg    }
18777104f784Smrg
18787104f784Smrg    WRITE_DPR(pSmi, 0xE4, ((SrcYPitch >> 4) << 16) | (SrcUVPitch >> 4));
18797104f784Smrg    WRITE_DPR(pSmi, 0xC8, SrcYBase);
18807104f784Smrg    WRITE_DPR(pSmi, 0xD8, SrcUBase);
18817104f784Smrg    WRITE_DPR(pSmi, 0xDC, SrcVBase);
18827104f784Smrg    WRITE_DPR(pSmi, 0xF4, (((ScaleXn << 13) | ScaleXd) << 16) |
18837104f784Smrg	      (ScaleYn << 13 | ScaleYd));
18847104f784Smrg
18857104f784Smrg    for (i = 0; i < nbox; i++, pbox++) {
18867104f784Smrg	rect_x = pbox->x1;
18877104f784Smrg	rect_y = pbox->y1;
18887104f784Smrg	rect_w = pbox->x2 - pbox->x1;
18897104f784Smrg	rect_h = pbox->y2 - pbox->y1;
18907104f784Smrg
18917104f784Smrg	SrcLn = (rect_x - dstBox->x1) * Hscale;
18927104f784Smrg	SrcLd = ((rect_x - dstBox->x1) << 13) * Hscale - (SrcLn << 13);
18937104f784Smrg	SrcRn = (rect_x + rect_w - dstBox->x1) * Hscale;
18947104f784Smrg
18957104f784Smrg	SrcTn = (rect_y - dstBox->y1) * Vscale;
18967104f784Smrg	SrcTd = ((rect_y - dstBox->y1) << 13) * Vscale - (SrcTn << 13);
18977104f784Smrg	SrcBn = (rect_y + rect_h - dstBox->y1) * Vscale;
18987104f784Smrg
18997104f784Smrg	SrcDimX = SrcRn - SrcLn + 2;
19007104f784Smrg	SrcDimY = SrcBn - SrcTn + 2;
19017104f784Smrg
19027104f784Smrg	WRITE_DPR(pSmi, 0xD0, (SrcLn << 16) | SrcLd);
19037104f784Smrg	WRITE_DPR(pSmi, 0xD4, (SrcTn << 16) | SrcTd);
19047104f784Smrg	WRITE_DPR(pSmi, 0xE0, (SrcDimX << 16) | SrcDimY);
19057104f784Smrg	WRITE_DPR(pSmi, 0xE8, (rect_x << 16) | rect_y);
19067104f784Smrg	WRITE_DPR(pSmi, 0xEC, (rect_w << 16) | rect_h);
19077104f784Smrg	WRITE_DPR(pSmi, 0xF0, ((DestPitch >> 4) << 16) | rect_h);
19087104f784Smrg
19097104f784Smrg	while (READ_DPR(pSmi, 0xfc) & (1 << 31))
19107104f784Smrg	    ;
19117104f784Smrg	WRITE_DPR(pSmi, 0xfc, csc);
19127104f784Smrg	/* CSC stop */
19137104f784Smrg	while (READ_DPR(pSmi, 0xfc) & (1 << 31))
19147104f784Smrg	    ;
19157104f784Smrg    }
19167104f784Smrg
19177104f784Smrg    LEAVE();
19187104f784Smrg}
19197104f784Smrg
19207104f784Smrgstatic void
19217104f784SmrgSMI_DisplayVideo0501(ScrnInfoPtr pScrn,
19227104f784Smrg		     int id,
19237104f784Smrg		     int offset,
19247104f784Smrg		     short width,
19257104f784Smrg		     short height,
19267104f784Smrg		     int pitch,
19277104f784Smrg		     int x1,
19287104f784Smrg		     int y1,
19297104f784Smrg		     int x2,
19307104f784Smrg		     int y2,
19317104f784Smrg		     BoxPtr dstBox,
19327104f784Smrg		     short vid_w, short vid_h, short drw_w, short drw_h)
19337104f784Smrg{
19347104f784Smrg    SMIPtr	pSmi = SMIPTR (pScrn);
19357104f784Smrg    CARD32	dcr40;
19367104f784Smrg    int		hstretch, vstretch;
19377104f784Smrg
19387104f784Smrg    ENTER();
19397104f784Smrg
19407104f784Smrg    dcr40 = READ_DCR(pSmi, 0x0040) & ~0x00003FFF;
19417104f784Smrg
19427104f784Smrg    switch (id) {
19437104f784Smrg	case FOURCC_YV12:
19447104f784Smrg	case FOURCC_I420:
19457104f784Smrg	case FOURCC_YUY2:
19467104f784Smrg	    dcr40 |= 0x3;
19477104f784Smrg	    break;
19487104f784Smrg
19497104f784Smrg	case FOURCC_RV16:
19507104f784Smrg	    dcr40 |= 0x1;
19517104f784Smrg	    break;
19527104f784Smrg
19537104f784Smrg	case FOURCC_RV32:
19547104f784Smrg	    dcr40 |= 0x2;
19557104f784Smrg	    break;
19567104f784Smrg    }
19577104f784Smrg
19587104f784Smrg    if (drw_w > vid_w) {	/*  Horizontal Stretch */
19597104f784Smrg	hstretch = 4096 * vid_w / drw_w;
19607104f784Smrg	dcr40 |= 1 << 8;
19617104f784Smrg    }
19627104f784Smrg    else {			/*  Horizontal Shrink */
19637104f784Smrg	if (drw_w < (vid_w >> 1))
19647104f784Smrg	    drw_w = vid_w >> 1;
19657104f784Smrg	hstretch = (4096 * drw_w / vid_w) | 0x8000;
19667104f784Smrg    }
19677104f784Smrg
19687104f784Smrg    if (drw_h > vid_h) {	/* Vertical Stretch */
19697104f784Smrg	vstretch = 4096 * vid_h / drw_h;
19707104f784Smrg	dcr40 |= 1 << 9;
19717104f784Smrg    }
19727104f784Smrg    else {			/* Vertical Shrink */
19737104f784Smrg	if (drw_h < (vid_h >> 1))
19747104f784Smrg	    drw_h = vid_h >> 1;
19757104f784Smrg	vstretch = (4096 * drw_h / vid_h) | 0x8000;
19767104f784Smrg    }
19777104f784Smrg
19787104f784Smrg    /* Set Color Key Enable bit */
19797104f784Smrg
19807104f784Smrg    WRITE_DCR(pSmi, 0x0000, READ_DCR(pSmi, 0x0000) | (1 << 9));
19817104f784Smrg    WRITE_DCR(pSmi, 0x0050, dstBox->x1 | (dstBox->y1 << 16));
19827104f784Smrg    WRITE_DCR(pSmi, 0x0054, dstBox->x2 | (dstBox->y2 << 16));
19837104f784Smrg    WRITE_DCR(pSmi, 0x0044, offset);
19847104f784Smrg
19857104f784Smrg    WRITE_DCR(pSmi, 0x0048, pitch | (pitch << 16));
19867104f784Smrg    WRITE_DCR(pSmi, 0x004C, offset + (pitch * height));
19877104f784Smrg    WRITE_DCR(pSmi, 0x0058, (vstretch << 16) | hstretch);
19887104f784Smrg    WRITE_DCR(pSmi, 0x005C, 0x00000000);
19897104f784Smrg    WRITE_DCR(pSmi, 0x0060, 0x00EDEDED);
19907104f784Smrg
19917104f784Smrg    WRITE_DCR(pSmi, 0x0040, dcr40 | (1 << 2));
19927104f784Smrg
19937104f784Smrg    LEAVE();
199409885543Smrg}
199509885543Smrg
199609885543Smrgstatic void
199709885543SmrgSMI_DisplayVideo0730(
199809885543Smrg	ScrnInfoPtr	pScrn,
199909885543Smrg	int		id,
200009885543Smrg	int		offset,
200109885543Smrg	short		width,
200209885543Smrg	short		height,
200309885543Smrg	int		pitch,
200409885543Smrg	int		x1,
200509885543Smrg	int		y1,
200609885543Smrg	int		x2,
200709885543Smrg	int		y2,
200809885543Smrg	BoxPtr		dstBox,
200909885543Smrg	short		vid_w,
201009885543Smrg	short		vid_h,
201109885543Smrg	short		drw_w,
201209885543Smrg	short		drw_h
201309885543Smrg)
201409885543Smrg{
201509885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
201609885543Smrg    CARD32 fpr00;
201709885543Smrg    int hstretch, vstretch;
201809885543Smrg
20197104f784Smrg    ENTER();
202009885543Smrg
202109885543Smrg    fpr00 = READ_FPR(pSmi, 0x00) & ~(FPR00_MASKBITS);
202209885543Smrg
202309885543Smrg    switch (id) {
202409885543Smrg    case FOURCC_YV12:
202509885543Smrg    case FOURCC_I420:
202609885543Smrg    case FOURCC_YUY2:
202709885543Smrg	fpr00 |= FPR00_FMT_YUV422;
202809885543Smrg	break;
202909885543Smrg    case FOURCC_RV15:
203009885543Smrg	fpr00 |= FPR00_FMT_15P;
203109885543Smrg	break;
203209885543Smrg    case FOURCC_RV16:
203309885543Smrg	fpr00 |= FPR00_FMT_16P;
203409885543Smrg	break;
203509885543Smrg    case FOURCC_RV24:
203609885543Smrg	fpr00 |= FPR00_FMT_24P;
203709885543Smrg	break;
203809885543Smrg    case FOURCC_RV32:
203909885543Smrg	fpr00 |= FPR00_FMT_32P;
204009885543Smrg	break;
204109885543Smrg    }
204209885543Smrg
204309885543Smrg    /* the formulas for calculating the stretch values do not match the
204409885543Smrg       documentation, but they're the same as the ddraw driver and they work */
204509885543Smrg    if (drw_w > vid_w) {
204609885543Smrg	hstretch = (8192 * vid_w / drw_w);
204709885543Smrg    } else {
204809885543Smrg	hstretch = 0;
204909885543Smrg    }
205009885543Smrg
205109885543Smrg    if (drw_h > vid_h) {
205209885543Smrg	vstretch = (8192 * vid_h / drw_h);
205309885543Smrg    } else {
205409885543Smrg	vstretch = 0;
205509885543Smrg    }
205609885543Smrg
205709885543Smrg    WRITE_FPR(pSmi, FPR00, fpr00 | FPR00_VWIENABLE | FPR00_VWIKEYENABLE);
205809885543Smrg    WRITE_FPR(pSmi, FPR14, (dstBox->x1) | (dstBox->y1 << 16));
205909885543Smrg    WRITE_FPR(pSmi, FPR18, (dstBox->x2) | (dstBox->y2 << 16));
206009885543Smrg    WRITE_FPR(pSmi, FPR1C, offset >> 3);
206109885543Smrg    WRITE_FPR(pSmi, FPR20, (pitch >> 3) | ((pitch >> 3) << 16));
206209885543Smrg    WRITE_FPR(pSmi, FPR24, (hstretch & 0xFF00) | ((vstretch & 0xFF00)>>8));
206309885543Smrg    WRITE_FPR(pSmi, FPR68, ((hstretch & 0x00FF)<<8) | (vstretch & 0x00FF));
206409885543Smrg
20657104f784Smrg    LEAVE();
206609885543Smrg}
206709885543Smrg
206809885543Smrgstatic void
2069b12e5c03SmrgSMI_BlockHandler(BLOCKHANDLER_ARGS_DECL)
207009885543Smrg{
2071b12e5c03Smrg    SCREEN_PTR(arg);
2072b12e5c03Smrg    ScrnInfoPtr	pScrn	= xf86ScreenToScrn(pScreen);
207309885543Smrg    SMIPtr	pSmi    = SMIPTR(pScrn);
207409885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
207509885543Smrg
207609885543Smrg    pScreen->BlockHandler = pSmi->BlockHandler;
2077b12e5c03Smrg    (*pScreen->BlockHandler)(BLOCKHANDLER_ARGS);
207809885543Smrg    pScreen->BlockHandler = SMI_BlockHandler;
207909885543Smrg
208009885543Smrg    if (pPort->videoStatus & TIMER_MASK) {
208109885543Smrg	UpdateCurrentTime();
208209885543Smrg        if (pPort->videoStatus & OFF_TIMER) {
208309885543Smrg            if (pPort->offTime < currentTime.milliseconds) {
208409885543Smrg		if (pSmi->Chipset == SMI_COUGAR3DR) {
208509885543Smrg		    WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE));
208609885543Smrg		}
20877104f784Smrg		else if (IS_MSOC(pSmi))
20887104f784Smrg		    WRITE_DCR(pSmi, 0x0040, READ_DCR(pSmi, 0x0040) & ~0x00000004);
20897104f784Smrg		else
20907104f784Smrg		    WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008);
209109885543Smrg                pPort->videoStatus = FREE_TIMER;
209209885543Smrg                pPort->freeTime = currentTime.milliseconds + FREE_DELAY;
209309885543Smrg	    }
209409885543Smrg	} else {
209509885543Smrg            if (pPort->freeTime < currentTime.milliseconds) {
209609885543Smrg		SMI_FreeMemory(pScrn, pPort->video_memory);
209709885543Smrg                pPort->video_memory = NULL;
209809885543Smrg	    }
209909885543Smrg            pPort->videoStatus = 0;
210009885543Smrg	}
210109885543Smrg    }
210209885543Smrg}
210309885543Smrg
210409885543Smrg#if 0
210509885543Smrgstatic int
210609885543SmrgSMI_SendI2C(
210709885543Smrg	ScrnInfoPtr		pScrn,
210809885543Smrg	CARD8			device,
210909885543Smrg	char			*devName,
211009885543Smrg	SMI_I2CDataPtr	i2cData
211109885543Smrg)
211209885543Smrg{
21137104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
21147104f784Smrg    I2CDevPtr	dev;
21157104f784Smrg    int		status = Success;
211609885543Smrg
21177104f784Smrg    ENTER();
211809885543Smrg
21197104f784Smrg    if (pSmi->I2C == NULL)
21207104f784Smrg	LEAVE(BadAlloc);
212109885543Smrg
21227104f784Smrg    dev = xf86CreateI2CDevRec();
21237104f784Smrg    if (dev == NULL)
21247104f784Smrg	LEAVE(BadAlloc);
212509885543Smrg
21267104f784Smrg    dev->DevName = devName;
21277104f784Smrg    dev->SlaveAddr = device;
21287104f784Smrg    dev->pI2CBus = pSmi->I2C;
21297104f784Smrg
21307104f784Smrg    if (!xf86I2CDevInit(dev))
21317104f784Smrg	status = BadAlloc;
21327104f784Smrg    else {
21337104f784Smrg	while (i2cData->address != 0xFF || i2cData->data != 0xFF) {	/* PDR#676 */
21347104f784Smrg	    if (!xf86I2CWriteByte(dev, i2cData->address, i2cData->data)) {
213509885543Smrg		status = BadAlloc;
21367104f784Smrg		break;
21377104f784Smrg	    }
21387104f784Smrg	    i2cData++;
213909885543Smrg	}
21407104f784Smrg    }
214109885543Smrg
21427104f784Smrg    xf86DestroyI2CDevRec(dev, TRUE);
21437104f784Smrg
21447104f784Smrg    LEAVE(status);
214509885543Smrg}
214609885543Smrg#endif
214709885543Smrg
214809885543Smrg/******************************************************************************\
214909885543Smrg**									      **
215009885543Smrg**	 O F F S C R E E N   M E M O R Y   M A N A G E R		      **
215109885543Smrg**									      **
215209885543Smrg\******************************************************************************/
215309885543Smrg
215409885543Smrgstatic void
215509885543SmrgSMI_InitOffscreenImages(
215609885543Smrg	ScreenPtr	pScreen
215709885543Smrg)
215809885543Smrg{
215909885543Smrg    XF86OffscreenImagePtr offscreenImages;
2160b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
216109885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
216209885543Smrg    SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
216309885543Smrg
21647104f784Smrg    ENTER();
216509885543Smrg
21667b58d2e0Smrg    offscreenImages = malloc(sizeof(XF86OffscreenImageRec));
216709885543Smrg    if (offscreenImages == NULL) {
21687104f784Smrg	LEAVE();
216909885543Smrg    }
217009885543Smrg
217109885543Smrg    offscreenImages->image = SMI_VideoImages;
21727104f784Smrg    offscreenImages->flags = VIDEO_OVERLAID_IMAGES;
21737104f784Smrg    if (IS_MSOC(pSmi))
21747104f784Smrg	offscreenImages->flags |= VIDEO_CLIP_TO_VIEWPORT;
217509885543Smrg    offscreenImages->alloc_surface = SMI_AllocSurface;
217609885543Smrg    offscreenImages->free_surface = SMI_FreeSurface;
217709885543Smrg    offscreenImages->display = SMI_DisplaySurface;
217809885543Smrg    offscreenImages->stop = SMI_StopSurface;
217909885543Smrg    offscreenImages->getAttribute = SMI_GetSurfaceAttribute;
218009885543Smrg    offscreenImages->setAttribute = SMI_SetSurfaceAttribute;
218109885543Smrg    offscreenImages->max_width = pSmi->lcdWidth;
218209885543Smrg    offscreenImages->max_height = pSmi->lcdHeight;
218309885543Smrg    if (!pPort->I2CDev.SlaveAddr) {
218409885543Smrg	offscreenImages->num_attributes = nElems(SMI_VideoAttributes);
218509885543Smrg	offscreenImages->attributes = SMI_VideoAttributes;
218609885543Smrg    } else {
218709885543Smrg	offscreenImages->num_attributes = nElems(SMI_VideoAttributesSAA711x);
218809885543Smrg	offscreenImages->attributes = SMI_VideoAttributesSAA711x;
218909885543Smrg    }
219009885543Smrg    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
219109885543Smrg
21927104f784Smrg    LEAVE();
219309885543Smrg}
219409885543Smrg
219509885543Smrgstatic void
219609885543SmrgSMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
219709885543Smrg{
2198b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
219909885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
220009885543Smrg    SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr;
220109885543Smrg
22027104f784Smrg    ENTER();
220309885543Smrg
220409885543Smrg    if (pPort->video_memory == area)
220509885543Smrg	pPort->video_memory = NULL;
220609885543Smrg
22077104f784Smrg    LEAVE();
220809885543Smrg}
220909885543Smrg
22107104f784SmrgCARD32
22117104f784SmrgSMI_AllocateMemory(ScrnInfoPtr pScrn, void **mem_struct, int size)
221209885543Smrg{
2213b12e5c03Smrg    ScreenPtr	pScreen = xf86ScrnToScreen(pScrn);
22147104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
22157104f784Smrg    int		offset = 0;
221609885543Smrg
22177104f784Smrg    ENTER();
221809885543Smrg
221909885543Smrg    if (pSmi->useEXA) {
222009885543Smrg	ExaOffscreenArea *area = *mem_struct;
222109885543Smrg
222209885543Smrg	if (area != NULL) {
222309885543Smrg	    if (area->size >= size)
22247104f784Smrg		LEAVE(area->offset);
222509885543Smrg
222609885543Smrg	    exaOffscreenFree(pScrn->pScreen, area);
222709885543Smrg	}
222809885543Smrg
22297104f784Smrg	area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE,
22307104f784Smrg				 SMI_VideoSave, NULL);
223109885543Smrg
223209885543Smrg	*mem_struct = area;
22337104f784Smrg	if (area != NULL)
22347104f784Smrg	    offset = area->offset;
22357104f784Smrg    }
22367104f784Smrg    else {
22377104f784Smrg	FBLinearPtr	linear = *mem_struct;
223809885543Smrg
223909885543Smrg	/*  XAA allocates in units of pixels at the screen bpp,
224009885543Smrg	 *  so adjust size appropriately.
224109885543Smrg	 */
224209885543Smrg	size = (size + pSmi->Bpp - 1) / pSmi->Bpp;
224309885543Smrg
224409885543Smrg	if (linear) {
224509885543Smrg	    if (linear->size >= size)
22467104f784Smrg		LEAVE(linear->offset * pSmi->Bpp);
224709885543Smrg
224809885543Smrg	    if (xf86ResizeOffscreenLinear(linear, size))
22497104f784Smrg		LEAVE(linear->offset * pSmi->Bpp);
225009885543Smrg
22517104f784Smrg	    xf86FreeOffscreenLinear(linear);
22527104f784Smrg	}
22537104f784Smrg	else {
22547104f784Smrg	    int max_size;
225509885543Smrg
22567104f784Smrg	    xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
22577104f784Smrg					    PRIORITY_EXTREME);
22587104f784Smrg	    if (max_size < size)
22597104f784Smrg		LEAVE(0);
226009885543Smrg
22617104f784Smrg	    xf86PurgeUnlockedOffscreenAreas(pScreen);
226209885543Smrg	}
226309885543Smrg
22647104f784Smrg	linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
22657104f784Smrg					     NULL, NULL, NULL);
22667104f784Smrg	if ((*mem_struct = linear) != NULL)
22677104f784Smrg	    offset = linear->offset * pSmi->Bpp;
22687104f784Smrg
22697104f784Smrg	DEBUG("offset = %p\n", offset);
227009885543Smrg    }
227109885543Smrg
22727104f784Smrg    LEAVE(offset);
227309885543Smrg}
227409885543Smrg
22757104f784Smrgvoid
227609885543SmrgSMI_FreeMemory(
227709885543Smrg	ScrnInfoPtr pScrn,
227809885543Smrg	void *mem_struct
227909885543Smrg)
228009885543Smrg{
228109885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
228209885543Smrg
22837104f784Smrg    ENTER();
228409885543Smrg
228509885543Smrg    if (pSmi->useEXA) {
228609885543Smrg	ExaOffscreenArea *area = mem_struct;
228709885543Smrg
228809885543Smrg	if (area != NULL)
228909885543Smrg	    exaOffscreenFree(pScrn->pScreen, area);
229009885543Smrg    } else {
229109885543Smrg	FBLinearPtr linear = mem_struct;
229209885543Smrg
229309885543Smrg	if (linear != NULL)
229409885543Smrg	    xf86FreeOffscreenLinear(linear);
229509885543Smrg    }
229609885543Smrg
22977104f784Smrg    LEAVE();
22987104f784Smrg}
22997104f784Smrg
23007104f784Smrgstatic void
23017104f784SmrgCopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2,
23027104f784Smrg		   unsigned char *src3, unsigned char *dst,
23037104f784Smrg		   int src1Pitch, int src23Pitch, int dstPitch,
23047104f784Smrg		   int height, int width)
23057104f784Smrg{
23067104f784Smrg    int		j = height;
23077104f784Smrg
23087104f784Smrg    ENTER();
23097104f784Smrg
23107104f784Smrg    /* copy 1 data */
23117104f784Smrg    while (j -- > 0) {
23127104f784Smrg	memcpy(dst, src1, width);
23137104f784Smrg	src1 += src1Pitch;
23147104f784Smrg	dst += dstPitch;
23157104f784Smrg    }
23167104f784Smrg    /* copy 2 data */
23177104f784Smrg    j = height / 2;
23187104f784Smrg    while (j -- > 0) {
23197104f784Smrg	memcpy(dst, src2, width / 2);
23207104f784Smrg	src2 += src23Pitch;
23217104f784Smrg	dst += dstPitch / 2;
23227104f784Smrg    }
23237104f784Smrg    /* copy 3 data */
23247104f784Smrg    j = height / 2;
23257104f784Smrg    while (j -- > 0) {
23267104f784Smrg	memcpy(dst, src3, width / 2);
23277104f784Smrg	src3 += src23Pitch;
23287104f784Smrg	dst += dstPitch / 2;
23297104f784Smrg    }
23307104f784Smrg
23317104f784Smrg    LEAVE();
233209885543Smrg}
233309885543Smrg
233409885543Smrgstatic int
233509885543SmrgSMI_AllocSurface(
233609885543Smrg	ScrnInfoPtr	pScrn,
233709885543Smrg	int		id,
233809885543Smrg	unsigned short	width,
233909885543Smrg	unsigned short	height,
234009885543Smrg	XF86SurfacePtr	surface
234109885543Smrg)
234209885543Smrg{
234309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
234409885543Smrg    int pitch, bpp, offset, size;
234509885543Smrg    void *surface_memory = NULL;
234609885543Smrg    SMI_OffscreenPtr ptrOffscreen;
234709885543Smrg
23487104f784Smrg    ENTER();
234909885543Smrg
23507104f784Smrg    if (width > pSmi->lcdWidth || height > pSmi->lcdHeight)
23517104f784Smrg	LEAVE(BadAlloc);
235209885543Smrg
235309885543Smrg    switch (id) {
235409885543Smrg    case FOURCC_YV12:
235509885543Smrg    case FOURCC_I420:
235609885543Smrg    case FOURCC_YUY2:
235709885543Smrg    case FOURCC_RV15:
235809885543Smrg    case FOURCC_RV16:
235909885543Smrg	bpp = 2;
236009885543Smrg	break;
236109885543Smrg    case FOURCC_RV24:
236209885543Smrg	bpp = 3;
236309885543Smrg	break;
236409885543Smrg    case FOURCC_RV32:
236509885543Smrg	bpp = 4;
236609885543Smrg	break;
236709885543Smrg    default:
23687104f784Smrg	LEAVE(BadAlloc);
236909885543Smrg    }
237009885543Smrg
237109885543Smrg    width = (width + 1) & ~1;
237209885543Smrg    pitch = (width * bpp + 15) & ~15;
237309885543Smrg    size  = pitch * height;
237409885543Smrg
237509885543Smrg    offset = SMI_AllocateMemory(pScrn, &surface_memory, size);
23767104f784Smrg    if (offset == 0)
23777104f784Smrg	LEAVE(BadAlloc);
237809885543Smrg
23797b58d2e0Smrg    surface->pitches = malloc(sizeof(int));
238009885543Smrg    if (surface->pitches == NULL) {
238109885543Smrg	SMI_FreeMemory(pScrn, surface_memory);
23827104f784Smrg	LEAVE(BadAlloc);
238309885543Smrg    }
23847b58d2e0Smrg    surface->offsets = malloc(sizeof(int));
238509885543Smrg    if (surface->offsets == NULL) {
23867b58d2e0Smrg	free(surface->pitches);
238709885543Smrg	SMI_FreeMemory(pScrn, surface_memory);
23887104f784Smrg	LEAVE(BadAlloc);
238909885543Smrg    }
239009885543Smrg
23917b58d2e0Smrg    ptrOffscreen = malloc(sizeof(SMI_OffscreenRec));
239209885543Smrg    if (ptrOffscreen == NULL) {
23937b58d2e0Smrg	free(surface->offsets);
23947b58d2e0Smrg	free(surface->pitches);
239509885543Smrg	SMI_FreeMemory(pScrn, surface_memory);
23967104f784Smrg	LEAVE(BadAlloc);
239709885543Smrg    }
239809885543Smrg
239909885543Smrg    surface->pScrn = pScrn;
240009885543Smrg    surface->id = id;
240109885543Smrg    surface->width = width;
240209885543Smrg    surface->height = height;
240309885543Smrg    surface->pitches[0] = pitch;
240409885543Smrg    surface->offsets[0] = offset;
240509885543Smrg    surface->devPrivate.ptr = (pointer) ptrOffscreen;
240609885543Smrg
240709885543Smrg    ptrOffscreen->surface_memory = surface_memory;
240809885543Smrg    ptrOffscreen->isOn = FALSE;
240909885543Smrg
24107104f784Smrg    LEAVE(Success);
241109885543Smrg}
241209885543Smrg
241309885543Smrgstatic int
241409885543SmrgSMI_FreeSurface(
241509885543Smrg	XF86SurfacePtr	surface
241609885543Smrg)
241709885543Smrg{
241809885543Smrg    ScrnInfoPtr pScrn = surface->pScrn;
241909885543Smrg    SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr;
242009885543Smrg
24217104f784Smrg    ENTER();
242209885543Smrg
242309885543Smrg    if (ptrOffscreen->isOn) {
242409885543Smrg	SMI_StopSurface(surface);
242509885543Smrg    }
242609885543Smrg
242709885543Smrg    SMI_FreeMemory(pScrn, ptrOffscreen->surface_memory);
24287b58d2e0Smrg    free(surface->pitches);
24297b58d2e0Smrg    free(surface->offsets);
24307b58d2e0Smrg    free(surface->devPrivate.ptr);
243109885543Smrg
24327104f784Smrg    LEAVE(Success);
243309885543Smrg}
243409885543Smrg
243509885543Smrgstatic int
243609885543SmrgSMI_DisplaySurface(
243709885543Smrg	XF86SurfacePtr	surface,
243809885543Smrg	short		vid_x,
243909885543Smrg	short		vid_y,
244009885543Smrg	short		drw_x,
244109885543Smrg	short		drw_y,
244209885543Smrg	short		vid_w,
244309885543Smrg	short		vid_h,
244409885543Smrg	short		drw_w,
244509885543Smrg	short		drw_h,
244609885543Smrg	RegionPtr	clipBoxes
244709885543Smrg)
244809885543Smrg{
244909885543Smrg    SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr;
245009885543Smrg    SMIPtr pSmi = SMIPTR(surface->pScrn);
245109885543Smrg    SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr;
245209885543Smrg    INT32 x1, y1, x2, y2;
245309885543Smrg    BoxRec dstBox;
24547104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(surface->pScrn);
24557104f784Smrg    xf86CrtcPtr crtc;
245609885543Smrg
24577104f784Smrg    ENTER();
245809885543Smrg
245909885543Smrg    x1 = vid_x;
246009885543Smrg    x2 = vid_x + vid_w;
246109885543Smrg    y1 = vid_y;
246209885543Smrg    y2 = vid_y + vid_h;
246309885543Smrg
246409885543Smrg    dstBox.x1 = drw_x;
246509885543Smrg    dstBox.x2 = drw_x + drw_w;
246609885543Smrg    dstBox.y1 = drw_y;
246709885543Smrg    dstBox.y2 = drw_y + drw_h;
246809885543Smrg
24697104f784Smrg    if(!xf86_crtc_clip_video_helper(surface->pScrn, &crtc, crtcConf->crtc[0], &dstBox,
24707104f784Smrg				    &x1, &x2, &y1, &y2, clipBoxes, surface->width, surface->height))
24717104f784Smrg	LEAVE(Success);
247209885543Smrg
24737b58d2e0Smrg    if (!crtc)
24747b58d2e0Smrg	LEAVE(Success);
24757b58d2e0Smrg
24767104f784Smrg    /* Transform dstBox to the CRTC coordinates */
24777104f784Smrg    dstBox.x1 -= crtc->x;
24787104f784Smrg    dstBox.y1 -= crtc->y;
24797104f784Smrg    dstBox.x2 -= crtc->x;
24807104f784Smrg    dstBox.y2 -= crtc->y;
248109885543Smrg
248209885543Smrg    xf86XVFillKeyHelper(surface->pScrn->pScreen,
248309885543Smrg			pPort->Attribute[XV_COLORKEY], clipBoxes);
24847104f784Smrg    SMI_ResetVideo(surface->pScrn);
248509885543Smrg
24867104f784Smrg    if (pSmi->Chipset == SMI_COUGAR3DR)
248709885543Smrg	SMI_DisplayVideo0730(surface->pScrn, surface->id, surface->offsets[0],
248809885543Smrg			     surface->width, surface->height, surface->pitches[0], x1, y1, x2,
248909885543Smrg			     y2, &dstBox, vid_w, vid_h, drw_w, drw_h);
24907104f784Smrg    else if (IS_MSOC(pSmi))
24917104f784Smrg	SMI_DisplayVideo0501(surface->pScrn, surface->id,
24927104f784Smrg			     surface->offsets[0], surface->width,
24937104f784Smrg			     surface->height, surface->pitches[0], x1, y1,
24947104f784Smrg			     x2, y2, &dstBox, vid_w, vid_h, drw_w, drw_h);
24957104f784Smrg    else{
24967104f784Smrg	if(crtc == crtcConf->crtc[0])
24977104f784Smrg	    SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0],
24987104f784Smrg			     surface->width, surface->height, surface->pitches[0], x1, y1, x2,
24997104f784Smrg			     y2, &dstBox, vid_w, vid_h, drw_w, drw_h);
250009885543Smrg    }
250109885543Smrg
250209885543Smrg    ptrOffscreen->isOn = TRUE;
250309885543Smrg    if (pPort->videoStatus & CLIENT_VIDEO_ON) {
250409885543Smrg        REGION_EMPTY(surface->pScrn->pScreen, &pPort->clip);
250509885543Smrg	UpdateCurrentTime();
250609885543Smrg        pPort->videoStatus = FREE_TIMER;
250709885543Smrg        pPort->freeTime = currentTime.milliseconds + FREE_DELAY;
250809885543Smrg    }
250909885543Smrg
25107104f784Smrg    LEAVE(Success);
251109885543Smrg}
251209885543Smrg
251309885543Smrgstatic int
251409885543SmrgSMI_StopSurface(
251509885543Smrg	XF86SurfacePtr	surface
251609885543Smrg)
251709885543Smrg{
251809885543Smrg    SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr;
251909885543Smrg
25207104f784Smrg    ENTER();
252109885543Smrg
252209885543Smrg    if (ptrOffscreen->isOn) {
252309885543Smrg	SMIPtr pSmi = SMIPTR(surface->pScrn);
252409885543Smrg	if (pSmi->Chipset == SMI_COUGAR3DR) {
252509885543Smrg	    WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE));
252609885543Smrg	} else {
252709885543Smrg	    WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008);
252809885543Smrg	}
252909885543Smrg
253009885543Smrg	ptrOffscreen->isOn = FALSE;
253109885543Smrg    }
253209885543Smrg
25337104f784Smrg    LEAVE(Success);
253409885543Smrg}
253509885543Smrg
253609885543Smrgstatic int
253709885543SmrgSMI_GetSurfaceAttribute(
253809885543Smrg	ScrnInfoPtr	pScrn,
253909885543Smrg	Atom		attr,
254009885543Smrg	INT32		*value
254109885543Smrg)
254209885543Smrg{
254309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
254409885543Smrg
254509885543Smrg    return SMI_GetPortAttribute(pScrn, attr, value,
254609885543Smrg			(pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr);
254709885543Smrg}
254809885543Smrg
254909885543Smrgstatic int
255009885543SmrgSMI_SetSurfaceAttribute(
255109885543Smrg	ScrnInfoPtr	pScrn,
255209885543Smrg	Atom		attr,
255309885543Smrg	INT32		value
255409885543Smrg)
255509885543Smrg{
255609885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
255709885543Smrg
255809885543Smrg    return SMI_SetPortAttribute(pScrn, attr, value,
255909885543Smrg			(pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr);
256009885543Smrg}
256109885543Smrg
256209885543Smrgstatic void
256309885543SmrgSetKeyReg(SMIPtr pSmi, int reg, int value)
256409885543Smrg{
25657104f784Smrg    if (pSmi->Chipset == SMI_COUGAR3DR)
256609885543Smrg	WRITE_FPR(pSmi, reg, value);
25677104f784Smrg    else if (IS_MSOC(pSmi)) {
25687104f784Smrg	/* We don't change the color mask, and we don't do brightness.  IF
25697104f784Smrg	 * they write to the colorkey register, we'll write the value to the
25707104f784Smrg	 * 501 colorkey register */
25717104f784Smrg	if (FPR04 == reg)		   /* Only act on colorkey value writes */
25727104f784Smrg	    WRITE_DCR(pSmi, 0x0008, value);/* ColorKey register is DCR08 */
257309885543Smrg    }
25747104f784Smrg    else
25757104f784Smrg	WRITE_VPR(pSmi, reg, value);
257609885543Smrg}
257709885543Smrg
257809885543Smrg#else /* SMI_USE_VIDEO */
257909885543Smrgvoid SMI_InitVideo(ScreenPtr pScreen) {}
258009885543Smrg#endif
2581