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