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