xref: /plan9-contrib/sys/src/9/pc/devtv.c (revision 5e4924093ecb86f7174bf23023955abc83fb6962)
1 /*
2   * Driver for Bt848 TV tuner.
3   *
4   */
5 #include	"u.h"
6 #include	"../port/lib.h"
7 #include	"mem.h"
8 #include	"dat.h"
9 #include	"fns.h"
10 #include	"../port/error.h"
11 #include "io.h"
12 #include "hcwAMC.h"
13 
14 #define max(a, b)	(((a) > (b))? (a): (b))
15 
16 enum {
17 	Qdir = 0,
18 	Qsubdir,
19 	Qsubbase,
20 	Qvdata = Qsubbase,
21 	Qadata,
22 	Qctl,
23 	Qregs,
24 
25 	Brooktree_vid = 0x109e,
26 	Brooktree_848_did = 0x0350,
27 	Brooktree_878_did = 0x036E,
28 	Intel_vid = 0x8086,
29 	Intel_82437_did = 0x122d,
30 
31 	K = 1024,
32 	M = K * K,
33 
34 	Ntvs = 4,
35 
36 	Numring = 16,
37 
38 	ntsc_rawpixels = 910,
39 	ntsc_sqpixels = 780,					// Including blanking & inactive
40 	ntsc_hactive = 640,
41 	ntsc_vactive = 480,
42 	ntsc_clkx1delay = 135,				// Clock ticks.
43 	ntsc_clkx1hactive = 754,
44 	ntsc_vdelay = 26,					// # of scan lines.
45 	ntsc_vscale = 0,
46 
47 	i2c_nostop = 1 << 5,
48 	i2c_nos1b = 1 << 4,
49 	i2c_timing = 7 << 4,
50 	i2c_bt848w3b = 1 << 2,
51 	i2c_bt848scl = 1 << 1,
52 	i2c_bt848sda = 1 << 0,
53 	i2c_scl = i2c_bt848scl,
54 	i2c_sda = i2c_bt848sda,
55 
56 	i2c_miroproee = 0x80,				// MIRO PRO EEPROM
57 	i2c_tea6300 = 0x80,
58 	i2c_tda8425 = 0x82,
59 	i2c_tda9840 = 0x84,
60 	i2c_tda9850 = 0xb6,
61 	i2c_haupee = 0xa0,					// Hauppage EEPROM
62 	i2c_stbee = 0xae,					// STB EEPROM
63 	i2c_msp3400 = 0x80,
64 
65 	i2c_timeout = 1000,
66 	i2c_delay = 10,
67 
68 	Bt848_miropro = 0,
69 	Bt848_miro,
70 	Bt878_hauppauge,
71 
72 	// Bit fields.
73 	iform_muxsel1 = 3 << 5,				// 004
74 	iform_muxsel0 = 2 << 5,
75 	iform_xtselmask = 3 << 3,
76 	iform_xtauto = 3 << 3,
77 	iform_formatmask = 7 << 0,
78 	iform_ntsc = 1 << 0,
79 
80 	control_ldec = 1 << 5,				// 02C
81 	contrast_100percent = 0xd8,			// 030
82 
83 	vscale_interlaced = 1 << 5,			// 04C
84 
85 	adelay_ntsc = 104,					// 060
86 	bdelay_ntsc = 93,					// 064
87 	adc_crush = 1 << 0,					// 068
88 
89 	colorfmt_rgb16 = (2 << 4) | (2 << 0),	// 0D4
90 	colorfmt_YCbCr422 = (8 << 4) | (8 << 0),
91 	colorfmt_YCbCr411 = (9 << 4) | (9 << 0),
92 	colorctl_gamma = 1 << 4,			// 0D8
93 	capctl_fullframe = 1 << 4,				// 0DC
94 	capctl_captureodd = 1 << 1,
95 	capctl_captureeven = 1 << 0,
96 	vbipacksize = 0x190,				// 0E0
97 
98 	intstat_riscstatshift = 28,				// 100
99 	intstat_i2crack = 1 << 25,
100 	intstat_scerr = 1 << 19,
101 	intstat_ocerr = 1 << 18,
102 	intstat_pabort = 1 << 17,
103 	intstat_riperr = 1 << 16,
104 	intstat_pperr = 1 << 15,
105 	intstat_fdsr = 1 << 14,
106 	intstat_ftrgt = 1 << 13,
107 	intstat_fbus = 1 << 12,
108 	intstat_risci = 1 << 11,
109 	intstat_i2cdone = 1 << 8,
110 	intstat_vpress = 1 << 5,
111 	intstat_hlock = 1 << 4,
112 	intstat_vsync = 1 << 1,
113 	intstat_fmtchg = 1 << 0,
114 	intmask_etbf = 1 << 23,				// 104
115 
116 	gpiodmactl_apwrdn = 1 << 26,			// 10C
117 	gpiodmactl_daes2 = 1 << 13,
118 	gpiodmactl_daiomda = 1 << 6,
119 	gpiodmactl_pltp23_16 = 2 << 6,
120 	gpiodmactl_pltp23_0 = 0 << 6,
121 	gpiodmactl_pltp1_16 = 2 << 4,
122 	gpiodmactl_pltp1_0 = 0 << 4,
123 	gpiodmactl_acapenable = 1 << 4,
124 	gpiodmactl_pktp_32 = 3 << 2,
125 	gpiodmactl_pktp_0 = 0 << 2,
126 	gpiodmactl_riscenable = 1 << 1,
127 	gpiodmactl_fifoenable = 1 << 0,
128 
129 	// RISC instructions and parameters.
130 	fifo_vre = 0x4,
131 	fifo_vro = 0xc,
132 	fifo_fm1 = 0x6,
133 	fifo_fm3 = 0xe,
134 
135 	riscirq = 1 << 24,
136 	riscwrite = 1 << 28,
137 	riscwrite123 = 9 << 28,
138 	riscwrite1s23 = 11 << 28,
139 		riscwrite_sol = 1 << 27,
140 		riscwrite_eol = 1 << 26,
141 	riscskip = 0x2 << 28,
142 	riscjmp = 0x7 << 28,
143 	riscsync = 0x8 << 28,
144 		riscsync_resync = 1 << 15,
145 		riscsync_vre = fifo_vre << 0,
146 		riscsync_vro = fifo_vro << 0,
147 		riscsync_fm1 = fifo_fm1 << 0,
148 		riscsync_fm3 = fifo_fm3 << 0,
149 	risclabelshift_set = 16,
150 	risclabelshift_reset = 20,
151 
152 	AudioTuner = 0,
153 	AudioRadio,
154 	AudioExtern,
155 	AudioIntern,
156 	AudioOff,
157 	AudioOn,
158 
159 	asel_tv = 0,
160 	asel_radio,
161 	asel_mic,
162 	asel_smxc,
163 
164 	Hwbase_ad = 448000,
165 
166 	msp_dem = 0x10,
167 	msp_bbp = 0x12,
168 
169 	// Altera definitions.
170 	gpio_altera_data = 1 << 0,
171 	gpio_altera_clock = 1 << 20,
172 	gpio_altera_nconfig = 1 << 23,
173 
174 	Ial = 0x140001,
175 	Idma = 0x100002,
176 
177 	Adsp = 0x7fd8,
178 	Adsp_verifysystem = 1,
179 	Adsp_querysupportplay,
180 	Adsp_setstyle,
181 	Adsp_setsrate,
182 	Adsp_setchannels,
183 	Adsp_setresolution,
184 	Adsp_setcrcoptions,
185 	Adsp_bufenqfor,
186 	Adsp_logbuffer,
187 	Adsp_startplay,
188 	Adsp_stopplay,
189 	Adsp_autostop,
190 	Adsp_startrecord,
191 	Adsp_stoprecord,
192 	Adsp_getlastprocessed,
193 	Adsp_pause,
194 	Adsp_resume,
195 	Adsp_setvolume,
196 	Adsp_querysupportrecord,
197 	Adsp_generalbufenq,
198 	Adsp_setdownmixtype,
199 	Adsp_setigain,
200 	Adsp_setlineout,
201 	Adsp_setlangmixtype,
202 
203 	Kfir_gc = 0,
204 	Kfir_dsp_riscmc,
205 	Kfir_dsp_risccram,
206 	Kfir_dsp_unitmc,
207 	Kfir_bsm_mc,
208 	Kfir_mux_mc,
209 
210 	Kfir_devid_gc = 7,
211 	Kfir_devid_dsp = 4,
212 	Kfir_devid_bsm = 5,
213 	Kfir_devid_mux = 8,
214 
215 	Kfir_200 = 200,
216 	Kfir_dev_inst = Kfir_200,
217 	Kfir_201 = 201,
218 	Kfir_exec = Kfir_201,
219 	Kfir_202 = 202,
220 	Kfir_adr_eready = 254,
221 
222 	Kfir_d_eready_encoding = 0,
223 	Kfir_d_eready_ready,
224 	Kfir_d_eready_test,
225 	Kfir_d_eready_stopdetect,
226 	Kfir_d_eready_seqend,
227 
228 	VT_KFIR_OFF = 0,
229 	VT_KFIR_ON,
230 
231 	VT_KFIR_LAYER_II = 1,
232 	VT_KFIR_STEREO = 1,
233 
234 	Gpioinit = 0,
235 	Gpiooutput,
236 	Gpioinput,
237 
238 	Srate_5512 = 0,
239 	Srate_11025 = 2,
240 	Srate_16000 = 3,
241 	Srate_22050 = 4,
242 	Srate_32000 = 5,
243 	Srate_44100 = 6,
244 	Srate_48000 = 7,
245 
246 };
247 
248 typedef struct Variant Variant;
249 struct Variant {
250 	ushort		vid;
251 	ushort		did;
252 	char			*name;
253 };
254 
255 typedef struct Bt848 Bt848;
256 struct Bt848 {
257 	ulong	devstat;		// 000
258 	ulong	iform;		// 004
259 	ulong	tdec;			// 008
260 	ulong	ecrop;		// 00C
261 	ulong	evdelaylo;		// 010
262 	ulong	evactivelo;	// 014
263 	ulong	ehdelaylo;		// 018
264 	ulong	ehactivelo;	// 01C
265 	ulong	ehscalehi;		// 020
266 	ulong	ehscalelo;		// 024
267 	ulong	bright;		// 028
268 	ulong	econtrol;		// 02C
269 	ulong	contrastlo;	// 030
270 	ulong	satulo;		// 034
271 	ulong	satvlo;		// 038
272 	ulong	hue;			// 03C
273 	ulong	escloop;		// 040
274 	ulong	pad0;		// 044
275 	ulong	oform;		// 048
276 	ulong	evscalehi;		// 04C
277 	ulong	evscalelo;		// 050
278 	ulong	test;			// 054
279 	ulong	pad1[2];		// 058-05C
280 	ulong	adelay;		// 060
281 	ulong	bdelay;		// 064
282 	ulong	adc;			// 068
283 	ulong	evtc;			// 06C
284 	ulong	pad2[3];		// 070-078
285 	ulong	sreset;		// 07C
286 	ulong	tglb;			// 080
287 	ulong	tgctrl;		// 084
288 	ulong	pad3;		// 088
289 	ulong	ocrop;		// 08C
290 	ulong	ovdelaylo;		// 090
291 	ulong	ovactivelo;	// 094
292 	ulong	ohdelaylo;	// 098
293 	ulong	ohactivelo;	// 09C
294 	ulong	ohscalehi;		// 0A0
295 	ulong	ohscalelo;		// 0A4
296 	ulong	pad4;		// 0A8
297 	ulong	ocontrol;		// 0AC
298 	ulong	pad5[4];		// 0B0-0BC
299 	ulong	oscloop;		// 0C0
300 	ulong	pad6[2];		// 0C4-0C8
301 	ulong	ovscalehi;		// 0CC
302 	ulong	ovscalelo;		// 0D0
303 	ulong	colorfmt;		// 0D4
304 	ulong	colorctl;		// 0D8
305 	ulong	capctl;		// 0DC
306 	ulong	vbipacksize;	// 0E0
307 	ulong	vbipackdel;	// 0E4
308 	ulong	fcap;			// 0E8
309 	ulong	ovtc;			// 0EC
310 	ulong	pllflo;		// 0F0
311 	ulong	pllfhi;		// 0F4
312 	ulong	pllxci;		// 0F8
313 	ulong	dvsif;		// 0FC
314 	ulong	intstat;		// 100
315 	ulong	intmask;		// 104
316 	ulong	pad7;		// 108
317 	ulong	gpiodmactl;	// 10C
318 	ulong	i2c;			// 110
319 	ulong	riscstrtadd;	// 114
320 	ulong	gpioouten;	// 118
321 	ulong	gpioreginp;	// 11C
322 	ulong	risccount;		// 120
323 	ulong	pad8[55];		// 124-1FC
324 	ulong	gpiodata[64];	// 200-2FC
325 };
326 
327 #define packetlen	i2c
328 
329 typedef struct Tuner Tuner;
330 struct Tuner {
331 	char		*name;
332   	ushort	freq_vhfh;	// Start frequency
333 	ushort	freq_uhf;
334 	uchar	VHF_L;
335 	uchar	VHF_H;
336 	uchar	UHF;
337 	uchar	cfg;
338 	ushort	offs;
339 };
340 
341 typedef struct Frame Frame;
342 struct Frame {
343 	ulong	*fstart;
344 	ulong	*fjmp;
345 	uchar	*fbase;
346 };
347 
348 typedef struct Tv Tv;
349 struct Tv {
350 	Lock;
351 	Rendez;
352 	Bt848	*bt848;
353 	Bt848	*bt878;			// Really only audio control registers
354 	Variant	*variant;
355 	Tuner	*tuner;
356 	Pcidev	*pci;
357 	uchar	i2ctuneraddr;
358 	uchar	i2ccmd;			// I2C command
359 	int		board;			// What board is this?
360 	ulong	cfmt;			// Current color format.
361 	int		channel;			// Current channel
362 	Ref		fref;				// Copying images?
363 	int		nframes;			// Number of frames to capture.
364 	Frame	*frames;			// DMA program
365 	int		lvframe;			// Last video frame DMAed
366 	uchar	*amux;			// Audio multiplexer.
367 	int		nablocks;			// Number of audio blocks allocated
368 	int		absize;			// Audio block size
369 	int		narblocks;		// Number of audio blocks received
370 	ulong	*arisc;			// Audio risc bloc
371 	uchar	*abuf;			// Audio data buffers
372 	char		ainfo[128];
373 
374 	// WinTV/PVR stuff.
375 	int		msp;
376 	Lock		kfirlock;
377 	ulong	i2cstate;			// Last i2c state.
378 	int		gpiostate;			// Current GPIO state
379 	ulong	alterareg;			// Last used altera register
380 	ulong	alteraclock;		// Used to clock the altera
381 	int		asrate;			// Audio sample rate
382 	uchar	aleft, aright;		// Left and right audio volume
383 	ulong	kfirclock;
384 	Ref		aref;				// Copying audio?
385 };
386 
387 enum {
388 	TemicPAL = 0,
389 	PhilipsPAL,
390 	PhilipsNTSC,
391 	PhilipsSECAM,
392 	Notuner,
393 	PhilipsPALI,
394 	TemicNTSC,
395 	TemicPALI,
396 	Temic4036,
397 	AlpsTSBH1,
398 	AlpsTSBE1,
399 
400 	Freqmultiplier = 16,
401 };
402 
403 static Tuner tuners[] = {
404         {"Temic PAL", Freqmultiplier * 140.25, Freqmultiplier * 463.25,
405 		0x02, 0x04, 0x01, 0x8e, 623 },
406 	{"Philips PAL_I", Freqmultiplier * 140.25, Freqmultiplier * 463.25,
407 		0xa0, 0x90, 0x30, 0x8e, 623 },
408 	{"Philips NTSC",  Freqmultiplier * 157.25, Freqmultiplier * 451.25,
409 		0xA0, 0x90, 0x30, 0x8e, 732 },
410 	{"Philips SECAM", Freqmultiplier * 168.25, Freqmultiplier * 447.25,
411 		0xA7, 0x97, 0x37, 0x8e, 623 },
412 	{"NoTuner", 0, 0,
413 		0x00, 0x00, 0x00, 0x00, 0 },
414 	{"Philips PAL", Freqmultiplier * 168.25, Freqmultiplier * 447.25,
415 		0xA0, 0x90, 0x30, 0x8e, 623 },
416 	{"Temic NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,
417 		0x02, 0x04, 0x01, 0x8e, 732 },
418 	{"TEMIC PAL_I", Freqmultiplier * 170.00, Freqmultiplier * 450.00,
419 		0x02, 0x04, 0x01, 0x8e, 623 },
420 	{"Temic 4036 FY5 NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,
421 		0xa0, 0x90, 0x30, 0x8e, 732 },
422 	{"Alps TSBH1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,
423 		0x01, 0x02, 0x08, 0x8e, 732 },
424 	{"Alps TSBE1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,
425 		0x01, 0x02, 0x08, 0x8e, 732 },
426 };
427 
428 static int hp_tuners[] = {
429 	Notuner,
430         	Notuner,
431         	Notuner,
432         	Notuner,
433         	Notuner,
434         	PhilipsNTSC,
435         	Notuner,
436         	Notuner,
437         	PhilipsPAL,
438         	PhilipsSECAM,
439         	PhilipsNTSC,
440         	PhilipsPALI,
441         	Notuner,
442         	Notuner,
443         	TemicPAL,
444         	TemicPALI,
445         	Notuner,
446         	PhilipsSECAM,
447         	PhilipsNTSC,
448         	PhilipsPALI,
449         	Notuner,
450         	PhilipsPAL,
451         	Notuner,
452         	PhilipsNTSC,
453 };
454 
455 enum {
456 	CMvstart,
457 	CMastart,
458 	CMastop,
459 	CMvgastart,
460 	CMvstop,
461 	CMchannel,
462 	CMcolormode,
463 	CMvolume,
464 	CMmute,
465 };
466 
467 static Cmdtab tvctlmsg[] = {
468 	CMvstart,			"vstart",			2,
469 	CMastart,			"astart",			5,
470 	CMastop,			"astop",			1,
471 	CMvgastart,		"vgastart",		3,
472 	CMvstop,			"vstop",			1,
473 	CMchannel,		"channel",			3,
474 	CMcolormode,		"colormode",		2,
475 	CMvolume,		"volume",			3,
476 	CMmute,			"mute",			1,
477 };
478 
479 static Variant variant[] = {
480 {	Brooktree_vid,	Brooktree_848_did,	"Brooktree 848 TV tuner",	},
481 {	Brooktree_vid,	Brooktree_878_did,	"Brooktree 878 TV tuner",	},
482 };
483 
484 static char *boards[] = {
485 	"MIRO PRO",
486 	"MIRO",
487 	"Hauppauge Bt878",
488 };
489 
490 static ushort Adspfsample[] = {
491 	0x500, 0x700, 0x400, 0x600, 0x300, 0x200, 0x000, 0x100
492 };
493 static ushort Adspstereorates[] = {
494 	64, 96, 112, 128, 160, 192, 224, 256, 320, 384
495 };
496 
497 static uchar miroamux[] = { 2, 0, 0, 0, 10, 0 };
498 static uchar hauppaugeamux[] = { 0, 1, 2, 3, 4, 0 };
499 static char *nicamstate[] = {
500 	"analog", "???", "digital", "bad digital receiption"
501 };
502 
503 
504 static Tv tvs[Ntvs];
505 static int ntvs;
506 
507 static int i2cread(Tv *, uchar, uchar *);
508 static int i2cwrite(Tv *, uchar, uchar, uchar, int);
509 static void tvinterrupt(Ureg *, Tv *);
510 static void vgastart(Tv *, ulong, int);
511 static void vstart(Tv *, int, int, int, int);
512 static void astart(Tv *, char *, uint, uint, uint);
513 static void vstop(Tv *);
514 static void astop(Tv *);
515 static void colormode(Tv *, char *);
516 static void frequency(Tv *, int, int);
517 static int getbitspp(Tv *);
518 static char *getcolormode(ulong);
519 static int mspreset(Tv *);
520 static void i2cscan(Tv *);
521 static int kfirinitialize(Tv *);
522 static void msptune(Tv *);
523 static void mspvolume(Tv *, int, int, int);
524 static void gpioenable(Tv *, ulong, ulong);
525 static void gpiowrite(Tv *, ulong, ulong);
526 
527 static void
528 tvinit(void)
529 {
530 	Pcidev *pci;
531 	ulong intmask;
532 
533 	// Test for a triton memory controller.
534 	intmask = 0;
535 	if (pcimatch(nil, Intel_vid, Intel_82437_did))
536 		intmask = intmask_etbf;
537 
538 	pci = nil;
539 	while ((pci = pcimatch(pci, 0, 0)) != nil) {
540 		int i, t;
541 		Tv *tv;
542 		Bt848 *bt848;
543 		ushort hscale, hdelay;
544 		uchar v;
545 
546 		for (i = 0; i != nelem(variant); i++)
547 			if (pci->vid == variant[i].vid && pci->did == variant[i].did)
548 				break;
549 		if (i == nelem(variant))
550 			continue;
551 
552 		if (ntvs >= Ntvs) {
553 			print("#V: Too many TV cards found\n");
554 			continue;
555 		}
556 
557 		tv = &tvs[ntvs++];
558 		tv->variant = &variant[i];
559 		tv->pci = pci;
560 		tv->bt848 = (Bt848 *)vmap(pci->mem[0].bar & ~0x0F, 4 * K);
561 		if (tv->bt848 == nil)
562 			panic("#V: Cannot allocate memory for Bt848");
563 		bt848 = tv->bt848;
564 
565 		// i2c stuff.
566 		if (pci->did >= 878)
567 			tv->i2ccmd = 0x83;
568 		else
569 			tv->i2ccmd = i2c_timing | i2c_bt848scl | i2c_bt848sda;
570 
571 		t = 0;
572 		if (i2cread(tv, i2c_haupee, &v)) {
573 			uchar ee[256];
574 			Pcidev *pci878;
575 			Bt848 *bt878;
576 
577 			tv->board = Bt878_hauppauge;
578 			if (!i2cwrite(tv, i2c_haupee, 0, 0, 0))
579 				panic("#V: Cannot write to Hauppauge EEPROM");
580 			for (i = 0; i != sizeof ee; i++)
581 				if (!i2cread(tv, i2c_haupee + 1, &ee[i]))
582 					panic("#V: Cannot read from Hauppauge EEPROM");
583 
584 			if (ee[9] > sizeof hp_tuners / sizeof hp_tuners[0])
585 				panic("#V: Tuner out of range (max %d, this %d)",
586 					sizeof hp_tuners / sizeof hp_tuners[0], ee[9]);
587 			t = hp_tuners[ee[9]];
588 
589 			// Initialize the audio channel.
590 			if ((pci878 = pcimatch(nil, Brooktree_vid, 0x878)) == nil)
591 				panic("#V: Unsupported Hauppage board");
592 
593 			tv->bt878 = bt878 =
594 				(Bt848 *)vmap(pci878->mem[0].bar & ~0x0F, 4 * K);
595 			if (bt878 == nil)
596 				panic("#V: Cannot allocate memory for the Bt878");
597 
598 			kfirinitialize(tv);
599 			// i2cscan(tv);
600 			mspreset(tv);
601 
602 			bt878->gpiodmactl = 0;
603 			bt878->intstat = (ulong)-1;
604 			intrenable(pci878->intl, (void (*)(Ureg *, void *))tvinterrupt,
605 					tv, pci878->tbdf, "tv");
606 
607 			tv->amux = hauppaugeamux;
608 		}
609 		else if (i2cread(tv, i2c_stbee, &v)) {
610 			USED(t);
611 			panic("#V: Cannot deal with STB cards\n");
612 		}
613 		else if (i2cread(tv, i2c_miroproee, &v)) {
614 			tv->board = Bt848_miropro;
615 			t = ((bt848->gpiodata[0] >> 10) - 1) & 7;
616 			tv->amux = miroamux;
617 		}
618 		else {
619 			tv->board = Bt848_miro;
620 			tv->amux = miroamux;
621 			t = ((bt848->gpiodata[0] >> 10) - 1) & 7;
622 		}
623 
624 		if (t >= nelem(tuners))
625 			t = 4;
626 		tv->tuner = &tuners[t];
627 		tv->i2ctuneraddr =
628 			i2cread(tv, 0xc1, &v)? 0xc0:
629 			i2cread(tv, 0xc3, &v)? 0xc2:
630 			i2cread(tv, 0xc5, &v)? 0xc4:
631 			i2cread(tv, 0xc7, &v)? 0xc6: -1;
632 
633 		bt848->capctl = capctl_fullframe;
634 		bt848->adelay = adelay_ntsc;
635 		bt848->bdelay = bdelay_ntsc;
636 		bt848->iform = iform_muxsel0|iform_xtauto|iform_ntsc;
637 		bt848->vbipacksize = vbipacksize & 0xff;
638 		bt848->vbipackdel = (vbipacksize >> 8) & 1;
639 
640 		// setpll(bt848);
641 
642 		tv->cfmt = bt848->colorfmt = colorfmt_rgb16;
643 
644 		hscale = (ntsc_rawpixels * 4096) / ntsc_sqpixels - 4096;
645 		hdelay = (ntsc_clkx1delay * ntsc_hactive) / ntsc_clkx1hactive;
646 
647 		bt848->ovtc = bt848->evtc = 0;
648 		bt848->ehscalehi = bt848->ohscalehi = (hscale >> 8) & 0xff;
649 		bt848->ehscalelo = bt848->ohscalelo = hscale & 0xff;
650 		bt848->evscalehi &= ~0x1f;
651 		bt848->ovscalehi &= ~0x1f;
652 		bt848->evscalehi |= vscale_interlaced | ((ntsc_vscale >> 8) & 0x1f);
653 		bt848->ovscalehi |= vscale_interlaced | (ntsc_vscale >> 8) & 0x1f;
654 		bt848->evscalelo = bt848->ovscalelo = ntsc_vscale & 0xff;
655 		bt848->ehactivelo = bt848->ohactivelo = ntsc_hactive & 0xff;
656 		bt848->ehdelaylo = bt848->ohdelaylo = hdelay & 0xff;
657 		bt848->evactivelo = bt848->ovactivelo = ntsc_vactive & 0xff;
658 		bt848->evdelaylo = bt848->ovdelaylo = ntsc_vdelay & 0xff;
659 		bt848->ecrop = bt848->ocrop =
660 			((ntsc_hactive >> 8) & 0x03) |
661 			((hdelay >> 6) & 0x0C) |
662 	        		((ntsc_vactive >> 4) & 0x30) |
663 			((ntsc_vdelay >> 2) & 0xC0);
664 
665 		bt848->colorctl = colorctl_gamma;
666 		bt848->capctl = 0;
667 		bt848->gpiodmactl = gpiodmactl_pltp23_16 |
668 			gpiodmactl_pltp1_16 | gpiodmactl_pktp_32;
669 		bt848->gpioreginp = 0;
670 		bt848->contrastlo = contrast_100percent;
671 		bt848->bright = 16;
672 		bt848->adc = (2 << 6) | adc_crush;
673 		bt848->econtrol = bt848->ocontrol = control_ldec;
674 		bt848->escloop = bt848->oscloop = 0;
675 		bt848->intstat = (ulong)-1;
676 		bt848->intmask = intmask |
677 			intstat_vsync | intstat_scerr | intstat_risci | intstat_ocerr |
678 			intstat_vpress | intstat_fmtchg;
679 
680 
681 		if (tv->amux) {
682 			gpioenable(tv, ~0xfff, 0xfff);
683 			gpiowrite(tv, ~0xfff, tv->amux[AudioRadio]);
684 		}
685 
686 		print("#V%ld: %s (rev %d) (%s/%s) intl %d\n",
687 				tv - tvs, tv->variant->name, pci->rid, boards[tv->board],
688 				tv->tuner->name, pci->intl);
689 
690 		intrenable(pci->intl, (void (*)(Ureg *, void *))tvinterrupt,
691 				tv, pci->tbdf, "tv");
692 	}
693 }
694 
695 static Chan*
696 tvattach(char *spec)
697 {
698 	return devattach('V', spec);
699 }
700 
701 #define TYPE(q)		((int)((q).path & 0xff))
702 #define DEV(q)			((int)(((q).path >> 8) & 0xff))
703 #define QID(d, t)		((((d) & 0xff) << 8) | (t))
704 
705 static int
706 tv1gen(Chan *c, int i, Dir *dp)
707 {
708 	Qid qid;
709 
710 	switch (i) {
711 	case Qvdata:
712 		mkqid(&qid, QID(DEV(c->qid), Qvdata), 0, QTFILE);
713 		devdir(c, qid, "video", 0, eve, 0444, dp);
714 		return 1;
715 	case Qadata:
716 		mkqid(&qid, QID(DEV(c->qid), Qadata), 0, QTFILE);
717 		devdir(c, qid, "audio", 0, eve, 0444, dp);
718 		return 1;
719 	case Qctl:
720 		mkqid(&qid, QID(DEV(c->qid), Qctl), 0, QTFILE);
721 		devdir(c, qid, "ctl", 0, eve, 0444, dp);
722 		return 1;
723 	case Qregs:
724 		mkqid(&qid, QID(DEV(c->qid), Qregs), 0, QTFILE);
725 		devdir(c, qid, "regs", 0, eve, 0444, dp);
726 		return 1;
727 	}
728 	return -1;
729 }
730 
731 static int
732 tvgen(Chan *c, char *, Dirtab *, int, int i, Dir *dp)
733 {
734 	Qid qid;
735 	int dev;
736 
737 	dev = DEV(c->qid);
738 	switch (TYPE(c->qid)) {
739 	case Qdir:
740 		if (i == DEVDOTDOT) {
741 			mkqid(&qid, Qdir, 0, QTDIR);
742 			devdir(c, qid, "#V", 0, eve, 0555, dp);
743 			return 1;
744 		}
745 
746 		if (i >= ntvs)
747 			return -1;
748 
749 		mkqid(&qid, QID(i, Qsubdir), 0, QTDIR);
750 		snprint(up->genbuf, sizeof(up->genbuf), "tv%d", i);
751 		devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
752 		return 1;
753 
754 	case Qsubdir:
755 		if (i == DEVDOTDOT) {
756 			mkqid(&qid, QID(dev, Qdir), 0, QTDIR);
757 			snprint(up->genbuf, sizeof(up->genbuf), "tv%d", dev);
758 			devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
759 			return 1;
760 		}
761 
762 		return tv1gen(c, i + Qsubbase, dp);
763 
764 	case Qvdata:
765 	case Qadata:
766 	case Qctl:
767 	case Qregs:
768 		return tv1gen(c, TYPE(c->qid), dp);
769 
770 	default:
771 		return -1;
772 	}
773 }
774 
775 static Walkqid *
776 tvwalk(Chan *c, Chan *nc, char **name, int nname)
777 {
778 	return devwalk(c, nc, name, nname, 0, 0, tvgen);
779 }
780 
781 static int
782 tvstat(Chan *c, uchar *db, int n)
783 {
784 	return devstat(c, db, n, 0, 0, tvgen);
785 }
786 
787 static Chan*
788 tvopen(Chan *c, int omode)
789 {
790 	if (omode != OREAD &&
791 		TYPE(c->qid) != Qctl && TYPE(c->qid) != Qvdata)
792 		error(Eperm);
793 
794 	switch (TYPE(c->qid)) {
795 	case Qdir:
796 		return devopen(c, omode, nil, 0, tvgen);
797 	case Qadata:
798 		if (tvs[DEV(c->qid)].bt878 == nil)
799 			error(Enonexist);
800 		break;
801 	}
802 
803 	c->mode = openmode(omode);
804 	c->flag |= COPEN;
805 	c->offset = 0;
806 
807 	if (TYPE(c->qid) == Qadata)
808 		c->aux = nil;
809 	return c;
810 }
811 
812 static void
813 tvclose(Chan *)
814 {}
815 
816 static int
817 audioblock(void *)
818 {
819 	return 1;
820 }
821 
822 static long
823 tvread(Chan *c, void *a, long n, vlong offset)
824 {
825 	static char regs[10 * K];
826 	static int regslen;
827 	Tv *tv;
828 	char *e, *p;
829 	uchar *src;
830 
831 	USED(offset);
832 
833 	switch(TYPE(c->qid)) {
834 	case Qdir:
835 	case Qsubdir:
836 		return devdirread(c, a, n, 0, 0, tvgen);
837 
838 	case Qvdata: {
839 		int bpf, nb;
840 
841 		tv = &tvs[DEV(c->qid)];
842 		bpf = ntsc_hactive * ntsc_vactive * getbitspp(tv) / 8;
843 
844 		if (offset >= bpf)
845 			return 0;
846 
847 		nb = n;
848 		if (offset + nb > bpf)
849 			nb = bpf - offset;
850 
851 		ilock(tv);
852 		if (tv->frames == nil || tv->lvframe >= tv->nframes ||
853 			tv->frames[tv->lvframe].fbase == nil) {
854 			iunlock(tv);
855 			return 0;
856 		}
857 
858 		src = tv->frames[tv->lvframe].fbase;
859 		incref(&tv->fref);
860 		iunlock(tv);
861 
862 		memmove(a, src + offset, nb);
863 		decref(&tv->fref);
864 		return nb;
865 	}
866 
867 	case Qadata: {
868 		ulong uablock = (ulong)c->aux, bnum, tvablock;
869 		int boffs, nbytes;
870 
871 		tv = &tvs[DEV(c->qid)];
872 		if (tv->bt878 == nil)
873 			error("#V: No audio device");
874 		if (tv->absize == 0)
875 			error("#V: audio not initialized");
876 
877 		bnum = offset / tv->absize;
878 		boffs = offset % tv->absize;
879 		nbytes = tv->absize - boffs;
880 
881 		incref(&tv->aref);
882 		while (1) {
883 			tvablock = tv->narblocks;	// Current tv block.
884 
885 			if (uablock == 0)
886 				uablock = tvablock - 1;
887 
888 			if (tvablock >= uablock + bnum + tv->narblocks)
889 				uablock = tvablock - 1 - bnum;
890 
891 			if (uablock + bnum == tvablock) {
892 				sleep(tv, audioblock, nil);
893 				continue;
894 			}
895 			break;
896 		}
897 
898 		print("uablock %ld, bnum %ld, boffs %d, nbytes %d, tvablock %ld\n",
899 				uablock, bnum, boffs, nbytes, tvablock);
900 		src = tv->abuf + ((uablock + bnum) % tv->nablocks) * tv->absize;
901 		print("copying from %.8ulX (abuf %.8ulX), nbytes %d (block %ld.%ld)\n",
902 				src + boffs, tv->abuf, nbytes, uablock, bnum);
903 
904 		memmove(a, src + boffs, nbytes);
905 		decref(&tv->aref);
906 
907 		uablock += (boffs + nbytes) % tv->absize;
908 		c->aux = (void*)uablock;
909 
910 		return nbytes;
911 	}
912 
913 	case Qctl: {
914 		char str[128];
915 
916 		tv = &tvs[DEV(c->qid)];
917 		snprint(str, sizeof str, "%dx%dx%d %s channel %d %s\n",
918 				ntsc_hactive, ntsc_vactive, getbitspp(tv),
919 				getcolormode(tv->cfmt), tv->channel,
920 				tv->ainfo);
921 		return readstr(offset, a, strlen(str) + 1, str);
922 	}
923 
924 	case Qregs:
925 		if (offset == 0) {
926 			Bt848 *bt848;
927 			int i;
928 
929 			tv = &tvs[DEV(c->qid)];
930 			bt848 = tv->bt848;
931 
932 			e = regs + sizeof(regs);
933 			p = regs;
934 			for (i = 0; i < 0x300 >> 2; i++)
935 				p = seprint(p, e, "%.3X %.8ulX\n", i << 2, ((ulong *)bt848)[i]);
936 			if (tv->bt878) {
937 				bt848 = tv->bt878;
938 
939 				for (i = 0; i < 0x300 >> 2; i++)
940 					p = seprint(p, e, "%.3X %.8ulX\n",
941 							i << 2, ((ulong *)bt848)[i]);
942 			}
943 
944 			regslen = p - regs;
945 		}
946 
947 		if (offset >= regslen)
948 			return 0;
949 		if (offset + n > regslen)
950 			n = regslen - offset;
951 
952 		return readstr(offset, a, n, &regs[offset]);
953 
954 	default:
955 		n = 0;
956 		break;
957 	}
958 	return n;
959 }
960 
961 static long
962 tvwrite(Chan *c, void *a, long n, vlong)
963 {
964 	Cmdbuf *cb;
965 	Cmdtab *ct;
966 	Tv *tv;
967 
968 	tv = &tvs[DEV(c->qid)];
969 	switch(TYPE(c->qid)) {
970 	case Qctl:
971 		cb = parsecmd(a, n);
972 		if(waserror()){
973 			free(cb);
974 			nexterror();
975 		}
976 		ct = lookupcmd(cb, tvctlmsg, nelem(tvctlmsg));
977 		switch (ct->index) {
978 		case CMvstart:
979 			vstart(tv, (int)strtol(cb->f[1], (char **)nil, 0),
980 					ntsc_hactive, ntsc_vactive, ntsc_hactive);
981 			break;
982 
983 		case CMastart:
984 			astart(tv, cb->f[1], (uint)strtol(cb->f[2], (char **)nil, 0),
985 					(uint)strtol(cb->f[3], (char **)nil, 0),
986 					(uint)strtol(cb->f[4], (char **)nil, 0));
987 			break;
988 
989 		case CMastop:
990 			astop(tv);
991 			break;
992 
993 		case CMvgastart:
994 			vgastart(tv, strtoul(cb->f[1], (char **)nil, 0),
995 					(int)strtoul(cb->f[2], (char **)nil, 0));
996 			break;
997 
998 		case CMvstop:
999 			vstop(tv);
1000 			break;
1001 
1002 		case CMchannel:
1003 			frequency(tv, (int)strtol(cb->f[1], (char **)nil, 0),
1004 				(int)strtol(cb->f[2], (char **)nil, 0));
1005 			break;
1006 
1007 		case CMcolormode:
1008 			colormode(tv, cb->f[1]);
1009 			break;
1010 
1011 		case CMvolume:
1012 			if (!tv->msp)
1013 				error("#V: No volume control");
1014 
1015 			mspvolume(tv, 0, (int)strtol(cb->f[1], (char **)nil, 0),
1016 						(int)strtol(cb->f[2], (char **)nil, 0));
1017 			break;
1018 
1019 		case CMmute:
1020 			if (!tv->msp)
1021 				error("#V: No volume control");
1022 
1023 			mspvolume(tv, 1, 0, 0);
1024 			break;
1025 		}
1026 		poperror();
1027 		free(cb);
1028 		break;
1029 
1030 	default:
1031 		error(Eio);
1032 	}
1033 	return n;
1034 }
1035 
1036 Dev tvdevtab = {
1037 	'V',
1038 	"tv",
1039 
1040 	devreset,
1041 	tvinit,
1042 	devshutdown,
1043 	tvattach,
1044 	tvwalk,
1045 	tvstat,
1046 	tvopen,
1047 	devcreate,
1048 	tvclose,
1049 	tvread,
1050 	devbread,
1051 	tvwrite,
1052 	devbwrite,
1053 	devremove,
1054 	devwstat,
1055 };
1056 
1057 static void
1058 tvinterrupt(Ureg *, Tv *tv)
1059 {
1060 	Bt848 *bt848 = tv->bt848,
1061 		*bt878 = tv->bt878;
1062 
1063 	while (1) {
1064 		ulong vstat, astat;
1065 		uchar fnum;
1066 
1067 		vstat = bt848->intstat;
1068 		fnum = (vstat >> intstat_riscstatshift) & 0xf;
1069 		vstat &= bt848->intmask;
1070 
1071 		if (bt878)
1072 			astat = bt878->intstat & bt878->intmask;
1073 		else
1074 			astat = 0;
1075 
1076 		if (vstat == 0 && astat == 0)
1077 			break;
1078 
1079 		if (astat)
1080 		print("vstat %.8luX, astat %.8luX\n", vstat, astat);
1081 
1082 		bt848->intstat = vstat;
1083 		if (bt878)
1084 			bt878->intstat = astat;
1085 
1086 		if ((vstat & intstat_fmtchg) == intstat_fmtchg) {
1087 			iprint("int: fmtchg\n");
1088 			vstat &= ~intstat_fmtchg;
1089 		}
1090 
1091 		if ((vstat & intstat_vpress) == intstat_vpress) {
1092 //			iprint("int: vpress\n");
1093 			vstat &= ~intstat_vpress;
1094 		}
1095 
1096 		if ((vstat & intstat_vsync) == intstat_vsync) {
1097 			vstat &= ~intstat_vsync;
1098 		}
1099 
1100 		if ((vstat & intstat_scerr) == intstat_scerr) {
1101 			iprint("int: scerr\n");
1102 			bt848->gpiodmactl &=
1103 				~(gpiodmactl_riscenable|gpiodmactl_fifoenable);
1104 			bt848->gpiodmactl |= gpiodmactl_fifoenable;
1105 			bt848->gpiodmactl |= gpiodmactl_riscenable;
1106 			vstat &= ~intstat_scerr;
1107 		}
1108 
1109 		if ((vstat & intstat_risci) == intstat_risci) {
1110 			tv->lvframe = fnum;
1111 			vstat &= ~intstat_risci;
1112 		}
1113 
1114 		if ((vstat & intstat_ocerr) == intstat_ocerr) {
1115 			iprint("int: ocerr\n");
1116 			vstat &= ~intstat_ocerr;
1117 		}
1118 
1119 		if ((vstat & intstat_fbus) == intstat_fbus) {
1120 			iprint("int: fbus\n");
1121 			vstat &= ~intstat_fbus;
1122 		}
1123 
1124 		if (vstat)
1125 			iprint("int: (v) ignored interrupts %.8ulX\n", vstat);
1126 
1127 		if ((astat & intstat_risci) == intstat_risci) {
1128 			tv->narblocks++;
1129 			if ((tv->narblocks % 100) == 0)
1130 				print("a");
1131 			wakeup(tv);
1132 			astat &= ~intstat_risci;
1133 		}
1134 
1135 		if ((astat & intstat_fdsr) == intstat_fdsr) {
1136 			iprint("int: (a) fdsr\n");
1137 			bt848->gpiodmactl &=
1138 				~(gpiodmactl_acapenable |
1139 					gpiodmactl_riscenable | gpiodmactl_fifoenable);
1140 			astat &= ~intstat_fdsr;
1141 		}
1142 
1143 		if (astat)
1144 			iprint("int: (a) ignored interrupts %.8ulX\n", astat);
1145 	}
1146 }
1147 
1148 static int
1149 i2cread(Tv *tv, uchar off, uchar *v)
1150 {
1151 	Bt848 *bt848 = tv->bt848;
1152 	ulong intstat;
1153 	int i;
1154 
1155 	bt848->intstat	= intstat_i2cdone;
1156 	bt848->i2c = (off << 24) | tv->i2ccmd;
1157 
1158 	intstat = -1;
1159 	for (i = 0; i != 1000; i++) {
1160 		if ((intstat = bt848->intstat) & intstat_i2cdone)
1161 			break;
1162 		microdelay(1000);
1163 	}
1164 
1165 	if (i == 1000) {
1166 		print("i2cread: timeout\n");
1167 		return 0;
1168 	}
1169 
1170 	if ((intstat & intstat_i2crack) == 0)
1171 		return 0;
1172 
1173 	*v = bt848->i2c >> 8;
1174 	return 1;
1175 }
1176 
1177 static int
1178 i2cwrite(Tv *tv, uchar addr, uchar sub, uchar data, int both)
1179 {
1180 	Bt848 *bt848 = tv->bt848;
1181 	ulong intstat, d;
1182 	int i;
1183 
1184 	bt848->intstat	= intstat_i2cdone;
1185 	d = (addr << 24) | (sub << 16) | tv->i2ccmd;
1186 	if (both)
1187 		d |= (data << 8) | i2c_bt848w3b;
1188 	bt848->i2c = d;
1189 
1190 	intstat = 0;
1191 	for (i = 0; i != 1000; i++) {
1192 		if ((intstat = bt848->intstat) & intstat_i2cdone)
1193 			break;
1194 		microdelay(1000);
1195 	}
1196 
1197 	if (i == i2c_timeout) {
1198 		print("i2cwrite: timeout\n");
1199 		return 0;
1200 	}
1201 
1202 	if ((intstat & intstat_i2crack) == 0)
1203 		return 0;
1204 
1205 	return 1;
1206 }
1207 
1208 static ulong *
1209 riscpacked(ulong pa, int fnum, int w, int h, int stride, ulong **lastjmp)
1210 {
1211 	ulong *p, *pbase;
1212 	int i;
1213 
1214 	pbase = p = (ulong *)malloc((h + 6) * 2 * sizeof(ulong));
1215 	assert(p);
1216 
1217 	assert(w <= 0x7FF);
1218 
1219 	*p++ = riscsync | riscsync_resync | riscsync_vre;
1220 	*p++ = 0;
1221 
1222 	*p++ = riscsync | riscsync_fm1;
1223 	*p++ = 0;
1224 
1225 	for (i = 0; i != h / 2; i++) {
1226 		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
1227 		*p++ = pa + i * 2 * stride;
1228 	}
1229 
1230 	*p++ = riscsync | riscsync_resync | riscsync_vro;
1231 	*p++ = 0;
1232 
1233 	*p++ = riscsync | riscsync_fm1;
1234 	*p++ = 0;
1235 
1236 	for (i = 0; i != h / 2; i++) {
1237 		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
1238 		*p++ = pa + (i * 2 + 1) * stride;
1239 	}
1240 
1241 	// reset status.  you really need two instructions ;-(.
1242 	*p++ = riscjmp | (0xf << risclabelshift_reset);
1243 	*p++ = PADDR(p);
1244 	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
1245 	*lastjmp = p;
1246 
1247 	return pbase;
1248 }
1249 
1250 static ulong *
1251 riscplanar411(ulong pa, int fnum, int w, int h, ulong **lastjmp)
1252 {
1253 	ulong *p, *pbase, Cw, Yw, Ch;
1254 	uchar *Ybase, *Cbbase, *Crbase;
1255 	int i, bitspp;
1256 
1257 	bitspp = 6;
1258 	assert(w * bitspp / 8 <= 0x7FF);
1259 	pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
1260 	assert(p);
1261 
1262 	Yw = w;
1263 	Ybase = (uchar *)pa;
1264 	Cw = w >> 1;
1265 	Ch = h >> 1;
1266 	Cbbase = Ybase + Yw * h;
1267 	Crbase = Cbbase + Cw * Ch;
1268 
1269 	*p++ = riscsync | riscsync_resync | riscsync_vre;
1270 	*p++ = 0;
1271 
1272 	*p++ = riscsync | riscsync_fm3;
1273 	*p++ = 0;
1274 
1275 	for (i = 0; i != h / 2; i++) {
1276 		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
1277 		*p++ = (Cw << 16) | Cw;
1278 		*p++ = (ulong)(Ybase + i * 2 * Yw);
1279 		*p++ = (ulong)(Cbbase + i * Cw);		// Do not interlace
1280 		*p++ = (ulong)(Crbase + i * Cw);
1281 	}
1282 
1283 	*p++ = riscsync | riscsync_resync | riscsync_vro;
1284 	*p++ = 0;
1285 
1286 	*p++ = riscsync | riscsync_fm3;
1287 	*p++ = 0;
1288 
1289 	for (i = 0; i != h / 2; i++) {
1290 		*p++ = riscwrite1s23 | Yw | riscwrite_sol | riscwrite_eol;
1291 		*p++ = (Cw << 16) | Cw;
1292 		*p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
1293 	}
1294 
1295 	// reset status.  you really need two instructions ;-(.
1296 	*p++ = riscjmp | (0xf << risclabelshift_reset);
1297 	*p++ = PADDR(p);
1298 	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
1299 	*lastjmp = p;
1300 
1301 	return pbase;
1302 }
1303 
1304 static ulong *
1305 riscplanar422(ulong pa, int fnum, int w, int h, ulong **lastjmp)
1306 {
1307 	ulong *p, *pbase, Cw, Yw;
1308 	uchar *Ybase, *Cbbase, *Crbase;
1309 	int i, bpp;
1310 
1311 	bpp = 2;
1312 	assert(w * bpp <= 0x7FF);
1313 	pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
1314 	assert(p);
1315 
1316 	Yw = w;
1317 	Ybase = (uchar *)pa;
1318 	Cw = w >> 1;
1319 	Cbbase = Ybase + Yw * h;
1320 	Crbase = Cbbase + Cw * h;
1321 
1322 	*p++ = riscsync | riscsync_resync | riscsync_vre;
1323 	*p++ = 0;
1324 
1325 	*p++ = riscsync | riscsync_fm3;
1326 	*p++ = 0;
1327 
1328 	for (i = 0; i != h / 2; i++) {
1329 		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
1330 		*p++ = (Cw << 16) | Cw;
1331 		*p++ = (ulong)(Ybase + i * 2 * Yw);
1332 		*p++ = (ulong)(Cbbase + i * 2 * Cw);
1333 		*p++ = (ulong)(Crbase + i * 2 * Cw);
1334 	}
1335 
1336 	*p++ = riscsync | riscsync_resync | riscsync_vro;
1337 	*p++ = 0;
1338 
1339 	*p++ = riscsync | riscsync_fm3;
1340 	*p++ = 0;
1341 
1342 	for (i = 0; i != h / 2; i++) {
1343 		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
1344 		*p++ = (Cw << 16) | Cw;
1345 		*p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
1346 		*p++ = (ulong)(Cbbase + (i * 2 + 1) * Cw);
1347 		*p++ = (ulong)(Crbase + (i * 2 + 1) * Cw);
1348 	}
1349 
1350 	// reset status.  you really need two instructions ;-(.
1351 	*p++ = riscjmp | (0xf << risclabelshift_reset);
1352 	*p++ = PADDR(p);
1353 	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
1354 	*lastjmp = p;
1355 
1356 	return pbase;
1357 }
1358 
1359 static ulong *
1360 riscaudio(ulong pa, int nblocks, int bsize)
1361 {
1362 	ulong *p, *pbase;
1363 	int i;
1364 
1365 	pbase = p = (ulong *)malloc((nblocks + 3) * 2 * sizeof(ulong));
1366 	assert(p);
1367 
1368 	*p++ = riscsync|riscsync_fm1;
1369 	*p++ = 0;
1370 
1371 	for (i = 0; i != nblocks; i++) {
1372 		*p++ = riscwrite | riscwrite_sol | riscwrite_eol | bsize | riscirq |
1373 				((i & 0xf) << risclabelshift_set) |
1374 				((~i & 0xf) << risclabelshift_reset);
1375 		*p++ = pa + i * bsize;
1376 	}
1377 
1378 	*p++ = riscsync | riscsync_vro;
1379 	*p++ = 0;
1380 	*p++ = riscjmp;
1381 	*p++ = PADDR(pbase);
1382 	USED(p);
1383 
1384 	return pbase;
1385 }
1386 
1387 
1388 static void
1389 vactivate(Tv *tv, Frame *frames, int nframes)
1390 {
1391 	Bt848 *bt848 = tv->bt848;
1392 
1393 	ilock(tv);
1394 	if (tv->frames) {
1395 		iunlock(tv);
1396 		error(Einuse);
1397 	}
1398 	poperror();
1399 
1400 	tv->frames = frames;
1401 	tv->nframes = nframes;
1402 
1403 	bt848->riscstrtadd = PADDR(tv->frames[0].fstart);
1404 	bt848->capctl |= capctl_captureodd|capctl_captureeven;
1405 	bt848->gpiodmactl |= gpiodmactl_fifoenable;
1406 	bt848->gpiodmactl |= gpiodmactl_riscenable;
1407 
1408 	iunlock(tv);
1409 }
1410 
1411 static void
1412 vstart(Tv *tv, int nframes, int w, int h, int stride)
1413 {
1414 	Frame *frames;
1415 	int bitspp, i, bpf;
1416 
1417 	if (nframes >= 0x10)
1418 		error(Ebadarg);
1419 
1420 	bitspp = getbitspp(tv);
1421 	bpf = w * h * bitspp / 8;
1422 
1423 	// Add one as a spare.
1424 	frames = (Frame *)malloc(nframes * sizeof(Frame));
1425 	assert(frames);
1426 	if (waserror()) {
1427 		for (i = 0; i != nframes; i++)
1428 			if (frames[i].fbase)
1429 				free(frames[i].fbase);
1430 		free(frames);
1431 		nexterror();
1432 	}
1433 	memset(frames, 0, nframes * sizeof(Frame));
1434 
1435 	for (i = 0; i != nframes; i++) {
1436 		if ((frames[i].fbase = (uchar *)malloc(bpf)) == nil)
1437 			error(Enomem);
1438 
1439 		switch (tv->cfmt) {
1440 		case colorfmt_YCbCr422:
1441 			frames[i].fstart = riscplanar422(PADDR(frames[i].fbase), i,
1442 									 w, h, &frames[i].fjmp);
1443 			break;
1444 		case colorfmt_YCbCr411:
1445 			frames[i].fstart = riscplanar411(PADDR(frames[i].fbase), i,
1446 									 w, h, &frames[i].fjmp);
1447 			break;
1448 		case colorfmt_rgb16:
1449 			frames[i].fstart = riscpacked(PADDR(frames[i].fbase), i,
1450 								     w * bitspp / 8, h, stride * bitspp / 8,
1451 								     &frames[i].fjmp);
1452 			break;
1453 		default:
1454 			panic("vstart: Unsupport colorformat\n");
1455 		}
1456 	}
1457 
1458 	for (i = 0; i != nframes; i++)
1459 		*frames[i].fjmp =
1460 			PADDR((i == nframes - 1)? frames[0].fstart: frames[i + 1].fstart);
1461 
1462 	vactivate(tv, frames, nframes);
1463 }
1464 
1465 static void
1466 astart(Tv *tv, char *input, uint rate, uint nab, uint nasz)
1467 {
1468 	Bt848 *bt878 = tv->bt878;
1469 	ulong *arisc;
1470 	int selector;
1471 	uchar *abuf;
1472 	int s, d;
1473 
1474 	if (bt878 == nil || tv->amux == nil)
1475 		error("#V: Card does not support audio");
1476 
1477 	selector = 0;
1478 	if (!strcmp(input, "tv"))
1479 		selector = asel_tv;
1480 	else 	if (!strcmp(input, "radio"))
1481 		selector = asel_radio;
1482 	else 	if (!strcmp(input, "mic"))
1483 		selector = asel_mic;
1484 	else 	if (!strcmp(input, "smxc"))
1485 		selector = asel_smxc;
1486 	else
1487 		error("#V: Invalid input");
1488 
1489 	if (nasz > 0xfff)
1490 		error("#V: Audio block size too big (max 0xfff)");
1491 
1492 	abuf = (uchar *)malloc(nab * nasz * sizeof(uchar));
1493 	assert(abuf);
1494 	arisc = riscaudio(PADDR(abuf), nab, nasz);
1495 
1496 	ilock(tv);
1497 	if (tv->arisc) {
1498 		iunlock(tv);
1499 		free(abuf);
1500 		free(arisc);
1501 		error(Einuse);
1502 	}
1503 
1504 	tv->arisc = arisc;
1505 	tv->abuf = abuf;
1506 	tv->nablocks = nab;
1507 	tv->absize = nasz;
1508 
1509 	bt878->riscstrtadd = PADDR(tv->arisc);
1510 	bt878->packetlen = (nab << 16) | nasz;
1511 	bt878->intmask =
1512 				intstat_scerr | intstat_ocerr | intstat_risci |
1513 				intstat_pabort | intstat_riperr | intstat_pperr |
1514 				intstat_fdsr | intstat_ftrgt | intstat_fbus;
1515 
1516 	/* Assume analog, 16bpp */
1517 	for (s = 0; s < 16; s++)
1518 		if (rate << s > Hwbase_ad * 4 / 15)
1519 			break;
1520 	for (d = 15; d >= 4; d--)
1521 		if (rate << s < Hwbase_ad * 4 / d)
1522 			break;
1523 
1524 	print("astart: sampleshift %d, decimation %d\n", s, d);
1525 
1526 	tv->narblocks = 0;
1527 	bt878->gpiodmactl = gpiodmactl_fifoenable |
1528 			gpiodmactl_riscenable | gpiodmactl_acapenable |
1529 			gpiodmactl_daes2 | /* gpiodmactl_apwrdn | */
1530 			gpiodmactl_daiomda | (d << 8) | (9 << 28) | (selector << 24);
1531 	print("dmactl %.8ulX\n", bt878->gpiodmactl);
1532 	iunlock(tv);
1533 }
1534 
1535 static void
1536 astop(Tv *tv)
1537 {
1538 	Bt848 *bt878 = tv->bt878;
1539 
1540 	ilock(tv);
1541 	if (tv->aref.ref > 0) {
1542 		iunlock(tv);
1543 		error(Einuse);
1544 	}
1545 
1546 	if (tv->abuf) {
1547 		bt878->gpiodmactl &= ~gpiodmactl_riscenable;
1548 		bt878->gpiodmactl &= ~gpiodmactl_fifoenable;
1549 
1550 		free(tv->abuf);
1551 		tv->abuf = nil;
1552 		free(tv->arisc);
1553 		tv->arisc = nil;
1554 	}
1555 	iunlock(tv);
1556 }
1557 
1558 static void
1559 vgastart(Tv *tv, ulong pa, int stride)
1560 {
1561 	Frame *frame;
1562 
1563 	frame = (Frame *)malloc(sizeof(Frame));
1564 	assert(frame);
1565 	if (waserror()) {
1566 		free(frame);
1567 		nexterror();
1568 	}
1569 
1570 	frame->fbase = nil;
1571 	frame->fstart = riscpacked(pa, 0, ntsc_hactive * getbitspp(tv) / 8,
1572 						   ntsc_vactive, stride * getbitspp(tv) / 8,
1573 						   &frame->fjmp);
1574 	*frame->fjmp = PADDR(frame->fstart);
1575 
1576 	vactivate(tv, frame, 1);
1577 }
1578 
1579 static void
1580 vstop(Tv *tv)
1581 {
1582 	Bt848 *bt848 = tv->bt848;
1583 
1584 	ilock(tv);
1585 	if (tv->fref.ref > 0) {
1586 		iunlock(tv);
1587 		error(Einuse);
1588 	}
1589 
1590 	if (tv->frames) {
1591 		int i;
1592 
1593 		bt848->gpiodmactl &= ~gpiodmactl_riscenable;
1594 		bt848->gpiodmactl &= ~gpiodmactl_fifoenable;
1595 		bt848->capctl &= ~(capctl_captureodd|capctl_captureeven);
1596 
1597 		for (i = 0; i != tv->nframes; i++)
1598 			if (tv->frames[i].fbase)
1599 				free(tv->frames[i].fbase);
1600 		free(tv->frames);
1601 		tv->frames = nil;
1602 	}
1603 	iunlock(tv);
1604 }
1605 
1606 static long
1607 hrcfreq[] = {	/* HRC CATV frequencies */
1608 	    0,  7200,  5400,  6000,  6600,  7800,  8400, 17400,
1609 	18000, 18600, 19200, 19800, 20400, 21000, 12000, 12600,
1610 	13200, 13800, 14400, 15000, 15600, 16200, 16800, 21600,
1611 	22200, 22800, 23400, 24000, 24600, 25200, 25800, 26400,
1612 	27000, 27600, 28200, 28800, 29400, 30000, 30600, 31200,
1613 	31800, 32400, 33000, 33600, 34200, 34800, 35400, 36000,
1614 	36600, 37200, 37800, 38400, 39000, 39600, 40200, 40800,
1615 	41400, 42000, 42600, 43200, 43800, 44400, 45000, 45600,
1616 	46200, 46800, 47400, 48000, 48600, 49200, 49800, 50400,
1617 	51000, 51600, 52200, 52800, 53400, 54000, 54600, 55200,
1618 	55800, 56400, 57000, 57600, 58200, 58800, 59400, 60000,
1619 	60600, 61200, 61800, 62400, 63000, 63600, 64200,  9000,
1620 	 9600, 10200, 10800, 11400, 64800, 65400, 66000, 66600,
1621 	67200, 67800, 68400, 69000, 69600, 70200, 70800, 71400,
1622 	72000, 72600, 73200, 73800, 74400, 75000, 75600, 76200,
1623 	76800, 77400, 78000, 78600, 79200, 79800,
1624 };
1625 
1626 static void
1627 frequency(Tv *tv, int channel, int finetune)
1628 {
1629 	Tuner *tuner = tv->tuner;
1630 	long freq;
1631 	ushort div;
1632 	uchar cfg;
1633 
1634 	if (channel < 0 || channel > nelem(hrcfreq))
1635 		error(Ebadarg);
1636 
1637 	freq = (hrcfreq[channel] * Freqmultiplier) / 100;
1638 
1639 	if (freq < tuner->freq_vhfh)
1640 		cfg = tuner->VHF_L;
1641 	else if (freq < tuner->freq_uhf)
1642 		cfg =  tuner->VHF_H;
1643 	else
1644 		cfg = tuner->UHF;
1645 
1646 	div = (freq + tuner->offs + finetune) & 0x7fff;
1647 
1648 	if (!i2cwrite(tv, tv->i2ctuneraddr, (div >> 8) & 0x7f, div, 1))
1649 		error(Eio);
1650 
1651 	if (!i2cwrite(tv, tv->i2ctuneraddr, tuner->cfg, cfg, 1))
1652 		error(Eio);
1653 
1654 	tv->channel = channel;
1655 	if (tv->msp)
1656 		msptune(tv);
1657 }
1658 
1659 static struct {
1660 	char *cmode;
1661 	ulong realmode;
1662 	ulong cbits;
1663 } colormodes[] = {
1664 {	"RGB16",		colorfmt_rgb16,		colorfmt_rgb16,		},
1665 {	"YCbCr422",	colorfmt_YCbCr422,	colorfmt_YCbCr422,	},
1666 {	"YCbCr411",	colorfmt_YCbCr411,	colorfmt_YCbCr422,	},
1667 };
1668 
1669 static void
1670 colormode(Tv *tv, char *colormode)
1671 {
1672 	Bt848 *bt848 = tv->bt848;
1673 	int i;
1674 
1675 	for (i = 0; i != nelem(colormodes); i++)
1676 		if (!strcmp(colormodes[i].cmode, colormode))
1677 			break;
1678 
1679 	if (i == nelem(colormodes))
1680 		error(Ebadarg);
1681 
1682 	tv->cfmt = colormodes[i].realmode;
1683 	bt848->colorfmt = colormodes[i].cbits;
1684 }
1685 
1686 static int
1687 getbitspp(Tv *tv)
1688 {
1689 	switch (tv->cfmt) {
1690 	case colorfmt_rgb16:
1691 	case colorfmt_YCbCr422:
1692 		return 16;
1693 	case colorfmt_YCbCr411:
1694 		return 12;
1695 	default:
1696 		error("getbitspp: Unsupport color format\n");
1697 	}
1698 	return -1;
1699 }
1700 
1701 static char *
1702 getcolormode(ulong cmode)
1703 {
1704 	switch (cmode) {
1705 	case colorfmt_rgb16:
1706 		return "RGB16";
1707 	case colorfmt_YCbCr411:
1708 		return "YCbCr411";
1709 	case colorfmt_YCbCr422:
1710 		return (cmode == colorfmt_YCbCr422)? "YCbCr422": "YCbCr411";
1711 	default:
1712 		error("getcolormode: Unsupport color format\n");
1713 	}
1714 	return nil;
1715 }
1716 
1717 static void
1718 i2c_set(Tv *tv, int scl, int sda)
1719 {
1720 	Bt848 *bt848 = tv->bt848;
1721 	ulong d;
1722 
1723 	bt848->i2c = (scl << 1) | sda;
1724 	d = bt848->i2c;
1725 	USED(d);
1726 	microdelay(i2c_delay);
1727 }
1728 
1729 static uchar
1730 i2c_getsda(Tv *tv)
1731 {
1732 	Bt848 *bt848 = tv->bt848;
1733 
1734 	return bt848->i2c & i2c_sda;
1735 }
1736 
1737 static void
1738 i2c_start(Tv *tv)
1739 {
1740 	i2c_set(tv, 0, 1);
1741 	i2c_set(tv, 1, 1);
1742 	i2c_set(tv, 1, 0);
1743 	i2c_set(tv, 0, 0);
1744 }
1745 
1746 static void
1747 i2c_stop(Tv *tv)
1748 {
1749 	i2c_set(tv, 0, 0);
1750 	i2c_set(tv, 1, 0);
1751 	i2c_set(tv, 1, 1);
1752 }
1753 
1754 static void
1755 i2c_bit(Tv *tv, int sda)
1756 {
1757 	i2c_set(tv, 0, sda);
1758 	i2c_set(tv, 1, sda);
1759 	i2c_set(tv, 0, sda);
1760 }
1761 
1762 static int
1763 i2c_getack(Tv *tv)
1764 {
1765 	int ack;
1766 
1767 	i2c_set(tv, 0, 1);
1768 	i2c_set(tv, 1, 1);
1769 	ack = i2c_getsda(tv);
1770 	i2c_set(tv, 0, 1);
1771 	return ack;
1772 }
1773 
1774 static int
1775 i2c_wr8(Tv *tv, uchar d, int wait)
1776 {
1777 	int i, ack;
1778 
1779 	i2c_set(tv, 0, 0);
1780 	for (i = 0; i != 8; i++) {
1781 		i2c_bit(tv, (d & 0x80)? 1: 0);
1782 		d <<= 1;
1783 	}
1784 	if (wait)
1785 		microdelay(wait);
1786 
1787 	ack = i2c_getack(tv);
1788 	return ack == 0;
1789 }
1790 
1791 static uchar
1792 i2c_rd8(Tv *tv, int lastbyte)
1793 {
1794 	int i;
1795 	uchar d;
1796 
1797 	d = 0;
1798 	i2c_set(tv, 0, 1);
1799 	for (i = 0; i != 8; i++) {
1800 		i2c_set(tv, 1, 1);
1801 		d <<= 1;
1802 		if (i2c_getsda(tv))
1803 			d |= 1;
1804 		i2c_set(tv, 0, 1);
1805 	}
1806 
1807 	i2c_bit(tv, lastbyte? 1: 0);
1808 	return d;
1809 }
1810 
1811 static int
1812 mspsend(Tv *tv, uchar *cmd, int ncmd)
1813 {
1814 	int i, j, delay;
1815 
1816 	for (i = 0; i != 3; i++) {
1817 		delay = 2000;
1818 
1819 		i2c_start(tv);
1820 		for (j = 0; j != ncmd; j++) {
1821 			if (!i2c_wr8(tv, cmd[j], delay))
1822 				break;
1823 			delay = 0;
1824 		}
1825 		i2c_stop(tv);
1826 
1827 		if (j == ncmd)
1828 			return 1;
1829 
1830 		microdelay(10000);
1831 		print("mspsend: retrying\n");
1832 	}
1833 
1834 	return 0;
1835 }
1836 
1837 static int
1838 mspwrite(Tv *tv, uchar sub, ushort reg, ushort v)
1839 {
1840 	uchar b[6];
1841 
1842 	b[0] = i2c_msp3400;
1843 	b[1] = sub;
1844 	b[2] = reg >> 8;
1845 	b[3] = reg;
1846 	b[4] = v >> 8;
1847 	b[5] = v;
1848 	return mspsend(tv, b, sizeof b);
1849 }
1850 
1851 static int
1852 mspread(Tv *tv, uchar sub, ushort reg, ushort *data)
1853 {
1854 	uchar b[4];
1855 	int i;
1856 
1857 	b[0] = i2c_msp3400;
1858 	b[1] = sub;
1859 	b[2] = reg >> 8;
1860 	b[3] = reg;
1861 
1862 	for (i = 0; i != 3; i++) {
1863 		i2c_start(tv);
1864 		if (!i2c_wr8(tv, b[0], 2000) ||
1865 			!i2c_wr8(tv, b[1] | 1, 0) ||
1866 			!i2c_wr8(tv, b[2], 0) ||
1867 			!i2c_wr8(tv, b[3], 0)) {
1868 
1869 			i2c_stop(tv);
1870 			microdelay(10000);
1871 			print("retrying\n");
1872 			continue;
1873 		}
1874 
1875 		i2c_start(tv);
1876 
1877 		if (!i2c_wr8(tv, b[0] | 1, 2000)) {
1878 
1879 			i2c_stop(tv);
1880 			continue;
1881 		}
1882 
1883 		*data = i2c_rd8(tv, 0) << 8;
1884 		*data |= i2c_rd8(tv, 1);
1885 		i2c_stop(tv);
1886 		return 1;
1887 	}
1888 	return 0;
1889 }
1890 
1891 static uchar mspt_reset[] = { i2c_msp3400, 0, 0x80, 0 };
1892 static uchar mspt_on[] = { i2c_msp3400, 0, 0, 0 };
1893 
1894 static int
1895 mspreset(Tv *tv)
1896 {
1897 	ushort v, p;
1898 	Bt848 *bt848 = tv->bt848;
1899 	ulong b;
1900 
1901 	b = 1 << 5;
1902 	gpioenable(tv, ~b, b);
1903 	gpiowrite(tv, ~b, 0);
1904 	microdelay(2500);
1905 	gpiowrite(tv, ~b, b);
1906 
1907 	bt848->i2c = 0x80;
1908 
1909 	microdelay(2000);
1910 	mspsend(tv, mspt_reset, sizeof mspt_reset);
1911 
1912 	microdelay(2000);
1913 	if (!mspsend(tv, mspt_on, sizeof mspt_on)) {
1914 		print("#V: Cannot find MSP34x5G on the I2C bus (on)\n");
1915 		return 0;
1916 	}
1917 	microdelay(2000);
1918 
1919 	if (!mspread(tv, msp_bbp, 0x001e, &v)) {
1920 		print("#V: Cannot read MSP34xG5 chip version\n");
1921 		return 0;
1922 	}
1923 
1924 	if (!mspread(tv, msp_bbp, 0x001f, &p)) {
1925 		print("#V: Cannot read MSP34xG5 product code\n");
1926 		return 0;
1927 	}
1928 
1929 	print("#V: MSP34%dg ROM %.d, %d.%d\n",
1930 		(uchar)(p >> 8), (uchar)p, (uchar)(v >> 8), (uchar)v);
1931 
1932 	tv->msp = 1;
1933 	return 1;
1934 }
1935 
1936 static void
1937 mspvolume(Tv *tv, int mute, int l, int r)
1938 {
1939 	short v, d;
1940 	ushort b;
1941 
1942 	if (mute) {
1943 		v = 0;
1944 		b = 0;
1945 	}
1946 	else {
1947 		tv->aleft = l;
1948 		tv->aright = r;
1949 		d = v = max(l, r);
1950 		if (d == 0)
1951 			d++;
1952 		b = ((r - l) * 0x7f) / d;
1953 	}
1954 
1955 	mspwrite(tv, msp_bbp, 0, v << 8);
1956 	mspwrite(tv, msp_bbp, 7, v? 0x4000: 0);
1957 	mspwrite(tv, msp_bbp, 1, b << 8);
1958 }
1959 
1960 static char *
1961 mspaformat(int f)
1962 {
1963 	switch (f) {
1964 	case 0:
1965 		return "unknown";
1966 	case 2:
1967 	case 0x20:
1968 	case 0x30:
1969 		return "M-BTSC";
1970 	case 3:
1971 		return "B/G-FM";
1972 	case 4:
1973 	case 9:
1974 	case 0xB:
1975 		return "L-AM/NICAM D/Kn";
1976 	case 8:
1977 		return "B/G-NICAM";
1978 	case 0xA:
1979 		return "I";
1980 	case 0x40:
1981 		return "FM-Radio";
1982 	}
1983 	return "unknown format";
1984 }
1985 
1986 
1987 static void
1988 msptune(Tv *tv)
1989 {
1990 	ushort d, s, nicam;
1991 	int i;
1992 
1993 	mspvolume(tv, 1, 0, 0);
1994 	if (!mspwrite(tv, msp_dem, 0x0030, 0x2033))
1995 		error("#V: Cannot set MODUS register");
1996 
1997 	if (!mspwrite(tv, msp_bbp, 0x0008, 0x0320))
1998 		error("#V: Cannot set loadspeaker input");
1999 
2000 	if (!mspwrite(tv, msp_dem, 0x0040, 0x0001))
2001 		error("#V: Cannot set I2S clock freq");
2002 	if (!mspwrite(tv, msp_bbp, 0x000d, 0x1900))
2003 		error("#V: Cannot set SCART prescale");
2004 	if (!mspwrite(tv, msp_bbp, 0x000e, 0x2403))
2005 		error("#V: Cannot set FM/AM prescale");
2006 	if (!mspwrite(tv, msp_bbp, 0x0010, 0x5a00))
2007 		error("#V: Cannot set NICAM prescale");
2008 	if (!mspwrite(tv, msp_dem, 0x0020, 0x0001))
2009 		error("#V: Cannot start auto detect");
2010 
2011 	for (d = (ushort)-1, i = 0; i != 10; i++) {
2012 		if (!mspread(tv, msp_dem, 0x007e, &d))
2013 			error("#V: Cannot get autodetect info MSP34xG5");
2014 
2015 		if (d == 0 || d < 0x800)
2016 			break;
2017 		delay(50);
2018 	}
2019 
2020 	if (!mspread(tv, msp_dem, 0x0200, &s))
2021 		error("#V: Cannot get status info MSP34xG5");
2022 
2023 	mspvolume(tv, 0, tv->aleft, tv->aright);
2024 
2025 	nicam = ((s >> 4) & 2) | ((s >> 9) & 1);
2026 	snprint(tv->ainfo, sizeof tv->ainfo, "%s %s %s",
2027 			mspaformat(d), (s & (1 << 6))? "stereo": "mono",
2028 			nicamstate[nicam]);
2029 }
2030 
2031 static void
2032 i2cscan(Tv *tv)
2033 {
2034 	int i, ack;
2035 
2036 	for (i = 0; i < 0x100; i += 2) {
2037 		i2c_start(tv);
2038 		ack = i2c_wr8(tv, i, 0);
2039 		i2c_stop(tv);
2040 		if (ack) {
2041 			print("i2c device @%.2uX\n", i);
2042 		}
2043 	}
2044 
2045 	for (i = 0xf0; i != 0xff; i++) {
2046 		i2c_start(tv);
2047 		ack = i2c_wr8(tv, i, 0);
2048 		i2c_stop(tv);
2049 		if (ack)
2050 			print("i2c device may be at @%.2uX\n", i);
2051 	}
2052 }
2053 
2054 static void
2055 gpioenable(Tv *tv, ulong mask, ulong data)
2056 {
2057 	Bt848 *bt848 = tv->bt848;
2058 
2059 	bt848->gpioouten = (bt848->gpioouten & mask) | data;
2060 }
2061 
2062 static void
2063 gpiowrite(Tv *tv, ulong mask, ulong data)
2064 {
2065 	Bt848 *bt848 = tv->bt848;
2066 
2067 	bt848->gpiodata[0] = (bt848->gpiodata[0] & mask) | data;
2068 }
2069 
2070 static void
2071 alteraoutput(Tv *tv)
2072 {
2073 	if (tv->gpiostate == Gpiooutput)
2074 		return;
2075 
2076 	gpioenable(tv, ~0xffffff, 0x56ffff);
2077 	microdelay(10);
2078 	tv->gpiostate = Gpiooutput;
2079 }
2080 
2081 static void
2082 alterainput(Tv *tv)
2083 {
2084 	if (tv->gpiostate == Gpioinput)
2085 		return;
2086 
2087 	gpioenable(tv, ~0xffffff, 0x570000);
2088 	microdelay(10);
2089 	tv->gpiostate = Gpioinput;
2090 }
2091 
2092 static void
2093 alterareg(Tv *tv, ulong reg)
2094 {
2095 	if (tv->alterareg == reg)
2096 		return;
2097 
2098 	gpiowrite(tv, ~0x56ffff, (reg & 0x54ffff) | tv->alteraclock);
2099 	microdelay(10);
2100 	tv->alterareg = reg;
2101 }
2102 
2103 static void
2104 alterawrite(Tv *tv, ulong reg, ushort data)
2105 {
2106 	alteraoutput(tv);
2107 	alterareg(tv, reg);
2108 
2109 	tv->alteraclock ^= 0x20000;
2110 	gpiowrite(tv, ~0x56ffff, (reg & 0x540000) | data | tv->alteraclock);
2111 	microdelay(10);
2112 }
2113 
2114 static void
2115 alteraread(Tv *tv, int reg, ushort *data)
2116 {
2117 	Bt848 *bt848 = tv->bt848;
2118 
2119 	if (tv->alterareg != reg) {
2120 		alteraoutput(tv);
2121 		alterareg(tv, reg);
2122 	}
2123 	else {
2124 		gpioenable(tv, ~0xffffff, 0x560000);
2125 		microdelay(10);
2126 	}
2127 
2128 	alterainput(tv);
2129 	gpiowrite(tv, ~0x570000, (reg & 0x560000) | tv->alteraclock);
2130 	microdelay(10);
2131 	*data = (ushort)bt848->gpiodata[0];
2132 	microdelay(10);
2133 }
2134 
2135 static void
2136 kfirloadu(Tv *tv, uchar *u, int ulen)
2137 {
2138 	Bt848 *bt848 = tv->bt848;
2139 	int i, j;
2140 
2141 	ilock(&tv->kfirlock);
2142 	bt848->gpioouten &= 0xff000000;
2143 	bt848->gpioouten |= gpio_altera_data |
2144 		gpio_altera_clock | gpio_altera_nconfig;
2145 	bt848->gpiodata[0] &= 0xff000000;
2146 	microdelay(10);
2147 	bt848->gpiodata[0] |= gpio_altera_nconfig;
2148 	microdelay(10);
2149 
2150 	// Download the microcode
2151 	for (i = 0; i != ulen; i++)
2152 		for (j = 0; j != 8; j++) {
2153 			bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
2154 			if (u[i] & 1)
2155 				bt848->gpiodata[0] |= gpio_altera_data;
2156 			bt848->gpiodata[0] |= gpio_altera_clock;
2157 			u[i] >>= 1;
2158 		}
2159 	bt848->gpiodata[0] &= ~gpio_altera_clock;
2160 	microdelay(100);
2161 
2162 	// Initialize.
2163 	for (i = 0; i != 30; i++) {
2164 		bt848->gpiodata[0] &= ~gpio_altera_clock;
2165 		bt848->gpiodata[0] |= gpio_altera_clock;
2166 	}
2167 	bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
2168 	iunlock(&tv->kfirlock);
2169 
2170 	tv->gpiostate = Gpioinit;
2171 }
2172 
2173 static void
2174 kfirreset(Tv *tv)
2175 {
2176 	alterawrite(tv, 0, 0);
2177 	microdelay(10);
2178 	alterawrite(tv, 0x40000, 0);
2179 	microdelay(10);
2180 	alterawrite(tv, 0x40006, 0x80);
2181 	microdelay(10);
2182 	alterawrite(tv, 8, 1);
2183 	microdelay(10);
2184 	alterawrite(tv, 0x40004, 2);
2185 	microdelay(10);
2186 	alterawrite(tv, 4, 3);
2187 	microdelay(3);
2188 }
2189 
2190 static int
2191 kfirinitialize(Tv *tv)
2192 {
2193 	// Initialize parameters?
2194 
2195 	tv->gpiostate = Gpioinit;
2196 	tv->alterareg = -1;
2197 	tv->alteraclock = 0x20000;
2198 	kfirloadu(tv, hcwAMC, sizeof hcwAMC);
2199 	kfirreset(tv);
2200 	return 1;
2201 }
2202 
2203