/* * IBM Smart Capture Card driver. * * Copyright (c) 1995 * International Business Machines Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by International * Business Machines Corporation. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * 5. Redistributions are permitted provided for Linux/FreeBSD systems. * If you want to support other operating system, please contact with * IBM Smart Capture Card technical support desk. * 6. Do not ask IBM product services and support about Linux/FreeBSD * drivers since International Business Machines Corporation does * not officially support them. * THIS SOFTWARE IS PROVIDED BY INTERNATIONAL BUSINESS MACHINES * CORPORATION AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL INTERNATIONAL BUSINESS MACHINES * CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Changed by Koji OKAMURA * Changed by Yoshihisa NAKAGAWA * Changed by Takeshi OHASHI * Version 0.34, Aug 11, 1996. * */ #if defined(__linux__) #include #include "scc_cs.h" #define outp(P,V) outb((V),(P)) #define inp(P) inb((P)) #elif defined(__FreeBSD__) #include "scc.h" #include #include #define outp(P,V) outb((P),(V)) #define inp(P) inb((P)) #endif /* linux or FreeBSD */ /* TV channel table for Japan */ BYTE vhf_table_1_JP[100] = { 0x08,0x08,0x09,0x0D,0x0D,0x0E,0x0E,0x0E, 0x0F,0x0F,0x10,0x10,0x20,0x20,0x21,0x21, 0x21,0x22,0x22,0x22,0x23,0x23,0x24,0x24, 0x24,0x25,0x25,0x25,0x26,0x26,0x27,0x27, 0x27,0x28,0x28,0x28,0x29,0x29,0x2A,0x2A, 0x2A,0x2B,0x2B,0x2B,0x2C,0x2C,0x2D,0x2D, 0x2D,0x2E,0x2E,0x2E,0x2F,0x2F,0x30,0x30, 0x30,0x31,0x31,0x31,0x32,0x32,0x00,0x00, 0x35,0x36,0x36,0x37,0x37,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00} ; BYTE vhf_table_2_JP[100] = { 0x92,0xF2,0x52,0x92,0xF2,0x52,0xB2,0xF2, 0x52,0xB2,0x12,0x72,0x52,0xB2,0x12,0x72, 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00} ; BYTE vhf_table_3_JP[100] = { 0xA0,0xA0,0xA0,0x90,0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30} ; /* TV channel table for US */ BYTE vhf_table_1_US[100] = { 0x00,0x06,0x06,0x07,0x07,0x08,0x0D,0x0E, 0x0E,0x0E,0x0F,0x0F,0x10,0x20,0x20,0x21, 0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x24, 0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x27, 0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x2A, 0x2A,0x2A,0x2B,0x2B,0x2B,0x2C,0x2C,0x2D, 0x2D,0x2D,0x2E,0x2E,0x2E,0x2F,0x2F,0x30, 0x30,0x30,0x31,0x31,0x31,0x32,0x32,0x33, 0x33,0x33,0x34,0x34,0x34,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00} ; BYTE vhf_table_2_US[100] = { 0x00,0x50,0xB0,0x10,0xB0,0x10,0xD0,0x30, 0x90,0xF0,0x50,0xB0,0x10,0x50,0xB0,0x10, 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, 0x70,0xB0,0x30,0x90,0xF0,0x50,0xB0,0x10, 0x70,0xD0,0x30,0x90,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00} ; BYTE vhf_table_3_US[100] = { 0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0x90,0x90, 0x90,0x90,0x90,0x90,0x90,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30} ; WORD SccBase[NSCC]; BYTE VPX_ver[NSCC]; WORD MemWidth[NSCC], MemHeight[NSCC]; BYTE MemStandard[NSCC]; int Index; /*-------------------------------- WriteReg --------------------------------- Sets a SCC/II register to a specified value. Exit: None -----------------------------------------------------------------------------*/ void WriteReg(BYTE index, BYTE Value) { BYTE SavedIndex; SavedIndex = inp(SccBase[Index]+1); /* Save current index */ outp(SccBase[Index]+1, index); outp(SccBase[Index]+2, Value); outp(SccBase[Index]+1, SavedIndex); /* Restore original index */ } /*--------------------------------- ReadReg --------------------------------- Gets a SCC/II register value. Exit: Register value -----------------------------------------------------------------------------*/ BYTE ReadReg(BYTE index) { BYTE SavedIndex, Value; SavedIndex = inp(SccBase[Index]+1); /* Save current index. */ outp(SccBase[Index]+1, index); Value = inp(SccBase[Index]+2); outp(SccBase[Index]+1, SavedIndex); /* Restore original index */ return(Value); } /*---------------------------------- FPbusy ----------------------------------- Send an 8-bit data streem (1 byte) starting from the MSb to the I2C bus. Begins with a start protocol bit when the byte to be sent is a slave address. -----------------------------------------------------------------------------*/ BYTE FPbusy() { BYTE retries; retries = 0; while ((i2crd8(VPXI2C, FPSTA) & 0x4) && retries <= I2CRET) retries++; return(0); } /*---------------------------------- i2cwr16 ---------------------------------- Write a byte to the selected slave device, from 'addr', and to the selected register, from 'subaddr'. -----------------------------------------------------------------------------*/ void i2cwr16(BYTE addr, BYTE subaddr, WORD data) { BYTE ready, retries; retries = 0; do { ready = 1; i2cstart (); i2cwdata ((BYTE)((addr<<1)&0xFE)); ready &= i2crack (); i2cwdata (subaddr); ready &= i2crack (); i2cwdata ((BYTE)(data>>8)); ready &= i2crack (); i2cwdata ((BYTE)data); ready &= i2crack (); i2cstop (); if (!ready) retries++; } while (!ready && (retries <= I2CRET)); } /*---------------------------------- i2crd16 ---------------------------------- Read a byte from the selected slave device, from addr, and from the selected register, from subaddr. -----------------------------------------------------------------------------*/ WORD i2crd16(BYTE addr, BYTE subaddr) { BYTE dataL, dataH; BYTE ready, retries; WORD i2csts; retries = 0; do { ready = 1; i2cstart (); /* send start protocol out to the slaves */ i2cwdata ((BYTE)((addr<<1)&0xFE)); /* send a byte ('addr') to i2c bus.*/ ready &= i2crack (); /* gets the acknowledge*/ i2cwdata (subaddr); /* send a byte ('subaddr') to i2c bus.*/ ready &= i2crack (); /* gets the acknowledge*/ i2cstart (); /* send start protocol out to the slaves*/ i2cwdata ((BYTE)((addr<<1)|0x01)); /* send a byte ('addr') to i2c bus.*/ ready &= i2crack (); /* gets the acknowledge */ dataH = i2crdata(); /* receive a byte from i2c bus (MSB)*/ i2cwack (); /* gets the acknowledge*/ dataL = i2crdata(); /* receive a byte from i2c bus (MSB)*/ i2cwnack (); /* gets the acknowledge*/ i2cstop (); /* sends a stop protocol to i2c bus*/ i2csts=dataL+(dataH << 8); /* compose the WORD read from the bus */ if (!ready) retries++; } while (!ready && (retries <= I2CRET)); return (i2csts); } /*----------------------------------- i2cwr8 ---------------------------------- Write a byte to the selected slave device, from 'addr', and to the selected register, from 'subaddr'. -----------------------------------------------------------------------------*/ void i2cwr8(BYTE addr, BYTE subaddr, BYTE data) { BYTE ready, retries; retries = 0; do { ready = 1; i2cstart (); i2cwdata ((BYTE)((addr<<1)&0xFE)); ready &= i2crack (); i2cwdata (subaddr); ready &= i2crack (); i2cwdata (data); ready &= i2crack (); i2cstop (); if (!ready) retries++; } while (!ready && (retries <= I2CRET)); } /*----------------------------------- i2crd8 ---------------------------------- Read a byte from the selected slave device, from addr, and from the selected register, from subaddr. -----------------------------------------------------------------------------*/ BYTE i2crd8(BYTE addr, BYTE subaddr) { BYTE data = 0; BYTE i2csts; BYTE ready, retries; retries = 0; do { ready = 1; i2cstart (); i2cwdata ((BYTE)((addr<<1)&0xFE)); i2crack (); i2cwdata (subaddr); i2crack (); i2cstart (); i2cwdata ((BYTE)((addr<<1)|0x01)); i2crack (); data = i2crdata(); i2cwnack (); i2cstop (); i2csts = data; if (!ready) retries++; } while (!ready && (retries <= I2CRET)); return (i2csts); } /*--------------------------------- i2cwdata ---------------------------------- Send an 8-bit data streem (1 byte) starting from the MSb to the I2C bus. Begins with a start protocol bit when the byte to be sent is a slave address. -----------------------------------------------------------------------------*/ void i2cwdata(BYTE data) { BYTE i; for(i = 0; i <= 7; i++) /* send out data stream*/ { i2cbwr(I2C_SDA, (BYTE)((data >> (7-i)) & 0x01)); /*MSbit goes out first*/ i2cbwr(I2C_SCL, HICLK); i2cwait(); i2cbwr(I2C_SCL, LOCLK); i2cbwr(I2C_SDA, HIDAT); } } /*--------------------------------- i2crdata ---------------------------------- Receive an 8-bit data streem (1 byte) starting from the MSb from the I2C bus. -----------------------------------------------------------------------------*/ BYTE i2crdata() { BYTE i; BYTE data = 0; for(i = 0; i <= 7; i++) /* send out data stream*/ { i2cbwr(I2C_SCL, HICLK); i2cwait(); data |= (i2cbrd(I2C_SDA) << (7-i)); /* MSbit comes first*/ i2cbwr(I2C_SCL, LOCLK); } return(data); } /*---------------------------------- i2cstart --------------------------------- Send a start protocol out to the slaves. Start of protocol occurs on an high-to-low transition of the data line while the clock is high. -----------------------------------------------------------------------------*/ void i2cstart() { i2cbwr (I2C_SCL, HICLK); i2cbwr (I2C_SDA, LODAT); i2cbwr (I2C_SCL, LOCLK); i2cbwr (I2C_SDA, HIDAT); } /*---------------------------------- i2cstop ---------------------------------- Send stop protocol out to i2c slave. Stop protocol occurs on a positive going transition of data line while clock line high. -----------------------------------------------------------------------------*/ void i2cstop() { i2cbwr(I2C_SDA, LODAT); i2cbwr(I2C_SCL, HICLK); i2cbwr(I2C_SDA, HIDAT); } /*---------------------------------- i2cwack ---------------------------------- Get an acknowledge back from a slave device -----------------------------------------------------------------------------*/ BYTE i2cwack() { i2cbwr (I2C_SDA, LODAT); i2cbwr (I2C_SCL, HICLK); i2cbwr (I2C_SCL, LOCLK); i2cbwr (I2C_SDA, HIDAT); return (0); } /*--------------------------------- i2cwnack ---------------------------------- Get an acknowledge back from a slave device -----------------------------------------------------------------------------*/ BYTE i2cwnack() { i2cbwr (I2C_SCL, HICLK); i2cbwr (I2C_SCL, LOCLK); return (0); } /*--------------------------------- i2crack ----------------------------------- Get an acknowledge back from a slave device -----------------------------------------------------------------------------*/ BYTE i2crack() { BYTE nack; i2cbwr (I2C_SCL, HICLK); nack = i2cbrd(I2C_SDA); i2cbwr (I2C_SCL, LOCLK); if (nack) return (0); else return (1); } /*------------------------------------ i2cbwr --------------------------------- Writes a Bit into the I2C bus -----------------------------------------------------------------------------*/ void i2cbwr(BYTE type, BYTE data) { BYTE inbtmp; data = ~data & 0x01; /* invert data because the HW inverts again*/ switch (type) { case I2C_SCL: outp(SccBase[Index]+1,IOIF_REG); inbtmp = (BYTE)~SCLW_MSK; inbtmp &= inp(SccBase[Index]+2); /* read IOIF_REG masking SCLW*/ inbtmp |= (data & 0x01); /* modify with the data bit*/ outp(SccBase[Index]+2,inbtmp); /* and write back to the reg.*/ break; case I2C_SDA: outp(SccBase[Index]+1,IOIF_REG); inbtmp = (BYTE)~SDAW_MSK; inbtmp &= inp(SccBase[Index]+2); /* read IOIF_REG masking SDAW*/ inbtmp |= ((data & 0x01) << 1); /* modify with the data bit*/ outp(SccBase[Index]+2,inbtmp); /* and write back to the reg.*/ break; } } /*----------------------------------- i2cbrd ---------------------------------- Reads a Bit from the I2C bus -----------------------------------------------------------------------------*/ BYTE i2cbrd(BYTE type) { BYTE inbtmp=0; switch (type) { case I2C_SCL: outp (SccBase[Index]+1,IOIF_REG); /* read the status of SCL pin*/ inbtmp = inp(SccBase[Index]+2) & SCLR_MSK; /* from the IOIF_REG*/ inbtmp >>= 3; break; case I2C_SDA: outp (SccBase[Index]+1,IOIF_REG); /* read the status of SDA pin*/ inbtmp = inp(SccBase[Index]+2) & SDAR_MSK; /* from the IOIF_REG*/ inbtmp >>= 4; break; } return(inbtmp); } /*---------------------------------- i2cwait ---------------------------------- Wait for the slave is ready to accept next data -----------------------------------------------------------------------------*/ BYTE i2cwait() { while (i2cbrd(I2C_SCL) == 0); return (0); } #if 0 /*------------------------------- SetTVStandard ------------------------------- Initializes the VPX to decode a selected TV broadcast standard. These will change among the VPX technical code versions! -----------------------------------------------------------------------------*/ void SetTVStandard(WORD stdsel, int index) { Index = index; switch (stdsel) { case PAL: i2cwr8 (VPXI2C, STS, 0x01); /* select the PAL standard*/ i2cwr8 (VPXI2C, DEEM, 0x08); i2cwr8 (VPXI2C, LDF, 0x00); /* luma/chroma matching delay*/ i2cwr8 (VPXI2C, YNF, 0x19); /* luma notch frequency*/ i2cwr16 (VPXI2C, FPWR, 0x001B); /* standard = PAL*/ i2cwr16 (VPXI2C, FPDAT, 0x0000); i2cwr16 (VPXI2C, FPWR, 0x001C); i2cwr16 (VPXI2C, FPDAT, 0x0000); i2cwr16 (VPXI2C, FPWR, 0x0023); /* samples per line*/ i2cwr16 (VPXI2C, FPDAT, 0x0510); i2cwr16 (VPXI2C, FPWR, 0x0019); /* oscillator frequency*/ i2cwr16 (VPXI2C, FPDAT, 0x0C69); i2cwr16 (VPXI2C, FPWR, 0x001A); i2cwr16 (VPXI2C, FPDAT, 0x0365); i2cwr16 (VPXI2C, FPWR, 0x001F); /* chroma gain PLL*/ i2cwr16 (VPXI2C, FPDAT, 0x0008); i2cwr16 (VPXI2C, FPWR, 0x0033); /* vertical blanking*/ i2cwr16 (VPXI2C, FPDAT, 0x026E); i2cwr16 (VPXI2C, FPWR, 0x003A); i2cwr16 (VPXI2C, FPDAT, 0x0135); i2cwr16 (VPXI2C, FPWR, 0x0040); /* burst key set count*/ i2cwr16 (VPXI2C, FPDAT, 0x00A0); i2cwr16 (VPXI2C, FPWR, 0x0041); i2cwr16 (VPXI2C, FPDAT, 0x00C0); i2cwr16 (VPXI2C, FPWR, 0x00C0); i2cwr16 (VPXI2C, FPDAT, 0x0001); i2cwr16 (VPXI2C, FPWR, 0x00C1); i2cwr16 (VPXI2C, FPDAT, 0x0135); i2cwr16 (VPXI2C, FPWR, 0x00C2); i2cwr16 (VPXI2C, FPDAT, 0x0140); i2cwr16 (VPXI2C, FPWR, 0x00C3); i2cwr16 (VPXI2C, FPDAT, 0x026E); break; case SECAM: break; case NTSC: i2cwr8 (VPXI2C, STS, 0x02); /* select the NTSC standard*/ i2cwr16 (VPXI2C, FPWR, 0x001B); /* standard = NTSC*/ i2cwr16 (VPXI2C, FPDAT, 0x0001); i2cwr16 (VPXI2C, FPWR, 0x001C); i2cwr16 (VPXI2C, FPDAT, 0x0000); i2cwr8 (VPXI2C, DEEM, 0x08); i2cwr8 (VPXI2C, LDF, 0x00); /* luma/chroma matching delay*/ i2cwr8 (VPXI2C, YNF, 0x39); /* luma notch frequency*/ i2cwr16 (VPXI2C, FPWR, 0x00B2); i2cwr16 (VPXI2C, FPDAT, 0x02DC); i2cwr16 (VPXI2C, FPWR, 0x00A0); i2cwr16 (VPXI2C, FPDAT, 0x0898); i2cwr16 (VPXI2C, FPWR, 0x0027); i2cwr16 (VPXI2C, FPDAT, 0x0054); i2cwr16 (VPXI2C, FPWR, 0x0023); /* samples per line*/ i2cwr16 (VPXI2C, FPDAT, 0x0507); i2cwr16 (VPXI2C, FPWR, 0x0033); i2cwr16 (VPXI2C, FPDAT, 0x020A); i2cwr16 (VPXI2C, FPWR, 0x003A); i2cwr16 (VPXI2C, FPDAT, 0x0103); i2cwr16 (VPXI2C, FPWR, 0x0040); i2cwr16 (VPXI2C, FPDAT, 0x008C); i2cwr16 (VPXI2C, FPWR, 0x0041); i2cwr16 (VPXI2C, FPDAT, 0x00AC); i2cwr16 (VPXI2C, FPWR, 0x00C0); i2cwr16 (VPXI2C, FPDAT, 0x0001); i2cwr16 (VPXI2C, FPWR, 0x00C1); i2cwr16 (VPXI2C, FPDAT, 0x0007); i2cwr16 (VPXI2C, FPWR, 0x00C2); i2cwr16 (VPXI2C, FPDAT, 0x0108); i2cwr16 (VPXI2C, FPWR, 0x00C3); i2cwr16 (VPXI2C, FPDAT, 0x010E); i2cwr16 (VPXI2C, FPWR, 0x0010); i2cwr16 (VPXI2C, FPDAT, 0x0022); break; case NTSCC: break; case NTSCK: i2cwr8 (VPXI2C, STS, 0x01); /* select the NTSC standard*/ i2cwr16 (VPXI2C, FPWR, 0x001B); /* standard = NTSC*/ i2cwr16 (VPXI2C, FPDAT, 0x0001); i2cwr16 (VPXI2C, FPWR, 0x001C); i2cwr16 (VPXI2C, FPDAT, 0x0000); i2cwr8 (VPXI2C, DEEM, 0x08); i2cwr8 (VPXI2C, LDF, 0x00); i2cwr8 (VPXI2C, YNF, 0x39); i2cwr16 (VPXI2C, FPWR, 0x0023); i2cwr16 (VPXI2C, FPDAT, 0x0507); i2cwr16 (VPXI2C, FPWR, 0x0019); i2cwr16 (VPXI2C, FPDAT, 0x00A5); i2cwr16 (VPXI2C, FPWR, 0x001A); i2cwr16 (VPXI2C, FPDAT, 0x02D4); i2cwr16 (VPXI2C, FPWR, 0x001F); i2cwr16 (VPXI2C, FPDAT, 0x0004); i2cwr16 (VPXI2C, FPWR, 0x0033); i2cwr16 (VPXI2C, FPDAT, 0x020A); i2cwr16 (VPXI2C, FPWR, 0x003A); i2cwr16 (VPXI2C, FPDAT, 0x0103); i2cwr16 (VPXI2C, FPWR, 0x0040); i2cwr16 (VPXI2C, FPDAT, 0x00A0); i2cwr16 (VPXI2C, FPWR, 0x0041); i2cwr16 (VPXI2C, FPDAT, 0x00C0); i2cwr16 (VPXI2C, FPWR, 0x00C1); i2cwr16 (VPXI2C, FPDAT, 0x0103); i2cwr16 (VPXI2C, FPWR, 0x00C2); i2cwr16 (VPXI2C, FPDAT, 0x010C); i2cwr16 (VPXI2C, FPWR, 0x00C3); i2cwr16 (VPXI2C, FPDAT, 0x020A); break; default: break; } } #endif /*------------------------------- SetTVChannel -------------------------------- Selects a TV channel according the channel table. This function have been designed around the Philips FI12XX family of tuners. It calculates the tuning parameters and programs the tuner PLL and control bytes. -----------------------------------------------------------------------------*/ BYTE SetTVChannel( BYTE tuntype, BYTE channel, BYTE fine, BYTE country, int index) { WORD u; BYTE retries, ready, inbbtmp; Index = index; if (country) u = (vhf_table_1_US[channel - 1] << 8 ) + vhf_table_2_US[channel - 1] + fine; else u = (vhf_table_1_JP[channel - 1] << 8 ) + vhf_table_2_JP[channel - 1] + fine; retries = 0; do { ready = 1; i2cstart (); i2cwdata ((BYTE)((tuntype<<1)&0xFE)); ready &= i2crack (); i2cwdata ((BYTE)(( u >> 8 ) & 0x7F)); /* set DIV1*/ ready &= i2crack (); i2cwdata ((BYTE)(u & 0xFF)); /* set DIV2*/ ready &= i2crack (); i2cwdata (0x8E); /* set CB1*/ ready &= i2crack (); if (country) i2cwdata (vhf_table_3_US[ channel - 1 ]); /* set CB2*/ else i2cwdata (vhf_table_3_JP[ channel - 1 ]); /* set CB2*/ ready &= i2crack (); i2cstop (); if (!ready) retries++; } while (!ready && (retries <= I2CRET)); i2cstart (); i2cwdata ((BYTE)((tuntype<<1)|0x01)); i2crack (); inbbtmp = i2crdata(); i2cwnack (); i2cstop (); return (ready); } /**************************************************************************** * Set up video filter ****************************************************************************/ void SetVideoFilter(WORD video_filter, int index) { Index = index; switch (video_filter) { case 320: /* these settings are to patch the wrong CCIR-601 pixel format into VPX */ FPbusy(); i2cwr8(VPXI2C, 0xD2, 0x00); /* luma prefilter selection*/ i2cwr8(VPXI2C, 0xD3, 0x09); /* writes to the Filter-RAM location 1*/ i2cwr8(VPXI2C, 0xD3, 0x17); /* writes to the Filter-RAM location 2*/ i2cwr8(VPXI2C, 0xD3, 0xC6); /* writes to the Filter-RAM location 3*/ i2cwr8(VPXI2C, 0xD3, 0xE7); /* writes to the Filter-RAM location 4*/ i2cwr8(VPXI2C, 0xD3, 0x79); /* writes to the Filter-RAM location 5*/ i2cwr8(VPXI2C, 0xD3, 0xAB); /* writes to the Filter-RAM location 6*/ i2cwr8(VPXI2C, 0xD3, 0x69); /* writes to the Filter-RAM location 7*/ i2cwr8(VPXI2C, 0xD3, 0x8C); /* writes to the Filter-RAM location 8*/ i2cwr8(VPXI2C, 0xD3, 0x35); /* writes to the Filter-RAM location 9*/ i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 10*/ i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 11*/ i2cwr8(VPXI2C, 0xD3, 0xAA); /* writes to the Filter-RAM location 12*/ i2cwr8(VPXI2C, 0xD3, 0x32); /* writes to the Filter-RAM location 13*/ i2cwr8(VPXI2C, 0xD3, 0x01); /* writes to the Filter-RAM location 14*/ i2cwr8(VPXI2C, 0xD3, 0x20); /* writes to the Filter-RAM location 15*/ i2cwr8(VPXI2C, 0xD0, 0x60); /* RAM and I2C override selection*/ break; case 640: /* The following values are to patch the wrong CCIR-601 pixel format.*/ /* These value settings refer to the 640 NPIX upper bound */ FPbusy(); i2cwr8(VPXI2C, 0xD2, 0x00); /* luma prefilter selection*/ i2cwr8(VPXI2C, 0xD3, 0x81); /* writes to the Filter-RAM location 1*/ i2cwr8(VPXI2C, 0xD3, 0x96); /* writes to the Filter-RAM location 2*/ i2cwr8(VPXI2C, 0xD3, 0x06); /* writes to the Filter-RAM location 3*/ i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 4*/ i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 5*/ i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 6*/ i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 7*/ i2cwr8(VPXI2C, 0xD3, 0x34); /* writes to the Filter-RAM location 8*/ i2cwr8(VPXI2C, 0xD3, 0xD0); /* writes to the Filter-RAM location 9*/ i2cwr8(VPXI2C, 0xD3, 0x02); /* writes to the Filter-RAM location 10*/ i2cwr8(VPXI2C, 0xD3, 0xC8); /* writes to the Filter-RAM location 11*/ i2cwr8(VPXI2C, 0xD3, 0x86); /* writes to the Filter-RAM location 12*/ i2cwr8(VPXI2C, 0xD3, 0x32); /* writes to the Filter-RAM location 13*/ i2cwr8(VPXI2C, 0xD3, 0x01); /* writes to the Filter-RAM location 14*/ i2cwr8(VPXI2C, 0xD3, 0x10); /* writes to the Filter-RAM location 15*/ i2cwr8(VPXI2C, 0xD0, 0x60); /* RAM and I2C override selection*/ break; } } /*****************************************************************************/ void SetVPXColor(BYTE brightness, BYTE contrast, WORD saturation, WORD hue, int index) { Index = index; FPbusy(); i2cwr8 (VPXI2C, CBM_BRI, (BYTE)(brightness-128)); FPbusy(); /* i2cwr8 (VPXI2C, CBM_CON, (contrast & 0x3f) | noise_shaping);*/ i2cwr8 (VPXI2C, CBM_CON, contrast); FPbusy(); i2cwr16 (VPXI2C, FPWR, ACCREF); i2cwr16 (VPXI2C, FPDAT, saturation); FPbusy(); i2cwr16(VPXI2C, FPWR, 0x001C); /* TINT color hue*/ i2cwr16(VPXI2C, FPDAT, hue-2048); /* brightness = def_brightness; SetBrightness(); contrast = def_contrast; noise_shaping = def_noise_shaping; SetContrast(); saturation = def_saturation; SetSaturation(); hue = def_hue; SetHue(); SetFormat(); */ } /**************************************************************************** ** Initialize VPX ****************************************************************************/ void InitVPX(WORD IOBase, BYTE Standard, BYTE Inbut, WORD Width, WORD Height, BYTE SkipRate, BYTE DataFormat, int index) { BYTE inbbtmp; Index = index; SccBase[Index] = IOBase; MemWidth[Index] = Width; MemHeight[Index] = Height; MemStandard[Index] = Standard; /* get VPX version*/ if (0xEC == i2crd8(VPXI2C, I2C_ID0) && 0x80 == i2crd8(VPXI2C, I2C_ID1) && 0x46 == i2crd8(VPXI2C, I2C_ID2)) { VPX_ver[Index] = 1; /* VPX is C4 version*/ } else { VPX_ver[Index] = 0; /* VPX is earlier than C4;*/ } /* set data format*/ i2cwr8(VPXI2C, FORMAT, (BYTE)(0xb0 | (DataFormat & 0x7))); if (!VPX_ver[Index]) SetVideoFilter(640, index); if (Standard == 1) /* NTSC*/ { if (Height > 240) Height = (Height + 1)/2; if (!VPX_ver[Index]) { i2cwr8(VPXI2C, STS, 0x02); /* select the NTSC standard*/ i2cwr16(VPXI2C, FPWR, 0x001C); /* TINT color hue*/ i2cwr16(VPXI2C, FPDAT, 0x0000); FPbusy(); i2cwr8(VPXI2C, DEEM, 0x08); i2cwr8(VPXI2C, LDF, 0x06); /* luma/chroma matching delay*/ i2cwr8(VPXI2C, YNF, 0x39); /* luma notch frequency*/ /* modification for TC05 */ i2cwr16(VPXI2C, FPWR, VSDT); i2cwr16(VPXI2C, FPDAT, 524); FPbusy(); i2cwr16(VPXI2C, FPWR, AGCREF); i2cwr16(VPXI2C, FPDAT, 732); FPbusy(); i2cwr16(VPXI2C, FPWR, ACCREF); i2cwr16(VPXI2C, FPDAT, 2263); FPbusy(); i2cwr16(VPXI2C, FPWR, CLPPK); i2cwr16(VPXI2C, FPDAT, 90); FPbusy(); i2cwr16(VPXI2C, FPWR, SPL); i2cwr16(VPXI2C, FPDAT, 1287); FPbusy(); i2cwr16(VPXI2C, FPWR, BKS); i2cwr16(VPXI2C, FPDAT, 140); FPbusy(); i2cwr16(VPXI2C, FPWR, BKR); i2cwr16(VPXI2C, FPDAT, 204); FPbusy(); i2cwr16(VPXI2C, FPWR, SDT); i2cwr16(VPXI2C, FPDAT, 1); FPbusy(); /* ### KS 05.11.94*/ /* write VREF timing for TC05*/ /**/ i2cwr16(VPXI2C, FPWR, 0x00C0); i2cwr16(VPXI2C, FPDAT, 0x0001); FPbusy(); i2cwr16(VPXI2C, FPWR, 0x00C1); i2cwr16(VPXI2C, FPDAT, 0x0007); FPbusy(); i2cwr16(VPXI2C, FPWR, 0x00C2); i2cwr16(VPXI2C, FPDAT, 0x0108); FPbusy(); i2cwr16(VPXI2C, FPWR, 0x00C3); i2cwr16(VPXI2C, FPDAT, 0x010E); FPbusy(); /* VREF TC02 compatible mode*/ i2cwr16(VPXI2C, FPWR, 0x00F0); i2cwr16(VPXI2C, FPDAT, 0x2); FPbusy(); } else { i2cwr16 (VPXI2C, FPWR, ACCREF); i2cwr16 (VPXI2C, FPDAT, 0x700); FPbusy(); i2cwr16 (VPXI2C, FPWR, TVSTD); i2cwr16 (VPXI2C, FPDAT, 0x13); FPbusy(); i2cwr16 (VPXI2C, FPWR, 0x00C2); i2cwr16 (VPXI2C, FPDAT, 0x0096); FPbusy(); i2cwr16 (VPXI2C, FPWR, 0x00C1); i2cwr16 (VPXI2C, FPDAT, 0x0055); FPbusy(); i2cwr16 (VPXI2C, FPWR, VSDT); i2cwr16 (VPXI2C, FPDAT, 0x20a); FPbusy(); i2cwr16 (VPXI2C, FPWR, IF1IF2); i2cwr16 (VPXI2C, FPDAT, 0x29c); FPbusy(); /* set up for VPX C4*/ i2cwr8 (VPXI2C, REFSIG, 0x06); /* C4 VREF,HREF */ FPbusy(); /* initialize VPX to RGB 565 16 bit Inverse Gamma, dither enabled*/ /* i2cwr8 (VPXI2C, FORMAT, 0xf6);*/ i2cwr8(VPXI2C, FORMAT_C4, (BYTE)(0xf0 | (DataFormat & 0x7))); FPbusy(); i2cwr8 (VPXI2C, OFIFO, 0x0b); FPbusy(); i2cwr8 (VPXI2C, OMUX, 0x88); FPbusy(); i2cwr8 (VPXI2C, OENA, 0x5b); FPbusy(); } } else { if (Height > 290) Height = (Height + 1)/2; if (!VPX_ver[Index]) { i2cwr8(VPXI2C, STS, 0x01); /* select the PAL standard*/ i2cwr8(VPXI2C, DEEM, 0x08); i2cwr8(VPXI2C, LDF, 0x06); /* luma/chroma matching delay*/ i2cwr8(VPXI2C, YNF, 25); /* luma notch frequency*/ /* ### KS 05.11.94*/ /* modification for TC05*/ i2cwr16(VPXI2C, FPWR, VSDT); i2cwr16(VPXI2C, FPDAT, 624); FPbusy(); i2cwr16(VPXI2C, FPWR, AGCREF); i2cwr16(VPXI2C, FPDAT, 768); FPbusy(); i2cwr16(VPXI2C, FPWR, ACCREF); i2cwr16(VPXI2C, FPDAT, 2263); FPbusy(); i2cwr16(VPXI2C, FPWR, CLPPK); i2cwr16(VPXI2C, FPDAT, 54); FPbusy(); i2cwr16(VPXI2C, FPWR, SPL); i2cwr16(VPXI2C, FPDAT, 1296); FPbusy(); i2cwr16(VPXI2C, FPWR, BKS); i2cwr16(VPXI2C, FPDAT, 140); FPbusy(); i2cwr16(VPXI2C, FPWR, BKR); i2cwr16(VPXI2C, FPDAT, 204); FPbusy(); i2cwr16(VPXI2C, FPWR, SDT); i2cwr16(VPXI2C, FPDAT, 0); FPbusy(); /* ### KS 05.11.94*/ /* write VREF timing for TC05*/ /**/ i2cwr16(VPXI2C, FPWR, 0x00C0); i2cwr16(VPXI2C, FPDAT, 0x0001); FPbusy(); i2cwr16(VPXI2C, FPWR, 0x00C1); i2cwr16(VPXI2C, FPDAT, 0x0007); FPbusy(); i2cwr16(VPXI2C, FPWR, 0x00C2); i2cwr16(VPXI2C, FPDAT, 0x013a); FPbusy(); i2cwr16(VPXI2C, FPWR, 0x00C3); i2cwr16(VPXI2C, FPDAT, 0x0140); FPbusy(); /* VREF TC02 compatible mode*/ i2cwr16(VPXI2C, FPWR, 0x00F0); i2cwr16(VPXI2C, FPDAT, 0x2); FPbusy(); } else { i2cwr16 (VPXI2C, FPWR, ACCREF); i2cwr16 (VPXI2C, FPDAT, 0x7d0); FPbusy(); i2cwr16 (VPXI2C, FPWR, TVSTD); i2cwr16 (VPXI2C, FPDAT, 0x11); FPbusy(); i2cwr16 (VPXI2C, FPWR, 0x00C2); i2cwr16 (VPXI2C, FPDAT, 0x0096); FPbusy(); i2cwr16 (VPXI2C, FPWR, 0x00C1); i2cwr16 (VPXI2C, FPDAT, 0x0055); FPbusy(); i2cwr16 (VPXI2C, FPWR, VSDT); i2cwr16 (VPXI2C, FPDAT, 0x26e); FPbusy(); i2cwr16 (VPXI2C, FPWR, IF1IF2); i2cwr16 (VPXI2C, FPDAT, 0x29c); FPbusy(); /* set up for VPX C4*/ i2cwr8 (VPXI2C, REFSIG, 0x06); /* C4 VREF,HREF */ FPbusy(); /* initialize VPX to RGB 565 16 bit Inverse Gamma, dither enabled*/ /* i2cwr8 (VPXI2C, FORMAT, 0xf6);*/ i2cwr8(VPXI2C, FORMAT_C4, (BYTE)(0xf0 | (DataFormat & 0x7))); FPbusy(); i2cwr8 (VPXI2C, OFIFO, 0x0b); FPbusy(); i2cwr8 (VPXI2C, OMUX, 0x88); FPbusy(); i2cwr8 (VPXI2C, OENA, 0x5b); FPbusy(); } } if (!VPX_ver[Index]) do { FPbusy(); i2cwr16(VPXI2C, FPRD, CWDWD); } while (i2crd16 (VPXI2C, FPDAT) & 0x30); else do { FPbusy(); i2cwr16(VPXI2C, FPRD, CWDWD_C4); } while (i2crd16 (VPXI2C, FPDAT) & 0x72); outp(IOBase, 0x00); /* clear the status register*/ while ((inp(IOBase) & 0x40)); /*-------------------------------------------------------------------*/ switch (Inbut) { case 0: /* switch to Video Inbut 1 */ FPbusy(); i2cwr8(VPXI2C, AFEND, 0x02); inbbtmp = i2crd8 (VPXI2C, STS); i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp & 0xFB)); break; case 1: /* switch to Video Inbut 2 */ FPbusy(); i2cwr8(VPXI2C, AFEND, 0x01); inbbtmp = i2crd8 (VPXI2C, STS); i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp & 0xFB)); break; case 2: /* switch to Video Inbut 3 */ FPbusy(); i2cwr8(VPXI2C, AFEND, 0x00); inbbtmp = i2crd8 (VPXI2C, STS); i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp & 0xFB)); break; case 3: /* switch to S-Video Inbut */ FPbusy(); i2cwr8(VPXI2C, AFEND, 0x08); inbbtmp = i2crd8 (VPXI2C, STS); i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp | 0x04)); break; } /*---------------------------------------------------------------------*/ outp(IOBase+1, 0x04); /* if (mem_wait_states)*/ /* outp(IOBase+3, 0x4D); // enable terminator resistors (SIC) */ /* else*/ outp(IOBase+3, 0x0D); /* enable terminator resistors (SIC)*/ outp(IOBase+1, 0x04); /* skip 1 field*/ outp(IOBase+2, (BYTE)((inp(IOBase+2) & 0x1f) | (SkipRate << 5))); SetVPXRect(Width, Height, index); } /**************************************************************************** ** Set VPX rect *****************************************************************************/ void SetVPXRect(WORD Width, WORD Height, int index) { Index = index; MemWidth[Index] = Width; MemHeight[Index] = Height; if (Height > 240) Height = (Height + 1)/2; if (MemStandard[Index] == 1) { /* set the source video window */ FPbusy(); i2cwr16(VPXI2C, FPWR, VBEG1); i2cwr16(VPXI2C, FPDAT, 12); FPbusy(); i2cwr16(VPXI2C, FPWR, VLINEI1); i2cwr16(VPXI2C, FPDAT, 248); FPbusy(); i2cwr16(VPXI2C, FPWR, VLINEO1); i2cwr16(VPXI2C, FPDAT, Height+8); FPbusy(); i2cwr16(VPXI2C, FPWR, HBEG1); i2cwr16(VPXI2C, FPDAT, 10); FPbusy(); i2cwr16(VPXI2C, FPWR, HLEN1); i2cwr16(VPXI2C, FPDAT, Width); FPbusy(); i2cwr16(VPXI2C, FPWR, NPIX1); i2cwr16(VPXI2C, FPDAT, Width + 10); FPbusy(); /* switches off Window 2*/ i2cwr16(VPXI2C, FPWR, VLINEI2); i2cwr16(VPXI2C, FPDAT, 0); FPbusy(); if (!VPX_ver[Index]) { i2cwr16(VPXI2C, FPWR, CWDWD); i2cwr16(VPXI2C, FPDAT, 0x0032); } else { i2cwr16(VPXI2C, FPWR, CWDWD_C4); i2cwr16(VPXI2C, FPDAT, 0x0077); } } else { /* set the source video window */ FPbusy(); i2cwr16(VPXI2C, FPWR, VBEG1); i2cwr16(VPXI2C, FPDAT, 12); FPbusy(); i2cwr16(VPXI2C, FPWR, VLINEI1); i2cwr16(VPXI2C, FPDAT, 298); FPbusy(); i2cwr16(VPXI2C, FPWR, VLINEO1); i2cwr16(VPXI2C, FPDAT, Height+8); FPbusy(); i2cwr16(VPXI2C, FPWR, HBEG1); i2cwr16(VPXI2C, FPDAT, 15); FPbusy(); i2cwr16(VPXI2C, FPWR, HLEN1); i2cwr16(VPXI2C, FPDAT, Width); FPbusy(); i2cwr16(VPXI2C, FPWR, NPIX1); i2cwr16(VPXI2C, FPDAT, Width + 10); FPbusy(); /* switches off Window 2*/ i2cwr16(VPXI2C, FPWR, VLINEI2); i2cwr16(VPXI2C, FPDAT, 0); FPbusy(); if (!VPX_ver[Index]) { i2cwr16(VPXI2C, FPWR, CWDWD); i2cwr16(VPXI2C, FPDAT, 0x0032); } else { i2cwr16(VPXI2C, FPWR, CWDWD_C4); i2cwr16(VPXI2C, FPDAT, 0x0077); } } if (!VPX_ver[Index]) do { FPbusy(); i2cwr16(VPXI2C, FPRD, CWDWD); } while (i2crd16 (VPXI2C, FPDAT) & 0x30); else do { FPbusy(); i2cwr16(VPXI2C, FPRD, CWDWD_C4); } while (i2crd16 (VPXI2C, FPDAT) & 0x72); while (inp(SccBase[Index]) & 0x20); while (!(inp(SccBase[Index]) & 0x20)); while (inp(SccBase[Index]) & 0x20); while (!(inp(SccBase[Index]) & 0x20)); } /**************************************************************************** ** Freeze VPX *****************************************************************************/ void FreezeVPX(BYTE Action, int index) { static WORD CopyWidth; static WORD CopyHeight; Index = index; switch (Action) { case 0: CopyWidth = MemWidth[Index]; CopyHeight = MemHeight[Index]; SetVPXRect(20, 0, index); break; case 1: SetVPXRect(CopyWidth, CopyHeight, index); break; case 2: outp(SccBase[Index]+1, 0x04); outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) | 0x10)); while (inp(SccBase[Index]) & 0x20); break; case 3: outp(SccBase[Index]+1, 0x04); outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) & 0xef)); break; } } /**************************************************************************** ** Set Format ***************************************************************************/ void SetVPXFmt(BYTE DataFormat, int index) { Index = index; i2cwr8(VPXI2C, FORMAT, (BYTE)(0xb0 | (DataFormat & 0x7))); } /**************************************************************************** ** Set IRQ state ***************************************************************************/ void SetIRQState(BYTE State, int index) { Index = index; /* outp(SccBase[Index]+1, 0x04);*/ switch (State) { case 0: outp(SccBase[Index]+1, 0x04); outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) & 0xfd)); break; case 1: outp(SccBase[Index]+1, 0x04); outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) | 2)); break; case 2: outp(SccBase[Index], (BYTE)(inp(SccBase[Index]) & 0xfd)); break; } } /**************************************************************************** ** Set IRQ state ****************************************************************************/ void WaitCapture(BYTE Wait, int index) { short i; Index = index; for (i=0;i