/* * * Header for I2C constants * * Authors: Brett W. Thompson, Gilberto Morejon, Alex Rudnick * */ /* This is the device's unique ID */ #define HRT_AD_DEVICE_ID (128+16+8+4) static unsigned char i2c_startcmd[] = { 0, 2, 3, 1, 0 }; static unsigned char i2c_stopcmd[] = { 0, 1, 3, 2, 3 }; static unsigned long i2c_offset = 0x2001; static int sd = 10; /* Thanks to Dr. Baker for informative comments for each byte */ const unsigned char i2c_datalow[] = { 0x4c, /* 0x00 - increment delay (IDEL) = */ 0x3c, /* 0x01 - HSY begin 50 Hz */ 0x0d, /* 0x02 - HSY stop 50 Hz */ 0xef, /* 0x03 - HCL begin 50 Hz */ 0xbd, /* 0x04 - HCL stop 50 Hz */ 0xf0, /* 0x05 - HSY after PHI1 50 Hz */ 0x00, /* 0x06 - luminance control */ 0x00, /* 0x07 - hue control */ 0xf8, /* 0x08 - colour killer threshold QUAM (PAL/NTSC) */ 0xf8, /* 0x09 - colour killer threshold SECAM */ 0x60, /* 0x0A - PAL switch sensitivity */ 0x50, /* 0x0B - SECAM switch sensitivity */ 0x00, /* 0x0C - gain control chrominance */ 0x86, /* 0x0D - standard/mode control */ /* 7 VTRC = 1 (VCR mode, not TV) 6 XXX 5 XXX 4 XXX 3 RTSE = 0 (PLIN switched to output) 2 HRMV = 1 (HREF normal position) 1 SSTB = 1 (status byte = 1) 0 SECS = 0 (other standards, not SECAM) */ 0x18, /* 0x0E - I/O and clock control */ 0x90, /* 0x0F - control #1 */ 0x00, /* 0x10 - control #2 */ 0x2c, /* 0x11 - chrominance gain reference */ 0x7f, /* 0x12 - chrominance saturation */ 0x5e, /* 0x13 - luminance contrast */ 0x42, /* 0x14 - HSY begin 60 Hz */ 0x1a, /* 0x15 - HSY stop 60 Hz */ 0xff, /* 0x16 - HCL begin 60 Hz */ 0xda, /* 0x17 - HCL stop 60 Hz */ 0xf0, /* 0x18 - HSY after PHI1 60 Hz */ 0x9b /* 0x19 - luminance brightness */ }; /* 1A - not used */ /* 1B - not used */ /* 1C - not used */ /* 1D - not used */ /* 1E - not used */ /* 1F - not used */ const unsigned char i2c_datahigh[] = { 0x7c, /* 0x20 - analog control #1 */ 0x03, /* 0x21 - analog control #2 */ 0xd2, /* 0x22 - mixer control #1 */ 0x41, /* 0x23 - clamping level control 21 */ 0x80, /* 0x24 - clamping level control 22 */ 0x41, /* 0x25 - clamping level control 31 */ 0x80, /* 0x26 - clamping level control 32 */ 0x4f, /* 0x27 - gain control #1*/ 0xfe, /* 0x28 - white peak control*/ 0x01, /* 0x29 - sync bottom control */ 0xcf, /* 0x2A - gain control analog #2 */ 0x0f, /* 0x2B - gain control analog #3 */ 0x83, /* 0x2C - mixer control #2 */ 0x01, /* 0x2D - integration value gain */ 0x81, /* 0x2E - vertical blanking pulse set */ 0x03, /* 0x2F - vertical blanking pulse reset */ 0x60, /* 0x30 - ADCs gain control */ 0x71, /* 0x31 - mixer control #3 */ 0x02, /* 0x32 - integration value white peak */ 0x8c, /* 0x33 - mixer control #4 */ 0x03 /* 0x34 - gain update level */ }; struct i2c_regval { int reg; unsigned char val; }; /* I2C routines */ int i2c_busy(unsigned long addr) { int rv; rv = !(readb(addr + 0x2000) & 0x80); rmb(); return rv; } void i2c_sendstop(unsigned long addr) { int i; for (i = 0; i < 5; i++) { writeb(i2c_stopcmd[i], i2c_offset + addr); wmb(); udelay(sd); } } void i2c_sendstart(unsigned long addr) { int i; for (i = 0; i < 5; i++) { writeb(i2c_startcmd[i], i2c_offset + addr); wmb(); udelay(sd); } } void i2c_sendbit(unsigned long addr, unsigned char sda) { unsigned long i2c = i2c_offset + addr; static int dontfreeze = 0; writeb(sda << 1, i2c); wmb(); udelay(sd); writeb((sda << 1) + 4, i2c); wmb(); for (;;) { if (i2c_busy(addr)) { mdelay(1); schedule(); dontfreeze++; if (dontfreeze > 10000) break; } else { break; } } writeb(2, i2c); wmb(); udelay(sd); } void i2c_sendbyte(unsigned long addr, unsigned char byte) { int i, sda; unsigned char ack; unsigned long i2c = i2c_offset + addr; for (i = 7; i >= 0; i--) { sda = (byte & (1 << i)) >> i; i2c_sendbit(addr, sda); } writeb(3, i2c); wmb(); udelay(sd); ack = readb(i2c); rmb(); if ((ack & 2) == 2) { printk("<1>Error: no ACK after sending a databyte\n"); } writeb(2, i2c); wmb(); } void init_i2c(unsigned long addr) { int i; i2c_sendstop(addr); /* Send start command */ i2c_sendstart(addr); /* Send unique A/D address */ i2c_sendbyte(addr, HRT_AD_DEVICE_ID); /* Set device's pointer to 0 */ i2c_sendbyte(addr, 0); for (i = 0; i < 26; i++) { i2c_sendbyte(addr, i2c_datalow[i]); } i2c_sendstop(addr); i2c_sendstart(addr); i2c_sendbyte(addr, HRT_AD_DEVICE_ID); /* Set address pointer = 0x20 */ i2c_sendbyte(addr, 0x20); for (i = 0; i < 21; i++) { i2c_sendbyte(addr, i2c_datahigh[i]); } i2c_sendstop(addr); } void shutdown_i2c(unsigned long addr) { int i; i2c_sendstop(addr); /* Send start command */ i2c_sendstart(addr); /* Send unique A/D address */ i2c_sendbyte(addr, HRT_AD_DEVICE_ID); /* Set device's pointer to 0 */ i2c_sendbyte(addr, 0); for (i = 0; i < 26; i++) { i2c_sendbyte(addr, 0); } i2c_sendstop(addr); i2c_sendstart(addr); i2c_sendbyte(addr, HRT_AD_DEVICE_ID); /* Set address pointer = 0x20 */ i2c_sendbyte(addr, 0x20); for (i = 0; i < 21; i++) { i2c_sendbyte(addr, 0); } i2c_sendstop(addr); } /* Set an I2C register */ int i2c_set_reg(unsigned long addr, int reg, unsigned char val) { i2c_sendstart(addr); i2c_sendbyte(addr, HRT_AD_DEVICE_ID); i2c_sendbyte(addr, reg); i2c_sendbyte(addr, val); i2c_sendstop(addr); return val; } int set_brightness(unsigned long addr, unsigned char b) { i2c_set_reg(addr, 0x19, b); return b; } int set_contrast(unsigned long addr, unsigned char c) { i2c_set_reg(addr, 0x13, c); return c; }