xref: /plan9/sys/src/9/pc/devtv.c (revision 567483c891f7c54442ce1d593e764767ee5fcaf7)
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
tvinit(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*
tvattach(char * spec)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
tv1gen(Chan * c,int i,Dir * dp)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
tvgen(Chan * c,char *,Dirtab *,int,int i,Dir * dp)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 *
tvwalk(Chan * c,Chan * nc,char ** name,int nname)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
tvstat(Chan * c,uchar * db,int n)782 tvstat(Chan *c, uchar *db, int n)
783 {
784 	return devstat(c, db, n, 0, 0, tvgen);
785 }
786 
787 static Chan*
tvopen(Chan * c,int omode)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
tvclose(Chan *)813 tvclose(Chan *)
814 {
815 }
816 
817 static int
audioblock(void *)818 audioblock(void *)
819 {
820 	return 1;
821 }
822 
823 static long
tvread(Chan * c,void * a,long n,vlong offset)824 tvread(Chan *c, void *a, long n, vlong offset)
825 {
826 	static char regs[10 * K];
827 	static int regslen;
828 	Tv *tv;
829 	char *e, *p;
830 	uchar *src;
831 
832 	USED(offset);
833 
834 	switch(TYPE(c->qid)) {
835 	case Qdir:
836 	case Qsubdir:
837 		return devdirread(c, a, n, 0, 0, tvgen);
838 
839 	case Qvdata: {
840 		int bpf, nb;
841 
842 		tv = &tvs[DEV(c->qid)];
843 		bpf = ntsc_hactive * ntsc_vactive * getbitspp(tv) / 8;
844 
845 		if (offset >= bpf)
846 			return 0;
847 
848 		nb = n;
849 		if (offset + nb > bpf)
850 			nb = bpf - offset;
851 
852 		ilock(tv);
853 		if (tv->frames == nil || tv->lvframe >= tv->nframes ||
854 			tv->frames[tv->lvframe].fbase == nil) {
855 			iunlock(tv);
856 			return 0;
857 		}
858 
859 		src = tv->frames[tv->lvframe].fbase;
860 		incref(&tv->fref);
861 		iunlock(tv);
862 
863 		memmove(a, src + offset, nb);
864 		decref(&tv->fref);
865 		return nb;
866 	}
867 
868 	case Qadata: {
869 		ulong uablock = (ulong)c->aux, bnum, tvablock;
870 		int boffs, nbytes;
871 
872 		tv = &tvs[DEV(c->qid)];
873 		if (tv->bt878 == nil)
874 			error("#V: No audio device");
875 		if (tv->absize == 0)
876 			error("#V: audio not initialized");
877 
878 		bnum = offset / tv->absize;
879 		boffs = offset % tv->absize;
880 		nbytes = tv->absize - boffs;
881 
882 		incref(&tv->aref);
883 		for (;;) {
884 			tvablock = tv->narblocks;	/* Current tv block. */
885 
886 			if (uablock == 0)
887 				uablock = tvablock - 1;
888 
889 			if (tvablock >= uablock + bnum + tv->narblocks)
890 				uablock = tvablock - 1 - bnum;
891 
892 			if (uablock + bnum == tvablock) {
893 				sleep(tv, audioblock, nil);
894 				continue;
895 			}
896 			break;
897 		}
898 
899 		print("uablock %ld, bnum %ld, boffs %d, nbytes %d, tvablock %ld\n",
900 			uablock, bnum, boffs, nbytes, tvablock);
901 		src = tv->abuf + ((uablock + bnum) % tv->nablocks) * tv->absize;
902 		print("copying from %#p (abuf %#p), nbytes %d (block %ld.%ld)\n",
903 			src + boffs, tv->abuf, nbytes, uablock, bnum);
904 
905 		memmove(a, src + boffs, nbytes);
906 		decref(&tv->aref);
907 
908 		uablock += (boffs + nbytes) % tv->absize;
909 		c->aux = (void*)uablock;
910 
911 		return nbytes;
912 	}
913 
914 	case Qctl: {
915 		char str[128];
916 
917 		tv = &tvs[DEV(c->qid)];
918 		snprint(str, sizeof str, "%dx%dx%d %s channel %d %s\n",
919 			ntsc_hactive, ntsc_vactive, getbitspp(tv),
920 			getcolormode(tv->cfmt), tv->channel, 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,
936 					((ulong *)bt848)[i]);
937 			if (tv->bt878) {
938 				bt848 = tv->bt878;
939 
940 				for (i = 0; i < 0x300 >> 2; i++)
941 					p = seprint(p, e, "%.3X %.8ulX\n",
942 						i << 2, ((ulong *)bt848)[i]);
943 			}
944 
945 			regslen = p - regs;
946 		}
947 
948 		if (offset >= regslen)
949 			return 0;
950 		if (offset + n > regslen)
951 			n = regslen - offset;
952 
953 		return readstr(offset, a, n, &regs[offset]);
954 
955 	default:
956 		n = 0;
957 		break;
958 	}
959 	return n;
960 }
961 
962 static long
tvwrite(Chan * c,void * a,long n,vlong)963 tvwrite(Chan *c, void *a, long n, vlong)
964 {
965 	Cmdbuf *cb;
966 	Cmdtab *ct;
967 	Tv *tv;
968 
969 	tv = &tvs[DEV(c->qid)];
970 	switch(TYPE(c->qid)) {
971 	case Qctl:
972 		cb = parsecmd(a, n);
973 		if(waserror()){
974 			free(cb);
975 			nexterror();
976 		}
977 		ct = lookupcmd(cb, tvctlmsg, nelem(tvctlmsg));
978 		switch (ct->index) {
979 		case CMvstart:
980 			vstart(tv, (int)strtol(cb->f[1], (char **)nil, 0),
981 				ntsc_hactive, ntsc_vactive, ntsc_hactive);
982 			break;
983 
984 		case CMastart:
985 			astart(tv, cb->f[1], (uint)strtol(cb->f[2], (char **)nil, 0),
986 				(uint)strtol(cb->f[3], (char **)nil, 0),
987 				(uint)strtol(cb->f[4], (char **)nil, 0));
988 			break;
989 
990 		case CMastop:
991 			astop(tv);
992 			break;
993 
994 		case CMvgastart:
995 			vgastart(tv, strtoul(cb->f[1], (char **)nil, 0),
996 				(int)strtoul(cb->f[2], (char **)nil, 0));
997 			break;
998 
999 		case CMvstop:
1000 			vstop(tv);
1001 			break;
1002 
1003 		case CMchannel:
1004 			frequency(tv, (int)strtol(cb->f[1], (char **)nil, 0),
1005 				(int)strtol(cb->f[2], (char **)nil, 0));
1006 			break;
1007 
1008 		case CMcolormode:
1009 			colormode(tv, cb->f[1]);
1010 			break;
1011 
1012 		case CMvolume:
1013 			if (!tv->msp)
1014 				error("#V: No volume control");
1015 
1016 			mspvolume(tv, 0, (int)strtol(cb->f[1], (char **)nil, 0),
1017 				(int)strtol(cb->f[2], (char **)nil, 0));
1018 			break;
1019 
1020 		case CMmute:
1021 			if (!tv->msp)
1022 				error("#V: No volume control");
1023 
1024 			mspvolume(tv, 1, 0, 0);
1025 			break;
1026 		}
1027 		poperror();
1028 		free(cb);
1029 		break;
1030 
1031 	default:
1032 		error(Eio);
1033 	}
1034 	return n;
1035 }
1036 
1037 Dev tvdevtab = {
1038 	'V',
1039 	"tv",
1040 
1041 	devreset,
1042 	tvinit,
1043 	devshutdown,
1044 	tvattach,
1045 	tvwalk,
1046 	tvstat,
1047 	tvopen,
1048 	devcreate,
1049 	tvclose,
1050 	tvread,
1051 	devbread,
1052 	tvwrite,
1053 	devbwrite,
1054 	devremove,
1055 	devwstat,
1056 };
1057 
1058 static void
tvinterrupt(Ureg *,Tv * tv)1059 tvinterrupt(Ureg *, Tv *tv)
1060 {
1061 	Bt848 *bt848 = tv->bt848, *bt878 = tv->bt878;
1062 
1063 	for (;;) {
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 		if ((vstat & intstat_scerr) == intstat_scerr) {
1100 			iprint("int: scerr\n");
1101 			bt848->gpiodmactl &=
1102 				~(gpiodmactl_riscenable|gpiodmactl_fifoenable);
1103 			bt848->gpiodmactl |= gpiodmactl_fifoenable;
1104 			bt848->gpiodmactl |= gpiodmactl_riscenable;
1105 			vstat &= ~intstat_scerr;
1106 		}
1107 
1108 		if ((vstat & intstat_risci) == intstat_risci) {
1109 			tv->lvframe = fnum;
1110 			vstat &= ~intstat_risci;
1111 		}
1112 
1113 		if ((vstat & intstat_ocerr) == intstat_ocerr) {
1114 			iprint("int: ocerr\n");
1115 			vstat &= ~intstat_ocerr;
1116 		}
1117 
1118 		if ((vstat & intstat_fbus) == intstat_fbus) {
1119 			iprint("int: fbus\n");
1120 			vstat &= ~intstat_fbus;
1121 		}
1122 
1123 		if (vstat)
1124 			iprint("int: (v) ignored interrupts %.8ulX\n", vstat);
1125 
1126 		if ((astat & intstat_risci) == intstat_risci) {
1127 			tv->narblocks++;
1128 			if ((tv->narblocks % 100) == 0)
1129 				print("a");
1130 			wakeup(tv);
1131 			astat &= ~intstat_risci;
1132 		}
1133 
1134 		if ((astat & intstat_fdsr) == intstat_fdsr) {
1135 			iprint("int: (a) fdsr\n");
1136 			bt848->gpiodmactl &=
1137 				~(gpiodmactl_acapenable |
1138 					gpiodmactl_riscenable | gpiodmactl_fifoenable);
1139 			astat &= ~intstat_fdsr;
1140 		}
1141 
1142 		if (astat)
1143 			iprint("int: (a) ignored interrupts %.8ulX\n", astat);
1144 	}
1145 }
1146 
1147 static int
i2cread(Tv * tv,uchar off,uchar * v)1148 i2cread(Tv *tv, uchar off, uchar *v)
1149 {
1150 	Bt848 *bt848 = tv->bt848;
1151 	ulong intstat;
1152 	int i;
1153 
1154 	bt848->intstat	= intstat_i2cdone;
1155 	bt848->i2c = (off << 24) | tv->i2ccmd;
1156 
1157 	intstat = -1;
1158 	for (i = 0; i != 1000; i++) {
1159 		if ((intstat = bt848->intstat) & intstat_i2cdone)
1160 			break;
1161 		microdelay(1000);
1162 	}
1163 
1164 	if (i == 1000) {
1165 		print("i2cread: timeout\n");
1166 		return 0;
1167 	}
1168 
1169 	if ((intstat & intstat_i2crack) == 0)
1170 		return 0;
1171 
1172 	*v = bt848->i2c >> 8;
1173 	return 1;
1174 }
1175 
1176 static int
i2cwrite(Tv * tv,uchar addr,uchar sub,uchar data,int both)1177 i2cwrite(Tv *tv, uchar addr, uchar sub, uchar data, int both)
1178 {
1179 	Bt848 *bt848 = tv->bt848;
1180 	ulong intstat, d;
1181 	int i;
1182 
1183 	bt848->intstat	= intstat_i2cdone;
1184 	d = (addr << 24) | (sub << 16) | tv->i2ccmd;
1185 	if (both)
1186 		d |= (data << 8) | i2c_bt848w3b;
1187 	bt848->i2c = d;
1188 
1189 	intstat = 0;
1190 	for (i = 0; i != 1000; i++) {
1191 		if ((intstat = bt848->intstat) & intstat_i2cdone)
1192 			break;
1193 		microdelay(1000);
1194 	}
1195 
1196 	if (i == i2c_timeout) {
1197 		print("i2cwrite: timeout\n");
1198 		return 0;
1199 	}
1200 
1201 	if ((intstat & intstat_i2crack) == 0)
1202 		return 0;
1203 
1204 	return 1;
1205 }
1206 
1207 static ulong *
riscpacked(ulong pa,int fnum,int w,int h,int stride,ulong ** lastjmp)1208 riscpacked(ulong pa, int fnum, int w, int h, int stride, ulong **lastjmp)
1209 {
1210 	ulong *p, *pbase;
1211 	int i;
1212 
1213 	pbase = p = (ulong *)malloc((h + 6) * 2 * sizeof(ulong));
1214 	assert(p);
1215 
1216 	assert(w <= 0x7FF);
1217 
1218 	*p++ = riscsync | riscsync_resync | riscsync_vre;
1219 	*p++ = 0;
1220 
1221 	*p++ = riscsync | riscsync_fm1;
1222 	*p++ = 0;
1223 
1224 	for (i = 0; i != h / 2; i++) {
1225 		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
1226 		*p++ = pa + i * 2 * stride;
1227 	}
1228 
1229 	*p++ = riscsync | riscsync_resync | riscsync_vro;
1230 	*p++ = 0;
1231 
1232 	*p++ = riscsync | riscsync_fm1;
1233 	*p++ = 0;
1234 
1235 	for (i = 0; i != h / 2; i++) {
1236 		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
1237 		*p++ = pa + (i * 2 + 1) * stride;
1238 	}
1239 
1240 	/* reset status.  you really need two instructions ;-(. */
1241 	*p++ = riscjmp | (0xf << risclabelshift_reset);
1242 	*p++ = PADDR(p);
1243 	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
1244 	*lastjmp = p;
1245 
1246 	return pbase;
1247 }
1248 
1249 static ulong *
riscplanar411(ulong pa,int fnum,int w,int h,ulong ** lastjmp)1250 riscplanar411(ulong pa, int fnum, int w, int h, ulong **lastjmp)
1251 {
1252 	ulong *p, *pbase, Cw, Yw, Ch;
1253 	uchar *Ybase, *Cbbase, *Crbase;
1254 	int i, bitspp;
1255 
1256 	bitspp = 6;
1257 	assert(w * bitspp / 8 <= 0x7FF);
1258 	pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
1259 	assert(p);
1260 
1261 	Yw = w;
1262 	Ybase = (uchar *)pa;
1263 	Cw = w >> 1;
1264 	Ch = h >> 1;
1265 	Cbbase = Ybase + Yw * h;
1266 	Crbase = Cbbase + Cw * Ch;
1267 
1268 	*p++ = riscsync | riscsync_resync | riscsync_vre;
1269 	*p++ = 0;
1270 
1271 	*p++ = riscsync | riscsync_fm3;
1272 	*p++ = 0;
1273 
1274 	for (i = 0; i != h / 2; i++) {
1275 		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
1276 		*p++ = (Cw << 16) | Cw;
1277 		*p++ = (ulong)(Ybase + i * 2 * Yw);
1278 		*p++ = (ulong)(Cbbase + i * Cw);	/* Do not interlace */
1279 		*p++ = (ulong)(Crbase + i * Cw);
1280 	}
1281 
1282 	*p++ = riscsync | riscsync_resync | riscsync_vro;
1283 	*p++ = 0;
1284 
1285 	*p++ = riscsync | riscsync_fm3;
1286 	*p++ = 0;
1287 
1288 	for (i = 0; i != h / 2; i++) {
1289 		*p++ = riscwrite1s23 | Yw | riscwrite_sol | riscwrite_eol;
1290 		*p++ = (Cw << 16) | Cw;
1291 		*p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
1292 	}
1293 
1294 	/* reset status.  you really need two instructions ;-(. */
1295 	*p++ = riscjmp | (0xf << risclabelshift_reset);
1296 	*p++ = PADDR(p);
1297 	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
1298 	*lastjmp = p;
1299 
1300 	return pbase;
1301 }
1302 
1303 static ulong *
riscplanar422(ulong pa,int fnum,int w,int h,ulong ** lastjmp)1304 riscplanar422(ulong pa, int fnum, int w, int h, ulong **lastjmp)
1305 {
1306 	ulong *p, *pbase, Cw, Yw;
1307 	uchar *Ybase, *Cbbase, *Crbase;
1308 	int i, bpp;
1309 
1310 	bpp = 2;
1311 	assert(w * bpp <= 0x7FF);
1312 	pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
1313 	assert(p);
1314 
1315 	Yw = w;
1316 	Ybase = (uchar *)pa;
1317 	Cw = w >> 1;
1318 	Cbbase = Ybase + Yw * h;
1319 	Crbase = Cbbase + Cw * h;
1320 
1321 	*p++ = riscsync | riscsync_resync | riscsync_vre;
1322 	*p++ = 0;
1323 
1324 	*p++ = riscsync | riscsync_fm3;
1325 	*p++ = 0;
1326 
1327 	for (i = 0; i != h / 2; i++) {
1328 		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
1329 		*p++ = (Cw << 16) | Cw;
1330 		*p++ = (ulong)(Ybase + i * 2 * Yw);
1331 		*p++ = (ulong)(Cbbase + i * 2 * Cw);
1332 		*p++ = (ulong)(Crbase + i * 2 * Cw);
1333 	}
1334 
1335 	*p++ = riscsync | riscsync_resync | riscsync_vro;
1336 	*p++ = 0;
1337 
1338 	*p++ = riscsync | riscsync_fm3;
1339 	*p++ = 0;
1340 
1341 	for (i = 0; i != h / 2; i++) {
1342 		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
1343 		*p++ = (Cw << 16) | Cw;
1344 		*p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
1345 		*p++ = (ulong)(Cbbase + (i * 2 + 1) * Cw);
1346 		*p++ = (ulong)(Crbase + (i * 2 + 1) * Cw);
1347 	}
1348 
1349 	/* reset status.  you really need two instructions ;-(. */
1350 	*p++ = riscjmp | (0xf << risclabelshift_reset);
1351 	*p++ = PADDR(p);
1352 	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
1353 	*lastjmp = p;
1354 
1355 	return pbase;
1356 }
1357 
1358 static ulong *
riscaudio(ulong pa,int nblocks,int bsize)1359 riscaudio(ulong pa, int nblocks, int bsize)
1360 {
1361 	ulong *p, *pbase;
1362 	int i;
1363 
1364 	pbase = p = (ulong *)malloc((nblocks + 3) * 2 * sizeof(ulong));
1365 	assert(p);
1366 
1367 	*p++ = riscsync|riscsync_fm1;
1368 	*p++ = 0;
1369 
1370 	for (i = 0; i != nblocks; i++) {
1371 		*p++ = riscwrite | riscwrite_sol | riscwrite_eol | bsize | riscirq |
1372 			((i & 0xf) << risclabelshift_set) |
1373 			((~i & 0xf) << risclabelshift_reset);
1374 		*p++ = pa + i * bsize;
1375 	}
1376 
1377 	*p++ = riscsync | riscsync_vro;
1378 	*p++ = 0;
1379 	*p++ = riscjmp;
1380 	*p++ = PADDR(pbase);
1381 	USED(p);
1382 
1383 	return pbase;
1384 }
1385 
1386 
1387 static void
vactivate(Tv * tv,Frame * frames,int nframes)1388 vactivate(Tv *tv, Frame *frames, int nframes)
1389 {
1390 	Bt848 *bt848 = tv->bt848;
1391 
1392 	ilock(tv);
1393 	if (tv->frames) {
1394 		iunlock(tv);
1395 		error(Einuse);
1396 	}
1397 	poperror();
1398 
1399 	tv->frames = frames;
1400 	tv->nframes = nframes;
1401 
1402 	bt848->riscstrtadd = PADDR(tv->frames[0].fstart);
1403 	bt848->capctl |= capctl_captureodd|capctl_captureeven;
1404 	bt848->gpiodmactl |= gpiodmactl_fifoenable;
1405 	bt848->gpiodmactl |= gpiodmactl_riscenable;
1406 
1407 	iunlock(tv);
1408 }
1409 
1410 static void
vstart(Tv * tv,int nframes,int w,int h,int stride)1411 vstart(Tv *tv, int nframes, int w, int h, int stride)
1412 {
1413 	Frame *frames;
1414 	int bitspp, i, bpf;
1415 
1416 	if (nframes >= 0x10)
1417 		error(Ebadarg);
1418 
1419 	bitspp = getbitspp(tv);
1420 	bpf = w * h * bitspp / 8;
1421 
1422 	/* Add one as a spare. */
1423 	frames = (Frame *)malloc(nframes * sizeof(Frame));
1424 	assert(frames);
1425 	if (waserror()) {
1426 		for (i = 0; i != nframes; i++)
1427 			if (frames[i].fbase)
1428 				free(frames[i].fbase);
1429 		free(frames);
1430 		nexterror();
1431 	}
1432 	memset(frames, 0, nframes * sizeof(Frame));
1433 
1434 	for (i = 0; i != nframes; i++) {
1435 		if ((frames[i].fbase = (uchar *)malloc(bpf)) == nil)
1436 			error(Enomem);
1437 
1438 		switch (tv->cfmt) {
1439 		case colorfmt_YCbCr422:
1440 			frames[i].fstart = riscplanar422(PADDR(frames[i].fbase),				i, w, h, &frames[i].fjmp);
1441 			break;
1442 		case colorfmt_YCbCr411:
1443 			frames[i].fstart = riscplanar411(PADDR(frames[i].fbase),
1444 				i, w, h, &frames[i].fjmp);
1445 			break;
1446 		case colorfmt_rgb16:
1447 			frames[i].fstart = riscpacked(PADDR(frames[i].fbase), i,
1448 				w * bitspp / 8, h, stride * bitspp / 8,
1449 				&frames[i].fjmp);
1450 			break;
1451 		default:
1452 			panic("vstart: Unsupport colorformat\n");
1453 		}
1454 	}
1455 
1456 	for (i = 0; i != nframes; i++)
1457 		*frames[i].fjmp = PADDR(i == nframes - 1? frames[0].fstart:
1458 			frames[i + 1].fstart);
1459 
1460 	vactivate(tv, frames, nframes);
1461 }
1462 
1463 static void
astart(Tv * tv,char * input,uint rate,uint nab,uint nasz)1464 astart(Tv *tv, char *input, uint rate, uint nab, uint nasz)
1465 {
1466 	Bt848 *bt878 = tv->bt878;
1467 	ulong *arisc;
1468 	int selector;
1469 	uchar *abuf;
1470 	int s, d;
1471 
1472 	if (bt878 == nil || tv->amux == nil)
1473 		error("#V: Card does not support audio");
1474 
1475 	selector = 0;
1476 	if (!strcmp(input, "tv"))
1477 		selector = asel_tv;
1478 	else if (!strcmp(input, "radio"))
1479 		selector = asel_radio;
1480 	else if (!strcmp(input, "mic"))
1481 		selector = asel_mic;
1482 	else if (!strcmp(input, "smxc"))
1483 		selector = asel_smxc;
1484 	else
1485 		error("#V: Invalid input");
1486 
1487 	if (nasz > 0xfff)
1488 		error("#V: Audio block size too big (max 0xfff)");
1489 
1490 	abuf = (uchar *)malloc(nab * nasz * sizeof(uchar));
1491 	assert(abuf);
1492 	arisc = riscaudio(PADDR(abuf), nab, nasz);
1493 
1494 	ilock(tv);
1495 	if (tv->arisc) {
1496 		iunlock(tv);
1497 		free(abuf);
1498 		free(arisc);
1499 		error(Einuse);
1500 	}
1501 
1502 	tv->arisc = arisc;
1503 	tv->abuf = abuf;
1504 	tv->nablocks = nab;
1505 	tv->absize = nasz;
1506 
1507 	bt878->riscstrtadd = PADDR(tv->arisc);
1508 	bt878->packetlen = (nab << 16) | nasz;
1509 	bt878->intmask = intstat_scerr | intstat_ocerr | intstat_risci |
1510 			intstat_pabort | intstat_riperr | intstat_pperr |
1511 			intstat_fdsr | intstat_ftrgt | intstat_fbus;
1512 
1513 	/* Assume analog, 16bpp */
1514 	for (s = 0; s < 16; s++)
1515 		if (rate << s > Hwbase_ad * 4 / 15)
1516 			break;
1517 	for (d = 15; d >= 4; d--)
1518 		if (rate << s < Hwbase_ad * 4 / d)
1519 			break;
1520 
1521 	print("astart: sampleshift %d, decimation %d\n", s, d);
1522 
1523 	tv->narblocks = 0;
1524 	bt878->gpiodmactl = gpiodmactl_fifoenable |
1525 		gpiodmactl_riscenable | gpiodmactl_acapenable |
1526 		gpiodmactl_daes2 |		/* gpiodmactl_apwrdn | */
1527 		gpiodmactl_daiomda | d << 8 | 9 << 28 | selector << 24;
1528 	print("dmactl %.8ulX\n", bt878->gpiodmactl);
1529 	iunlock(tv);
1530 }
1531 
1532 static void
astop(Tv * tv)1533 astop(Tv *tv)
1534 {
1535 	Bt848 *bt878 = tv->bt878;
1536 
1537 	ilock(tv);
1538 	if (tv->aref.ref > 0) {
1539 		iunlock(tv);
1540 		error(Einuse);
1541 	}
1542 
1543 	if (tv->abuf) {
1544 		bt878->gpiodmactl &= ~gpiodmactl_riscenable;
1545 		bt878->gpiodmactl &= ~gpiodmactl_fifoenable;
1546 
1547 		free(tv->abuf);
1548 		tv->abuf = nil;
1549 		free(tv->arisc);
1550 		tv->arisc = nil;
1551 	}
1552 	iunlock(tv);
1553 }
1554 
1555 static void
vgastart(Tv * tv,ulong pa,int stride)1556 vgastart(Tv *tv, ulong pa, int stride)
1557 {
1558 	Frame *frame;
1559 
1560 	frame = (Frame *)malloc(sizeof(Frame));
1561 	assert(frame);
1562 	if (waserror()) {
1563 		free(frame);
1564 		nexterror();
1565 	}
1566 
1567 	frame->fbase = nil;
1568 	frame->fstart = riscpacked(pa, 0, ntsc_hactive * getbitspp(tv) / 8,
1569 		ntsc_vactive, stride * getbitspp(tv) / 8, &frame->fjmp);
1570 	*frame->fjmp = PADDR(frame->fstart);
1571 
1572 	vactivate(tv, frame, 1);
1573 }
1574 
1575 static void
vstop(Tv * tv)1576 vstop(Tv *tv)
1577 {
1578 	Bt848 *bt848 = tv->bt848;
1579 
1580 	ilock(tv);
1581 	if (tv->fref.ref > 0) {
1582 		iunlock(tv);
1583 		error(Einuse);
1584 	}
1585 
1586 	if (tv->frames) {
1587 		int i;
1588 
1589 		bt848->gpiodmactl &= ~gpiodmactl_riscenable;
1590 		bt848->gpiodmactl &= ~gpiodmactl_fifoenable;
1591 		bt848->capctl &= ~(capctl_captureodd|capctl_captureeven);
1592 
1593 		for (i = 0; i != tv->nframes; i++)
1594 			if (tv->frames[i].fbase)
1595 				free(tv->frames[i].fbase);
1596 		free(tv->frames);
1597 		tv->frames = nil;
1598 	}
1599 	iunlock(tv);
1600 }
1601 
1602 static long hrcfreq[] = {		/* HRC CATV frequencies */
1603 	    0,  7200,  5400,  6000,  6600,  7800,  8400, 17400,
1604 	18000, 18600, 19200, 19800, 20400, 21000, 12000, 12600,
1605 	13200, 13800, 14400, 15000, 15600, 16200, 16800, 21600,
1606 	22200, 22800, 23400, 24000, 24600, 25200, 25800, 26400,
1607 	27000, 27600, 28200, 28800, 29400, 30000, 30600, 31200,
1608 	31800, 32400, 33000, 33600, 34200, 34800, 35400, 36000,
1609 	36600, 37200, 37800, 38400, 39000, 39600, 40200, 40800,
1610 	41400, 42000, 42600, 43200, 43800, 44400, 45000, 45600,
1611 	46200, 46800, 47400, 48000, 48600, 49200, 49800, 50400,
1612 	51000, 51600, 52200, 52800, 53400, 54000, 54600, 55200,
1613 	55800, 56400, 57000, 57600, 58200, 58800, 59400, 60000,
1614 	60600, 61200, 61800, 62400, 63000, 63600, 64200,  9000,
1615 	 9600, 10200, 10800, 11400, 64800, 65400, 66000, 66600,
1616 	67200, 67800, 68400, 69000, 69600, 70200, 70800, 71400,
1617 	72000, 72600, 73200, 73800, 74400, 75000, 75600, 76200,
1618 	76800, 77400, 78000, 78600, 79200, 79800,
1619 };
1620 
1621 static void
frequency(Tv * tv,int channel,int finetune)1622 frequency(Tv *tv, int channel, int finetune)
1623 {
1624 	Tuner *tuner = tv->tuner;
1625 	long freq;
1626 	ushort div;
1627 	uchar cfg;
1628 
1629 	if (channel < 0 || channel > nelem(hrcfreq))
1630 		error(Ebadarg);
1631 
1632 	freq = (hrcfreq[channel] * Freqmultiplier) / 100;
1633 
1634 	if (freq < tuner->freq_vhfh)
1635 		cfg = tuner->VHF_L;
1636 	else if (freq < tuner->freq_uhf)
1637 		cfg = tuner->VHF_H;
1638 	else
1639 		cfg = tuner->UHF;
1640 
1641 	div = (freq + tuner->offs + finetune) & 0x7fff;
1642 
1643 	if (!i2cwrite(tv, tv->i2ctuneraddr, (div >> 8) & 0x7f, div, 1))
1644 		error(Eio);
1645 
1646 	if (!i2cwrite(tv, tv->i2ctuneraddr, tuner->cfg, cfg, 1))
1647 		error(Eio);
1648 
1649 	tv->channel = channel;
1650 	if (tv->msp)
1651 		msptune(tv);
1652 }
1653 
1654 static struct {
1655 	char	*cmode;
1656 	ulong	realmode;
1657 	ulong	cbits;
1658 } colormodes[] = {
1659 	{ "RGB16",	colorfmt_rgb16,		colorfmt_rgb16, },
1660 	{ "YCbCr422",	colorfmt_YCbCr422,	colorfmt_YCbCr422, },
1661 	{ "YCbCr411",	colorfmt_YCbCr411,	colorfmt_YCbCr422, },
1662 };
1663 
1664 static void
colormode(Tv * tv,char * colormode)1665 colormode(Tv *tv, char *colormode)
1666 {
1667 	Bt848 *bt848 = tv->bt848;
1668 	int i;
1669 
1670 	for (i = 0; i != nelem(colormodes); i++)
1671 		if (!strcmp(colormodes[i].cmode, colormode))
1672 			break;
1673 
1674 	if (i == nelem(colormodes))
1675 		error(Ebadarg);
1676 
1677 	tv->cfmt = colormodes[i].realmode;
1678 	bt848->colorfmt = colormodes[i].cbits;
1679 }
1680 
1681 static int
getbitspp(Tv * tv)1682 getbitspp(Tv *tv)
1683 {
1684 	switch (tv->cfmt) {
1685 	case colorfmt_rgb16:
1686 	case colorfmt_YCbCr422:
1687 		return 16;
1688 	case colorfmt_YCbCr411:
1689 		return 12;
1690 	default:
1691 		error("getbitspp: Unsupport color format\n");
1692 	}
1693 	return -1;
1694 }
1695 
1696 static char *
getcolormode(ulong cmode)1697 getcolormode(ulong cmode)
1698 {
1699 	switch (cmode) {
1700 	case colorfmt_rgb16:
1701 		return "RGB16";
1702 	case colorfmt_YCbCr411:
1703 		return "YCbCr411";
1704 	case colorfmt_YCbCr422:
1705 		return (cmode == colorfmt_YCbCr422)? "YCbCr422": "YCbCr411";
1706 	default:
1707 		error("getcolormode: Unsupport color format\n");
1708 	}
1709 	return nil;
1710 }
1711 
1712 static void
i2c_set(Tv * tv,int scl,int sda)1713 i2c_set(Tv *tv, int scl, int sda)
1714 {
1715 	Bt848 *bt848 = tv->bt848;
1716 	ulong d;
1717 
1718 	bt848->i2c = (scl << 1) | sda;
1719 	d = bt848->i2c;
1720 	USED(d);
1721 	microdelay(i2c_delay);
1722 }
1723 
1724 static uchar
i2c_getsda(Tv * tv)1725 i2c_getsda(Tv *tv)
1726 {
1727 	Bt848 *bt848 = tv->bt848;
1728 
1729 	return bt848->i2c & i2c_sda;
1730 }
1731 
1732 static void
i2c_start(Tv * tv)1733 i2c_start(Tv *tv)
1734 {
1735 	i2c_set(tv, 0, 1);
1736 	i2c_set(tv, 1, 1);
1737 	i2c_set(tv, 1, 0);
1738 	i2c_set(tv, 0, 0);
1739 }
1740 
1741 static void
i2c_stop(Tv * tv)1742 i2c_stop(Tv *tv)
1743 {
1744 	i2c_set(tv, 0, 0);
1745 	i2c_set(tv, 1, 0);
1746 	i2c_set(tv, 1, 1);
1747 }
1748 
1749 static void
i2c_bit(Tv * tv,int sda)1750 i2c_bit(Tv *tv, int sda)
1751 {
1752 	i2c_set(tv, 0, sda);
1753 	i2c_set(tv, 1, sda);
1754 	i2c_set(tv, 0, sda);
1755 }
1756 
1757 static int
i2c_getack(Tv * tv)1758 i2c_getack(Tv *tv)
1759 {
1760 	int ack;
1761 
1762 	i2c_set(tv, 0, 1);
1763 	i2c_set(tv, 1, 1);
1764 	ack = i2c_getsda(tv);
1765 	i2c_set(tv, 0, 1);
1766 	return ack;
1767 }
1768 
1769 static int
i2c_wr8(Tv * tv,uchar d,int wait)1770 i2c_wr8(Tv *tv, uchar d, int wait)
1771 {
1772 	int i, ack;
1773 
1774 	i2c_set(tv, 0, 0);
1775 	for (i = 0; i != 8; i++) {
1776 		i2c_bit(tv, (d & 0x80)? 1: 0);
1777 		d <<= 1;
1778 	}
1779 	if (wait)
1780 		microdelay(wait);
1781 
1782 	ack = i2c_getack(tv);
1783 	return ack == 0;
1784 }
1785 
1786 static uchar
i2c_rd8(Tv * tv,int lastbyte)1787 i2c_rd8(Tv *tv, int lastbyte)
1788 {
1789 	int i;
1790 	uchar d;
1791 
1792 	d = 0;
1793 	i2c_set(tv, 0, 1);
1794 	for (i = 0; i != 8; i++) {
1795 		i2c_set(tv, 1, 1);
1796 		d <<= 1;
1797 		if (i2c_getsda(tv))
1798 			d |= 1;
1799 		i2c_set(tv, 0, 1);
1800 	}
1801 
1802 	i2c_bit(tv, lastbyte? 1: 0);
1803 	return d;
1804 }
1805 
1806 static int
mspsend(Tv * tv,uchar * cmd,int ncmd)1807 mspsend(Tv *tv, uchar *cmd, int ncmd)
1808 {
1809 	int i, j, delay;
1810 
1811 	for (i = 0; i != 3; i++) {
1812 		delay = 2000;
1813 
1814 		i2c_start(tv);
1815 		for (j = 0; j != ncmd; j++) {
1816 			if (!i2c_wr8(tv, cmd[j], delay))
1817 				break;
1818 			delay = 0;
1819 		}
1820 		i2c_stop(tv);
1821 
1822 		if (j == ncmd)
1823 			return 1;
1824 
1825 		microdelay(10000);
1826 		print("mspsend: retrying\n");
1827 	}
1828 
1829 	return 0;
1830 }
1831 
1832 static int
mspwrite(Tv * tv,uchar sub,ushort reg,ushort v)1833 mspwrite(Tv *tv, uchar sub, ushort reg, ushort v)
1834 {
1835 	uchar b[6];
1836 
1837 	b[0] = i2c_msp3400;
1838 	b[1] = sub;
1839 	b[2] = reg >> 8;
1840 	b[3] = reg;
1841 	b[4] = v >> 8;
1842 	b[5] = v;
1843 	return mspsend(tv, b, sizeof b);
1844 }
1845 
1846 static int
mspread(Tv * tv,uchar sub,ushort reg,ushort * data)1847 mspread(Tv *tv, uchar sub, ushort reg, ushort *data)
1848 {
1849 	uchar b[4];
1850 	int i;
1851 
1852 	b[0] = i2c_msp3400;
1853 	b[1] = sub;
1854 	b[2] = reg >> 8;
1855 	b[3] = reg;
1856 
1857 	for (i = 0; i != 3; i++) {
1858 		i2c_start(tv);
1859 		if (!i2c_wr8(tv, b[0], 2000) ||
1860 			!i2c_wr8(tv, b[1] | 1, 0) ||
1861 			!i2c_wr8(tv, b[2], 0) ||
1862 			!i2c_wr8(tv, b[3], 0)) {
1863 
1864 			i2c_stop(tv);
1865 			microdelay(10000);
1866 			print("retrying\n");
1867 			continue;
1868 		}
1869 
1870 		i2c_start(tv);
1871 
1872 		if (!i2c_wr8(tv, b[0] | 1, 2000)) {
1873 			i2c_stop(tv);
1874 			continue;
1875 		}
1876 
1877 		*data  = i2c_rd8(tv, 0) << 8;
1878 		*data |= i2c_rd8(tv, 1);
1879 		i2c_stop(tv);
1880 		return 1;
1881 	}
1882 	return 0;
1883 }
1884 
1885 static uchar mspt_reset[] = { i2c_msp3400, 0, 0x80, 0 };
1886 static uchar mspt_on[] = { i2c_msp3400, 0, 0, 0 };
1887 
1888 static int
mspreset(Tv * tv)1889 mspreset(Tv *tv)
1890 {
1891 	ushort v, p;
1892 	Bt848 *bt848 = tv->bt848;
1893 	ulong b;
1894 
1895 	b = 1 << 5;
1896 	gpioenable(tv, ~b, b);
1897 	gpiowrite(tv, ~b, 0);
1898 	microdelay(2500);
1899 	gpiowrite(tv, ~b, b);
1900 
1901 	bt848->i2c = 0x80;
1902 
1903 	microdelay(2000);
1904 	mspsend(tv, mspt_reset, sizeof mspt_reset);
1905 
1906 	microdelay(2000);
1907 	if (!mspsend(tv, mspt_on, sizeof mspt_on)) {
1908 		print("#V: Cannot find MSP34x5G on the I2C bus (on)\n");
1909 		return 0;
1910 	}
1911 	microdelay(2000);
1912 
1913 	if (!mspread(tv, msp_bbp, 0x001e, &v)) {
1914 		print("#V: Cannot read MSP34xG5 chip version\n");
1915 		return 0;
1916 	}
1917 
1918 	if (!mspread(tv, msp_bbp, 0x001f, &p)) {
1919 		print("#V: Cannot read MSP34xG5 product code\n");
1920 		return 0;
1921 	}
1922 
1923 	print("#V: MSP34%dg ROM %.d, %d.%d\n",
1924 		(uchar)(p >> 8), (uchar)p, (uchar)(v >> 8), (uchar)v);
1925 
1926 	tv->msp = 1;
1927 	return 1;
1928 }
1929 
1930 static void
mspvolume(Tv * tv,int mute,int l,int r)1931 mspvolume(Tv *tv, int mute, int l, int r)
1932 {
1933 	short v, d;
1934 	ushort b;
1935 
1936 	if (mute) {
1937 		v = 0;
1938 		b = 0;
1939 	}
1940 	else {
1941 		tv->aleft = l;
1942 		tv->aright = r;
1943 		d = v = max(l, r);
1944 		if (d == 0)
1945 			d++;
1946 		b = ((r - l) * 0x7f) / d;
1947 	}
1948 
1949 	mspwrite(tv, msp_bbp, 0, v << 8);
1950 	mspwrite(tv, msp_bbp, 7, v? 0x4000: 0);
1951 	mspwrite(tv, msp_bbp, 1, b << 8);
1952 }
1953 
1954 static char *
mspaformat(int f)1955 mspaformat(int f)
1956 {
1957 	switch (f) {
1958 	case 0:
1959 		return "unknown";
1960 	case 2:
1961 	case 0x20:
1962 	case 0x30:
1963 		return "M-BTSC";
1964 	case 3:
1965 		return "B/G-FM";
1966 	case 4:
1967 	case 9:
1968 	case 0xB:
1969 		return "L-AM/NICAM D/Kn";
1970 	case 8:
1971 		return "B/G-NICAM";
1972 	case 0xA:
1973 		return "I";
1974 	case 0x40:
1975 		return "FM-Radio";
1976 	}
1977 	return "unknown format";
1978 }
1979 
1980 
1981 static void
msptune(Tv * tv)1982 msptune(Tv *tv)
1983 {
1984 	ushort d, s, nicam;
1985 	int i;
1986 
1987 	mspvolume(tv, 1, 0, 0);
1988 	if (!mspwrite(tv, msp_dem, 0x0030, 0x2033))
1989 		error("#V: Cannot set MODUS register");
1990 
1991 	if (!mspwrite(tv, msp_bbp, 0x0008, 0x0320))
1992 		error("#V: Cannot set loadspeaker input");
1993 
1994 	if (!mspwrite(tv, msp_dem, 0x0040, 0x0001))
1995 		error("#V: Cannot set I2S clock freq");
1996 	if (!mspwrite(tv, msp_bbp, 0x000d, 0x1900))
1997 		error("#V: Cannot set SCART prescale");
1998 	if (!mspwrite(tv, msp_bbp, 0x000e, 0x2403))
1999 		error("#V: Cannot set FM/AM prescale");
2000 	if (!mspwrite(tv, msp_bbp, 0x0010, 0x5a00))
2001 		error("#V: Cannot set NICAM prescale");
2002 	if (!mspwrite(tv, msp_dem, 0x0020, 0x0001))
2003 		error("#V: Cannot start auto detect");
2004 
2005 	for (d = (ushort)-1, i = 0; i != 10; i++) {
2006 		if (!mspread(tv, msp_dem, 0x007e, &d))
2007 			error("#V: Cannot get autodetect info MSP34xG5");
2008 
2009 		if (d == 0 || d < 0x800)
2010 			break;
2011 		delay(50);
2012 	}
2013 
2014 	if (!mspread(tv, msp_dem, 0x0200, &s))
2015 		error("#V: Cannot get status info MSP34xG5");
2016 
2017 	mspvolume(tv, 0, tv->aleft, tv->aright);
2018 
2019 	nicam = ((s >> 4) & 2) | ((s >> 9) & 1);
2020 	snprint(tv->ainfo, sizeof tv->ainfo, "%s %s %s",
2021 		mspaformat(d), (s & (1 << 6))? "stereo": "mono",
2022 		nicamstate[nicam]);
2023 }
2024 
2025 static void
i2cscan(Tv * tv)2026 i2cscan(Tv *tv)
2027 {
2028 	int i, ack;
2029 
2030 	for (i = 0; i < 0x100; i += 2) {
2031 		i2c_start(tv);
2032 		ack = i2c_wr8(tv, i, 0);
2033 		i2c_stop(tv);
2034 		if (ack)
2035 			print("i2c device @%.2uX\n", i);
2036 	}
2037 
2038 	for (i = 0xf0; i != 0xff; i++) {
2039 		i2c_start(tv);
2040 		ack = i2c_wr8(tv, i, 0);
2041 		i2c_stop(tv);
2042 		if (ack)
2043 			print("i2c device may be at @%.2uX\n", i);
2044 	}
2045 }
2046 
2047 static void
gpioenable(Tv * tv,ulong mask,ulong data)2048 gpioenable(Tv *tv, ulong mask, ulong data)
2049 {
2050 	Bt848 *bt848 = tv->bt848;
2051 
2052 	bt848->gpioouten = (bt848->gpioouten & mask) | data;
2053 }
2054 
2055 static void
gpiowrite(Tv * tv,ulong mask,ulong data)2056 gpiowrite(Tv *tv, ulong mask, ulong data)
2057 {
2058 	Bt848 *bt848 = tv->bt848;
2059 
2060 	bt848->gpiodata[0] = (bt848->gpiodata[0] & mask) | data;
2061 }
2062 
2063 static void
alteraoutput(Tv * tv)2064 alteraoutput(Tv *tv)
2065 {
2066 	if (tv->gpiostate == Gpiooutput)
2067 		return;
2068 
2069 	gpioenable(tv, ~0xffffff, 0x56ffff);
2070 	microdelay(10);
2071 	tv->gpiostate = Gpiooutput;
2072 }
2073 
2074 static void
alterainput(Tv * tv)2075 alterainput(Tv *tv)
2076 {
2077 	if (tv->gpiostate == Gpioinput)
2078 		return;
2079 
2080 	gpioenable(tv, ~0xffffff, 0x570000);
2081 	microdelay(10);
2082 	tv->gpiostate = Gpioinput;
2083 }
2084 
2085 static void
alterareg(Tv * tv,ulong reg)2086 alterareg(Tv *tv, ulong reg)
2087 {
2088 	if (tv->alterareg == reg)
2089 		return;
2090 
2091 	gpiowrite(tv, ~0x56ffff, (reg & 0x54ffff) | tv->alteraclock);
2092 	microdelay(10);
2093 	tv->alterareg = reg;
2094 }
2095 
2096 static void
alterawrite(Tv * tv,ulong reg,ushort data)2097 alterawrite(Tv *tv, ulong reg, ushort data)
2098 {
2099 	alteraoutput(tv);
2100 	alterareg(tv, reg);
2101 
2102 	tv->alteraclock ^= 0x20000;
2103 	gpiowrite(tv, ~0x56ffff, (reg & 0x540000) | data | tv->alteraclock);
2104 	microdelay(10);
2105 }
2106 
2107 static void
alteraread(Tv * tv,int reg,ushort * data)2108 alteraread(Tv *tv, int reg, ushort *data)
2109 {
2110 	Bt848 *bt848 = tv->bt848;
2111 
2112 	if (tv->alterareg != reg) {
2113 		alteraoutput(tv);
2114 		alterareg(tv, reg);
2115 	}
2116 	else {
2117 		gpioenable(tv, ~0xffffff, 0x560000);
2118 		microdelay(10);
2119 	}
2120 
2121 	alterainput(tv);
2122 	gpiowrite(tv, ~0x570000, (reg & 0x560000) | tv->alteraclock);
2123 	microdelay(10);
2124 	*data = (ushort)bt848->gpiodata[0];
2125 	microdelay(10);
2126 }
2127 
2128 static void
kfirloadu(Tv * tv,uchar * u,int ulen)2129 kfirloadu(Tv *tv, uchar *u, int ulen)
2130 {
2131 	Bt848 *bt848 = tv->bt848;
2132 	int i, j;
2133 
2134 	ilock(&tv->kfirlock);
2135 	bt848->gpioouten &= 0xff000000;
2136 	bt848->gpioouten |= gpio_altera_data |
2137 		gpio_altera_clock | gpio_altera_nconfig;
2138 	bt848->gpiodata[0] &= 0xff000000;
2139 	microdelay(10);
2140 	bt848->gpiodata[0] |= gpio_altera_nconfig;
2141 	microdelay(10);
2142 
2143 	/* Download the microcode */
2144 	for (i = 0; i != ulen; i++)
2145 		for (j = 0; j != 8; j++) {
2146 			bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
2147 			if (u[i] & 1)
2148 				bt848->gpiodata[0] |= gpio_altera_data;
2149 			bt848->gpiodata[0] |= gpio_altera_clock;
2150 			u[i] >>= 1;
2151 		}
2152 	bt848->gpiodata[0] &= ~gpio_altera_clock;
2153 	microdelay(100);
2154 
2155 	/* Initialize. */
2156 	for (i = 0; i != 30; i++) {
2157 		bt848->gpiodata[0] &= ~gpio_altera_clock;
2158 		bt848->gpiodata[0] |= gpio_altera_clock;
2159 	}
2160 	bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
2161 	iunlock(&tv->kfirlock);
2162 
2163 	tv->gpiostate = Gpioinit;
2164 }
2165 
2166 static void
kfirreset(Tv * tv)2167 kfirreset(Tv *tv)
2168 {
2169 	alterawrite(tv, 0, 0);
2170 	microdelay(10);
2171 	alterawrite(tv, 0x40000, 0);
2172 	microdelay(10);
2173 	alterawrite(tv, 0x40006, 0x80);
2174 	microdelay(10);
2175 	alterawrite(tv, 8, 1);
2176 	microdelay(10);
2177 	alterawrite(tv, 0x40004, 2);
2178 	microdelay(10);
2179 	alterawrite(tv, 4, 3);
2180 	microdelay(3);
2181 }
2182 
2183 static int
kfirinitialize(Tv * tv)2184 kfirinitialize(Tv *tv)
2185 {
2186 	/* Initialize parameters? */
2187 
2188 	tv->gpiostate = Gpioinit;
2189 	tv->alterareg = -1;
2190 	tv->alteraclock = 0x20000;
2191 	kfirloadu(tv, hcwAMC, sizeof hcwAMC);
2192 	kfirreset(tv);
2193 	return 1;
2194 }
2195