Charles.Forsyth20060303644188019 years agoHistory
1826 lines · 43.1 KB · C
RawDownload
/* * Driver for Hauppage TV board * * Control commands: * *	init *	window %d %d %d %d *	colorkey %d %d %d %d %d %d *	capture %d %d %d %d *	capbrightness %d *	capcontrast %d *	capsaturation %d *	caphue %d *	capbw %d *	brightness %d *	contrast %d *	saturation %d *	source %d *	svideo %d *	format %d *	channel %d %d *	signal *	volume %d [ %d ] *	bass %d *	treble %d *	freeze %d */#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	"tv.h" #include	<draw.h> enum {	MemSize=			1,	MemAddr=			0xB8000, 	CompressReg=			-14, 	/* smart lock registers */	SLReg1=				-2,	SLReg2=				-1, 	/* the Bt812 registers */	Bt812Index=			-5,	Bt812Data=			-6, 	Bt2VideoPresent=		0x40,	Bt4ColorBars=			0x40,	Bt5YCFormat=			0x80,	Bt7TriState=			0x0C, 	/* VxP 500 registers */	Vxp500Index=			0,	Vxp500Data=			1, 	/* video controller registers */	MemoryWindowBaseAddrA=		0x14,	MemoryWindowBaseAddrB=		0x15,	MemoryPageReg=			0x16,	MemoryConfReg=			0x18,	ISAControl=			0x30,	I2CControl=			0x34,	InputVideoConfA=		0x38,	InputVideoConfB=		0x39,	ISASourceWindowWidthA=		0x3A,	ISASourceWindowWidthB=		0x3B,	ISASourceWindowHeightA=		0x3C,	ISASourceWindowHeightB=		0x3D,	InputHorzCropLeftA=		0x40,	InputHorzCropLeftB=		0x41,	InputHorzCropRightA=		0x44,	InputHorzCropRightB=		0x45,	InputHorzCropTopA=		0x48,	InputHorzCropTopB=		0x49,	InputHorzCropBottomA=		0x4C,	InputHorzCropBottomB=		0x4D,	InputHorzFilter=		0x50,	InputHorzScaleControlA=		0x54,	InputHorzScaleControlB=		0x55,	InputVertInterpolControl=	0x58,	InputVertScaleControlA=		0x5C,	InputVertScaleControlB=		0x5D,	InputFieldPixelBufStatus=	0x64,	VideoInputFrameBufDepthA=	0x68,	VideoInputFrameBufDepthB=	0x69,	AcquisitionControl=		0x6C,	AcquisitionAddrA=		0x70,	AcquisitionAddrB=		0x71,	AcquisitionAddrC=		0x72,	VideoBufferLayoutControl=	0x73,	CaptureControl=			0x80,	CaptureViewPortAddrA=		0x81,	CaptureViewPortAddrB=		0x82,	CaptureViewPortAddrC=		0x83,	CaptureViewPortWidthA=		0x84,	CaptureViewPortWidthB=		0x85,	CaptureViewPortHeightA=		0x86,	CaptureViewPortHeightB=		0x87,	CapturePixelBufLow=		0x88,	CapturePixelBufHigh=		0x89,	CaptureMultiBufDepthA=		0x8A,	CaptureMultiBufDepthB=		0x8B,	DisplayControl=			0x92,	VGAControl=			0x94,	OutputProcControlA=		0x96,	OutputProcControlB=		0x97,        DisplayViewPortStartAddrA=	0xA0,        DisplayViewPortStartAddrB=	0xA1,        DisplayViewPortStartAddrC=	0xA2,	DisplayViewPortWidthA=		0xA4,	DisplayViewPortWidthB=		0xA5,	DisplayViewPortHeightA=		0xA6,	DisplayViewPortHeightB=		0xA7,	DisplayViewPortOrigTopA=	0xA8,	DisplayViewPortOrigTopB=	0xA9,	DisplayViewPortOrigLeftA=	0xAA,	DisplayViewPortOrigLeftB=	0xAB,	DisplayWindowLeftA=		0xB0,	DisplayWindowLeftB=		0xB1,	DisplayWindowRightA=		0xB4,	DisplayWindowRightB=		0xB5,	DisplayWindowTopA=		0xB8,	DisplayWindowTopB=		0xB9,	DisplayWindowBottomA=		0xBC,	DisplayWindowBottomB=		0xBD,	OutputVertZoomControlA=		0xC0,	OutputVertZoomControlB=		0xC1,	OutputHorzZoomControlA=		0xC4,	OutputHorzZoomControlB=		0xC5,	BrightnessControl=		0xC8,	ContrastControl=		0xC9,	SaturationControl=		0xCA,	VideoOutIntrStatus=		0xD3, 	/* smart lock bits */	PixelClk=			0x03,	SmartLock=			0x00,	FeatureConnector=		0x01,	Divider=			0x02,	Window=				0x08,	KeyWindow=			0x0C,	HSyncLow=			0x20,	VSyncLow=			0x40, 	ClkBit=				0x01,	DataBit=			0x02,	HoldBit=			0x04,	SelBit=				0x08,	DivControl=			0x40, 	/* i2c bus control bits */	I2C_Clock=			0x02,	I2C_Data=			0x08,	I2C_RdClock=			0x10,	I2C_RdData=			0x20,	I2C_RdData_D=			0x40, 	/* I2C bus addresses */	Adr5249=			0x22,	/* teletext decoder */	Adr8444=			0x48,	/* 6-bit DAC (TDA 8444) */	Adr6300=			0x80,	/* sound fader (TEA 6300) */	Adr6320=			0x80,	/* sound fader (TEA 6320T) */	AdrTuner=			0xC0, 	/* Philips audio chips */	TEA6300=			0,	TEA6320T=			1, 	/* input formats */	NTSC_M = 0,	NTSC_443 = 1,	External = 2, 	NTSCCropLeft= 			36,	/* NTSC 3.6 usec */	NTSCCropRight=			558,	/* NTSC 55.8 usec */ 	/* color control indices */	Vxp500Brightness=		1,	Vxp500Contrast=			2,	Vxp500Saturation=		3,	Bt812Brightness=		4,	Bt812Contrast=			5,	Bt812Saturation=		6,	Bt812Hue=			7,	Bt812BW=			8, 	/* board revision numbers */	RevisionPP=			0,	RevisionA=			1,	HighQ=				2, 	/* VGA controller registers */	VGAMiscOut=			0x3CC,	VGAIndex=			0x3D4,	VGAData=			0x3D5,	VGAHorzTotal=			0x00,}; enum {	Qdir,	Qdata,	Qctl,}; staticDirtab tvtab[]={	".",		{Qdir, 0, QTDIR},	0,	0555,	"tv",		{Qdata, 0},	0,	0666,	"tvctl",	{Qctl, 0},	0,	0666,}; staticint ports[] = {	/* board addresses */	0x51C, 0x53C, 0x55C, 0x57C,	0x59C, 0x5BC, 0x5DC, 0x5FC}; /* * Default settings, settings between 0..100 */staticint defaults[] = {	Vxp500Brightness,	0,	Vxp500Contrast,		54,	Vxp500Saturation,	54,	Bt812Brightness,	13,	Bt812Contrast,		57,	Bt812Saturation,	51,	Bt812Hue,		0,	Bt812BW,		0,}; static int port;static int soundchip;static int boardrev;static int left, right;static int vsync, hsync;static ulong xtalfreq;static ushort cropleft, cropright;static ushort cropbottom, croptop;static Rectangle window, capwindow; static void setreg(int, int);static void setbt812reg(int, int);static void videoinit(void);static void createwindow(Rectangle);static void setcontrols(int, uchar);static void setcolorkey(int, int, int, int, int, int);static void soundinit(void);static void setvolume(int, int);static void setbass(int);static void settreble(int);static void setsoundsource(int);static void tunerinit(void);static void settuner(int, int);static void setvideosource(int);static int waitvideosignal(void);static void freeze(int);static void setsvideo(int);static void setinputformat(int);static void enablevideo(void);static void *saveframe(int *); static intmin(int a, int b){	return a < b ? a : b;} static intmax(int a, int b){	return a < b ? b : a;} static intpresent(int port){	outb(port+Vxp500Index, 0xAA);	if (inb(port+Vxp500Index) != 0xAA)		return 0;	outb(port+Vxp500Index, 0x55);	outb(port+Vxp500Data, 0xAA);	if (inb(port+Vxp500Index) != 0x55)		return 0;	if (inb(port+Vxp500Data) != 0xAA)		return 0;	outb(port+Vxp500Data, 0x55);	if (inb(port+Vxp500Index) != 0x55)		return 0;	if (inb(port+Vxp500Data) != 0x55)		return 0;	return 1;} static intgetvsync(void){	int vslow, vshigh, s;	ushort timo; 	s = splhi(); 	outb(port+Vxp500Index, VideoOutIntrStatus); 	/* wait for VSync to go high then low */	for (timo = ~0; timo; timo--)		if (inb(port+Vxp500Data) & 2) break;	for (timo = ~0; timo; timo--)		if ((inb(port+Vxp500Data) & 2) == 0) break; 	/* count how long it stays low and how long it stays high */	for (vslow = 0, timo = ~0; timo; timo--, vslow++)		if (inb(port+Vxp500Data) & 2) break;	for (vshigh = 0, timo = ~0; timo; timo--, vshigh++)		if ((inb(port+Vxp500Data) & 2) == 0) break;	splx(s); 	return vslow < vshigh;} static intgethsync(void){	int hslow, hshigh, s;	ushort timo; 	s = splhi(); 	outb(port+Vxp500Index, VideoOutIntrStatus); 	/* wait for HSync to go high then low */	for (timo = ~0; timo; timo--)		if (inb(port+Vxp500Data) & 1) break;	for (timo = ~0; timo; timo--)		if ((inb(port+Vxp500Data) & 1) == 0) break; 	/* count how long it stays low and how long it stays high */	for (hslow = 0, timo = ~0; timo; timo--, hslow++)		if (inb(port+Vxp500Data) & 1) break;	for (hshigh = 0, timo = ~0; timo; timo--, hshigh++)		if ((inb(port+Vxp500Data) & 1) == 0) break;	splx(s); 	return hslow < hshigh;} static voidtvinit(void){	int i; 	for (i = 0, port = 0; i < nelem(ports); i++) {		if (present(ports[i])) {			port = ports[i];			break;		}	}	if (i == nelem(ports))		return; 	/*	 * the following routines are the prefered way to	 * find out the sync polarities. Unfortunately, it	 * doesn't always work.	 */#ifndef VSync	vsync = getvsync();	hsync = gethsync();#else	vsync = VSync;	hsync = HSync;#endif	left = right = 80;	soundinit();	tunerinit();	videoinit();} static Chan*tvattach(char *spec){	if (port == 0)		error(Enonexist);	return devattach('V', spec);} static Walkqid*tvwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, tvtab, nelem(tvtab), devgen);} static inttvstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, tvtab, nelem(tvtab), devgen);} static Chan*tvopen(Chan *c, int omode){	return devopen(c, omode, tvtab, nelem(tvtab), devgen);} static voidtvclose(Chan *){} static longtvread(Chan *c, void *a, long n, vlong offset){	static void *frame;	static int size; 	USED(offset); 	switch((ulong)c->qid.path){	case Qdir:		return devdirread(c, a, n, tvtab, nelem(tvtab), devgen);	case Qdata:		if (eqrect(capwindow, Rect(0, 0, 0, 0)))			error(Ebadarg);		if (offset == 0)			frame = saveframe(&size);		if (frame) {			if (n > size - offset)				n = size - offset;			memmove(a, (char *)frame + offset, n);		} else			error(Enovmem);		break;	default:		n=0;		break;	}	return n;} static longtvwrite(Chan *c, void *vp, long n, vlong offset){	char buf[128], *field[10], *a;	int i, nf, source;	static Rectangle win;	static int hsize, size = 0;	static void *frame; 	USED(offset); 	a = vp;	switch((ulong)c->qid.path){	case Qctl:		if (n > sizeof(buf)-1)			n = sizeof(buf)-1;		memmove(buf, a, n);		buf[n] = '\0'; 		nf = getfields(buf, field, nelem(field), 1, " \t");		if (nf < 1) error(Ebadarg); 		if (strcmp(field[0], "init") == 0) {			window = Rect(0, 0, 0, 0);			capwindow = Rect(0, 0, 0, 0);			source = 0; /* video 0 input */			setvideosource(source);			left = right = 80;			setsoundsource(source);			for (i = 0; i < nelem(defaults); i += 2)				setcontrols(defaults[i], defaults[i+1]);		} else if (strcmp(field[0], "colorkey") == 0) {			if (nf < 7) error(Ebadarg);			setcolorkey(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0),				strtoul(field[3], 0, 0), strtoul(field[4], 0, 0),				strtoul(field[5], 0, 0), strtoul(field[6], 0, 0));		} else if (strcmp(field[0], "window") == 0) {			if (nf < 5) error(Ebadarg);			createwindow(Rect(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0),				strtoul(field[3], 0, 0), strtoul(field[4], 0, 0)));			setvolume(left, right);		} else if (strcmp(field[0], "capture") == 0) {			if (nf < 5) error(Ebadarg);			capwindow = Rect(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0),				strtoul(field[3], 0, 0), strtoul(field[4], 0, 0));		} else if (strcmp(field[0], "freeze") == 0) {			if (nf < 2) error(Ebadarg);			freeze(strtoul(field[1], 0, 0));		} else if (strcmp(field[0], "capbrightness") == 0) {			if (nf < 2) error(Ebadarg);			setcontrols(Bt812Brightness, strtoul(field[1], 0, 0));		} else if (strcmp(field[0], "capcontrast") == 0) {			if (nf < 2) error(Ebadarg);			setcontrols(Bt812Contrast, strtoul(field[1], 0, 0));		} else if (strcmp(field[0], "capsaturation") == 0) {

Lines 1–500 of 1826.