Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
 
817
static int
818
audioblock(void *)
819
{
820
	return 1;
821
}
822
 
823
static long
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
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
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
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
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 *
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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 *
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
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
1725
i2c_getsda(Tv *tv)
1726
{
1727
	Bt848 *bt848 = tv->bt848;
1728
 
1729
	return bt848->i2c & i2c_sda;
1730
}
1731
 
1732
static void
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
}