radeon_video.c revision 7821949a
1
2#ifdef HAVE_CONFIG_H
3#include "config.h"
4#endif
5
6#include <stdlib.h>
7#include <string.h>
8#include <stdio.h>
9#include <math.h>
10
11#include "radeon.h"
12#include "radeon_reg.h"
13#include "radeon_macros.h"
14#include "radeon_probe.h"
15#include "radeon_video.h"
16
17#include "xf86.h"
18#include "dixstruct.h"
19#include "atipciids.h"
20#include "xf86fbman.h"
21
22/* DPMS */
23#ifdef HAVE_XEXTPROTO_71
24#include <X11/extensions/dpmsconst.h>
25#else
26#define DPMS_SERVER
27#include <X11/extensions/dpms.h>
28#endif
29
30#include <X11/extensions/Xv.h>
31#include "fourcc.h"
32
33#include "theatre_detect.h"
34#include "theatre_reg.h"
35#include "fi1236.h"
36#include "msp3430.h"
37#include "tda9885.h"
38
39#define OFF_DELAY       250  /* milliseconds */
40#define FREE_DELAY      15000
41
42#define OFF_TIMER       0x01
43#define FREE_TIMER      0x02
44#define CLIENT_VIDEO_ON 0x04
45
46#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
47
48/* capture config constants */
49#define BUF_TYPE_FIELD          0
50#define BUF_TYPE_ALTERNATING    1
51#define BUF_TYPE_FRAME          2
52
53
54#define BUF_MODE_SINGLE         0
55#define BUF_MODE_DOUBLE         1
56#define BUF_MODE_TRIPLE         2
57/* CAP0_CONFIG values */
58
59#define FORMAT_BROOKTREE        0
60#define FORMAT_CCIR656          1
61#define FORMAT_ZV               2
62#define FORMAT_VIP16            3
63#define FORMAT_TRANSPORT        4
64
65#define ENABLE_RADEON_CAPTURE_WEAVE (RADEON_CAP0_CONFIG_CONTINUOS \
66                        | (BUF_MODE_DOUBLE <<7) \
67                        | (BUF_TYPE_FRAME << 4) \
68                        | ( (pPriv->theatre !=NULL)?(FORMAT_CCIR656<<23):(FORMAT_BROOKTREE<<23)) \
69                        | RADEON_CAP0_CONFIG_HORZ_DECIMATOR \
70                        | (pPriv->capture_vbi_data ? RADEON_CAP0_CONFIG_VBI_EN : 0) \
71                        | RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422)
72
73#define ENABLE_RADEON_CAPTURE_BOB (RADEON_CAP0_CONFIG_CONTINUOS \
74                        | (BUF_MODE_SINGLE <<7)  \
75                        | (BUF_TYPE_ALTERNATING << 4) \
76                        | ( (pPriv->theatre !=NULL)?(FORMAT_CCIR656<<23):(FORMAT_BROOKTREE<<23)) \
77                        | RADEON_CAP0_CONFIG_HORZ_DECIMATOR \
78                        | (pPriv->capture_vbi_data ? RADEON_CAP0_CONFIG_VBI_EN : 0) \
79                        | RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422)
80
81
82static void RADEONInitOffscreenImages(ScreenPtr);
83
84static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr);
85static int  RADEONPutImage(ScrnInfoPtr, short, short, short, short, short,
86			short, short, short, int, unsigned char*, short,
87			short, Bool, RegionPtr, pointer,
88			DrawablePtr);
89static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now);
90static int RADEONPutVideo(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y,
91                        short src_w, short src_h, short drw_w, short drw_h,
92			RegionPtr clipBoxes, pointer data, DrawablePtr pDraw);
93
94static void RADEON_board_setmisc(RADEONPortPrivPtr pPriv);
95static void RADEON_RT_SetEncoding(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
96static void RADEON_MSP_SetEncoding(RADEONPortPrivPtr pPriv);
97static void RADEON_TDA9885_SetEncoding(RADEONPortPrivPtr pPriv);
98static void RADEON_FI1236_SetEncoding(RADEONPortPrivPtr pPriv);
99
100static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;
101static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity;
102static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults;
103static Atom xvGamma, xvColorspace;
104static Atom xvCRTC;
105static Atom xvEncoding, xvFrequency, xvVolume, xvMute,
106	     xvDecBrightness, xvDecContrast, xvDecHue, xvDecColor, xvDecSaturation,
107	     xvTunerStatus, xvSAP, xvOverlayDeinterlacingMethod,
108	     xvLocationID, xvDeviceID, xvInstanceID, xvDumpStatus,
109	     xvAdjustment;
110
111static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode;
112
113#define GET_PORT_PRIVATE(pScrn) \
114   (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
115
116static void
117radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
118{
119    dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
120    dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
121    dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
122    dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
123
124    if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
125	dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
126}
127
128static void
129radeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
130{
131    if (crtc->enabled) {
132	crtc_box->x1 = crtc->x;
133	crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
134	crtc_box->y1 = crtc->y;
135	crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
136    } else
137	crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
138}
139
140static int
141radeon_box_area(BoxPtr box)
142{
143    return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
144}
145
146static Bool
147radeon_crtc_is_enabled(xf86CrtcPtr crtc)
148{
149    RADEONCrtcPrivatePtr radeon_crtc;
150
151#ifdef XF86DRM_MODE
152    if (RADEONPTR(crtc->scrn)->cs) {
153	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
154	return drmmode_crtc->dpms_mode == DPMSModeOn;
155    }
156#endif
157
158    radeon_crtc = crtc->driver_private;
159    return radeon_crtc->enabled;
160}
161
162xf86CrtcPtr
163radeon_pick_best_crtc(ScrnInfoPtr pScrn,
164		      int x1, int x2, int y1, int y2)
165{
166    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
167    int			coverage, best_coverage, c;
168    BoxRec		box, crtc_box, cover_box;
169    RROutputPtr         primary_output = NULL;
170    xf86CrtcPtr         best_crtc = NULL, primary_crtc = NULL;
171
172    if (!pScrn->vtSema)
173	return NULL;
174
175    box.x1 = x1;
176    box.x2 = x2;
177    box.y1 = y1;
178    box.y2 = y2;
179    best_coverage = 0;
180
181    /* Prefer the CRTC of the primary output */
182#ifdef HAS_DIXREGISTERPRIVATEKEY
183    if (dixPrivateKeyRegistered(rrPrivKey))
184#endif
185    {
186	primary_output = RRFirstOutput(pScrn->pScreen);
187    }
188    if (primary_output && primary_output->crtc)
189	primary_crtc = primary_output->crtc->devPrivate;
190
191    for (c = 0; c < xf86_config->num_crtc; c++) {
192	xf86CrtcPtr crtc = xf86_config->crtc[c];
193
194	if (!radeon_crtc_is_enabled(crtc))
195	    continue;
196
197	radeon_crtc_box(crtc, &crtc_box);
198	radeon_box_intersect(&cover_box, &crtc_box, &box);
199	coverage = radeon_box_area(&cover_box);
200	if (coverage > best_coverage ||
201	    (coverage == best_coverage && crtc == primary_crtc)) {
202	    best_crtc = crtc;
203	    best_coverage = coverage;
204	}
205    }
206    return best_crtc;
207}
208
209#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER
210static xf86CrtcPtr
211radeon_covering_crtc(ScrnInfoPtr pScrn,
212		     BoxPtr	box,
213		     xf86CrtcPtr desired,
214		     BoxPtr	crtc_box_ret)
215{
216    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
217    xf86CrtcPtr		crtc, best_crtc;
218    int			coverage, best_coverage;
219    int			c;
220    BoxRec		crtc_box, cover_box;
221
222    best_crtc = NULL;
223    best_coverage = 0;
224    crtc_box_ret->x1 = 0;
225    crtc_box_ret->x2 = 0;
226    crtc_box_ret->y1 = 0;
227    crtc_box_ret->y2 = 0;
228    for (c = 0; c < xf86_config->num_crtc; c++) {
229	crtc = xf86_config->crtc[c];
230	radeon_crtc_box(crtc, &crtc_box);
231	radeon_box_intersect(&cover_box, &crtc_box, box);
232	coverage = radeon_box_area(&cover_box);
233	if (coverage && crtc == desired) {
234	    *crtc_box_ret = crtc_box;
235	    return crtc;
236	} else if (coverage > best_coverage) {
237	    *crtc_box_ret = crtc_box;
238	    best_crtc = crtc;
239	    best_coverage = coverage;
240	}
241    }
242    return best_crtc;
243}
244
245static Bool
246radeon_crtc_clip_video_helper(ScrnInfoPtr pScrn,
247			      xf86CrtcPtr *crtc_ret,
248			      xf86CrtcPtr desired_crtc,
249			      BoxPtr      dst,
250			      INT32	  *xa,
251			      INT32	  *xb,
252			      INT32	  *ya,
253			      INT32	  *yb,
254			      RegionPtr   reg,
255			      INT32	  width,
256			      INT32	  height)
257{
258    Bool	ret;
259    RegionRec	crtc_region_local;
260    RegionPtr	crtc_region = reg;
261
262    /*
263     * For overlay video, compute the relevant CRTC and
264     * clip video to that
265     */
266    if (crtc_ret) {
267	BoxRec		crtc_box;
268	xf86CrtcPtr	crtc = radeon_covering_crtc(pScrn, dst,
269						    desired_crtc,
270						    &crtc_box);
271
272	if (crtc) {
273	    REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
274	    crtc_region = &crtc_region_local;
275	    REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
276	}
277	*crtc_ret = crtc;
278    }
279
280    ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb,
281				crtc_region, width, height);
282
283    if (crtc_region != reg)
284	REGION_UNINIT (pScreen, &crtc_region_local);
285
286    return ret;
287}
288#endif
289
290static Bool
291radeon_crtc_clip_video(ScrnInfoPtr pScrn,
292		       xf86CrtcPtr *crtc_ret,
293		       xf86CrtcPtr desired_crtc,
294		       BoxPtr      dst,
295		       INT32       *xa,
296		       INT32       *xb,
297		       INT32       *ya,
298		       INT32       *yb,
299		       RegionPtr   reg,
300		       INT32       width,
301		       INT32       height)
302{
303#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER
304    return radeon_crtc_clip_video_helper(pScrn, crtc_ret, desired_crtc,
305				       dst, xa, xb, ya, yb,
306				       reg, width, height);
307#else
308    return xf86_crtc_clip_video_helper(pScrn, crtc_ret, desired_crtc,
309				       dst, xa, xb, ya, yb,
310				       reg, width, height);
311#endif
312}
313
314void RADEONInitVideo(ScreenPtr pScreen)
315{
316    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
317    RADEONInfoPtr    info = RADEONPTR(pScrn);
318    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
319    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
320    XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
321    int num_adaptors;
322
323    /* no overlay or 3D on RN50 */
324    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2)
325	    return;
326
327    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
328    newAdaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
329    if (newAdaptors == NULL)
330	return;
331
332    memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
333    adaptors = newAdaptors;
334
335    if (!IS_AVIVO_VARIANT && !info->kms_enabled) {
336	overlayAdaptor = RADEONSetupImageVideo(pScreen);
337	if (overlayAdaptor != NULL) {
338	    adaptors[num_adaptors++] = overlayAdaptor;
339	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
340	} else
341	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up overlay video\n");
342	RADEONInitOffscreenImages(pScreen);
343    }
344
345    if ((info->ChipFamily < CHIP_FAMILY_RS400)
346#ifdef XF86DRI
347	|| (info->directRenderingEnabled)
348#endif
349	) {
350	texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);
351	if (texturedAdaptor != NULL) {
352	    adaptors[num_adaptors++] = texturedAdaptor;
353	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
354	} else
355	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video\n");
356    } else
357	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textured video requires CP on R5xx/R6xx/R7xx/IGP\n");
358
359    if(num_adaptors)
360	xf86XVScreenInit(pScreen, adaptors, num_adaptors);
361
362    if(texturedAdaptor) {
363	XF86MCAdaptorPtr xvmcAdaptor = RADEONCreateAdaptorXvMC(pScreen, texturedAdaptor->name);
364	if(xvmcAdaptor) {
365	    if(!xf86XvMCScreenInit(pScreen, 1, &xvmcAdaptor))
366		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] Failed to initialize extension.\n");
367	    else
368		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[XvMC] Extension initialized.\n");
369	}
370    }
371
372    if(newAdaptors)
373	free(newAdaptors);
374
375}
376
377/* client libraries expect an encoding */
378static XF86VideoEncodingRec DummyEncoding =
379{
380   0,
381   "XV_IMAGE",
382   2047, 2047,
383   {1, 1}
384};
385
386 /* the picture is interlaced - hence the half-heights */
387
388static XF86VideoEncodingRec
389InputVideoEncodings[] =
390{
391    { 0, "XV_IMAGE",			2047,2047,{1,1}},
392    { 1, "pal-composite",		720, 288, { 1, 50 }},
393    { 2, "pal-tuner",			720, 288, { 1, 50 }},
394    { 3, "pal-svideo",			720, 288, { 1, 50 }},
395    { 4, "ntsc-composite",		640, 240, { 1001, 60000 }},
396    { 5, "ntsc-tuner",			640, 240, { 1001, 60000 }},
397    { 6, "ntsc-svideo",			640, 240, { 1001, 60000 }},
398    { 7, "secam-composite",		720, 288, { 1, 50 }},
399    { 8, "secam-tuner",			720, 288, { 1, 50 }},
400    { 9, "secam-svideo",		720, 288, { 1, 50 }},
401    { 10,"pal_60-composite",		768, 288, { 1, 50 }},
402    { 11,"pal_60-tuner",		768, 288, { 1, 50 }},
403    { 12,"pal_60-svideo",		768, 288, { 1, 50 }}
404};
405
406
407#define NUM_FORMATS 12
408
409static XF86VideoFormatRec Formats[NUM_FORMATS] =
410{
411   {8, TrueColor}, {8, DirectColor}, {8, PseudoColor},
412   {8, GrayScale}, {8, StaticGray}, {8, StaticColor},
413   {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
414   {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
415};
416
417
418#if 0
419#define NUM_ATTRIBUTES 9+6
420
421static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
422{
423   {XvSettable             ,     0,    1, "XV_SET_DEFAULTS"},
424   {XvSettable | XvGettable,     0,    1, "XV_AUTOPAINT_COLORKEY"},
425   {XvSettable | XvGettable,     0,   ~0, "XV_COLORKEY"},
426   {XvSettable | XvGettable,     0,    1, "XV_DOUBLE_BUFFER"},
427   {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
428   {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
429   {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
430   {XvSettable | XvGettable, -1000, 1000, "XV_COLOR"},
431   {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
432   {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"},
433   {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"},
434   {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"},
435   {XvSettable | XvGettable,     -1,    1, "XV_CRTC"},
436   {XvSettable | XvGettable,   100, 10000, "XV_GAMMA"},
437   {XvSettable | XvGettable,     0,    1, "XV_COLORSPACE"},
438};
439
440#endif
441
442#define NUM_ATTRIBUTES 22
443#define NUM_DEC_ATTRIBUTES (NUM_ATTRIBUTES+12)
444
445static XF86AttributeRec Attributes[NUM_DEC_ATTRIBUTES+1] =
446{
447   {             XvGettable, 0, ~0, "XV_DEVICE_ID"},
448   {             XvGettable, 0, ~0, "XV_LOCATION_ID"},
449   {             XvGettable, 0, ~0, "XV_INSTANCE_ID"},
450   {XvSettable		   , 0, 1, "XV_DUMP_STATUS"},
451   {XvSettable             , 0, 1, "XV_SET_DEFAULTS"},
452   {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
453   {XvSettable | XvGettable, 0, ~0,"XV_COLORKEY"},
454   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
455   {XvSettable | XvGettable,     0,  255, "XV_OVERLAY_ALPHA"},
456   {XvSettable | XvGettable,     0,  255, "XV_GRAPHICS_ALPHA"},
457   {XvSettable | XvGettable,     0,    1, "XV_ALPHA_MODE"},
458   {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
459   {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
460   {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
461   {XvSettable | XvGettable, -1000, 1000, "XV_COLOR"},
462   {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
463   {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"},
464   {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"},
465   {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"},
466   {XvSettable | XvGettable,     -1,    1, "XV_CRTC"},
467   {XvSettable | XvGettable,   100, 10000, "XV_GAMMA"},
468   {XvSettable | XvGettable,     0,    1, "XV_COLORSPACE"},
469
470   {XvSettable | XvGettable, -1000, 1000, "XV_DEC_BRIGHTNESS"},
471   {XvSettable | XvGettable, -1000, 1000, "XV_DEC_CONTRAST"},
472   {XvSettable | XvGettable, -1000, 1000, "XV_DEC_SATURATION"},
473   {XvSettable | XvGettable, -1000, 1000, "XV_DEC_HUE"},
474   {XvSettable | XvGettable, 0, 2, "XV_OVERLAY_DEINTERLACING_METHOD"},
475   {XvSettable | XvGettable, 0, 12, "XV_ENCODING"},
476   {XvSettable | XvGettable, 0, -1, "XV_FREQ"},
477   {             XvGettable, -1000, 1000, "XV_TUNER_STATUS"},
478   {XvSettable | XvGettable, -1000, 1000, "XV_VOLUME"},
479   {XvSettable | XvGettable, 0, 1, "XV_MUTE"},
480   {XvSettable | XvGettable, 0, 1, "XV_SAP"},
481   {XvSettable | XvGettable, 0, 0x1F, "XV_DEBUG_ADJUSTMENT"},
482   { 0, 0, 0, NULL}  /* just a place holder so I don't have to be fancy with commas */
483};
484
485
486#define INCLUDE_RGB_FORMATS 1
487
488#if INCLUDE_RGB_FORMATS
489
490#define NUM_IMAGES 8
491
492/* Note: GUIDs are bogus... - but nothing uses them anyway */
493
494#define FOURCC_RGBA32   0x41424752
495
496#define XVIMAGE_RGBA32(byte_order)   \
497        { \
498                FOURCC_RGBA32, \
499                XvRGB, \
500                byte_order, \
501                { 'R', 'G', 'B', 'A', \
502                  0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
503                32, \
504                XvPacked, \
505                1, \
506                32, 0x00FF0000, 0x0000FF00, 0x000000FF, \
507                0, 0, 0, 0, 0, 0, 0, 0, 0, \
508                {'A', 'R', 'G', 'B', \
509                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
510                XvTopToBottom \
511        }
512
513#define FOURCC_RGB24    0x00000000
514
515#define XVIMAGE_RGB24   \
516        { \
517                FOURCC_RGB24, \
518                XvRGB, \
519                LSBFirst, \
520                { 'R', 'G', 'B', 0, \
521                  0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
522                24, \
523                XvPacked, \
524                1, \
525                24, 0x00FF0000, 0x0000FF00, 0x000000FF, \
526                0, 0, 0, 0, 0, 0, 0, 0, 0, \
527                { 'R', 'G', 'B', \
528                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
529                XvTopToBottom \
530        }
531
532#define FOURCC_RGBT16   0x54424752
533
534#define XVIMAGE_RGBT16(byte_order)   \
535        { \
536                FOURCC_RGBT16, \
537                XvRGB, \
538                byte_order, \
539                { 'R', 'G', 'B', 'T', \
540                  0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
541                16, \
542                XvPacked, \
543                1, \
544                16, 0x00007C00, 0x000003E0, 0x0000001F, \
545                0, 0, 0, 0, 0, 0, 0, 0, 0, \
546                {'A', 'R', 'G', 'B', \
547                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
548                XvTopToBottom \
549        }
550
551#define FOURCC_RGB16    0x32424752
552
553#define XVIMAGE_RGB16(byte_order)   \
554        { \
555                FOURCC_RGB16, \
556                XvRGB, \
557                byte_order, \
558                { 'R', 'G', 'B', 0x00, \
559                  0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
560                16, \
561                XvPacked, \
562                1, \
563                16, 0x0000F800, 0x000007E0, 0x0000001F, \
564                0, 0, 0, 0, 0, 0, 0, 0, 0, \
565                {'R', 'G', 'B', \
566                  0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
567                XvTopToBottom \
568        }
569
570static XF86ImageRec Images[NUM_IMAGES] =
571{
572#if X_BYTE_ORDER == X_BIG_ENDIAN
573        XVIMAGE_RGBA32(MSBFirst),
574        XVIMAGE_RGBT16(MSBFirst),
575        XVIMAGE_RGB16(MSBFirst),
576#else
577        XVIMAGE_RGBA32(LSBFirst),
578        XVIMAGE_RGBT16(LSBFirst),
579        XVIMAGE_RGB16(LSBFirst),
580#endif
581        XVIMAGE_RGB24,
582        XVIMAGE_YUY2,
583        XVIMAGE_UYVY,
584        XVIMAGE_YV12,
585        XVIMAGE_I420
586};
587
588#else
589
590#define NUM_IMAGES 4
591
592static XF86ImageRec Images[NUM_IMAGES] =
593{
594    XVIMAGE_YUY2,
595    XVIMAGE_UYVY,
596    XVIMAGE_YV12,
597    XVIMAGE_I420
598};
599
600#endif
601
602/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
603static REF_TRANSFORM trans[2] =
604{
605    {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
606    {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0}  /* BT.709 */
607};
608
609/* Gamma curve definition for preset gammas */
610typedef struct tagGAMMA_CURVE_R100
611{
612    uint32_t GAMMA_0_F_SLOPE;
613    uint32_t GAMMA_0_F_OFFSET;
614    uint32_t GAMMA_10_1F_SLOPE;
615    uint32_t GAMMA_10_1F_OFFSET;
616    uint32_t GAMMA_20_3F_SLOPE;
617    uint32_t GAMMA_20_3F_OFFSET;
618    uint32_t GAMMA_40_7F_SLOPE;
619    uint32_t GAMMA_40_7F_OFFSET;
620    uint32_t GAMMA_380_3BF_SLOPE;
621    uint32_t GAMMA_380_3BF_OFFSET;
622    uint32_t GAMMA_3C0_3FF_SLOPE;
623    uint32_t GAMMA_3C0_3FF_OFFSET;
624    float OvGammaCont;
625} GAMMA_CURVE_R100;
626
627typedef struct tagGAMMA_CURVE_R200
628{
629    uint32_t GAMMA_0_F_SLOPE;
630    uint32_t GAMMA_0_F_OFFSET;
631    uint32_t GAMMA_10_1F_SLOPE;
632    uint32_t GAMMA_10_1F_OFFSET;
633    uint32_t GAMMA_20_3F_SLOPE;
634    uint32_t GAMMA_20_3F_OFFSET;
635    uint32_t GAMMA_40_7F_SLOPE;
636    uint32_t GAMMA_40_7F_OFFSET;
637    uint32_t GAMMA_80_BF_SLOPE;
638    uint32_t GAMMA_80_BF_OFFSET;
639    uint32_t GAMMA_C0_FF_SLOPE;
640    uint32_t GAMMA_C0_FF_OFFSET;
641    uint32_t GAMMA_100_13F_SLOPE;
642    uint32_t GAMMA_100_13F_OFFSET;
643    uint32_t GAMMA_140_17F_SLOPE;
644    uint32_t GAMMA_140_17F_OFFSET;
645    uint32_t GAMMA_180_1BF_SLOPE;
646    uint32_t GAMMA_180_1BF_OFFSET;
647    uint32_t GAMMA_1C0_1FF_SLOPE;
648    uint32_t GAMMA_1C0_1FF_OFFSET;
649    uint32_t GAMMA_200_23F_SLOPE;
650    uint32_t GAMMA_200_23F_OFFSET;
651    uint32_t GAMMA_240_27F_SLOPE;
652    uint32_t GAMMA_240_27F_OFFSET;
653    uint32_t GAMMA_280_2BF_SLOPE;
654    uint32_t GAMMA_280_2BF_OFFSET;
655    uint32_t GAMMA_2C0_2FF_SLOPE;
656    uint32_t GAMMA_2C0_2FF_OFFSET;
657    uint32_t GAMMA_300_33F_SLOPE;
658    uint32_t GAMMA_300_33F_OFFSET;
659    uint32_t GAMMA_340_37F_SLOPE;
660    uint32_t GAMMA_340_37F_OFFSET;
661    uint32_t GAMMA_380_3BF_SLOPE;
662    uint32_t GAMMA_380_3BF_OFFSET;
663    uint32_t GAMMA_3C0_3FF_SLOPE;
664    uint32_t GAMMA_3C0_3FF_OFFSET;
665    float OvGammaCont;
666} GAMMA_CURVE_R200;
667
668
669/* Preset gammas */
670static GAMMA_CURVE_R100 gamma_curve_r100[8] =
671{
672	/* Gamma 1.0 */
673	{0x100, 0x0,
674	 0x100, 0x20,
675	 0x100, 0x40,
676	 0x100, 0x80,
677	 0x100, 0x100,
678	 0x100, 0x100,
679	 1.0},
680	/* Gamma 0.85 */
681	{0x75,  0x0,
682	 0xA2,  0xF,
683	 0xAC,  0x23,
684	 0xC6,  0x4E,
685	 0x129, 0xD6,
686	 0x12B, 0xD5,
687	 1.0},
688	/* Gamma 1.1 */
689	{0x180, 0x0,
690	 0x13C, 0x30,
691	 0x13C, 0x57,
692	 0x123, 0xA5,
693	 0xEA,  0x116,
694	 0xEA, 0x116,
695	 0.9913},
696	/* Gamma 1.2 */
697	{0x21B, 0x0,
698	 0x16D, 0x43,
699	 0x172, 0x71,
700	 0x13D, 0xCD,
701	 0xD9,  0x128,
702	 0xD6, 0x12A,
703	 0.9827},
704	/* Gamma 1.45 */
705	{0x404, 0x0,
706	 0x1B9, 0x81,
707	 0x1EE, 0xB8,
708	 0x16A, 0x133,
709	 0xB7, 0x14B,
710	 0xB2, 0x14E,
711	 0.9567},
712	/* Gamma 1.7 */
713	{0x658, 0x0,
714	 0x1B5, 0xCB,
715	 0x25F, 0x102,
716	 0x181, 0x199,
717	 0x9C,  0x165,
718	 0x98, 0x167,
719	 0.9394},
720	/* Gamma 2.2 */
721	{0x7FF, 0x0,
722	 0x625, 0x100,
723	 0x1E4, 0x1C4,
724	 0x1BD, 0x23D,
725	 0x79,  0x187,
726	 0x76,  0x188,
727	 0.9135},
728	/* Gamma 2.5 */
729	{0x7FF, 0x0,
730	 0x7FF, 0x100,
731	 0x2AD, 0x200,
732	 0x1A2, 0x2AB,
733	 0x6E,  0x194,
734	 0x67,  0x197,
735	 0.9135}
736};
737
738static GAMMA_CURVE_R200 gamma_curve_r200[8] =
739 {
740	/* Gamma 1.0 */
741      {0x00000100, 0x00000000,
742       0x00000100, 0x00000020,
743       0x00000100, 0x00000040,
744       0x00000100, 0x00000080,
745       0x00000100, 0x00000100,
746       0x00000100, 0x00000100,
747       0x00000100, 0x00000200,
748       0x00000100, 0x00000200,
749       0x00000100, 0x00000300,
750       0x00000100, 0x00000300,
751       0x00000100, 0x00000400,
752       0x00000100, 0x00000400,
753       0x00000100, 0x00000500,
754       0x00000100, 0x00000500,
755       0x00000100, 0x00000600,
756       0x00000100, 0x00000600,
757       0x00000100, 0x00000700,
758       0x00000100, 0x00000700,
759       1.0},
760	/* Gamma 0.85 */
761      {0x0000001D, 0x00000000,
762       0x00000028, 0x0000000F,
763       0x00000056, 0x00000023,
764       0x000000C5, 0x0000004E,
765       0x000000DA, 0x000000B0,
766       0x000000E6, 0x000000AA,
767       0x000000F1, 0x00000190,
768       0x000000F9, 0x0000018C,
769       0x00000101, 0x00000286,
770       0x00000108, 0x00000282,
771       0x0000010D, 0x0000038A,
772       0x00000113, 0x00000387,
773       0x00000118, 0x0000049A,
774       0x0000011C, 0x00000498,
775       0x00000120, 0x000005B4,
776       0x00000124, 0x000005B2,
777       0x00000128, 0x000006D6,
778       0x0000012C, 0x000006D5,
779       1.0},
780	/* Gamma 1.1 */
781      {0x00000060, 0x00000000,
782       0x0000004F, 0x00000030,
783       0x0000009C, 0x00000057,
784       0x00000121, 0x000000A5,
785       0x00000113, 0x00000136,
786       0x0000010B, 0x0000013A,
787       0x00000105, 0x00000245,
788       0x00000100, 0x00000247,
789       0x000000FD, 0x00000348,
790       0x000000F9, 0x00000349,
791       0x000000F6, 0x00000443,
792       0x000000F4, 0x00000444,
793       0x000000F2, 0x00000538,
794       0x000000F0, 0x00000539,
795       0x000000EE, 0x00000629,
796       0x000000EC, 0x00000629,
797       0x000000EB, 0x00000716,
798       0x000000E9, 0x00000717,
799       0.9913},
800	/* Gamma 1.2 */
801      {0x00000087, 0x00000000,
802       0x0000005B, 0x00000043,
803       0x000000B7, 0x00000071,
804       0x0000013D, 0x000000CD,
805       0x00000121, 0x0000016B,
806       0x00000113, 0x00000172,
807       0x00000107, 0x00000286,
808       0x000000FF, 0x0000028A,
809       0x000000F8, 0x00000389,
810       0x000000F2, 0x0000038B,
811       0x000000ED, 0x0000047D,
812       0x000000E9, 0x00000480,
813       0x000000E5, 0x00000568,
814       0x000000E1, 0x0000056A,
815       0x000000DE, 0x0000064B,
816       0x000000DB, 0x0000064D,
817       0x000000D9, 0x00000728,
818       0x000000D6, 0x00000729,
819       0.9827},
820	/* Gamma 1.45 */
821      {0x00000101, 0x00000000,
822       0x0000006E, 0x00000081,
823       0x000000F7, 0x000000B8,
824       0x0000016E, 0x00000133,
825       0x00000139, 0x000001EA,
826       0x0000011B, 0x000001F9,
827       0x00000105, 0x00000314,
828       0x000000F6, 0x0000031C,
829       0x000000E9, 0x00000411,
830       0x000000DF, 0x00000417,
831       0x000000D7, 0x000004F6,
832       0x000000CF, 0x000004F9,
833       0x000000C9, 0x000005C9,
834       0x000000C4, 0x000005CC,
835       0x000000BF, 0x0000068F,
836       0x000000BA, 0x00000691,
837       0x000000B6, 0x0000074B,
838       0x000000B2, 0x0000074D,
839       0.9567},
840	/* Gamma 1.7 */
841      {0x00000196, 0x00000000,
842       0x0000006D, 0x000000CB,
843       0x0000012F, 0x00000102,
844       0x00000187, 0x00000199,
845       0x00000144, 0x0000025b,
846       0x00000118, 0x00000273,
847       0x000000FE, 0x0000038B,
848       0x000000E9, 0x00000395,
849       0x000000DA, 0x0000047E,
850       0x000000CE, 0x00000485,
851       0x000000C3, 0x00000552,
852       0x000000BB, 0x00000556,
853       0x000000B3, 0x00000611,
854       0x000000AC, 0x00000614,
855       0x000000A7, 0x000006C1,
856       0x000000A1, 0x000006C3,
857       0x0000009D, 0x00000765,
858       0x00000098, 0x00000767,
859       0.9394},
860	/* Gamma 2.2 */
861      {0x000001FF, 0x00000000,
862       0x0000018A, 0x00000100,
863       0x000000F1, 0x000001C5,
864       0x000001D6, 0x0000023D,
865       0x00000124, 0x00000328,
866       0x00000116, 0x0000032F,
867       0x000000E2, 0x00000446,
868       0x000000D3, 0x0000044D,
869       0x000000BC, 0x00000520,
870       0x000000B0, 0x00000526,
871       0x000000A4, 0x000005D6,
872       0x0000009B, 0x000005DB,
873       0x00000092, 0x00000676,
874       0x0000008B, 0x00000679,
875       0x00000085, 0x00000704,
876       0x00000080, 0x00000707,
877       0x0000007B, 0x00000787,
878       0x00000076, 0x00000789,
879       0.9135},
880	/* Gamma 2.5 */
881      {0x000001FF, 0x00000000,
882       0x000001FF, 0x00000100,
883       0x00000159, 0x000001FF,
884       0x000001AC, 0x000002AB,
885       0x0000012F, 0x00000381,
886       0x00000101, 0x00000399,
887       0x000000D9, 0x0000049A,
888       0x000000C3, 0x000004A5,
889       0x000000AF, 0x00000567,
890       0x000000A1, 0x0000056E,
891       0x00000095, 0x00000610,
892       0x0000008C, 0x00000614,
893       0x00000084, 0x000006A0,
894       0x0000007D, 0x000006A4,
895       0x00000077, 0x00000721,
896       0x00000071, 0x00000723,
897       0x0000006D, 0x00000795,
898       0x00000068, 0x00000797,
899       0.9135}
900};
901
902static void
903RADEONSetOverlayGamma(ScrnInfoPtr pScrn, uint32_t gamma)
904{
905    RADEONInfoPtr    info = RADEONPTR(pScrn);
906    unsigned char   *RADEONMMIO = info->MMIO;
907
908    /* Set gamma */
909    RADEONWaitForIdleMMIO(pScrn);
910
911    if (info->ChipFamily < CHIP_FAMILY_R200) {
912	uint32_t ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL) & ~RADEON_SCALER_GAMMA_SEL_MASK;
913	OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl | (gamma << 5));
914    }
915
916    /* Load gamma curve adjustments */
917    if (info->ChipFamily >= CHIP_FAMILY_R200) {
918    	OUTREG(RADEON_OV0_GAMMA_000_00F,
919	    (gamma_curve_r200[gamma].GAMMA_0_F_OFFSET << 0x00000000) |
920	    (gamma_curve_r200[gamma].GAMMA_0_F_SLOPE << 0x00000010));
921    	OUTREG(RADEON_OV0_GAMMA_010_01F,
922	    (gamma_curve_r200[gamma].GAMMA_10_1F_OFFSET << 0x00000000) |
923	    (gamma_curve_r200[gamma].GAMMA_10_1F_SLOPE << 0x00000010));
924    	OUTREG(RADEON_OV0_GAMMA_020_03F,
925	    (gamma_curve_r200[gamma].GAMMA_20_3F_OFFSET << 0x00000000) |
926	    (gamma_curve_r200[gamma].GAMMA_20_3F_SLOPE << 0x00000010));
927    	OUTREG(RADEON_OV0_GAMMA_040_07F,
928	    (gamma_curve_r200[gamma].GAMMA_40_7F_OFFSET << 0x00000000) |
929	    (gamma_curve_r200[gamma].GAMMA_40_7F_SLOPE << 0x00000010));
930    	OUTREG(RADEON_OV0_GAMMA_080_0BF,
931	    (gamma_curve_r200[gamma].GAMMA_80_BF_OFFSET << 0x00000000) |
932	    (gamma_curve_r200[gamma].GAMMA_80_BF_SLOPE << 0x00000010));
933    	OUTREG(RADEON_OV0_GAMMA_0C0_0FF,
934	    (gamma_curve_r200[gamma].GAMMA_C0_FF_OFFSET << 0x00000000) |
935	    (gamma_curve_r200[gamma].GAMMA_C0_FF_SLOPE << 0x00000010));
936    	OUTREG(RADEON_OV0_GAMMA_100_13F,
937	    (gamma_curve_r200[gamma].GAMMA_100_13F_OFFSET << 0x00000000) |
938	    (gamma_curve_r200[gamma].GAMMA_100_13F_SLOPE << 0x00000010));
939    	OUTREG(RADEON_OV0_GAMMA_140_17F,
940	    (gamma_curve_r200[gamma].GAMMA_140_17F_OFFSET << 0x00000000) |
941	    (gamma_curve_r200[gamma].GAMMA_140_17F_SLOPE << 0x00000010));
942    	OUTREG(RADEON_OV0_GAMMA_180_1BF,
943	    (gamma_curve_r200[gamma].GAMMA_180_1BF_OFFSET << 0x00000000) |
944	    (gamma_curve_r200[gamma].GAMMA_180_1BF_SLOPE << 0x00000010));
945    	OUTREG(RADEON_OV0_GAMMA_1C0_1FF,
946	    (gamma_curve_r200[gamma].GAMMA_1C0_1FF_OFFSET << 0x00000000) |
947	    (gamma_curve_r200[gamma].GAMMA_1C0_1FF_SLOPE << 0x00000010));
948    	OUTREG(RADEON_OV0_GAMMA_200_23F,
949	    (gamma_curve_r200[gamma].GAMMA_200_23F_OFFSET << 0x00000000) |
950	    (gamma_curve_r200[gamma].GAMMA_200_23F_SLOPE << 0x00000010));
951    	OUTREG(RADEON_OV0_GAMMA_240_27F,
952	    (gamma_curve_r200[gamma].GAMMA_240_27F_OFFSET << 0x00000000) |
953	    (gamma_curve_r200[gamma].GAMMA_240_27F_SLOPE << 0x00000010));
954    	OUTREG(RADEON_OV0_GAMMA_280_2BF,
955	    (gamma_curve_r200[gamma].GAMMA_280_2BF_OFFSET << 0x00000000) |
956	    (gamma_curve_r200[gamma].GAMMA_280_2BF_SLOPE << 0x00000010));
957    	OUTREG(RADEON_OV0_GAMMA_2C0_2FF,
958	    (gamma_curve_r200[gamma].GAMMA_2C0_2FF_OFFSET << 0x00000000) |
959	    (gamma_curve_r200[gamma].GAMMA_2C0_2FF_SLOPE << 0x00000010));
960    	OUTREG(RADEON_OV0_GAMMA_300_33F,
961	    (gamma_curve_r200[gamma].GAMMA_300_33F_OFFSET << 0x00000000) |
962	    (gamma_curve_r200[gamma].GAMMA_300_33F_SLOPE << 0x00000010));
963    	OUTREG(RADEON_OV0_GAMMA_340_37F,
964	    (gamma_curve_r200[gamma].GAMMA_340_37F_OFFSET << 0x00000000) |
965	    (gamma_curve_r200[gamma].GAMMA_340_37F_SLOPE << 0x00000010));
966    	OUTREG(RADEON_OV0_GAMMA_380_3BF,
967	    (gamma_curve_r200[gamma].GAMMA_380_3BF_OFFSET << 0x00000000) |
968	    (gamma_curve_r200[gamma].GAMMA_380_3BF_SLOPE << 0x00000010));
969    	OUTREG(RADEON_OV0_GAMMA_3C0_3FF,
970	    (gamma_curve_r200[gamma].GAMMA_3C0_3FF_OFFSET << 0x00000000) |
971	    (gamma_curve_r200[gamma].GAMMA_3C0_3FF_SLOPE << 0x00000010));
972    } else {
973    	OUTREG(RADEON_OV0_GAMMA_000_00F,
974	    (gamma_curve_r100[gamma].GAMMA_0_F_OFFSET << 0x00000000) |
975	    (gamma_curve_r100[gamma].GAMMA_0_F_SLOPE << 0x00000010));
976    	OUTREG(RADEON_OV0_GAMMA_010_01F,
977	    (gamma_curve_r100[gamma].GAMMA_10_1F_OFFSET << 0x00000000) |
978	    (gamma_curve_r100[gamma].GAMMA_10_1F_SLOPE << 0x00000010));
979    	OUTREG(RADEON_OV0_GAMMA_020_03F,
980	    (gamma_curve_r100[gamma].GAMMA_20_3F_OFFSET << 0x00000000) |
981	    (gamma_curve_r100[gamma].GAMMA_20_3F_SLOPE << 0x00000010));
982    	OUTREG(RADEON_OV0_GAMMA_040_07F,
983	    (gamma_curve_r100[gamma].GAMMA_40_7F_OFFSET << 0x00000000) |
984	    (gamma_curve_r100[gamma].GAMMA_40_7F_SLOPE << 0x00000010));
985    	OUTREG(RADEON_OV0_GAMMA_380_3BF,
986	    (gamma_curve_r100[gamma].GAMMA_380_3BF_OFFSET << 0x00000000) |
987	    (gamma_curve_r100[gamma].GAMMA_380_3BF_SLOPE << 0x00000010));
988    	OUTREG(RADEON_OV0_GAMMA_3C0_3FF,
989	    (gamma_curve_r100[gamma].GAMMA_3C0_3FF_OFFSET << 0x00000000) |
990	    (gamma_curve_r100[gamma].GAMMA_3C0_3FF_SLOPE << 0x00000010));
991    }
992
993}
994
995static uint32_t
996RADEONTranslateUserGamma(uint32_t user_gamma)
997{
998    /* translate from user_gamma (gamma x 1000) to radeon gamma table index value */
999    if (user_gamma <= 925)       /* 0.85 */
1000	return 1;
1001    else if (user_gamma <= 1050) /* 1.0  */
1002	return 0;
1003    else if (user_gamma <= 1150) /* 1.1  */
1004	return 2;
1005    else if (user_gamma <= 1325) /* 1.2  */
1006	return 3;
1007    else if (user_gamma <= 1575) /* 1.45 */
1008	return 4;
1009    else if (user_gamma <= 1950) /* 1.7  */
1010	return 5;
1011    else if (user_gamma <= 2350) /* 2.2  */
1012	return 6;
1013    else if (user_gamma > 2350)  /* 2.5  */
1014	return 7;
1015    else
1016	return 0;
1017}
1018
1019
1020/****************************************************************************
1021 * SetTransform                                                             *
1022 *  Function: Calculates and sets color space transform from supplied       *
1023 *            reference transform, gamma, brightness, contrast, hue and     *
1024 *            saturation.                                                   *
1025 *    Inputs: bright - brightness                                           *
1026 *            cont - contrast                                               *
1027 *            sat - saturation                                              *
1028 *            hue - hue                                                     *
1029 *            red_intensity - intensity of red component                    *
1030 *            green_intensity - intensity of green component                *
1031 *            blue_intensity - intensity of blue component                  *
1032 *            ref - index to the table of refernce transforms               *
1033 *            user_gamma - gamma value x 1000 (e.g., 1200 = gamma of 1.2)   *
1034 *   Outputs: NONE                                                          *
1035 ****************************************************************************/
1036
1037static void RADEONSetTransform (ScrnInfoPtr pScrn,
1038				float	    bright,
1039				float	    cont,
1040				float	    sat,
1041				float	    hue,
1042				float	    red_intensity,
1043				float	    green_intensity,
1044				float	    blue_intensity,
1045				uint32_t    ref,
1046				uint32_t    user_gamma)
1047{
1048    RADEONInfoPtr    info = RADEONPTR(pScrn);
1049    unsigned char   *RADEONMMIO = info->MMIO;
1050    float	    OvHueSin, OvHueCos;
1051    float	    CAdjLuma, CAdjOff;
1052    float	    CAdjRCb, CAdjRCr;
1053    float	    CAdjGCb, CAdjGCr;
1054    float	    CAdjBCb, CAdjBCr;
1055    float	    RedAdj,GreenAdj,BlueAdj;
1056    float	    OvLuma, OvROff, OvGOff, OvBOff;
1057    float	    OvRCb, OvRCr;
1058    float	    OvGCb, OvGCr;
1059    float	    OvBCb, OvBCr;
1060    float	    Loff = 64.0;
1061    float	    Coff = 512.0f;
1062
1063    uint32_t	    dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
1064    uint32_t	    dwOvRCb, dwOvRCr;
1065    uint32_t	    dwOvGCb, dwOvGCr;
1066    uint32_t	    dwOvBCb, dwOvBCr;
1067    uint32_t	    gamma = 0;
1068
1069    if (ref >= 2)
1070	return;
1071
1072    /* translate from user_gamma (gamma x 1000) to radeon gamma table index value */
1073    gamma = RADEONTranslateUserGamma(user_gamma);
1074
1075    if (gamma >= 8)
1076	return;
1077
1078    OvHueSin = sin(hue);
1079    OvHueCos = cos(hue);
1080
1081    CAdjLuma = cont * trans[ref].RefLuma;
1082    CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
1083    RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
1084    GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
1085    BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
1086
1087    CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
1088    CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
1089    CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
1090    CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
1091    CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
1092    CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
1093
1094#if 0 /* default constants */
1095    CAdjLuma = 1.16455078125;
1096
1097    CAdjRCb = 0.0;
1098    CAdjRCr = 1.59619140625;
1099    CAdjGCb = -0.39111328125;
1100    CAdjGCr = -0.8125;
1101    CAdjBCb = 2.01708984375;
1102    CAdjBCr = 0;
1103#endif
1104
1105    OvLuma = CAdjLuma * gamma_curve_r100[gamma].OvGammaCont;
1106    OvRCb = CAdjRCb * gamma_curve_r100[gamma].OvGammaCont;
1107    OvRCr = CAdjRCr * gamma_curve_r100[gamma].OvGammaCont;
1108    OvGCb = CAdjGCb * gamma_curve_r100[gamma].OvGammaCont;
1109    OvGCr = CAdjGCr * gamma_curve_r100[gamma].OvGammaCont;
1110    OvBCb = CAdjBCb * gamma_curve_r100[gamma].OvGammaCont;
1111    OvBCr = CAdjBCr * gamma_curve_r100[gamma].OvGammaCont;
1112    OvROff = RedAdj + CAdjOff * gamma_curve_r100[gamma].OvGammaCont -
1113	OvLuma * Loff - (OvRCb + OvRCr) * Coff;
1114    OvGOff = GreenAdj + CAdjOff * gamma_curve_r100[gamma].OvGammaCont -
1115	OvLuma * Loff - (OvGCb + OvGCr) * Coff;
1116    OvBOff = BlueAdj + CAdjOff * gamma_curve_r100[gamma].OvGammaCont -
1117	OvLuma * Loff - (OvBCb + OvBCr) * Coff;
1118#if 0 /* default constants */
1119    OvROff = -888.5;
1120    OvGOff = 545;
1121    OvBOff = -1104;
1122#endif
1123
1124    OvROff = ClipValue(OvROff, -2048.0, 2047.5);
1125    OvGOff = ClipValue(OvGOff, -2048.0, 2047.5);
1126    OvBOff = ClipValue(OvBOff, -2048.0, 2047.5);
1127    dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff;
1128    dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff;
1129    dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff;
1130
1131    if(info->ChipFamily == CHIP_FAMILY_RADEON)
1132    {
1133	dwOvLuma =(((INT32)(OvLuma * 2048.0))&0x7fff)<<17;
1134	dwOvRCb = (((INT32)(OvRCb * 2048.0))&0x7fff)<<1;
1135	dwOvRCr = (((INT32)(OvRCr * 2048.0))&0x7fff)<<17;
1136	dwOvGCb = (((INT32)(OvGCb * 2048.0))&0x7fff)<<1;
1137	dwOvGCr = (((INT32)(OvGCr * 2048.0))&0x7fff)<<17;
1138	dwOvBCb = (((INT32)(OvBCb * 2048.0))&0x7fff)<<1;
1139	dwOvBCr = (((INT32)(OvBCr * 2048.0))&0x7fff)<<17;
1140    }
1141    else
1142    {
1143	dwOvLuma = (((INT32)(OvLuma * 256.0))&0xfff)<<20;
1144	dwOvRCb = (((INT32)(OvRCb * 256.0))&0xfff)<<4;
1145	dwOvRCr = (((INT32)(OvRCr * 256.0))&0xfff)<<20;
1146	dwOvGCb = (((INT32)(OvGCb * 256.0))&0xfff)<<4;
1147	dwOvGCr = (((INT32)(OvGCr * 256.0))&0xfff)<<20;
1148	dwOvBCb = (((INT32)(OvBCb * 256.0))&0xfff)<<4;
1149	dwOvBCr = (((INT32)(OvBCr * 256.0))&0xfff)<<20;
1150    }
1151
1152    /* set gamma */
1153    RADEONSetOverlayGamma(pScrn, gamma);
1154
1155    /* color transforms */
1156    OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
1157    OUTREG(RADEON_OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
1158    OUTREG(RADEON_OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
1159    OUTREG(RADEON_OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
1160    OUTREG(RADEON_OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
1161    OUTREG(RADEON_OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
1162}
1163
1164static void RADEONSetOverlayAlpha(ScrnInfoPtr pScrn, int ov_alpha, int gr_alpha, int alpha_mode)
1165{
1166    RADEONInfoPtr info = RADEONPTR(pScrn);
1167    unsigned char *RADEONMMIO = info->MMIO;
1168
1169    if (alpha_mode == 0) { /* key mode */
1170    	OUTREG(RADEON_OV0_KEY_CNTL,
1171		RADEON_GRAPHIC_KEY_FN_EQ | /* what does this do? */
1172		RADEON_VIDEO_KEY_FN_FALSE | /* what does this do? */
1173		RADEON_CMP_MIX_OR);
1174    	/* crtc 1 */
1175    	OUTREG(RADEON_DISP_MERGE_CNTL,
1176		(RADEON_DISP_ALPHA_MODE_KEY &
1177		RADEON_DISP_ALPHA_MODE_MASK) |
1178		((gr_alpha << 0x00000010) &
1179		RADEON_DISP_GRPH_ALPHA_MASK) |
1180		((ov_alpha << 0x00000018) &
1181		RADEON_DISP_OV0_ALPHA_MASK));
1182    	/* crtc 2 */
1183    	OUTREG(RADEON_DISP2_MERGE_CNTL,
1184		(RADEON_DISP_ALPHA_MODE_KEY &
1185		RADEON_DISP_ALPHA_MODE_MASK) |
1186		((gr_alpha << 0x00000010) &
1187		RADEON_DISP_GRPH_ALPHA_MASK) |
1188		((ov_alpha << 0x00000018) &
1189		RADEON_DISP_OV0_ALPHA_MASK));
1190    } else { /* global mode */
1191    	OUTREG(RADEON_OV0_KEY_CNTL,
1192		RADEON_GRAPHIC_KEY_FN_FALSE |   /* what does this do? */
1193		RADEON_VIDEO_KEY_FN_FALSE |   /* what does this do? */
1194		RADEON_CMP_MIX_AND);
1195    	/* crtc 2 */
1196    	OUTREG(RADEON_DISP2_MERGE_CNTL,
1197		(RADEON_DISP_ALPHA_MODE_GLOBAL &
1198		RADEON_DISP_ALPHA_MODE_MASK) |
1199		((gr_alpha << 0x00000010) &
1200		RADEON_DISP_GRPH_ALPHA_MASK) |
1201		((ov_alpha << 0x00000018) &
1202		RADEON_DISP_OV0_ALPHA_MASK));
1203    	/* crtc 1 */
1204    	OUTREG(RADEON_DISP_MERGE_CNTL,
1205		(RADEON_DISP_ALPHA_MODE_GLOBAL &
1206		RADEON_DISP_ALPHA_MODE_MASK) |
1207		((gr_alpha << 0x00000010) &
1208		RADEON_DISP_GRPH_ALPHA_MASK) |
1209		((ov_alpha << 0x00000018) &
1210		RADEON_DISP_OV0_ALPHA_MASK));
1211    }
1212     /* per-pixel mode - RADEON_DISP_ALPHA_MODE_PER_PIXEL */
1213     /* not yet supported */
1214}
1215
1216static void RADEONSetColorKey(ScrnInfoPtr pScrn, uint32_t colorKey)
1217{
1218    RADEONInfoPtr info = RADEONPTR(pScrn);
1219    unsigned char *RADEONMMIO = info->MMIO;
1220    uint32_t min, max;
1221    uint8_t r, g, b;
1222
1223    if (info->CurrentLayout.depth > 8)
1224    {
1225	uint32_t	rbits, gbits, bbits;
1226
1227	rbits = (colorKey & pScrn->mask.red) >> pScrn->offset.red;
1228	gbits = (colorKey & pScrn->mask.green) >> pScrn->offset.green;
1229	bbits = (colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
1230
1231	r = rbits << (8 - pScrn->weight.red);
1232	g = gbits << (8 - pScrn->weight.green);
1233	b = bbits << (8 - pScrn->weight.blue);
1234    }
1235    else
1236    {
1237	uint32_t	bits;
1238
1239	bits = colorKey & ((1 << info->CurrentLayout.depth) - 1);
1240	r = bits;
1241	g = bits;
1242	b = bits;
1243    }
1244    min = (r << 16) | (g << 8) | (b);
1245    max = (0xff << 24) | (r << 16) | (g << 8) | (b);
1246
1247    RADEONWaitForFifo(pScrn, 2);
1248    OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_HIGH, max);
1249    OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_LOW, min);
1250}
1251
1252void
1253RADEONResetVideo(ScrnInfoPtr pScrn)
1254{
1255    RADEONInfoPtr   info      = RADEONPTR(pScrn);
1256    unsigned char *RADEONMMIO = info->MMIO;
1257    RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
1258    char tmp[200];
1259
1260    /* this function is called from ScreenInit. pScreen is used
1261       by XAA internally, but not valid until ScreenInit finishs.
1262    */
1263    if (info->accelOn && pScrn->pScreen)
1264	RADEON_SYNC(info, pScrn);
1265
1266    /* this is done here because each time the server is reset these
1267       could change.. Otherwise they remain constant */
1268    xvInstanceID = MAKE_ATOM("XV_INSTANCE_ID");
1269    xvDeviceID = MAKE_ATOM("XV_DEVICE_ID");
1270    xvLocationID = MAKE_ATOM("XV_LOCATION_ID");
1271    xvDumpStatus = MAKE_ATOM("XV_DUMP_STATUS");
1272
1273    xvBrightness   = MAKE_ATOM("XV_BRIGHTNESS");
1274    xvSaturation   = MAKE_ATOM("XV_SATURATION");
1275    xvColor        = MAKE_ATOM("XV_COLOR");
1276    xvContrast     = MAKE_ATOM("XV_CONTRAST");
1277    xvColorKey     = MAKE_ATOM("XV_COLORKEY");
1278    xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
1279    xvHue          = MAKE_ATOM("XV_HUE");
1280    xvRedIntensity   = MAKE_ATOM("XV_RED_INTENSITY");
1281    xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY");
1282    xvBlueIntensity  = MAKE_ATOM("XV_BLUE_INTENSITY");
1283    xvGamma          = MAKE_ATOM("XV_GAMMA");
1284    xvColorspace     = MAKE_ATOM("XV_COLORSPACE");
1285
1286    xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
1287    xvSetDefaults       = MAKE_ATOM("XV_SET_DEFAULTS");
1288    xvCRTC              = MAKE_ATOM("XV_CRTC");
1289
1290    xvOvAlpha	      = MAKE_ATOM("XV_OVERLAY_ALPHA");
1291    xvGrAlpha	      = MAKE_ATOM("XV_GRAPHICS_ALPHA");
1292    xvAlphaMode       = MAKE_ATOM("XV_ALPHA_MODE");
1293
1294    xvOverlayDeinterlacingMethod = MAKE_ATOM("XV_OVERLAY_DEINTERLACING_METHOD");
1295
1296    xvDecBrightness   = MAKE_ATOM("XV_DEC_BRIGHTNESS");
1297    xvDecSaturation   = MAKE_ATOM("XV_DEC_SATURATION");
1298    xvDecColor        = MAKE_ATOM("XV_DEC_COLOR");
1299    xvDecContrast     = MAKE_ATOM("XV_DEC_CONTRAST");
1300    xvDecHue          = MAKE_ATOM("XV_DEC_HUE");
1301
1302    xvEncoding        = MAKE_ATOM("XV_ENCODING");
1303    xvFrequency       = MAKE_ATOM("XV_FREQ");
1304    xvTunerStatus     = MAKE_ATOM("XV_TUNER_STATUS");
1305    xvVolume          = MAKE_ATOM("XV_VOLUME");
1306    xvMute            = MAKE_ATOM("XV_MUTE");
1307    xvSAP             = MAKE_ATOM("XV_SAP");
1308
1309    xvAdjustment      = MAKE_ATOM("XV_DEBUG_ADJUSTMENT");
1310
1311    sprintf(tmp, "RXXX:%d.%d.%d", PCI_DEV_VENDOR_ID(info->PciInfo),
1312	    PCI_DEV_DEVICE_ID(info->PciInfo), PCI_DEV_REVISION(info->PciInfo));
1313    pPriv->device_id = MAKE_ATOM(tmp);
1314    sprintf(tmp, "PCI:%02d:%02d.%d", PCI_DEV_BUS(info->PciInfo),
1315	    PCI_DEV_DEV(info->PciInfo), PCI_DEV_FUNC(info->PciInfo));
1316    pPriv->location_id = MAKE_ATOM(tmp);
1317    sprintf(tmp, "INSTANCE:%d", pScrn->scrnIndex);
1318    pPriv->instance_id = MAKE_ATOM(tmp);
1319
1320    OUTREG(RADEON_OV0_SCALE_CNTL, RADEON_SCALER_SOFT_RESET);
1321    OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0);   /* maybe */
1322    OUTREG(RADEON_OV0_EXCLUSIVE_HORZ, 0);
1323    OUTREG(RADEON_OV0_FILTER_CNTL, RADEON_FILTER_PROGRAMMABLE_COEF);
1324    OUTREG(RADEON_OV0_KEY_CNTL, RADEON_GRAPHIC_KEY_FN_EQ |
1325				RADEON_VIDEO_KEY_FN_FALSE |
1326				RADEON_CMP_MIX_OR);
1327    OUTREG(RADEON_OV0_TEST, 0);
1328    OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND);
1329    OUTREG(RADEON_CAP0_TRIG_CNTL, 0);
1330    RADEONSetColorKey(pScrn, pPriv->colorKey);
1331
1332    if (info->ChipFamily == CHIP_FAMILY_RADEON) {
1333
1334	OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000);
1335	OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e);
1336	OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0);
1337	OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442);
1338	OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040);
1339	OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
1340
1341    } else {
1342
1343	OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000);
1344	OUTREG(RADEON_OV0_LIN_TRANS_B, 0x198a190e);
1345	OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a2f9da);
1346	OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf2fe0442);
1347	OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a22046);
1348	OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
1349    }
1350	/*
1351	 * Set default Gamma ramp:
1352	 *
1353	 * Of 18 segments for gamma curve, all segments in R200 (and
1354	 * newer) are programmable, while only lower 4 and upper 2
1355	 * segments are programmable in the older Radeons.
1356	 */
1357
1358    RADEONSetOverlayGamma(pScrn, 0); /* gamma = 1.0 */
1359
1360    if(pPriv->VIP!=NULL){
1361        RADEONVIP_reset(pScrn,pPriv);
1362        }
1363
1364    if(pPriv->theatre != NULL) {
1365        xf86_InitTheatre(pPriv->theatre);
1366/*      xf86_ResetTheatreRegsForNoTVout(pPriv->theatre); */
1367        }
1368
1369    if(pPriv->i2c != NULL){
1370        RADEONResetI2C(pScrn, pPriv);
1371        }
1372}
1373
1374static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
1375{
1376    RADEONInfoPtr info = RADEONPTR(pScrn);
1377    RADEONPLLPtr  pll = &(info->pll);
1378    TheatrePtr t;
1379
1380    uint8_t a;
1381    int i;
1382
1383    pPriv->theatre = NULL;
1384
1385    if(!info->MM_TABLE_valid &&
1386       !((info->RageTheatreCrystal>=0) &&
1387           (info->RageTheatreTunerPort>=0) && (info->RageTheatreCompositePort>=0) &&
1388           (info->RageTheatreSVideoPort>=0)))
1389    {
1390       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no multimedia table present, disabling Rage Theatre.\n");
1391       return;
1392    }
1393
1394    /* Go and find Rage Theatre, if it exists */
1395
1396    if (info->IsMobility)
1397	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility, not scanning for Rage Theatre\n");
1398    else
1399	pPriv->theatre=xf86_DetectTheatre(pPriv->VIP);
1400
1401    if(pPriv->theatre==NULL)return;
1402
1403    /* just a matter of convenience */
1404    t=pPriv->theatre;
1405
1406    t->video_decoder_type=info->video_decoder_type;
1407
1408    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "video decoder type is 0x%04x (BIOS value) versus 0x%04x (current PLL setting)\n",
1409         t->video_decoder_type, pll->xclk);
1410
1411    if(info->MM_TABLE_valid){
1412         for(i=0;i<5;i++){
1413                a=info->MM_TABLE.input[i];
1414
1415                switch(a & 0x3){
1416                        case 1:
1417                                t->wTunerConnector=i;
1418                                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Tuner is on port %d\n",i);
1419                                break;
1420                        case 2:  if(a & 0x4){
1421                                   t->wComp0Connector=RT_COMP2;
1422                                   } else {
1423                                   t->wComp0Connector=RT_COMP1;
1424                                   }
1425                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %u\n", (unsigned)t->wComp0Connector);
1426                                  break;
1427                        case 3:  if(a & 0x4){
1428                                   t->wSVideo0Connector=RT_YCR_COMP4;
1429                                   } else {
1430                                   t->wSVideo0Connector=RT_YCF_COMP4;
1431                                   }
1432                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %u\n", (unsigned)t->wSVideo0Connector);
1433                                   break;
1434                        default:
1435                                break;
1436                        }
1437                }
1438        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%u, composite=%u, svideo=%u\n",
1439    	     (unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector);
1440
1441         }
1442
1443    if(info->RageTheatreTunerPort>=0)t->wTunerConnector=info->RageTheatreTunerPort;
1444    if(info->RageTheatreCompositePort>=0)t->wComp0Connector=info->RageTheatreCompositePort;
1445    if(info->RageTheatreSVideoPort>=0)t->wSVideo0Connector=info->RageTheatreSVideoPort;
1446
1447    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%u, composite=%u, svideo=%u\n",
1448    	(unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector);
1449
1450    switch((info->RageTheatreCrystal>=0)?info->RageTheatreCrystal:pll->reference_freq){
1451                case 2700:
1452                        t->video_decoder_type=RT_FREF_2700;
1453                        break;
1454                case 2950:
1455                        t->video_decoder_type=RT_FREF_2950;
1456                        break;
1457                default:
1458                        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1459                                "Unsupported reference clock frequency, Rage Theatre disabled\n");
1460                        t->theatre_num=-1;
1461			free(pPriv->theatre);
1462			pPriv->theatre = NULL;
1463			return;
1464                }
1465    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "video decoder type used: 0x%04x\n", t->video_decoder_type);
1466}
1467
1468static XF86VideoAdaptorPtr
1469RADEONAllocAdaptor(ScrnInfoPtr pScrn)
1470{
1471    XF86VideoAdaptorPtr adapt;
1472    RADEONInfoPtr info = RADEONPTR(pScrn);
1473    RADEONPortPrivPtr pPriv;
1474    uint32_t dot_clock;
1475    int ecp;
1476
1477    if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
1478	return NULL;
1479
1480    if(!(pPriv = calloc(1, sizeof(RADEONPortPrivRec) + sizeof(DevUnion))))
1481    {
1482	free(adapt);
1483	return NULL;
1484    }
1485
1486    adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
1487    adapt->pPortPrivates[0].ptr = (pointer)pPriv;
1488
1489    pPriv->colorKey = info->videoKey;
1490    pPriv->doubleBuffer = TRUE;
1491    pPriv->videoStatus = 0;
1492    pPriv->brightness = 0;
1493    pPriv->transform_index = 0;
1494    pPriv->saturation = 0;
1495    pPriv->contrast = 0;
1496    pPriv->red_intensity = 0;
1497    pPriv->green_intensity = 0;
1498    pPriv->blue_intensity = 0;
1499    pPriv->hue = 0;
1500    pPriv->currentBuffer = 0;
1501    pPriv->autopaint_colorkey = TRUE;
1502    pPriv->gamma = 1000;
1503    pPriv->desired_crtc = NULL;
1504
1505    pPriv->ov_alpha = 255;
1506    pPriv->gr_alpha = 255;
1507    pPriv->alpha_mode = 0;
1508
1509       /* TV-in stuff */
1510    pPriv->video_stream_active = FALSE;
1511    pPriv->encoding = 4;
1512    pPriv->frequency = 1000;
1513    pPriv->volume = -1000;
1514    pPriv->mute = TRUE;
1515    pPriv->v = 0;
1516    pPriv->overlay_deinterlacing_method = METHOD_BOB;
1517    pPriv->capture_vbi_data = 0;
1518    pPriv->dec_brightness = 0;
1519    pPriv->dec_saturation = 0;
1520    pPriv->dec_contrast = 0;
1521    pPriv->dec_hue = 0;
1522
1523
1524    /*
1525     * Unlike older Mach64 chips, RADEON has only two ECP settings:
1526     * 0 for PIXCLK < 175Mhz, and 1 (divide by 2)
1527     * for higher clocks, sure makes life nicer
1528     */
1529    dot_clock = info->ModeReg->dot_clock_freq;
1530
1531    if (dot_clock < 17500)
1532        info->ecp_div = 0;
1533    else
1534        info->ecp_div = 1;
1535    ecp = (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (info->ecp_div << 8);
1536
1537    if (info->IsIGP) {
1538        /* Force the overlay clock on for integrated chips
1539	 */
1540        ecp |= (1<<18);
1541    }
1542
1543    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, ecp);
1544
1545
1546    /* Decide on tuner type */
1547    if((info->tunerType<0) && (info->MM_TABLE_valid)) {
1548        pPriv->tuner_type = info->MM_TABLE.tuner_type;
1549    	} else
1550        pPriv->tuner_type = info->tunerType;
1551
1552    /* Initialize I2C bus */
1553    RADEONInitI2C(pScrn, pPriv);
1554    if(pPriv->i2c != NULL)RADEON_board_setmisc(pPriv);
1555
1556
1557    #if 0  /* this is just here for easy debugging - normally off */
1558    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Scanning I2C Bus\n");
1559    for(i=0;i<255;i+=2)
1560        if(RADEONProbeAddress(pPriv->i2c, i))
1561                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "     found device at address 0x%02x\n", i);
1562    #endif
1563
1564    /* resetting the VIP bus causes problems with some mobility chips.
1565     * we don't support video in on any mobility chips at the moment anyway
1566     */
1567    /* Initialize VIP bus */
1568    if (!info->IsMobility)
1569	RADEONVIP_init(pScrn, pPriv);
1570
1571    info->adaptor = adapt;
1572    info->xv_max_width = 2047;
1573    info->xv_max_height = 2047;
1574
1575	if(!xf86LoadSubModule(pScrn,"theatre_detect"))
1576	{
1577		xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre detect module\n");
1578		goto skip_theatre;
1579    }
1580	RADEONSetupTheatre(pScrn, pPriv);
1581
1582	/*
1583	 * Now load the correspondind theatre chip based on what has been detected.
1584	 */
1585	if (pPriv->theatre)
1586	{
1587		xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Going to load the corresponding theatre module\n");
1588		switch (pPriv->theatre->theatre_id)
1589		{
1590			case RT100_ATI_ID:
1591			{
1592				if(!xf86LoadSubModule(pScrn,"theatre"))
1593				{
1594					xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre module\n");
1595					free(pPriv->theatre);
1596					goto skip_theatre;
1597				}
1598				break;
1599			}
1600			case RT200_ATI_ID:
1601			{
1602				if(!xf86LoadSubModule(pScrn,"theatre200"))
1603				{
1604					xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre module\n");
1605					free(pPriv->theatre);
1606					goto skip_theatre;
1607				}
1608				pPriv->theatre->microc_path = info->RageTheatreMicrocPath;
1609				pPriv->theatre->microc_type = info->RageTheatreMicrocType;
1610				break;
1611			}
1612			default:
1613			{
1614				xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unknown Theatre chip\n");
1615				free(pPriv->theatre);
1616				goto skip_theatre;
1617			}
1618		}
1619	}
1620
1621	if(pPriv->theatre!=NULL)
1622	{
1623		xf86_InitTheatre(pPriv->theatre);
1624		if(pPriv->theatre->mode == MODE_UNINITIALIZED)
1625		{
1626			free(pPriv->theatre);
1627			pPriv->theatre = NULL;
1628			xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Rage Theatre disabled\n");
1629			/* Here the modules must be unloaded */
1630			goto skip_theatre;
1631		}
1632	}
1633
1634    if(pPriv->theatre!=NULL){
1635        xf86_ResetTheatreRegsForNoTVout(pPriv->theatre);
1636        xf86_RT_SetTint(pPriv->theatre, pPriv->dec_hue);
1637        xf86_RT_SetSaturation(pPriv->theatre, pPriv->dec_saturation);
1638        xf86_RT_SetSharpness(pPriv->theatre, RT_NORM_SHARPNESS);
1639        xf86_RT_SetContrast(pPriv->theatre, pPriv->dec_contrast);
1640        xf86_RT_SetBrightness(pPriv->theatre, pPriv->dec_brightness);
1641
1642        RADEON_RT_SetEncoding(pScrn, pPriv);
1643	}
1644
1645skip_theatre:
1646
1647    return adapt;
1648}
1649
1650static XF86VideoAdaptorPtr
1651RADEONSetupImageVideo(ScreenPtr pScreen)
1652{
1653    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1654    RADEONPortPrivPtr pPriv;
1655    XF86VideoAdaptorPtr adapt;
1656
1657    if(!(adapt = RADEONAllocAdaptor(pScrn)))
1658	return NULL;
1659
1660    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1661    adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
1662    adapt->name = "ATI Radeon Video Overlay";
1663    adapt->nEncodings = 1;
1664    adapt->pEncodings = &DummyEncoding;
1665    adapt->nFormats = NUM_FORMATS;
1666    adapt->pFormats = Formats;
1667    adapt->nPorts = 1;
1668    adapt->nAttributes = NUM_ATTRIBUTES;
1669    adapt->pAttributes = Attributes;
1670    adapt->nImages = NUM_IMAGES;
1671    adapt->pImages = Images;
1672    adapt->PutVideo = NULL;
1673    adapt->PutStill = NULL;
1674    adapt->GetVideo = NULL;
1675    adapt->GetStill = NULL;
1676    adapt->StopVideo = RADEONStopVideo;
1677    adapt->SetPortAttribute = RADEONSetPortAttribute;
1678    adapt->GetPortAttribute = RADEONGetPortAttribute;
1679    adapt->QueryBestSize = RADEONQueryBestSize;
1680    adapt->PutImage = RADEONPutImage;
1681    adapt->QueryImageAttributes = RADEONQueryImageAttributes;
1682
1683    pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr);
1684    REGION_NULL(pScreen, &(pPriv->clip));
1685
1686    pPriv->textured = FALSE;
1687
1688    if(pPriv->theatre != NULL) {
1689	/* video decoder is present, extend capabilities */
1690       adapt->nEncodings = 13;
1691       adapt->pEncodings = InputVideoEncodings;
1692       adapt->type |= XvVideoMask;
1693       adapt->nAttributes = NUM_DEC_ATTRIBUTES;
1694       adapt->PutVideo = RADEONPutVideo;
1695    }
1696
1697    RADEONResetVideo(pScrn);
1698
1699    return adapt;
1700}
1701
1702void
1703RADEONFreeVideoMemory(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
1704{
1705    RADEONInfoPtr info = RADEONPTR(pScrn);
1706
1707    if (pPriv->video_memory != NULL) {
1708	radeon_legacy_free_memory(pScrn, pPriv->video_memory);
1709	pPriv->video_memory = NULL;
1710
1711	if (info->cs && pPriv->textured) {
1712	    pPriv->src_bo[0] = NULL;
1713	    radeon_legacy_free_memory(pScrn, pPriv->src_bo[1]);
1714	    pPriv->src_bo[1] = NULL;
1715	}
1716    }
1717}
1718
1719void
1720RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
1721{
1722  RADEONInfoPtr info = RADEONPTR(pScrn);
1723  unsigned char *RADEONMMIO = info->MMIO;
1724  RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
1725
1726  if (pPriv->textured) {
1727      if (cleanup) {
1728	  RADEONFreeVideoMemory(pScrn, pPriv);
1729      }
1730      return;
1731  }
1732
1733  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1734
1735  if(cleanup) {
1736     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
1737	RADEONWaitForFifo(pScrn, 2);
1738	OUTREG(RADEON_OV0_SCALE_CNTL, 0);
1739     }
1740     if(pPriv->video_stream_active){
1741        RADEONWaitForFifo(pScrn, 2);
1742        OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND);
1743        OUTREG(RADEON_CAP0_TRIG_CNTL, 0);
1744        RADEONResetVideo(pScrn);
1745        pPriv->video_stream_active = FALSE;
1746        if(pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_FAST_MUTE);
1747		if(pPriv->uda1380 != NULL) xf86_uda1380_mute(pPriv->uda1380, TRUE);
1748        if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv);
1749     }
1750     RADEONFreeVideoMemory(pScrn, pPriv);
1751     pPriv->videoStatus = 0;
1752  } else {
1753     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
1754	pPriv->videoStatus |= OFF_TIMER;
1755	pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
1756     }
1757  }
1758}
1759
1760int
1761RADEONSetPortAttribute(ScrnInfoPtr  pScrn,
1762		       Atom	    attribute,
1763		       INT32	    value,
1764		       pointer	    data)
1765{
1766    RADEONInfoPtr	info = RADEONPTR(pScrn);
1767    RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
1768    Bool		setTransform = FALSE;
1769    Bool		setAlpha = FALSE;
1770    unsigned char *RADEONMMIO = info->MMIO;
1771
1772    RADEON_SYNC(info, pScrn);
1773
1774    if(attribute == xvAutopaintColorkey)
1775    {
1776	pPriv->autopaint_colorkey = ClipValue (value, 0, 1);
1777    }
1778    else if(attribute == xvSetDefaults)
1779    {
1780	pPriv->autopaint_colorkey = TRUE;
1781	pPriv->brightness = 0;
1782	pPriv->saturation = 0;
1783	pPriv->contrast = 0;
1784	pPriv->hue = 0;
1785	pPriv->red_intensity = 0;
1786	pPriv->green_intensity = 0;
1787	pPriv->blue_intensity = 0;
1788	pPriv->gamma = 1000;
1789	pPriv->transform_index = 0;
1790	pPriv->doubleBuffer = FALSE;
1791	pPriv->ov_alpha = 255;
1792	pPriv->gr_alpha = 255;
1793	pPriv->alpha_mode = 0;
1794
1795        /* It is simpler to call itself */
1796        RADEONSetPortAttribute(pScrn, xvDecBrightness, 0, data);
1797        RADEONSetPortAttribute(pScrn, xvDecSaturation, 0, data);
1798        RADEONSetPortAttribute(pScrn, xvDecContrast,   0, data);
1799        RADEONSetPortAttribute(pScrn, xvDecHue,   0, data);
1800
1801        RADEONSetPortAttribute(pScrn, xvVolume,   -1000, data);
1802        RADEONSetPortAttribute(pScrn, xvMute,   1, data);
1803        RADEONSetPortAttribute(pScrn, xvSAP,   0, data);
1804        RADEONSetPortAttribute(pScrn, xvDoubleBuffer,   1, data);
1805
1806	setTransform = TRUE;
1807	setAlpha = TRUE;
1808    }
1809    else if(attribute == xvBrightness)
1810    {
1811	pPriv->brightness = ClipValue (value, -1000, 1000);
1812	setTransform = TRUE;
1813    }
1814    else if((attribute == xvSaturation) || (attribute == xvColor))
1815    {
1816	pPriv->saturation = ClipValue (value, -1000, 1000);
1817	setTransform = TRUE;
1818    }
1819    else if(attribute == xvContrast)
1820    {
1821	pPriv->contrast = ClipValue (value, -1000, 1000);
1822	setTransform = TRUE;
1823    }
1824    else if(attribute == xvHue)
1825    {
1826	pPriv->hue = ClipValue (value, -1000, 1000);
1827	setTransform = TRUE;
1828    }
1829    else if(attribute == xvRedIntensity)
1830    {
1831	pPriv->red_intensity = ClipValue (value, -1000, 1000);
1832	setTransform = TRUE;
1833    }
1834    else if(attribute == xvGreenIntensity)
1835    {
1836	pPriv->green_intensity = ClipValue (value, -1000, 1000);
1837	setTransform = TRUE;
1838    }
1839    else if(attribute == xvBlueIntensity)
1840    {
1841	pPriv->blue_intensity = ClipValue (value, -1000, 1000);
1842	setTransform = TRUE;
1843    }
1844    else if(attribute == xvGamma)
1845    {
1846	pPriv->gamma = ClipValue (value, 100, 10000);
1847	setTransform = TRUE;
1848    }
1849    else if(attribute == xvColorspace)
1850    {
1851	pPriv->transform_index = ClipValue (value, 0, 1);
1852	setTransform = TRUE;
1853    }
1854    else if(attribute == xvDoubleBuffer)
1855    {
1856	pPriv->doubleBuffer = ClipValue (value, 0, 1);
1857    }
1858    else if(attribute == xvColorKey)
1859    {
1860	pPriv->colorKey = value;
1861	RADEONSetColorKey (pScrn, pPriv->colorKey);
1862	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1863    }
1864    else if(attribute == xvCRTC)
1865    {
1866	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1867	if ((value < -1) || (value > xf86_config->num_crtc))
1868	    return BadValue;
1869	if (value < 0)
1870	    pPriv->desired_crtc = NULL;
1871	else
1872	    pPriv->desired_crtc = xf86_config->crtc[value];
1873    }
1874    else if(attribute == xvOvAlpha)
1875    {
1876	pPriv->ov_alpha = ClipValue (value, 0, 255);
1877	setAlpha = TRUE;
1878    }
1879    else if(attribute == xvGrAlpha)
1880    {
1881	pPriv->gr_alpha = ClipValue (value, 0, 255);
1882	setAlpha = TRUE;
1883    }
1884    else if(attribute == xvAlphaMode)
1885    {
1886	pPriv->alpha_mode = ClipValue (value, 0, 1);
1887	setAlpha = TRUE;
1888    }
1889    else if(attribute == xvDecBrightness)
1890    {
1891        pPriv->dec_brightness = value;
1892        if(pPriv->theatre!=NULL) xf86_RT_SetBrightness(pPriv->theatre, pPriv->dec_brightness);
1893    }
1894    else if((attribute == xvDecSaturation) || (attribute == xvDecColor))
1895    {
1896        if(value<-1000)value = -1000;
1897        if(value>1000)value = 1000;
1898        pPriv->dec_saturation = value;
1899        if(pPriv->theatre != NULL)xf86_RT_SetSaturation(pPriv->theatre, value);
1900    }
1901    else if(attribute == xvDecContrast)
1902    {
1903        pPriv->dec_contrast = value;
1904        if(pPriv->theatre != NULL)xf86_RT_SetContrast(pPriv->theatre, value);
1905    }
1906    else if(attribute == xvDecHue)
1907    {
1908        pPriv->dec_hue = value;
1909        if(pPriv->theatre != NULL)xf86_RT_SetTint(pPriv->theatre, value);
1910    }
1911    else if(attribute == xvEncoding)
1912    {
1913        pPriv->encoding = value;
1914        if(pPriv->video_stream_active)
1915        {
1916           if(pPriv->theatre != NULL) RADEON_RT_SetEncoding(pScrn, pPriv);
1917           if(pPriv->msp3430 != NULL) RADEON_MSP_SetEncoding(pPriv);
1918           if(pPriv->tda9885 != NULL) RADEON_TDA9885_SetEncoding(pPriv);
1919	   if(pPriv->fi1236 != NULL) RADEON_FI1236_SetEncoding(pPriv);
1920           if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv);
1921        /* put more here to actually change it */
1922        }
1923   }
1924   else if(attribute == xvFrequency)
1925   {
1926        pPriv->frequency = value;
1927        /* mute volume if it was not muted before */
1928        if((pPriv->msp3430!=NULL)&& !pPriv->mute)xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_FAST_MUTE);
1929		if((pPriv->uda1380!=NULL)&& !pPriv->mute)xf86_uda1380_mute(pPriv->uda1380, TRUE);
1930        if(pPriv->fi1236 != NULL) xf86_TUNER_set_frequency(pPriv->fi1236, value);
1931/*        if(pPriv->theatre != NULL) RADEON_RT_SetEncoding(pScrn, pPriv);  */
1932        if((pPriv->msp3430 != NULL) && (pPriv->msp3430->recheck))
1933                xf86_InitMSP3430(pPriv->msp3430);
1934        if((pPriv->msp3430 != NULL)&& !pPriv->mute) xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_VOLUME(pPriv->volume));
1935		if((pPriv->uda1380 != NULL)&& !pPriv->mute) xf86_uda1380_setvolume(pPriv->uda1380, pPriv->volume);
1936   }
1937   else if(attribute == xvMute)
1938   {
1939        pPriv->mute = value;
1940        if(pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, pPriv->mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume));
1941        if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv);
1942		if(pPriv->uda1380 != NULL) xf86_uda1380_mute(pPriv->uda1380, pPriv->mute);
1943   }
1944   else if(attribute == xvSAP)
1945   {
1946        pPriv->sap_channel = value;
1947        if(pPriv->msp3430 != NULL) xf86_MSP3430SetSAP(pPriv->msp3430, pPriv->sap_channel?4:3);
1948   }
1949   else if(attribute == xvVolume)
1950   {
1951        if(value<-1000)value = -1000;
1952        if(value>1000)value = 1000;
1953        pPriv->volume = value;
1954        pPriv->mute = FALSE;
1955        if(pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_VOLUME(value));
1956        if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv);
1957		if(pPriv->uda1380 != NULL) xf86_uda1380_setvolume(pPriv->uda1380, value);
1958   }
1959   else if(attribute == xvOverlayDeinterlacingMethod)
1960   {
1961        if(value<0)value = 0;
1962        if(value>2)value = 2;
1963        pPriv->overlay_deinterlacing_method = value;
1964        switch(pPriv->overlay_deinterlacing_method){
1965                case METHOD_BOB:
1966                        OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA);
1967                        break;
1968                case METHOD_SINGLE:
1969                        OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xEEEEE | (9<<28));
1970                        break;
1971                case METHOD_WEAVE:
1972                        OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0x0);
1973                        break;
1974                default:
1975                        OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA);
1976                }
1977   }
1978   else if(attribute == xvDumpStatus)
1979   {
1980  	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Current mode flags 0x%08x: %s%s\n",
1981		pScrn->currentMode->Flags,
1982		pScrn->currentMode->Flags & V_INTERLACE ? " interlaced" : "" ,
1983		pScrn->currentMode->Flags & V_DBLSCAN ? " doublescan" : ""
1984		);
1985	if(pPriv->tda9885 != NULL){
1986		xf86_tda9885_getstatus(pPriv->tda9885);
1987		xf86_tda9885_dumpstatus(pPriv->tda9885);
1988		}
1989	if(pPriv->fi1236!=NULL){
1990		xf86_fi1236_dump_status(pPriv->fi1236);
1991		}
1992   }
1993   else if(attribute == xvAdjustment)
1994   {
1995  	pPriv->adjustment=value;
1996        xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %u\n",
1997		   (unsigned)pPriv->adjustment);
1998  	if(pPriv->tda9885!=0){
1999		pPriv->tda9885->top_adjustment=value;
2000		RADEON_TDA9885_SetEncoding(pPriv);
2001		}
2002   }
2003   else
2004	return BadMatch;
2005
2006    if (setTransform)
2007    {
2008	RADEONSetTransform(pScrn,
2009			   RTFBrightness(pPriv->brightness),
2010			   RTFContrast(pPriv->contrast),
2011			   RTFSaturation(pPriv->saturation),
2012			   RTFHue(pPriv->hue),
2013			   RTFIntensity(pPriv->red_intensity),
2014			   RTFIntensity(pPriv->green_intensity),
2015			   RTFIntensity(pPriv->blue_intensity),
2016			   pPriv->transform_index,
2017			   pPriv->gamma);
2018    }
2019
2020    if (setAlpha)
2021    {
2022	RADEONSetOverlayAlpha(pScrn, pPriv->ov_alpha, pPriv->gr_alpha, pPriv->alpha_mode);
2023    }
2024
2025    return Success;
2026}
2027
2028int
2029RADEONGetPortAttribute(ScrnInfoPtr  pScrn,
2030		       Atom	    attribute,
2031		       INT32	    *value,
2032		       pointer	    data)
2033{
2034    RADEONInfoPtr	info = RADEONPTR(pScrn);
2035    RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
2036
2037    if (info->accelOn) RADEON_SYNC(info, pScrn);
2038
2039    if(attribute == xvAutopaintColorkey)
2040	*value = pPriv->autopaint_colorkey;
2041    else if(attribute == xvBrightness)
2042	*value = pPriv->brightness;
2043    else if((attribute == xvSaturation) || (attribute == xvColor))
2044	*value = pPriv->saturation;
2045    else if(attribute == xvContrast)
2046	*value = pPriv->contrast;
2047    else if(attribute == xvHue)
2048	*value = pPriv->hue;
2049    else if(attribute == xvRedIntensity)
2050	*value = pPriv->red_intensity;
2051    else if(attribute == xvGreenIntensity)
2052	*value = pPriv->green_intensity;
2053    else if(attribute == xvBlueIntensity)
2054	*value = pPriv->blue_intensity;
2055    else if(attribute == xvGamma)
2056	*value = pPriv->gamma;
2057    else if(attribute == xvColorspace)
2058	*value = pPriv->transform_index;
2059    else if(attribute == xvDoubleBuffer)
2060	*value = pPriv->doubleBuffer ? 1 : 0;
2061    else if(attribute == xvColorKey)
2062	*value = pPriv->colorKey;
2063    else if(attribute == xvCRTC) {
2064	int		c;
2065	xf86CrtcConfigPtr	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2066	for (c = 0; c < xf86_config->num_crtc; c++)
2067	    if (xf86_config->crtc[c] == pPriv->desired_crtc)
2068		break;
2069	if (c == xf86_config->num_crtc)
2070	    c = -1;
2071	*value = c;
2072    }
2073    else if(attribute == xvOvAlpha)
2074	*value = pPriv->ov_alpha;
2075    else if(attribute == xvGrAlpha)
2076	*value = pPriv->gr_alpha;
2077    else if(attribute == xvAlphaMode)
2078	*value = pPriv->alpha_mode;
2079    else if(attribute == xvDecBrightness)
2080        *value = pPriv->dec_brightness;
2081    else if((attribute == xvDecSaturation) || (attribute == xvDecColor))
2082        *value = pPriv->dec_saturation;
2083    else if(attribute == xvDecContrast)
2084        *value = pPriv->dec_contrast;
2085    else if(attribute == xvDecHue)
2086        *value = pPriv->dec_hue;
2087    else if(attribute == xvEncoding)
2088        *value = pPriv->encoding;
2089    else if(attribute == xvFrequency)
2090        *value = pPriv->frequency;
2091    else
2092    if(attribute == xvTunerStatus) {
2093        if(pPriv->fi1236==NULL){
2094                *value=TUNER_OFF;
2095                } else
2096                {
2097                *value = xf86_TUNER_get_afc_hint(pPriv->fi1236);
2098                }
2099       }
2100    else if(attribute == xvMute)
2101        *value = pPriv->mute;
2102    else if(attribute == xvSAP)
2103        *value = pPriv->sap_channel;
2104    else if(attribute == xvVolume)
2105        *value = pPriv->volume;
2106    else if(attribute == xvOverlayDeinterlacingMethod)
2107        *value = pPriv->overlay_deinterlacing_method;
2108    else if(attribute == xvDeviceID)
2109        *value = pPriv->device_id;
2110    else if(attribute == xvLocationID)
2111        *value = pPriv->location_id;
2112    else if(attribute == xvInstanceID)
2113        *value = pPriv->instance_id;
2114    else if(attribute == xvAdjustment)
2115  	*value = pPriv->adjustment;
2116    else
2117	return BadMatch;
2118
2119    return Success;
2120}
2121
2122void
2123RADEONQueryBestSize(
2124  ScrnInfoPtr pScrn,
2125  Bool motion,
2126  short vid_w, short vid_h,
2127  short drw_w, short drw_h,
2128  unsigned int *p_w, unsigned int *p_h,
2129  pointer data
2130){
2131    RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
2132
2133    if (!pPriv->textured) {
2134	if (vid_w > (drw_w << 4))
2135	    drw_w = vid_w >> 4;
2136	if (vid_h > (drw_h << 4))
2137	    drw_h = vid_h >> 4;
2138    }
2139
2140  *p_w = drw_w;
2141  *p_h = drw_h;
2142}
2143
2144static struct {
2145	double range;
2146	signed char coeff[5][4];
2147	} TapCoeffs[]=
2148	{
2149        {0.25, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13,   13,    3}, }},
2150        {0.26, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2151        {0.27, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2152        {0.28, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2153        {0.29, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2154        {0.30, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2155        {0.31, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2156        {0.32, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2157        {0.33, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2158        {0.34, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2159        {0.35, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2160        {0.36, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2161        {0.37, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2162        {0.38, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2163        {0.39, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2164        {0.40, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2165        {0.41, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2166        {0.42, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2167        {0.43, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2168        {0.44, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2169        {0.45, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2170        {0.46, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2171        {0.47, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2172        {0.48, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2173        {0.49, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2174        {0.50, {{ 7,    16,  9,  0}, { 7,   16,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 3,   13, 13,  3}, }},
2175        {0.51, {{ 7,    17,  8,  0}, { 6,   17,  9,  0}, { 5,   15, 11,  1}, { 4,   15, 12,  1}, { 2,   14, 14,  2}, }},
2176        {0.52, {{ 7,    17,  8,  0}, { 6,   17,  9,  0}, { 5,   16, 11,  0}, { 3,   15, 13,  1}, { 2,   14, 14,  2}, }},
2177        {0.53, {{ 7,    17,  8,  0}, { 6,   17,  9,  0}, { 5,   16, 11,  0}, { 3,   15, 13,  1}, { 2,   14, 14,  2}, }},
2178        {0.54, {{ 7,    17,  8,  0}, { 6,   17,  9,  0}, { 4,   17, 11,  0}, { 3,   15, 13,  1}, { 2,   14, 14,  2}, }},
2179        {0.55, {{ 7,    18,  7,  0}, { 6,   17,  9,  0}, { 4,   17, 11,  0}, { 3,   15, 13,  1}, { 1,   15, 15,  1}, }},
2180        {0.56, {{ 7,    18,  7,  0}, { 5,   18,  9,  0}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2181        {0.57, {{ 7,    18,  7,  0}, { 5,   18,  9,  0}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2182        {0.58, {{ 7,    18,  7,  0}, { 5,   18,  9,  0}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2183        {0.59, {{ 7,    18,  7,  0}, { 5,   18,  9,  0}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2184        {0.60, {{ 7,    18,  8, -1}, { 6,   17, 10, -1}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2185        {0.61, {{ 7,    18,  8, -1}, { 6,   17, 10, -1}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2186        {0.62, {{ 7,    18,  8, -1}, { 6,   17, 10, -1}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2187        {0.63, {{ 7,    18,  8, -1}, { 6,   17, 10, -1}, { 4,   17, 11,  0}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2188        {0.64, {{ 7,    18,  8, -1}, { 6,   17, 10, -1}, { 4,   17, 12, -1}, { 2,   17, 13,  0}, { 1,   15, 15,  1}, }},
2189        {0.65, {{ 7,    18,  8, -1}, { 6,   17, 10, -1}, { 4,   17, 12, -1}, { 2,   17, 13,  0}, { 0,   16, 16,  0}, }},
2190        {0.66, {{ 7,    18,  8, -1}, { 6,   18, 10, -2}, { 4,   17, 12, -1}, { 2,   17, 13,  0}, { 0,   16, 16,  0}, }},
2191        {0.67, {{ 7,    20,  7, -2}, { 5,   19, 10, -2}, { 3,   18, 12, -1}, { 2,   17, 13,  0}, { 0,   16, 16,  0}, }},
2192        {0.68, {{ 7,    20,  7, -2}, { 5,   19, 10, -2}, { 3,   19, 12, -2}, { 1,   18, 14, -1}, { 0,   16, 16,  0}, }},
2193        {0.69, {{ 7,    20,  7, -2}, { 5,   19, 10, -2}, { 3,   19, 12, -2}, { 1,   18, 14, -1}, { 0,   16, 16,  0}, }},
2194        {0.70, {{ 7,    20,  7, -2}, { 5,   20,  9, -2}, { 3,   19, 12, -2}, { 1,   18, 14, -1}, { 0,   16, 16,  0}, }},
2195        {0.71, {{ 7,    20,  7, -2}, { 5,   20,  9, -2}, { 3,   19, 12, -2}, { 1,   18, 14, -1}, { 0,   16, 16,  0}, }},
2196        {0.72, {{ 7,    20,  7, -2}, { 5,   20,  9, -2}, { 2,   20, 12, -2}, { 0,   19, 15, -2}, {-1,   17, 17, -1}, }},
2197        {0.73, {{ 7,    20,  7, -2}, { 4,   21,  9, -2}, { 2,   20, 12, -2}, { 0,   19, 15, -2}, {-1,   17, 17, -1}, }},
2198        {0.74, {{ 6,    22,  6, -2}, { 4,   21,  9, -2}, { 2,   20, 12, -2}, { 0,   19, 15, -2}, {-1,   17, 17, -1}, }},
2199        {0.75, {{ 6,    22,  6, -2}, { 4,   21,  9, -2}, { 1,   21, 12, -2}, { 0,   19, 15, -2}, {-1,   17, 17, -1}, }},
2200        {0.76, {{ 6,    22,  6, -2}, { 4,   21,  9, -2}, { 1,   21, 12, -2}, { 0,   19, 15, -2}, {-1,   17, 17, -1}, }},
2201        {0.77, {{ 6,    22,  6, -2}, { 3,   22,  9, -2}, { 1,   22, 12, -3}, { 0,   19, 15, -2}, {-2,   18, 18, -2}, }},
2202        {0.78, {{ 6,    21,  6, -1}, { 3,   22,  9, -2}, { 1,   22, 12, -3}, { 0,   19, 15, -2}, {-2,   18, 18, -2}, }},
2203        {0.79, {{ 5,    23,  5, -1}, { 3,   22,  9, -2}, { 0,   23, 12, -3}, {-1,   21, 15, -3}, {-2,   18, 18, -2}, }},
2204        {0.80, {{ 5,    23,  5, -1}, { 3,   23,  8, -2}, { 0,   23, 12, -3}, {-1,   21, 15, -3}, {-2,   18, 18, -2}, }},
2205        {0.81, {{ 5,    23,  5, -1}, { 2,   24,  8, -2}, { 0,   23, 12, -3}, {-1,   21, 15, -3}, {-2,   18, 18, -2}, }},
2206        {0.82, {{ 5,    23,  5, -1}, { 2,   24,  8, -2}, { 0,   23, 12, -3}, {-1,   21, 15, -3}, {-3,   19, 19, -3}, }},
2207        {0.83, {{ 5,    23,  5, -1}, { 2,   24,  8, -2}, { 0,   23, 11, -2}, {-2,   22, 15, -3}, {-3,   19, 19, -3}, }},
2208        {0.84, {{ 4,    25,  4, -1}, { 1,   25,  8, -2}, { 0,   23, 11, -2}, {-2,   22, 15, -3}, {-3,   19, 19, -3}, }},
2209        {0.85, {{ 4,    25,  4, -1}, { 1,   25,  8, -2}, { 0,   23, 11, -2}, {-2,   22, 15, -3}, {-3,   19, 19, -3}, }},
2210        {0.86, {{ 4,    24,  4,  0}, { 1,   25,  7, -1}, {-1,   24, 11, -2}, {-2,   22, 15, -3}, {-3,   19, 19, -3}, }},
2211        {0.87, {{ 4,    24,  4,  0}, { 1,   25,  7, -1}, {-1,   24, 11, -2}, {-2,   22, 15, -3}, {-3,   19, 19, -3}, }},
2212        {0.88, {{ 3,    26,  3,  0}, { 0,   26,  7, -1}, {-1,   24, 11, -2}, {-3,   23, 15, -3}, {-3,   19, 19, -3}, }},
2213        {0.89, {{ 3,    26,  3,  0}, { 0,   26,  7, -1}, {-1,   24, 11, -2}, {-3,   23, 15, -3}, {-3,   19, 19, -3}, }},
2214        {0.90, {{ 3,    26,  3,  0}, { 0,   26,  7, -1}, {-2,   25, 11, -2}, {-3,   23, 15, -3}, {-3,   19, 19, -3}, }},
2215        {0.91, {{ 3,    26,  3,  0}, { 0,   27,  6, -1}, {-2,   25, 11, -2}, {-3,   23, 15, -3}, {-3,   19, 19, -3}, }},
2216        {0.92, {{ 2,    28,  2,  0}, { 0,   27,  6, -1}, {-2,   25, 11, -2}, {-3,   23, 15, -3}, {-3,   19, 19, -3}, }},
2217        {0.93, {{ 2,    28,  2,  0}, { 0,   26,  6,  0}, {-2,   25, 10, -1}, {-3,   23, 15, -3}, {-3,   19, 19, -3}, }},
2218        {0.94, {{ 2,    28,  2,  0}, { 0,   26,  6,  0}, {-2,   25, 10, -1}, {-3,   23, 15, -3}, {-3,   19, 19, -3}, }},
2219        {0.95, {{ 1,    30,  1,  0}, {-1,   28,  5,  0}, {-3,   26, 10, -1}, {-3,   23, 14, -2}, {-3,   19, 19, -3}, }},
2220        {0.96, {{ 1,    30,  1,  0}, {-1,   28,  5,  0}, {-3,   26, 10, -1}, {-3,   23, 14, -2}, {-3,   19, 19, -3}, }},
2221        {0.97, {{ 1,    30,  1,  0}, {-1,   28,  5,  0}, {-3,   26, 10, -1}, {-3,   23, 14, -2}, {-3,   19, 19, -3}, }},
2222        {0.98, {{ 1,    30,  1,  0}, {-2,   29,  5,  0}, {-3,   27,  9, -1}, {-3,   23, 14, -2}, {-3,   19, 19, -3}, }},
2223        {0.99, {{ 0,    32,  0,  0}, {-2,   29,  5,  0}, {-3,   27,  9, -1}, {-4,   24, 14, -2}, {-3,   19, 19, -3}, }},
2224        {1.00, {{ 0,    32,  0,  0}, {-2,   29,  5,  0}, {-3,   27,  9, -1}, {-4,   24, 14, -2}, {-3,   19, 19, -3}, }}
2225    };
2226
2227void
2228RADEONCopyData(
2229  ScrnInfoPtr pScrn,
2230  unsigned char *src,
2231  unsigned char *dst,
2232  unsigned int srcPitch,
2233  unsigned int dstPitch,
2234  unsigned int h,
2235  unsigned int w,
2236  unsigned int bpp
2237){
2238    RADEONInfoPtr info = RADEONPTR(pScrn);
2239
2240    /* Get the byte-swapping right for big endian systems */
2241    if ( bpp == 2 ) {
2242	w *= 2;
2243	bpp = 1;
2244    }
2245
2246#ifdef XF86DRI
2247
2248    if ( info->directRenderingEnabled && info->DMAForXv )
2249    {
2250	uint8_t *buf;
2251	uint32_t bufPitch, dstPitchOff;
2252	int x, y;
2253	unsigned int hpass;
2254
2255	RADEONHostDataParams( pScrn, dst, dstPitch, bpp, &dstPitchOff, &x, &y );
2256
2257	while ( (buf = RADEONHostDataBlit( pScrn, bpp, w, dstPitchOff, &bufPitch,
2258					   x, &y, &h, &hpass )) )
2259	{
2260	    RADEONHostDataBlitCopyPass( pScrn, bpp, buf, src, hpass, bufPitch,
2261					srcPitch );
2262	    src += hpass * srcPitch;
2263	}
2264
2265	FLUSH_RING();
2266
2267	return;
2268    }
2269    else
2270#endif /* XF86DRI */
2271    {
2272	int swap = RADEON_HOST_DATA_SWAP_NONE;
2273
2274#if X_BYTE_ORDER == X_BIG_ENDIAN
2275	if (info->kms_enabled) {
2276	    switch(bpp) {
2277	    case 2:
2278		swap = RADEON_HOST_DATA_SWAP_16BIT;
2279		break;
2280	    case 4:
2281		swap = RADEON_HOST_DATA_SWAP_32BIT;
2282		break;
2283	    }
2284	} else {
2285	    switch (pScrn->bitsPerPixel) {
2286	    case 16:
2287		swap = RADEON_HOST_DATA_SWAP_16BIT;
2288		break;
2289	    case 32:
2290		swap = RADEON_HOST_DATA_SWAP_32BIT;
2291		break;
2292	    }
2293	}
2294#endif
2295
2296	w *= bpp;
2297
2298	if (dstPitch == w && dstPitch == srcPitch)
2299	    RADEONCopySwap(dst, src, h * dstPitch, swap);
2300	else {
2301	    while (h--) {
2302		RADEONCopySwap(dst, src, w, swap);
2303		src += srcPitch;
2304		dst += dstPitch;
2305	    }
2306	}
2307    }
2308}
2309
2310static void
2311RADEONCopyRGB24Data(
2312  ScrnInfoPtr pScrn,
2313  unsigned char *src,
2314  unsigned char *dst,
2315  unsigned int srcPitch,
2316  unsigned int dstPitch,
2317  unsigned int h,
2318  unsigned int w
2319){
2320    uint32_t *dptr;
2321    uint8_t *sptr;
2322    int i,j;
2323    RADEONInfoPtr info = RADEONPTR(pScrn);
2324#ifdef XF86DRI
2325
2326    if ( info->directRenderingEnabled && info->DMAForXv )
2327    {
2328	uint32_t bufPitch, dstPitchOff;
2329	int x, y;
2330	unsigned int hpass;
2331
2332	RADEONHostDataParams( pScrn, dst, dstPitch, 4, &dstPitchOff, &x, &y );
2333
2334	while ( (dptr = ( uint32_t* )RADEONHostDataBlit( pScrn, 4, w, dstPitchOff,
2335						       &bufPitch, x, &y, &h,
2336						       &hpass )) )
2337	{
2338	    for( j = 0; j < hpass; j++ )
2339	    {
2340		sptr = src;
2341
2342		for ( i = 0 ; i < w; i++, sptr += 3 )
2343		{
2344		    dptr[i] = (sptr[2] << 16) | (sptr[1] << 8) | sptr[0];
2345		}
2346
2347		src += srcPitch;
2348		dptr += bufPitch / 4;
2349	    }
2350	}
2351
2352	FLUSH_RING();
2353
2354	return;
2355    }
2356    else
2357#endif /* XF86DRI */
2358    {
2359#if X_BYTE_ORDER == X_BIG_ENDIAN
2360	unsigned char *RADEONMMIO = info->MMIO;
2361
2362	if (!info->kms_enabled)
2363	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl &
2364		   ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP0_SWP_32BPP));
2365#endif
2366
2367	for (j = 0; j < h; j++) {
2368	    dptr = (uint32_t *)(dst + j * dstPitch);
2369	    sptr = src + j * srcPitch;
2370
2371	    for (i = 0; i < w; i++, sptr += 3) {
2372		dptr[i] = cpu_to_le32((sptr[2] << 16) | (sptr[1] << 8) | sptr[0]);
2373	    }
2374	}
2375
2376#if X_BYTE_ORDER == X_BIG_ENDIAN
2377	if (!info->kms_enabled) {
2378	    /* restore byte swapping */
2379	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
2380	}
2381#endif
2382    }
2383}
2384
2385
2386#ifdef XF86DRI
2387static void RADEON_420_422(
2388    unsigned int *d,
2389    unsigned char *s1,
2390    unsigned char *s2,
2391    unsigned char *s3,
2392    unsigned int n
2393)
2394{
2395    while ( n ) {
2396	*(d++) = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
2397	s1+=2; s2++; s3++;
2398	n--;
2399    }
2400}
2401#endif
2402
2403void
2404RADEONCopyMungedData(
2405   ScrnInfoPtr pScrn,
2406   unsigned char *src1,
2407   unsigned char *src2,
2408   unsigned char *src3,
2409   unsigned char *dst1,
2410   unsigned int srcPitch,
2411   unsigned int srcPitch2,
2412   unsigned int dstPitch,
2413   unsigned int h,
2414   unsigned int w
2415){
2416    RADEONInfoPtr info = RADEONPTR(pScrn);
2417#ifdef XF86DRI
2418
2419    if ( info->directRenderingEnabled && info->DMAForXv )
2420    {
2421	uint8_t *buf;
2422	uint32_t y = 0, bufPitch, dstPitchOff;
2423	int blitX, blitY;
2424	unsigned int hpass;
2425
2426	/* XXX Fix endian flip on R300 */
2427
2428	RADEONHostDataParams( pScrn, dst1, dstPitch, 4, &dstPitchOff, &blitX, &blitY );
2429
2430	while ( (buf = RADEONHostDataBlit( pScrn, 4, w/2, dstPitchOff, &bufPitch,
2431					   blitX, &blitY, &h, &hpass )) )
2432	{
2433	    while ( hpass-- )
2434	    {
2435		RADEON_420_422( (unsigned int *) buf, src1, src2, src3,
2436				bufPitch / 4 );
2437		src1 += srcPitch;
2438		if ( y & 1 )
2439		{
2440		    src2 += srcPitch2;
2441		    src3 += srcPitch2;
2442		}
2443		buf += bufPitch;
2444		y++;
2445	    }
2446	}
2447
2448	FLUSH_RING();
2449    }
2450    else
2451#endif /* XF86DRI */
2452    {
2453	uint32_t *dst;
2454	uint8_t *s1, *s2, *s3;
2455	int i, j;
2456
2457#if X_BYTE_ORDER == X_BIG_ENDIAN
2458	unsigned char *RADEONMMIO = info->MMIO;
2459
2460	if (!info->kms_enabled)
2461	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl &
2462		   ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP0_SWP_32BPP));
2463#endif
2464
2465	w /= 2;
2466
2467	for( j = 0; j < h; j++ )
2468	{
2469	    dst = (pointer)dst1;
2470	    s1 = src1;  s2 = src2;  s3 = src3;
2471	    i = w;
2472	    while( i > 4 )
2473	    {
2474		dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
2475		dst[1] = cpu_to_le32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24));
2476		dst[2] = cpu_to_le32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24));
2477		dst[3] = cpu_to_le32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24));
2478		dst += 4; s2 += 4; s3 += 4; s1 += 8;
2479		i -= 4;
2480	    }
2481	    while( i-- )
2482	    {
2483		dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
2484		dst++; s2++; s3++;
2485		s1 += 2;
2486	    }
2487
2488	    dst1 += dstPitch;
2489	    src1 += srcPitch;
2490	    if( j & 1 )
2491	    {
2492		src2 += srcPitch2;
2493		src3 += srcPitch2;
2494	    }
2495	}
2496#if X_BYTE_ORDER == X_BIG_ENDIAN
2497	if (!info->kms_enabled) {
2498	    /* restore byte swapping */
2499	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
2500	}
2501#endif
2502    }
2503}
2504
2505static void
2506RADEONDisplayVideo(
2507    ScrnInfoPtr pScrn,
2508    xf86CrtcPtr crtc,
2509    RADEONPortPrivPtr pPriv,
2510    int id,
2511    int base_offset,
2512    int offset1, int offset2,
2513    int offset3, int offset4,
2514    int offset5, int offset6,
2515    short width, short height,
2516    int pitch,
2517    int left, int right, int top,
2518    BoxPtr dstBox,
2519    short src_w, short src_h,
2520    short drw_w, short drw_h,
2521    int deinterlacing_method
2522){
2523    RADEONInfoPtr info = RADEONPTR(pScrn);
2524    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2525    unsigned char *RADEONMMIO = info->MMIO;
2526    uint32_t v_inc, h_inc, h_inc_uv, step_by_y, step_by_uv, tmp;
2527    double h_inc_d;
2528    int p1_h_accum_init, p23_h_accum_init;
2529    int p1_v_accum_init, p23_v_accum_init;
2530    int p23_blank_lines;
2531    int ecp_div;
2532    int v_inc_shift;
2533    int y_mult;
2534    int x_off;
2535    int y_off;
2536    uint32_t scaler_src;
2537    uint32_t dot_clock;
2538    int is_rgb;
2539    int is_planar;
2540    int i;
2541    uint32_t scale_cntl;
2542    double dsr;
2543    int tap_set;
2544    int predownscale=0;
2545    int src_w_d;
2546    int leftuv = 0;
2547    DisplayModePtr mode;
2548    RADEONOutputPrivatePtr radeon_output;
2549    xf86OutputPtr output;
2550    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
2551
2552    is_rgb=0; is_planar=0;
2553    switch(id){
2554        case FOURCC_I420:
2555        case FOURCC_YV12:
2556            is_planar=1;
2557            break;
2558        case FOURCC_RGBA32:
2559        case FOURCC_RGB24:
2560        case FOURCC_RGBT16:
2561        case FOURCC_RGB16:
2562            is_rgb=1;
2563            break;
2564        default:
2565	    break;
2566    }
2567
2568    /* Here we need to find ecp_div again, as the user may have switched resolutions
2569       but only call OUTPLL/INPLL if needed since it may cause a 10ms delay due to
2570       workarounds for chip erratas */
2571
2572    /* Figure out which head we are on for dot clock */
2573    if (radeon_crtc->crtc_id == 1)
2574        dot_clock = info->ModeReg->dot_clock_freq_2;
2575    else
2576        dot_clock = info->ModeReg->dot_clock_freq;
2577
2578    if (dot_clock < 17500)
2579        ecp_div = 0;
2580    else
2581	ecp_div = 1;
2582
2583    if (ecp_div != info->ecp_div) {
2584	info->ecp_div = ecp_div;
2585	OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL,
2586	   (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8));
2587    }
2588
2589    /* I suspect we may need a usleep after writing to the PLL.  if you play a video too soon
2590       after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey
2591       on the right edge video output.
2592       Is this still the case? Might have been chips which need the errata,
2593       there is now plenty of usleep after INPLL/OUTPLL for those...*/
2594
2595    v_inc_shift = 20;
2596    y_mult = 1;
2597
2598    mode = &crtc->mode;
2599
2600    if (mode->Flags & V_INTERLACE)
2601	v_inc_shift++;
2602    if (mode->Flags & V_DBLSCAN) {
2603	v_inc_shift--;
2604	y_mult = 2;
2605    }
2606
2607    v_inc = (src_h << v_inc_shift) / drw_h;
2608
2609    for (i = 0; i < xf86_config->num_output; i++) {
2610	output = xf86_config->output[i];
2611	if (output->crtc == crtc) {
2612	    radeon_output = output->driver_private;
2613	    if (radeon_output->Flags & RADEON_USE_RMX)
2614		v_inc = ((src_h * mode->CrtcVDisplay /
2615			  radeon_output->native_mode.PanelYRes) << v_inc_shift) / drw_h;
2616	    break;
2617	}
2618    }
2619
2620    h_inc = (1 << (12 + ecp_div));
2621
2622    step_by_y = 1;
2623    step_by_uv = step_by_y;
2624
2625    src_w_d = src_w;
2626#if 0
2627    /* XXX this does not appear to work */
2628    /* if the source width was larger than what would fit in overlay scaler increase step_by values */
2629    i=src_w;
2630    while(i>info->overlay_scaler_buffer_width){
2631	step_by_y++;
2632	step_by_uv++;
2633	h_inc >>=1;
2634	i=i/2;
2635	}
2636#else
2637    /* predownscale instead (yes this hurts quality) - will only work for widths up
2638       to 2 times the overlay_scaler_buffer_width, should be enough */
2639    if (src_w_d > info->overlay_scaler_buffer_width) {
2640	src_w_d /= 2; /* odd widths? */
2641	predownscale = 1;
2642    }
2643#endif
2644
2645    h_inc_d = src_w_d;
2646    h_inc_d = h_inc_d/drw_w;
2647    /* we could do a tad better  - but why
2648       bother when this concerns downscaling and the code is so much more
2649       hairy */
2650    while(h_inc*h_inc_d >= (2 << 12)) {
2651        if(!is_rgb && (((h_inc+h_inc/2)*h_inc_d)<(2<<12))){
2652                step_by_uv = step_by_y+1;
2653                break;
2654                }
2655        step_by_y++;
2656        step_by_uv = step_by_y;
2657        h_inc >>= 1;
2658    }
2659
2660    h_inc_uv = h_inc>>(step_by_uv-step_by_y);
2661    h_inc = h_inc * h_inc_d;
2662    h_inc_uv = h_inc_uv * h_inc_d;
2663    /* info->overlay_scaler_buffer_width is magic number - maximum line length the overlay scaler can fit
2664       in the buffer for 2 tap filtering */
2665    /* the only place it is documented in is in ATI source code */
2666    /* we need twice as much space for 4 tap filtering.. */
2667    /* under special circumstances turn on 4 tap filtering */
2668    /* disable this code for now as it has a DISASTROUS effect on image quality when upscaling
2669       at least on rv250 (only as long as the drw_w*2 <=... requirement is still met of course) */
2670#if 0
2671    if(!is_rgb && (step_by_y==1) && (step_by_uv==1) && (h_inc < (1<<12))
2672       && (deinterlacing_method!=METHOD_WEAVE)
2673       && (drw_w*2 <= info->overlay_scaler_buffer_width)){
2674        step_by_y=0;
2675        step_by_uv=1;
2676        h_inc_uv = h_inc;
2677        }
2678#endif
2679
2680    /* Make the overlay base address as close to the buffers as possible to
2681     * prevent the buffer offsets from exceeding the hardware limit of 128 MB.
2682     * The base address must be aligned to a multiple of 4 MB.
2683     */
2684    base_offset = ((info->fbLocation + base_offset) & (~0 << 22)) -
2685	info->fbLocation;
2686
2687    offset1 -= base_offset;
2688    offset2 -= base_offset;
2689    offset3 -= base_offset;
2690    offset4 -= base_offset;
2691    offset5 -= base_offset;
2692    offset6 -= base_offset;
2693
2694    /* keep everything in 16.16 */
2695
2696    if (is_planar) {
2697	offset1 += ((left >> 16) & ~15);
2698	offset2 += ((left >> 16) & ~31) >> 1;
2699	offset3 += ((left >> 16) & ~31) >> 1;
2700	offset4 += ((left >> 16) & ~15);
2701	offset5 += ((left >> 16) & ~31) >> 1;
2702	offset6 += ((left >> 16) & ~31) >> 1;
2703	offset2 |= RADEON_VIF_BUF0_PITCH_SEL;
2704	offset3 |= RADEON_VIF_BUF0_PITCH_SEL;
2705	offset5 |= RADEON_VIF_BUF0_PITCH_SEL;
2706	offset6 |= RADEON_VIF_BUF0_PITCH_SEL;
2707    }
2708    else {
2709	/* is this really correct for non-2-byte formats? */
2710	offset1 += ((left >> 16) & ~7) << 1;
2711	offset2 += ((left >> 16) & ~7) << 1;
2712	offset3 += ((left >> 16) & ~7) << 1;
2713	offset4 += ((left >> 16) & ~7) << 1;
2714	offset5 += ((left >> 16) & ~7) << 1;
2715	offset6 += ((left >> 16) & ~7) << 1;
2716    }
2717
2718    tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
2719    p1_h_accum_init = ((tmp <<  4) & 0x000f8000) |
2720		      ((tmp << 12) & 0xf0000000);
2721
2722    tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc_uv << 2);
2723    p23_h_accum_init = ((tmp <<  4) & 0x000f8000) |
2724		       ((tmp << 12) & 0x70000000);
2725
2726    tmp = (top & 0x0000ffff) + 0x00018000;
2727    p1_v_accum_init = ((tmp << 4) & 0x03ff8000) |
2728    	(((deinterlacing_method!=METHOD_WEAVE)&&!is_rgb)?0x03:0x01);
2729
2730    if (is_planar) {
2731	p23_v_accum_init = ((tmp << 4) & 0x03ff8000) |
2732	    ((deinterlacing_method != METHOD_WEAVE) ? 0x03 : 0x01);
2733	p23_blank_lines = (((src_h >> 1) - 1) << 16);
2734    }
2735    else {
2736	p23_v_accum_init = 0;
2737	p23_blank_lines = 0;
2738    }
2739
2740    if (is_planar) {
2741	leftuv = ((left >> 16) >> 1) & 15;
2742	left = (left >> 16) & 15;
2743    }
2744    else {
2745	left = (left >> 16) & 7;
2746	if (!is_rgb)
2747	    leftuv = left >> 1;
2748    }
2749
2750    RADEONWaitForFifo(pScrn, 2);
2751    OUTREG(RADEON_OV0_REG_LOAD_CNTL, RADEON_REG_LD_CTL_LOCK);
2752    if (info->accelOn) RADEON_SYNC(info, pScrn);
2753    while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_LOCK_READBACK));
2754
2755    RADEONWaitForFifo(pScrn, 10);
2756    OUTREG(RADEON_OV0_H_INC, h_inc | ((is_rgb? h_inc_uv: (h_inc_uv >> 1)) << 16));
2757    OUTREG(RADEON_OV0_STEP_BY, step_by_y | (step_by_uv << 8) |
2758	predownscale << 4 | predownscale << 12);
2759
2760    x_off = 8;
2761    y_off = 0;
2762
2763    if (IS_R300_VARIANT ||
2764        (info->ChipFamily == CHIP_FAMILY_R200))
2765	x_off = 0;
2766
2767    /* needed to make the overlay work on crtc1 in leftof and above modes */
2768    /* XXX: may need to adjust x_off/y_off for dualhead like mergedfb -- need to test */
2769    /*
2770    if (srel == radeonLeftOf) {
2771	x_off -= mode->CrtcHDisplay;
2772    }
2773    if (srel == radeonAbove) {
2774	y_off -= mode->CrtcVDisplay;
2775    }
2776    */
2777
2778    /* Put the hardware overlay on CRTC2:
2779     *
2780     * Since one hardware overlay can not be displayed on two heads
2781     * at the same time, we might need to consider using software
2782     * rendering for the second head.
2783     */
2784
2785    if (radeon_crtc->crtc_id == 1) {
2786        x_off = 0;
2787        OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) |
2788                                      ((dstBox->y1*y_mult) << 16)));
2789        OUTREG(RADEON_OV1_Y_X_END,   ((dstBox->x2 + x_off) |
2790                                      ((dstBox->y2*y_mult) << 16)));
2791        scaler_src = RADEON_SCALER_CRTC_SEL;
2792    } else {
2793	OUTREG(RADEON_OV0_Y_X_START, ((dstBox->x1 + x_off) |
2794				      (((dstBox->y1*y_mult) + y_off) << 16)));
2795	OUTREG(RADEON_OV0_Y_X_END,   ((dstBox->x2 + x_off) |
2796				      (((dstBox->y2*y_mult) + y_off) << 16)));
2797	scaler_src = 0;
2798    }
2799
2800    /* program the tap coefficients for better downscaling quality.
2801       Could do slightly better by using hardcoded coefficients for one axis
2802       in case only the other axis is downscaled (see RADEON_OV0_FILTER_CNTL) */
2803    dsr=(double)(1<<0xC)/h_inc;
2804    if(dsr<0.25)dsr=0.25;
2805    if(dsr>1.0)dsr=1.0;
2806    tap_set=(int)((dsr-0.25)*100);
2807    for(i=0;i<5;i++){
2808	    OUTREG(RADEON_OV0_FOUR_TAP_COEF_0+i*4, (TapCoeffs[tap_set].coeff[i][0] &0xf) |
2809	    	((TapCoeffs[tap_set].coeff[i][1] &0x7f)<<8) |
2810	    	((TapCoeffs[tap_set].coeff[i][2] &0x7f)<<16) |
2811	    	((TapCoeffs[tap_set].coeff[i][3] &0xf)<<24));
2812		}
2813
2814    RADEONWaitForFifo(pScrn, 11);
2815    OUTREG(RADEON_OV0_V_INC, v_inc);
2816    OUTREG(RADEON_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16));
2817    OUTREG(RADEON_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | p23_blank_lines);
2818    OUTREG(RADEON_OV0_VID_BUF_PITCH0_VALUE, pitch);
2819    OUTREG(RADEON_OV0_VID_BUF_PITCH1_VALUE, is_planar ? pitch >> 1 : pitch);
2820    OUTREG(RADEON_OV0_P1_X_START_END, (src_w + left - 1) | (left << 16));
2821    if (!is_rgb)
2822	src_w >>= 1;
2823    OUTREG(RADEON_OV0_P2_X_START_END, (src_w + leftuv - 1) | (leftuv << 16));
2824    OUTREG(RADEON_OV0_P3_X_START_END, (src_w + leftuv - 1) | (leftuv << 16));
2825    if (info->ModeReg->ov0_base_addr != (info->fbLocation + base_offset)) {
2826	ErrorF("Changing OV0_BASE_ADDR from 0x%08x to 0x%08x\n",
2827	       info->ModeReg->ov0_base_addr, (uint32_t)info->fbLocation + base_offset);
2828	info->ModeReg->ov0_base_addr = info->fbLocation + base_offset;
2829	OUTREG(RADEON_OV0_BASE_ADDR, info->ModeReg->ov0_base_addr);
2830    }
2831    OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1);
2832    OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2);
2833    OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset3);
2834
2835    RADEONWaitForFifo(pScrn, 9);
2836    OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset4);
2837    OUTREG(RADEON_OV0_VID_BUF4_BASE_ADRS, offset5);
2838    OUTREG(RADEON_OV0_VID_BUF5_BASE_ADRS, offset6);
2839    OUTREG(RADEON_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
2840    OUTREG(RADEON_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
2841    OUTREG(RADEON_OV0_P23_V_ACCUM_INIT, p23_v_accum_init);
2842    OUTREG(RADEON_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
2843
2844   scale_cntl = RADEON_SCALER_ADAPTIVE_DEINT | RADEON_SCALER_DOUBLE_BUFFER
2845        | RADEON_SCALER_ENABLE | RADEON_SCALER_SMART_SWITCH | (0x7f<<16) | scaler_src;
2846   switch(id){
2847        case FOURCC_UYVY:
2848		scale_cntl |= RADEON_SCALER_SOURCE_YVYU422;
2849		break;
2850        case FOURCC_RGB24:
2851        case FOURCC_RGBA32:
2852		scale_cntl |= RADEON_SCALER_SOURCE_32BPP | RADEON_SCALER_LIN_TRANS_BYPASS;
2853		break;
2854        case FOURCC_RGB16:
2855		scale_cntl |= RADEON_SCALER_SOURCE_16BPP | RADEON_SCALER_LIN_TRANS_BYPASS;
2856		break;
2857        case FOURCC_RGBT16:
2858		scale_cntl |= RADEON_SCALER_SOURCE_15BPP | RADEON_SCALER_LIN_TRANS_BYPASS;
2859		break;
2860        case FOURCC_YV12:
2861        case FOURCC_I420:
2862		scale_cntl |= RADEON_SCALER_SOURCE_YUV12;
2863		break;
2864        case FOURCC_YUY2:
2865        default:
2866		scale_cntl |= RADEON_SCALER_SOURCE_VYUY422
2867			| ((info->ChipFamily >= CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT : 0);
2868		break;
2869    }
2870
2871    if (info->ChipFamily < CHIP_FAMILY_R200) {
2872	scale_cntl &= ~RADEON_SCALER_GAMMA_SEL_MASK;
2873	scale_cntl |= ((RADEONTranslateUserGamma(pPriv->gamma)) << 5);
2874    }
2875
2876    OUTREG(RADEON_OV0_SCALE_CNTL, scale_cntl);
2877    OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0);
2878}
2879
2880
2881static void
2882RADEONFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes)
2883{
2884#if HAVE_XV_DRAWABLE_HELPER
2885    xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes);
2886#else
2887    xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes);
2888#endif
2889}
2890
2891
2892static int
2893RADEONPutImage(
2894  ScrnInfoPtr pScrn,
2895  short src_x, short src_y,
2896  short drw_x, short drw_y,
2897  short src_w, short src_h,
2898  short drw_w, short drw_h,
2899  int id, unsigned char* buf,
2900  short width, short height,
2901  Bool Sync,
2902  RegionPtr clipBoxes, pointer data,
2903  DrawablePtr pDraw
2904){
2905   RADEONInfoPtr info = RADEONPTR(pScrn);
2906   RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
2907   INT32 xa, xb, ya, yb;
2908   unsigned char *dst_start;
2909   int new_size, offset, s2offset, s3offset;
2910   int srcPitch, srcPitch2, dstPitch;
2911   int d2line, d3line;
2912   int top, left, npixels, nlines, bpp;
2913   int idconv = id;
2914   BoxRec dstBox;
2915   uint32_t tmp;
2916   xf86CrtcPtr crtc;
2917
2918   /*
2919    * s2offset, s3offset - byte offsets into U and V plane of the
2920    *                      source where copying starts.  Y plane is
2921    *                      done by editing "buf".
2922    *
2923    * offset - byte offset to the first line of the destination.
2924    *
2925    * dst_start - byte address to the first displayed pel.
2926    *
2927    */
2928
2929   /* make the compiler happy */
2930   s2offset = s3offset = srcPitch2 = 0;
2931   d2line = d3line = 0;
2932
2933   if(src_w > (drw_w << 4))
2934	drw_w = src_w >> 4;
2935   if(src_h > (drw_h << 4))
2936	drw_h = src_h >> 4;
2937
2938   /* Clip */
2939   xa = src_x;
2940   xb = src_x + src_w;
2941   ya = src_y;
2942   yb = src_y + src_h;
2943
2944   dstBox.x1 = drw_x;
2945   dstBox.x2 = drw_x + drw_w;
2946   dstBox.y1 = drw_y;
2947   dstBox.y2 = drw_y + drw_h;
2948
2949   if (!radeon_crtc_clip_video(pScrn, &crtc, pPriv->desired_crtc,
2950			       &dstBox, &xa, &xb, &ya, &yb,
2951			       clipBoxes, width, height))
2952       return Success;
2953
2954   if (!crtc) {
2955       if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
2956	   unsigned char *RADEONMMIO = info->MMIO;
2957	   OUTREG(RADEON_OV0_SCALE_CNTL, 0);
2958	   pPriv->videoStatus &= ~CLIENT_VIDEO_ON;
2959       }
2960       return Success;
2961   }
2962
2963   dstBox.x1 -= crtc->x;
2964   dstBox.x2 -= crtc->x;
2965   dstBox.y1 -= crtc->y;
2966   dstBox.y2 -= crtc->y;
2967
2968   bpp = pScrn->bitsPerPixel >> 3;
2969
2970   switch(id) {
2971   case FOURCC_RGB24:
2972	dstPitch = width * 4;
2973	srcPitch = width * 3;
2974	break;
2975   case FOURCC_RGBA32:
2976	dstPitch = width * 4;
2977	srcPitch = width * 4;
2978	break;
2979   case FOURCC_RGB16:
2980   case FOURCC_RGBT16:
2981	dstPitch = width * 2;
2982	srcPitch = RADEON_ALIGN(width * 2, 4);
2983	break;
2984   case FOURCC_YV12:
2985   case FOURCC_I420:
2986	/* it seems rs4xx chips (all of them???) either can't handle planar
2987	   yuv at all or would need some unknown different setup. */
2988       if ((info->ChipFamily != CHIP_FAMILY_RS400) &&
2989	   (info->ChipFamily != CHIP_FAMILY_RS480)) {
2990	    /* need 16bytes alignment for u,v plane, so 2 times that for width
2991	       but blitter needs 64bytes alignment. 128byte is a waste but dstpitch
2992	       for uv planes needs to be dstpitch yplane >> 1 for now. */
2993	    dstPitch = (RADEON_ALIGN(width, 128));
2994	    srcPitch = RADEON_ALIGN(width, 4);
2995	}
2996	else {
2997	    dstPitch = width * 2;
2998	    srcPitch = RADEON_ALIGN(width, 4);
2999	    idconv = FOURCC_YUY2;
3000	}
3001	break;
3002   case FOURCC_UYVY:
3003   case FOURCC_YUY2:
3004   default:
3005	dstPitch = width * 2;
3006	srcPitch = width * 2;
3007	break;
3008   }
3009
3010#ifdef XF86DRI
3011   if (info->directRenderingEnabled && info->DMAForXv) {
3012       /* The upload blit only supports multiples of 64 bytes */
3013       dstPitch = RADEON_ALIGN(dstPitch, 64);
3014   } else
3015#endif
3016       /* The overlay only supports multiples of 16 bytes */
3017       dstPitch = RADEON_ALIGN(dstPitch, 16);
3018
3019   new_size = dstPitch * height;
3020   if (idconv == FOURCC_YV12 || id == FOURCC_I420) {
3021      new_size += (dstPitch >> 1) * (RADEON_ALIGN(height, 2));
3022   }
3023   pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, &pPriv->video_memory,
3024						       (pPriv->doubleBuffer ?
3025						       (new_size * 2) : new_size), 64,
3026						       RADEON_GEM_DOMAIN_VRAM);
3027   if (pPriv->video_offset == 0)
3028      return BadAlloc;
3029
3030   pPriv->currentBuffer ^= 1;
3031
3032    /* copy data */
3033   top = ya >> 16;
3034   left = (xa >> 16) & ~1;
3035   npixels = ((xb + 0xffff) >> 16) - left;
3036
3037   offset = (pPriv->video_offset) + (top * dstPitch);
3038
3039   if(pPriv->doubleBuffer) {
3040	unsigned char *RADEONMMIO = info->MMIO;
3041
3042	/* Wait for last flip to take effect */
3043	while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_FLIP_READBACK));
3044
3045	offset += pPriv->currentBuffer * new_size;
3046   }
3047
3048   dst_start = info->FB + offset;
3049
3050   switch(id) {
3051   case FOURCC_YV12:
3052   case FOURCC_I420:
3053	if (id == idconv) {
3054	    /* meh. Such a mess just for someone who wants to watch half the video clipped */
3055	    top &= ~1;
3056	    /* odd number of pixels? That may not work correctly */
3057	    srcPitch2 = RADEON_ALIGN(width >> 1, 4);
3058	    /* odd number of lines? Maybe... */
3059	    s2offset = srcPitch * (RADEON_ALIGN(height, 2));
3060	    s3offset = s2offset + srcPitch2 * ((height + 1) >> 1);
3061	    s2offset += (top >> 1) * srcPitch2 + (left >> 1);
3062	    s3offset += (top >> 1) * srcPitch2 + (left >> 1);
3063	    d2line = (height * dstPitch);
3064	    d3line = d2line + ((height + 1) >> 1) * (dstPitch >> 1);
3065	    nlines = ((yb + 0xffff) >> 16) - top;
3066	    d2line += (top >> 1) * (dstPitch >> 1) - (top * dstPitch);
3067	    d3line += (top >> 1) * (dstPitch >> 1) - (top * dstPitch);
3068	    if(id == FOURCC_YV12) {
3069		tmp = s2offset;
3070		s2offset = s3offset;
3071		s3offset = tmp;
3072	    }
3073	    RADEONCopyData(pScrn, buf + (top * srcPitch) + left, dst_start + left,
3074		srcPitch, dstPitch, nlines, npixels, 1);
3075	    RADEONCopyData(pScrn, buf + s2offset, dst_start + d2line + (left >> 1),
3076		srcPitch2, dstPitch >> 1, (nlines + 1) >> 1, npixels >> 1, 1);
3077	    RADEONCopyData(pScrn, buf + s3offset, dst_start + d3line + (left >> 1),
3078		srcPitch2, dstPitch >> 1, (nlines + 1) >> 1, npixels >> 1, 1);
3079	}
3080	else {
3081	    s2offset = srcPitch * height;
3082	    srcPitch2 = RADEON_ALIGN(width >> 1, 4);
3083	    s3offset = (srcPitch2 * (height >> 1)) + s2offset;
3084	    top &= ~1;
3085	    dst_start += left << 1;
3086	    tmp = ((top >> 1) * srcPitch2) + (left >> 1);
3087	    s2offset += tmp;
3088	    s3offset += tmp;
3089	    if(id == FOURCC_I420) {
3090		tmp = s2offset;
3091		s2offset = s3offset;
3092		s3offset = tmp;
3093	    }
3094	    nlines = ((yb + 0xffff) >> 16) - top;
3095	    RADEONCopyMungedData(pScrn, buf + (top * srcPitch) + left,
3096				 buf + s2offset, buf + s3offset, dst_start,
3097				 srcPitch, srcPitch2, dstPitch, nlines, npixels);
3098	}
3099	break;
3100    case FOURCC_RGBT16:
3101    case FOURCC_RGB16:
3102    case FOURCC_UYVY:
3103    case FOURCC_YUY2:
3104    default:
3105	left <<= 1;
3106	buf += (top * srcPitch) + left;
3107	nlines = ((yb + 0xffff) >> 16) - top;
3108	dst_start += left;
3109	RADEONCopyData(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels, 2);
3110	break;
3111    case FOURCC_RGBA32:
3112	buf += (top * srcPitch) + left*4;
3113	nlines = ((yb + 0xffff) >> 16) - top;
3114	dst_start += left*4;
3115	RADEONCopyData(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels, 4);
3116    	break;
3117    case FOURCC_RGB24:
3118	buf += (top * srcPitch) + left*3;
3119	nlines = ((yb + 0xffff) >> 16) - top;
3120	dst_start += left*4;
3121	RADEONCopyRGB24Data(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels);
3122    	break;
3123    }
3124
3125    /* update cliplist */
3126    if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))
3127    {
3128	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
3129	/* draw these */
3130	if(pPriv->autopaint_colorkey)
3131	    RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes);
3132    }
3133
3134    /* FIXME: someone should look at these offsets, I don't think it makes sense how
3135              they are handled throughout the source. */
3136    RADEONDisplayVideo(pScrn, crtc, pPriv, idconv, pPriv->video_offset, offset,
3137		       offset + d2line, offset + d3line, offset, offset + d2line,
3138		       offset + d3line, width, height, dstPitch, xa, xb, ya,
3139		       &dstBox, src_w, src_h, drw_w, drw_h, METHOD_BOB);
3140
3141    pPriv->videoStatus = CLIENT_VIDEO_ON;
3142
3143    info->VideoTimerCallback = RADEONVideoTimerCallback;
3144
3145    return Success;
3146}
3147
3148
3149int
3150RADEONQueryImageAttributes(
3151    ScrnInfoPtr pScrn,
3152    int id,
3153    unsigned short *w, unsigned short *h,
3154    int *pitches, int *offsets
3155){
3156    const RADEONInfoRec * const info = RADEONPTR(pScrn);
3157    int size, tmp;
3158
3159    if(*w > info->xv_max_width) *w = info->xv_max_width;
3160    if(*h > info->xv_max_height) *h = info->xv_max_height;
3161
3162    *w = RADEON_ALIGN(*w, 2);
3163    if(offsets) offsets[0] = 0;
3164
3165    switch(id) {
3166    case FOURCC_YV12:
3167    case FOURCC_I420:
3168	*h = RADEON_ALIGN(*h, 2);
3169	size = RADEON_ALIGN(*w, 4);
3170	if(pitches) pitches[0] = size;
3171	size *= *h;
3172	if(offsets) offsets[1] = size;
3173	tmp = RADEON_ALIGN(*w >> 1, 4);
3174	if(pitches) pitches[1] = pitches[2] = tmp;
3175	tmp *= (*h >> 1);
3176	size += tmp;
3177	if(offsets) offsets[2] = size;
3178	size += tmp;
3179	break;
3180    case FOURCC_RGBA32:
3181	size = *w << 2;
3182	if(pitches) pitches[0] = size;
3183	size *= *h;
3184	break;
3185    case FOURCC_RGB24:
3186	size = *w * 3;
3187	if(pitches) pitches[0] = size;
3188	size *= *h;
3189	break;
3190    case FOURCC_RGBT16:
3191    case FOURCC_RGB16:
3192    case FOURCC_UYVY:
3193    case FOURCC_YUY2:
3194    default:
3195	size = *w << 1;
3196	if(pitches) pitches[0] = size;
3197	size *= *h;
3198	break;
3199    }
3200
3201    return size;
3202}
3203
3204static void
3205RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now)
3206{
3207    RADEONInfoPtr info = RADEONPTR(pScrn);
3208    RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
3209
3210    if(pPriv->videoStatus & TIMER_MASK) {
3211	if(pPriv->videoStatus & OFF_TIMER) {
3212	    if(pPriv->offTime < now) {
3213		unsigned char *RADEONMMIO = info->MMIO;
3214		OUTREG(RADEON_OV0_SCALE_CNTL, 0);
3215		pPriv->videoStatus = FREE_TIMER;
3216		pPriv->freeTime = now + FREE_DELAY;
3217	    }
3218	} else {  /* FREE_TIMER */
3219	    if(pPriv->freeTime < now) {
3220		RADEONFreeVideoMemory(pScrn, pPriv);
3221		pPriv->videoStatus = 0;
3222		info->VideoTimerCallback = NULL;
3223	    }
3224	}
3225    } else  /* shouldn't get here */
3226	info->VideoTimerCallback = NULL;
3227}
3228
3229/****************** Offscreen stuff ***************/
3230typedef struct {
3231  void *surface_memory;
3232  Bool isOn;
3233} OffscreenPrivRec, * OffscreenPrivPtr;
3234
3235static int
3236RADEONAllocateSurface(
3237    ScrnInfoPtr pScrn,
3238    int id,
3239    unsigned short w,
3240    unsigned short h,
3241    XF86SurfacePtr surface
3242){
3243    int offset, pitch, size;
3244    OffscreenPrivPtr pPriv;
3245    void *surface_memory = NULL;
3246    if((w > 1024) || (h > 1024))
3247	return BadAlloc;
3248
3249    w = RADEON_ALIGN(w, 2);
3250    pitch = RADEON_ALIGN(w << 1, 16);
3251    size = pitch * h;
3252
3253    offset = radeon_legacy_allocate_memory(pScrn, &surface_memory, size, 64,
3254		    RADEON_GEM_DOMAIN_VRAM);
3255    if (offset == 0)
3256	return BadAlloc;
3257
3258    surface->width = w;
3259    surface->height = h;
3260
3261    if(!(surface->pitches = malloc(sizeof(int)))) {
3262	radeon_legacy_free_memory(pScrn, surface_memory);
3263	return BadAlloc;
3264    }
3265    if(!(surface->offsets = malloc(sizeof(int)))) {
3266	free(surface->pitches);
3267	radeon_legacy_free_memory(pScrn, surface_memory);
3268	return BadAlloc;
3269    }
3270    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
3271	free(surface->pitches);
3272	free(surface->offsets);
3273	radeon_legacy_free_memory(pScrn, surface_memory);
3274	return BadAlloc;
3275    }
3276
3277    pPriv->surface_memory = surface_memory;
3278    pPriv->isOn = FALSE;
3279
3280    surface->pScrn = pScrn;
3281    surface->id = id;
3282    surface->pitches[0] = pitch;
3283    surface->offsets[0] = offset;
3284    surface->devPrivate.ptr = (pointer)pPriv;
3285
3286    return Success;
3287}
3288
3289static int
3290RADEONStopSurface(
3291    XF86SurfacePtr surface
3292){
3293  OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
3294  RADEONInfoPtr info = RADEONPTR(surface->pScrn);
3295  unsigned char *RADEONMMIO = info->MMIO;
3296
3297  if(pPriv->isOn) {
3298	OUTREG(RADEON_OV0_SCALE_CNTL, 0);
3299	pPriv->isOn = FALSE;
3300  }
3301  return Success;
3302}
3303
3304
3305static int
3306RADEONFreeSurface(
3307    XF86SurfacePtr surface
3308){
3309    ScrnInfoPtr pScrn = surface->pScrn;
3310    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
3311
3312    if(pPriv->isOn)
3313	RADEONStopSurface(surface);
3314    radeon_legacy_free_memory(pScrn, pPriv->surface_memory);
3315    pPriv->surface_memory = NULL;
3316    free(surface->pitches);
3317    free(surface->offsets);
3318    free(surface->devPrivate.ptr);
3319
3320    return Success;
3321}
3322
3323static int
3324RADEONGetSurfaceAttribute(
3325    ScrnInfoPtr pScrn,
3326    Atom attribute,
3327    INT32 *value
3328){
3329   return RADEONGetPortAttribute(pScrn, attribute, value,
3330		(pointer)(GET_PORT_PRIVATE(pScrn)));
3331}
3332
3333static int
3334RADEONSetSurfaceAttribute(
3335    ScrnInfoPtr pScrn,
3336    Atom attribute,
3337    INT32 value
3338){
3339   return RADEONSetPortAttribute(pScrn, attribute, value,
3340		(pointer)(GET_PORT_PRIVATE(pScrn)));
3341}
3342
3343
3344static int
3345RADEONDisplaySurface(
3346    XF86SurfacePtr surface,
3347    short src_x, short src_y,
3348    short drw_x, short drw_y,
3349    short src_w, short src_h,
3350    short drw_w, short drw_h,
3351    RegionPtr clipBoxes
3352){
3353    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
3354    ScrnInfoPtr pScrn = surface->pScrn;
3355    RADEONInfoPtr info = RADEONPTR(pScrn);
3356    RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr;
3357
3358    INT32 xa, ya, xb, yb;
3359    BoxRec dstBox;
3360    xf86CrtcPtr crtc;
3361
3362    if (src_w > (drw_w << 4))
3363	drw_w = src_w >> 4;
3364    if (src_h > (drw_h << 4))
3365	drw_h = src_h >> 4;
3366
3367    xa = src_x;
3368    xb = src_x + src_w;
3369    ya = src_y;
3370    yb = src_y + src_h;
3371
3372    dstBox.x1 = drw_x;
3373    dstBox.x2 = drw_x + drw_w;
3374    dstBox.y1 = drw_y;
3375    dstBox.y2 = drw_y + drw_h;
3376
3377    if (!radeon_crtc_clip_video(pScrn, &crtc, portPriv->desired_crtc,
3378				&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
3379				surface->width, surface->height))
3380        return Success;
3381
3382   if (!crtc) {
3383       if (pPriv->isOn) {
3384	   unsigned char *RADEONMMIO = info->MMIO;
3385	   OUTREG(RADEON_OV0_SCALE_CNTL, 0);
3386	   pPriv->isOn = FALSE;
3387       }
3388       return Success;
3389   }
3390
3391    dstBox.x1 -= crtc->x;
3392    dstBox.x2 -= crtc->x;
3393    dstBox.y1 -= crtc->y;
3394    dstBox.y2 -= crtc->y;
3395
3396#if 0
3397    /* this isn't needed */
3398    RADEONResetVideo(pScrn);
3399#endif
3400    RADEONDisplayVideo(pScrn, crtc, portPriv, surface->id,
3401		       surface->offsets[0], surface->offsets[0],
3402		       surface->offsets[0], surface->offsets[0],
3403		       surface->offsets[0], surface->offsets[0],
3404		       surface->offsets[0], surface->width, surface->height,
3405		       surface->pitches[0], xa, xb, ya, &dstBox, src_w, src_h,
3406		       drw_w, drw_h, METHOD_BOB);
3407
3408    if (portPriv->autopaint_colorkey)
3409	xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
3410
3411    pPriv->isOn = TRUE;
3412    /* we've prempted the XvImage stream so set its free timer */
3413    if (portPriv->videoStatus & CLIENT_VIDEO_ON) {
3414	REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
3415	UpdateCurrentTime();
3416	portPriv->videoStatus = FREE_TIMER;
3417	portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
3418	info->VideoTimerCallback = RADEONVideoTimerCallback;
3419    }
3420
3421    return Success;
3422}
3423
3424
3425static void
3426RADEONInitOffscreenImages(ScreenPtr pScreen)
3427{
3428/*  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3429    RADEONInfoPtr info = RADEONPTR(pScrn); */
3430    XF86OffscreenImagePtr offscreenImages;
3431    /* need to free this someplace */
3432
3433    if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
3434	return;
3435
3436    offscreenImages[0].image = &Images[0];
3437    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*|
3438			       VIDEO_CLIP_TO_VIEWPORT*/;
3439    offscreenImages[0].alloc_surface = RADEONAllocateSurface;
3440    offscreenImages[0].free_surface = RADEONFreeSurface;
3441    offscreenImages[0].display = RADEONDisplaySurface;
3442    offscreenImages[0].stop = RADEONStopSurface;
3443    offscreenImages[0].setAttribute = RADEONSetSurfaceAttribute;
3444    offscreenImages[0].getAttribute = RADEONGetSurfaceAttribute;
3445    offscreenImages[0].max_width = 2047;
3446    offscreenImages[0].max_height = 2047;
3447    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
3448    offscreenImages[0].attributes = Attributes;
3449
3450    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
3451}
3452
3453         /* TV-in functions */
3454
3455static int
3456RADEONPutVideo(
3457  ScrnInfoPtr pScrn,
3458  short src_x, short src_y,
3459  short drw_x, short drw_y,
3460  short src_w, short src_h,
3461  short drw_w, short drw_h,
3462  RegionPtr clipBoxes, pointer data,
3463  DrawablePtr pDraw
3464){
3465   RADEONInfoPtr info = RADEONPTR(pScrn);
3466   RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
3467   unsigned char *RADEONMMIO = info->MMIO;
3468   INT32 xa, xb, ya, yb, top;
3469   unsigned int pitch, new_size, alloc_size;
3470   unsigned int offset1, offset2, offset3, offset4, s2offset, s3offset;
3471   unsigned int vbi_offset0, vbi_offset1;
3472   int srcPitch, srcPitch2, dstPitch;
3473   int bpp;
3474   BoxRec dstBox;
3475   uint32_t id, display_base;
3476   int width, height;
3477   int mult;
3478   int vbi_line_width, vbi_start, vbi_end;
3479   xf86CrtcPtr crtc;
3480
3481    RADEON_SYNC(info, pScrn);
3482   /*
3483    * s2offset, s3offset - byte offsets into U and V plane of the
3484    *                      source where copying starts.  Y plane is
3485    *                      done by editing "buf".
3486    *
3487    * offset - byte offset to the first line of the destination.
3488    *
3489    * dst_start - byte address to the first displayed pel.
3490    *
3491    */
3492
3493   /* make the compiler happy */
3494   s2offset = s3offset = srcPitch2 = 0;
3495
3496   if(src_w > (drw_w << 4))
3497        drw_w = src_w >> 4;
3498   if(src_h > (drw_h << 4))
3499        drw_h = src_h >> 4;
3500
3501   /* Clip */
3502   xa = src_x;
3503   xb = src_x + src_w;
3504   ya = src_y;
3505   yb = src_y + src_h;
3506
3507   dstBox.x1 = drw_x;
3508   dstBox.x2 = drw_x + drw_w;
3509   dstBox.y1 = drw_y;
3510   dstBox.y2 = drw_y + drw_h;
3511
3512   width = InputVideoEncodings[pPriv->encoding].width;
3513   height = InputVideoEncodings[pPriv->encoding].height;
3514
3515   vbi_line_width = 798*2;
3516   if(width<=640)
3517       vbi_line_width = 0x640; /* 1600 actually */
3518   else
3519       vbi_line_width = 2000; /* might need adjustment */
3520
3521   if (!radeon_crtc_clip_video(pScrn, &crtc, pPriv->desired_crtc,
3522			       &dstBox, &xa, &xb, &ya, &yb,
3523			       clipBoxes, width, height))
3524       return Success;
3525
3526   if (!crtc) {
3527       if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
3528	   unsigned char *RADEONMMIO = info->MMIO;
3529	   OUTREG(RADEON_OV0_SCALE_CNTL, 0);
3530	   pPriv->videoStatus &= ~CLIENT_VIDEO_ON;
3531       }
3532       return Success;
3533   }
3534
3535   dstBox.x1 -= crtc->x;
3536   dstBox.x2 -= crtc->x;
3537   dstBox.y1 -= crtc->y;
3538   dstBox.y2 -= crtc->y;
3539
3540   bpp = pScrn->bitsPerPixel >> 3;
3541   pitch = bpp * pScrn->displayWidth;
3542
3543   switch(pPriv->overlay_deinterlacing_method){
3544        case METHOD_BOB:
3545        case METHOD_SINGLE:
3546                mult=2;
3547                break;
3548        case METHOD_WEAVE:
3549        case METHOD_ADAPTIVE:
3550                mult=4;
3551                break;
3552        default:
3553                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Internal error: PutVideo\n");
3554                mult=4;
3555        }
3556
3557   id = FOURCC_YUY2;
3558
3559   top = ya>>16;
3560#if 0
3561   /* setting the ID above makes this useful - needs revisiting */
3562   switch(id) {
3563   case FOURCC_YV12:
3564   case FOURCC_I420:
3565        top &= ~1;
3566        dstPitch = RADEON_ALIGN(width << 1, 16);
3567        srcPitch = RADEON_ALIGN(width, 4);
3568        s2offset = srcPitch * height;
3569        srcPitch2 = RADEON_ALIGN(width >> 1, 4);
3570        s3offset = (srcPitch2 * (height >> 1)) + s2offset;
3571        break;
3572   case FOURCC_UYVY:
3573   case FOURCC_YUY2:
3574   default:
3575        dstPitch = RADEON_ALIGN(width<<1, 16);
3576        srcPitch = (width<<1);
3577        break;
3578   }
3579#else
3580   dstPitch = RADEON_ALIGN(width << 1, 16);
3581   srcPitch = (width<<1);
3582#endif
3583
3584   new_size = dstPitch * height;
3585   new_size = new_size + 0x1f; /* for aligning */
3586   alloc_size = new_size * mult;
3587   if (pPriv->capture_vbi_data)
3588      alloc_size += 2 * 2 * vbi_line_width * 21;
3589
3590   pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, &pPriv->video_memory,
3591						      (pPriv->doubleBuffer ?
3592						      (new_size * 2) : new_size), 64,
3593						      RADEON_GEM_DOMAIN_GTT);
3594   if (pPriv->video_offset == 0)
3595      return BadAlloc;
3596
3597/* I have suspicion that capture engine must be active _before_ Rage Theatre
3598   is being manipulated with.. */
3599
3600   RADEONWaitForIdleMMIO(pScrn);
3601   display_base=INREG(RADEON_DISPLAY_BASE_ADDR);
3602
3603/*   RADEONWaitForFifo(pScrn, 15); */
3604
3605   switch(pPriv->overlay_deinterlacing_method){
3606        case METHOD_BOB:
3607        case METHOD_SINGLE:
3608           offset1 = RADEON_ALIGN(pPriv->video_offset, 0x10);
3609           offset2 = RADEON_ALIGN(pPriv->video_offset + new_size, 0x10);
3610           offset3 = offset1;
3611           offset4 = offset2;
3612           break;
3613        case METHOD_WEAVE:
3614           offset1 = RADEON_ALIGN(pPriv->video_offset, 0x10);
3615           offset2 = offset1+dstPitch;
3616           offset3 = RADEON_ALIGN(pPriv->video_offset + 2 * new_size, 0x10);
3617           offset4 = offset3+dstPitch;
3618           break;
3619        default:
3620           offset1 = RADEON_ALIGN(pPriv->video_offset, 0x10);
3621           offset2 = RADEON_ALIGN(pPriv->video_offset + new_size, 0x10);
3622           offset3 = offset1;
3623           offset4 = offset2;
3624        }
3625
3626   OUTREG(RADEON_CAP0_BUF0_OFFSET,        offset1+display_base);
3627   OUTREG(RADEON_CAP0_BUF0_EVEN_OFFSET,   offset2+display_base);
3628   OUTREG(RADEON_CAP0_BUF1_OFFSET,        offset3+display_base);
3629   OUTREG(RADEON_CAP0_BUF1_EVEN_OFFSET,   offset4+display_base);
3630
3631   OUTREG(RADEON_CAP0_ONESHOT_BUF_OFFSET, offset1+display_base);
3632
3633   if(pPriv->capture_vbi_data){
3634        if ((pPriv->encoding==2)||(pPriv->encoding==8)) {
3635            /* PAL, SECAM */
3636            vbi_start = 5;
3637            vbi_end = 21;
3638        } else {
3639            /* NTSC */
3640            vbi_start = 8;
3641            vbi_end = 20;
3642        }
3643
3644        vbi_offset0 = RADEON_ALIGN(pPriv->video_offset + mult * new_size * bpp, 0x10);
3645        vbi_offset1 = vbi_offset0 + dstPitch*20;
3646        OUTREG(RADEON_CAP0_VBI0_OFFSET, vbi_offset0+display_base);
3647        OUTREG(RADEON_CAP0_VBI1_OFFSET, vbi_offset1+display_base);
3648        OUTREG(RADEON_CAP0_VBI2_OFFSET, 0);
3649        OUTREG(RADEON_CAP0_VBI3_OFFSET, 0);
3650        OUTREG(RADEON_CAP0_VBI_V_WINDOW, vbi_start | (vbi_end<<16));
3651        OUTREG(RADEON_CAP0_VBI_H_WINDOW, 0 | (vbi_line_width)<<16);
3652        }
3653
3654   OUTREG(RADEON_CAP0_BUF_PITCH, dstPitch*mult/2);
3655   OUTREG(RADEON_CAP0_H_WINDOW, (2*width)<<16);
3656   OUTREG(RADEON_CAP0_V_WINDOW, (((height)+pPriv->v-1)<<16)|(pPriv->v-1));
3657   if(mult==2){
3658           OUTREG(RADEON_CAP0_CONFIG, ENABLE_RADEON_CAPTURE_BOB);
3659           } else {
3660           OUTREG(RADEON_CAP0_CONFIG, ENABLE_RADEON_CAPTURE_WEAVE);
3661           }
3662   OUTREG(RADEON_CAP0_DEBUG, 0);
3663
3664   OUTREG(RADEON_VID_BUFFER_CONTROL, (1<<16) | 0x01);
3665   OUTREG(RADEON_TEST_DEBUG_CNTL, 0);
3666
3667   if(! pPriv->video_stream_active)
3668   {
3669
3670      RADEONWaitForIdleMMIO(pScrn);
3671      OUTREG(RADEON_VIDEOMUX_CNTL, INREG(RADEON_VIDEOMUX_CNTL)|1 );
3672      OUTREG(RADEON_CAP0_PORT_MODE_CNTL, (pPriv->theatre!=NULL)? 1: 0);
3673      OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_PCLK);
3674      OUTREG(RADEON_CAP0_TRIG_CNTL, 0x11);
3675      if(pPriv->theatre != NULL)
3676      {
3677         RADEON_RT_SetEncoding(pScrn, pPriv);
3678      }
3679      if(pPriv->msp3430 != NULL) RADEON_MSP_SetEncoding(pPriv);
3680      if(pPriv->tda9885 != NULL) RADEON_TDA9885_SetEncoding(pPriv);
3681      if(pPriv->fi1236 != NULL) RADEON_FI1236_SetEncoding(pPriv);
3682      if(pPriv->i2c != NULL)RADEON_board_setmisc(pPriv);
3683   }
3684
3685
3686   /* update cliplist */
3687   if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
3688        REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
3689        /* draw these */
3690        if(pPriv->autopaint_colorkey)
3691	    RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes);
3692   }
3693
3694   RADEONDisplayVideo(pScrn, crtc, pPriv, id, pPriv->video_offset,
3695		      offset1+top*srcPitch, offset2+top*srcPitch,
3696		      offset3+top*srcPitch, offset4+top*srcPitch,
3697		      offset1+top*srcPitch, offset2+top*srcPitch, width, height,
3698		      dstPitch*mult/2, xa, xb, ya, &dstBox, src_w, src_h*mult/2,
3699		      drw_w, drw_h, pPriv->overlay_deinterlacing_method);
3700
3701   RADEONWaitForFifo(pScrn, 1);
3702   OUTREG(RADEON_OV0_REG_LOAD_CNTL,  RADEON_REG_LD_CTL_LOCK);
3703   RADEONWaitForIdleMMIO(pScrn);
3704   while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_LOCK_READBACK));
3705
3706
3707   switch(pPriv->overlay_deinterlacing_method){
3708        case METHOD_BOB:
3709           OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA);
3710           OUTREG(RADEON_OV0_AUTO_FLIP_CNTL,0 /*| RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD*/
3711                |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN);
3712           break;
3713        case METHOD_SINGLE:
3714           OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xEEEEE | (9<<28));
3715           OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD
3716                |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN);
3717           break;
3718        case METHOD_WEAVE:
3719           OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0x11111 | (9<<28));
3720           OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0  |RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD
3721                | RADEON_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN
3722                /* |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN */
3723                /*|RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN */
3724                |RADEON_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE);
3725           break;
3726        default:
3727           OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA);
3728           OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD
3729                |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN);
3730        }
3731
3732
3733   RADEONWaitForIdleMMIO(pScrn);
3734   OUTREG (RADEON_OV0_AUTO_FLIP_CNTL, (INREG (RADEON_OV0_AUTO_FLIP_CNTL) ^ RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE ));
3735   OUTREG (RADEON_OV0_AUTO_FLIP_CNTL, (INREG (RADEON_OV0_AUTO_FLIP_CNTL) ^ RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE ));
3736
3737   OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0);
3738
3739#if 0
3740   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "OV0_FLAG_CNTL=0x%08x\n", INREG(RADEON_OV0_FLAG_CNTL));
3741/*   OUTREG(RADEON_OV0_FLAG_CNTL, 8); */
3742   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "OV0_VID_BUFFER_CNTL=0x%08x\n", INREG(RADEON_VID_BUFFER_CONTROL));
3743   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CAP0_BUF_STATUS=0x%08x\n", INREG(RADEON_CAP0_BUF_STATUS));
3744
3745/*   OUTREG(RADEON_OV0_SCALE_CNTL, 0x417f1B00); */
3746#endif
3747
3748   pPriv->videoStatus = CLIENT_VIDEO_ON;
3749   pPriv->video_stream_active = TRUE;
3750
3751   info->VideoTimerCallback = RADEONVideoTimerCallback;
3752
3753   return Success;
3754}
3755        /* miscellaneous TV-in helper functions */
3756
3757static void RADEON_board_setmisc(RADEONPortPrivPtr pPriv)
3758{
3759    /* Adjust PAL/SECAM constants for FI1216MF tuner */
3760    if((((pPriv->tuner_type & 0xf)==5) ||
3761        ((pPriv->tuner_type & 0xf)==11)||
3762        ((pPriv->tuner_type & 0xf)==14))
3763        && (pPriv->fi1236!=NULL))
3764    {
3765        if((pPriv->encoding>=1)&&(pPriv->encoding<=3)) /*PAL*/
3766        {
3767           pPriv->fi1236->parm.band_low = 0xA1;
3768           pPriv->fi1236->parm.band_mid = 0x91;
3769           pPriv->fi1236->parm.band_high = 0x31;
3770        }
3771        if((pPriv->encoding>=7)&&(pPriv->encoding<=9)) /*SECAM*/
3772        {
3773           pPriv->fi1236->parm.band_low = 0xA3;
3774           pPriv->fi1236->parm.band_mid = 0x93;
3775           pPriv->fi1236->parm.band_high = 0x33;
3776        }
3777    }
3778
3779}
3780
3781static void RADEON_RT_SetEncoding(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
3782{
3783int width, height;
3784RADEONWaitForIdleMMIO(pScrn);
3785
3786/* Disable VBI capture for anything but TV tuner */
3787switch(pPriv->encoding){
3788	case 2:
3789	case 5:
3790	case 8:
3791		pPriv->capture_vbi_data=1;
3792		break;
3793	default:
3794		pPriv->capture_vbi_data=0;
3795	}
3796
3797switch(pPriv->encoding){
3798        case 1:
3799                xf86_RT_SetConnector(pPriv->theatre,DEC_COMPOSITE, 0);
3800                xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL);
3801                pPriv->v=25;
3802                break;
3803        case 2:
3804                xf86_RT_SetConnector(pPriv->theatre,DEC_TUNER,0);
3805                xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL);
3806                pPriv->v=25;
3807                break;
3808        case 3:
3809                xf86_RT_SetConnector(pPriv->theatre,DEC_SVIDEO,0);
3810                xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL);
3811                pPriv->v=25;
3812                break;
3813        case 4:
3814                xf86_RT_SetConnector(pPriv->theatre, DEC_COMPOSITE,0);
3815                xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE);
3816                pPriv->v=23;
3817                break;
3818        case 5:
3819                xf86_RT_SetConnector(pPriv->theatre, DEC_TUNER, 0);
3820                xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE);
3821                pPriv->v=23;
3822                break;
3823        case 6:
3824                xf86_RT_SetConnector(pPriv->theatre, DEC_SVIDEO, 0);
3825                xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE);
3826                pPriv->v=23;
3827                break;
3828        case 7:
3829                xf86_RT_SetConnector(pPriv->theatre, DEC_COMPOSITE, 0);
3830                xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE);
3831                pPriv->v=25;
3832                break;
3833        case 8:
3834                xf86_RT_SetConnector(pPriv->theatre, DEC_TUNER, 0);
3835                xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE);
3836                pPriv->v=25;
3837                break;
3838        case 9:
3839                xf86_RT_SetConnector(pPriv->theatre, DEC_SVIDEO, 0);
3840                xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE);
3841                pPriv->v=25;
3842                break;
3843        case 10:
3844                xf86_RT_SetConnector(pPriv->theatre,DEC_COMPOSITE, 0);
3845                xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60);
3846                pPriv->v=25;
3847                break;
3848        case 11:
3849                xf86_RT_SetConnector(pPriv->theatre,DEC_TUNER,0);
3850                xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60);
3851                pPriv->v=25;
3852                break;
3853        case 12:
3854                xf86_RT_SetConnector(pPriv->theatre,DEC_SVIDEO,0);
3855                xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60);
3856                pPriv->v=25;
3857                break;
3858        default:
3859                pPriv->v=0;
3860                return;
3861        }
3862xf86_RT_SetInterlace(pPriv->theatre, 1);
3863width = InputVideoEncodings[pPriv->encoding].width;
3864height = InputVideoEncodings[pPriv->encoding].height;
3865xf86_RT_SetOutputVideoSize(pPriv->theatre, width, height*2, 0, pPriv->capture_vbi_data);
3866}
3867
3868static void RADEON_MSP_SetEncoding(RADEONPortPrivPtr pPriv)
3869{
3870xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_FAST_MUTE);
3871switch(pPriv->encoding){
3872        case 1:
3873                pPriv->msp3430->standard = MSP3430_PAL;
3874                pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
3875                break;
3876        case 2:
3877                pPriv->msp3430->standard = MSP3430_PAL;
3878                pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
3879                break;
3880        case 3:
3881                pPriv->msp3430->standard = MSP3430_PAL;
3882                pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
3883                break;
3884        case 4:
3885                pPriv->msp3430->standard = MSP3430_NTSC;
3886                pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
3887                break;
3888        case 5:
3889                pPriv->msp3430->standard = MSP3430_NTSC;
3890                pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
3891                break;
3892        case 6:
3893                pPriv->msp3430->standard = MSP3430_NTSC;
3894                pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
3895                break;
3896        case 7:
3897                pPriv->msp3430->standard = MSP3430_SECAM;
3898                pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
3899                break;
3900        case 8:
3901                pPriv->msp3430->standard = MSP3430_SECAM;
3902                pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
3903                break;
3904        case 9:
3905                pPriv->msp3430->standard = MSP3430_SECAM;
3906                pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
3907                break;
3908        case 10:
3909                pPriv->msp3430->standard = MSP3430_SECAM;
3910                pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
3911                break;
3912        case 11:
3913                pPriv->msp3430->standard = MSP3430_SECAM;
3914                pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
3915                break;
3916        case 12:
3917                pPriv->msp3430->standard = MSP3430_SECAM;
3918                pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
3919                break;
3920        default:
3921                return;
3922        }
3923xf86_InitMSP3430(pPriv->msp3430);
3924xf86_MSP3430SetVolume(pPriv->msp3430, pPriv->mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume));
3925}
3926
3927static void RADEON_TDA9885_SetEncoding(RADEONPortPrivPtr pPriv)
3928{
3929TDA9885Ptr t=pPriv->tda9885;
3930
3931switch(pPriv->encoding){
3932                /* PAL */
3933        case 1:
3934        case 2:
3935        case 3:
3936                t->standard_video_if=2;
3937                t->standard_sound_carrier=1;
3938					 t->modulation=2; /* negative FM */
3939                break;
3940                /* NTSC */
3941        case 4:
3942        case 5:
3943        case 6:
3944                t->standard_video_if=1;
3945                t->standard_sound_carrier=0;
3946					 t->modulation=2; /* negative FM */
3947                break;
3948                /* SECAM */
3949        case 7:
3950        case 8:
3951        case 9:
3952        case 10:
3953        case 11:
3954        case 12:
3955                t->standard_video_if=0;
3956                t->standard_sound_carrier=3;
3957                t->modulation=0; /* positive AM */
3958                break;
3959        default:
3960                return;
3961        }
3962xf86_tda9885_setparameters(pPriv->tda9885);
3963xf86_tda9885_getstatus(pPriv->tda9885);
3964xf86_tda9885_dumpstatus(pPriv->tda9885);
3965}
3966
3967static void RADEON_FI1236_SetEncoding(RADEONPortPrivPtr pPriv)
3968{
3969/* at the moment this only affect MT2032 */
3970switch(pPriv->encoding){
3971                /* PAL */
3972        case 1:
3973        case 2:
3974        case 3:
3975		pPriv->fi1236->video_if=38.900;
3976                break;
3977                /* NTSC */
3978        case 4:
3979        case 5:
3980        case 6:
3981		pPriv->fi1236->video_if=45.7812;
3982		pPriv->fi1236->video_if=45.750;
3983		pPriv->fi1236->video_if=45.125;
3984                break;
3985                /* SECAM */
3986        case 7:
3987        case 8:
3988        case 9:
3989        case 10:
3990        case 11:
3991        case 12:
3992		pPriv->fi1236->video_if=58.7812;
3993                break;
3994        default:
3995                return;
3996        }
3997}
3998
3999