summaryrefslogtreecommitdiff
path: root/os/pc/devtv.c
diff options
context:
space:
mode:
authorKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
committerKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
commit78ee7d5717807e6ac779293d0d3c78341de6130a (patch)
treea43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/pc/devtv.c
parentbdaf46cf45bbb59261da245d548a179d95a42768 (diff)
Move existing boards into subdits split per arch
Diffstat (limited to 'os/pc/devtv.c')
-rw-r--r--os/pc/devtv.c1826
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;
-}