1 /*
2 * Boffin MPEG decoder
3 */
4 #include "u.h"
5 #include "../port/lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "../port/error.h"
10 #include "zoran.h"
11 #include "crystal.h"
12 #include "io.h"
13
14 enum
15 {
16
17 CPUACCCTRL = 0x20, /* Trident Window Chip control registers */
18 CPUACCMD = 0x21,
19 BNKADR = 0x22,
20 SYSCONFIG = 0x23,
21 VGACOMP = 0x24,
22 VGAMASK = 0x25,
23 VIDCOMPL = 0x26,
24 VIDCOMPH = 0x27,
25 MOS = 0x28,
26 DISPCTRL = 0x29,
27 CAPCTRL = 0x2a,
28 OVLKT = 0x2b,
29 OVLWINHSTRT = 0x2c,
30 OVLWINVSTRT = 0x2d,
31 OVLWINHEND = 0x2e,
32 OVLWINVEND = 0x2f,
33 RESERVED1 = 0x30,
34 RESERVED2 = 0x31,
35 DISPWINVSTRT1 = 0x32,
36 DISPWINVSTRT2 = 0x33,
37 DISPWINVEND = 0x34,
38 DISPWINHSTRT1 = 0x35,
39 DISPWINHSTRT2 = 0x36,
40 DISPWINHEND = 0x37,
41 CAPWINVSTRT = 0x38,
42 CAPWINHSTRT = 0x39,
43 CAPWINVMF = 0x3a,
44 CAPWINHMF = 0x3b,
45 RESERVED3 = 0x3c,
46 CAPMASK = 0x3d,
47 BNKPOLATION = 0x3e,
48 SYNCPOL = 0x3f,
49 DISPVTOTAL = 0x40,
50 DISPHTOTAL = 0x41,
51 DISPVSTRT = 0x42,
52 DISPVEND = 0x43,
53 DISPHSTRT = 0x44,
54 DISPHEND = 0x45,
55 DISPSYNCW = 0x46,
56 DISPCRTCCTRL = 0x47,
57 CAPVTOTAL = 0x48,
58 CAPHTOTAL = 0x49,
59 CAPVSTRT = 0x4a,
60 CAPVEND = 0x4b,
61 CAPHSTRT = 0x4c,
62 CAPHEND = 0x4d,
63 CAPSYNCW = 0x4e,
64 CAPCRTCCTRL = 0x4f,
65 VIDLUTDACRW = 0x50,
66 VIDLUTDACRW0 = (VIDLUTDACRW),
67 VIDLUTDACRW1 = (VIDLUTDACRW+1),
68 VIDLUTDACRW2 = (VIDLUTDACRW+2),
69 VIDLUTDACRW3 = (VIDLUTDACRW+3),
70 VIDLUTDACRW4 = (VIDLUTDACRW+4),
71 VIDLUTDACRW5 = (VIDLUTDACRW+5),
72 VIDLUTDACRW6 = (VIDLUTDACRW+6),
73 VIDLUTDACRW7 = (VIDLUTDACRW+7),
74 VGALUTDACRW = 0x58,
75 VGALUTDACRW0 = (VGALUTDACRW),
76 VGALUTDACRW1 = (VGALUTDACRW+1),
77 VGALUTDACRW2 = (VGALUTDACRW+2),
78 VGALUTDACRW3 = (VGALUTDACRW+3),
79 VGALUTDACRW4 = (VGALUTDACRW+4),
80 VGALUTDACRW5 = (VGALUTDACRW+5),
81 VGALUTDACRW6 = (VGALUTDACRW+6),
82 VGALUTDACRW7 = (VGALUTDACRW+7),
83 HZOOMF = 0x60,
84 VZOOMF = 0x61,
85 DELAY1 = 0x62,
86 DELAY2 = 0x63,
87
88 TRILO = 0,
89 TRIHI = 1,
90 TRIINDEX = 2,
91
92 SCL = 0x02,
93 SDA = 0x01,
94 I2CR = 0x2B,
95 SAA7110 = 0x9c,
96 WRITE_C = 0x00,
97 I2DLY = 5,
98 };
99
100 enum
101 {
102 ZR36100 = 0x1e0,
103 ZRIRQ = 15,
104 ZRDMA = 6,
105
106 ZRIDREG = 4, /* offset */
107 ZRMACH210 = 6, /* offset */
108 ZRREG0 = 8, /* offset */
109 ZRREG1 = 10, /* offset */
110 ZRSR = ZRREG1, /* offset */
111 ZRRDY = (1<<3),
112 ZRIDLE = (1<<2),
113 ZRREG2 = 12, /* offset */
114 ZRREG3 = 14, /* offset */
115
116 SIFwidth = 320,
117 SIFheight = 240,
118
119 IDPCOUNT = 3064,
120 PMDPCOUNT = 2048,
121 SVMDPCOUNT = 2048,
122
123 HIWAT = 2*128*1024,
124 DMABLK = 16384,
125 };
126
127 static struct {
128 int zrport;
129 int irq;
130 int dma;
131 int trport;
132 } mpegconf;
133
134 static char Evmode[] = "video format not supported";
135 static char Eaudio[] = "invalid audio layer";
136 static char Earate[] = "bad audio sample rate";
137
138 /* Status bits depend on board revision */
139 static short STDBY;
140 static short VIDSEL;
141 static short VSNIRQn;
142 static short INTENAn;
143 static short DSPBOOT;
144 static short DSPRST;
145 static short MPGRST;
146 static int machsr;
147 static int dopen;
148 static int started;
149 static int stop;
150 static int pause;
151 static int sp2br;
152 static int sp2cd;
153 static char properties[] = "video mpeg1,sif\naudio musicam,I musicam,II\n";
154 static void inittrident(void);
155 static int initzoran(void);
156 static void initcrystal(void);
157 static void mpegintr(Ureg*, void*);
158 static void setwindow(int, char**);
159 static void freebufs(void);
160 static int mkbuf(char*, int);
161
162 typedef struct Buf Buf;
163 struct Buf
164 {
165 int nchar;
166 uchar* ptr;
167 Buf* link;
168 uchar data[1];
169 };
170
171 static struct
172 {
173 Lock;
174 int qlen;
175 Buf* head;
176 Buf* tail;
177 Rendez flow;
178 } bqueue;
179
180 static int
zrstatus(void)181 zrstatus(void)
182 {
183 return ins(mpegconf.zrport+ZRSR) & 0xf;
184 }
185
186 static int
zrwaitrdy(int timo,char * msg)187 zrwaitrdy(int timo, char *msg)
188 {
189 int i;
190
191 for(i = 0; i < timo; i++)
192 if(ins(mpegconf.zrport+ZRSR) & ZRRDY)
193 return 0;
194
195 print("devmpeg: device not ready %s\n", msg);
196 return 1;
197 }
198
199 static void
zrdma(Buf * b)200 zrdma(Buf *b)
201 {
202 int n;
203
204 n = dmasetup(mpegconf.dma, b->ptr, b->nchar, 0);
205 b->ptr += n;
206 b->nchar -= n;
207 bqueue.qlen -= n;
208 }
209
210 static void
triwr(int reg,int val)211 triwr(int reg, int val)
212 {
213 outb(mpegconf.trport+TRIINDEX, reg);
214 outb(mpegconf.trport+TRILO, val);
215 outb(mpegconf.trport+TRIHI, val>>8);
216 }
217
218 static int
trird(int reg)219 trird(int reg)
220 {
221 int v;
222
223 outb(mpegconf.trport+TRIINDEX, reg);
224 v = inb(mpegconf.trport+TRILO);
225 v |= inb(mpegconf.trport+TRIHI)<<8;
226
227 return v;
228 }
229
230 enum
231 {
232 Qdir,
233 Qdata,
234 Qctl,
235 };
236 static Dirtab mpegtab[]=
237 {
238 "mpeg", {Qdata, 0}, 0, 0666,
239 "mpegctl", {Qctl, 0}, 0, 0666,
240 };
241
242 static void
mpegreset(void)243 mpegreset(void)
244 {
245 ISAConf isa;
246
247 mpegconf.zrport = ZR36100;
248 mpegconf.irq = ZRIRQ;
249 mpegconf.dma = ZRDMA;
250
251 memset(&isa, 0, sizeof(isa));
252 if(isaconfig("mpeg", 0, &isa) == 0)
253 return;
254 if(isa.port)
255 mpegconf.zrport = isa.port;
256 if(isa.irq)
257 mpegconf.irq = isa.irq;
258 if(isa.dma)
259 mpegconf.dma = isa.dma;
260 dmainit(mpegconf.dma, 64*1024);
261 print("mpeg0: port 0x%uX, irq %d, dma %d\n",
262 mpegconf.zrport, mpegconf.irq, mpegconf.dma);
263 mpegconf.trport = mpegconf.zrport+0x100;
264 intrenable(VectorPIC+mpegconf.irq, mpegintr, 0, BUSUNKNOWN);
265 }
266
267 static void
mpeginit(void)268 mpeginit(void)
269 {
270 if(mpegconf.trport == 0)
271 return;
272
273 inittrident();
274 setwindow(0, 0);
275 }
276
277 static Chan*
mpegattach(char * spec)278 mpegattach(char *spec)
279 {
280 if(mpegconf.trport == 0)
281 error(Enodev);
282
283 return devattach('E', spec);
284 }
285
286 static int
mpegwalk(Chan * c,char * name)287 mpegwalk(Chan *c, char *name)
288 {
289 return devwalk(c, name, mpegtab, nelem(mpegtab), devgen);
290 }
291
292 static void
mpegstat(Chan * c,char * db)293 mpegstat(Chan *c, char *db)
294 {
295 devstat(c, db, mpegtab, nelem(mpegtab), devgen);
296 }
297
298 static Chan*
mpegopen(Chan * c,int omode)299 mpegopen(Chan *c, int omode)
300 {
301 switch(c->qid.path) {
302 default:
303 break;
304 case Qdata:
305 if(dopen)
306 error(Einuse);
307 dopen = 1;
308 break;
309 }
310 return devopen(c, omode, mpegtab, nelem(mpegtab), devgen);
311 }
312
313 static void
mpegclose(Chan * c)314 mpegclose(Chan *c)
315 {
316 int i;
317
318 switch(c->qid.path) {
319 default:
320 break;
321 case Qdata:
322 if((c->flag & COPEN) == 0)
323 break;
324 if(started) {
325 for(i = 0; i < 50; i++) {
326 if(ins(mpegconf.zrport+ZRSR) & ZRIDLE)
327 break;
328 tsleep(&up->sleep, return0, 0, 100);
329 }
330 }
331 if(stop != 0)
332 outs(mpegconf.zrport+ZRREG1, 0x1000);
333 microdelay(15);
334 outs(mpegconf.zrport+ZRREG1, 0x8000);
335 freebufs();
336 dopen = 0;
337 }
338 }
339
340 static long
mpegread(Chan * c,void * a,long n,ulong off)341 mpegread(Chan *c, void *a, long n, ulong off)
342 {
343 switch(c->qid.path & ~CHDIR){
344 default:
345 error(Eperm);
346 case Qdir:
347 return devdirread(c, a, n, mpegtab, nelem(mpegtab), devgen);
348 case Qctl:
349 return readstr(off, a, n, properties);
350 }
351 return 0;
352 }
353
354 #define SCALE(a, b) ((((a)<<10)/(b))-1024)
355 enum
356 {
357 CWINVF = 0x3ff,
358 CWINHF = 0x1da,
359 };
360
361 static void
setwindow(int nf,char ** field)362 setwindow(int nf, char **field)
363 {
364 int minx, miny, maxx, maxy, width, height;
365
366 if(field == 0) {
367 minx = 0;
368 miny = 0;
369 maxx = 0;
370 maxy = 0;
371 }
372 else {
373 if(nf != 5)
374 error(Ebadarg);
375
376 minx = strtoul(field[1], 0, 0);
377 miny = strtoul(field[2], 0, 0);
378 maxx = strtoul(field[3], 0, 0) + 8;
379 maxy = strtoul(field[4], 0, 0);
380 }
381
382 triwr(OVLWINHSTRT, minx);
383 triwr(OVLWINVSTRT, miny);
384 triwr(OVLWINHEND, maxx+12);
385 triwr(OVLWINVEND, maxy);
386
387 width = maxx - minx;
388 height = maxy - miny;
389 if(width >= SIFwidth) {
390 triwr(HZOOMF, SCALE(width, SIFwidth));
391 triwr(CAPWINHMF, CWINHF);
392 }
393 else {
394 triwr(HZOOMF, SCALE(SIFwidth, SIFwidth));
395 triwr(CAPWINHMF, width*CWINHF/SIFwidth);
396 }
397 if(height >= SIFheight) {
398 triwr(VZOOMF, SCALE(height, SIFheight));
399 triwr(CAPWINVMF, CWINVF);
400 }
401 else {
402 triwr(VZOOMF, SCALE(SIFheight, SIFheight));
403 triwr(CAPWINVMF, height*CWINVF/SIFheight);
404 }
405 }
406
407 static int
mpegflow(void *)408 mpegflow(void*)
409 {
410 return bqueue.qlen < HIWAT || stop;
411 }
412
413 static int
mkbuf(char * d,int n)414 mkbuf(char *d, int n)
415 {
416 Buf *b;
417
418 b = malloc(sizeof(Buf)+n);
419 if(b == 0)
420 return 0;
421
422 memmove(b->data, d, n);
423 b->ptr = b->data;
424 b->nchar = n;
425 b->link = 0;
426
427 ilock(&bqueue);
428 bqueue.qlen += n;
429 if(bqueue.head)
430 bqueue.tail->link = b;
431 else
432 bqueue.head = b;
433 bqueue.tail = b;
434 iunlock(&bqueue);
435
436 return 1;
437 }
438
439 static void
freebufs(void)440 freebufs(void)
441 {
442 Buf *next;
443
444 ilock(&bqueue);
445 bqueue.qlen = 0;
446 while(bqueue.head) {
447 next = bqueue.head->link;
448 free(bqueue.head);
449 bqueue.head = next;
450 }
451 iunlock(&bqueue);
452 }
453
454 typedef struct Audio Audio;
455 struct Audio {
456 int rate;
457 int cd;
458 int br;
459 };
460
461 static Audio AudioclkI[] =
462 {
463 64000, 0x000000bb, 0x00071797,
464 96000, 0x0000007d, 0x00071c71,
465 128000, 0x0000005d, 0x00070de1,
466 160000, 0x0000004b, 0x00071c71,
467 192000, 0x0000003e, 0x00070de1,
468 224000, 0x00000035, 0x00070906,
469 256000, 0x0000002e, 0x0006fa76,
470 288000, 0x00000029, 0x0006ff51,
471 320000, 0x00000025, 0x0007042b,
472 352000, 0x00000022, 0x00071797,
473 384000, 0x0000001f, 0x00070de1,
474 416000, 0x0000001c, 0x0006e70b,
475 448000, 0x0000001a, 0x0006e70b,
476 };
477
478 static Audio AudioclkII[] =
479 {
480 48000, 0x000000fa, 0x00071c71,
481 56000, 0x000000d6, 0x00071a04,
482 64000, 0x000000bb, 0x00071797,
483 80000, 0x00000096, 0x00071c71,
484 96000, 0x0000007d, 0x00071c71,
485 112000, 0x0000006b, 0x00071a04,
486 128000, 0x0000005d, 0x00070de1,
487 160000, 0x0000004b, 0x00071c71,
488 192000, 0x0000003e, 0x00070de1,
489 224000, 0x00000035, 0x00070906,
490 256000, 0x0000002e, 0x0006fa76,
491 320000, 0x00000025, 0x0007042b,
492 384000, 0x0000001f, 0x00070de1,
493 };
494
495 static long
mpegwrite(Chan * c,char * a,long n,vlong)496 mpegwrite(Chan *c, char *a, long n, vlong)
497 {
498 Audio *t;
499 int i, nf, l, x;
500 char buf[128], *field[10];
501
502 switch(c->qid.path & ~CHDIR) {
503 case Qctl:
504 if(n > sizeof(buf)-1)
505 n = sizeof(buf)-1;
506 memmove(buf, a, n);
507 buf[n] = '\0';
508
509 nf = getfields(buf, field, nelem(field), 1, " \t\n");
510 if(nf < 1)
511 error(Ebadarg);
512
513 if(strcmp(field[0], "stop") == 0) {
514 if(started == 0)
515 error("not started");
516 if(pause) {
517 pause = 0;
518 outs(mpegconf.zrport+ZRREG1, 0x9000);
519 }
520 stop = 1;
521 outs(mpegconf.zrport+ZRREG1, 0x1000);
522 microdelay(15);
523 outs(mpegconf.zrport+ZRREG1, 0x8000);
524 wakeup(&bqueue.flow);
525 return n;
526 }
527 if(strcmp(field[0], "pause") == 0) {
528 if(started == 0)
529 error("not started");
530 if(pause == 0) {
531 pause = 1;
532 outs(mpegconf.zrport+ZRREG1, 0x1000);
533 }
534 else {
535 pause = 0;
536 outs(mpegconf.zrport+ZRREG1, 0x9000);
537 }
538 return n;
539 }
540 if(strcmp(field[0], "window") == 0) {
541 setwindow(nf, field);
542 return n;
543 }
544 if(strcmp(field[0], "audio") == 0) {
545 if(nf < 3)
546 error(Ebadarg);
547 t = 0;
548 if(strcmp(field[1], "musicam,I") == 0)
549 t = AudioclkI;
550 else
551 if(strcmp(field[1], "musicam,II") == 0)
552 t = AudioclkII;
553 else
554 error(Eaudio);
555 x = strtoul(field[2], 0, 0);
556 for(i = 0; t[i].rate != 0; i++) {
557 if(t[i].rate == x) {
558 sp2cd = t[i].cd;
559 sp2br = t[i].br;
560 return n;
561 }
562 }
563 error(Earate);
564 }
565 if(strcmp(field[0], "video") == 0) {
566 if(nf != 3)
567 error(Ebadarg);
568 if(strcmp(field[1], "iso11172") != 0)
569 error(Evmode);
570 if(strcmp(field[2], "mpeg1,sif") != 0)
571 error(Evmode);
572 return n;
573 }
574 if(strcmp(field[0], "init") == 0) {
575 inittrident();
576 for(i = 0; i < 3; i++)
577 if(initzoran() != -1)
578 break;
579 initcrystal();
580 started = 0;
581 stop = 0;
582 pause = 0;
583 return n;
584 }
585 error(Ebadarg);
586 case Qdata:
587 if(n & 1)
588 error("odd write");
589
590 while(!mpegflow(0))
591 sleep(&bqueue.flow, mpegflow, 0);
592
593 if(stop)
594 error("stopped");
595
596 x = n;
597 while(x) {
598 l = x;
599 if(l > DMABLK)
600 l = DMABLK;
601 if(mkbuf(a, l) == 0)
602 error(Enomem);
603 x -= l;
604 a += l;
605 }
606 if(started || bqueue.qlen < (HIWAT*3)/4)
607 break;
608
609 zrdma(bqueue.head);
610 outs(mpegconf.zrport+ZRREG1, 0x0000);
611 outs(mpegconf.zrport+ZRREG1, 0x0000);
612 started = 1;
613 break;
614 default:
615 error(Ebadusefd);
616 }
617 return n;
618 }
619
620 Dev mpegdevtab = {
621 'E',
622 "mpeg",
623
624 mpegreset,
625 mpeginit,
626 mpegattach,
627 devdetach,
628 devclone,
629 mpegwalk,
630 mpegstat,
631 mpegopen,
632 devcreate,
633 mpegclose,
634 mpegread,
635 devbread,
636 mpegwrite,
637 devbwrite,
638 devremove,
639 devwstat,
640 };
641
642 static void
initctl(void)643 initctl(void)
644 {
645 int boardid;
646 static int done;
647
648 if(done)
649 return;
650
651 boardid = ins(mpegconf.zrport+ZRIDREG);
652 if(boardid == 0xE3E3) { /* REV c/d */
653 STDBY = 0x0000;
654 VIDSEL = 0x2020;
655 VSNIRQn = 0x1010;
656 INTENAn = 0x0808;
657 DSPBOOT = 0x0404;
658 DSPRST = 0x0202;
659 MPGRST = 0x0101;
660 }
661 else { /* REV b */
662 STDBY = 0x0404;
663 VIDSEL = 0x1010;
664 VSNIRQn = 0x8080;
665 INTENAn = 0x4040;
666 DSPBOOT = 0x0202;
667 DSPRST = 0x0101;
668 MPGRST = 0x2020;
669 }
670 done = 1;
671
672 }
673
674 /*
675 * nbl (reg 0x1[ab]) was 0x0022, nblf (reg 1[cd]) was 0x0006
676 */
677 static uchar
678 zrparam[] =
679 {
680 /* 00 */ 0xEF, 0x01, 0x01, 0x01, 0x80, 0x0E, 0x31, 0x00,
681 /* 08 */ 0x01, 0x60, 0x00, 0x00, 0x03, 0x5A, 0x00, 0x7A,
682 /* 10 */ 0x00, 0x10, 0x00, 0x08, 0x00, 0xF0, 0x00, 0x00,
683 /* 18 */ 0x02, 0x0D, 0x00, 0x1e, 0x00, 0x0a, 0x00, 0x02,
684 /* 20 */ 0x40, 0x06, 0x80, 0x00, 0x80, 0x00, 0x05, 0x9B,
685 /* 28 */ 0x07, 0x16, 0xFD, 0x25, 0xFE, 0xA0, 0x00, 0x00,
686 /* 30 */ 0x00, 0x07, 0x0d, 0xe1, 0x00, 0x00, 0x00, 0x3E,
687 /* 38 */ 0x00, 0x00, 0x09, 0x51, 0x00, 0x00, 0xCD, 0xFE,
688 /* 40 */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 /* 48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 /* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 /* 58 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 /* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 /* 68 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 /* 70 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 /* 78 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
696 };
697
698 static int
initzoran(void)699 initzoran(void)
700 {
701 int i, nbytes, zrs;
702
703 initctl();
704 freebufs();
705
706 machsr = DSPRST|VSNIRQn;
707 outs(mpegconf.zrport+ZRMACH210, machsr);
708 microdelay(4000);
709
710 machsr |= STDBY;
711 outs(mpegconf.zrport+ZRMACH210, machsr);
712 microdelay(4000);
713
714 machsr |= MPGRST;
715 outs(mpegconf.zrport+ZRMACH210, machsr);
716 microdelay(4000);
717 machsr &= ~MPGRST;
718 outs(mpegconf.zrport+ZRMACH210, machsr);
719 microdelay(4000);
720 machsr |= MPGRST;
721 outs(mpegconf.zrport+ZRMACH210, machsr);
722 microdelay(4000);
723
724 if(zrwaitrdy(2000, "load IDP"))
725 return -1;
726
727 for(i = 0; i < IDPCOUNT; i++)
728 outb(mpegconf.zrport+ZRREG2, zrmpeg1[i]);
729
730 if(((zrs = zrstatus()) & 3) != 3) {
731 /* print("devmpeg: error loading IDP sr=%2.2ux\n", zrs); */
732 USED(zrs);
733 return -1;
734 }
735
736 if(zrwaitrdy(2000, "load PMDP"))
737 return -1;
738
739 for(i = 0; i < PMDPCOUNT; i++)
740 outb(mpegconf.zrport+ZRREG3, zrmpeg2[i]);
741
742 if(((zrs = zrstatus()) & 3) != 3) {
743 /* print("devmpeg: error loading PMDP sr=%2.2ux\n", zrs); */
744 USED(zrs);
745 return -1;
746 }
747
748 zrparam[0x36] = sp2cd>>8;
749 zrparam[0x37] = sp2cd>>0;
750 zrparam[0x31] = sp2br>>16;
751 zrparam[0x32] = sp2br>>8;
752 zrparam[0x33] = sp2br>>0;
753
754 nbytes = 16;
755 for(i = 0; i < 128; i++) {
756 if(nbytes >= 16) {
757 if(zrwaitrdy(2000, "load parameters"))
758 return -1;
759 nbytes = 0;
760 }
761 outb(mpegconf.zrport+ZRREG0, zrparam[i]);
762 nbytes++;
763 }
764
765 if(zrwaitrdy(2000, "load SVMDP"))
766 return -1;
767
768 for(i = 0; i < SVMDPCOUNT; i++)
769 outb(mpegconf.zrport+ZRREG3, zrmpeg3s[i]);
770
771 if(((zrs = zrstatus()) & 3) != 3) {
772 /* print("devmpeg: error loading SVMDP sr=%2.2ux\n", zrs); */
773 USED(zrs);
774 return -1;
775 }
776 return 0;
777 }
778
779 static struct
780 {
781 short reg;
782 ushort val;
783 } trireg[] =
784 {
785 0x20, 0x0400,
786 0x21, 0x00e9,
787 0x22, 0x0000,
788 0x23, 0x07ee,
789 0x24, 0x0005,
790 0x25, 0xff00,
791 0x26, 0x0000,
792 0x27, 0x7fff,
793 0x28, 0x0004,
794 0x29, 0x88a0,
795 0x2a, 0x0011,
796 0x2b, 0x8540,
797 0x2c, 0x00c4,
798 0x2d, 0x00ac,
799 0x2e, 0x020f,
800 0x2f, 0x019d,
801 0x30, 0x00bd,
802 0x31, 0x00ff,
803 0x32, 0x0000,
804 0x33, 0x0000,
805 0x34, 0x03ff,
806 0x35, 0x0000,
807 0x36, 0x0000,
808 0x37, 0x03ff,
809 0x38, 0x0000,
810 0x39, 0x0000,
811 0x3a, 0x03ff,
812 0x3b, 0x01da,
813 0x3c, 0xe8ce,
814 0x3d, 0x2ac0,
815 0x3e, 0x891f,
816 0x3f, 0x3e25,
817 0x40, 0x03ff,
818 0x41, 0x01ff,
819 0x42, 0x001f,
820 0x43, 0x01ff,
821 0x44, 0x003b,
822 0x45, 0x0186,
823 0x46, 0x1d06,
824 0x47, 0x1a4f,
825 0x48, 0x020d,
826 0x49, 0x01ad,
827 0x4a, 0x001b,
828 0x4b, 0x01fd,
829 0x4c, 0x003a,
830 0x4d, 0x034b,
831 0x4e, 0x2006,
832 0x4f, 0x0083,
833 0x50, 0xef08,
834 0x51, 0xef3a,
835 0x52, 0xefff,
836 0x53, 0xef08,
837 0x54, 0xef08,
838 0x55, 0xef15,
839 0x56, 0xefc0,
840 0x57, 0xef08,
841 0x58, 0xefef,
842 0x59, 0xefef,
843 0x5a, 0xefef,
844 0x5b, 0xefef,
845 0x5c, 0xefef,
846 0x5d, 0xefef,
847 0x5e, 0xefef,
848 0x5f, 0xefef,
849 0x60, 0x0000,
850 0x61, 0x0004,
851 0x62, 0x0020,
852 0x63, 0x8080,
853 0x64, 0x0300,
854 -1
855 };
856
857 static void
clrI2C(uchar b)858 clrI2C(uchar b)
859 {
860 uchar t;
861
862 outb(mpegconf.trport+TRIINDEX, I2CR);
863 t = inb(mpegconf.trport+TRIHI);
864 t &= ~b;
865 outb(mpegconf.trport+TRIHI, t);
866 }
867
868 static void
setI2C(uchar b)869 setI2C(uchar b)
870 {
871 uchar t;
872
873 outb(mpegconf.trport+TRIINDEX, I2CR);
874 t = inb(mpegconf.trport+TRIHI);
875 t |= b;
876 outb(mpegconf.trport+TRIHI, t);
877 }
878
879 static void
startI2C(void)880 startI2C(void)
881 {
882 setI2C(SDA);
883 setI2C(SCL);
884 microdelay(I2DLY);
885 clrI2C(SDA);
886 microdelay(I2DLY);
887 clrI2C(SCL);
888 microdelay(I2DLY);
889 }
890
891 static void
endI2C(void)892 endI2C(void)
893 {
894 clrI2C(SDA);
895 clrI2C(SCL);
896 microdelay(I2DLY);
897 setI2C(SCL);
898 microdelay(I2DLY);
899 setI2C(SDA);
900 microdelay(I2DLY);
901 }
902
903 static void
wrI2Cbit(uchar b)904 wrI2Cbit(uchar b)
905 {
906 clrI2C(SDA);
907 clrI2C(SCL);
908 microdelay(I2DLY);
909 if(b & 1) {
910 setI2C(SDA);
911 microdelay(I2DLY);
912 setI2C(SCL);
913 microdelay(I2DLY);
914 clrI2C(SCL);
915 microdelay(I2DLY);
916 clrI2C(SDA);
917 microdelay(I2DLY);
918 }
919 else {
920 setI2C(SCL);
921 microdelay(I2DLY);
922 clrI2C(SCL);
923 microdelay(I2DLY);
924 }
925 }
926
927 static void
wrI2CB(unsigned char data)928 wrI2CB(unsigned char data)
929 {
930 int i;
931
932 for(i = 0; i < 8; i++)
933 wrI2Cbit(data >>(7-i));
934 }
935
936 static int
rdI2CBit(void)937 rdI2CBit(void)
938 {
939 int bit = 1;
940
941 setI2C(SDA);
942 clrI2C(SCL);
943 setI2C(SCL);
944 outb(mpegconf.trport+TRIINDEX, I2CR);
945 if(inb(mpegconf.trport+TRIHI) & SDA)
946 bit = 0;
947 clrI2C(SDA);
948 clrI2C(SCL);
949
950 return bit;
951 }
952
953 static int
wrI2CD(uchar data)954 wrI2CD(uchar data)
955 {
956 int r;
957 ulong s;
958
959 s = splhi();
960 wrI2CB(data);
961 r = rdI2CBit();
962 splx(s);
963 return r;
964 }
965
966 static uchar
967 setupSAA7110[] =
968 {
969 /* Digital */
970 0x4c, 0x3c, 0x0d, 0xef, 0xbd, 0xf0, 0x40, 0x03,
971 0xf8, 0xf8, 0x90, 0x90, 0x00, 0x02, 0x10, 0x77,
972 0x00, 0x2c, 0x40, 0x40, 0x3b, 0x10, 0xfc, 0xd2,
973 0xf0, 0x80,
974
975 /* Analog */
976 0xd9, 0x16, 0x40, 0x40, 0x80, 0x40, 0x80, 0x4f,
977 0xfe, 0x01, 0xcf, 0x0f, 0x03, 0x01, 0x81, 0x0a,
978 0x40, 0x35, 0x02, 0x8c, 0x03
979 };
980
981 static void
addrI2CB(int addr,int val)982 addrI2CB(int addr, int val)
983 {
984 ulong s;
985
986 s = splhi();
987 startI2C();
988 wrI2CD(SAA7110|WRITE_C);
989 wrI2CD(addr);
990 wrI2CD(val);
991 endI2C();
992 splx(s);
993 }
994
995 static void
inittrident(void)996 inittrident(void)
997 {
998 int i;
999
1000 for(i = 0; trireg[i].reg != -1; i++)
1001 triwr(trireg[i].reg, trireg[i].val);
1002
1003 for(i = 0; i < 47; i++)
1004 addrI2CB(i, setupSAA7110[i]);
1005 }
1006
1007 static void
initcrystal(void)1008 initcrystal(void)
1009 {
1010 int i;
1011 static int done;
1012
1013 if(done)
1014 return;
1015
1016 done = 1;
1017
1018 initctl();
1019
1020 /* Reboot the Musicam decoder */
1021 clrI2C(SCL);
1022 clrI2C(SDA);
1023 machsr |= DSPRST;
1024 outs(mpegconf.zrport+ZRMACH210, machsr);
1025 machsr |= DSPBOOT;
1026 outs(mpegconf.zrport+ZRMACH210, machsr);
1027 machsr &= ~DSPRST;
1028 outs(mpegconf.zrport+ZRMACH210, machsr);
1029 machsr |= DSPRST;
1030 outs(mpegconf.zrport+ZRMACH210, machsr);
1031 machsr &= ~DSPBOOT;
1032 outs(mpegconf.zrport+ZRMACH210, machsr);
1033
1034 startI2C();
1035 wrI2CD(0);
1036 for(i = 0; i < sizeof(crystal); i++ )
1037 wrI2CD(crystal[i]);
1038 endI2C();
1039 }
1040
1041 static void
mpegintr(Ureg *,void *)1042 mpegintr(Ureg*, void*)
1043 {
1044 Buf *b;
1045
1046 b = bqueue.head;
1047 if(b == 0 || dmadone(mpegconf.dma) == 0)
1048 return;
1049
1050 dmaend(mpegconf.dma);
1051 if(b->nchar == 0) {
1052 bqueue.head = b->link;
1053 free(b);
1054
1055 b = bqueue.head;
1056 if(b == 0) {
1057 started = 0;
1058 return;
1059 }
1060 }
1061 zrdma(b);
1062 wakeup(&bqueue.flow);
1063 }
1064