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