Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

338 lines
8.7 KiB

/*
* hardware.c
*
* 32-bit Video Capture driver
* internal hardware control functions
*
* Geraint Davies, Feb 93
*/
#include <vckernel.h>
#include <spigot.h>
#include "hardware.h"
#include "hwstruct.h"
VOID HW_SetTOFOffset(PDEVICE_INFO pDevInfo, PHWINFO pHw);
/* --- support functions -------------------------------------------- */
/*
* set up the demodulator according to the video standard (ntsc, pal
* or secam).
*/
VOID
HW_SetVideoStandard(PDEVICE_INFO pDevInfo, PHWINFO pHw)
{
static I2CDATA std7191[MAXVIDEOSTD][REGISTERS_7191] = {
{ // VF_NTSC...
{0x00,0x50}, // IDEL
{0x01,0x30}, // HSY begin 50Hz
{0x02,0x00}, // HSY stop 50Hz
{0x03,0xe8}, // HCL begin 50Hz
{0x04,0xb6}, // HCL stop 50Hz
{0x05,0xf4}, // HSY after PHI1 50Hz
{0x06,0x01}, // luminance control
{0x07,0x00}, // hue control
{0x08,0xf8}, // color killer threshold QAM
{0x09,0xf8}, // color killer threshold SECAM
{0x0a,0x90}, // sensitivity PAL switch
{0x0b,0x90}, // sensitivity SECAM switch
{0x0c,0x00}, // gain control
{0x0d,0x00}, // standard/mode control
{0x0e,0x30}, // i/o and clock control
{0x0f,0x99}, // control #3
{0x10,0x00}, // control #4
{0x11,0x2c}, // chrominance control value
{0x14,0x34}, // HSY begin 60Hz
{0x15,0x0a}, // HSY stop 60Hz
{0x16,0xf4}, // HCL begin 60Hz
{0x17,0xce}, // HCL stop 60Hz
{0x18,0xf4} // HSY after PHI1 60Hz
},
{ // VF_PAL...
{0x00,0x50}, // IDEL
{0x01,0x30}, // HSY begin 50Hz
{0x02,0x00}, // HSY stop 50Hz
{0x03,0xe8}, // HCL begin 50Hz
{0x04,0xb6}, // HCL stop 50Hz
{0x05,0xf4}, // HSY after PHI1 50Hz
{0x06,0x01}, // luminance control
{0x07,0x00}, // hue control
{0x08,0xf8}, // color killer threshold QAM
{0x09,0xf8}, // color killer threshold SECAM
{0x0a,0x90}, // sensitivity PAL switch
{0x0b,0x90}, // sensitivity SECAM switch
{0x0c,0x00}, // gain control
{0x0d,0x00}, // standard/mode control
{0x0e,0x30}, // i/o and clock control
{0x0f,0x99}, // control #3
{0x10,0x00}, // control #4
{0x11,0x59}, // chrominance control value
{0x14,0x34}, // HSY begin 60Hz
{0x15,0x0a}, // HSY stop 60Hz
{0x16,0xf4}, // HCL begin 60Hz
{0x17,0xce}, // HCL stop 60Hz
{0x18,0xf4} // HSY after PHI1 60Hz
},
{ // VF_SECAM...
{0x00,0x50}, // IDEL
{0x01,0x30}, // HSY begin 50Hz
{0x02,0x00}, // HSY stop 50Hz
{0x03,0xe8}, // HCL begin 50Hz
{0x04,0xb6}, // HCL stop 50Hz
{0x05,0xf4}, // HSY after PHI1 50Hz
{0x06,0x01}, // luminance control
{0x07,0x00}, // hue control
{0x08,0xf8}, // color killer threshold QAM
{0x09,0xf8}, // color killer threshold SECAM
{0x0a,0x90}, // sensitivity PAL switch
{0x0b,0x90}, // sensitivity SECAM switch
{0x0c,0x00}, // gain control
{0x0d,0x01}, // standard/mode control
{0x0e,0x30}, // i/o and clock control
{0x0f,0x99}, // control #3
{0x10,0x00}, // control #4
{0x11,0x2c}, // chrominance control value
{0x14,0x34}, // HSY begin 60Hz
{0x15,0x0a}, // HSY stop 60Hz
{0x16,0xf4}, // HCL begin 60Hz
{0x17,0xce}, // HCL stop 60Hz
{0x18,0xf4} // HSY after PHI1 60Hz
}
};
int i;
BYTE ucMode,ucHue,ucSource;
// remember current settings for the dynamic parameters
ucMode = pHw->Init7191[REG_7191_MODE].bI2CData & 0x80;
ucHue = pHw->Init7191[REG_7191_HUE].bI2CData;
ucSource = pHw->Init7191[REG_7191_IOCLK].bI2CData & 3;
// initialize the SAA7191 chip...
for (i = 0; i < REGISTERS_7191; i++) {
// load values into our h/w info struct
pHw->Init7191[i] = std7191[pHw->VideoStd][i];
switch (i) { // add in dynamic parameter settings...
case REG_7191_HUE: { // hardware hue adjustment
pHw->Init7191[i].bI2CData = ucHue;
break;
}
case REG_7191_IOCLK: { // video source
pHw->Init7191[i].bI2CData |= ucSource;
break;
}
case REG_7191_MODE: { // VCR flag
pHw->Init7191[i].bI2CData |= ucMode;
break;
}
}
// send the data out to the device
HW_Set7191Reg(pDevInfo,
pHw->Init7191[i].bI2CReg, pHw->Init7191[i].bI2CData);
}
// initialize # lines we drop at top of screen...
HW_SetTOFOffset(pDevInfo, pHw);
}
/*
* set the video-standard-dependent top of form offset - the number of
* lines at start of field that are discarded before reaching the fifo.
*/
VOID HW_SetTOFOffset(PDEVICE_INFO pDevInfo, PHWINFO pHw)
{
pHw->bImage = (pHw->bImage & ~TOF_OFFSET_BITS) |
TOF_OFFSET(pHw->StdTOFOffset[pHw->VideoStd]);
VC_Out(pDevInfo, PORT_IMAGE, pHw->bImage);
}
/*
* select which of the source connectors to use, the SVideo or the composite.
* If autodetect is selected, then look for the connector that has an
* active signal.
*
* Sets the hardware up to reflect the selector specified in pHw->VideoSrc.
*/
VOID
HW_SetVideoSource(PDEVICE_INFO pDevInfo, PHWINFO pHw)
{
/*
* store the new setting in our list of 7191 registers, and write to device
*/
pHw->Init7191[REG_7191_IOCLK].bI2CData =
(pHw->Init7191[REG_7191_IOCLK].bI2CData & 0xfc) | pHw->VideoSrc;
// send the data out to the device
HW_Set7191Reg(
pDevInfo,
REG_7191_IOCLK,
pHw->Init7191[REG_7191_IOCLK].bI2CData);
/* we need to wait for 4 field times for the signal to be locked onto
* (so that a call to HW_HaveHLck() will get a valid answer).
* Rather than poll, we'll sleep for the estimated length of 4 fields.
*/
VC_Delay((pHw->VideoStd == NTSC ? 1000/60 : 1000/50) * 4 );
}
/*
* check if we have a valid signal coming in: request a status byte from the
* demodulator and see if it thinks it is locked on.
*/
BOOL
HW_HaveHLck(PDEVICE_INFO pDevInfo, PHWINFO pHw)
{
BYTE bStatus;
/* read a byte from 7191 via the I2C bus */
bStatus = HW_Get7191Reg(pDevInfo);
/* remember that the lock bit is inverted */
return(! (bStatus & NO_HLOCK));
}
/*
* find which of the two connections has a valid input signal - set each
* in turn as the source and see if the 7191 locks on.
* this routine is only called if we have SPG_SOURCEAUTO and have to search
* for the input video signal
*/
BOOL
HW_GetActiveSource(PDEVICE_INFO pDevInfo, PHWINFO pHw)
{
int Retries;
for (Retries = 2; Retries--; ) {
/* check if we have a signal */
if (HW_HaveHLck(pDevInfo, pHw)) {
return(TRUE);
}
/* try the other connector */
/* pHw->VideoSrc MUST only contain SVideo or Composite */
pHw->VideoSrc ^= SVideo; // switch SVideo <-> Composite
// Assertion: SVideo == 1, Composite == 0
// note: on exit, if we did not find a source, then pHw->VideoSrc is
// the same as on entry. This means that if the signal returns we
// will automatically pick up the same source as last worked.
/*
* set pHw->VideoSrc as the current source - also waits for
* signal to settle
*/
HW_SetVideoSource(pDevInfo, pHw);
/*
* We ensure that the contents of pHw->VideoSrc and the hardware
* register stay in sync.
*/
}
dprintf2(("GetActiveSource cannot find a source, current setting is %d", pHw->VideoSrc));
return(FALSE);
}
/*
* given the destination capture size in pHw->dwWidth x pHw->dwHeight,
* set the hardware and capture flags for this size
*/
VOID
HW_SetDisplayRect(PDEVICE_INFO pDevInfo, PHWINFO pHw)
{
int ratio, scale;
switch(pHw->dwWidth)
{
case (VIDEO_WIDTH_NTSC / 8):
case (VIDEO_WIDTH_PAL / 8):
ratio = 1;
scale = SIZE_1_8;
break;
case (VIDEO_WIDTH_NTSC / 4):
case (VIDEO_WIDTH_PAL / 4):
ratio = 2;
scale = SIZE_1_4;
break;
case ((VIDEO_WIDTH_NTSC * 3) / 8):
case ((VIDEO_WIDTH_PAL * 3) / 8):
ratio = 3;
scale = SIZE_3_8;
break;
case (VIDEO_WIDTH_NTSC / 2):
case (VIDEO_WIDTH_PAL / 2):
ratio = 4;
scale = SIZE_1_2;
break;
case VIDEO_WIDTH_NTSC:
case VIDEO_WIDTH_PAL:
ratio = 8;
scale = SIZE_FULL;
break;
};
/* write new scale bits to device and record in pHw*/
pHw->bImage = (pHw->bImage & ~SIZE_BITS) | scale;
VC_Out(pDevInfo, PORT_IMAGE, pHw->bImage);
/*
* calculate the number of scans that go into the fifo each capture
*/
pHw->nScansInField = pHw->dwHeight;
/*
* is this larger than one field: if so, it is also larger than the fifo
*/
if (pHw->nScansInField >= TWO_FIELD_SIZE) {
/* note that capture is larger than fifo */
pHw->dwFlags |= SPG_BLARGE;
/* capture only one field and scan-double later */
pHw->nScansInField /= 2;
} else {
pHw->dwFlags &= ~SPG_BLARGE;
}
/* set the re-arm threshold: when the fifo is down to this many lines,
* its safe to start the next capture.
*/
pHw->nThreshold = (pHw->ThresholdTable[ratio-1] * pHw->nScansInField) /100;
/* force to even */
pHw->nThreshold &= ~1;
}