2203 lines · 44.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /*  * Driver for Bt848 TV tuner.  *  */#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include "io.h"#include "hcwAMC.h" #define max(a, b)	(((a) > (b))? (a): (b)) enum {	Qdir = 0,	Qsubdir,	Qsubbase,	Qvdata = Qsubbase,	Qadata,	Qctl,	Qregs, 	Brooktree_vid = 0x109e,	Brooktree_848_did = 0x0350,	Brooktree_878_did = 0x036E,	Intel_vid = 0x8086,	Intel_82437_did = 0x122d, 	K = 1024,	M = K * K, 	Ntvs = 4, 	Numring = 16, 	ntsc_rawpixels = 910,	ntsc_sqpixels = 780,		/* Including blanking & inactive */	ntsc_hactive = 640,	ntsc_vactive = 480,	ntsc_clkx1delay = 135,		/* Clock ticks. */	ntsc_clkx1hactive = 754,	ntsc_vdelay = 26,		/* # of scan lines. */	ntsc_vscale = 0, 	i2c_nostop = 1 << 5,	i2c_nos1b  = 1 << 4,	i2c_timing = 7 << 4,	i2c_bt848w3b = 1 << 2,	i2c_bt848scl = 1 << 1,	i2c_bt848sda = 1 << 0,	i2c_scl = i2c_bt848scl,	i2c_sda = i2c_bt848sda, 	i2c_miroproee = 0x80,		/* MIRO PRO EEPROM */	i2c_tea6300 = 0x80,	i2c_tda8425 = 0x82,	i2c_tda9840 = 0x84,	i2c_tda9850 = 0xb6,	i2c_haupee = 0xa0,		/* Hauppage EEPROM */	i2c_stbee = 0xae,		/* STB EEPROM */	i2c_msp3400 = 0x80, 	i2c_timeout = 1000,	i2c_delay = 10, 	Bt848_miropro = 0,	Bt848_miro,	Bt878_hauppauge, 	/* Bit fields. */	iform_muxsel1 = 3 << 5,		/* 004 */	iform_muxsel0 = 2 << 5,	iform_xtselmask = 3 << 3,	iform_xtauto = 3 << 3,	iform_formatmask = 7 << 0,	iform_ntsc = 1 << 0, 	control_ldec = 1 << 5,		/* 02C */	contrast_100percent = 0xd8,	/* 030 */ 	vscale_interlaced = 1 << 5,	/* 04C */ 	adelay_ntsc = 104,		/* 060 */	bdelay_ntsc = 93,		/* 064 */	adc_crush = 1 << 0,		/* 068 */ 	colorfmt_rgb16 = 2 << 4 | 2 << 0,	/* 0D4 */	colorfmt_YCbCr422 = 8 << 4 | 8 << 0,	colorfmt_YCbCr411 = 9 << 4 | 9 << 0,	colorctl_gamma     = 1 << 4,	/* 0D8 */	capctl_fullframe   = 1 << 4,	/* 0DC */	capctl_captureodd  = 1 << 1,	capctl_captureeven = 1 << 0,	vbipacksize = 0x190,		/* 0E0 */ 	intstat_riscstatshift = 28,	/* 100 */	intstat_i2crack = 1 << 25,	intstat_scerr = 1 << 19,	intstat_ocerr = 1 << 18,	intstat_pabort = 1 << 17,	intstat_riperr = 1 << 16,	intstat_pperr = 1 << 15,	intstat_fdsr = 1 << 14,	intstat_ftrgt = 1 << 13,	intstat_fbus = 1 << 12,	intstat_risci = 1 << 11,	intstat_i2cdone = 1 << 8,	intstat_vpress = 1 << 5,	intstat_hlock = 1 << 4,	intstat_vsync = 1 << 1,	intstat_fmtchg = 1 << 0,	intmask_etbf = 1 << 23,		/* 104 */ 	gpiodmactl_apwrdn = 1 << 26,	/* 10C */	gpiodmactl_daes2 = 1 << 13,	gpiodmactl_daiomda = 1 << 6,	gpiodmactl_pltp23_16 = 2 << 6,	gpiodmactl_pltp23_0 = 0 << 6,	gpiodmactl_pltp1_16 = 2 << 4,	gpiodmactl_pltp1_0 = 0 << 4,	gpiodmactl_acapenable = 1 << 4,	gpiodmactl_pktp_32 = 3 << 2,	gpiodmactl_pktp_0 = 0 << 2,	gpiodmactl_riscenable = 1 << 1,	gpiodmactl_fifoenable = 1 << 0, 	/* RISC instructions and parameters. */	fifo_vre = 0x4,	fifo_vro = 0xc,	fifo_fm1 = 0x6,	fifo_fm3 = 0xe, 	riscirq = 1 << 24,	riscwrite = 1 << 28,	riscwrite123 = 9 << 28,	riscwrite1s23 = 11 << 28,		riscwrite_sol = 1 << 27,		riscwrite_eol = 1 << 26,	riscskip = 0x2 << 28,	riscjmp = 0x7 << 28,	riscsync = 0x8 << 28,		riscsync_resync = 1 << 15,		riscsync_vre = fifo_vre << 0,		riscsync_vro = fifo_vro << 0,		riscsync_fm1 = fifo_fm1 << 0,		riscsync_fm3 = fifo_fm3 << 0,	risclabelshift_set = 16,	risclabelshift_reset = 20, 	AudioTuner = 0,	AudioRadio,	AudioExtern,	AudioIntern,	AudioOff,	AudioOn, 	asel_tv = 0,	asel_radio,	asel_mic,	asel_smxc, 	Hwbase_ad = 448000, 	msp_dem = 0x10,	msp_bbp = 0x12, 	/* Altera definitions. */	gpio_altera_data = 1 << 0,	gpio_altera_clock = 1 << 20,	gpio_altera_nconfig = 1 << 23, 	Ial = 0x140001,	Idma = 0x100002, 	Adsp = 0x7fd8,	Adsp_verifysystem = 1,	Adsp_querysupportplay,	Adsp_setstyle,	Adsp_setsrate,	Adsp_setchannels,	Adsp_setresolution,	Adsp_setcrcoptions,	Adsp_bufenqfor,	Adsp_logbuffer,	Adsp_startplay,	Adsp_stopplay,	Adsp_autostop,	Adsp_startrecord,	Adsp_stoprecord,	Adsp_getlastprocessed,	Adsp_pause,	Adsp_resume,	Adsp_setvolume,	Adsp_querysupportrecord,	Adsp_generalbufenq,	Adsp_setdownmixtype,	Adsp_setigain,	Adsp_setlineout,	Adsp_setlangmixtype, 	Kfir_gc = 0,	Kfir_dsp_riscmc,	Kfir_dsp_risccram,	Kfir_dsp_unitmc,	Kfir_bsm_mc,	Kfir_mux_mc, 	Kfir_devid_gc = 7,	Kfir_devid_dsp = 4,	Kfir_devid_bsm = 5,	Kfir_devid_mux = 8, 	Kfir_200 = 200,	Kfir_dev_inst = Kfir_200,	Kfir_201 = 201,	Kfir_exec = Kfir_201,	Kfir_202 = 202,	Kfir_adr_eready = 254, 	Kfir_d_eready_encoding = 0,	Kfir_d_eready_ready,	Kfir_d_eready_test,	Kfir_d_eready_stopdetect,	Kfir_d_eready_seqend, 	VT_KFIR_OFF = 0,	VT_KFIR_ON, 	VT_KFIR_LAYER_II = 1,	VT_KFIR_STEREO = 1, 	Gpioinit = 0,	Gpiooutput,	Gpioinput, 	Srate_5512 = 0,	Srate_11025 = 2,	Srate_16000 = 3,	Srate_22050 = 4,	Srate_32000 = 5,	Srate_44100 = 6,	Srate_48000 = 7, }; typedef struct Variant Variant;struct Variant {	ushort	vid;	ushort	did;	char	*name;}; typedef struct Bt848 Bt848;struct Bt848 {	ulong	devstat;	/* 000 */	ulong	iform;		/* 004 */	ulong	tdec;		/* 008 */	ulong	ecrop;		/* 00C */	ulong	evdelaylo;	/* 010 */	ulong	evactivelo;	/* 014 */	ulong	ehdelaylo;	/* 018 */	ulong	ehactivelo;	/* 01C */	ulong	ehscalehi;	/* 020 */	ulong	ehscalelo;	/* 024 */	ulong	bright;		/* 028 */	ulong	econtrol;	/* 02C */	ulong	contrastlo;	/* 030 */	ulong	satulo;		/* 034 */	ulong	satvlo;		/* 038 */	ulong	hue;		/* 03C */	ulong	escloop;	/* 040 */	ulong	pad0;		/* 044 */	ulong	oform;		/* 048 */	ulong	evscalehi;	/* 04C */	ulong	evscalelo;	/* 050 */	ulong	test;		/* 054 */	ulong	pad1[2];	/* 058-05C */	ulong	adelay;		/* 060 */	ulong	bdelay;		/* 064 */	ulong	adc;		/* 068 */	ulong	evtc;		/* 06C */	ulong	pad2[3];	/* 070-078 */	ulong	sreset;		/* 07C */	ulong	tglb;		/* 080 */	ulong	tgctrl;		/* 084 */	ulong	pad3;		/* 088 */	ulong	ocrop;		/* 08C */	ulong	ovdelaylo;	/* 090 */	ulong	ovactivelo;	/* 094 */	ulong	ohdelaylo;	/* 098 */	ulong	ohactivelo;	/* 09C */	ulong	ohscalehi;	/* 0A0 */	ulong	ohscalelo;	/* 0A4 */	ulong	pad4;		/* 0A8 */	ulong	ocontrol;	/* 0AC */	ulong	pad5[4];	/* 0B0-0BC */	ulong	oscloop;	/* 0C0 */	ulong	pad6[2];	/* 0C4-0C8 */	ulong	ovscalehi;	/* 0CC */	ulong	ovscalelo;	/* 0D0 */	ulong	colorfmt;	/* 0D4 */	ulong	colorctl;	/* 0D8 */	ulong	capctl;		/* 0DC */	ulong	vbipacksize;	/* 0E0 */	ulong	vbipackdel;	/* 0E4 */	ulong	fcap;		/* 0E8 */	ulong	ovtc;		/* 0EC */	ulong	pllflo;		/* 0F0 */	ulong	pllfhi;		/* 0F4 */	ulong	pllxci;		/* 0F8 */	ulong	dvsif;		/* 0FC */	ulong	intstat;	/* 100 */	ulong	intmask;	/* 104 */	ulong	pad7;		/* 108 */	ulong	gpiodmactl;	/* 10C */	ulong	i2c;		/* 110 */	ulong	riscstrtadd;	/* 114 */	ulong	gpioouten;	/* 118 */	ulong	gpioreginp;	/* 11C */	ulong	risccount;	/* 120 */	ulong	pad8[55];	/* 124-1FC */	ulong	gpiodata[64];	/* 200-2FC */}; #define packetlen	i2c typedef struct Tuner Tuner;struct Tuner {	char	*name;  	ushort	freq_vhfh;	/* Start frequency */	ushort	freq_uhf;	uchar	VHF_L;	uchar	VHF_H;	uchar	UHF;	uchar	cfg;	ushort	offs;}; typedef struct Frame Frame;struct Frame {	ulong	*fstart;	ulong	*fjmp;	uchar	*fbase;}; typedef struct Tv Tv;struct Tv {	Lock;	Rendez;	Bt848	*bt848;	Bt848	*bt878;		/* Really only audio control registers */	Variant	*variant;	Tuner	*tuner;	Pcidev	*pci;	uchar	i2ctuneraddr;	uchar	i2ccmd;		/* I2C command */	int	board;		/* What board is this? */	ulong	cfmt;		/* Current color format. */	int	channel;	/* Current channel */	Ref	fref;		/* Copying images? */	int	nframes;	/* Number of frames to capture. */	Frame	*frames;	/* DMA program */	int	lvframe;	/* Last video frame DMAed */	uchar	*amux;		/* Audio multiplexer. */	int	nablocks;	/* Number of audio blocks allocated */	int	absize;		/* Audio block size */	int	narblocks;	/* Number of audio blocks received */	ulong	*arisc;		/* Audio risc bloc */	uchar	*abuf;		/* Audio data buffers */	char	ainfo[128]; 	/* WinTV/PVR stuff. */	int	msp;	Lock	kfirlock;	ulong	i2cstate;	/* Last i2c state. */	int	gpiostate;	/* Current GPIO state */	ulong	alterareg;	/* Last used altera register */	ulong	alteraclock;	/* Used to clock the altera */	int	asrate;		/* Audio sample rate */	uchar	aleft, aright;	/* Left and right audio volume */	ulong	kfirclock;	Ref	aref;		/* Copying audio? */}; enum {	TemicPAL = 0,	PhilipsPAL,	PhilipsNTSC,	PhilipsSECAM,	Notuner,	PhilipsPALI,	TemicNTSC,	TemicPALI,	Temic4036,	AlpsTSBH1,	AlpsTSBE1, 	Freqmultiplier = 16,}; static Tuner tuners[] = {        {"Temic PAL", Freqmultiplier * 140.25, Freqmultiplier * 463.25,		0x02, 0x04, 0x01, 0x8e, 623 },	{"Philips PAL_I", Freqmultiplier * 140.25, Freqmultiplier * 463.25,		0xa0, 0x90, 0x30, 0x8e, 623 },	{"Philips NTSC",  Freqmultiplier * 157.25, Freqmultiplier * 451.25,		0xA0, 0x90, 0x30, 0x8e, 732 },	{"Philips SECAM", Freqmultiplier * 168.25, Freqmultiplier * 447.25,		0xA7, 0x97, 0x37, 0x8e, 623 },	{"NoTuner", 0, 0,		0x00, 0x00, 0x00, 0x00, 0 },	{"Philips PAL", Freqmultiplier * 168.25, Freqmultiplier * 447.25,		0xA0, 0x90, 0x30, 0x8e, 623 },	{"Temic NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,		0x02, 0x04, 0x01, 0x8e, 732 },	{"TEMIC PAL_I", Freqmultiplier * 170.00, Freqmultiplier * 450.00,		0x02, 0x04, 0x01, 0x8e, 623 },	{"Temic 4036 FY5 NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,		0xa0, 0x90, 0x30, 0x8e, 732 },	{"Alps TSBH1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,		0x01, 0x02, 0x08, 0x8e, 732 },	{"Alps TSBE1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,		0x01, 0x02, 0x08, 0x8e, 732 },}; static int hp_tuners[] = {	Notuner,	Notuner,	Notuner,	Notuner,	Notuner,	PhilipsNTSC,	Notuner,	Notuner,	PhilipsPAL,	PhilipsSECAM,	PhilipsNTSC,	PhilipsPALI,	Notuner,	Notuner,	TemicPAL,	TemicPALI,	Notuner,	PhilipsSECAM,	PhilipsNTSC,	PhilipsPALI,	Notuner,	PhilipsPAL,	Notuner,	PhilipsNTSC,}; enum {	CMvstart,	CMastart,	CMastop,	CMvgastart,	CMvstop,	CMchannel,	CMcolormode,	CMvolume,	CMmute,}; static Cmdtab tvctlmsg[] = {	CMvstart,	"vstart",	2,	CMastart,	"astart",	5,	CMastop,	"astop",	1,	CMvgastart,	"vgastart",	3,	CMvstop,	"vstop",	1,	CMchannel,	"channel",	3,	CMcolormode,	"colormode",	2,	CMvolume,	"volume",	3,	CMmute,		"mute",		1,}; static Variant variant[] = {	{ Brooktree_vid, Brooktree_848_did, "Brooktree 848 TV tuner", },	{ Brooktree_vid, Brooktree_878_did, "Brooktree 878 TV tuner", },}; static char *boards[] = {	"MIRO PRO",	"MIRO",	"Hauppauge Bt878",}; static ushort Adspfsample[] = {	0x500, 0x700, 0x400, 0x600, 0x300, 0x200, 0x000, 0x100

Lines 1–500 of 2203.