diff options
| author | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
|---|---|---|
| committer | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
| commit | 78ee7d5717807e6ac779293d0d3c78341de6130a (patch) | |
| tree | a43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/pc/devtv.c | |
| parent | bdaf46cf45bbb59261da245d548a179d95a42768 (diff) | |
Move existing boards into subdits split per arch
Diffstat (limited to 'os/pc/devtv.c')
| -rw-r--r-- | os/pc/devtv.c | 1826 |
1 files changed, 0 insertions, 1826 deletions
diff --git a/os/pc/devtv.c b/os/pc/devtv.c deleted file mode 100644 index 5e45fa37..00000000 --- a/os/pc/devtv.c +++ /dev/null @@ -1,1826 +0,0 @@ -/* - * Driver for Hauppage TV board - * - * Control commands: - * - * init - * window %d %d %d %d - * colorkey %d %d %d %d %d %d - * capture %d %d %d %d - * capbrightness %d - * capcontrast %d - * capsaturation %d - * caphue %d - * capbw %d - * brightness %d - * contrast %d - * saturation %d - * source %d - * svideo %d - * format %d - * channel %d %d - * signal - * volume %d [ %d ] - * bass %d - * treble %d - * freeze %d - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "tv.h" - -#include <draw.h> - -enum { - MemSize= 1, - MemAddr= 0xB8000, - - CompressReg= -14, - - /* smart lock registers */ - SLReg1= -2, - SLReg2= -1, - - /* the Bt812 registers */ - Bt812Index= -5, - Bt812Data= -6, - - Bt2VideoPresent= 0x40, - Bt4ColorBars= 0x40, - Bt5YCFormat= 0x80, - Bt7TriState= 0x0C, - - /* VxP 500 registers */ - Vxp500Index= 0, - Vxp500Data= 1, - - /* video controller registers */ - MemoryWindowBaseAddrA= 0x14, - MemoryWindowBaseAddrB= 0x15, - MemoryPageReg= 0x16, - MemoryConfReg= 0x18, - ISAControl= 0x30, - I2CControl= 0x34, - InputVideoConfA= 0x38, - InputVideoConfB= 0x39, - ISASourceWindowWidthA= 0x3A, - ISASourceWindowWidthB= 0x3B, - ISASourceWindowHeightA= 0x3C, - ISASourceWindowHeightB= 0x3D, - InputHorzCropLeftA= 0x40, - InputHorzCropLeftB= 0x41, - InputHorzCropRightA= 0x44, - InputHorzCropRightB= 0x45, - InputHorzCropTopA= 0x48, - InputHorzCropTopB= 0x49, - InputHorzCropBottomA= 0x4C, - InputHorzCropBottomB= 0x4D, - InputHorzFilter= 0x50, - InputHorzScaleControlA= 0x54, - InputHorzScaleControlB= 0x55, - InputVertInterpolControl= 0x58, - InputVertScaleControlA= 0x5C, - InputVertScaleControlB= 0x5D, - InputFieldPixelBufStatus= 0x64, - VideoInputFrameBufDepthA= 0x68, - VideoInputFrameBufDepthB= 0x69, - AcquisitionControl= 0x6C, - AcquisitionAddrA= 0x70, - AcquisitionAddrB= 0x71, - AcquisitionAddrC= 0x72, - VideoBufferLayoutControl= 0x73, - CaptureControl= 0x80, - CaptureViewPortAddrA= 0x81, - CaptureViewPortAddrB= 0x82, - CaptureViewPortAddrC= 0x83, - CaptureViewPortWidthA= 0x84, - CaptureViewPortWidthB= 0x85, - CaptureViewPortHeightA= 0x86, - CaptureViewPortHeightB= 0x87, - CapturePixelBufLow= 0x88, - CapturePixelBufHigh= 0x89, - CaptureMultiBufDepthA= 0x8A, - CaptureMultiBufDepthB= 0x8B, - DisplayControl= 0x92, - VGAControl= 0x94, - OutputProcControlA= 0x96, - OutputProcControlB= 0x97, - DisplayViewPortStartAddrA= 0xA0, - DisplayViewPortStartAddrB= 0xA1, - DisplayViewPortStartAddrC= 0xA2, - DisplayViewPortWidthA= 0xA4, - DisplayViewPortWidthB= 0xA5, - DisplayViewPortHeightA= 0xA6, - DisplayViewPortHeightB= 0xA7, - DisplayViewPortOrigTopA= 0xA8, - DisplayViewPortOrigTopB= 0xA9, - DisplayViewPortOrigLeftA= 0xAA, - DisplayViewPortOrigLeftB= 0xAB, - DisplayWindowLeftA= 0xB0, - DisplayWindowLeftB= 0xB1, - DisplayWindowRightA= 0xB4, - DisplayWindowRightB= 0xB5, - DisplayWindowTopA= 0xB8, - DisplayWindowTopB= 0xB9, - DisplayWindowBottomA= 0xBC, - DisplayWindowBottomB= 0xBD, - OutputVertZoomControlA= 0xC0, - OutputVertZoomControlB= 0xC1, - OutputHorzZoomControlA= 0xC4, - OutputHorzZoomControlB= 0xC5, - BrightnessControl= 0xC8, - ContrastControl= 0xC9, - SaturationControl= 0xCA, - VideoOutIntrStatus= 0xD3, - - /* smart lock bits */ - PixelClk= 0x03, - SmartLock= 0x00, - FeatureConnector= 0x01, - Divider= 0x02, - Window= 0x08, - KeyWindow= 0x0C, - HSyncLow= 0x20, - VSyncLow= 0x40, - - ClkBit= 0x01, - DataBit= 0x02, - HoldBit= 0x04, - SelBit= 0x08, - DivControl= 0x40, - - /* i2c bus control bits */ - I2C_Clock= 0x02, - I2C_Data= 0x08, - I2C_RdClock= 0x10, - I2C_RdData= 0x20, - I2C_RdData_D= 0x40, - - /* I2C bus addresses */ - Adr5249= 0x22, /* teletext decoder */ - Adr8444= 0x48, /* 6-bit DAC (TDA 8444) */ - Adr6300= 0x80, /* sound fader (TEA 6300) */ - Adr6320= 0x80, /* sound fader (TEA 6320T) */ - AdrTuner= 0xC0, - - /* Philips audio chips */ - TEA6300= 0, - TEA6320T= 1, - - /* input formats */ - NTSC_M = 0, - NTSC_443 = 1, - External = 2, - - NTSCCropLeft= 36, /* NTSC 3.6 usec */ - NTSCCropRight= 558, /* NTSC 55.8 usec */ - - /* color control indices */ - Vxp500Brightness= 1, - Vxp500Contrast= 2, - Vxp500Saturation= 3, - Bt812Brightness= 4, - Bt812Contrast= 5, - Bt812Saturation= 6, - Bt812Hue= 7, - Bt812BW= 8, - - /* board revision numbers */ - RevisionPP= 0, - RevisionA= 1, - HighQ= 2, - - /* VGA controller registers */ - VGAMiscOut= 0x3CC, - VGAIndex= 0x3D4, - VGAData= 0x3D5, - VGAHorzTotal= 0x00, -}; - -enum { - Qdir, - Qdata, - Qctl, -}; - -static -Dirtab tvtab[]={ - ".", {Qdir, 0, QTDIR}, 0, 0555, - "tv", {Qdata, 0}, 0, 0666, - "tvctl", {Qctl, 0}, 0, 0666, -}; - -static -int ports[] = { /* board addresses */ - 0x51C, 0x53C, 0x55C, 0x57C, - 0x59C, 0x5BC, 0x5DC, 0x5FC -}; - -/* - * Default settings, settings between 0..100 - */ -static -int defaults[] = { - Vxp500Brightness, 0, - Vxp500Contrast, 54, - Vxp500Saturation, 54, - Bt812Brightness, 13, - Bt812Contrast, 57, - Bt812Saturation, 51, - Bt812Hue, 0, - Bt812BW, 0, -}; - -static int port; -static int soundchip; -static int boardrev; -static int left, right; -static int vsync, hsync; -static ulong xtalfreq; -static ushort cropleft, cropright; -static ushort cropbottom, croptop; -static Rectangle window, capwindow; - -static void setreg(int, int); -static void setbt812reg(int, int); -static void videoinit(void); -static void createwindow(Rectangle); -static void setcontrols(int, uchar); -static void setcolorkey(int, int, int, int, int, int); -static void soundinit(void); -static void setvolume(int, int); -static void setbass(int); -static void settreble(int); -static void setsoundsource(int); -static void tunerinit(void); -static void settuner(int, int); -static void setvideosource(int); -static int waitvideosignal(void); -static void freeze(int); -static void setsvideo(int); -static void setinputformat(int); -static void enablevideo(void); -static void *saveframe(int *); - -static int -min(int a, int b) -{ - return a < b ? a : b; -} - -static int -max(int a, int b) -{ - return a < b ? b : a; -} - -static int -present(int port) -{ - outb(port+Vxp500Index, 0xAA); - if (inb(port+Vxp500Index) != 0xAA) - return 0; - outb(port+Vxp500Index, 0x55); - outb(port+Vxp500Data, 0xAA); - if (inb(port+Vxp500Index) != 0x55) - return 0; - if (inb(port+Vxp500Data) != 0xAA) - return 0; - outb(port+Vxp500Data, 0x55); - if (inb(port+Vxp500Index) != 0x55) - return 0; - if (inb(port+Vxp500Data) != 0x55) - return 0; - return 1; -} - -static int -getvsync(void) -{ - int vslow, vshigh, s; - ushort timo; - - s = splhi(); - - outb(port+Vxp500Index, VideoOutIntrStatus); - - /* wait for VSync to go high then low */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & 2) break; - for (timo = ~0; timo; timo--) - if ((inb(port+Vxp500Data) & 2) == 0) break; - - /* count how long it stays low and how long it stays high */ - for (vslow = 0, timo = ~0; timo; timo--, vslow++) - if (inb(port+Vxp500Data) & 2) break; - for (vshigh = 0, timo = ~0; timo; timo--, vshigh++) - if ((inb(port+Vxp500Data) & 2) == 0) break; - splx(s); - - return vslow < vshigh; -} - -static int -gethsync(void) -{ - int hslow, hshigh, s; - ushort timo; - - s = splhi(); - - outb(port+Vxp500Index, VideoOutIntrStatus); - - /* wait for HSync to go high then low */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & 1) break; - for (timo = ~0; timo; timo--) - if ((inb(port+Vxp500Data) & 1) == 0) break; - - /* count how long it stays low and how long it stays high */ - for (hslow = 0, timo = ~0; timo; timo--, hslow++) - if (inb(port+Vxp500Data) & 1) break; - for (hshigh = 0, timo = ~0; timo; timo--, hshigh++) - if ((inb(port+Vxp500Data) & 1) == 0) break; - splx(s); - - return hslow < hshigh; -} - -static void -tvinit(void) -{ - int i; - - for (i = 0, port = 0; i < nelem(ports); i++) { - if (present(ports[i])) { - port = ports[i]; - break; - } - } - if (i == nelem(ports)) - return; - - /* - * the following routines are the prefered way to - * find out the sync polarities. Unfortunately, it - * doesn't always work. - */ -#ifndef VSync - vsync = getvsync(); - hsync = gethsync(); -#else - vsync = VSync; - hsync = HSync; -#endif - left = right = 80; - soundinit(); - tunerinit(); - videoinit(); -} - -static Chan* -tvattach(char *spec) -{ - if (port == 0) - error(Enonexist); - return devattach('V', spec); -} - -static Walkqid* -tvwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, tvtab, nelem(tvtab), devgen); -} - -static int -tvstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, tvtab, nelem(tvtab), devgen); -} - -static Chan* -tvopen(Chan *c, int omode) -{ - return devopen(c, omode, tvtab, nelem(tvtab), devgen); -} - -static void -tvclose(Chan *) -{ -} - -static long -tvread(Chan *c, void *a, long n, vlong offset) -{ - static void *frame; - static int size; - - USED(offset); - - switch((ulong)c->qid.path){ - case Qdir: - return devdirread(c, a, n, tvtab, nelem(tvtab), devgen); - case Qdata: - if (eqrect(capwindow, Rect(0, 0, 0, 0))) - error(Ebadarg); - if (offset == 0) - frame = saveframe(&size); - if (frame) { - if (n > size - offset) - n = size - offset; - memmove(a, (char *)frame + offset, n); - } else - error(Enovmem); - break; - default: - n=0; - break; - } - return n; -} - -static long -tvwrite(Chan *c, void *vp, long n, vlong offset) -{ - char buf[128], *field[10], *a; - int i, nf, source; - static Rectangle win; - static int hsize, size = 0; - static void *frame; - - USED(offset); - - a = vp; - switch((ulong)c->qid.path){ - case Qctl: - if (n > sizeof(buf)-1) - n = sizeof(buf)-1; - memmove(buf, a, n); - buf[n] = '\0'; - - nf = getfields(buf, field, nelem(field), 1, " \t"); - if (nf < 1) error(Ebadarg); - - if (strcmp(field[0], "init") == 0) { - window = Rect(0, 0, 0, 0); - capwindow = Rect(0, 0, 0, 0); - source = 0; /* video 0 input */ - setvideosource(source); - left = right = 80; - setsoundsource(source); - for (i = 0; i < nelem(defaults); i += 2) - setcontrols(defaults[i], defaults[i+1]); - } else if (strcmp(field[0], "colorkey") == 0) { - if (nf < 7) error(Ebadarg); - setcolorkey(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0), - strtoul(field[3], 0, 0), strtoul(field[4], 0, 0), - strtoul(field[5], 0, 0), strtoul(field[6], 0, 0)); - } else if (strcmp(field[0], "window") == 0) { - if (nf < 5) error(Ebadarg); - createwindow(Rect(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0), - strtoul(field[3], 0, 0), strtoul(field[4], 0, 0))); - setvolume(left, right); - } else if (strcmp(field[0], "capture") == 0) { - if (nf < 5) error(Ebadarg); - capwindow = Rect(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0), - strtoul(field[3], 0, 0), strtoul(field[4], 0, 0)); - } else if (strcmp(field[0], "freeze") == 0) { - if (nf < 2) error(Ebadarg); - freeze(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capbrightness") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Brightness, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capcontrast") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Contrast, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capsaturation") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Saturation, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "caphue") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Hue, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capbw") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812BW, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "brightness") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Vxp500Brightness, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "contrast") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Vxp500Contrast, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "saturation") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Vxp500Saturation, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "source") == 0) { - if (nf < 2) error(Ebadarg); - source = strtoul(field[1], 0, 0); - setvideosource(source); - setsoundsource(source); - } else if (strcmp(field[0], "svideo") == 0) { - if (nf < 2) error(Ebadarg); - setsvideo(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "format") == 0) { - if (nf < 2) error(Ebadarg); - setinputformat(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "channel") == 0) { - if (nf < 3) error(Ebadarg); - setvolume(0, 0); - settuner(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0)); - tsleep(&up->sleep, return0, 0, 300); - setvolume(left, right); - } else if (strcmp(field[0], "signal") == 0) { - if (!waitvideosignal()) - error(Etimedout); - } else if (strcmp(field[0], "volume") == 0) { - if (nf < 2) error(Ebadarg); - left = strtoul(field[1], 0, 0); - if (nf < 3) - right = left; - else - right = strtoul(field[2], 0, 0); - setvolume(left, right); - } else if (strcmp(field[0], "bass") == 0) { - if (nf < 2) error(Ebadarg); - setbass(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "treble") == 0) { - if (nf < 2) error(Ebadarg); - settreble(strtoul(field[1], 0, 0)); - } else - error(Ebadctl); - break; - default: - error(Ebadusefd); - } - return n; -} - - -Dev tvdevtab = { - 'V', - "tv", - - devreset, - tvinit, - devshutdown, - tvattach, - tvwalk, - tvstat, - tvopen, - devcreate, - tvclose, - tvread, - devbread, - tvwrite, - devbwrite, - devremove, - devwstat, -}; - -static void -setreg(int index, int data) -{ - outb(port+Vxp500Index, index); - outb(port+Vxp500Data, data); -} - -static unsigned int -getreg(int index) -{ - outb(port+Vxp500Index, index); - return inb(port+Vxp500Data); -} - -/* - * I2C routines - */ -static void -delayi2c(void) -{ - int i, val; - - /* delay for 4.5 usec to guarantee clock time */ - for (i = 0; i < 75; i++) { /* was 50 */ - val = inb(port+Vxp500Data); - USED(val); - } -} - -static int -waitSDA(void) -{ - ushort timo; - - /* wait for i2c clock to float high */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & I2C_RdData) - break; - if (!timo) print("devtv: waitSDA fell out of loop\n"); - return !timo; -} - -static int -waitSCL(void) -{ - ushort timo; - - /* wait for i2c clock to float high */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & I2C_RdClock) - break; - delayi2c(); - if (!timo) print("devtv: waitSCL fell out of loop\n"); - return !timo; -} - -static int -seti2cdata(int data) -{ - int b, reg, val; - int error; - - error = 0; - reg = inb(port+Vxp500Data); - for (b = 0x80; b; b >>= 1) { - if (data & b) - reg |= I2C_Data; - else - reg &= ~I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - reg &= ~I2C_Clock; - outb(port+Vxp500Data, reg); - delayi2c(); - } - reg |= I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - val = inb(port+Vxp500Data); - USED(val); - reg &= ~I2C_Clock; - outb(port+Vxp500Data, reg); - delayi2c(); - return error; -} - -static int -seti2creg(int id, int index, int data) -{ - int reg, error; - - error = 0; - /* set i2c control register to enable i2c clock and data lines */ - setreg(I2CControl, I2C_Data|I2C_Clock); - error |= waitSDA(); - error |= waitSCL(); - outb(port+Vxp500Data, I2C_Clock); - delayi2c(); - outb(port+Vxp500Data, 0); - delayi2c(); - - error |= seti2cdata(id); - error |= seti2cdata(index); - error |= seti2cdata(data); - - reg = inb(port+Vxp500Data); - reg &= ~I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - reg |= I2C_Data; - outb(port+Vxp500Data, reg); - error |= waitSDA(); - return error; -} - -static int -seti2cregs(int id, int index, int n, uchar *data) -{ - int reg, error; - - error = 0; - /* set i2c control register to enable i2c clock and data lines */ - setreg(I2CControl, I2C_Data|I2C_Clock); - error |= waitSDA(); - error |= waitSCL(); - outb(port+Vxp500Data, I2C_Clock); - delayi2c(); - outb(port+Vxp500Data, 0); - delayi2c(); - - /* send data */ - error |= seti2cdata(id); - error |= seti2cdata(index); - while (n--) - error |= seti2cdata(*data++); - - /* send stop */ - reg = inb(port+Vxp500Data); - reg &= ~I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - reg |= I2C_Data; - outb(port+Vxp500Data, reg); - error |= waitSDA(); - return error; -} - -/* - * Audio routines - */ -static void -setvolume(int left, int right) -{ - int vol, loudness = 0; - - if (soundchip == TEA6300) { - seti2creg(Adr6300, 0, (63L * left) / 100); - seti2creg(Adr6300, 1, (63L * right) / 100); - vol = (15L * max(left, right)) / 100; - seti2creg(Adr6300, 4, 0x30 | vol); - } else { - vol = (63L * max(left, right)) / 100; - seti2creg(Adr6320, 0, vol | (loudness << 6)); - seti2creg(Adr6320, 1, (63L * right) / 100); - seti2creg(Adr6320, 2, (63L * left) / 100); - } -} - -static void -setbass(int bass) -{ - if (soundchip == TEA6300) - seti2creg(Adr6300, 2, (15L * bass) / 100); - else - seti2creg(Adr6320, 5, max((31L * bass) / 100, 4)); -} - -static void -settreble(int treble) -{ - if (soundchip == TEA6300) - seti2creg(Adr6300, 3, (15L * treble) / 100); - else - seti2creg(Adr6320, 6, max((31L * treble) / 100, 7)); - -} - -static void -setsoundsource(int source) -{ - if (soundchip == TEA6300) - seti2creg(Adr6300, 5, 1 << source); - else - seti2creg(Adr6320, 7, source); - setbass(50); - settreble(50); - setvolume(left, right); -} - -static void -soundinit(void) -{ - if (seti2creg(Adr6320, 7, 0) && seti2creg(Adr6300, 4, 0)) - print("devtv: Audio init failed\n"); - - soundchip = AudioChip; - setvolume(0, 0); -} - -/* - * Tuner routines - */ -static -long hrcfreq[] = { /* HRC CATV frequencies */ - 0, 7200, 5400, 6000, 6600, 7800, 8400, 17400, - 18000, 18600, 19200, 19800, 20400, 21000, 12000, 12600, - 13200, 13800, 14400, 15000, 15600, 16200, 16800, 21600, - 22200, 22800, 23400, 24000, 24600, 25200, 25800, 26400, - 27000, 27600, 28200, 28800, 29400, 30000, 30600, 31200, - 31800, 32400, 33000, 33600, 34200, 34800, 35400, 36000, - 36600, 37200, 37800, 38400, 39000, 39600, 40200, 40800, - 41400, 42000, 42600, 43200, 43800, 44400, 45000, 45600, - 46200, 46800, 47400, 48000, 48600, 49200, 49800, 50400, - 51000, 51600, 52200, 52800, 53400, 54000, 54600, 55200, - 55800, 56400, 57000, 57600, 58200, 58800, 59400, 60000, - 60600, 61200, 61800, 62400, 63000, 63600, 64200, 9000, - 9600, 10200, 10800, 11400, 64800, 65400, 66000, 66600, - 67200, 67800, 68400, 69000, 69600, 70200, 70800, 71400, - 72000, 72600, 73200, 73800, 74400, 75000, 75600, 76200, - 76800, 77400, 78000, 78600, 79200, 79800, -}; - -static void -settuner(int channel, int finetune) -{ - static long lastfreq; - uchar data[3]; - long freq; - int cw2, n, sa; - - if (channel < 0 || channel > nelem(hrcfreq)) - error(Ebadarg); - - freq = hrcfreq[channel]; - - /* these settings are all for (FS936E) USA Tuners */ - if (freq < 16025) /* low band */ - cw2 = 0xA4; - else if (freq < 45425) /* mid band */ - cw2 = 0x94; - else - cw2 = 0x34; - - /* - * Channels are stored are 1/100 MHz resolutions, but - * the tuner wants stuff in MHZ, so divide by 100, we - * then have to shift by 4 to get the prog. div. value - */ - n = ((freq + 4575L) * 16) / 100L + finetune; - - if (freq > lastfreq) { - sa = (n >> 8) & 0xFF; - data[0] = n & 0xFF; - data[1] = 0x8E; - data[2] = cw2; - } else { - sa = 0x8E; - data[0] = cw2; - data[1] = (n >> 8) & 0xFF; - data[2] = n & 0xFF; - } - lastfreq = freq; - seti2cregs(AdrTuner, sa, 3, data); -} - -static void -tunerinit(void) -{ - if (seti2creg(AdrTuner, 0, 0)) - print("devtv: Tuner init failed\n"); -} - -/* - * Video routines - */ -static int slreg1 = 0; -static int slreg2 = 0; -static int vcogain = 0; -static int phdetgain = 2; -static int plln1 = 2; -static int pllp2 = 1; - -static void -waitforretrace(void) -{ - ushort timo; - - for (timo = ~0; (getreg(VideoOutIntrStatus) & 2) == 0 && timo; timo--) - /* wait for VSync inactive */; - for (timo = ~0; (getreg(VideoOutIntrStatus) & 2) && timo; timo--) - /* wait for VSync active */; -} - -static void -updateshadowregs(void) -{ - int val; - - setreg(InputVideoConfA, getreg(InputVideoConfA) | 0x40); - val = getreg(OutputProcControlB); - setreg(OutputProcControlB, val & 0x7F); - setreg(OutputProcControlB, val | 0x80); -} - -static void -setvgareg(int data) -{ - /* set HSync & VSync first, to make sure VSync works properly */ - setreg(VGAControl, (getreg(VGAControl) & ~0x06) | (data & 0x06)); - - /* wait for VSync and set the whole register */ - waitforretrace(); - setreg(VGAControl, data); -} - -static void -setbt812reg(int index, int data) -{ - outb(port+Bt812Index, index); - outb(port+Bt812Data, data); -} - -static int -getbt812reg(int index) -{ - outb(port+Bt812Index, index); - return inb(port+Bt812Data); -} - -static void -setbt812regpair(int index, ushort data) -{ - outb(port+Bt812Index, index); - outb(port+Bt812Data, data); - outb(port+Bt812Data, data >> 8); -} - -static void -setvideosource(int source) -{ - int s; - - source &= 7; - s = source & 3; - setbt812reg(0, ((s << 2) | s) << 3); - s = (source & 4) << 4; - setbt812reg(4, (getbt812reg(4) & ~Bt4ColorBars) | s); -} - -static void -setsvideo(int enable) -{ - if (enable) - setbt812reg(5, getbt812reg(5) | Bt5YCFormat); - else - setbt812reg(5, getbt812reg(5) & ~Bt5YCFormat); -} - -static int -waitvideosignal(void) -{ - ushort timo; - - for (timo = ~0; timo; timo--) - if (getbt812reg(2) & Bt2VideoPresent) - return 1; - return 0; -} - -/* - * ICS1572 Programming Configuration - * - * R = 1 - * M = x - * A = x - * N1 = 4 - * N2 = internal divide ratio - */ -static -uchar ICSbits[7] = { - 0x01, /* bits 8 - 1 00000001 */ - 0x05, /* bits 16 - 9 00000101 */ - 0xFF, /* bits 24 - 17 11111111 */ - 0x8C, /* bits 32 - 25 10001100 */ - 0xBF, /* bits 40 - 33 10111111 */ - 0x00, /* bits 48 - 41 00000000 */ - 0x00, /* bits 56 - 49 00000000 */ -}; - -static void -sendbit(int val, int hold) -{ - slreg2 &= ~(HoldBit|DataBit|ClkBit); - if (val) slreg2 |= DataBit; - if (hold) slreg2 |= HoldBit; - outb(port+SLReg2, slreg2); - outb(port+SLReg2, slreg2|ClkBit); - outb(port+SLReg2, slreg2); -} - -static void -load1572(int select) -{ - int reg; - uchar mask; - - if (select) - slreg2 |= SelBit; - else - slreg2 &= ~SelBit; - outb(port+SLReg2, slreg2); - - for (reg = 0; reg < sizeof(ICSbits); reg++) { - for (mask = 1; mask != 0; mask <<= 1) { - if (reg == sizeof(ICSbits)-1 && mask == 0x80) { - sendbit(ICSbits[reg] & mask, 1); - } else - sendbit(ICSbits[reg] & mask, 0); - } - } -} - -static void -smartlockdiv(int count, int vcogain, int phdetgain, int n1, int p2) -{ - int extdiv, intdiv; - int nslreg2, external; - - nslreg2 = slreg2; - extdiv = ((count - 1) / 512) + 1; - intdiv = (count / extdiv); - nslreg2 &= ~0xC0; - switch (extdiv) { - case 1: external = 0; break; - case 2: external = 1; break; - case 3: external = 1; nslreg2 |= 0x40; break; - case 4: external = 1; nslreg2 |= 0x80; break; - default: return; - } - if ((slreg1 & PixelClk) == 0) { - slreg2 = nslreg2; - outb(port+SLReg2, slreg2); - } - - /* set PLL divider */ - ICSbits[0] &= ~0x07; - ICSbits[0] |= n1 & 0x07; - ICSbits[3] &= ~0xB7; - ICSbits[3] |= vcogain & 0x07; - ICSbits[3] |= (phdetgain & 0x03) << 4; - ICSbits[3] |= p2 << 7; - if (external) - ICSbits[1] |= 0x04; /* set EXTFBKEN */ - else - ICSbits[1] &= ~0x04; /* clear EXTFBKEN */ - intdiv--; - ICSbits[2] = intdiv; /* set N2 */ - ICSbits[3] &= ~ 0x08; - ICSbits[3] |= (intdiv >> 5) & 0x08; - load1572(1); -} - -static void -disablecolorkey(void) -{ - setreg(DisplayControl, getreg(DisplayControl) & 0xFE); - updateshadowregs(); -} - -static -uchar colorkeylimit[6] = { - 15, /* upper limit green */ - 255, /* lower limit green */ - 63, /* upper limit red */ - 63, /* upper limit blue */ - 15, /* lower limit red */ - 15, /* lower limit blue */ -}; - -static void -enablecolorkey(int enable) -{ - int i; - - if (enable) { - for (i = 0; i < 6; i++) - seti2creg(Adr8444, 0xF0 | i, colorkeylimit[i]); - slreg1 &= ~0x1C; - if (colorkeylimit[4] == 255) - slreg1 |= 0x04; /* disable red lower limit */ - if (colorkeylimit[1] == 255) - slreg1 |= 0x08; /* disable green lower limit */ - if (colorkeylimit[5] == 255) - slreg1 |= 0x10; /* disable blue lower limit */ - } else { - for (i = 0; i < 6; i++) - seti2creg(Adr8444, 0xF0 | i, 63); - slreg1 |= 0x1C; - } - outb(port+SLReg1, slreg1); - disablecolorkey(); -} - -static void -setcolorkey(int rl, int rh, int gl, int gh, int bl, int bh) -{ - colorkeylimit[0] = gh; - colorkeylimit[1] = gl; - colorkeylimit[2] = rh; - colorkeylimit[3] = bh; - colorkeylimit[4] = rl; - colorkeylimit[5] = bl; - enablecolorkey(1); -} - -static void -waitvideoframe(void) -{ - ushort timo; - int val; - - /* clear status bits and wait for start of an even field */ - val = getreg(InputFieldPixelBufStatus); - USED(val); - for (timo = ~0; timo; timo--) - if ((getreg(InputFieldPixelBufStatus) & 2) == 0) - break; - if (!timo) print("devtv: Wait for video frame failed\n"); -} - -static void -freeze(int enable) -{ - ushort timo; - int reg; - - if (enable) { - waitvideoframe(); - waitvideoframe(); - - setreg(InputVideoConfB, getreg(InputVideoConfB) | 0x08); - updateshadowregs(); - - for (timo = ~0; timo; timo--) - if (getreg(InputVideoConfB) & 0x80) break; - waitvideoframe(); - - reg = getreg(OutputProcControlB); - if ((reg & 0x20) == 0) { - setreg(ISAControl, 0x80); - setreg(OutputProcControlB, getreg(OutputProcControlB) | 0x20); - setreg(ISAControl, 0x42); - - reg = getreg(OutputProcControlB); - setreg(OutputProcControlB, reg & 0x7F); - setreg(OutputProcControlB, reg | 0x80); - } - } else { - setreg(InputVideoConfB, getreg(InputVideoConfB) & ~0x08); - updateshadowregs(); - - for (timo = ~0; timo; timo--) - if (getreg(InputVideoConfB) & 0x40) break; - waitvideoframe(); - reg = getreg(InputFieldPixelBufStatus); - USED(reg); - } -} - -static void -enablevideo(void) -{ - setreg(DisplayControl, 0x04); - updateshadowregs(); -} - -static void -disablevideo(void) -{ - setreg(DisplayControl, 0x18); - updateshadowregs(); -} - -static -uchar vxp500init[] = { /* video register initialization in (index,data) hex pairs */ - 0x30, 0x82, 0x39, 0x40, 0x58, 0x0C, 0x73, 0x02, 0x80, 0x00, 0x25, 0x0F, - 0x26, 0x0F, 0x38, 0x46, 0x30, 0x03, 0x12, 0x3B, 0x97, 0x20, 0x13, 0x00, - 0x14, 0x34, 0x15, 0x04, 0x16, 0x00, 0x17, 0x53, 0x18, 0x04, 0x19, 0x62, - 0x1C, 0x00, 0x1D, 0x00, 0x34, 0x3A, 0x38, 0x06, 0x3A, 0x00, 0x3B, 0x00, - 0x3C, 0x00, 0x3D, 0x00, 0x40, 0x40, 0x41, 0x40, 0x44, 0xFF, 0x45, 0xFF, - 0x48, 0x40, 0x49, 0x40, 0x4C, 0xFF, 0x4D, 0xFF, 0x50, 0xF0, 0x54, 0x30, - 0x55, 0x00, 0x5C, 0x04, 0x5D, 0x00, 0x60, 0x00, 0x68, 0x00, 0x69, 0x00, - 0x6C, 0x06, 0x6D, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x78, 0x01, - 0x79, 0x0C, 0x80, 0x10, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, - 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x04, 0x89, 0x10, 0x8A, 0x00, - 0x8B, 0x00, 0x90, 0x05, 0x91, 0x0C, 0x92, 0x18, 0x93, 0x00, 0x96, 0x18, - 0x9A, 0x30, 0x9C, 0x2D, 0x9D, 0x00, 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, - 0xA4, 0x50, 0xA5, 0x50, 0xA6, 0xF0, 0xA7, 0xF0, 0xA8, 0x19, 0xA9, 0x18, - 0xAA, 0x64, 0xAB, 0x64, 0xB0, 0x64, 0xB1, 0x64, 0xB4, 0xA4, 0xB5, 0xA5, - 0xB8, 0x19, 0xB9, 0x18, 0xBC, 0x09, 0xBD, 0x09, 0xC0, 0x00, 0xC1, 0x02, - 0xC4, 0x00, 0xC5, 0x00, 0xC8, 0x00, 0xC9, 0x08, 0xCA, 0x08, 0xCE, 0x00, - 0xCF, 0x00, 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD8, 0x00, 0xD9, 0x00, - 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0x38, 0x46, 0x97, 0xA0, - 0x97, 0x20, 0x97, 0xA0, -}; - -static -uchar bt812init[] = { /* bt812 initializations */ - 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0xC0, - 0x04, 0x08, 0x05, 0x00, 0x06, 0x40, 0x07, 0x00, 0x08, 0x10, - 0x09, 0x90, 0x0A, 0x80, 0x0B, 0x00, 0x0C, 0x0C, 0x0D, 0x03, - 0x0E, 0x66, 0x0F, 0x00, 0x10, 0x80, 0x11, 0x02, 0x12, 0x16, - 0x13, 0x00, 0x14, 0xE5, 0x15, 0x01, 0x16, 0xAB, 0x17, 0xAA, - 0x18, 0x12, 0x19, 0x51, 0x1A, 0x46, 0x1B, 0x00, 0x1C, 0x00, - 0x1D, 0x37, -}; - -static ushort actpixs = 720; -static ulong Hdesired = 13500000L; - -/* NTSC-M NTSC-443 EXTERNAL */ -static ushort horzfreq[] = { 15734, 15625, 0 }; -static ushort Vdelay[] = { 22, 25, 25 }; -static ushort s2b[] = { 90, 90, 0 }; -static ushort actlines[] = { 485, 485, 575 }; -static ulong subcarfreq[] = { 3579545, 4433619, 4433619 }; - -static -unsigned int framewidth[5][4] = { - 1024, 512, 512, 512, /* mode 0 - single, double, single, quad */ - 1536, 768, 768, 384, /* mode 1 - single, double, single, quad */ - 2048, 1024, 1024, 512, /* mode 2 - single, double, single, quad */ - 1024, 512, 512, 512, /* mode 3 - single, double, single, quad */ - 1536, 768, 768, 384 /* mode 4 - single, double, single, quad */ -}; - -static -unsigned int frameheight[5][4] = { - 512, 512, 1024, 512, /* mode 0 - single, double, single, quad */ - 512, 512, 1024, 512, /* mode 1 - single, double, single, quad */ - 512, 512, 1024, 512, /* mode 2 - single, double, single, quad */ - 512, 512, 1024, 512, /* mode 3 - single, double, single, quad */ - 512, 512, 1024, 256 /* mode 4 - single, double, single, quad */ -}; - -static -uchar horzfilter[] = { 3, 3, 2, 2, 1, 1, 0, 0 }; - -static -uchar interleave[] = { 2, 3, 4, 2, 3 }; - -#define ADJUST(n) (((n) * hrsmult + hrsdiv - 1) / hrsdiv) - -static int q = 100; -static int ilv = 2; -static int hrsmult = 1; -static int hrsdiv = 2; - -static ushort panmask[] = { 0xFFFE, 0xFFFC, 0xFFFF, 0xFFFF, 0xFFFE }; - - -static void -cropwindow(int left, int right, int top, int bottom) -{ - top &= 0x3FE; - bottom &= 0x3FE; - setreg(InputHorzCropLeftA, left); - setreg(InputHorzCropLeftB, left >> 8); - setreg(InputHorzCropRightA, right); - setreg(InputHorzCropRightB, right >> 8); - setreg(InputHorzCropTopA, top); - setreg(InputHorzCropTopB, top >> 8); - setreg(InputHorzCropBottomA, bottom); - setreg(InputHorzCropBottomB, bottom >> 8); -} - -static void -setinputformat(int format) -{ - ushort hclock, hclockdesired; - ulong subcarrier; - int cr7; - - cr7 = getbt812reg(7) & ~Bt7TriState; - if (format == External) - cr7 |= Bt7TriState; - setbt812reg(7, cr7); - setbt812reg(5, getbt812reg(5) & 2); - - hclock = (xtalfreq >> 1) / horzfreq[format]; - setbt812regpair(0x0C, hclock); - setbt812regpair(0x0E, - (ushort)(s2b[format] * (Hdesired / 10) / 1000000L) | 1); - setbt812regpair(0x10, actpixs); - setbt812regpair(0x12, Vdelay[format]); - setbt812regpair(0x14, actlines[format]); - - subcarrier = (ulong) - ((((long long)subcarfreq[format] * 0x1000000) / xtalfreq + 1) / 2); - setbt812regpair(0x16, (int)(subcarrier & 0xFFFF)); /* subcarrier */ - setbt812reg(0x18, (int)(subcarrier >> 16)); - - setbt812reg(0x19, (uchar)(((xtalfreq / 200) * 675) / 1000000L + 8)); - setbt812reg(0x1A, (uchar)((xtalfreq * 65) / 20000000L - 10)); - hclockdesired = (ushort) (Hdesired / horzfreq[format]); - setbt812regpair(0x1B, - (ushort)(((hclock - hclockdesired) * 65536L) / hclockdesired)); -} - -static ushort -vgadivider(void) -{ - ushort horztotal; - - outb(VGAIndex, VGAHorzTotal); - horztotal = (inb(VGAData) << 3) + 40; - if (horztotal > ScreenWidth && horztotal < ((ScreenWidth * 3 ) / 2)) - return horztotal; - else - return (ScreenWidth * 5) / 4; -} - -static void -videoinit(void) -{ - int i, reg, width, tuner; - - /* early PLL smart lock initialization */ - if (ScreenWidth == 640) { - slreg1 = Window|HSyncLow|VSyncLow; - slreg2 = 0x0D; - } else { - slreg1 = Window; - slreg2 = 0x0C; - } - outb(port+CompressReg, 2); - outb(port+SLReg1, slreg1); - outb(port+SLReg2, slreg2); - smartlockdiv((vgadivider() * hrsmult)/hrsdiv, vcogain, phdetgain, 2, 1); - - /* program the VxP-500 chip (disables video) */ - waitforretrace(); - for (i = 0; i < sizeof(vxp500init); i += 2) - setreg(vxp500init[i], vxp500init[i+1]); - - /* set memory base for frame capture */ - setreg(MemoryWindowBaseAddrA, MemAddr >> 14); - setreg(MemoryWindowBaseAddrB, ((MemAddr >> 22) & 3) | (MemSize << 2)); - setreg(MemoryPageReg, 0); - - /* generic 422 decoder, mode 3 and 4 */ - setreg(MemoryConfReg, ilv+1); - - setreg(AcquisitionAddrA, 0); - setreg(AcquisitionAddrB, 0); - setreg(AcquisitionAddrC, 0); - - /* program VxP-500 for correct sync polarity */ - reg = ScreenWidth > 1023 ? 0x01 : 0x00; - reg |= (vsync << 1) | (hsync << 2); - setvgareg(reg); - setreg(VGAControl, reg); - - setreg(VideoBufferLayoutControl, 0); /* for ilv = 2 */ - - /* set sync polarities to get proper blanking */ - if (vsync) - slreg1 |= VSyncLow; - if (!hsync) { - slreg1 ^= HSyncLow; - setreg(VGAControl, reg | 4); - } - outb(port+SLReg1, slreg1); - - if ((slreg1 & PixelClk) == 0) { /* smart lock active */ - enablecolorkey(1); - setreg(VGAControl, getreg(VGAControl) & 6); - } else - enablecolorkey(0); - - /* color key initializations */ - if ((slreg1 & PixelClk) == 0) - setreg(VGAControl, getreg(VGAControl) & 7); - - /* initialize Bt812 */ - for (i = 0; i < sizeof(bt812init); i += 2) - setbt812reg(bt812init[i], bt812init[i+1]); - - /* figure out clock source (Xtal or Oscillator) and revision */ - setbt812reg(6, 0x40); - reg = getreg(InputFieldPixelBufStatus) & 3; - if ((getreg(InputFieldPixelBufStatus) & 3) == reg) { - /* crystal - could be revision PP if R34 is installed */ - setbt812reg(6, 0x00); - reg = inb(port+SLReg1); - if (reg & 0x20) { - if ((reg & 0xE0) == 0xE0) - boardrev = HighQ; - else - boardrev = RevisionA; - } else - boardrev = RevisionPP; - } else /* revision A or newer with 27 MHz oscillator */ - boardrev = RevisionA; - - /* figure out xtal frequency */ - if (xtalfreq == 0) { - if (boardrev == RevisionPP) { - tuner = (inb(port+SLReg1) >> 6) & 3; - if (tuner == 0) /* NTSC */ - xtalfreq = 24545400L; - else - xtalfreq = 29500000L; - } else if (boardrev == HighQ) - xtalfreq = 29500000L; - else - xtalfreq = 27000000L; - } - -// print("Hauppage revision %d (xtalfreq %ld)\n", boardrev, xtalfreq); - - /* on RevPP boards set early sync, on rev A and newer clear it */ - if (boardrev == RevisionPP) - setreg(InputVideoConfA, getreg(InputVideoConfA) | 4); - else - setreg(InputVideoConfA, getreg(InputVideoConfA) & ~4); - - switch (xtalfreq) { - case 24545400L: - actpixs = 640; - break; - case 29500000L: - actpixs = 768; - break; - default: - actpixs = 720; - break; - } - - /* set crop window (these values are for NTSC!) */ - if (boardrev == RevisionPP) { - Hdesired = xtalfreq / 2; - cropleft = (NTSCCropLeft * ((Hdesired / 10))) / 1000000L; - cropright = (NTSCCropRight * ((Hdesired / 10))) / 1000000L; - } else { - cropleft = actpixs / 100; - cropright = actpixs - cropleft; - } - width = ((cropright - cropleft + ilv) / ilv) * ilv; - cropright = cropleft + width + 1; - croptop = 26; - cropbottom = 505; - cropwindow(cropleft, cropright, croptop, cropbottom); - - /* set input format */ - setinputformat(NTSC_M); - setsvideo(0); -} - -static void -panwindow(Point p) -{ - int memmode, ilv, frw; - ulong pos; - - memmode = getreg(MemoryConfReg) & 7; - ilv = interleave[memmode]; - frw = framewidth[memmode][getreg(VideoBufferLayoutControl) & 3]; - - pos = (p.y * (frw/ilv)) + ((p.x/ilv) & panmask[memmode]); - setreg(DisplayViewPortStartAddrA, (uchar) pos); - setreg(DisplayViewPortStartAddrB, (uchar) (pos >> 8)); - setreg(DisplayViewPortStartAddrC, (uchar) (pos >> 16) & 0x03); - updateshadowregs(); -} - -static int -testqfactor(void) -{ - ulong timo; - int reg; - - waitvideoframe(); - for (reg = 0, timo = ~0; timo; timo--) { - reg |= getreg(InputFieldPixelBufStatus); - if (reg & 0xE) break; - } - if (reg & 0xC) return 0; - - waitvideoframe(); - for (reg = 0, timo = ~0; timo; timo--) { - reg |= getreg(InputFieldPixelBufStatus); - if (reg & 0xE) break; - } - return (reg & 0xC) == 0; -} - -static void -newwindow(Rectangle r) -{ - unsigned ww, wh, dx, dy, xs, ys, xe, ye; - unsigned scalex, scaley; - int frwidth, frheight, vidwidth, vidheight; - int memmode, layout; - int width, height; - int filter, changed, val; - - changed = r.min.x != window.min.x || r.min.y != window.min.y || - r.max.x != window.max.x || r.max.y != window.max.y; - if (changed) window = r; - - if (r.min.x < 0) r.min.x = 0; - if (r.max.x > ScreenWidth) r.max.x = ScreenWidth; - if (r.min.y < 0) r.min.y = 0; - if (r.max.y > ScreenHeight) r.max.y = ScreenHeight; - - if ((dx = r.max.x - r.min.x) <= 0) dx = 1; - if ((dy = r.max.y - r.min.y) <= 0) dy = 1; - - wh = dy; - ww = dx = ADJUST(dx); - r.min.x = (r.min.x * hrsmult) / hrsdiv; - - memmode = getreg(MemoryConfReg) & 7; - layout = getreg(VideoBufferLayoutControl) & 3; - vidwidth = cropright - cropleft + 1; - vidheight = (cropbottom & 0x3FE) - (croptop & 0x3FE) + 1; - frwidth = min(framewidth[memmode][layout], vidwidth); - frheight = min(frameheight[memmode][layout], vidheight); - - /* round up scale width to nearest multiple of interleave factor */ - dx = ((ulong)dx * q) / 100; - dx = ilv * ((dx + ilv - 1) / ilv); - - scalex = (((ulong)dx * 1024L) + vidwidth - 2) / (vidwidth - 1); - if (dy > frheight) dy = frheight - 1; - scaley = (((ulong)dy * 1024L) + vidheight - 2) / (vidheight - 1); - - setreg(InputHorzScaleControlA, (scalex << 6) & 0xC0); - setreg(InputHorzScaleControlB, (scalex >> 2) & 0xFF); - setreg(InputVertScaleControlA, (scaley << 6) & 0xC0); - setreg(InputVertScaleControlB, (scaley >> 2) & 0xFF); - - /* turn on horizontal filtering if we are scaling down */ - setreg(InputHorzFilter, horzfilter[((scalex - 1) >> 7) & 7]); - - /* set vertical interpolation */ - filter = scaley > 512 ? (ScreenWidth == 640 ? 0x44 : 0xC5) : 0x46; /* magic */ - if ((getreg(InputVertInterpolControl) & 0x1F) != (filter & 0x1F)) { - setreg(ISAControl, 0x80); - setreg(InputVertInterpolControl, filter & 0x1F); - setreg(ISAControl, 0x42); - } - setreg(AcquisitionControl, ((filter >> 6) ^ 3) | 0x04); - - /* set viewport position and size */ - width = ((ulong)ww * q) / 100; - if (width >= frwidth - ilv) - width = frwidth - ilv; - width = ((width + ilv - 1) / ilv) + 2; - - height = ((ulong)wh * dy + wh - 1) / wh; - if (height >= frheight) - height = frheight - 3; - height += 2; - - xs = r.min.x + XCorrection; - if (xs < 0) xs = 2; - ys = r.min.y + YCorrection; - if (ys < 0) ys = 2; - if (ScreenWidth > 1023) ys |= 1; - - setreg(DisplayViewPortWidthA, width); - setreg(DisplayViewPortWidthB, width >> 8); - setreg(DisplayViewPortHeightA, height); - setreg(DisplayViewPortHeightB, height >> 8); - setreg(DisplayViewPortOrigTopA, ys); - setreg(DisplayViewPortOrigTopB, ys >> 8); - setreg(DisplayViewPortOrigLeftA, xs); - setreg(DisplayViewPortOrigLeftB, xs >> 8); - - xe = r.min.x + ww - 1 + XCorrection; - if (xe < 0) xe = 2; - ye = r.min.y + wh - 1 + YCorrection; - if (ye < 0) ye = 2; - - setreg(DisplayWindowLeftA, xs); - setreg(DisplayWindowLeftB, xs >> 8); - setreg(DisplayWindowRightA, xe); - setreg(DisplayWindowRightB, xe >> 8); - setreg(DisplayWindowTopA, ys); - setreg(DisplayWindowTopB, ys >> 8); - setreg(DisplayWindowBottomA, ye); - setreg(DisplayWindowBottomB, ye >> 8); - - if (dx < ww) { /* horizontal zoom */ - int zoom = ((ulong) (dx - 1) * 2048) / ww; - setreg(OutputProcControlA, getreg(OutputProcControlA) | 6); - setreg(OutputHorzZoomControlA, zoom); - setreg(OutputHorzZoomControlB, zoom >> 8); - } else - setreg(OutputProcControlA, getreg(OutputProcControlA) & 0xF9); - - if (dy < wh) { /* vertical zoom */ - int zoom = ((ulong) (dy - 1) * 2048) / wh; - setreg(OutputProcControlB, getreg(OutputProcControlB) | 1); - setreg(OutputVertZoomControlA, zoom); - setreg(OutputVertZoomControlB, zoom >> 8); - } else - setreg(OutputProcControlB, getreg(OutputProcControlB) & 0xFE); - - setreg(OutputProcControlB, getreg(OutputProcControlB) | 0x20); - updateshadowregs(); - - if (changed) { - setreg(OutputProcControlA, getreg(OutputProcControlA) & 0xDF); - } else { - val = getreg(InputFieldPixelBufStatus); - USED(val); - } - - panwindow(Pt(0, 0)); -} - -static void -createwindow(Rectangle r) -{ - for (q = 100; q >= 30; q -= 10) { - newwindow(r); - if (testqfactor()) - break; - } - enablevideo(); -} - -static void -setcontrols(int index, uchar val) -{ - switch (index) { - case Vxp500Brightness: - setreg(BrightnessControl, (127L * val) / 100); - updateshadowregs(); - break; - case Vxp500Contrast: - setreg(ContrastControl, (15L * val) / 100); - updateshadowregs(); - break; - case Vxp500Saturation: - setreg(SaturationControl, (15L * val) / 100); - updateshadowregs(); - break; - case Bt812Brightness: - setbt812reg(0x08, ((126L * val) / 100) & 0xFE); - break; - case Bt812Contrast: - setbt812reg(0x09, ((254L * val) / 100) & 0xFE); - break; - case Bt812Saturation: - setbt812reg(0x0A, ((254L * val) / 100) & 0xFE); - break; - case Bt812Hue: - setbt812reg(0x0B, ((254L * val) / 100) & 0xFE); - break; - case Bt812BW: - setbt812reg(0x05, (getbt812reg(0x5) & ~2) | ((val << 1) & 2)); - break; - } -} - -static void -enablememwindow(void) -{ - setreg(MemoryWindowBaseAddrB, getreg(MemoryWindowBaseAddrB) | 0x20); -} - -static void -disablememwindow(void) -{ - setreg(MemoryWindowBaseAddrB, getreg(MemoryWindowBaseAddrB) & ~0x20); -} - -volatile static ushort *fb = (ushort *)EISA(MemAddr); -static uchar yuvpadbound[] = { 4, 12, 4, 2, 6 }; - -/* - * Capture a frame in UY0, VY1 format - */ -static void * -saveframe(int *nb) -{ - int memmode, layout, ilv; - int frwidth, frheight; - int bound, n, val, toggle; - unsigned save58, save6C; - int x, y, w, h, width, height; - ulong pos, size; - char *p; - static void *frame = 0; - static ulong framesize = 0; - - width = capwindow.max.x - capwindow.min.x; - height = capwindow.max.y - capwindow.min.y; - - memmode = getreg(MemoryConfReg) & 7; - if (memmode <= 2) { - print("devtv: cannot handle YUV411\n"); - error(Egreg); /* actually, Eleendert */ - } - layout = getreg(VideoBufferLayoutControl) & 3; - ilv = interleave[memmode]; - frwidth = framewidth[memmode][layout]; - frheight = frameheight[memmode][layout]; - - pos = getreg(AcquisitionAddrA) + - (getreg(AcquisitionAddrB) << 8) + (getreg(AcquisitionAddrC) & 3) << 16; - - x = capwindow.min.x + (pos % frwidth); - y = capwindow.min.y + (pos / frwidth); - if (x > frwidth || y > frheight) - return 0; - if (x + width > frwidth) - width = frwidth - x; - if (y + height > frheight) - height = frheight - y; - - pos = y * (frwidth / ilv) + (x / ilv); - - /* compute padding for each scan line */ - bound = yuvpadbound[memmode]; - switch (bound) { - case 2: - width = (width + 1) & ~1; - break; - case 4: - width = (width + 3) & ~3; - break; - default: - width = (width + (bound - 1)) / bound; - break; - } - - size = width * height * sizeof(ushort); - if (size != framesize) { - framesize = 0; - if (frame) - free(frame); - frame = malloc(size + 256); - } - if (frame == 0) - return 0; - - memset(frame, 0, size + 256); - - framesize = size; - p = (char *) frame + snprint(frame, 256, - "TYPE=ccir601\nWINDOW=%d %d %d %d\n\n", - capwindow.min.x, capwindow.min.y, - capwindow.min.x+width, capwindow.min.y+height); - - freeze(1); - - save58 = getreg(InputVertInterpolControl); - save6C = getreg(AcquisitionControl); - - waitforretrace(); - setreg(ISAControl, 0xC0); /* global reset */ - setreg(InputVertInterpolControl, 0x0D); - setreg(AcquisitionControl, 0x04); - setreg(CaptureControl, 0x80); /* set capture mode */ - setreg(VideoInputFrameBufDepthA, 0xFF); - setreg(VideoInputFrameBufDepthB, 0x03); - setreg(InputVideoConfA, getreg(InputVideoConfA) | 0x40); - setreg(ISAControl, 0x44); /* tight decode, global reset off */ - - setreg(CaptureViewPortAddrA, (int) pos & 0xFF); - setreg(CaptureViewPortAddrB, (int) (pos >> 8) & 0xFF); - setreg(CaptureViewPortAddrC, (int) (pos >> 16) & 0x03); - n = (width / ilv) - 1; - setreg(CaptureViewPortWidthA, n & 0xFF); - setreg(CaptureViewPortWidthB, n >> 8); - setreg(CaptureViewPortHeightA, (height-1) & 0xFF); - setreg(CaptureViewPortHeightB, (height-1) >> 8); - setreg(CapturePixelBufLow, 0x04); /* pix buffer low */ - setreg(CapturePixelBufHigh, 0x0E); /* pix buffer high */ - setreg(CaptureMultiBufDepthA, 0xFF); /* multi buffer depth maximum */ - setreg(CaptureMultiBufDepthB, 0x03); - updateshadowregs(); - - setreg(CaptureControl, 0x90); /* capture reset */ - val = getreg(InputFieldPixelBufStatus); /* clear read status */ - USED(val); - - toggle = !(getreg(OutputProcControlA) & 0x01) ? 0x8000 : 0x0000; - setreg(CaptureControl, 0xC0); /* capture enable, active */ - - while ((getreg(InputFieldPixelBufStatus) & 0x10) == 0) - /* wait for capture FIFO to become ready */; - - enablememwindow(); - for (h = height; h > 0; h--) { - for (w = width; w > 0; w -= 2) { - ushort uy0 = swab16(fb[0]) ^ toggle; - ushort vy1 = swab16(fb[1]) ^ toggle; - /* unfortunately p may not be properly aligned */ - *p++ = uy0 >> 8; - *p++ = uy0; - *p++ = vy1 >> 8; - *p++ = vy1; - } - } - disablememwindow(); - - waitforretrace(); - setreg(ISAControl, 0xC0); /* global reset */ - setreg(CaptureControl, 0); /* clear capture mode */ - setreg(InputVertInterpolControl, save58); - setreg(AcquisitionControl, save6C); - setreg(InputVideoConfA, getreg(InputVideoConfA) | 0x40); - setreg(ISAControl, 0x40); /* clear global reset */ - updateshadowregs(); - - freeze(0); - - *nb = p - (char *) frame; - return frame; -} |
