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 181 zrstatus(void) 182 { 183 return ins(mpegconf.zrport+ZRSR) & 0xf; 184 } 185 186 static int 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 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 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 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 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 268 mpeginit(void) 269 { 270 if(mpegconf.trport == 0) 271 return; 272 273 inittrident(); 274 setwindow(0, 0); 275 } 276 277 static Chan* 278 mpegattach(char *spec) 279 { 280 if(mpegconf.trport == 0) 281 error(Enodev); 282 283 return devattach('E', spec); 284 } 285 286 static int 287 mpegwalk(Chan *c, char *name) 288 { 289 return devwalk(c, name, mpegtab, nelem(mpegtab), devgen); 290 } 291 292 static void 293 mpegstat(Chan *c, char *db) 294 { 295 devstat(c, db, mpegtab, nelem(mpegtab), devgen); 296 } 297 298 static Chan* 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 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 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 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 408 mpegflow(void*) 409 { 410 return bqueue.qlen < HIWAT || stop; 411 } 412 413 static int 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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