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