#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "xf86fbman.h"
#include "regionstr.h"
#include "via_driver.h"
#include "via_video.h"
#include "ddmpeg.h"
#include "via_capture.h"
#include "via.h"
#include "xf86xv.h"
#include "Xv.h"
#include "xaa.h"
#include "xaalocal.h"
#include "dixstruct.h"
#include "via_xvpriv.h"
#include "via_swov.h"
#define OFF_DELAY 200
#define FREE_DELAY 60000
#define PARAMSIZE 1024
#define SLICESIZE 65536
#define OFF_TIMER 0x01
#define FREE_TIMER 0x02
#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
#define LOW_BAND 0x0CB0
#define MID_BAND 0x1f10
#define XV_IMAGE 0
#define NTSC_COMPOSITE 1
#define NTSC_TUNER 2
#define NTSC_SVIDEO 3
#define PAL_SVIDEO 4
#define PAL_60_COMPOSITE 5
#define PAL_60_TUNER 6
#define PAL_60_SVIDEO 7
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
#define IN_FLIP ( viaVidEng->ramtab & 0x00000003)
#define IN_DISPLAY ( viaVidEng->interruptflag & 0x00000200)
#define IN_VBLANK ( !IN_DISPLAY )
#ifndef XvExtension
void viaInitVideo(ScreenPtr pScreen) {}
#else
XF86VideoAdaptorPtr viaSetupImageVideoG(ScreenPtr);
static void viaStopVideoG(ScrnInfoPtr, pointer, Bool);
static int viaSetPortAttributeG(ScrnInfoPtr, Atom, INT32, pointer);
static int viaGetPortAttributeG(ScrnInfoPtr, Atom ,INT32 *, pointer);
static void viaQueryBestSizeG(ScrnInfoPtr, Bool,
short, short, short, short, unsigned int *, unsigned int *, pointer);
static int viaPutImageG( ScrnInfoPtr,
short, short, short, short, short, short, short, short,
int, unsigned char*, short, short, Bool, RegionPtr, pointer);
static int viaPutVideo(ScrnInfoPtr ,
short , short , short , short ,short , short , short , short ,
RegionPtr , pointer );
static int viaQueryImageAttributesG(ScrnInfoPtr,
int, unsigned short *, unsigned short *, int *, int *);
static Atom xvBrightness, xvContrast, xvColorKey, xvHue, xvSaturation, xvPort,
xvCompose, xvEncoding, xvMute, xvVolume, xvFreq, xvAudioCtrl,
xvHQV, xvBOB, xvExitTV;
static XF86VideoEncodingRec DummyEncoding[8] =
{
{ XV_IMAGE , "XV_IMAGE",-1, -1,{1, 1}},
{ NTSC_COMPOSITE , "ntsc-composite",720, 480, { 1001, 60000 }},
{ NTSC_TUNER , "ntsc-tuner",720, 480, { 1001, 60000 }},
{ NTSC_SVIDEO , "ntsc-svideo",720, 480, { 1001, 60000 }},
{ PAL_SVIDEO , "pal-svideo",720, 576, { 1, 50 }},
{ PAL_60_COMPOSITE, "pal_60-composite", 704, 576, { 1, 50 }},
{ PAL_60_TUNER , "pal_60-tuner", 720, 576, { 1, 50 }},
{ PAL_60_SVIDEO , "pal_60-svideo",720, 576, { 1, 50 }}
};
#define NUM_FORMATS_G 9
static XF86VideoFormatRec FormatsG[NUM_FORMATS_G] =
{
{ 8, TrueColor },
{ 8, PseudoColor },
{ 8, StaticColor },
{ 8, GrayScale },
{ 8, StaticGray },
{16, TrueColor},
{24, TrueColor},
{16, DirectColor},
{24, DirectColor}
};
#define NUM_ATTRIBUTES_G 17
static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] =
{
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
{XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
{XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
{XvSettable | XvGettable,-1000,1000,"XV_SATURATION"},
{XvSettable | XvGettable,-1000,1000,"XV_HUE"},
{XvSettable | XvGettable,0,255,"XV_MUTE"},
{XvSettable | XvGettable,0,255,"XV_VOLUME"},
{XvSettable,0,2,"XV_PORT"},
{XvSettable,0,2,"XV_COMPOSE"},
{XvSettable,0,2,"XV_SVIDEO"},
{XvSettable | XvGettable,0, 255,"XV_ENCODING"},
{XvSettable | XvGettable,0, 255, "XV_CHANNEL"},
{XvSettable,0,-1,"XV_FREQ"},
{XvSettable,0,2,"XV_AUDIOCTRL"},
{XvSettable,0,2,"XV_HIGHQVDO"},
{XvSettable,0,2,"XV_BOB"},
{XvSettable,0,2,"XV_EXITTV"},
};
#define NUM_IMAGES_G 2
static XF86ImageRec ImagesG[NUM_IMAGES_G] =
{
{
0x32595559,
XvYUV,
LSBFirst,
{'Y','U','Y','2',
0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71},
16,
XvPacked,
1,
0, 0, 0, 0 ,
8, 8, 8,
1, 2, 2,
1, 2, 2,
{'Y','U','Y','V',
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},
XvTopToBottom
} ,
{
0x32315659,
XvYUV,
LSBFirst,
{'Y','V','1','2',
0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71},
12,
XvPlanar,
3,
0, 0, 0, 0 ,
8, 8, 8,
1, 2, 2,
1, 2, 2,
{'Y','V','U',
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},
XvTopToBottom
}
};
static char * XVPORTNAME[5] =
{
"XV_SWOV",
"XV_TV0" ,
"XV_TV1" ,
"XV_UTCTRL",
"XV_DUMMY"
};
static __inline void waitVBLANK(vmmtr viaVidEng)
{
while (IN_DISPLAY);
}
static __inline void waitIfFlip(vmmtr viaVidEng)
{
while( IN_FLIP );
}
static __inline void waitDISPLAYBEGIN(vmmtr viaVidEng)
{
while (IN_VBLANK);
}
static Bool DecideOverlaySupport(VIAPtr pVia)
{
unsigned long bandwidth = (pVia->graphicInfo.dwHeight >> 4) * (pVia->graphicInfo.dwWidth >> 5) *
pVia->graphicInfo.dwBPP * pVia->graphicInfo.dwRefreshRate;
VGAOUT8(0x3D4, 0x3D);
switch ((VGAIN8(0x3D5) & 0x70) >> 4)
{
case 0:
case SDR100:
case SDR133:
return FALSE;
case DDR100:
if(bandwidth > 1800000)
return FALSE;
if (pVia->graphicInfo.dwWidth > 800)
{
if(pVia->graphicInfo.dwBPP != 8)
return FALSE;
if(pVia->graphicInfo.dwHeight > 768)
return FALSE;
if(pVia->graphicInfo.dwRefreshRate > 60)
return FALSE;
}
return TRUE;
case DDR133:
if(bandwidth > 7901250)
return FALSE;
return TRUE;
}
return FALSE;
}
void viaResetVideo(ScrnInfoPtr pScrn)
{
VIAPtr pVia = VIAPTR(pScrn);
vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
DBG_DD(ErrorF(" via_video.c : viaResetVideo: \n"));
waitVBLANK(viaVidEng);
viaVidEng->compose = 0;
viaVidEng->video1_ctl = 0;
viaVidEng->video3_ctl = 0;
}
void viaSaveVideo(ScrnInfoPtr pScrn)
{
VIAPtr pVia = VIAPTR(pScrn);
vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
pVia->dwV1 = ((vmmtr)viaVidEng)->video1_ctl;
pVia->dwV3 = ((vmmtr)viaVidEng)->video3_ctl;
waitVBLANK(viaVidEng);
viaVidEng->video1_ctl = 0;
viaVidEng->video3_ctl = 0;
}
void viaRestoreVideo(ScrnInfoPtr pScrn)
{
VIAPtr pVia = VIAPTR(pScrn);
vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
waitVBLANK(viaVidEng);
viaVidEng->video1_ctl = pVia->dwV1 ;
viaVidEng->video3_ctl = pVia->dwV3 ;
}
void viaExitVideo(ScrnInfoPtr pScrn)
{
VIAPtr pVia = VIAPTR(pScrn);
vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
DBG_DD(ErrorF(" via_video.c : viaExitVideo : \n"));
waitVBLANK(viaVidEng);
viaVidEng->video1_ctl = 0;
viaVidEng->video3_ctl = 0;
}
XF86VideoAdaptorPtr adaptPtr[XV_PORT_NUM];
void viaInitVideo(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
VIAPtr pVia = VIAPTR(pScrn);
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
XF86VideoAdaptorPtr newAdaptor = NULL;
int num_adaptors;
DBG_DD(ErrorF(" via_video.c : viaInitVideo : \n"));
if(pVia->Chipset == VIA_CLE266)
{
newAdaptor = viaSetupImageVideoG(pScreen);
}
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
DBG_DD(ErrorF(" via_video.c : num_adaptors : %d\n",num_adaptors));
if(newAdaptor) {
if(!num_adaptors) {
num_adaptors = 1;
adaptors = &newAdaptor;
} else {
DBG_DD(ErrorF(" via_video.c : viaInitVideo : Warning !!! MDS not supported yet !\n"));
newAdaptors =
xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
if(newAdaptors) {
memcpy(newAdaptors, adaptors, num_adaptors *
sizeof(XF86VideoAdaptorPtr));
newAdaptors[num_adaptors] = newAdaptor;
adaptors = newAdaptors;
num_adaptors++;
}
}
}
if(num_adaptors)
xf86XVScreenInit(pScreen, adaptPtr, XV_PORT_NUM);
if(newAdaptors)
xfree(newAdaptors);
}
XF86VideoAdaptorPtr
viaSetupImageVideoG(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
viaPortPrivRec *gviaPortPriv[XV_PORT_NUM];
DevUnion * pdevUnion[XV_PORT_NUM];
int i;
DBG_DD(ErrorF(" via_video.c : viaSetupImageVideoG: \n"));
ViaTunerProbe(pScrn);
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
xvContrast = MAKE_ATOM("XV_CONTRAST");
xvColorKey = MAKE_ATOM("XV_COLORKEY");
xvHue = MAKE_ATOM("XV_HUE");
xvSaturation = MAKE_ATOM("XV_SATURATION");
xvMute = MAKE_ATOM("XV_MUTE");
xvVolume = MAKE_ATOM("XV_VOLUME");
xvPort = MAKE_ATOM("XV_PORT");
xvCompose = MAKE_ATOM("XV_COMPOSE");
xvEncoding = MAKE_ATOM("XV_ENCODING");
xvFreq = MAKE_ATOM("XV_FREQ");
xvAudioCtrl = MAKE_ATOM("XV_AUDIOCTRL");
xvHQV = MAKE_ATOM("XV_HIGHQVDO");
xvBOB = MAKE_ATOM("XV_BOB");
xvExitTV = MAKE_ATOM("XV_EXITTV");
for ( i = 0; i< XV_PORT_NUM; i ++ ) {
if(!(adaptPtr[i] = xf86XVAllocateVideoAdaptorRec(pScrn)))
return NULL;
gviaPortPriv[i] = (viaPortPrivPtr)xnfcalloc(1, sizeof(viaPortPrivRec) );
pdevUnion[i] = (DevUnion *)xnfcalloc(1, sizeof(DevUnion));
if(i == 0)
{
adaptPtr[i]->type = XvInputMask | XvWindowMask | XvImageMask | XvVideoMask | XvStillMask;
adaptPtr[i]->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
}
else
{
adaptPtr[i]->type = XvInputMask | XvWindowMask | XvVideoMask;
adaptPtr[i]->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
}
adaptPtr[i]->name = XVPORTNAME[i];
adaptPtr[i]->nEncodings = 8;
adaptPtr[i]->pEncodings = DummyEncoding;
adaptPtr[i]->nFormats = sizeof(FormatsG) / sizeof(FormatsG[0]);
adaptPtr[i]->pFormats = FormatsG;
adaptPtr[i]->nPorts = 1;
adaptPtr[i]->pPortPrivates = pdevUnion[i];
adaptPtr[i]->pPortPrivates->ptr = (pointer) gviaPortPriv[i];
if (i == 3)
{
adaptPtr[i]->nAttributes = 0;
adaptPtr[i]->pAttributes = NULL;
}
else
{
adaptPtr[i]->nAttributes = NUM_ATTRIBUTES_G;
adaptPtr[i]->pAttributes = AttributesG;
}
adaptPtr[i]->nImages = NUM_IMAGES_G;
adaptPtr[i]->pImages = ImagesG;
adaptPtr[i]->PutVideo = viaPutVideo;
adaptPtr[i]->StopVideo = viaStopVideoG;
adaptPtr[i]->SetPortAttribute = viaSetPortAttributeG;
adaptPtr[i]->GetPortAttribute = viaGetPortAttributeG;
adaptPtr[i]->QueryBestSize = viaQueryBestSizeG;
adaptPtr[i]->PutImage = viaPutImageG;
adaptPtr[i]->QueryImageAttributes = viaQueryImageAttributesG;
#ifdef COLOR_KEY
gviaPortPriv[i]->colorKey = 0x0821;
#endif
gviaPortPriv[i]->brightness = 0;
gviaPortPriv[i]->saturation = 0;
gviaPortPriv[i]->contrast = 0;
gviaPortPriv[i]->hue = 0;
gviaPortPriv[i]->xv_portnum = i;
#ifdef XFREE86_44
REGION_NULL(pScreen, &gviaPortPriv[i]->clip);
#else
REGION_INIT(pScreen, &gviaPortPriv[i]->clip, NullBox, 1);
#endif
}
viaResetVideo(pScrn);
return adaptPtr[0];
}
static Bool
RegionsEqual(RegionPtr A, RegionPtr B)
{
int *dataA, *dataB;
int num;
num = REGION_NUM_RECTS(A);
if(num != REGION_NUM_RECTS(B))
return FALSE;
if((A->extents.x1 != B->extents.x1) ||
(A->extents.x2 != B->extents.x2) ||
(A->extents.y1 != B->extents.y1) ||
(A->extents.y2 != B->extents.y2))
return FALSE;
dataA = (int*)REGION_RECTS(A);
dataB = (int*)REGION_RECTS(B);
while(num--) {
if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
return FALSE;
dataA += 2;
dataB += 2;
}
return TRUE;
}
static int CreateSWOVSurface(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv, int fourcc, short width, short height)
{
VIAPtr pVia = VIAPTR(pScrn);
LPDDSURFACEDESC lpSurfaceDesc = &pPriv->SurfaceDesc;
unsigned long retCode;
if (pVia->Video.VideoStatus & SWOV_SURFACE_CREATED)
return Success;
lpSurfaceDesc->dwWidth = (unsigned long)width;
lpSurfaceDesc->dwHeight = (unsigned long)height;
lpSurfaceDesc->dwBackBufferCount =1;
lpSurfaceDesc->dwFourCC = (unsigned long)fourcc;
if (Success != (retCode = VIAVidCreateSurface(pScrn, lpSurfaceDesc)))
return retCode;
pPriv->ddLock.dwFourCC = (unsigned long)fourcc;
VIAVidLockSurface(pScrn, &pPriv->ddLock);
pPriv->ddLock.SWDevice.lpSWOverlaySurface[0] = pVia->FBBase + pPriv->ddLock.SWDevice.dwSWPhysicalAddr[0];
pPriv->ddLock.SWDevice.lpSWOverlaySurface[1] = pVia->FBBase + pPriv->ddLock.SWDevice.dwSWPhysicalAddr[1];
DBG_DD(ErrorF(" lpSWOverlaySurface[0]: %p\n", pPriv->ddLock.SWDevice.lpSWOverlaySurface[0]));
DBG_DD(ErrorF(" lpSWOverlaySurface[1]: %p\n", pPriv->ddLock.SWDevice.lpSWOverlaySurface[1]));
pVia->Video.VideoStatus |= SWOV_SURFACE_CREATED|SW_VIDEO_ON;
pVia->Video.dwAction = ACTION_SET_VIDEOSTATUS;
return Success;
}
static void DestroySWOVSurface(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv)
{
VIAPtr pVia = VIAPTR(pScrn);
LPDDSURFACEDESC lpSurfaceDesc = &pPriv->SurfaceDesc;
DBG_DD(ErrorF(" via_video.c : Destroy SW Overlay Surface, fourcc =0x%08x : \n",
lpSurfaceDesc->dwFourCC));
if (pVia->Video.VideoStatus & SWOV_SURFACE_CREATED)
{
DBG_DD(ErrorF(" via_video.c : Destroy SW Overlay Surface, VideoStatus =0x%08x : \n",
pVia->Video.VideoStatus));
}
else
{
DBG_DD(ErrorF(" via_video.c : No SW Overlay Surface Destroyed, VideoStatus =0x%08x : \n",
pVia->Video.VideoStatus));
return;
}
VIAVidDestroySurface(pScrn, lpSurfaceDesc);
pVia->Video.VideoStatus &= ~SWOV_SURFACE_CREATED;
pVia->Video.dwAction = ACTION_SET_VIDEOSTATUS;
}
static void StopSWOVerlay(ScrnInfoPtr pScrn)
{
DDUPDATEOVERLAY UpdateOverlay_Video;
LPDDUPDATEOVERLAY lpUpdateOverlay = &UpdateOverlay_Video;
VIAPtr pVia = VIAPTR(pScrn);
pVia->Video.VideoStatus &= ~SW_VIDEO_ON;
pVia->Video.dwAction = ACTION_SET_VIDEOSTATUS;
lpUpdateOverlay->dwFlags = DDOVER_HIDE;
VIAVidUpdateOverlay(pScrn, lpUpdateOverlay);
}
static void
viaStopVideoG(ScrnInfoPtr pScrn, pointer data, Bool exit)
{
VIAPtr pVia = VIAPTR(pScrn);
viaPortPrivPtr pPriv = (viaPortPrivPtr)data;
DBG_DD(ErrorF(" via_video.c : viaStopVideoG: exit=%d\n", exit));
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
if(exit) {
StopSWOVerlay(pScrn);
DestroySWOVSurface(pScrn, pPriv);
pVia->dwFrameNum = 0;
pPriv->old_drw_x= 0;
pPriv->old_drw_y= 0;
pPriv->old_drw_w= 0;
pPriv->old_drw_h= 0;
} else {
StopSWOVerlay(pScrn);
}
}
#define Attr_Mapping(x) x = ( (x + 1000) >> 3 )
static void SetTunerChannel (ViaTunerPtr pTuner, viaPortPrivPtr pChanPriv, INT32 frequency)
{
int control;
short divider = 0;
switch(pChanPriv->dwEncoding)
{
case PAL_60_COMPOSITE :
case PAL_60_TUNER :
case PAL_60_SVIDEO :
divider = 633 + (short)frequency;
break;
case NTSC_COMPOSITE :
case NTSC_TUNER :
case NTSC_SVIDEO :
divider = 733 + (short)frequency;
break;
default:
divider = frequency;
}
control = 0x8E00;
if ( divider <= LOW_BAND )
control |= 0xA0;
else if ( divider <= MID_BAND )
control |= 0x90;
else
control |= 0x30;
DBG_DD(ErrorF(" via_video.c : SetTunerChannel : Divider = 0x%08x, Control= 0x%08x, \n", divider,control));
if(pTuner)
ViaTunerChannel(pTuner, divider, control);
}
static int
v4l_to_xv(int val) {
val = val * 2000 / 65536 - 1000;
if (val < -1000) val = -1000;
if (val > 1000) val = 1000;
return val;
}
static int
xv_to_v4l(int val) {
val = val * 65536 / 2000 + 32768;
if (val < -0) val = 0;
if (val > 65535) val = 65535;
return val;
}
static int
viaSetPortAttributeG(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 value,
pointer data
){
VIAPtr pVia = VIAPTR(pScrn);
vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
viaPortPrivPtr pPriv = (viaPortPrivPtr)data;
int attr, avalue;
ViaTunerPtr pTuner = NULL;
if(pPriv->xv_portnum == COMMAND_FOR_TV0)
pTuner = pVia->Tuner[0];
else if(pPriv->xv_portnum == COMMAND_FOR_TV1)
pTuner = pVia->Tuner[1];
;
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : \n"));
pVia->OverlaySupported = DecideOverlaySupport(pVia);
if(attribute == xvColorKey) {
DBG_DD(ErrorF(" V4L Disable xvColorKey = %08x\n",value));
pPriv->colorKey = value;
value &= 0x00FFFFFF;
viaVidEng->color_key = value;
viaVidEng->snd_color_key = value;
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
DBG_DD(ErrorF(" V4L Disable done xvColorKey = %08x\n",value));
} else if (attribute == xvBrightness ||
attribute == xvContrast ||
attribute == xvSaturation ||
attribute == xvHue) {
if (attribute == xvBrightness)
{
DBG_DD(ErrorF(" xvBrightness = %08d\n",value));
pPriv->pict.brightness = xv_to_v4l(value);
if(pTuner)
ViaTunerBrightness(pTuner, value);
}
if (attribute == xvContrast)
{
DBG_DD(ErrorF(" xvContrast = %08d\n",value));
pPriv->pict.contrast = xv_to_v4l(value);
if(pTuner)
ViaTunerContrast(pTuner, value);
}
if (attribute == xvSaturation)
{
DBG_DD(ErrorF(" xvSaturation = %08d\n",value));
pPriv->pict.colour = xv_to_v4l(value);
if(pTuner)
ViaTunerSaturation(pTuner, value);
}
if (attribute == xvHue)
{
DBG_DD(ErrorF(" xvHue = %08d\n",value));
pPriv->pict.hue = xv_to_v4l(value);
if(pTuner)
ViaTunerHue(pTuner, value);
}
} else if (attribute == xvMute){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvMute = %08d\n",value));
if(value)
value = 1;
ViaAudioMute(pVia, value);
} else if (attribute == xvVolume){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvVolume = %08d\n",value));
pPriv->Volume = value;
attr = ATTR_VOLUME;
avalue = value;
} else if (attribute == xvFreq){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvFreq = %08x\n",value));
SetTunerChannel(pTuner, pPriv, value );
} else if (attribute == xvEncoding){
DBG_DD(ErrorF(" xvEncoding = %d. \n",value));
pPriv->dwEncoding = value;
if(pTuner)
ViaTunerStandard(pTuner, value);
} else if (attribute == xvPort ){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvPort=%d\n", value));
} else if (attribute == xvCompose){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvCompose=%08x\n",value));
} else if (attribute == xvHQV){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvHQV=%08x\n",value));
} else if (attribute == xvBOB){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvBOB=%08x\n",value));
} else if (attribute == xvExitTV){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvExitTV=%08x\n",value));
} else if (attribute == xvAudioCtrl ){
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : xvAudioSwitch=%d\n", value));
if(pTuner)
{
ViaAudioMode(pVia, value);
if(pPriv->xv_portnum == COMMAND_FOR_TV0)
ViaAudioSelect(pVia,0);
else
ViaAudioSelect(pVia, 1);
}
}else{
DBG_DD(ErrorF(" via_video.c : viaSetPortAttributeG : is not supported the attribute"));
return BadMatch;
}
(void)attr;
(void)avalue;
return Success;
}
static int
viaGetPortAttributeG(
ScrnInfoPtr pScrn,
Atom attribute,
INT32 *value,
pointer data
){
viaPortPrivPtr pPriv = (viaPortPrivPtr)data;
DBG_DD(ErrorF(" via_video.c : viaGetPortAttributeG : port %d\n",pPriv->xv_portnum));
*value = 0;
if (attribute == xvColorKey ) {
*value =(INT32) pPriv->colorKey;
DBG_DD(ErrorF(" via_video.c : ColorKey 0x%x\n",pPriv->colorKey));
} else if (attribute == xvBrightness ||
attribute == xvContrast ||
attribute == xvSaturation ||
attribute == xvHue) {
if (attribute == xvBrightness)
{
*value = v4l_to_xv(pPriv->pict.brightness);
DBG_DD(ErrorF(" xvBrightness = %08d\n", *value));
}
if (attribute == xvContrast)
{
*value = v4l_to_xv(pPriv->pict.contrast);
DBG_DD(ErrorF(" xvContrast = %08d\n", *value));
}
if (attribute == xvSaturation)
{
*value = v4l_to_xv(pPriv->pict.colour);
DBG_DD(ErrorF(" xvSaturation = %08d\n", *value));
}
if (attribute == xvHue)
{
*value = v4l_to_xv(pPriv->pict.hue);
DBG_DD(ErrorF(" xvHue = %08d\n", *value));
}
}else {
;
}
return Success;
}
static void
viaQueryBestSizeG(
ScrnInfoPtr pScrn,
Bool motion,
short vid_w, short vid_h,
short drw_w, short drw_h,
unsigned int *p_w, unsigned int *p_h,
pointer data
){
DBG_DD(ErrorF(" via_video.c : viaQueryBestSizeG :\n"));
*p_w = drw_w;
*p_h = drw_h;
if(*p_w > 2048 )
*p_w = 2048;
}
static void Flip(VIAPtr pVia, viaPortPrivPtr pPriv, int fourcc, unsigned long DisplayBufferIndex)
{
switch(fourcc)
{
case FOURCC_UYVY:
case FOURCC_YUY2:
while ((VIDInD(HQV_CONTROL) & HQV_SW_FLIP) );
VIDOutD(HQV_SRC_STARTADDR_Y, pPriv->ddLock.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
VIDOutD(HQV_CONTROL,( VIDInD(HQV_CONTROL)&~HQV_FLIP_ODD) |HQV_SW_FLIP|HQV_FLIP_STATUS);
break;
case FOURCC_YV12:
default:
while ((VIDInD(HQV_CONTROL) & HQV_SW_FLIP) );
VIDOutD(HQV_SRC_STARTADDR_Y, pPriv->ddLock.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
VIDOutD(HQV_SRC_STARTADDR_U, pPriv->ddLock.SWDevice.dwSWCbPhysicalAddr[DisplayBufferIndex]);
VIDOutD(HQV_SRC_STARTADDR_V, pPriv->ddLock.SWDevice.dwSWCrPhysicalAddr[DisplayBufferIndex]);
VIDOutD(HQV_CONTROL,( VIDInD(HQV_CONTROL)&~HQV_FLIP_ODD) |HQV_SW_FLIP|HQV_FLIP_STATUS);
break;
}
}
static void CopyDataYUV422(
ScrnInfoPtr pScrn,
VIAPtr pVia,
unsigned char * src,
unsigned char * dst,
int srcPitch,
int dstPitch,
int h,
int w )
{
int count;
w <<= 1;
srcPitch <<= 1;
count = h;
while(count--) {
memcpy(dst, src, w);
src += srcPitch;
dst += dstPitch;
}
}
static void
CopyDataYUV420(
ScrnInfoPtr pScrn,
VIAPtr pVia,
unsigned char *src1,
unsigned char *src2,
unsigned char *src3,
unsigned char *dst1,
unsigned char *dst2,
unsigned char *dst3,
int srcPitch,
int dstPitch,
int h,
int w
){
int count;
count = h;
while(count--) {
memcpy(dst1, src1, w);
src1 += srcPitch;
dst1 += dstPitch;
}
w >>= 1;
h >>= 1;
srcPitch >>= 1;
dstPitch >>= 1;
count = h;
while(count--) {
memcpy(dst2, src2, w);
src2 += srcPitch;
dst2 += dstPitch;
}
count = h;
while(count--) {
memcpy(dst3, src3, w);
src3 += srcPitch;
dst3 += dstPitch;
}
}
static int
viaPutImageG(
ScrnInfoPtr pScrn,
short src_x, short src_y,
short drw_x, short drw_y,
short src_w, short src_h,
short drw_w, short drw_h,
int id, unsigned char* buf,
short width, short height,
Bool sync,
RegionPtr clipBoxes, pointer data
){
VIAPtr pVia = VIAPTR(pScrn);
viaPortPrivPtr pPriv = (viaPortPrivPtr)data;
vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
unsigned long retCode;
# ifdef XV_DEBUG
ErrorF(" via_video.c : viaPutImageG : called\n");
ErrorF(" via_video.c : FourCC=0x%x width=%d height=%d sync=%d\n",id,width,height,sync);
ErrorF(" via_video.c : src_x=%d src_y=%d src_w=%d src_h=%d colorkey=0x%x\n",src_x, src_y, src_w, src_h, pPriv->colorKey);
ErrorF(" via_video.c : drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n",drw_x,drw_y,drw_w,drw_h);
# endif
switch ( pPriv->xv_portnum )
{
case COMMAND_FOR_TV0 :
case COMMAND_FOR_TV1 :
DBG_DD(ErrorF(" via_video.c : : Shall not happen! \n"));
break;
case COMMAND_FOR_SWOV :
case COMMAND_FOR_DUMMY :
{
DDUPDATEOVERLAY UpdateOverlay_Video;
LPDDUPDATEOVERLAY lpUpdateOverlay = &UpdateOverlay_Video;
int srcPitch, dstPitch;
int srcYSize, srcUVSize;
int dstYSize, dstUVSize;
unsigned long dwUseExtendedFIFO=0;
DBG_DD(ErrorF(" via_video.c : : S/W Overlay! \n"));
if ( (pPriv->old_src_w != src_w) || (pPriv->old_src_h != src_h) )
DestroySWOVSurface(pScrn, pPriv);
if (Success != ( retCode = CreateSWOVSurface(pScrn, pPriv, id, width, height) ))
{
DBG_DD(ErrorF(" : Fail to Create SW Video Surface\n"));
return retCode;
}
srcPitch = width;
srcYSize = width * height;
srcUVSize = srcYSize >>2;
dstPitch = pPriv->ddLock.SWDevice.dwPitch;
dstYSize = dstPitch * height;
dstUVSize = dstYSize >>2;
switch(id)
{
case FOURCC_YV12:
CopyDataYUV420(pScrn, pVia, buf , buf + srcYSize, buf + srcYSize + srcUVSize,
pPriv->ddLock.SWDevice.lpSWOverlaySurface[pVia->dwFrameNum&1],
pPriv->ddLock.SWDevice.lpSWOverlaySurface[pVia->dwFrameNum&1] + dstYSize,
pPriv->ddLock.SWDevice.lpSWOverlaySurface[pVia->dwFrameNum&1] + dstYSize + dstUVSize,
srcPitch, dstPitch, height, width);
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
CopyDataYUV422(pScrn, pVia, buf,
pPriv->ddLock.SWDevice.lpSWOverlaySurface[pVia->dwFrameNum&1],
srcPitch, dstPitch, height, width);
break;
}
if ((viaVidEng->video3_ctl & 0x00000001) && !pVia->OverlaySupported)
return BadAlloc;
lpUpdateOverlay->rSrc.left = src_x;
lpUpdateOverlay->rSrc.top = src_y;
lpUpdateOverlay->rSrc.right = src_x + width;
lpUpdateOverlay->rSrc.bottom = src_y + height;
lpUpdateOverlay->rDest.left = drw_x;
lpUpdateOverlay->rDest.top = drw_y;
lpUpdateOverlay->rDest.right = lpUpdateOverlay->rDest.left + drw_w;
lpUpdateOverlay->rDest.bottom = drw_y + drw_h;
lpUpdateOverlay->dwFlags = DDOVER_SHOW | DDOVER_KEYDEST;
if (pScrn->bitsPerPixel == 8)
{
lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff;
}
else
{
lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
}
lpUpdateOverlay->dwFourcc = id;
if ((pVia->graphicInfo.dwWidth > 1024))
{
dwUseExtendedFIFO = 1;
}
DBG_DD(ErrorF(" : Flip\n"));
Flip(pVia, pPriv, id, pVia->dwFrameNum&1);
pVia->dwFrameNum ++;
if ( (pPriv->old_drw_x == drw_x) && (pPriv->old_drw_y == drw_y)
&& (pPriv->old_drw_w == drw_w) && (pPriv->old_drw_h == drw_h)
&& (pPriv->old_src_w == src_w) && (pPriv->old_src_h == src_h)
&& (pVia->old_dwUseExtendedFIFO == dwUseExtendedFIFO)
&& (pVia->Video.VideoStatus & SW_VIDEO_ON) &&
RegionsEqual(&pPriv->clip, clipBoxes))
{
return Success;
}
pPriv->old_drw_x = drw_x;
pPriv->old_drw_y = drw_y;
pPriv->old_drw_w = drw_w;
pPriv->old_drw_h = drw_h;
pVia->old_dwUseExtendedFIFO = dwUseExtendedFIFO;
pVia->Video.VideoStatus |= SW_VIDEO_ON;
pPriv->old_src_w = src_w;
pPriv->old_src_h = src_h;
if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
}
if ( -1 == VIAVidUpdateOverlay(pScrn, lpUpdateOverlay))
{
DBG_DD(ErrorF(" via_video.c : : call v4l updateoverlay fail. \n"));
}
else
{
DBG_DD(ErrorF(" via_video.c : PutImageG done OK\n"));
return Success;
}
}
break;
case COMMAND_FOR_UTCTRL :{
VIAXVUtilityProc(pScrn, buf);
break;
}
default:
DBG_DD(ErrorF(" via_video.c : XVPort not supported\n"));
break;
}
DBG_DD(ErrorF(" via_video.c : PutImageG done OK\n"));
return Success;
}
static int
viaQueryImageAttributesG(
ScrnInfoPtr pScrn,
int id,
unsigned short *w, unsigned short *h,
int *pitches, int *offsets
){
int size, tmp;
DBG_DD(ErrorF(" via_video.c : viaQueryImageAttributesG : FourCC=0x%x, ", id));
if ( (!w) || (!h) )
return 0;
if(*w > 1024) *w = 1024;
if(*h > 1024) *h = 1024;
*w = (*w + 1) & ~1;
if(offsets)
offsets[0] = 0;
switch(id) {
case 0x32315659:
*h = (*h + 1) & ~1;
size = (*w + 3) & ~3;
if(pitches) pitches[0] = size;
size *= *h;
if(offsets) offsets[1] = size;
tmp = ((*w >> 1) + 3) & ~3;
if(pitches) pitches[1] = pitches[2] = tmp;
tmp *= (*h >> 1);
size += tmp;
if(offsets) offsets[2] = size;
size += tmp;
break;
case 0x59565955:
case 0x32595559:
default:
size = *w << 1;
if(pitches)
pitches[0] = size;
size *= *h;
break;
}
if ( pitches )
DBG_DD(ErrorF(" pitches[0]=%d, pitches[1]=%d, pitches[2]=%d, ", pitches[0], pitches[1], pitches[2]));
if ( offsets )
DBG_DD(ErrorF(" offsets[0]=%d, offsets[1]=%d, offsets[2]=%d, ", offsets[0], offsets[1], offsets[2]));
DBG_DD(ErrorF(" width=%d, height=%d \n", *w, *h));
return size;
}
static int
viaPutVideo(ScrnInfoPtr pScrn,
short src_x, short src_y, short drw_x, short drw_y,
short src_w, short src_h, short drw_w, short drw_h,
RegionPtr clipBoxes, pointer data)
{
viaPortPrivPtr pPriv=(viaPortPrivPtr)data;
#ifdef XV_DEBUG
ErrorF(" via_video.c : viaPutVideo : Src %dx%d, %d, %d, %p\n",src_w,src_h,src_x,src_y,clipBoxes);
ErrorF(" via_video.c : Dst %dx%d, %d, %d \n",drw_w,drw_h,drw_x,drw_y);
ErrorF(" via_video.c : colorkey : 0x%x \n",pPriv->colorKey);
#endif
if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
XAAFillSolidRects(pScrn,pPriv->colorKey,GXcopy, ~0,
REGION_NUM_RECTS(clipBoxes),
REGION_RECTS(clipBoxes));
}
switch ( pPriv->xv_portnum )
{
case COMMAND_FOR_TV0 :
pPriv->yuv_win.x = drw_x;
pPriv->yuv_win.y = drw_y;
pPriv->yuv_win.width = drw_w;
pPriv->yuv_win.height = drw_h;
pPriv->yuv_win.chromakey = pPriv->colorKey;
break;
case COMMAND_FOR_TV1 :
pPriv->yuv_win.x = drw_x;
pPriv->yuv_win.y = drw_y;
pPriv->yuv_win.width = drw_w;
pPriv->yuv_win.height = drw_h;
pPriv->yuv_win.chromakey = pPriv->colorKey;
break;
case COMMAND_FOR_SWOV :
case COMMAND_FOR_DUMMY :
case COMMAND_FOR_UTCTRL :
DBG_DD(ErrorF(" via_video.c : This port doesn't support PutVideo.\n"));
return XvBadAlloc;
default:
DBG_DD(ErrorF(" via_video.c : Error port access.\n"));
return XvBadAlloc;
}
return Success;
}
#endif