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