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