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