1de2362d3Smrg
2de2362d3Smrg#ifdef HAVE_CONFIG_H
3de2362d3Smrg#include "config.h"
4de2362d3Smrg#endif
5de2362d3Smrg
6de2362d3Smrg#include <stdlib.h>
7de2362d3Smrg#include <string.h>
8de2362d3Smrg#include <stdio.h>
9de2362d3Smrg#include <math.h>
10de2362d3Smrg
11de2362d3Smrg#include "radeon.h"
1218781e08Smrg#include "radeon_glamor.h"
13de2362d3Smrg#include "radeon_reg.h"
14de2362d3Smrg#include "radeon_probe.h"
15de2362d3Smrg#include "radeon_video.h"
16de2362d3Smrg
17de2362d3Smrg#include "xf86.h"
18de2362d3Smrg#include "dixstruct.h"
19de2362d3Smrg
20de2362d3Smrg/* DPMS */
21de2362d3Smrg#ifdef HAVE_XEXTPROTO_71
22de2362d3Smrg#include <X11/extensions/dpmsconst.h>
23de2362d3Smrg#else
24de2362d3Smrg#define DPMS_SERVER
25de2362d3Smrg#include <X11/extensions/dpms.h>
26de2362d3Smrg#endif
27de2362d3Smrg
28de2362d3Smrg#include <X11/extensions/Xv.h>
29de2362d3Smrg#include "fourcc.h"
30de2362d3Smrg
31de2362d3Smrg#define OFF_DELAY       250  /* milliseconds */
32de2362d3Smrg#define FREE_DELAY      15000
33de2362d3Smrg
34de2362d3Smrg#define OFF_TIMER       0x01
35de2362d3Smrg#define FREE_TIMER      0x02
36de2362d3Smrg#define CLIENT_VIDEO_ON 0x04
37de2362d3Smrg
38de2362d3Smrg#define GET_PORT_PRIVATE(pScrn) \
39de2362d3Smrg   (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
40de2362d3Smrg
41de2362d3Smrgstatic void
42de2362d3Smrgradeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
43de2362d3Smrg{
44de2362d3Smrg    dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
45de2362d3Smrg    dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
46de2362d3Smrg    dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
47de2362d3Smrg    dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
48de2362d3Smrg
49de2362d3Smrg    if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
50de2362d3Smrg	dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
51de2362d3Smrg}
52de2362d3Smrg
53de2362d3Smrgstatic void
54de2362d3Smrgradeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
55de2362d3Smrg{
56de2362d3Smrg    if (crtc->enabled) {
57de2362d3Smrg	crtc_box->x1 = crtc->x;
58de2362d3Smrg	crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
59de2362d3Smrg	crtc_box->y1 = crtc->y;
60de2362d3Smrg	crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
61de2362d3Smrg    } else
62de2362d3Smrg	crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
63de2362d3Smrg}
64de2362d3Smrg
65de2362d3Smrgstatic int
66de2362d3Smrgradeon_box_area(BoxPtr box)
67de2362d3Smrg{
68de2362d3Smrg    return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
69de2362d3Smrg}
70de2362d3Smrg
7118781e08SmrgBool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
72de2362d3Smrg{
7318781e08Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
748bf5c682Smrg    return drmmode_crtc->dpms_mode == DPMSModeOn;
75de2362d3Smrg}
76de2362d3Smrg
77de2362d3Smrgxf86CrtcPtr
7818781e08Smrgradeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
79de2362d3Smrg		      int x1, int x2, int y1, int y2)
80de2362d3Smrg{
81de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
8218781e08Smrg    int			coverage, best_coverage, c, cd;
83de2362d3Smrg    BoxRec		box, crtc_box, cover_box;
84de2362d3Smrg    RROutputPtr         primary_output = NULL;
85de2362d3Smrg    xf86CrtcPtr         best_crtc = NULL, primary_crtc = NULL;
86de2362d3Smrg
87de2362d3Smrg    if (!pScrn->vtSema)
88de2362d3Smrg	return NULL;
89de2362d3Smrg
90de2362d3Smrg    box.x1 = x1;
91de2362d3Smrg    box.x2 = x2;
92de2362d3Smrg    box.y1 = y1;
93de2362d3Smrg    box.y2 = y2;
94de2362d3Smrg    best_coverage = 0;
95de2362d3Smrg
96de2362d3Smrg    /* Prefer the CRTC of the primary output */
97de2362d3Smrg    if (dixPrivateKeyRegistered(rrPrivKey))
98de2362d3Smrg    {
99de2362d3Smrg	primary_output = RRFirstOutput(pScrn->pScreen);
100de2362d3Smrg    }
101de2362d3Smrg    if (primary_output && primary_output->crtc)
102de2362d3Smrg	primary_crtc = primary_output->crtc->devPrivate;
103de2362d3Smrg
10418781e08Smrg    /* first consider only enabled CRTCs
10518781e08Smrg     * then on second pass consider disabled ones
1067821949aSmrg     */
10718781e08Smrg    for (cd = 0; cd < (consider_disabled ? 2 : 1); cd++) {
10818781e08Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
10918781e08Smrg	    xf86CrtcPtr crtc = xf86_config->crtc[c];
11018781e08Smrg
11118781e08Smrg	    if (!cd && !radeon_crtc_is_enabled(crtc))
11218781e08Smrg		continue;
11318781e08Smrg
11418781e08Smrg	    radeon_crtc_box(crtc, &crtc_box);
11518781e08Smrg	    radeon_box_intersect(&cover_box, &crtc_box, &box);
11618781e08Smrg	    coverage = radeon_box_area(&cover_box);
11718781e08Smrg	    if (coverage > best_coverage ||
11818781e08Smrg		(coverage == best_coverage &&
11918781e08Smrg		 crtc == primary_crtc)) {
12018781e08Smrg		best_crtc = crtc;
12118781e08Smrg		best_coverage = coverage;
12218781e08Smrg	    }
1237821949aSmrg	}
12418781e08Smrg	if (best_crtc)
12518781e08Smrg	    break;
1267821949aSmrg    }
1277821949aSmrg
12818781e08Smrg    return best_crtc;
1297821949aSmrg}
1307821949aSmrg
131de2362d3Smrg
132de2362d3Smrgvoid RADEONInitVideo(ScreenPtr pScreen)
133de2362d3Smrg{
134de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
135de2362d3Smrg    RADEONInfoPtr    info = RADEONPTR(pScrn);
136de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
137de2362d3Smrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
13818781e08Smrg    XF86VideoAdaptorPtr texturedAdaptor = NULL;
139de2362d3Smrg    int num_adaptors;
140de2362d3Smrg
141de2362d3Smrg    /* no overlay or 3D on RN50 */
142de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2)
143de2362d3Smrg	    return;
144de2362d3Smrg
145de2362d3Smrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
14618781e08Smrg    newAdaptors = malloc((num_adaptors + 2) * sizeof(*newAdaptors));
14739413783Smrg    if (!newAdaptors)
148de2362d3Smrg	return;
149de2362d3Smrg
150de2362d3Smrg    memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
151de2362d3Smrg    adaptors = newAdaptors;
152de2362d3Smrg
15318781e08Smrg    if (info->use_glamor) {
15418781e08Smrg        texturedAdaptor = radeon_glamor_xv_init(pScreen, 16);
15539413783Smrg	if (texturedAdaptor) {
15618781e08Smrg	    adaptors[num_adaptors++] = texturedAdaptor;
15718781e08Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video (glamor)\n");
158de2362d3Smrg	} else
15918781e08Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video (glamor)\n");
16018781e08Smrg    } else if ((info->ChipFamily < CHIP_FAMILY_RS400)
161de2362d3Smrg	|| (info->directRenderingEnabled)
162de2362d3Smrg	) {
163de2362d3Smrg	texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);
16439413783Smrg	if (texturedAdaptor) {
165de2362d3Smrg	    adaptors[num_adaptors++] = texturedAdaptor;
166de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
167de2362d3Smrg	} else
168de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video\n");
169de2362d3Smrg    } else
170de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textured video requires CP on R5xx/R6xx/R7xx/IGP\n");
171de2362d3Smrg
172de2362d3Smrg    if(num_adaptors)
173de2362d3Smrg	xf86XVScreenInit(pScreen, adaptors, num_adaptors);
174de2362d3Smrg
175de2362d3Smrg    if(texturedAdaptor) {
176861b9feeSmrg	XF86MCAdaptorPtr xvmcAdaptor = RADEONCreateAdaptorXvMC(pScreen, texturedAdaptor->name);
177de2362d3Smrg	if(xvmcAdaptor) {
178de2362d3Smrg	    if(!xf86XvMCScreenInit(pScreen, 1, &xvmcAdaptor))
179de2362d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] Failed to initialize extension.\n");
180de2362d3Smrg	    else
181de2362d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[XvMC] Extension initialized.\n");
182de2362d3Smrg	}
183de2362d3Smrg    }
184de2362d3Smrg
185de2362d3Smrg    if(newAdaptors)
186de2362d3Smrg	free(newAdaptors);
187de2362d3Smrg
188de2362d3Smrg}
189de2362d3Smrg
19018781e08Smrgvoid
19118781e08SmrgRADEONCopyData(
19218781e08Smrg  ScrnInfoPtr pScrn,
19318781e08Smrg  unsigned char *src,
19418781e08Smrg  unsigned char *dst,
19518781e08Smrg  unsigned int srcPitch,
19618781e08Smrg  unsigned int dstPitch,
19718781e08Smrg  unsigned int h,
19818781e08Smrg  unsigned int w,
19918781e08Smrg  unsigned int bpp
20018781e08Smrg){
20118781e08Smrg    /* Get the byte-swapping right for big endian systems */
20218781e08Smrg    if ( bpp == 2 ) {
20318781e08Smrg	w *= 2;
20418781e08Smrg	bpp = 1;
2057821949aSmrg    }
2067821949aSmrg
2077821949aSmrg    {
20818781e08Smrg	int swap = RADEON_HOST_DATA_SWAP_NONE;
2097821949aSmrg
21018781e08Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
21118781e08Smrg	switch(bpp) {
21218781e08Smrg	case 2:
21318781e08Smrg	    swap = RADEON_HOST_DATA_SWAP_16BIT;
21418781e08Smrg	    break;
21518781e08Smrg	case 4:
21618781e08Smrg	    swap = RADEON_HOST_DATA_SWAP_32BIT;
21718781e08Smrg	    break;
21818781e08Smrg	}
21918781e08Smrg#endif
2207821949aSmrg
22118781e08Smrg	w *= bpp;
2227821949aSmrg
22318781e08Smrg	if (dstPitch == w && dstPitch == srcPitch)
22418781e08Smrg	    RADEONCopySwap(dst, src, h * dstPitch, swap);
22518781e08Smrg	else {
22618781e08Smrg	    while (h--) {
22718781e08Smrg		RADEONCopySwap(dst, src, w, swap);
22818781e08Smrg		src += srcPitch;
22918781e08Smrg		dst += dstPitch;
23018781e08Smrg	    }
23118781e08Smrg	}
232de2362d3Smrg    }
233de2362d3Smrg}
234de2362d3Smrg
235de2362d3Smrg
236de2362d3Smrgvoid
23718781e08SmrgRADEONCopyMungedData(
23818781e08Smrg   ScrnInfoPtr pScrn,
23918781e08Smrg   unsigned char *src1,
24018781e08Smrg   unsigned char *src2,
24118781e08Smrg   unsigned char *src3,
24218781e08Smrg   unsigned char *dst1,
24318781e08Smrg   unsigned int srcPitch,
24418781e08Smrg   unsigned int srcPitch2,
24518781e08Smrg   unsigned int dstPitch,
24618781e08Smrg   unsigned int h,
24718781e08Smrg   unsigned int w
24818781e08Smrg){
24918781e08Smrg    uint32_t *dst;
25018781e08Smrg    uint8_t *s1, *s2, *s3;
25118781e08Smrg    int i, j;
25218781e08Smrg
25318781e08Smrg    w /= 2;
25418781e08Smrg
25518781e08Smrg    for( j = 0; j < h; j++ ) {
25618781e08Smrg	dst = (pointer)dst1;
25718781e08Smrg	s1 = src1;  s2 = src2;  s3 = src3;
25818781e08Smrg	i = w;
25918781e08Smrg	while( i > 4 ) {
26018781e08Smrg	    dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
26118781e08Smrg	    dst[1] = cpu_to_le32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24));
26218781e08Smrg	    dst[2] = cpu_to_le32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24));
26318781e08Smrg	    dst[3] = cpu_to_le32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24));
26418781e08Smrg	    dst += 4; s2 += 4; s3 += 4; s1 += 8;
26518781e08Smrg	    i -= 4;
266de2362d3Smrg	}
26718781e08Smrg	while( i-- ) {
26818781e08Smrg	    dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
26918781e08Smrg	    dst++; s2++; s3++;
27018781e08Smrg	    s1 += 2;
271de2362d3Smrg	}
272de2362d3Smrg
27318781e08Smrg	dst1 += dstPitch;
27418781e08Smrg	src1 += srcPitch;
27518781e08Smrg	if( j & 1 ) {
27618781e08Smrg	    src2 += srcPitch2;
27718781e08Smrg	    src3 += srcPitch2;
27818781e08Smrg	}
2797821949aSmrg    }
2807821949aSmrg}
281