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