diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2006-07-06 14:56:42 -0600 |
---|---|---|
committer | Jordan Crouse <jordan.crouse@amd.com> | 2006-07-06 14:56:42 -0600 |
commit | c3ab9f1a60afe1f5e86db1cf2635acda14fae2f5 (patch) | |
tree | 00cfb19765f276220eb794553b545e9f67402688 /src/cim |
Initial commit of the xf86-video-amd tree
Diffstat (limited to 'src/cim')
-rw-r--r-- | src/cim/cim_defs.h | 719 | ||||
-rw-r--r-- | src/cim/cim_defs.h.rej | 45 | ||||
-rw-r--r-- | src/cim/cim_df.c | 2581 | ||||
-rw-r--r-- | src/cim/cim_filter.c | 547 | ||||
-rw-r--r-- | src/cim/cim_gp.c | 3392 | ||||
-rw-r--r-- | src/cim/cim_init.c | 223 | ||||
-rw-r--r-- | src/cim/cim_modes.c | 1905 | ||||
-rw-r--r-- | src/cim/cim_msr.c | 434 | ||||
-rw-r--r-- | src/cim/cim_parm.h | 1284 | ||||
-rw-r--r-- | src/cim/cim_regs.h | 1252 | ||||
-rw-r--r-- | src/cim/cim_rtns.h | 392 | ||||
-rw-r--r-- | src/cim/cim_version.h | 31 | ||||
-rw-r--r-- | src/cim/cim_vg.c | 3711 | ||||
-rw-r--r-- | src/cim/cim_vip.c | 1640 | ||||
-rw-r--r-- | src/cim/cim_vop.c | 604 | ||||
-rw-r--r-- | src/cim/doc/release.txt | 48 |
16 files changed, 18808 insertions, 0 deletions
diff --git a/src/cim/cim_defs.h b/src/cim/cim_defs.h new file mode 100644 index 0000000..638ba8e --- /dev/null +++ b/src/cim/cim_defs.h @@ -0,0 +1,719 @@ + /* + * <LIC_AMD_STD> + * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved. + * </LIC_AMD_STD> + * + * <CTL_AMD_STD> + * </CTL_AMD_STD> + * + * <DOC_AMD_STD> + * Cimarron hardware access macros. + * </DOC_AMD_STD> + * + */ + +#ifndef _cim_defs_h +#define _cim_defs_h + +/*-----------------------------------------*/ +/* MEMORY ACCESS MACROS */ +/*-----------------------------------------*/ + +#ifndef CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS + +#define READ_GP32(offset) \ + (*(volatile unsigned long *)(cim_gp_ptr + (offset))) + +#define READ_REG32(offset) \ + (*(volatile unsigned long *)(cim_vg_ptr + (offset))) + +#define READ_FB32(offset) \ + (*(volatile unsigned long *)(cim_fb_ptr + (offset))) + +#define WRITE_GP32(offset, value) \ + (*(volatile unsigned long *)(cim_gp_ptr + (offset))) = (value) + +#define WRITE_REG32(offset, value) \ + (*(volatile unsigned long *)(cim_vg_ptr + (offset))) = (value) + +#define WRITE_COMMAND32(offset, value) \ + (*(unsigned long *)(cim_cmd_ptr + (offset))) = (value) + +#define WRITE_COMMAND8(offset, value) \ + (*(unsigned char *)(cim_cmd_ptr + (offset))) = (value) + +#define WRITE_FB32(offset, value) \ + (*(unsigned long *)(cim_fb_ptr + (offset))) = (value) + +#define READ_VID32(offset) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) + +#define WRITE_VID32(offset, value) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value) + +#define READ_VIP32(offset) \ + (*(volatile unsigned long *)(cim_vip_ptr + (offset))) + +#define WRITE_VIP32(offset, value) \ + (*(volatile unsigned long *)(cim_vip_ptr + (offset))) = (value) + +#define READ_VOP32(offset) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) + +#define WRITE_VOP32(offset, value) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value) + +#endif + +/*-----------------------------------------*/ +/* GP POLLING MACROS */ +/*-----------------------------------------*/ + +#define GP3_WAIT_WRAP(variable) \ + while(((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) || \ + (variable <= (gp3_cmd_top + GP3_BLT_COMMAND_SIZE + GP3_BLT_COMMAND_SIZE + 96))) + +#define GP3_WAIT_PRIMITIVE(variable) \ + while (((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) && \ + (variable <= (gp3_cmd_next + 96))) + +#define GP3_WAIT_BUSY \ + while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_BUSY) + +#define GP3_WAIT_PENDING \ + while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_PENDING) + +/*-----------------------------------------------------------------*/ +/* MSR MACROS */ +/* These macros facilitate interaction with the model specific */ +/* registers in GeodeLX. There are two included methods, direct */ +/* access using the rdmsr and wrmsr opcodes and an indirect method */ +/* using VSAII. */ +/*-----------------------------------------------------------------*/ + +#ifdef CIMARRON_INCLUDE_MSR_MACROS + +#if CIMARRON_MSR_DIRECT_ASM + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + _asm { mov ecx, msr_add } \ + _asm { rdmsr } \ + _asm { mov data_high, edx } \ + _asm { mov data_low, eax } \ + \ + ((Q_WORD *)(data64_ptr))->high = data_high; \ + ((Q_WORD *)(data64_ptr))->low = data_low; \ +} + +/*----------------------------------------------------------------- + * MSR_WRITE + * Write the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + \ + data_high = ((Q_WORD *)(data64_ptr))->high; \ + data_low = ((Q_WORD *)(data64_ptr))->low; \ + \ + _asm { mov ecx, msr_add } \ + _asm { mov edx, data_high } \ + _asm { mov eax, data_low } \ + _asm { wrmsr } \ +} + +#elif CIMARRON_MSR_VSA_IO + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + \ + _asm { mov dx, 0x0AC1C } \ + _asm { mov eax, 0x0FC530007 } \ + _asm { out dx, eax } \ + \ + _asm { add dl, 2 } \ + _asm { mov ecx, msr_add } \ + _asm { in ax, dx } \ + _asm { mov data_high, edx } \ + _asm { mov data_low, eax } \ + \ + ((Q_WORD *)(data64_ptr))->high = data_high; \ + ((Q_WORD *)(data64_ptr))->low = data_low; \ +} + +/*----------------------------------------------------------------- + * MSR_WRITE + * Write the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + \ + data_high = ((Q_WORD *)(data64_ptr))->high; \ + data_low = ((Q_WORD *)(data64_ptr))->low; \ + \ + _asm { mov dx, 0x0AC1C } \ + _asm { mov eax, 0x0FC530007 } \ + _asm { out dx, eax } \ + \ + _asm { add dl, 2 } \ + _asm { mov ecx, msr_add } \ + _asm { mov ebx, data_high } \ + _asm { mov eax, data_low } \ + \ + _asm { mov esi, 0 } \ + _asm { mov edi, 0 } \ + _asm { out dx, ax } \ +} + +#elif CIMARRON_MSR_ABSTRACTED_ASM + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr,adr,val) \ + __asm__ __volatile__( \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " in %%dx, %%ax" \ + : "=a" ((val)->low), "=d" ((val)->high) \ + : "c" (msr | adr)) + +/*----------------------------------------------------------------- + * MSR_WRITE + * Write the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr,adr,val) \ + { int d0, d1, d2, d3; \ + __asm__ __volatile__( \ + " push %%ebx\n" \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " mov %4, %3\n" \ + " mov 0(%5), %%ebx\n" \ + " mov 4(%5), %0\n" \ + " xor %2, %2\n" \ + " xor %1, %1\n" \ + " out %%ax, %%dx\n" \ + " pop %%ebx\n" \ + : "=a" (d0), "=&D" (d1), "=&S" (d2), "=c" (d3) \ + : "1" (msr | adr), "2" (val)); \ + } + +#elif CIMARRON_MSR_KERNEL_ROUTINE + +#include "asm/msr.h" + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long addr, val1, val2; \ + \ + addr = device_add | msr_reg; \ + rdmsr (addr, val1, val2); \ + \ + ((Q_WORD *)(data64_ptr))->high = val2; \ + ((Q_WORD *)(data64_ptr))->low = val1; \ +} + +/*----------------------------------------------------------------- + * MSR_WRITE + * Read the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long addr, val1, val2; \ + \ + val2 = ((Q_WORD *)(data64_ptr))->high; \ + val1 = ((Q_WORD *)(data64_ptr))->low; \ + \ + addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg; \ + wrmsr(addr, val1, val2); \ +} + +#endif + +#endif /* #ifdef CIMARRON_INCLUDE_MSR_MACROS */ + +/*-----------------------------------------------------------------*/ +/* STRING MACROS */ +/* These macros are included to facilitate the optimization of */ +/* routines that write or copy large amounts of data. Two vesions */ +/* of these macros are included. One is intended for operating */ +/* systems that allow the use of inline assembly, while the other */ +/* is a pure C implementation for stricter operating systems. */ +/*-----------------------------------------------------------------*/ + +#ifdef CIMARRON_INCLUDE_STRING_MACROS + +#if CIMARRON_OPTIMIZE_ASSEMBLY + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING32 + * Write a series of DWORDs to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ +{ \ + _asm { cld } \ + _asm { mov edi, cim_cmd_ptr } \ + _asm { add edi, offset } \ + _asm { mov esi, dataptr } \ + _asm { add esi, dataoffset } \ + _asm { mov ecx, dword_count } \ + _asm { rep movsd } \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_STRING32 + * Write a series of DWORDS to video memory. + *-----------------------------------------------------------------*/ + +#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ +{ \ + unsigned long temp = (unsigned long)(dataptr); \ + _asm { cld } \ + _asm { mov edi, cim_fb_ptr } \ + _asm { add edi, offset } \ + _asm { mov esi, temp } \ + _asm { mov ecx, dword_count } \ + _asm { rep movsd } \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_CONSTANT + * Write a constant DWORD to multiple video memory addresses + *-----------------------------------------------------------------*/ + +#define WRITE_FB_CONSTANT(offset, value, dword_count) \ +{ \ + unsigned long outptr = (unsigned long)cim_fb_ptr + offset; \ + unsigned long dwords = dword_count; \ + _asm { cld } \ + _asm { mov edi, outptr } \ + _asm { mov eax, value } \ + _asm { mov ecx, dwords } \ + _asm { rep stosd } \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING32 + * Write a series of DWORDs to the GP host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ +{ \ + _asm { cld } \ + _asm { mov edi, cim_gp_ptr } \ + _asm { add edi, GP3_HST_SRC_RANGE } \ + _asm { mov esi, dataptr } \ + _asm { add esi, dataoffset } \ + _asm { mov ecx, dword_count } \ + _asm { rep movsd } \ +} + +#elif CIMARRON_OPTIMIZE_FORLOOP + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING32 + * Write a series of DWORDs to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_COMMAND32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off))); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_STRING32 + * Write a series of DWORDS to video memory. + *-----------------------------------------------------------------*/ + +#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr; \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_FB32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off))); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_CONSTANT + * Write a constant DWORD to multiple video memory addresses + *-----------------------------------------------------------------*/ + +#define WRITE_FB_CONSTANT(offset, value, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempoffset = offset; \ + for (i = 0; i < dword_count; i++, tempoffset += 4) \ + WRITE_FB32 (tempoffset, value); \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING32 + * Write a series of DWORDs to the GP host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, *((unsigned long *)(tempdata + byte_off))); \ +} + +#elif CIMARRON_OPTIMIZE_ABSTRACTED_ASM + +#define move_dw(d,s,n) \ + __asm__ __volatile__( \ + " rep\n" \ + " movsl\n" \ + : "=&c" (d0), "=&S" (d1), "=&D" (d2) \ + : "0" (n), "1" ((const char *)s), "2" ((char *)d) \ + : "memory") + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING32 + * Write a series of DWORDs to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ +{ \ + int d0, d1, d2; \ + move_dw (cim_cmd_ptr+ ((unsigned long)(offset)), \ + ((unsigned long)(dataptr)+(dataoffset)), \ + dword_count); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_STRING32 + * Write a series of DWORDS to video memory. + *-----------------------------------------------------------------*/ + +#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr; \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_FB32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off))); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_CONSTANT + * Write a constant DWORD to multiple video memory addresses + *-----------------------------------------------------------------*/ + +#define WRITE_FB_CONSTANT(offset, value, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempoffset = offset; \ + for (i = 0; i < dword_count; i++, tempoffset += 4) \ + WRITE_FB32 (tempoffset, value); \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING32 + * Write a series of DWORDs to the GP host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, *((unsigned long *)(tempdata + byte_off))); \ +} + +#endif + +#endif /* #ifdef CIMARRON_INCLUDE_STRING_MACROS */ + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING8 + * Write a series of bytes to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING8(offset, dataptr, dataoffset, byte_count) \ +{ \ + unsigned long i; \ + unsigned long array = (unsigned long)dataptr + (dataoffset); \ + for (i = 0; i < byte_count; i++) \ + WRITE_COMMAND8 ((offset) + i, *((unsigned char *)(array + i))); \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING8 + * Write a series of bytes to the host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING8(dataptr, dataoffset, byte_count) \ +{ \ + unsigned long temp1 = (unsigned long)dataptr + (dataoffset); \ + unsigned long temp2 = 0; \ + unsigned long shift = 0; \ + unsigned long counter; \ + if (byte_count) \ + { \ + for (counter = 0; counter < byte_count; counter++) \ + { \ + temp2 |= ((unsigned long)(*((unsigned char *)(temp1 + counter)))) << shift; \ + shift += 8; \ + } \ + WRITE_GP32 (GP3_HST_SRC, temp2); \ + } \ +} + +/*-----------------------------------------*/ +/* CUSTOM STRING MACROS */ +/*-----------------------------------------*/ + +#ifndef CIMARRON_EXCLUDE_CUSTOM_MACROS + +#define WRITE_CUSTOM_COMMAND_STRING32 WRITE_COMMAND_STRING32 +#define WRITE_CUSTOM_COMMAND_STRING8 WRITE_COMMAND_STRING8 + +#endif + +/*-----------------------------------------*/ +/* IO ACCESS MACROS */ +/*-----------------------------------------*/ + +#ifdef CIMARRON_INCLUDE_IO_MACROS + +#if CIMARRON_IO_DIRECT_ACCESS + +/*------------------------------------------- + * OUTD + * Writes one DWORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTD(port, data) cim_outd(port, data) +void cim_outd (unsigned short port, unsigned long data) +{ + _asm { + pushf + mov eax, data + mov dx, port + out dx, eax + popf + } +} + +/*------------------------------------------- + * IND + * Reads one DWORD from a single I/O address. + *-------------------------------------------*/ + +#define IND(port) cim_ind(port) +unsigned long cim_ind (unsigned short port) +{ + unsigned long data; + _asm { + pushf + mov dx, port + in eax, dx + mov data, eax + popf + } + return data; +} + +/*------------------------------------------- + * OUTW + * Writes one WORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTW(port, data) cim_outw(port, data) +void cim_outw (unsigned short port, unsigned short data) +{ + _asm { + pushf + mov ax, data + mov dx, port + out dx, ax + popf + } +} + +/*------------------------------------------- + * INW + * Reads one WORD from a single I/O address. + *-------------------------------------------*/ + +#define INW(port) cim_inw(port) +unsigned short cim_inw (unsigned short port) +{ + unsigned short data; + _asm { + pushf + mov dx, port + in ax, dx + mov data, ax + popf + } + return data; +} + +/*------------------------------------------- + * OUTB + * Writes one BYTE to a single I/O address. + *-------------------------------------------*/ + +#define OUTB(port, data) cim_outb(port, data) +void cim_outb (unsigned short port, unsigned char data) +{ + _asm { + pushf + mov al, data + mov dx, port + out dx, al + popf + } +} + +/*------------------------------------------- + * INB + * Reads one BYTE from a single I/O address. + *-------------------------------------------*/ + +#define INB(port) cim_inb(port) +unsigned char cim_inb (unsigned short port) +{ + unsigned char data; + _asm { + pushf + mov dx, port + in al, dx + mov data, al + popf + } + return data; +} + +#elif CIMARRON_IO_ABSTRACTED_ASM + +/*------------------------------------------- + * OUTD + * Writes one DWORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTD(port, data) cim_outd(port, data) +void cim_outd (unsigned short port, unsigned long data); +void cim_outd (unsigned short port, unsigned long data) +{ + __asm__ __volatile__ ("outl %0,%w1" : : "a" (data), "Nd" (port)); +} + +/*------------------------------------------- + * IND + * Reads one DWORD from a single I/O address. + *-------------------------------------------*/ + +#define IND(port) cim_ind(port) +unsigned long cim_ind (unsigned short port); +unsigned long cim_ind (unsigned short port) +{ + unsigned long value; + __asm__ __volatile__ ("inl %w1,%0" : "=a" (value) : "Nd" (port) ); + + return value; +} + +/*------------------------------------------- + * OUTW + * Writes one WORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTW(port, data) cim_outw(port, data) +void cim_outw (unsigned short port, unsigned short data); +void cim_outw (unsigned short port, unsigned short data) +{ + __asm__ volatile ("out %0,%1" : : "a" (data),"d" (port)); +} + +/*------------------------------------------- + * INW + * Reads one WORD from a single I/O address. + *-------------------------------------------*/ + +#define INW(port) cim_inw(port) +unsigned short cim_inw (unsigned short port); +unsigned short cim_inw (unsigned short port) +{ + unsigned short value; + __asm__ volatile ("in %1,%0" : "=a" (value) : "d" (port)); + return value; +} + +/*------------------------------------------- + * INB + * Reads one BYTE from a single I/O address. + *-------------------------------------------*/ + +#define INB(port) cim_inb(port) +unsigned char cim_inb(unsigned short port); +unsigned char cim_inb(unsigned short port) +{ + unsigned char value; + __asm__ volatile ("inb %1,%0":"=a" (value):"d"(port)); + + return value; +} + +/*------------------------------------------- + * OUTB + * Writes one BYTE to a single I/O address. + *-------------------------------------------*/ + +#define OUTB(port) cim_outb(port) +void cim_outb(unsigned short port, unsigned char data); +void cim_outb(unsigned short port, unsigned char data) +{ + __asm__ volatile ("outb %0,%1"::"a" (data), "d"(port)); +} + +#endif + +#endif /* CIMARRON_INCLUDE_IO_MACROS */ + +#endif diff --git a/src/cim/cim_defs.h.rej b/src/cim/cim_defs.h.rej new file mode 100644 index 0000000..3d892c6 --- /dev/null +++ b/src/cim/cim_defs.h.rej @@ -0,0 +1,45 @@ +*************** +*** 208,227 **** + *-----------------------------------------------------------------*/ + + #define MSR_WRITE(msr,adr,val) \ +- { int d0, d1, d2, d3, d4; \ + __asm__ __volatile__( \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ +- " mov %5, %4\n" \ +- " mov 0(%6), %1\n" \ +- " mov 4(%6), %0\n" \ +- " xor %3, %3\n" \ + " xor %2, %2\n" \ +- " out %%ax, %%dx" \ +- : "=a" (d0), "=b" (d1), "=&D" (d2), "=&S" (d3), "=c" (d4) \ +- : "2" (msr | adr), "3" (val)); \ + } + + #elif CIMARRON_MSR_KERNEL_ROUTINE +--- 208,229 ---- + *-----------------------------------------------------------------*/ + + #define MSR_WRITE(msr,adr,val) \ ++ { int d0, d1, d2, d3; \ + __asm__ __volatile__( \ ++ " push %%ebx\n" \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ ++ " mov %4, %3\n" \ ++ " mov 0(%5), %%ebx\n" \ ++ " mov 4(%5), %0\n" \ + " xor %2, %2\n" \ ++ " xor %1, %1\n" \ ++ " out %%ax, %%dx\n" \ ++ " pop %%ebx\n" \ ++ : "=a" (d0), "=&D" (d1), "=&S" (d2), "=c" (d3) \ ++ : "1" (msr | adr), "2" (val)); \ + } + + #elif CIMARRON_MSR_KERNEL_ROUTINE diff --git a/src/cim/cim_df.c b/src/cim/cim_df.c new file mode 100644 index 0000000..242603a --- /dev/null +++ b/src/cim/cim_df.c @@ -0,0 +1,2581 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron display filter routines. These routines program the video + * hardware. + */ + +/*--------------------------------------------------------------------------- + * df_set_crt_enable + * + * This routine enables or disables CRT output. + *--------------------------------------------------------------------------*/ + +int +df_set_crt_enable(int crt_output) +{ + unsigned long config, misc; + + config = READ_VID32(DF_DISPLAY_CONFIG); + misc = READ_VID32(DF_VID_MISC); + + switch (crt_output) { + /* DISABLE DISPLAY */ + + case DF_CRT_DISABLE: + + config &= ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | + DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN); + misc |= DF_DAC_POWER_DOWN; + break; + + /* ENABLE THE DISPLAY */ + + case DF_CRT_ENABLE: + + config |= (DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | + DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN); + misc &= ~(DF_DAC_POWER_DOWN | DF_ANALOG_POWER_DOWN); + break; + + /* HSYNC:OFF VSYNC:ON */ + + case DF_CRT_STANDBY: + + config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | + DF_DCFG_DAC_BL_EN)) | DF_DCFG_VSYNC_EN; + misc |= DF_DAC_POWER_DOWN; + break; + + /* HSYNC:ON VSYNC:OFF */ + + case DF_CRT_SUSPEND: + + config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_VSYNC_EN | + DF_DCFG_DAC_BL_EN)) | DF_DCFG_HSYNC_EN; + misc |= DF_DAC_POWER_DOWN; + break; + + default: + return CIM_STATUS_INVALIDPARAMS; + } + + WRITE_VID32(DF_DISPLAY_CONFIG, config); + WRITE_VID32(DF_VID_MISC, misc); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_panel_enable + * + * This routine enables or disables panel output. + *--------------------------------------------------------------------------*/ + +int +df_set_panel_enable(int enable) +{ + unsigned long pm; + + pm = READ_VID32(DF_POWER_MANAGEMENT); + + if (enable) + pm |= DF_PM_PANEL_ON; + else + pm &= ~DF_PM_PANEL_ON; + + WRITE_VID32(DF_POWER_MANAGEMENT, pm); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_configure_video_source + * + * This routine initializes all aspects of the source buffer for a video overlay. + *--------------------------------------------------------------------------*/ + +int +df_configure_video_source(DF_VIDEO_SOURCE_PARAMS * video_source_odd, + DF_VIDEO_SOURCE_PARAMS * video_source_even) +{ + unsigned long pitch, ctrl, vcfg; + unsigned long lock, vg_line, gcfg; + unsigned long width, size, scale; + unsigned long misc; + + lock = READ_REG32(DC3_UNLOCK); + vg_line = READ_REG32(DC3_LINE_SIZE); + gcfg = READ_REG32(DC3_GENERAL_CFG); + vcfg = READ_VID32(DF_VIDEO_CONFIG); + ctrl = READ_VID32(DF_VID_ALPHA_CONTROL); + scale = READ_VID32(DF_VIDEO_SCALER); + + /* STORE THE DESIRED SCALING PROCEDURE */ + /* Cimarron supports two modes when programming the scale and position */ + /* of the video window. The first mode is designed to implicitly apply */ + /* the graphics scale to any video operations. The second applys the */ + /* video unchanged, allowing complete control by the user. To allow */ + /* visibility between modules, the current mode is stored in a spare */ + /* bit in the DF miscellaneous register. */ + + misc = READ_VID32(DF_VID_MISC); + if (video_source_odd->flags & DF_SOURCEFLAG_IMPLICITSCALING) + misc |= DF_USER_IMPLICIT_SCALING; + else + misc &= DF_USER_IMPLICIT_SCALING; + WRITE_VID32(DF_VID_MISC, misc); + + /* PARAMETER - VIDEO PITCH */ + + pitch = + (video_source_odd->y_pitch >> 3) | ((video_source_odd-> + uv_pitch >> 3) << 16); + + /* PARAMETER - VIDEO FORMAT */ + + gcfg &= ~DC3_GCFG_YUV_420; + vcfg &= ~(DF_VCFG_VID_INP_FORMAT | DF_VCFG_4_2_0_MODE); + ctrl &= ~(DF_VIDEO_INPUT_IS_RGB | DF_CSC_VIDEO_YUV_TO_RGB | DF_HD_VIDEO | + DF_YUV_CSC_EN); + + /* SELECT PIXEL ORDERING */ + + switch (video_source_odd->video_format & 3) { + case 0: + vcfg |= DF_VCFG_UYVY_FORMAT; + break; + case 1: + vcfg |= DF_VCFG_Y2YU_FORMAT; + break; + case 2: + vcfg |= DF_VCFG_YUYV_FORMAT; + break; + case 3: + vcfg |= DF_VCFG_YVYU_FORMAT; + break; + } + + /* SELECT SOURCE FORMAT (4:2:2, 4:2:0, RGB) */ + + switch (video_source_odd->video_format >> 2) { + case 0: + ctrl |= DF_CSC_VIDEO_YUV_TO_RGB; + break; + + case 1: + ctrl |= DF_CSC_VIDEO_YUV_TO_RGB; + vcfg |= DF_VCFG_4_2_0_MODE; + gcfg |= DC3_GCFG_YUV_420; + break; + + case 2: + ctrl |= DF_VIDEO_INPUT_IS_RGB; + break; + + default: + return CIM_STATUS_INVALIDPARAMS; + } + + /* ALIGN TO APPROPRIATE OUTPUT COLOR SPACE */ + /* We have assumed until this point that the output color space is RGB */ + /* and the input (if YUV) is always SDTV video. */ + + if (video_source_odd->flags & DF_SOURCEFLAG_HDTVSOURCE) + ctrl |= DF_HD_VIDEO; + + if (ctrl & DF_CSC_GRAPHICS_RGB_TO_YUV) { + /* YUV OUTPUT - DISABLE YUV->RGB AND ENABLE YUV->YUV */ + + ctrl &= ~DF_CSC_VIDEO_YUV_TO_RGB; + + if ((!(ctrl & DF_HD_VIDEO) && (ctrl & DF_HD_GRAPHICS)) || + ((ctrl & DF_HD_VIDEO) && !(ctrl & DF_HD_GRAPHICS))) { + ctrl |= DF_YUV_CSC_EN; + } + } + + /* PARAMETER - DISPLAY FILTER BUFFER SIZE */ + /* The line size in the video generator must be 32-byte aligned. */ + /* However, smaller alignments are managed by setting the */ + /* appropriate pitch and clipping the video window. */ + + vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 | + DF_VCFG_LINE_SIZE_BIT9); + + size = ((video_source_odd->width >> 1) + 7) & 0xFFF8; + + vcfg |= (size & 0x00FF) << 8; + if (size & 0x0100) + vcfg |= DF_VCFG_LINE_SIZE_BIT8; + if (size & 0x0200) + vcfg |= DF_VCFG_LINE_SIZE_BIT9; + + scale = (scale & ~0x7FF) | video_source_odd->height; + + /* PARAMETER - VIDEO GENERATOR BUFFER SIZE */ + + vg_line &= ~DC3_LINE_SIZE_VLS_MASK; + + if (gcfg & DC3_GCFG_YUV_420) + width = ((video_source_odd->width >> 1) + 7) & 0xFFF8; + else + width = ((video_source_odd->width << 1) + 31) & 0xFFE0; + + vg_line |= (width >> 3) << DC3_LINE_SIZE_VB_SHIFT; + + /* WRITE ALL PARAMETERS AT ONCE */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_VID32(DF_VIDEO_CONFIG, vcfg); + WRITE_VID32(DF_VID_ALPHA_CONTROL, ctrl); + WRITE_VID32(DF_VIDEO_SCALER, scale); + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + WRITE_REG32(DC3_LINE_SIZE, vg_line); + WRITE_REG32(DC3_VID_YUV_PITCH, pitch); + + /* WRITE EVEN OR ODD BUFFER OFFSETS */ + /* The even buffer is only valid inside an interlaced display. */ + + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + WRITE_REG32(DC3_VID_EVEN_Y_ST_OFFSET, video_source_even->y_offset); + WRITE_REG32(DC3_VID_EVEN_U_ST_OFFSET, video_source_even->u_offset); + WRITE_REG32(DC3_VID_EVEN_V_ST_OFFSET, video_source_even->v_offset); + } + + WRITE_REG32(DC3_VID_Y_ST_OFFSET, video_source_odd->y_offset); + WRITE_REG32(DC3_VID_U_ST_OFFSET, video_source_odd->u_offset); + WRITE_REG32(DC3_VID_V_ST_OFFSET, video_source_odd->v_offset); + + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_offsets + * + * This routine sets the starting offset for the video buffer(s). The buffers + * can also be configured inside df_configure_video_source, but a separate + * routine is provided here to allow quick buffer flipping. + *--------------------------------------------------------------------------*/ + +int +df_set_video_offsets(int even, unsigned long y_offset, + unsigned long u_offset, unsigned long v_offset) +{ + unsigned long lock = READ_REG32(DC3_UNLOCK); + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + if (even) { + WRITE_REG32(DC3_VID_EVEN_Y_ST_OFFSET, y_offset); + WRITE_REG32(DC3_VID_EVEN_U_ST_OFFSET, u_offset); + WRITE_REG32(DC3_VID_EVEN_V_ST_OFFSET, v_offset); + } else { + WRITE_REG32(DC3_VID_Y_ST_OFFSET, y_offset); + WRITE_REG32(DC3_VID_U_ST_OFFSET, u_offset); + WRITE_REG32(DC3_VID_V_ST_OFFSET, v_offset); + } + + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_scale + * + * This routine programs the horizontal/vertical scale factors for video. To + * disable scaling/filtering, this routine should be called with identical source + * and destination dimensions. + *--------------------------------------------------------------------------*/ + +int +df_set_video_scale(unsigned long src_width, unsigned long src_height, + unsigned long dst_width, unsigned long dst_height, unsigned long flags) +{ + unsigned long temp, misc; + unsigned long scale, gfxscale; + unsigned long fbactive, src; + unsigned long size, downscale; + unsigned long vcfg, gcfg, unlock; + + /* APPLY THE GRAPHICS SCALE */ + /* When requested by the user, we will adjust the video scale by the */ + /* current graphics scale factor. This allows video to be programmed */ + /* in terms of the graphics source resolution. */ + + misc = READ_VID32(DF_VID_MISC); + if (misc & DF_USER_IMPLICIT_SCALING) { + gfxscale = READ_REG32(DC3_GFX_SCALE); + fbactive = READ_REG32(DC3_FB_ACTIVE); + + /* REVERSE ENGINEER THE SCALE FACTOR */ + /* The graphics scale factor is (source / (dst - 1)), so a little */ + /* math is performed to reverse engineer the correct scale for */ + /* video. */ + /* */ + /* F = (0x4000*S)/(D-1) -> (D/S) = (((0x4000*S)/F)+1)/S */ + + scale = gfxscale & 0xFFFF; + src = (fbactive >> 16) + 1; + if (scale != 0x4000) { + dst_width = dst_width * (((0x4000 * src) / scale) + 1); + dst_width /= src; + } + + scale = gfxscale >> 16; + src = (fbactive & 0xFFFF) + 1; + if (scale != 0x4000) { + dst_height = dst_height * (((0x4000 * src) / scale) + 1); + dst_height /= src; + } + } + + /* CHECK FOR VALID SCALING FACTOR */ + /* The display filter/video generator can support up to 8:1 */ + /* horizontal downscale and up to 4:1 vertical downscale. */ + /* Scale factors above 4:1 horizontal and 2:1 horizontal */ + /* will have a quality impact. However, at such large scale */ + /* factors, it might not matter, */ + + if (((flags & DF_SCALEFLAG_CHANGEX) && dst_width < (src_width >> 3)) || + ((flags & DF_SCALEFLAG_CHANGEY) && dst_height < (src_height >> 2))) { + return CIM_STATUS_INVALIDSCALE; + } + + /* ENABLE OR DISABLE ADVANCED SCALING FEATURES */ + /* Scaling above 2:1 vertical and 4:1 horizontal relies */ + /* on mechanisms beside the line filter. */ + + if (flags & DF_SCALEFLAG_CHANGEX) { + scale = READ_VID32(DF_VIDEO_SCALER); + vcfg = READ_VID32(DF_VIDEO_CONFIG); + vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 | + DF_VCFG_LINE_SIZE_BIT9); + + if (dst_width < (src_width >> 2)) { + src_width >>= 1; + WRITE_VID32(DF_VIDEO_SCALER, scale | DF_SCALE_DOUBLE_H_DOWNSCALE); + } else { + WRITE_VID32(DF_VIDEO_SCALER, + scale & ~DF_SCALE_DOUBLE_H_DOWNSCALE); + } + + /* PROGRAM A NEW LINE SIZE */ + /* The line size must be updated when using the Double Horizontal */ + /* Downscale (DHD) bit. This is because the amount of VFIFO space */ + /* consumed is effectively half in this mode. */ + + size = ((src_width >> 1) + 7) & 0xFFF8; + vcfg |= (size & 0x00FF) << 8; + if (size & 0x0100) + vcfg |= DF_VCFG_LINE_SIZE_BIT8; + if (size & 0x0200) + vcfg |= DF_VCFG_LINE_SIZE_BIT9; + WRITE_VID32(DF_VIDEO_CONFIG, vcfg); + WRITE_VID32(DF_VIDEO_XSCALE, ((0x10000 * src_width) / dst_width)); + } + + if (flags & DF_SCALEFLAG_CHANGEY) { + unlock = READ_REG32(DC3_UNLOCK); + gcfg = READ_REG32(DC3_GENERAL_CFG) & ~DC3_GCFG_VDSE; + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + if (dst_height < (src_height >> 1)) { + gcfg |= DC3_GCFG_VDSE; + downscale = READ_REG32(DC3_VID_DS_DELTA) & ~DC3_DS_DELTA_MASK; + if (dst_height == (src_height >> 2)) + downscale |= (0x3FFF << 18); + else + downscale |= (((src_height >> 1) << 14) / dst_height) << 18; + + WRITE_REG32(DC3_VID_DS_DELTA, downscale); + WRITE_VID32(DF_VIDEO_YSCALE, 0x20000); + } else { + WRITE_VID32(DF_VIDEO_YSCALE, + ((0x10000 * src_height) / dst_height)); + } + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + WRITE_REG32(DC3_UNLOCK, unlock); + } + + /* CHECK IF SCALING IS DISABLED */ + /* If no scaling occurs, we disable the hardware filter. */ + + temp = READ_VID32(DF_VIDEO_CONFIG); + if ((READ_VID32(DF_VIDEO_XSCALE) == 0x10000) && + (READ_VID32(DF_VIDEO_YSCALE) == 0x10000)) { + WRITE_VID32(DF_VIDEO_CONFIG, (temp | DF_VCFG_SC_BYP)); + } else + WRITE_VID32(DF_VIDEO_CONFIG, (temp & ~DF_VCFG_SC_BYP)); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_position + * + * This routine programs the position of the video window on the display. + * An indent parameter is also passed to this program to prevent artifacts + * when the video window is moved beyond the left edge of the screen. + *--------------------------------------------------------------------------*/ + +int +df_set_video_position(DF_VIDEO_POSITION * video_window) +{ + unsigned long vblankstart_even, vblankend_even, vsyncend_even, + vtotal_even, vactive_even; + unsigned long hblankstart, hblankend, hsyncend, htotal, hactive; + unsigned long vblankstart, vblankend, vsyncend, vtotal, vactive; + unsigned long width, height, height_even; + unsigned long adjust, border_x, border_y, border_y_even; + unsigned long xstart, xend; + unsigned long ystart, yend; + unsigned long ckey_x, ckey_y; + unsigned long x_copy, y_copy; + unsigned long width_copy, height_copy; + unsigned long vcfg, initread; + unsigned long xscale, dst_clip; + unsigned long ypos, ypos_even; + unsigned long y, gfxscale; + unsigned long misc, fbactive; + unsigned long scale, src; + unsigned long irq_ctl; + unsigned long unlock; + + hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; + vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; + vblankend = ((READ_REG32(DC3_V_BLANK_TIMING) >> 16) & 0xFFF) + 1; + hblankend = ((READ_REG32(DC3_H_BLANK_TIMING) >> 16) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + vblankstart = (READ_REG32(DC3_V_BLANK_TIMING) & 0xFFF) + 1; + hblankstart = (READ_REG32(DC3_H_BLANK_TIMING) & 0xFFF) + 1; + hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1; + vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1; + unlock = READ_REG32(DC3_UNLOCK); + + /* INCLUDE BORDER IF REQUESTED */ + + if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) { + border_x = htotal - hblankend; + border_y = vtotal - vblankend; + hactive = hblankstart + htotal - hblankend; + vactive = vblankstart + vtotal - vblankend; + } else { + border_x = border_y = 0; + } + + /* APPLY THE GRAPHICS SCALE */ + /* Do not alter the input data. */ + + width_copy = video_window->width; + height_copy = video_window->height; + x_copy = video_window->x; + y_copy = video_window->y; + + misc = READ_VID32(DF_VID_MISC); + if (misc & DF_USER_IMPLICIT_SCALING) { + gfxscale = READ_REG32(DC3_GFX_SCALE); + fbactive = READ_REG32(DC3_FB_ACTIVE); + + /* REVERSE ENGINEER THE SCALE FACTOR */ + + scale = gfxscale & 0xFFFF; + src = (fbactive >> 16) + 1; + if (scale != 0x4000) { + width_copy = width_copy * (((0x4000 * src) / scale) + 1); + width_copy /= src; + x_copy = x_copy * (((0x4000 * src) / scale) + 1); + x_copy /= src; + } + + scale = gfxscale >> 16; + src = (fbactive & 0xFFFF) + 1; + if (scale != 0x4000) { + height_copy = height_copy * (((0x4000 * src) / scale) + 1); + height_copy /= src; + y_copy = y_copy * (((0x4000 * src) / scale) + 1); + y_copy /= src; + } + } + + /* HANDLE INTERLACING */ + /* When the output is interlaced, we must set the position and height */ + /* on the fields and not on the composite image. */ + + if ((irq_ctl = READ_REG32(DC3_IRQ_FILT_CTL)) & DC3_IRQFILT_INTL_EN) { + vsyncend_even = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; + vtotal_even = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; + vblankend_even = ((READ_REG32(DC3_V_BLANK_EVEN) >> 16) & 0xFFF) + 1; + vactive_even = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1; + vblankstart_even = (READ_REG32(DC3_V_BLANK_EVEN) & 0xFFF) + 1; + + if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) { + border_y_even = vtotal_even - vblankend_even; + vactive_even = vblankstart_even + vtotal_even - vblankend_even; + } else + border_y_even = 0; + + /* + * THE ODD FIELD MUST ALWAYS PRECEDE THE EVEN FIELD + * This implies that we can never start video on an odd y position + * in the composite image. This is required because the only way + * to accomplish an odd y start would be to switch the buffer + * which could have serious repercussions for genlocked VIP. + */ + + y = y_copy >> 1; + + /* CALCULATE Y POSITION FOR ODD FIELD */ + /* Clip the video window to the odd field timings. Note that the */ + /* height in the odd field may be greater if the video height is */ + /* odd. */ + + height = (height_copy + 1) >> 1; + if ((y + height) > vactive) + height = vactive - y; + + ystart = y + vtotal_even - vsyncend_even + 1; + if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) + ystart -= border_y_even; + + yend = ystart + height; + ypos = (yend << 16) | ystart; + + /* CALCULATE Y POSITION FOR EVEN FIELD */ + + height_even = height_copy >> 1; + if ((y + height_even) > vactive_even) + height_even = vactive_even - y; + + ystart = y + vtotal - vsyncend + 1; + if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) + ystart -= border_y; + + yend = ystart + height_even; + ypos_even = (yend << 16) | ystart; + + /* CALCULATE ACTUAL FRAME BUFFER HEIGHT */ + /* The y position and height are used to determine the actual */ + /* placement of the color key region. The region will either be */ + /* the sum of the even and odd fields (for interlaced addressing */ + /* or flicker filtering) or it will be the union of the two (for */ + /* line doubling). We must also adjust the region such that the */ + /* origin (0, 0) is centered on the beginning of graphics data. */ + /* This is only a problem if video is being displayed over the */ + /* overscan area. */ + + if ((READ_REG32(DC3_GENLK_CTL) & DC3_GC_FLICKER_FILTER_ENABLE) || + (irq_ctl & DC3_IRQFILT_INTL_ADDR)) { + y <<= 1; + height += height_even; + adjust = border_y + border_y_even; + } else { + adjust = border_y; + if (height_even > height) + height = height_even; + } + if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) { + if (y > adjust) { + y -= adjust; + adjust = 0; + } else { + adjust -= y; + if (height > adjust) + height -= adjust; + else + height = 0; + } + } + + } else { + y = y_copy; + + height = height_copy; + if ((y + height) > vactive) + height = vactive - y; + + ystart = y + vtotal - vsyncend + 1; + if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) + ystart -= border_y; + + yend = ystart + height; + ypos = (yend << 16) | ystart; + ypos_even = 0; + } + + /* HORIZONTAL POSITION */ + /* The horizontal values are identical for the even and odd field. */ + + width = width_copy; + xstart = x_copy + htotal - hsyncend - 14; + if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) + xstart -= border_x; + + /* RIGHT CLIPPING */ + + if ((x_copy + width) > hactive) + width = hactive - x_copy; + + xend = xstart + width; + + /* + * CALCULATE LEFT CLIPPING PARAMETER + * The value passed in can be interpreted as destination pixels, in + * which case the video scale is factored in, or as source pixels, in + * which case the value is written directly. Also, the display filter's + * initial read address value is only programmable on 4-pixel increments. + * However, we can achieve an arbitrary left clip by adjusting the + * xstart value, as there is a 14-clock delay in which to play. Also, + * according to the designers, 4:2:0 and 4:2:2 behave identically when + * setting the initial read address. The addition of scaling further + * complicates the algorithm. When setting the initial read address, it + * is in terms of source pixels, while adjusting the xstart value is in + * destination pixels We may thus not be able to achieve a perfect + * clipping fit for scaled video. We compensate by including two + * clipping parameters in our structure. This allows us the user + * additional control and it allows us to accurately convey to the user + * the state of clipping on the machine. + */ + + initread = video_window->left_clip; + dst_clip = 0; + if (!(video_window->flags & DF_POSFLAG_DIRECTCLIP)) { + xscale = READ_VID32(DF_VIDEO_XSCALE) & 0xFFFFF; + initread = (initread * xscale) / 0x10000; + if (xscale) + dst_clip = ((initread & 3) * 0x10000) / xscale; + } else + dst_clip = video_window->dst_clip; + + /* + * LIMIT THE CLIP + * We technically have a 14 pixel window in which to play. However, + * taking the entire 14 pixels makes the video timing a little hairy... + * Also note that we cannot do this when performing panel centering, as + * the video would then exceed the mode size. + */ + + if (dst_clip > 4) + dst_clip = 4; + if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) + dst_clip = 0; + + xstart -= dst_clip; + + vcfg = READ_VID32(DF_VIDEO_CONFIG); + vcfg &= ~DF_VCFG_INIT_READ_MASK; + vcfg |= (initread >> 2) << 16; + + /* SET COLOR KEY REGION */ + /* We are assuming that color keying will never be desired outside */ + /* of the video region. We adjust the color key region for graphics */ + /* scaling. */ + + gfxscale = READ_REG32(DC3_GFX_SCALE); + + ckey_x = ((x_copy * (gfxscale & 0xFFFF)) / 0x4000) | + ((((x_copy + width) * (gfxscale & 0xFFFF)) / 0x4000) << 16); + ckey_y = ((y * (gfxscale >> 16)) / 0x4000) | + ((((y + height) * (gfxscale >> 16)) / 0x4000) << 16); + + /* WRITE ALL PARAMETERS AT ONCE */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_CLR_KEY_X, ckey_x); + WRITE_REG32(DC3_CLR_KEY_Y, ckey_y); + WRITE_VID32(DF_VIDEO_X_POS, (xend << 16) | xstart); + WRITE_VID32(DF_VIDEO_Y_POS, ypos); + WRITE_VID32(DF_VID_YPOS_EVEN, ypos_even); + WRITE_VID32(DF_VIDEO_CONFIG, vcfg); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_filter_coefficients + * + * This routine sets the horizontal and vertical filter coefficients for video + * scaling. These coefficients are used for upscaling and downscaling video. + * If the phase256 parameter is 1, the coefficient arrays are used as single + * arrays of 256 phases for both vertical and horizontal scaling. If the + * phase256 parameter is clear, the coefficient arrays are used as two + * 128-phase arrays. The first 128 entries represent the phases for + * vertical scaling. The last 128 entries represent the phases for + * horizontal scaling. + *--------------------------------------------------------------------------*/ + +int +df_set_video_filter_coefficients(long taps[][4], int phase256) +{ + unsigned long scale, coeff0, coeff1; + unsigned long i; + long (*defaults)[2]; + + /* SET PHASE COUNT AND CHOOSE COEFFICIENT ARRAY */ + + scale = READ_VID32(DF_VIDEO_SCALER); + if (phase256) { + WRITE_VID32(DF_VIDEO_SCALER, (scale & ~DF_SCALE_128_PHASES)); + defaults = CimarronVideoFilter256; + } else { + WRITE_VID32(DF_VIDEO_SCALER, (scale | DF_SCALE_128_PHASES)); + defaults = CimarronVideoFilter128; + } + + /* PROGRAM COEFFICIENTS */ + + for (i = 0; i < 256; i++) { + if (!taps) { + coeff0 = defaults[i][0]; + coeff1 = defaults[i][1]; + } else { + if (taps[i][1] < 0) + coeff0 = -taps[i][1] | 0x8000; + else + coeff0 = taps[i][1]; + + coeff0 <<= 16; + + if (taps[i][0] < 0) + coeff0 |= -taps[i][0] | 0x8000; + else + coeff0 |= taps[i][0]; + + if (taps[i][3] < 0) + coeff1 = -taps[i][3] | 0x8000; + else + coeff1 = taps[i][3]; + + coeff1 <<= 16; + + if (taps[i][2] < 0) + coeff1 |= -taps[i][2] | 0x8000; + else + coeff1 |= taps[i][2]; + } + + WRITE_VID32((DF_COEFFICIENT_BASE + (i << 3)), coeff0); + WRITE_VID32((DF_COEFFICIENT_BASE + (i << 3) + 4), coeff1); + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_enable + * + * This routine enables or disables the video overlay. + *--------------------------------------------------------------------------*/ + +int +df_set_video_enable(int enable, unsigned long flags) +{ + unsigned long vcfg, lock, gcfg; + unsigned long dcfg, vg_ckey, fifo = 0; + + vcfg = READ_VID32(DF_VIDEO_CONFIG); + lock = READ_REG32(DC3_UNLOCK); + gcfg = READ_REG32(DC3_GENERAL_CFG); + + /* SET VIDEO FIFO END WATERMARK */ + /* The video FIFO end watermark is set to 0 when video is disabled */ + /* to allow low priority transactions in the VG. Otherwise, the */ + /* priority will be forced high until the VG fills the video FIFO */ + /* by not fetching video. That could take a while... Note that */ + /* we set the end priority to be 4 greater than the start. We */ + /* assume that the start priority has been configured by a modeset. */ + + dcfg = READ_REG32(DC3_DISPLAY_CFG) & ~DC3_DCFG_VFHPEL_MASK; + if (enable) { + fifo = ((dcfg >> 12) & 0x0000000F) + 4; + if (fifo > 0xF) + fifo = 0xF; + } + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_DISPLAY_CFG, dcfg | (fifo << 16)); + + /* ENABLE OR DISABLE VIDEO */ + /* The mechanism to fetch video data is enabled first and */ + /* disabled last. */ + + if (enable) { + WRITE_REG32(DC3_GENERAL_CFG, (gcfg | DC3_GCFG_VIDE)); + WRITE_VID32(DF_VIDEO_CONFIG, (vcfg | DF_VCFG_VID_EN)); + + /* DISABLE COLOR KEYING IF REQUESTED BY THE USER */ + + if (flags & DF_ENABLEFLAG_NOCOLORKEY) { + /* OVERRIDE THE MODE TO COLOR KEYING */ + + dcfg = READ_VID32(DF_DISPLAY_CONFIG); + WRITE_VID32(DF_DISPLAY_CONFIG, (dcfg & ~DF_DCFG_VG_CK)); + + /* DISABLE COLOR KEYING IN THE VG */ + + vg_ckey = READ_REG32(DC3_COLOR_KEY); + WRITE_REG32(DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE)); + } else if (!(READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK)) { + /* OTHERWISE RE-ENABLE COLOR KEYING */ + + vg_ckey = READ_REG32(DC3_COLOR_KEY); + WRITE_REG32(DC3_COLOR_KEY, (vg_ckey | DC3_CLR_KEY_ENABLE)); + } + } else { + WRITE_VID32(DF_VIDEO_CONFIG, (vcfg & ~DF_VCFG_VID_EN)); + WRITE_REG32(DC3_GENERAL_CFG, (gcfg & ~DC3_GCFG_VIDE)); + + /* DISABLE COLOR KEY WINDOW WHEN VIDEO IS INACTIVE */ + /* To mimic legacy functionality, we disble color keying */ + /* when the video window is not active. We will restore */ + /* the enable when video is re-enabled if the appropriate */ + /* bit is set in display config. */ + + vg_ckey = READ_REG32(DC3_COLOR_KEY); + WRITE_REG32(DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE)); + } + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_color_key + * + * This routine configures the video color/chroma key mechanism. + *--------------------------------------------------------------------------*/ + +int +df_set_video_color_key(unsigned long key, unsigned long mask, int graphics) +{ + unsigned long lock, vg_ckey, df_dcfg; + + vg_ckey = READ_REG32(DC3_COLOR_KEY); + lock = READ_REG32(DC3_UNLOCK); + df_dcfg = READ_VID32(DF_DISPLAY_CONFIG); + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + if (graphics) { + /* COLOR KEY - USE VG HARDWARE */ + /* Note that color key is never enabled unless a video window */ + /* is active. This is to match legacy behavior. */ + + df_dcfg &= ~DF_DCFG_VG_CK; + vg_ckey = (vg_ckey & 0xFF000000) | (key & 0xFFFFFF); + if (READ_VID32(DF_VIDEO_CONFIG) & DF_VCFG_VID_EN) + vg_ckey |= DC3_CLR_KEY_ENABLE; + else + vg_ckey &= ~DC3_CLR_KEY_ENABLE; + + WRITE_VID32(DF_DISPLAY_CONFIG, df_dcfg); + WRITE_REG32(DC3_COLOR_KEY, vg_ckey); + WRITE_REG32(DC3_COLOR_MASK, (mask & 0xFFFFFF)); + } else { + /* CHROMA KEY - USE DF HARDWARE */ + + df_dcfg |= DF_DCFG_VG_CK; + vg_ckey &= ~DC3_CLR_KEY_ENABLE; + + WRITE_REG32(DC3_COLOR_KEY, vg_ckey); + WRITE_VID32(DF_DISPLAY_CONFIG, df_dcfg); + WRITE_VID32(DF_VIDEO_COLOR_KEY, (key & 0xFFFFFF)); + WRITE_VID32(DF_VIDEO_COLOR_MASK, (mask & 0xFFFFFF)); + } + + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_palette + * + * This routine loads the video hardware palette. If a NULL pointer is + * specified, the palette is bypassed. + *-------------------------------------------------------------------------*/ + +int +df_set_video_palette(unsigned long *palette) +{ + unsigned long i, entry; + unsigned long misc, dcfg; + + /* LOAD GEODE LX VIDEO PALETTE */ + + WRITE_VID32(DF_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) { + if (palette) + entry = palette[i]; + else + entry = i | (i << 8) | (i << 16); + WRITE_VID32(DF_PALETTE_DATA, entry); + } + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(DF_DISPLAY_CONFIG); + misc = READ_VID32(DF_VID_MISC); + + dcfg |= DF_DCFG_GV_PAL_BYP; + misc &= ~DF_GAMMA_BYPASS_BOTH; + + WRITE_VID32(DF_DISPLAY_CONFIG, dcfg); + WRITE_VID32(DF_VID_MISC, misc); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_palette_entry + * + * This routine loads a single entry of the video hardware palette. + *--------------------------------------------------------------------------*/ + +int +df_set_video_palette_entry(unsigned long index, unsigned long palette) +{ + unsigned long misc, dcfg; + + if (index > 0xFF) + return CIM_STATUS_INVALIDPARAMS; + + /* SET A SINGLE ENTRY */ + + WRITE_VID32(DF_PALETTE_ADDRESS, index); + WRITE_VID32(DF_PALETTE_DATA, palette); + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(DF_DISPLAY_CONFIG); + misc = READ_VID32(DF_VID_MISC); + + dcfg |= DF_DCFG_GV_PAL_BYP; + misc &= ~DF_GAMMA_BYPASS_BOTH; + + WRITE_VID32(DF_DISPLAY_CONFIG, dcfg); + WRITE_VID32(DF_VID_MISC, misc); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_configure_video_cursor_color_key + * + * This routine configures the hardware video cursor color key mechanism. + *--------------------------------------------------------------------------*/ + +int +df_configure_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * cursor_color_key) +{ + unsigned long key; + + if (cursor_color_key->select_color2 >= 24) + return CIM_STATUS_INVALIDPARAMS; + + key = READ_VID32(DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE; + key = key | (cursor_color_key->key & 0xFFFFFF) | (cursor_color_key-> + select_color2 << 24); + + WRITE_VID32(DF_CURSOR_COLOR_KEY, key); + WRITE_VID32(DF_CURSOR_COLOR_MASK, (cursor_color_key->mask & 0xFFFFFF)); + WRITE_VID32(DF_CURSOR_COLOR_1, (cursor_color_key->color1 & 0xFFFFFF)); + WRITE_VID32(DF_CURSOR_COLOR_2, (cursor_color_key->color2 & 0xFFFFFF)); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_cursor_color_key_enable + * + * This routine enables or disables the video cursor color key. + *--------------------------------------------------------------------------*/ + +int +df_set_video_cursor_color_key_enable(int enable) +{ + unsigned long temp = READ_VID32(DF_CURSOR_COLOR_KEY); + + if (enable) + temp |= DF_CURSOR_COLOR_KEY_ENABLE; + else + temp &= ~DF_CURSOR_COLOR_KEY_ENABLE; + + WRITE_VID32(DF_CURSOR_COLOR_KEY, temp); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_configure_alpha_window + * + * This routine configures one of the three hardware alpha regions. + *--------------------------------------------------------------------------*/ + +int +df_configure_alpha_window(int window, DF_ALPHA_REGION_PARAMS * alpha_data) +{ + unsigned long vsyncend_even, vtotal_even, vactive_even; + unsigned long hsyncend, htotal, hactive; + unsigned long vsyncend, vtotal, vactive; + unsigned long alpha_ctl, pos; + unsigned long hadjust, vadjust; + unsigned long y, height; + unsigned long xstart, xend; + unsigned long ystart, yend; + unsigned long x_copy, width_copy; + unsigned long y_copy, height_copy; + unsigned long scale, src, misc; + unsigned long gfxscale, fbactive; + unsigned long color; + + if (window > 2) + return CIM_STATUS_INVALIDPARAMS; + + hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; + vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1; + vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1; + + /* APPLY THE GRAPHICS SCALE */ + + width_copy = alpha_data->width; + height_copy = alpha_data->height; + x_copy = alpha_data->x; + y_copy = alpha_data->y; + + misc = READ_VID32(DF_VID_MISC); + if (misc & DF_USER_IMPLICIT_SCALING) { + gfxscale = READ_REG32(DC3_GFX_SCALE); + fbactive = READ_REG32(DC3_FB_ACTIVE); + + /* REVERSE ENGINEER THE SCALE FACTOR */ + + scale = gfxscale & 0xFFFF; + src = (fbactive >> 16) + 1; + if (scale != 0x4000) { + width_copy = width_copy * (((0x4000 * src) / scale) + 1); + width_copy /= src; + x_copy = x_copy * (((0x4000 * src) / scale) + 1); + x_copy /= src; + } + + scale = gfxscale >> 16; + src = (fbactive & 0xFFFF) + 1; + if (scale != 0x4000) { + height_copy = height_copy * (((0x4000 * src) / scale) + 1); + height_copy /= src; + y_copy = y_copy * (((0x4000 * src) / scale) + 1); + y_copy /= src; + } + } + + /* SET PRIORITY */ + /* Priority is the only alpha parameter that is not in a register that */ + /* can be indexed based on the alpha window number. */ + + pos = 16 + (window << 1); + alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL) & ~(3L << pos); + alpha_ctl |= (alpha_data->priority & 3) << pos; + WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha_ctl); + + /* HANDLE INTERLACED MODES */ + + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + vsyncend_even = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; + vtotal_even = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; + vactive_even = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1; + + y = y_copy >> 1; + + /* SET Y POSITION FOR ODD FIELD */ + + height = (height_copy + 1) >> 1; + vadjust = vtotal_even - vsyncend_even + 1; + + ystart = y + vadjust; + yend = y + vadjust + height; + + if (yend > (vactive + vadjust)) + yend = vactive + vadjust; + + WRITE_VID32((DF_ALPHA_YPOS_1 + (window << 5)), + (ystart | (yend << 16))); + + /* SET Y POSITION FOR EVEN FIELD */ + + height = height_copy >> 1; + vadjust = vtotal - vsyncend + 1; + + ystart = y + vadjust; + yend = y + vadjust + height; + + if (yend > (vactive_even + vadjust)) + yend = vactive_even + vadjust; + + WRITE_VID32((DF_VID_ALPHA_Y_EVEN_1 + (window << 3)), + (ystart | (yend << 16))); + } else { + y = y_copy; + height = height_copy; + vadjust = vtotal - vsyncend + 1; + + ystart = y + vadjust; + yend = y + vadjust + height; + + if (yend > (vactive + vadjust)) + yend = vactive + vadjust; + + WRITE_VID32((DF_ALPHA_YPOS_1 + (window << 5)), + (ystart | (yend << 16))); + } + + /* SET ALPHA X POSITION */ + /* The x position is the same for both the odd and even fields. */ + + hadjust = htotal - hsyncend - 2; + + xstart = x_copy + hadjust; + xend = x_copy + hadjust + width_copy; + + if (xend > (hactive + hadjust)) + xend = hactive + hadjust; + + WRITE_VID32((DF_ALPHA_XPOS_1 + (window << 5)), (xstart | (xend << 16))); + + /* SET COLOR REGISTER */ + + color = alpha_data->color & 0xFFFFFF; + if (alpha_data->flags & DF_ALPHAFLAG_COLORENABLED) + color |= DF_ALPHA_COLOR_ENABLE; + + WRITE_VID32((DF_ALPHA_COLOR_1 + (window << 5)), color); + + /* SET ALPHA VALUE, DELTA AND PER PIXEL */ + + alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)) & + DF_ACTRL_WIN_ENABLE; + alpha_ctl |= (alpha_data->alpha_value & 0xFF) | DF_ACTRL_LOAD_ALPHA | + (((unsigned long)alpha_data->delta & 0xFF) << 8); + if (alpha_data->flags & DF_ALPHAFLAG_PERPIXELENABLED) + alpha_ctl |= DF_ACTRL_PERPIXEL_EN; + + WRITE_VID32((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_alpha_window_enable + * + * This routine enables or disables one of the three hardware alpha regions. + *--------------------------------------------------------------------------*/ + +int +df_set_alpha_window_enable(int window, int enable) +{ + unsigned long alpha_ctl; + + if (window > 2) + return CIM_STATUS_INVALIDPARAMS; + + alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)); + if (enable) + alpha_ctl |= DF_ACTRL_WIN_ENABLE; + else + alpha_ctl &= ~DF_ACTRL_WIN_ENABLE; + WRITE_VID32((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_no_ck_outside_alpha + * + * This function affects how color/chroma keying is performed inside the video + * window. + * + * If enable is 1, color/chroma key comparison is performed only inside + * the enabled alpha windows. Outside the enabled alpha windows, video + * is displayed if color keying is enabled, or graphics is displayed if + * chroma keying is enabled. + * If enable is 0, color/chroma key comparison is performed inside the + * entire video window. + *--------------------------------------------------------------------------*/ + +int +df_set_no_ck_outside_alpha(int enable) +{ + unsigned long value; + + value = READ_VID32(DF_VID_ALPHA_CONTROL); + if (enable) + value |= DF_NO_CK_OUTSIDE_ALPHA; + else + value &= ~DF_NO_CK_OUTSIDE_ALPHA; + WRITE_VID32(DF_VID_ALPHA_CONTROL, value); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_video_request + * + * This routine sets the horizontal (pixel) and vertical (line) video request + * values. + *--------------------------------------------------------------------------*/ + +int +df_set_video_request(unsigned long x, unsigned long y) +{ + unsigned long htotal, hsyncend; + unsigned long vtotal, vsyncend; + + hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; + vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + + /* SET DISPLAY FILTER VIDEO REQUEST */ + + x += htotal - hsyncend - 2; + y += vtotal - vsyncend + 1; + + if (x >= 0x1000 || y >= 0x800) + return CIM_STATUS_INVALIDPARAMS; + + WRITE_VID32(DF_VIDEO_REQUEST, (y | (x << 16))); + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_output_color_space + * + * This routine sets the color space used when combining graphics and video. + *--------------------------------------------------------------------------*/ + +int +df_set_output_color_space(int color_space) +{ + unsigned long alpha_ctl; + + alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL); + + alpha_ctl &= ~(DF_CSC_GRAPHICS_RGB_TO_YUV | DF_CSC_VIDEO_YUV_TO_RGB | + DF_HD_GRAPHICS | DF_YUV_CSC_EN | DF_ALPHA_DRGB); + + /* OUTPUT IS RGB */ + /* Enable YUV->RGB CSC if necessary and enable alpha output if */ + /* requested. */ + + if (color_space == DF_OUTPUT_RGB || color_space == DF_OUTPUT_ARGB) { + if (!(alpha_ctl & DF_VIDEO_INPUT_IS_RGB)) + alpha_ctl |= DF_CSC_VIDEO_YUV_TO_RGB; + + if (color_space == DF_OUTPUT_ARGB) + alpha_ctl |= DF_ALPHA_DRGB; + } + + /* OUTPUT IS YUV */ + /* Enable YUV->YUV CSC if necessary and enable RGB->YUV CSC. */ + + else if (color_space == DF_OUTPUT_SDTV || color_space == DF_OUTPUT_HDTV) { + alpha_ctl |= DF_CSC_GRAPHICS_RGB_TO_YUV; + + if (((alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_SDTV) || + (!(alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_HDTV)) { + alpha_ctl |= DF_YUV_CSC_EN; + } + + if (color_space == DF_OUTPUT_HDTV) + alpha_ctl |= DF_HD_GRAPHICS; + } else + return CIM_STATUS_INVALIDPARAMS; + + WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha_ctl); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_set_output_path + * + * This routine changes the current output path in the display filter. + *--------------------------------------------------------------------------*/ + +int +df_set_output_path(int format) +{ + unsigned long panel_tim2, panel_pm; + unsigned long output = 0; + Q_WORD msr_value; + + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + msr_value.low &= ~(DF_SIMULTANEOUS_CRT_FP | DF_CONFIG_OUTPUT_MASK); + panel_tim2 = READ_VID32(DF_VIDEO_PANEL_TIM2); + panel_pm = READ_VID32(DF_POWER_MANAGEMENT); + + if (format == DF_DISPLAY_CRT) { + /* SiBZ #4188 */ + /* When CRT output is selected, the DF drives the DISP_EN signal */ + /* with the CRT display enable. As a consequence, systems that */ + /* wire the DISP_EN signal to the TFT backlight control will not */ + /* be able to set CRT-only output without leaving the backlight */ + /* enabled. To workaround this issue, we are setting simultaneous */ + /* TFT/CRT and disabling the TFT logic. The only caveat to this */ + /* is that some TFT pins are shared with VIP 601 pins. VIP 601 */ + /* will thus not work when in this pseudo-CRT mode. To address */ + /* THAT issue, normal CRT mode sets (in cim_vg.c) will set CRT */ + /* as the DF output format. This will allow VIP 601 on CRT-only */ + /* systems without a TFT attached. */ + + panel_pm &= ~DF_PM_PANEL_ON; + panel_tim2 |= DF_PMTIM2_TFT_PASSHTHROUGH; + output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP; + } else if (format == DF_DISPLAY_FP || format == DF_DISPLAY_CRT_FP) { + panel_pm |= DF_PM_PANEL_ON; + panel_tim2 &= ~DF_PMTIM2_TFT_PASSHTHROUGH; + + if (format == DF_DISPLAY_FP) + output = DF_OUTPUT_PANEL; + else if (format == DF_DISPLAY_CRT_FP) + output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP; + } else { + switch (format) { + case DF_DISPLAY_VOP: + output = DF_OUTPUT_VOP; + break; + case DF_DISPLAY_DRGB: + output = DF_OUTPUT_DRGB; + break; + case DF_DISPLAY_CRT_DRGB: + output = DF_OUTPUT_DRGB | DF_SIMULTANEOUS_CRT_FP; + break; + default: + return CIM_STATUS_INVALIDPARAMS; + } + } + msr_value.low |= output; + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + WRITE_VID32(DF_VIDEO_PANEL_TIM2, panel_tim2); + WRITE_VID32(DF_POWER_MANAGEMENT, panel_pm); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_test_video_flip_status + * + * This routine tests if a new video offset has been latched. + *--------------------------------------------------------------------------*/ + +unsigned long +df_test_video_flip_status(void) +{ + return (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VFLIP); +} + +/*--------------------------------------------------------------------------- + * df_save_state + * + * This routine saves all persistent DF state information. + *--------------------------------------------------------------------------*/ + +int +df_save_state(DF_SAVE_RESTORE * df_state) +{ + unsigned long i; + + /* READ ALL DF REGISTERS */ + + df_state->vcfg = READ_VID32(DF_VIDEO_CONFIG); + df_state->dcfg = READ_VID32(DF_DISPLAY_CONFIG); + df_state->video_x = READ_VID32(DF_VIDEO_X_POS); + df_state->video_y = READ_VID32(DF_VIDEO_Y_POS); + df_state->video_scaler = READ_VID32(DF_VIDEO_SCALER); + df_state->video_color_key = READ_VID32(DF_VIDEO_COLOR_KEY); + df_state->video_color_mask = READ_VID32(DF_VIDEO_COLOR_MASK); + df_state->sat_limit = READ_VID32(DF_SATURATION_LIMIT); + df_state->vid_misc = READ_VID32(DF_VID_MISC); + df_state->video_yscale = READ_VID32(DF_VIDEO_YSCALE); + df_state->video_xscale = READ_VID32(DF_VIDEO_XSCALE); + df_state->vid_alpha_control = READ_VID32(DF_VID_ALPHA_CONTROL); + df_state->cursor_key = READ_VID32(DF_CURSOR_COLOR_KEY); + df_state->cursor_mask = READ_VID32(DF_CURSOR_COLOR_MASK); + df_state->cursor_color1 = READ_VID32(DF_CURSOR_COLOR_1); + df_state->cursor_color2 = READ_VID32(DF_CURSOR_COLOR_2); + df_state->alpha_xpos1 = READ_VID32(DF_ALPHA_XPOS_1); + df_state->alpha_ypos1 = READ_VID32(DF_ALPHA_YPOS_1); + df_state->alpha_color1 = READ_VID32(DF_ALPHA_COLOR_1); + df_state->alpha_control1 = READ_VID32(DF_ALPHA_CONTROL_1); + df_state->alpha_xpos2 = READ_VID32(DF_ALPHA_XPOS_2); + df_state->alpha_ypos2 = READ_VID32(DF_ALPHA_YPOS_2); + df_state->alpha_color2 = READ_VID32(DF_ALPHA_COLOR_2); + df_state->alpha_control2 = READ_VID32(DF_ALPHA_CONTROL_2); + df_state->alpha_xpos3 = READ_VID32(DF_ALPHA_XPOS_3); + df_state->alpha_ypos3 = READ_VID32(DF_ALPHA_YPOS_3); + df_state->alpha_color3 = READ_VID32(DF_ALPHA_COLOR_3); + df_state->alpha_control3 = READ_VID32(DF_ALPHA_CONTROL_3); + df_state->vid_request = READ_VID32(DF_VIDEO_REQUEST); + df_state->vid_ypos_even = READ_VID32(DF_VID_YPOS_EVEN); + df_state->alpha_ypos_even1 = READ_VID32(DF_VID_ALPHA_Y_EVEN_1); + df_state->alpha_ypos_even2 = READ_VID32(DF_VID_ALPHA_Y_EVEN_2); + df_state->alpha_ypos_even3 = READ_VID32(DF_VID_ALPHA_Y_EVEN_3); + df_state->panel_tim1 = READ_VID32(DF_VIDEO_PANEL_TIM1); + df_state->panel_tim2 = READ_VID32(DF_VIDEO_PANEL_TIM2); + df_state->panel_pm = READ_VID32(DF_POWER_MANAGEMENT); + df_state->panel_dither = READ_VID32(DF_DITHER_CONTROL); + + /* READ DF PALETTE */ + + WRITE_VID32(DF_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) + df_state->palette[i] = READ_VID32(DF_PALETTE_DATA); + + /* READ FILTER COEFFICIENTS */ + + for (i = 0; i < 512; i++) + df_state->coefficients[i] = + READ_VID32(DF_COEFFICIENT_BASE + (i << 2)); + + /* READ ALL DF MSRS */ + + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP, + &(df_state->msr_cap)); + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, + &(df_state->msr_config)); + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI, + &(df_state->msr_smi)); + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR, + &(df_state->msr_error)); + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM, &(df_state->msr_pm)); + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, + &(df_state->msr_diag)); + msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, + &(df_state->msr_df_diag)); + msr_read64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, + &(df_state->msr_pad_sel)); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_restore_state + * + * This routine restores all persistent DF state information. + *--------------------------------------------------------------------------*/ + +int +df_restore_state(DF_SAVE_RESTORE * df_state) +{ + unsigned long i; + + /* CLEAR VCFG AND DCFG */ + + WRITE_VID32(DF_VIDEO_CONFIG, 0); + WRITE_VID32(DF_DISPLAY_CONFIG, 0); + + /* RESTORE DF MSRS */ + + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP, + &(df_state->msr_cap)); + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, + &(df_state->msr_config)); + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI, + &(df_state->msr_smi)); + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR, + &(df_state->msr_error)); + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM, &(df_state->msr_pm)); + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, + &(df_state->msr_diag)); + msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, + &(df_state->msr_df_diag)); + msr_write64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, + &(df_state->msr_pad_sel)); + + /* RESTORE ALL DF REGISTERS */ + + WRITE_VID32(DF_VIDEO_X_POS, df_state->video_x); + WRITE_VID32(DF_VIDEO_Y_POS, df_state->video_y); + WRITE_VID32(DF_VIDEO_SCALER, df_state->video_scaler); + WRITE_VID32(DF_VIDEO_COLOR_KEY, df_state->video_color_key); + WRITE_VID32(DF_VIDEO_COLOR_MASK, df_state->video_color_mask); + WRITE_VID32(DF_SATURATION_LIMIT, df_state->sat_limit); + WRITE_VID32(DF_VID_MISC, df_state->vid_misc); + WRITE_VID32(DF_VIDEO_YSCALE, df_state->video_yscale); + WRITE_VID32(DF_VIDEO_XSCALE, df_state->video_xscale); + WRITE_VID32(DF_VID_ALPHA_CONTROL, df_state->vid_alpha_control); + WRITE_VID32(DF_CURSOR_COLOR_KEY, df_state->cursor_key); + WRITE_VID32(DF_CURSOR_COLOR_MASK, df_state->cursor_mask); + WRITE_VID32(DF_CURSOR_COLOR_1, df_state->cursor_color1); + WRITE_VID32(DF_CURSOR_COLOR_2, df_state->cursor_color2); + WRITE_VID32(DF_ALPHA_XPOS_1, df_state->alpha_xpos1); + WRITE_VID32(DF_ALPHA_YPOS_1, df_state->alpha_ypos1); + WRITE_VID32(DF_ALPHA_COLOR_1, df_state->alpha_color1); + WRITE_VID32(DF_ALPHA_CONTROL_1, df_state->alpha_control1); + WRITE_VID32(DF_ALPHA_XPOS_2, df_state->alpha_xpos2); + WRITE_VID32(DF_ALPHA_YPOS_2, df_state->alpha_ypos2); + WRITE_VID32(DF_ALPHA_COLOR_2, df_state->alpha_color2); + WRITE_VID32(DF_ALPHA_CONTROL_2, df_state->alpha_control1); + WRITE_VID32(DF_ALPHA_XPOS_3, df_state->alpha_xpos3); + WRITE_VID32(DF_ALPHA_YPOS_3, df_state->alpha_ypos3); + WRITE_VID32(DF_ALPHA_COLOR_3, df_state->alpha_color3); + WRITE_VID32(DF_ALPHA_CONTROL_3, df_state->alpha_control3); + WRITE_VID32(DF_VIDEO_REQUEST, df_state->vid_request); + WRITE_VID32(DF_VID_YPOS_EVEN, df_state->vid_ypos_even); + WRITE_VID32(DF_VID_ALPHA_Y_EVEN_1, df_state->alpha_ypos_even1); + WRITE_VID32(DF_VID_ALPHA_Y_EVEN_2, df_state->alpha_ypos_even2); + WRITE_VID32(DF_VID_ALPHA_Y_EVEN_3, df_state->alpha_ypos_even3); + WRITE_VID32(DF_VIDEO_PANEL_TIM1, df_state->panel_tim1); + WRITE_VID32(DF_VIDEO_PANEL_TIM2, df_state->panel_tim2); + WRITE_VID32(DF_POWER_MANAGEMENT, df_state->panel_pm); + WRITE_VID32(DF_DITHER_CONTROL, df_state->panel_dither); + + /* RESTORE DF PALETTE */ + + WRITE_VID32(DF_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) + WRITE_VID32(DF_PALETTE_DATA, df_state->palette[i]); + + /* RESTORE FILTER COEFFICIENTS */ + + for (i = 0; i < 512; i++) + WRITE_VID32(DF_COEFFICIENT_BASE + (i << 2), + df_state->coefficients[i]); + + /* RESTORE DCFG AND VCFG */ + + WRITE_VID32(DF_DISPLAY_CONFIG, df_state->dcfg); + WRITE_VID32(DF_VIDEO_CONFIG, df_state->vcfg); + + return CIM_STATUS_OK; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * CIMARRON DF READ ROUTINES + * These routines are included for use in diagnostics or when debugging. They + * can be optionally excluded from a project. + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +#if CIMARRON_INCLUDE_DF_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * df_read_composite_crc + * + * This routine reads the CRC of the combination of graphics/video data. This + * CRC checks data immediately before the CRT DACs. + *--------------------------------------------------------------------------*/ + +unsigned long +df_read_composite_crc(int crc_source) +{ + Q_WORD msr_value; + unsigned long crc; + unsigned long interlaced; + unsigned long line, field; + unsigned long timeout = 1000; + + if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) + return 0xFFFFFFFF; + + /* ENABLE 32-BIT CRCS */ + + msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); + msr_value.low |= DF_DIAG_32BIT_CRC; + msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); + + /* RESET THE CRC */ + + WRITE_VID32(DF_VID_CRC, 0); + + /* WAIT FOR THE RESET TO BE LATCHED */ + + while ((READ_VID32(DF_VID_CRC32) != 0x00000001) && timeout) + timeout--; + + /* WAIT FOR THE CORRECT FIELD */ + /* We use the VG line count and field indicator to determine when */ + /* to kick off a CRC. */ + + if (crc_source & DF_CRC_SOURCE_EVEN) + field = 0; + else + field = DC3_LNCNT_EVEN_FIELD; + + if ((interlaced = (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN))) { + /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */ + /* Note that we wait for the field to be odd when CRCing the even */ + /* field and vice versa. This is because the CRC will not begin */ + /* until the following field. */ + + do { + line = READ_REG32(DC3_LINE_CNT_STATUS); + } while ((line & DC3_LNCNT_EVEN_FIELD) != field || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 10 || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 15); + } else { + /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */ + + if (crc_source & DF_CRC_SOURCE_EVEN) + return 0xFFFFFFFF; + } + + /* ENABLE THE CRC */ + + WRITE_VID32(DF_VID_CRC, 1); + + /* WAIT FOR THE CRC TO BE COMPLETED */ + + while (!(READ_VID32(DF_VID_CRC) & 4)) ; + + crc = READ_VID32(DF_VID_CRC32); + + return crc; +} + +/*--------------------------------------------------------------------------- + * df_read_composite_window_crc + * + * This routine reads the CRC of a rectangular subsection of the combination + * of graphics/video data. + *--------------------------------------------------------------------------*/ + +unsigned long +df_read_composite_window_crc(unsigned long x, unsigned long y, + unsigned long width, unsigned long height, int source) +{ + Q_WORD msr_value; + unsigned long interlaced; + unsigned long line, field; + unsigned long crc = 0; + unsigned long hsyncend, htotal, hsyncstart; + unsigned long vsyncend, vtotal, vsyncstart; + unsigned long hblankstart, hactive; + unsigned long vblankstart, vactive; + + hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + hsyncstart = (READ_REG32(DC3_H_SYNC_TIMING) & 0xFFF) + 1; + hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1; + hblankstart = (READ_REG32(DC3_H_BLANK_TIMING) & 0xFFF) + 1; + if ((interlaced = (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)) && + !(source & DF_CRC_SOURCE_EVEN)) { + vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; + vsyncstart = (READ_REG32(DC3_V_SYNC_EVEN) & 0xFFF) + 1; + vactive = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1; + vblankstart = (READ_REG32(DC3_V_BLANK_EVEN) & 0xFFF) + 1; + } else { + vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + vsyncstart = (READ_REG32(DC3_V_SYNC_TIMING) & 0xFFF) + 1; + vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1; + vblankstart = (READ_REG32(DC3_V_BLANK_TIMING) & 0xFFF) + 1; + } + + /* TIMINGS MUST BE ACTIVE */ + + if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) + return 0xFFFFFFFF; + + /* DISABLE GLCP ACTIONS */ + + msr_value.low = 0; + msr_value.high = 0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); + + /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */ + + msr_value.low = 5; + msr_write64(MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value); + msr_value.low = 0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + msr_value.low = 3; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + + /* USE H4 FUNCTION A FOR HSYNC AND H4 FUNCTION B FOR NOT HSYNC */ + /* HSYNC is bit 30 for the DF */ + + msr_value.high = 0x00000001; + msr_value.low = 0xE0000FF0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 4, &msr_value); + + /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */ + /* VSYNC is bit 54 for VG and bit 29 for DF */ + + msr_value.high = 0x00000000; + msr_value.low = 0x001D55AA; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value); + + /* M4 (XSTATE = 00 AND VSYNC HIGH) */ + /* Goto state 01 */ + /* Note: VSync = H3A */ + + msr_value.high = 0x00000001; + msr_value.low = 0x000000A0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 4, &msr_value); + + /* N0 (XSTATE = 01 AND VSYNC LOW) */ + /* Goto state 02 */ + /* Note: VSync low = H3B */ + + msr_value.high = 0x00040000; + msr_value.low = 0x000000C0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL, &msr_value); + + /* M5 (XSTATE = 10 AND VSYNC HIGH) */ + /* Goto state 11 */ + + msr_value.high = 0x00000001; + msr_value.low = 0x00000120; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 5, &msr_value); + + /* N1 (XSTATE = 10 and HSYNC LOW) */ + /* Increment H. Counter */ + /* Note: HSync = H4 */ + + msr_value.high = 0x00080000; + msr_value.low = 0x00000120; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 1, &msr_value); + + /* M0 (XSTATE = 10 and H. COUNTER == LIMIT) */ + /* Clear H. Counter and increment V. Counter */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000122; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL, &msr_value); + + /* N4 (XSTATE = 10 && CMP0 <= H. COUNTER <= CMP1 && CMP2 <= V. COUNTER + * <= CMP3) + * CRC into REGB + */ + + msr_value.high = 0x00000000; + msr_value.low = 0x10C20120; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 4, &msr_value); + + /* COMPARATOR 0 VALUE */ + /* Value = xstart + (htotal - hsync_end) - 1 */ + /* The value will be adjusted for a border if necessary */ + + msr_value.low = x + htotal - hsyncend - 1; + if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) + msr_value.low -= hblankstart - hactive; + msr_value.low--; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0, &msr_value); + + /* COMPARATOR 1 VALUE */ + /* Value = xstart + (htotal - hsync_end - 1) - 1 + width */ + + msr_value.low += width - 1; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 2, &msr_value); + + /* COMPARATOR 2 VALUE */ + /* Value = ystart + vtotal - vsyncend */ + + msr_value.low = (y + vtotal - vsyncend) << 16; + if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) + msr_value.low -= (vblankstart - vactive) << 16; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 4, &msr_value); + + /* COMPARATOR 3 VALUE */ + /* Value = ystart + vtotal - vsyncend + height - 1 */ + + msr_value.low += (height - 1) << 16; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 6, &msr_value); + + /* COMPARATOR MASKS */ + /* Comparators 0 and 1 refer to lower 16 bits of RegB */ + + msr_value.low = 0x0000FFFF; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 2, &msr_value); + + /* Comparators 2 and 3 refer to upper 16 bits of RegB */ + + msr_value.low = 0xFFFF0000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 4, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 6, &msr_value); + + /* SET REGB MASK */ + /* We set the mask such that all only 24 bits of data are CRCed */ + + msr_value.low = 0x00FFFFFF; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGBMASK, &msr_value); + + /* SET REGA LIMITS */ + /* Lower counter uses htotal - sync_time - 1. */ + /* Upper counter is 0xFFFF to prevent rollover. */ + + msr_value.low = 0xFFFF0000 | (htotal - (hsyncend - hsyncstart) - 1); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value); + + /* ACTIONS */ + + /* STATE 00->01 (SET 4M) */ + + msr_value.low = 0x000C0000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 14, &msr_value); + + /* STATE 01->10 (SET 0N) */ + + msr_value.low = 0x0000000A; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 15, &msr_value); + + /* STATE 10->11 (SET 5M) */ + + msr_value.low = 0x00C00000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 16, &msr_value); + + /* CLEAR REGA WHEN TRANSITIONING TO STATE 10 */ + /* Do not clear RegB as the initial value must be 0x00000001 */ + + msr_value.low = 0x0000000A; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0, &msr_value); + + /* REGISTER ACTION 1 */ + /* CRC into RegB if cmp0 <= h.counter <= cmp1 && cmp2 <= v. counter < + * cmp3 && 7 xstate = 10 8 + * Increment h.counter if xstate = 10 and HSync is low. + */ + + msr_value.low = 0x000A00A0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 1, &msr_value); + + /* REGISTER ACTION 2 */ + /* Increment V. Counter in REGA */ + + msr_value.low = 0x0000000C; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 2, &msr_value); + + /* SET REGB TO 0x00000001 */ + + msr_value.low = 0x00000001; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value); + + /* SET XSTATE TO 0 */ + + msr_value.low = 0x00000000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value); + + /* CLEAR ALL OTHER ACTIONS */ + /* This prevents side-effects from previous accesses to the GLCP */ + /* debug logic. */ + + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 3, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 4, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 5, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 6, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 7, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 8, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 9, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 10, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 11, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 12, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 13, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 17, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 18, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 19, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 20, &msr_value); + + /* WAIT FOR THE CORRECT FIELD */ + /* We use the VG line count and field indicator to determine when */ + /* to kick off a CRC. */ + + if (source & DF_CRC_SOURCE_EVEN) + field = 0; + else + field = DC3_LNCNT_EVEN_FIELD; + + if (interlaced) { + /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */ + /* Note that we wait for the field to be odd when CRCing the even */ + /* field and vice versa. This is because the CRC will not begin */ + /* until the following field. */ + + do { + line = READ_REG32(DC3_LINE_CNT_STATUS); + } while ((line & DC3_LNCNT_EVEN_FIELD) != field || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 1 || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 5); + } else { + /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */ + + if (source & DF_CRC_SOURCE_EVEN) + return 0xFFFFFFFF; + } + + /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */ + + msr_value.high = 0; + msr_value.low = 0x0000800B; + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, &msr_value); + + /* CONFIGURE DIAG CONTROL */ + /* Set RegA action1 to increment lower 16 bits and clear at limit. (5) + * Set RegA action2 to increment upper 16 bits. (6) + * Set RegB action1 to CRC32 (1) + * Set all comparators to REGA override (0,1 lower mbus, 2,3 upper mbus) + * Enable all actions + */ + + msr_value.low = 0x80EA20A0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); + + /* DELAY TWO FRAMES */ + + while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA) ; + while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)) ; + while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA) ; + while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)) ; + while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA) ; + + /* VERIFY THAT XSTATE = 11 */ + + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value); + if ((msr_value.low & 3) == 3) { + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value); + + crc = msr_value.low; + } + + /* DISABLE DF DIAG BUS OUTPUTS */ + + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, &msr_value); + + /* DISABLE GLCP ACTIONS */ + + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); + + return crc; +} + +/*--------------------------------------------------------------------------- + * df_read_panel_crc + * + * This routine reads the CRC for a frame of data after the panel dithering + * logic. + *--------------------------------------------------------------------------*/ + +unsigned long +df_read_panel_crc(void) +{ + Q_WORD msr_value; + unsigned long timeout = 1000; + + if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) + return 0xFFFFFFFF; + + /* ENABLE 32-BIT CRCS */ + + msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); + msr_value.low |= DF_DIAG_32BIT_CRC; + msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); + + /* RESET CRC */ + + WRITE_VID32(DF_PANEL_CRC, 0); + + /* WAIT FOR THE RESET TO BE LATCHED */ + + while ((READ_VID32(DF_PANEL_CRC32) != 0x00000001) && timeout) + timeout--; + + WRITE_VID32(DF_PANEL_CRC, 1); + + /* WAIT FOR THE CRC TO BE COMPLETED */ + + while (!(READ_VID32(DF_PANEL_CRC) & 4)) ; + + return READ_VID32(DF_PANEL_CRC32); +} + +/*--------------------------------------------------------------------------- + * df_get_video_enable + * + * This routine reads the enable status of the video overlay. + *--------------------------------------------------------------------------*/ + +int +df_get_video_enable(int *enable, unsigned long *flags) +{ + *enable = 0; + *flags = 0; + if (READ_VID32(DF_VIDEO_CONFIG) & DF_VCFG_VID_EN) { + *enable = 1; + + /* CHECK FOR COLOR KEY DISABLED */ + /* Color keying can be completely disabled when video is enabled to */ + /* allow unhindered per-pixel alpha blending. As color keying is */ + /* always disabled when video is disabled, it is only possible to */ + /* test for this condition when video is enabled. */ + + if (!(READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK) && + !(READ_REG32(DC3_COLOR_KEY) & DC3_CLR_KEY_ENABLE)) { + *flags = DF_ENABLEFLAG_NOCOLORKEY; + } + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_source_configuration + * + * This routine reads the current configuration of the source buffers for the + * video overlay. + *--------------------------------------------------------------------------*/ + +int +df_get_video_source_configuration(DF_VIDEO_SOURCE_PARAMS * video_source_odd, + DF_VIDEO_SOURCE_PARAMS * video_source_even) +{ + unsigned long format, temp; + unsigned long size; + + /* READ VIDEO FORMAT */ + + temp = READ_VID32(DF_VIDEO_CONFIG); + + format = (temp >> 2) & 3; + if (temp & DF_VCFG_4_2_0_MODE) + format |= 4; + else if (READ_VID32(DF_VID_ALPHA_CONTROL) & DF_VIDEO_INPUT_IS_RGB) + format |= 8; + video_source_odd->video_format = format; + + /* CHECK IF SOURCE IS HD VIDEO */ + + if (READ_VID32(DF_VID_ALPHA_CONTROL) & DF_HD_VIDEO) + video_source_odd->flags = DF_SOURCEFLAG_HDTVSOURCE; + else + video_source_odd->flags = 0; + + /* READ SCALING ALGORITHM */ + + if (READ_VID32(DF_VID_MISC) & DF_USER_IMPLICIT_SCALING) + video_source_odd->flags |= DF_SOURCEFLAG_IMPLICITSCALING; + + /* READ VIDEO PITCH */ + + temp = READ_REG32(DC3_VID_YUV_PITCH); + video_source_odd->y_pitch = (temp & 0xFFFF) << 3; + video_source_odd->uv_pitch = (temp >> 16) << 3; + + /* READ VIDEO SIZE */ + + temp = READ_VID32(DF_VIDEO_CONFIG); + size = (temp >> 8) & 0xFF; + if (temp & DF_VCFG_LINE_SIZE_BIT8) + size |= 0x100; + if (temp & DF_VCFG_LINE_SIZE_BIT9) + size |= 0x200; + + video_source_odd->width = size << 1; + video_source_odd->height = READ_VID32(DF_VIDEO_SCALER) & 0x7FF; + + /* READ VIDEO OFFSETS */ + + video_source_odd->y_offset = READ_REG32(DC3_VID_Y_ST_OFFSET) & 0xFFFFFFF; + video_source_odd->u_offset = READ_REG32(DC3_VID_U_ST_OFFSET) & 0xFFFFFFF; + video_source_odd->v_offset = READ_REG32(DC3_VID_V_ST_OFFSET) & 0xFFFFFFF; + + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + video_source_even->y_offset = + READ_REG32(DC3_VID_EVEN_Y_ST_OFFSET) & 0xFFFFFFF; + video_source_even->u_offset = + READ_REG32(DC3_VID_EVEN_U_ST_OFFSET) & 0xFFFFFFF; + video_source_even->v_offset = + READ_REG32(DC3_VID_EVEN_V_ST_OFFSET) & 0xFFFFFFF; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_position + * + * This routine reads the current position of the video overlay. + *--------------------------------------------------------------------------*/ + +int +df_get_video_position(DF_VIDEO_POSITION * video_window) +{ + unsigned long xreg, yreg, dst_clip, clip; + unsigned long height; + unsigned long xend, yend; + unsigned long hsyncend, htotal; + unsigned long vsyncend, vtotal; + unsigned long hadjust, vadjust; + unsigned long misc, gfxscale; + unsigned long temp; + long xstart, ystart; + + video_window->flags = DF_POSFLAG_DIRECTCLIP; + + hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + + /* ODD FIELD START COUNTS FROM THE EVEN FIELD TIMINGS */ + /* We assume that the even field y position is always programmed */ + /* to be just after the odd field. */ + + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; + } else { + vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + } + + hadjust = htotal - hsyncend - 14; + vadjust = vtotal - vsyncend + 1; + + xreg = READ_VID32(DF_VIDEO_X_POS); + yreg = READ_VID32(DF_VIDEO_Y_POS); + + xstart = (xreg & 0xFFF) - hadjust; + ystart = (yreg & 0x7FF) - vadjust; + xend = ((xreg >> 16) & 0xFFF) - hadjust; + yend = ((yreg >> 16) & 0x7FF) - vadjust; + + height = yend - ystart; + + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */ + + ystart <<= 1; + + /* CALCULATE THE EXACT VIDEO HEIGHT */ + /* The height of the video window is the sum of the */ + /* odd and even field heights. */ + + yreg = READ_VID32(DF_VID_YPOS_EVEN); + height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF); + } + + clip = ((READ_VID32(DF_VIDEO_CONFIG) >> 16) & 0x1FF) << 2; + + /* ADJUST FOR CLIPPING VALUES THAT ARE NOT FOUR-PIXEL ALIGNED */ + + dst_clip = 0; + if (xstart < 0) { + dst_clip += -xstart; + xstart = 0; + } + + /* REVERSE THE GRAPHICS SCALE */ + + misc = READ_VID32(DF_VID_MISC); + if (misc & DF_USER_IMPLICIT_SCALING) { + gfxscale = READ_REG32(DC3_GFX_SCALE); + + if (gfxscale != 0x40004000) { + temp = ystart + height; + temp = (temp * (gfxscale >> 16)) / 0x4000; + + xstart = (xstart * (gfxscale & 0xFFFF)) / 0x4000; + xend = (xend * (gfxscale & 0xFFFF)) / 0x4000; + ystart = (ystart * (gfxscale >> 16)) / 0x4000; + height = temp - ystart; + } + } + + video_window->left_clip = clip; + video_window->dst_clip = dst_clip; + video_window->x = xstart; + video_window->y = ystart; + video_window->width = xend - xstart; + video_window->height = height; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_scale + * + * This routine reads the current scale values for video scaling. + *--------------------------------------------------------------------------*/ + +int +df_get_video_scale(unsigned long *x_scale, unsigned long *y_scale) +{ + *x_scale = READ_VID32(DF_VIDEO_XSCALE) & 0x000FFFFF; + *y_scale = READ_VID32(DF_VIDEO_YSCALE) & 0x000FFFFF; + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_filter_coefficients + * + * This routine reads the coefficients for the video scaler/filter. + *--------------------------------------------------------------------------*/ + +int +df_get_video_filter_coefficients(long taps[][4], int *phase256) +{ + unsigned long i, temp; + long coeff; + + if (READ_VID32(DF_VIDEO_SCALER) & DF_SCALE_128_PHASES) + *phase256 = 0; + else + *phase256 = 1; + + for (i = 0; i < 256; i++) { + temp = READ_VID32(DF_COEFFICIENT_BASE + (i << 3)); + + /* TAP 0 */ + + coeff = temp & 0x7FFF; + if (temp & 0x8000) + coeff = -coeff; + taps[i][0] = coeff; + + /* TAP 1 */ + + temp >>= 16; + coeff = temp & 0x7FFF; + if (temp & 0x8000) + coeff = -coeff; + taps[i][1] = coeff; + + temp = READ_VID32(DF_COEFFICIENT_BASE + (i << 3) + 4); + + /* TAP 2 */ + + coeff = temp & 0x7FFF; + if (temp & 0x8000) + coeff = -coeff; + taps[i][2] = coeff; + + /* TAP 3 */ + + temp >>= 16; + coeff = temp & 0x7FFF; + if (temp & 0x8000) + coeff = -coeff; + taps[i][3] = coeff; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_color_key + * + * This routine reads the current settings for hardware color/chroma keying. + *--------------------------------------------------------------------------*/ + +int +df_get_video_color_key(unsigned long *key, unsigned long *mask, int *graphics) +{ + unsigned long chroma = READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK; + + if (chroma) { + /* CHROMA KEY - READ KEY AND MASK FROM DF */ + + *graphics = 0; + *key = READ_VID32(DF_VIDEO_COLOR_KEY) & 0xFFFFFF; + *mask = READ_VID32(DF_VIDEO_COLOR_MASK) & 0xFFFFFF; + } else { + *graphics = 1; + + *key = READ_REG32(DC3_COLOR_KEY) & 0xFFFFFF; + *mask = READ_REG32(DC3_COLOR_MASK) & 0xFFFFFF; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_palette_entry + * + * This routine returns a single palette entry. + *--------------------------------------------------------------------------*/ + +int +df_get_video_palette_entry(unsigned long index, unsigned long *palette) +{ + if (index > 0xFF) + return CIM_STATUS_INVALIDPARAMS; + + /* READ A SINGLE ENTRY */ + + WRITE_VID32(DF_PALETTE_ADDRESS, index); + *palette = READ_VID32(DF_PALETTE_DATA); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_palette + * + * This routine returns the entire video palette. + *--------------------------------------------------------------------------*/ + +int +df_get_video_palette(unsigned long *palette) +{ + unsigned long i; + + WRITE_VID32(DF_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) + palette[i] = READ_VID32(DF_PALETTE_DATA); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_cursor_color_key + * + * This routine returns the current configuration for the hardware video cursor + * color key. + *--------------------------------------------------------------------------*/ + +int +df_get_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * cursor_color_key) +{ + unsigned long key; + + cursor_color_key->flags = 0; + cursor_color_key->color1 = READ_VID32(DF_CURSOR_COLOR_1) & 0xFFFFFF; + cursor_color_key->color2 = READ_VID32(DF_CURSOR_COLOR_2) & 0xFFFFFF; + cursor_color_key->mask = READ_VID32(DF_CURSOR_COLOR_MASK) & 0xFFFFFF; + + key = READ_VID32(DF_CURSOR_COLOR_KEY); + cursor_color_key->key = key & 0xFFFFFF; + cursor_color_key->select_color2 = (key >> 24) & 0x1F; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_video_cursor_color_key_enable + * + * This routine returns the current enable status of the hardware video cursor + * color key. + *--------------------------------------------------------------------------*/ + +int +df_get_video_cursor_color_key_enable(void) +{ + if (READ_VID32(DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * df_get_alpha_window_configuration + * + * This routine reads the current configuration for one of the three hardware + * alpha regions. + *--------------------------------------------------------------------------*/ + +int +df_get_alpha_window_configuration(int window, + DF_ALPHA_REGION_PARAMS * alpha_data) +{ + unsigned long pos, color, alpha_ctl; + unsigned long hsyncend, htotal; + unsigned long vsyncend, vtotal; + unsigned long hadjust, vadjust; + unsigned long xreg, yreg; + unsigned long misc, gfxscale; + unsigned long temp; + char delta; + + if (window > 2) + return CIM_STATUS_INVALIDPARAMS; + + hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; + vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; + } else { + vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; + } + + /* GET PRIORITY */ + + pos = 16 + (window << 1); + alpha_data->priority = (READ_VID32(DF_VID_ALPHA_CONTROL) >> pos) & 3L; + + /* GET ALPHA WINDOW */ + + hadjust = htotal - hsyncend - 2; + vadjust = vtotal - vsyncend + 1; + + xreg = READ_VID32(DF_ALPHA_XPOS_1 + (window << 5)); + yreg = READ_VID32(DF_ALPHA_YPOS_1 + (window << 5)); + alpha_data->width = ((xreg >> 16) & 0xFFF) - (xreg & 0xFFF); + alpha_data->height = ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF); + alpha_data->x = (xreg & 0xFFF) - hadjust; + alpha_data->y = (yreg & 0x7FF) - vadjust; + + /* REVERSE THE GRAPHICS SCALE */ + + misc = READ_VID32(DF_VID_MISC); + if (misc & DF_USER_IMPLICIT_SCALING) { + gfxscale = READ_REG32(DC3_GFX_SCALE); + if (gfxscale != 0x40004000) { + temp = alpha_data->y + alpha_data->height; + temp = (temp * (gfxscale >> 16)) / 0x4000; + + alpha_data->x = (alpha_data->x * (gfxscale & 0xFFFF)) / 0x4000; + alpha_data->width = + (alpha_data->width * (gfxscale & 0xFFFF)) / 0x4000; + alpha_data->y = (alpha_data->y * (gfxscale >> 16)) / 0x4000; + alpha_data->height = temp - alpha_data->y; + } + } + + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */ + + alpha_data->y <<= 1; + + /* CALCULATE THE EXACT VIDEO HEIGHT */ + /* The height of the video window is the sum of the */ + /* odd and even field heights. */ + + yreg = READ_VID32(DF_VID_ALPHA_Y_EVEN_1 + (window << 3)); + alpha_data->height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF); + } + + /* GET COLOR REGISTER */ + + color = READ_VID32(DF_ALPHA_COLOR_1 + (window << 5)); + alpha_data->color = color & 0xFFFFFF; + if (color & DF_ALPHA_COLOR_ENABLE) + alpha_data->flags = DF_ALPHAFLAG_COLORENABLED; + else + alpha_data->flags = 0; + + /* GET ALPHA VALUE, DELTA AND PER PIXEL */ + + alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)); + alpha_data->alpha_value = alpha_ctl & 0xFF; + if (alpha_ctl & DF_ACTRL_PERPIXEL_EN) + alpha_data->flags |= DF_ALPHAFLAG_PERPIXELENABLED; + + delta = (char)((alpha_ctl >> 8) & 0xFF); + alpha_data->delta = (long)delta; + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_alpha_window_enable + * + * This routine reads the current enable status of one of the three hardware + * alpha regions. + *--------------------------------------------------------------------------*/ + +int +df_get_alpha_window_enable(int window) +{ + if (window > 2) + return 0; + + if (READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)) & DF_ACTRL_WIN_ENABLE) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * df_get_video_request + * + * This routine reads the horizontal (pixel) and vertical (line) video request + * values. + *--------------------------------------------------------------------------*/ + +int +df_get_video_request(unsigned long *x, unsigned long *y) +{ + unsigned long request; + unsigned long hsyncend, htotal; + unsigned long vsyncend, vtotal; + + hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; + vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + + request = READ_VID32(DF_VIDEO_REQUEST); + *x = ((request >> 16) & 0xFFF) - (htotal - hsyncend - 2); + *y = (request & 0x7FF) - (vtotal - vsyncend + 1); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * df_get_output_color_space + * + * This routine sets the color space used when combining graphics and video. + *--------------------------------------------------------------------------*/ + +int +df_get_output_color_space(int *color_space) +{ + unsigned long alpha_ctl; + + alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL); + + if ((alpha_ctl & DF_CSC_VIDEO_YUV_TO_RGB) || + !(alpha_ctl & DF_CSC_GRAPHICS_RGB_TO_YUV)) { + if (alpha_ctl & DF_ALPHA_DRGB) + *color_space = DF_OUTPUT_ARGB; + else + *color_space = DF_OUTPUT_RGB; + } else { + *color_space = DF_OUTPUT_SDTV; + + if (alpha_ctl & DF_HD_GRAPHICS) + *color_space = DF_OUTPUT_HDTV; + } + + return CIM_STATUS_OK; +} + +#endif diff --git a/src/cim/cim_filter.c b/src/cim/cim_filter.c new file mode 100644 index 0000000..87c1bf6 --- /dev/null +++ b/src/cim/cim_filter.c @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron default video coefficients. + */ + +long CimarronVideoFilter256[][2] = { + {0x10000000, 0x00000000}, /* 0, 4096, 0, 0 */ + {0x10008008, 0x00000008}, /* -8, 4096, 8, 0 */ + {0x10008010, 0x80010011}, /* -16, 4096, 17, -1 */ + {0x10008019, 0x8001001A}, /* -25, 4096, 26, -1 */ + {0x10008021, 0x80020023}, /* -33, 4096, 35, -2 */ + {0x0FFF8029, 0x8003002D}, /* -41, 4095, 45, -3 */ + {0x0FFE8031, 0x80030036}, /* -49, 4094, 54, -3 */ + {0x0FFC8038, 0x80040040}, /* -56, 4092, 64, -4 */ + {0x0FFB8040, 0x8005004A}, /* -64, 4091, 74, -5 */ + {0x0FF88047, 0x80050054}, /* -71, 4088, 84, -5 */ + {0x0FF6804E, 0x8006005E}, /* -78, 4086, 94, -6 */ + {0x0FF48055, 0x80070068}, /* -85, 4084, 104, -7 */ + {0x0FF0805C, 0x80070073}, /* -92, 4080, 115, -7 */ + {0x0FEE8063, 0x8008007D}, /* -99, 4078, 125, -8 */ + {0x0FEA8069, 0x80090088}, /* -105, 4074, 136, -9 */ + {0x0FE78070, 0x800A0093}, /* -112, 4071, 147, -10 */ + {0x0FE28076, 0x800A009E}, /* -118, 4066, 158, -10 */ + {0x0FDD807C, 0x800B00AA}, /* -124, 4061, 170, -11 */ + {0x0FD98082, 0x800C00B5}, /* -130, 4057, 181, -12 */ + {0x0FD48088, 0x800D00C1}, /* -136, 4052, 193, -13 */ + {0x0FCE808E, 0x800D00CD}, /* -142, 4046, 205, -13 */ + {0x0FC88093, 0x800E00D9}, /* -147, 4040, 217, -14 */ + {0x0FC38099, 0x800F00E5}, /* -153, 4035, 229, -15 */ + {0x0FBD809E, 0x801000F1}, /* -158, 4029, 241, -16 */ + {0x0FB680A3, 0x801000FD}, /* -163, 4022, 253, -16 */ + {0x0FAF80A8, 0x8011010A}, /* -168, 4015, 266, -17 */ + {0x0FA880AD, 0x80120117}, /* -173, 4008, 279, -18 */ + {0x0FA180B2, 0x80130124}, /* -178, 4001, 292, -19 */ + {0x0F9980B6, 0x80140131}, /* -182, 3993, 305, -20 */ + {0x0F9280BB, 0x8015013E}, /* -187, 3986, 318, -21 */ + {0x0F8880BF, 0x8015014C}, /* -191, 3976, 332, -21 */ + {0x0F8080C3, 0x80160159}, /* -195, 3968, 345, -22 */ + {0x0F7880C8, 0x80170167}, /* -200, 3960, 359, -23 */ + {0x0F6E80CB, 0x80180175}, /* -203, 3950, 373, -24 */ + {0x0F6580CF, 0x80190183}, /* -207, 3941, 387, -25 */ + {0x0F5C80D3, 0x801A0191}, /* -211, 3932, 401, -26 */ + {0x0F5280D7, 0x801B01A0}, /* -215, 3922, 416, -27 */ + {0x0F4880DA, 0x801C01AE}, /* -218, 3912, 430, -28 */ + {0x0F3D80DD, 0x801D01BD}, /* -221, 3901, 445, -29 */ + {0x0F3280E0, 0x801E01CC}, /* -224, 3890, 460, -30 */ + {0x0F2880E4, 0x801F01DB}, /* -228, 3880, 475, -31 */ + {0x0F1C80E6, 0x802001EA}, /* -230, 3868, 490, -32 */ + {0x0F1180E9, 0x802101F9}, /* -233, 3857, 505, -33 */ + {0x0F0480EB, 0x80210208}, /* -235, 3844, 520, -33 */ + {0x0EFA80EF, 0x80230218}, /* -239, 3834, 536, -35 */ + {0x0EEC80F0, 0x80230227}, /* -240, 3820, 551, -35 */ + {0x0EE080F3, 0x80240237}, /* -243, 3808, 567, -36 */ + {0x0ED380F5, 0x80250247}, /* -245, 3795, 583, -37 */ + {0x0EC780F7, 0x80270257}, /* -247, 3783, 599, -39 */ + {0x0EB980F9, 0x80280268}, /* -249, 3769, 616, -40 */ + {0x0EAC80FB, 0x80290278}, /* -251, 3756, 632, -41 */ + {0x0E9E80FD, 0x802A0289}, /* -253, 3742, 649, -42 */ + {0x0E9080FE, 0x802B0299}, /* -254, 3728, 665, -43 */ + {0x0E838100, 0x802D02AA}, /* -256, 3715, 682, -45 */ + {0x0E758102, 0x802E02BB}, /* -258, 3701, 699, -46 */ + {0x0E668103, 0x802F02CC}, /* -259, 3686, 716, -47 */ + {0x0E568104, 0x803002DE}, /* -260, 3670, 734, -48 */ + {0x0E498106, 0x803202EF}, /* -262, 3657, 751, -50 */ + {0x0E398107, 0x80330301}, /* -263, 3641, 769, -51 */ + {0x0E298108, 0x80340313}, /* -264, 3625, 787, -52 */ + {0x0E1A8109, 0x80360325}, /* -265, 3610, 805, -54 */ + {0x0E0B810A, 0x80370336}, /* -266, 3595, 822, -55 */ + {0x0DFA810A, 0x80380348}, /* -266, 3578, 840, -56 */ + {0x0DEA810B, 0x803A035B}, /* -267, 3562, 859, -58 */ + {0x0DDA810C, 0x803B036D}, /* -268, 3546, 877, -59 */ + {0x0DCA810C, 0x803D037F}, /* -268, 3530, 895, -61 */ + {0x0DB7810B, 0x803E0392}, /* -267, 3511, 914, -62 */ + {0x0DA7810C, 0x804003A5}, /* -268, 3495, 933, -64 */ + {0x0D95810C, 0x804103B8}, /* -268, 3477, 952, -65 */ + {0x0D85810C, 0x804303CA}, /* -268, 3461, 970, -67 */ + {0x0D73810C, 0x804403DD}, /* -268, 3443, 989, -68 */ + {0x0D61810C, 0x804603F1}, /* -268, 3425, 1009, -70 */ + {0x0D50810C, 0x80480404}, /* -268, 3408, 1028, -72 */ + {0x0D3E810C, 0x80490417}, /* -268, 3390, 1047, -73 */ + {0x0D2C810C, 0x804B042B}, /* -268, 3372, 1067, -75 */ + {0x0D1B810C, 0x804D043E}, /* -268, 3355, 1086, -77 */ + {0x0D07810B, 0x804E0452}, /* -267, 3335, 1106, -78 */ + {0x0CF5810B, 0x80500466}, /* -267, 3317, 1126, -80 */ + {0x0CE2810A, 0x8052047A}, /* -266, 3298, 1146, -82 */ + {0x0CCF810A, 0x8053048E}, /* -266, 3279, 1166, -83 */ + {0x0CBC8109, 0x805504A2}, /* -265, 3260, 1186, -85 */ + {0x0CA98108, 0x805704B6}, /* -264, 3241, 1206, -87 */ + {0x0C968108, 0x805904CB}, /* -264, 3222, 1227, -89 */ + {0x0C838107, 0x805B04DF}, /* -263, 3203, 1247, -91 */ + {0x0C6F8106, 0x805C04F3}, /* -262, 3183, 1267, -92 */ + {0x0C5B8105, 0x805E0508}, /* -261, 3163, 1288, -94 */ + {0x0C478104, 0x8060051D}, /* -260, 3143, 1309, -96 */ + {0x0C348103, 0x80620531}, /* -259, 3124, 1329, -98 */ + {0x0C1F8102, 0x80640547}, /* -258, 3103, 1351, -100 */ + {0x0C0C8101, 0x8066055B}, /* -257, 3084, 1371, -102 */ + {0x0BF88100, 0x80680570}, /* -256, 3064, 1392, -104 */ + {0x0BE380FE, 0x806A0585}, /* -254, 3043, 1413, -106 */ + {0x0BCF80FD, 0x806C059A}, /* -253, 3023, 1434, -108 */ + {0x0BBA80FC, 0x806E05B0}, /* -252, 3002, 1456, -110 */ + {0x0BA480F9, 0x807005C5}, /* -249, 2980, 1477, -112 */ + {0x0B8F80F8, 0x807205DB}, /* -248, 2959, 1499, -114 */ + {0x0B7A80F6, 0x807405F0}, /* -246, 2938, 1520, -116 */ + {0x0B6580F5, 0x80760606}, /* -245, 2917, 1542, -118 */ + {0x0B4F80F3, 0x8077061B}, /* -243, 2895, 1563, -119 */ + {0x0B3A80F2, 0x80790631}, /* -242, 2874, 1585, -121 */ + {0x0B2480F0, 0x807B0647}, /* -240, 2852, 1607, -123 */ + {0x0B0F80EE, 0x807D065C}, /* -238, 2831, 1628, -125 */ + {0x0AF980ED, 0x807F0673}, /* -237, 2809, 1651, -127 */ + {0x0AE480EB, 0x80810688}, /* -235, 2788, 1672, -129 */ + {0x0ACE80E9, 0x8084069F}, /* -233, 2766, 1695, -132 */ + {0x0AB980E7, 0x808606B4}, /* -231, 2745, 1716, -134 */ + {0x0AA380E6, 0x808806CB}, /* -230, 2723, 1739, -136 */ + {0x0A8D80E4, 0x808A06E1}, /* -228, 2701, 1761, -138 */ + {0x0A7780E2, 0x808C06F7}, /* -226, 2679, 1783, -140 */ + {0x0A6180E0, 0x808E070D}, /* -224, 2657, 1805, -142 */ + {0x0A4B80DE, 0x80910724}, /* -222, 2635, 1828, -145 */ + {0x0A3580DC, 0x8093073A}, /* -220, 2613, 1850, -147 */ + {0x0A1F80DA, 0x80950750}, /* -218, 2591, 1872, -149 */ + {0x0A0880D8, 0x80970767}, /* -216, 2568, 1895, -151 */ + {0x09F280D6, 0x8099077D}, /* -214, 2546, 1917, -153 */ + {0x09DD80D4, 0x809C0793}, /* -212, 2525, 1939, -156 */ + {0x09C680D2, 0x809E07AA}, /* -210, 2502, 1962, -158 */ + {0x09B080D0, 0x80A007C0}, /* -208, 2480, 1984, -160 */ + {0x099980CE, 0x80A207D7}, /* -206, 2457, 2007, -162 */ + {0x098380CB, 0x80A507ED}, /* -203, 2435, 2029, -165 */ + {0x096C80C9, 0x80A70804}, /* -201, 2412, 2052, -167 */ + {0x095680C7, 0x80A9081A}, /* -199, 2390, 2074, -169 */ + {0x094080C5, 0x80AB0830}, /* -197, 2368, 2096, -171 */ + {0x092980C3, 0x80AE0848}, /* -195, 2345, 2120, -174 */ + {0x091380C1, 0x80B0085E}, /* -193, 2323, 2142, -176 */ + {0x08FC80BE, 0x80B20874}, /* -190, 2300, 2164, -178 */ + {0x08E580BC, 0x80B4088B}, /* -188, 2277, 2187, -180 */ + {0x08D080BB, 0x80B708A2}, /* -187, 2256, 2210, -183 */ + {0x08B980B9, 0x80B908B9}, /* -185, 2233, 2233, -185 */ + {0x08A380B7, 0x80BB08CF}, /* -183, 2211, 2255, -187 */ + {0x088B80B4, 0x80BC08E5}, /* -180, 2187, 2277, -188 */ + {0x087480B2, 0x80BE08FC}, /* -178, 2164, 2300, -190 */ + {0x085E80B0, 0x80C10913}, /* -176, 2142, 2323, -193 */ + {0x084880AE, 0x80C30929}, /* -174, 2120, 2345, -195 */ + {0x083080AB, 0x80C50940}, /* -171, 2096, 2368, -197 */ + {0x081A80A9, 0x80C70956}, /* -169, 2074, 2390, -199 */ + {0x080480A7, 0x80C9096C}, /* -167, 2052, 2412, -201 */ + {0x07ED80A5, 0x80CB0983}, /* -165, 2029, 2435, -203 */ + {0x07D780A2, 0x80CE0999}, /* -162, 2007, 2457, -206 */ + {0x07C080A0, 0x80D009B0}, /* -160, 1984, 2480, -208 */ + {0x07AA809E, 0x80D209C6}, /* -158, 1962, 2502, -210 */ + {0x0793809C, 0x80D409DD}, /* -156, 1939, 2525, -212 */ + {0x077D8099, 0x80D609F2}, /* -153, 1917, 2546, -214 */ + {0x07668097, 0x80D80A09}, /* -151, 1894, 2569, -216 */ + {0x074F8095, 0x80DA0A20}, /* -149, 1871, 2592, -218 */ + {0x073A8093, 0x80DC0A35}, /* -147, 1850, 2613, -220 */ + {0x07238091, 0x80DE0A4C}, /* -145, 1827, 2636, -222 */ + {0x070C808E, 0x80E00A62}, /* -142, 1804, 2658, -224 */ + {0x06F7808C, 0x80E20A77}, /* -140, 1783, 2679, -226 */ + {0x06E0808A, 0x80E40A8E}, /* -138, 1760, 2702, -228 */ + {0x06CA8088, 0x80E60AA4}, /* -136, 1738, 2724, -230 */ + {0x06B48086, 0x80E70AB9}, /* -134, 1716, 2745, -231 */ + {0x069E8084, 0x80E90ACF}, /* -132, 1694, 2767, -233 */ + {0x06878081, 0x80EB0AE5}, /* -129, 1671, 2789, -235 */ + {0x0672807F, 0x80ED0AFA}, /* -127, 1650, 2810, -237 */ + {0x065C807D, 0x80EE0B0F}, /* -125, 1628, 2831, -238 */ + {0x0646807B, 0x80F00B25}, /* -123, 1606, 2853, -240 */ + {0x06308079, 0x80F20B3B}, /* -121, 1584, 2875, -242 */ + {0x061A8077, 0x80F30B50}, /* -119, 1562, 2896, -243 */ + {0x06068076, 0x80F50B65}, /* -118, 1542, 2917, -245 */ + {0x05F08074, 0x80F60B7A}, /* -116, 1520, 2938, -246 */ + {0x05DB8072, 0x80F80B8F}, /* -114, 1499, 2959, -248 */ + {0x05C58070, 0x80F90BA4}, /* -112, 1477, 2980, -249 */ + {0x05B1806E, 0x80FC0BB9}, /* -110, 1457, 3001, -252 */ + {0x059B806C, 0x80FD0BCE}, /* -108, 1435, 3022, -253 */ + {0x0586806A, 0x80FE0BE2}, /* -106, 1414, 3042, -254 */ + {0x05718068, 0x81000BF7}, /* -104, 1393, 3063, -256 */ + {0x055C8066, 0x81010C0B}, /* -102, 1372, 3083, -257 */ + {0x05478064, 0x81020C1F}, /* -100, 1351, 3103, -258 */ + {0x05328062, 0x81030C33}, /* -98, 1330, 3123, -259 */ + {0x051D8060, 0x81040C47}, /* -96, 1309, 3143, -260 */ + {0x0508805E, 0x81050C5B}, /* -94, 1288, 3163, -261 */ + {0x04F3805C, 0x81060C6F}, /* -92, 1267, 3183, -262 */ + {0x04E0805B, 0x81070C82}, /* -91, 1248, 3202, -263 */ + {0x04CB8059, 0x81080C96}, /* -89, 1227, 3222, -264 */ + {0x04B68057, 0x81080CA9}, /* -87, 1206, 3241, -264 */ + {0x04A28055, 0x81090CBC}, /* -85, 1186, 3260, -265 */ + {0x048E8053, 0x810A0CCF}, /* -83, 1166, 3279, -266 */ + {0x047A8052, 0x810A0CE2}, /* -82, 1146, 3298, -266 */ + {0x04668050, 0x810B0CF5}, /* -80, 1126, 3317, -267 */ + {0x0451804E, 0x810B0D08}, /* -78, 1105, 3336, -267 */ + {0x043E804D, 0x810C0D1B}, /* -77, 1086, 3355, -268 */ + {0x042B804B, 0x810C0D2C}, /* -75, 1067, 3372, -268 */ + {0x04178049, 0x810C0D3E}, /* -73, 1047, 3390, -268 */ + {0x04038048, 0x810C0D51}, /* -72, 1027, 3409, -268 */ + {0x03F08046, 0x810C0D62}, /* -70, 1008, 3426, -268 */ + {0x03DD8044, 0x810C0D73}, /* -68, 989, 3443, -268 */ + {0x03CA8043, 0x810C0D85}, /* -67, 970, 3461, -268 */ + {0x03B78041, 0x810C0D96}, /* -65, 951, 3478, -268 */ + {0x03A48040, 0x810C0DA8}, /* -64, 932, 3496, -268 */ + {0x0391803E, 0x810B0DB8}, /* -62, 913, 3512, -267 */ + {0x0380803D, 0x810C0DC9}, /* -61, 896, 3529, -268 */ + {0x036D803B, 0x810C0DDA}, /* -59, 877, 3546, -268 */ + {0x035B803A, 0x810B0DEA}, /* -58, 859, 3562, -267 */ + {0x03488038, 0x810A0DFA}, /* -56, 840, 3578, -266 */ + {0x03368037, 0x810A0E0B}, /* -55, 822, 3595, -266 */ + {0x03248036, 0x81090E1B}, /* -54, 804, 3611, -265 */ + {0x03128034, 0x81080E2A}, /* -52, 786, 3626, -264 */ + {0x03018033, 0x81070E39}, /* -51, 769, 3641, -263 */ + {0x02EF8032, 0x81060E49}, /* -50, 751, 3657, -262 */ + {0x02DE8030, 0x81040E56}, /* -48, 734, 3670, -260 */ + {0x02CC802F, 0x81030E66}, /* -47, 716, 3686, -259 */ + {0x02BB802E, 0x81020E75}, /* -46, 699, 3701, -258 */ + {0x02AA802D, 0x81000E83}, /* -45, 682, 3715, -256 */ + {0x0299802B, 0x80FE0E90}, /* -43, 665, 3728, -254 */ + {0x0288802A, 0x80FD0E9F}, /* -42, 648, 3743, -253 */ + {0x02778029, 0x80FB0EAD}, /* -41, 631, 3757, -251 */ + {0x02678028, 0x80F90EBA}, /* -40, 615, 3770, -249 */ + {0x02568027, 0x80F70EC8}, /* -39, 598, 3784, -247 */ + {0x02468025, 0x80F50ED4}, /* -37, 582, 3796, -245 */ + {0x02368024, 0x80F30EE1}, /* -36, 566, 3809, -243 */ + {0x02268023, 0x80F00EED}, /* -35, 550, 3821, -240 */ + {0x02188023, 0x80EF0EFA}, /* -35, 536, 3834, -239 */ + {0x02078021, 0x80EB0F05}, /* -33, 519, 3845, -235 */ + {0x01F98021, 0x80E90F11}, /* -33, 505, 3857, -233 */ + {0x01EA8020, 0x80E60F1C}, /* -32, 490, 3868, -230 */ + {0x01DC801F, 0x80E40F27}, /* -31, 476, 3879, -228 */ + {0x01CD801E, 0x80E00F31}, /* -30, 461, 3889, -224 */ + {0x01BE801D, 0x80DD0F3C}, /* -29, 446, 3900, -221 */ + {0x01AF801C, 0x80DA0F47}, /* -28, 431, 3911, -218 */ + {0x01A1801B, 0x80D70F51}, /* -27, 417, 3921, -215 */ + {0x0192801A, 0x80D30F5B}, /* -26, 402, 3931, -211 */ + {0x01848019, 0x80CF0F64}, /* -25, 388, 3940, -207 */ + {0x01768018, 0x80CB0F6D}, /* -24, 374, 3949, -203 */ + {0x01688017, 0x80C80F77}, /* -23, 360, 3959, -200 */ + {0x015A8016, 0x80C30F7F}, /* -22, 346, 3967, -195 */ + {0x014D8015, 0x80BF0F87}, /* -21, 333, 3975, -191 */ + {0x013F8015, 0x80BB0F91}, /* -21, 319, 3985, -187 */ + {0x01328014, 0x80B60F98}, /* -20, 306, 3992, -182 */ + {0x01258013, 0x80B20FA0}, /* -19, 293, 4000, -178 */ + {0x01188012, 0x80AD0FA7}, /* -18, 280, 4007, -173 */ + {0x010B8011, 0x80A80FAE}, /* -17, 267, 4014, -168 */ + {0x00FE8010, 0x80A30FB5}, /* -16, 254, 4021, -163 */ + {0x00F28010, 0x809E0FBC}, /* -16, 242, 4028, -158 */ + {0x00E6800F, 0x80990FC2}, /* -15, 230, 4034, -153 */ + {0x00DA800E, 0x80930FC7}, /* -14, 218, 4039, -147 */ + {0x00CE800D, 0x808E0FCD}, /* -13, 206, 4045, -142 */ + {0x00C2800D, 0x80880FD3}, /* -13, 194, 4051, -136 */ + {0x00B6800C, 0x80820FD8}, /* -12, 182, 4056, -130 */ + {0x00AB800B, 0x807C0FDC}, /* -11, 171, 4060, -124 */ + {0x009F800A, 0x80760FE1}, /* -10, 159, 4065, -118 */ + {0x0094800A, 0x80700FE6}, /* -10, 148, 4070, -112 */ + {0x00898009, 0x80690FE9}, /* -9, 137, 4073, -105 */ + {0x007E8008, 0x80630FED}, /* -8, 126, 4077, -99 */ + {0x00748007, 0x805C0FEF}, /* -7, 116, 4079, -92 */ + {0x00698007, 0x80550FF3}, /* -7, 105, 4083, -85 */ + {0x005F8006, 0x804E0FF5}, /* -6, 95, 4085, -78 */ + {0x00558005, 0x80470FF7}, /* -5, 85, 4087, -71 */ + {0x004B8005, 0x80400FFA}, /* -5, 75, 4090, -64 */ + {0x00418004, 0x80380FFB}, /* -4, 65, 4091, -56 */ + {0x00378003, 0x80310FFD}, /* -3, 55, 4093, -49 */ + {0x002E8003, 0x80290FFE}, /* -3, 46, 4094, -41 */ + {0x00238002, 0x80211000}, /* -2, 35, 4096, -33 */ + {0x001A8001, 0x80191000}, /* -1, 26, 4096, -25 */ + {0x00118001, 0x80101000}, /* -1, 17, 4096, -16 */ + {0x00080000, 0x80081000}, /* 0, 8, 4096, -8 */ +}; + +long CimarronVideoFilter128[][2] = { + {0x10000000, 0x00000000}, /* 0, 4096, 0, 0 */ + {0x10018011, 0x80010011}, /* -17, 4097, 17, -1 */ + {0x10008021, 0x80020023}, /* -33, 4096, 35, -2 */ + {0x0FFE8031, 0x80030036}, /* -49, 4094, 54, -3 */ + {0x0FFB8040, 0x8005004A}, /* -64, 4091, 74, -5 */ + {0x0FF6804E, 0x8006005E}, /* -78, 4086, 94, -6 */ + {0x0FF0805C, 0x80070073}, /* -92, 4080, 115, -7 */ + {0x0FEB806A, 0x80090088}, /* -106, 4075, 136, -9 */ + {0x0FE18076, 0x800A009F}, /* -118, 4065, 159, -10 */ + {0x0FD98082, 0x800C00B5}, /* -130, 4057, 181, -12 */ + {0x0FCE808E, 0x800D00CD}, /* -142, 4046, 205, -13 */ + {0x0FC38099, 0x800F00E5}, /* -153, 4035, 229, -15 */ + {0x0FB680A4, 0x801000FE}, /* -164, 4022, 254, -16 */ + {0x0FA880AD, 0x80120117}, /* -173, 4008, 279, -18 */ + {0x0F9A80B7, 0x80140131}, /* -183, 3994, 305, -20 */ + {0x0F8980C0, 0x8015014C}, /* -192, 3977, 332, -21 */ + {0x0F7880C8, 0x80170167}, /* -200, 3960, 359, -23 */ + {0x0F6680D0, 0x80190183}, /* -208, 3942, 387, -25 */ + {0x0F5280D7, 0x801B01A0}, /* -215, 3922, 416, -27 */ + {0x0F3E80DE, 0x801D01BD}, /* -222, 3902, 445, -29 */ + {0x0F2880E4, 0x801F01DB}, /* -228, 3880, 475, -31 */ + {0x0F1180EA, 0x802101FA}, /* -234, 3857, 506, -33 */ + {0x0EF880EE, 0x80220218}, /* -238, 3832, 536, -34 */ + {0x0EDF80F3, 0x80240238}, /* -243, 3807, 568, -36 */ + {0x0EC680F7, 0x80270258}, /* -247, 3782, 600, -39 */ + {0x0EAB80FB, 0x80290279}, /* -251, 3755, 633, -41 */ + {0x0E9080FF, 0x802B029A}, /* -255, 3728, 666, -43 */ + {0x0E748102, 0x802E02BC}, /* -258, 3700, 700, -46 */ + {0x0E588105, 0x803102DE}, /* -261, 3672, 734, -49 */ + {0x0E388107, 0x80330302}, /* -263, 3640, 770, -51 */ + {0x0E1A8109, 0x80360325}, /* -265, 3610, 805, -54 */ + {0x0DFB810B, 0x80390349}, /* -267, 3579, 841, -57 */ + {0x0DDB810C, 0x803C036D}, /* -268, 3547, 877, -60 */ + {0x0DBA810D, 0x803F0392}, /* -269, 3514, 914, -63 */ + {0x0D98810E, 0x804203B8}, /* -270, 3480, 952, -66 */ + {0x0D74810D, 0x804503DE}, /* -269, 3444, 990, -69 */ + {0x0D50810D, 0x80480405}, /* -269, 3408, 1029, -72 */ + {0x0D2C810C, 0x804B042B}, /* -268, 3372, 1067, -75 */ + {0x0D08810C, 0x804F0453}, /* -268, 3336, 1107, -79 */ + {0x0CE3810B, 0x8052047A}, /* -267, 3299, 1146, -82 */ + {0x0CBD810A, 0x805604A3}, /* -266, 3261, 1187, -86 */ + {0x0C968108, 0x805904CB}, /* -264, 3222, 1227, -89 */ + {0x0C708107, 0x805D04F4}, /* -263, 3184, 1268, -93 */ + {0x0C488105, 0x8061051E}, /* -261, 3144, 1310, -97 */ + {0x0C208103, 0x80640547}, /* -259, 3104, 1351, -100 */ + {0x0BF78100, 0x80680571}, /* -256, 3063, 1393, -104 */ + {0x0BCF80FE, 0x806C059B}, /* -254, 3023, 1435, -108 */ + {0x0BA480FA, 0x807005C6}, /* -250, 2980, 1478, -112 */ + {0x0B7A80F7, 0x807405F1}, /* -247, 2938, 1521, -116 */ + {0x0B4F80F4, 0x8077061C}, /* -244, 2895, 1564, -119 */ + {0x0B2580F1, 0x807C0648}, /* -241, 2853, 1608, -124 */ + {0x0AFA80ED, 0x80800673}, /* -237, 2810, 1651, -128 */ + {0x0ACF80EA, 0x8084069F}, /* -234, 2767, 1695, -132 */ + {0x0AA380E6, 0x808806CB}, /* -230, 2723, 1739, -136 */ + {0x0A7880E2, 0x808D06F7}, /* -226, 2680, 1783, -141 */ + {0x0A4C80DF, 0x80910724}, /* -223, 2636, 1828, -145 */ + {0x0A2080DB, 0x80960751}, /* -219, 2592, 1873, -150 */ + {0x09F480D7, 0x809A077D}, /* -215, 2548, 1917, -154 */ + {0x09C780D2, 0x809F07AA}, /* -210, 2503, 1962, -159 */ + {0x099A80CE, 0x80A307D7}, /* -206, 2458, 2007, -163 */ + {0x096D80CA, 0x80A70804}, /* -202, 2413, 2052, -167 */ + {0x094180C6, 0x80AC0831}, /* -198, 2369, 2097, -172 */ + {0x091380C1, 0x80B0085E}, /* -193, 2323, 2142, -176 */ + {0x08E780BE, 0x80B5088C}, /* -190, 2279, 2188, -181 */ + {0x08B980B9, 0x80B908B9}, /* -185, 2233, 2233, -185 */ + {0x088C80B5, 0x80BE08E7}, /* -181, 2188, 2279, -190 */ + {0x085E80B0, 0x80C10913}, /* -176, 2142, 2323, -193 */ + {0x083180AC, 0x80C60941}, /* -172, 2097, 2369, -198 */ + {0x080480A7, 0x80CA096D}, /* -167, 2052, 2413, -202 */ + {0x07D780A3, 0x80CE099A}, /* -163, 2007, 2458, -206 */ + {0x07AA809F, 0x80D209C7}, /* -159, 1962, 2503, -210 */ + {0x077D809A, 0x80D709F4}, /* -154, 1917, 2548, -215 */ + {0x07518096, 0x80DB0A20}, /* -150, 1873, 2592, -219 */ + {0x07248091, 0x80DF0A4C}, /* -145, 1828, 2636, -223 */ + {0x06F7808D, 0x80E20A78}, /* -141, 1783, 2680, -226 */ + {0x06CA8088, 0x80E60AA4}, /* -136, 1738, 2724, -230 */ + {0x069E8084, 0x80EA0AD0}, /* -132, 1694, 2768, -234 */ + {0x06738080, 0x80ED0AFA}, /* -128, 1651, 2810, -237 */ + {0x0647807C, 0x80F10B26}, /* -124, 1607, 2854, -241 */ + {0x061B8077, 0x80F40B50}, /* -119, 1563, 2896, -244 */ + {0x05F18074, 0x80F70B7A}, /* -116, 1521, 2938, -247 */ + {0x05C68070, 0x80FA0BA4}, /* -112, 1478, 2980, -250 */ + {0x059C806C, 0x80FE0BCE}, /* -108, 1436, 3022, -254 */ + {0x05728068, 0x81000BF6}, /* -104, 1394, 3062, -256 */ + {0x05478064, 0x81030C20}, /* -100, 1351, 3104, -259 */ + {0x051E8061, 0x81050C48}, /* -97, 1310, 3144, -261 */ + {0x04F4805D, 0x81070C70}, /* -93, 1268, 3184, -263 */ + {0x04CB8059, 0x81080C96}, /* -89, 1227, 3222, -264 */ + {0x04A38056, 0x810A0CBD}, /* -86, 1187, 3261, -266 */ + {0x047A8052, 0x810B0CE3}, /* -82, 1146, 3299, -267 */ + {0x0453804F, 0x810C0D08}, /* -79, 1107, 3336, -268 */ + {0x042B804B, 0x810C0D2C}, /* -75, 1067, 3372, -268 */ + {0x04048048, 0x810D0D51}, /* -72, 1028, 3409, -269 */ + {0x03DE8045, 0x810D0D74}, /* -69, 990, 3444, -269 */ + {0x03B88042, 0x810E0D98}, /* -66, 952, 3480, -270 */ + {0x0393803F, 0x810D0DB9}, /* -63, 915, 3513, -269 */ + {0x036E803C, 0x810C0DDA}, /* -60, 878, 3546, -268 */ + {0x03498039, 0x810B0DFB}, /* -57, 841, 3579, -267 */ + {0x03258036, 0x81090E1A}, /* -54, 805, 3610, -265 */ + {0x03018033, 0x81070E39}, /* -51, 769, 3641, -263 */ + {0x02DE8031, 0x81050E58}, /* -49, 734, 3672, -261 */ + {0x02BC802E, 0x81020E74}, /* -46, 700, 3700, -258 */ + {0x0299802B, 0x80FF0E91}, /* -43, 665, 3729, -255 */ + {0x02788029, 0x80FB0EAC}, /* -41, 632, 3756, -251 */ + {0x02578027, 0x80F70EC7}, /* -39, 599, 3783, -247 */ + {0x02378024, 0x80F30EE0}, /* -36, 567, 3808, -243 */ + {0x02178022, 0x80EE0EF9}, /* -34, 535, 3833, -238 */ + {0x01FA8021, 0x80EA0F11}, /* -33, 506, 3857, -234 */ + {0x01DC801F, 0x80E40F27}, /* -31, 476, 3879, -228 */ + {0x01BE801D, 0x80DE0F3D}, /* -29, 446, 3901, -222 */ + {0x01A1801B, 0x80D70F51}, /* -27, 417, 3921, -215 */ + {0x01848019, 0x80D00F65}, /* -25, 388, 3941, -208 */ + {0x01688017, 0x80C80F77}, /* -23, 360, 3959, -200 */ + {0x014D8015, 0x80C00F88}, /* -21, 333, 3976, -192 */ + {0x01328014, 0x80B70F99}, /* -20, 306, 3993, -183 */ + {0x01188012, 0x80AD0FA7}, /* -18, 280, 4007, -173 */ + {0x00FF8010, 0x80A40FB5}, /* -16, 255, 4021, -164 */ + {0x00E6800F, 0x80990FC2}, /* -15, 230, 4034, -153 */ + {0x00CE800D, 0x808E0FCD}, /* -13, 206, 4045, -142 */ + {0x00B6800C, 0x80820FD8}, /* -12, 182, 4056, -130 */ + {0x00A0800A, 0x80760FE0}, /* -10, 160, 4064, -118 */ + {0x00898009, 0x806A0FEA}, /* -9, 137, 4074, -106 */ + {0x00748007, 0x805C0FEF}, /* -7, 116, 4079, -92 */ + {0x005F8006, 0x804E0FF5}, /* -6, 95, 4085, -78 */ + {0x004B8005, 0x80400FFA}, /* -5, 75, 4090, -64 */ + {0x00378003, 0x80310FFD}, /* -3, 55, 4093, -49 */ + {0x00238002, 0x80211000}, /* -2, 35, 4096, -33 */ + {0x00118001, 0x80111001}, /* -1, 17, 4097, -17 */ + {0x10000000, 0x00000000}, /* 0, 4096, 0, 0 */ + {0x10018011, 0x80010011}, /* -17, 4097, 17, -1 */ + {0x10008021, 0x80020023}, /* -33, 4096, 35, -2 */ + {0x0FFE8031, 0x80030036}, /* -49, 4094, 54, -3 */ + {0x0FFB8040, 0x8005004A}, /* -64, 4091, 74, -5 */ + {0x0FF6804E, 0x8006005E}, /* -78, 4086, 94, -6 */ + {0x0FF0805C, 0x80070073}, /* -92, 4080, 115, -7 */ + {0x0FEB806A, 0x80090088}, /* -106, 4075, 136, -9 */ + {0x0FE18076, 0x800A009F}, /* -118, 4065, 159, -10 */ + {0x0FD98082, 0x800C00B5}, /* -130, 4057, 181, -12 */ + {0x0FCE808E, 0x800D00CD}, /* -142, 4046, 205, -13 */ + {0x0FC38099, 0x800F00E5}, /* -153, 4035, 229, -15 */ + {0x0FB680A4, 0x801000FE}, /* -164, 4022, 254, -16 */ + {0x0FA880AD, 0x80120117}, /* -173, 4008, 279, -18 */ + {0x0F9A80B7, 0x80140131}, /* -183, 3994, 305, -20 */ + {0x0F8980C0, 0x8015014C}, /* -192, 3977, 332, -21 */ + {0x0F7880C8, 0x80170167}, /* -200, 3960, 359, -23 */ + {0x0F6680D0, 0x80190183}, /* -208, 3942, 387, -25 */ + {0x0F5280D7, 0x801B01A0}, /* -215, 3922, 416, -27 */ + {0x0F3E80DE, 0x801D01BD}, /* -222, 3902, 445, -29 */ + {0x0F2880E4, 0x801F01DB}, /* -228, 3880, 475, -31 */ + {0x0F1180EA, 0x802101FA}, /* -234, 3857, 506, -33 */ + {0x0EF880EE, 0x80220218}, /* -238, 3832, 536, -34 */ + {0x0EDF80F3, 0x80240238}, /* -243, 3807, 568, -36 */ + {0x0EC680F7, 0x80270258}, /* -247, 3782, 600, -39 */ + {0x0EAB80FB, 0x80290279}, /* -251, 3755, 633, -41 */ + {0x0E9080FF, 0x802B029A}, /* -255, 3728, 666, -43 */ + {0x0E748102, 0x802E02BC}, /* -258, 3700, 700, -46 */ + {0x0E588105, 0x803102DE}, /* -261, 3672, 734, -49 */ + {0x0E388107, 0x80330302}, /* -263, 3640, 770, -51 */ + {0x0E1A8109, 0x80360325}, /* -265, 3610, 805, -54 */ + {0x0DFB810B, 0x80390349}, /* -267, 3579, 841, -57 */ + {0x0DDB810C, 0x803C036D}, /* -268, 3547, 877, -60 */ + {0x0DBA810D, 0x803F0392}, /* -269, 3514, 914, -63 */ + {0x0D98810E, 0x804203B8}, /* -270, 3480, 952, -66 */ + {0x0D74810D, 0x804503DE}, /* -269, 3444, 990, -69 */ + {0x0D50810D, 0x80480405}, /* -269, 3408, 1029, -72 */ + {0x0D2C810C, 0x804B042B}, /* -268, 3372, 1067, -75 */ + {0x0D08810C, 0x804F0453}, /* -268, 3336, 1107, -79 */ + {0x0CE3810B, 0x8052047A}, /* -267, 3299, 1146, -82 */ + {0x0CBD810A, 0x805604A3}, /* -266, 3261, 1187, -86 */ + {0x0C968108, 0x805904CB}, /* -264, 3222, 1227, -89 */ + {0x0C708107, 0x805D04F4}, /* -263, 3184, 1268, -93 */ + {0x0C488105, 0x8061051E}, /* -261, 3144, 1310, -97 */ + {0x0C208103, 0x80640547}, /* -259, 3104, 1351, -100 */ + {0x0BF78100, 0x80680571}, /* -256, 3063, 1393, -104 */ + {0x0BCF80FE, 0x806C059B}, /* -254, 3023, 1435, -108 */ + {0x0BA480FA, 0x807005C6}, /* -250, 2980, 1478, -112 */ + {0x0B7A80F7, 0x807405F1}, /* -247, 2938, 1521, -116 */ + {0x0B4F80F4, 0x8077061C}, /* -244, 2895, 1564, -119 */ + {0x0B2580F1, 0x807C0648}, /* -241, 2853, 1608, -124 */ + {0x0AFA80ED, 0x80800673}, /* -237, 2810, 1651, -128 */ + {0x0ACF80EA, 0x8084069F}, /* -234, 2767, 1695, -132 */ + {0x0AA380E6, 0x808806CB}, /* -230, 2723, 1739, -136 */ + {0x0A7880E2, 0x808D06F7}, /* -226, 2680, 1783, -141 */ + {0x0A4C80DF, 0x80910724}, /* -223, 2636, 1828, -145 */ + {0x0A2080DB, 0x80960751}, /* -219, 2592, 1873, -150 */ + {0x09F480D7, 0x809A077D}, /* -215, 2548, 1917, -154 */ + {0x09C780D2, 0x809F07AA}, /* -210, 2503, 1962, -159 */ + {0x099A80CE, 0x80A307D7}, /* -206, 2458, 2007, -163 */ + {0x096D80CA, 0x80A70804}, /* -202, 2413, 2052, -167 */ + {0x094180C6, 0x80AC0831}, /* -198, 2369, 2097, -172 */ + {0x091380C1, 0x80B0085E}, /* -193, 2323, 2142, -176 */ + {0x08E780BE, 0x80B5088C}, /* -190, 2279, 2188, -181 */ + {0x08B980B9, 0x80B908B9}, /* -185, 2233, 2233, -185 */ + {0x088C80B5, 0x80BE08E7}, /* -181, 2188, 2279, -190 */ + {0x085E80B0, 0x80C10913}, /* -176, 2142, 2323, -193 */ + {0x083180AC, 0x80C60941}, /* -172, 2097, 2369, -198 */ + {0x080480A7, 0x80CA096D}, /* -167, 2052, 2413, -202 */ + {0x07D780A3, 0x80CE099A}, /* -163, 2007, 2458, -206 */ + {0x07AA809F, 0x80D209C7}, /* -159, 1962, 2503, -210 */ + {0x077D809A, 0x80D709F4}, /* -154, 1917, 2548, -215 */ + {0x07518096, 0x80DB0A20}, /* -150, 1873, 2592, -219 */ + {0x07248091, 0x80DF0A4C}, /* -145, 1828, 2636, -223 */ + {0x06F7808D, 0x80E20A78}, /* -141, 1783, 2680, -226 */ + {0x06CA8088, 0x80E60AA4}, /* -136, 1738, 2724, -230 */ + {0x069E8084, 0x80EA0AD0}, /* -132, 1694, 2768, -234 */ + {0x06738080, 0x80ED0AFA}, /* -128, 1651, 2810, -237 */ + {0x0647807C, 0x80F10B26}, /* -124, 1607, 2854, -241 */ + {0x061B8077, 0x80F40B50}, /* -119, 1563, 2896, -244 */ + {0x05F18074, 0x80F70B7A}, /* -116, 1521, 2938, -247 */ + {0x05C68070, 0x80FA0BA4}, /* -112, 1478, 2980, -250 */ + {0x059C806C, 0x80FE0BCE}, /* -108, 1436, 3022, -254 */ + {0x05728068, 0x81000BF6}, /* -104, 1394, 3062, -256 */ + {0x05478064, 0x81030C20}, /* -100, 1351, 3104, -259 */ + {0x051E8061, 0x81050C48}, /* -97, 1310, 3144, -261 */ + {0x04F4805D, 0x81070C70}, /* -93, 1268, 3184, -263 */ + {0x04CB8059, 0x81080C96}, /* -89, 1227, 3222, -264 */ + {0x04A38056, 0x810A0CBD}, /* -86, 1187, 3261, -266 */ + {0x047A8052, 0x810B0CE3}, /* -82, 1146, 3299, -267 */ + {0x0453804F, 0x810C0D08}, /* -79, 1107, 3336, -268 */ + {0x042B804B, 0x810C0D2C}, /* -75, 1067, 3372, -268 */ + {0x04048048, 0x810D0D51}, /* -72, 1028, 3409, -269 */ + {0x03DE8045, 0x810D0D74}, /* -69, 990, 3444, -269 */ + {0x03B88042, 0x810E0D98}, /* -66, 952, 3480, -270 */ + {0x0393803F, 0x810D0DB9}, /* -63, 915, 3513, -269 */ + {0x036E803C, 0x810C0DDA}, /* -60, 878, 3546, -268 */ + {0x03498039, 0x810B0DFB}, /* -57, 841, 3579, -267 */ + {0x03258036, 0x81090E1A}, /* -54, 805, 3610, -265 */ + {0x03018033, 0x81070E39}, /* -51, 769, 3641, -263 */ + {0x02DE8031, 0x81050E58}, /* -49, 734, 3672, -261 */ + {0x02BC802E, 0x81020E74}, /* -46, 700, 3700, -258 */ + {0x0299802B, 0x80FF0E91}, /* -43, 665, 3729, -255 */ + {0x02788029, 0x80FB0EAC}, /* -41, 632, 3756, -251 */ + {0x02578027, 0x80F70EC7}, /* -39, 599, 3783, -247 */ + {0x02378024, 0x80F30EE0}, /* -36, 567, 3808, -243 */ + {0x02178022, 0x80EE0EF9}, /* -34, 535, 3833, -238 */ + {0x01FA8021, 0x80EA0F11}, /* -33, 506, 3857, -234 */ + {0x01DC801F, 0x80E40F27}, /* -31, 476, 3879, -228 */ + {0x01BE801D, 0x80DE0F3D}, /* -29, 446, 3901, -222 */ + {0x01A1801B, 0x80D70F51}, /* -27, 417, 3921, -215 */ + {0x01848019, 0x80D00F65}, /* -25, 388, 3941, -208 */ + {0x01688017, 0x80C80F77}, /* -23, 360, 3959, -200 */ + {0x014D8015, 0x80C00F88}, /* -21, 333, 3976, -192 */ + {0x01328014, 0x80B70F99}, /* -20, 306, 3993, -183 */ + {0x01188012, 0x80AD0FA7}, /* -18, 280, 4007, -173 */ + {0x00FF8010, 0x80A40FB5}, /* -16, 255, 4021, -164 */ + {0x00E6800F, 0x80990FC2}, /* -15, 230, 4034, -153 */ + {0x00CE800D, 0x808E0FCD}, /* -13, 206, 4045, -142 */ + {0x00B6800C, 0x80820FD8}, /* -12, 182, 4056, -130 */ + {0x00A0800A, 0x80760FE0}, /* -10, 160, 4064, -118 */ + {0x00898009, 0x806A0FEA}, /* -9, 137, 4074, -106 */ + {0x00748007, 0x805C0FEF}, /* -7, 116, 4079, -92 */ + {0x005F8006, 0x804E0FF5}, /* -6, 95, 4085, -78 */ + {0x004B8005, 0x80400FFA}, /* -5, 75, 4090, -64 */ + {0x00378003, 0x80310FFD}, /* -3, 55, 4093, -49 */ + {0x00238002, 0x80211000}, /* -2, 35, 4096, -33 */ + {0x00118001, 0x80111001}, /* -1, 17, 4097, -17 */ +}; diff --git a/src/cim/cim_gp.c b/src/cim/cim_gp.c new file mode 100644 index 0000000..fc105c9 --- /dev/null +++ b/src/cim/cim_gp.c @@ -0,0 +1,3392 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron graphics processor routines. These routines program the graphics + * hardware using the graphics command buffer. + */ + +/*---------------------*/ +/* CIMARRON GP GLOBALS */ +/*---------------------*/ + +CIMARRON_STATIC unsigned long gp3_bpp = 0; +CIMARRON_STATIC unsigned long gp3_ch3_bpp = 0; +CIMARRON_STATIC unsigned long gp3_pat_origin = 0; +CIMARRON_STATIC unsigned long gp3_buffer_lead = 0; +CIMARRON_STATIC unsigned long gp3_cmd_header; +CIMARRON_STATIC unsigned long gp3_cmd_top; +CIMARRON_STATIC unsigned long gp3_cmd_bottom; +CIMARRON_STATIC unsigned long gp3_cmd_current; +CIMARRON_STATIC unsigned long gp3_cmd_next; +CIMARRON_STATIC unsigned long gp3_blt_mode; +CIMARRON_STATIC unsigned long gp3_vec_mode; +CIMARRON_STATIC unsigned long gp3_raster_mode; +CIMARRON_STATIC unsigned long gp3_pix_shift; +CIMARRON_STATIC unsigned long gp3_ch3_pat; +CIMARRON_STATIC unsigned long gp3_blt; +CIMARRON_STATIC unsigned long gp3_blt_flags; +CIMARRON_STATIC unsigned long gp3_src_stride; +CIMARRON_STATIC unsigned long gp3_dst_stride; +CIMARRON_STATIC unsigned long gp3_src_format; +CIMARRON_STATIC unsigned long gp3_src_pix_shift; +CIMARRON_STATIC unsigned long gp3_pat_format; +CIMARRON_STATIC unsigned long gp3_pat_pix_shift; +CIMARRON_STATIC unsigned long gp3_fb_base; +CIMARRON_STATIC unsigned long gp3_vector_pattern_color; +CIMARRON_STATIC unsigned long gp3_scratch_base; +CIMARRON_STATIC unsigned long gp3_base_register; +CIMARRON_STATIC unsigned long gp3_vec_pat; + +/*--------------------------------------------------------------------------- + * gp_set_limit_on_buffer_lead + * + * This routine is used to specify the maximum number of bytes in the command + * buffer by which software can lead the graphics processor. When declaring + * a BLT with the CIMGP_BLTFLAGS_LIMITBUFFER flag set, Cimarron will wait + * until the command buffer read and write pointers differ by no more than + * 'lead' bytes. This can be useful to limit the time lag possible when + * creating a command buffer full of simple BLT commands. + *-------------------------------------------------------------------------*/ + +void +gp_set_limit_on_buffer_lead(unsigned long lead) +{ + gp3_buffer_lead = lead; +} + +/*--------------------------------------------------------------------------- + * gp_set_command_buffer_base + * + * This routine is used to program the command buffer region in physical + * memory. The command buffer start address must be 1MB aligned. start and + * stop refer to endpoints within the associated 16MB region. Command buffers + * larger than 16MB are not supported. + *-------------------------------------------------------------------------*/ + +void +gp_set_command_buffer_base(unsigned long address, unsigned long start, + unsigned long stop) +{ + Q_WORD msr_value; + + /* WAIT FOR IDLE */ + /* Obviously, we cannot change the command buffer pointer while the GP */ + /* is currently fetching commands. */ + + gp_wait_until_idle(); + + /* WRITE THE COMMAND BUFFER BASE */ + + msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value); + msr_value.low &= 0xF000FFFF; + msr_value.low |= (address >> 4) & 0x0FFF0000; + msr_write64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value); + + /* WRITE THE BASE OFFSETS */ + /* We also reset the write and read pointers. The hardware will */ + /* automatically update the write pointer when the read pointer */ + /* is updated to prevent the hardware from getting confused when */ + /* initializing a new command buffer. */ + + WRITE_GP32(GP3_CMD_TOP, start); + WRITE_GP32(GP3_CMD_BOT, stop); + WRITE_GP32(GP3_CMD_READ, start); + + /* SAVE THE BASE ADDRESSES */ + /* These are used to determine the appropriate wrap point. */ + + gp3_cmd_current = gp3_cmd_top = start; + gp3_cmd_bottom = stop; +} + +/*--------------------------------------------------------------------------- + * gp_set_frame_buffer_base + * + * This routine is used to program the base address of the frame buffer in + * physical memory. The frame buffer address must be 16MB aligned. Cimarron + * tracks the base address because the maximum frame buffer size may exceed + * 16MB. Any primitive will thus program the corresponding 16MB region into + * all base offset registers as well as program the offset into the 16MB + * region. The size parameter is provided to allow Cimarron to claim the + * last 1MB of space to be used as a scratch area for workarounds or + * expanded functionality. + *-------------------------------------------------------------------------*/ + +void +gp_set_frame_buffer_base(unsigned long address, unsigned long size) +{ + gp3_scratch_base = size - GP3_SCRATCH_BUFFER_SIZE; + gp3_fb_base = address >> 24; + gp3_base_register = + (gp3_fb_base << 24) | (gp3_fb_base << 14) | (gp3_fb_base << 4); + WRITE_GP32(GP3_BASE_OFFSET, gp3_base_register); +} + +/*--------------------------------------------------------------------------- + * gp_set_bpp + * + * This routine sets the output BPP of the GP. The BPP used by the GP does + * not have to match the display BPP, but that is usually the case. The + * supported BPP values are as follows: + * + * 8 - palettized 8BPP + * 12 - 4:4:4:4 + * 15 - 1:5:5:5 + * 16 - 0:5:6:5 + * 32 - 8:8:8:8 + *-------------------------------------------------------------------------*/ + +void +gp_set_bpp(int bpp) +{ + /* STORE BPP */ + /* The bpp is not updated until the next call to gp_set_raster_mode. */ + /* This allows the gp_set_bpp call to happen outside of a BLT. It */ + /* also implies that no registers need be written in this routine. */ + + switch (bpp) { + case 8: + gp3_bpp = GP3_RM_BPPFMT_332; + gp3_ch3_bpp = GP3_CH3_SRC_3_3_2; + gp3_pix_shift = 0; + break; + case 12: + gp3_bpp = GP3_RM_BPPFMT_4444; + gp3_ch3_bpp = GP3_CH3_SRC_4_4_4_4; + gp3_pix_shift = 1; + break; + case 15: + gp3_bpp = GP3_RM_BPPFMT_1555; + gp3_ch3_bpp = GP3_CH3_SRC_1_5_5_5; + gp3_pix_shift = 1; + break; + case 16: + gp3_bpp = GP3_RM_BPPFMT_565; + gp3_ch3_bpp = GP3_CH3_SRC_0_5_6_5; + gp3_pix_shift = 1; + break; + case 24: + case 32: + gp3_bpp = GP3_RM_BPPFMT_8888; + gp3_ch3_bpp = GP3_CH3_SRC_8_8_8_8; + gp3_pix_shift = 2; + break; + default: + gp3_bpp = GP3_RM_BPPFMT_332; + gp3_ch3_bpp = GP3_CH3_SRC_3_3_2; + gp3_pix_shift = 0; + break; + } +} + +/*--------------------------------------------------------------------------- + * gp_declare_blt + * + * This routine is used to prepare for a 2D BLT. Its primary function + * is to verify that enough room is available in the command buffer + * to hold a BLT command. This command can be called multiple times if + * necessary. For example, if a function calls this routine on entry, but + * later realizes that a LUT load command must be executed before the BLT, + * the application could call gp_set_color_pattern and then call + * gp_declare_blt to declare the BLT. This is possible because the hardware + * buffer pointer is not updated until a new BLT is actually executed. An + * application must take care not to call any routines that perform a buffer + * command, (such as gp_set_color_pattern) between gp_declare_blt and the + * routines used to program the BLT parameters. In addition to checking for + * available space, this routine also performs the following actions: + * - Sets the wrap bit if this BLT will pass close to the end of the + * buffer. + * - Writes the command header. + * + * The available flags are defined as follows: + * 0x01 - Preserve the LUT + * 0x02 - Preserve the color pattern. + * 0x04 - Enable prefetch. + *-------------------------------------------------------------------------*/ + +void +gp_declare_blt(unsigned long flags) +{ + unsigned long temp; + + gp3_blt = 1; + gp3_blt_flags = flags; + + /* SET ADDRESS OF NEXT COMMAND */ + /* A summary of the command buffer logic is as follows: */ + /* - If after a basic BLT we will not have room for the largest */ + /* command (a full line of host source data), we set the wrap */ + /* bit. This will waste up to a whopping 8K of command buffer */ + /* space, but it simplifies the logic for all commands. */ + /* - If we are wrapping, we have extra logic to ensure that we */ + /* don't skip over the current GP read pointer. */ + + gp3_cmd_next = gp3_cmd_current + GP3_BLT_COMMAND_SIZE; + + /* CHECK WRAP CONDITION */ + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + gp3_cmd_header = GP3_BLT_HDR_TYPE | GP3_BLT_HDR_WRAP; + + /* WAIT FOR HARDWARE */ + /* When wrapping, we must take steps to ensure that we do not */ + /* wrap over the current hardware read pointer. We do this by */ + /* verifying that the hardware is not between us and the end of */ + /* the command buffer. We also have a special case to make sure */ + /* that the hardware is not currently reading the top of the */ + /* command buffer. */ + + GP3_WAIT_WRAP(temp); + } else { + gp3_cmd_header = GP3_BLT_HDR_TYPE; + + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + } + + if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) { + while (1) { + temp = READ_GP32(GP3_CMD_READ); + if (((gp3_cmd_current >= temp) + && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) + || ((gp3_cmd_current < temp) + && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= + gp3_buffer_lead))) { + break; + } + } + } + + /* SET THE CURRENT BUFFER POINTER */ + /* We initialize a pointer to the current buffer base to avoid an */ + /* extra addition for every buffer write. */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* SET THE HAZARD BIT */ + + if (flags & CIMGP_BLTFLAGS_HAZARD) + gp3_cmd_header |= GP3_BLT_HDR_HAZARD_ENABLE; +} + +/*--------------------------------------------------------------------------- + * gp_declare_vector + * + * This routine is used to prepare for a 2D vector. It has no other function + * except to verify that enough room is available in the command buffer + * to hold a vector command. The same rules that apply to BLTs apply to + * vectors. (See the documentation for gp_declare_blt). + *-------------------------------------------------------------------------*/ + +void +gp_declare_vector(unsigned long flags) +{ + unsigned long temp; + + gp3_blt = 0; + gp3_blt_flags = flags; + + /* SET ADDRESS OF NEXT COMMAND */ + /* The logic to force a wrap during a vector is identical */ + /* to the BLT logic. */ + + /* ALLOCATE SPACE FOR AN ADDITIONAL VECTOR TO CLEAR THE BYTE ENABLES */ + + gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_COMMAND_SIZE + + GP3_VECTOR_COMMAND_SIZE + 32; + + /* CHECK WRAP CONDITION */ + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + gp3_cmd_header = GP3_VEC_HDR_TYPE | GP3_VEC_HDR_WRAP; + + /* CHECK WRAP CONDITION */ + + GP3_WAIT_WRAP(temp); + } else { + gp3_cmd_header = GP3_VEC_HDR_TYPE; + + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + + gp3_cmd_next -= GP3_VECTOR_COMMAND_SIZE + 32; + } + + if (flags & CIMGP_BLTFLAGS_LIMITBUFFER) { + while (1) { + temp = READ_GP32(GP3_CMD_READ); + if (((gp3_cmd_current >= temp) + && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) + || ((gp3_cmd_current < temp) + && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= + gp3_buffer_lead))) { + break; + } + } + } + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* SET THE HAZARD BIT */ + + if (flags & CIMGP_BLTFLAGS_HAZARD) + gp3_cmd_header |= GP3_VEC_HDR_HAZARD_ENABLE; +} + +/*--------------------------------------------------------------------------- + * gp_write_parameters + * + * This routine is called to write all recent parameters to the hardware. + * This routine is necessary for any implementation that performs the setup + * for a BLT separate from the actual BLT. An example would be a driver + * that prepares for multiple pattern fills by programming the ROP, + * pattern color and destination stride. The driver might then perform + * repeated pattern fills with minimal effort. + *-------------------------------------------------------------------------*/ + +void +gp_write_parameters(void) +{ + /* WRITE THE COMMAND HEADER */ + /* Command header is at offset 0 for BLTs and vectors */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + + /* INCREMENT THE CURRENT WRITE POINTER */ + + gp3_cmd_current = gp3_cmd_next; + + /* UPDATE THE GP WRITE POINTER */ + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_current); +} + +/*--------------------------------------------------------------------------- + * gp_set_raster_operation + * + * This is generally the first routine called when programming a BLT. This + * routine performs the following functions: + * - Sets the initial value of the GP3_RASTER_MODE register in the buffer. + * - Clears any 8x8 pattern if the ROP does not involve pattern data. + *-------------------------------------------------------------------------*/ + +void +gp_set_raster_operation(unsigned char ROP) +{ + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; + + /* WRITE THE RASTER MODE REGISTER */ + /* This register is in the same location in BLT and vector commands */ + + gp3_raster_mode = gp3_bpp | (unsigned long)ROP; + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); + + /* CHECK IF DESTINATION IS REQUIRED */ + + if ((ROP & 0x55) ^ ((ROP >> 1) & 0x55)) { + gp3_blt_mode = GP3_BM_DST_REQ; + gp3_vec_mode = GP3_VM_DST_REQ; + } else { + gp3_blt_mode = gp3_vec_mode = 0; + } +} + +/*---------------------------------------------------------------------------- + * gp_set_alpha_operation + * + * BLTs are generally one of two types, a ROPed BLT or a BLT composited using + * alpha blending. For the latter, this routine is used to configure the + * mathematical function used to create the blended output. This routine + * should generally be called first when programming a BLT. The available + * parameters mirror the hardware and are described as follows: + * + * alpha_operation = + * 0 - alpha * A + * 1 - (1 - alpha) * B + * 2 - A + (1 - alpha)*B + * 3 - alpha*A + (1 - alpha)*B + * + * alpha_type = + * 0 - alpha component of channel A + * 1 - alpha component of channel B + * 2 - Constant alpha + * 3 - Constant 1 + * 4 - The color components of channel A + * 5 - The color components of channel B + * 6 - Alpha comes from the alpha channel of the source before the source + * undergoes color conversion. + * + * channel = + * 0 - Channel A = source, channel B = destination + * 1 - Channel B = source, channel A = destination + * + * apply_alpha = + * 1 - Apply alpha blend to only the RGB portion of the pixel. This must be + * set when the source or destination format do not include an alpha + * channel. + * 2 - Apply alpha blend only to the alpha portion of the pixel. This + * implies that both destination and source include an alpha channel. + * 3 - Apply alpha blend to both the RGB and alpha portions of the pixel. + * + * Alpha-blended vectors are not currently supported. + *-------------------------------------------------------------------------*/ + +void +gp_set_alpha_operation(int alpha_operation, int alpha_type, int channel, + int apply_alpha, unsigned char alpha) +{ + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; + + /* THE AVAILABLE ALPHA DEFINITIONS FOLLOW THE HARDWARE */ + /* This allows us to avoid giant switch structures, but it */ + /* also implies that there is no mechanism to detect invalid */ + /* parameters. */ + + gp3_raster_mode = gp3_bpp | (unsigned long)alpha | + ((unsigned long)apply_alpha << 22) | + ((unsigned long)alpha_operation << 20) | + ((unsigned long)alpha_type << 17) | ((unsigned long)channel << 16); + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); + + /* CHECK IF DESTINATION IS REQUIRED */ + + if ((alpha_operation == CIMGP_ALPHA_TIMES_A && + channel == CIMGP_CHANNEL_A_SOURCE && + alpha_type != CIMGP_CHANNEL_B_ALPHA && + alpha_type != CIMGP_ALPHA_FROM_RGB_B) || + (alpha_operation == CIMGP_BETA_TIMES_B && + channel == CIMGP_CHANNEL_A_DEST && + alpha_type != CIMGP_CHANNEL_A_ALPHA && + alpha_type != CIMGP_ALPHA_FROM_RGB_A)) { + gp3_blt_mode = 0; + } else + gp3_blt_mode = GP3_BM_DST_REQ; +} + +/*--------------------------------------------------------------------------- + * gp_set_solid_pattern + * + * This routine is called to program the hardware for a solid pattern. It + * need not be called for any other reason. As a side effect, this routine + * will clear any 8x8 pattern data. + *-------------------------------------------------------------------------*/ + +void +gp_set_solid_pattern(unsigned long color) +{ + /* CHANNEL 3 IS NOT NEEDED FOR SOLID PATTERNS */ + + gp3_ch3_pat = 0; + + /* SET SOLID PATTERN IN COMMAND BUFFER */ + /* We are assuming that only one pattern type is ever set for a */ + /* BLT. We are also assuming that gp_set_raster_operation will */ + /* be called before this routine. With these assumptions, we */ + /* will thus never have to change the raster mode register for */ + /* solid patterns. */ + + if (gp3_blt) { + gp3_cmd_header |= GP3_BLT_HDR_PAT_CLR0_ENABLE; + + WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, color); + } else { + gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE; + + WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, color); + } +} + +/*--------------------------------------------------------------------------- + * gp_set_mono_pattern + * + * This routine is called to program the hardware for a monochrome pattern. + * As a side effect, this routine will clear any 8x8 pattern data. + *-------------------------------------------------------------------------*/ + +void +gp_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, int transparent, int x, int y) +{ + /* CHANNEL 3 IS NOT NEEDED FOR MONOCHROME PATTERNS */ + + gp3_ch3_pat = 0; + + /* UPDATE RASTER MODE REGISTER */ + + if (transparent) + gp3_raster_mode |= GP3_RM_PAT_MONO | GP3_RM_PAT_TRANS; + else + gp3_raster_mode |= GP3_RM_PAT_MONO; + + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); + + /* SET MONOCHROME PATTERN DATA AND COLORS */ + + if (gp3_blt) { + gp3_cmd_header |= + (GP3_BLT_HDR_PAT_CLR0_ENABLE | GP3_BLT_HDR_PAT_CLR1_ENABLE | + GP3_BLT_HDR_PAT_DATA0_ENABLE | GP3_BLT_HDR_PAT_DATA1_ENABLE); + + WRITE_COMMAND32(GP3_BLT_PAT_COLOR_0, bgcolor); + WRITE_COMMAND32(GP3_BLT_PAT_COLOR_1, fgcolor); + WRITE_COMMAND32(GP3_BLT_PAT_DATA_0, data0); + WRITE_COMMAND32(GP3_BLT_PAT_DATA_1, data1); + } else { + gp3_cmd_header |= + (GP3_VEC_HDR_PAT_CLR0_ENABLE | GP3_VEC_HDR_PAT_CLR1_ENABLE | + GP3_VEC_HDR_PAT_DATA0_ENABLE | GP3_VEC_HDR_PAT_DATA1_ENABLE); + + WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, bgcolor); + WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_1, fgcolor); + WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_0, data0); + WRITE_COMMAND32(GP3_VECTOR_PAT_DATA_1, data1); + } + + /* SAVE PATTERN ORIGIN */ + + gp3_pat_origin = ((unsigned long)y << 29) | + (((unsigned long)x & 7) << 26); +} + +/*--------------------------------------------------------------------------- + * gp_set_pattern_origin + * + * This routine overrides the pattern origins set in gp_set_mono_pattern or + * gp_set_color_pattern. It is generally used to override the original + * pattern origin due to a change in clipping. + *-------------------------------------------------------------------------*/ + +void +gp_set_pattern_origin(int x, int y) +{ + /* SAVE PATTERN ORIGIN */ + + gp3_pat_origin = ((unsigned long)y << 29) | + (((unsigned long)x & 7) << 26); +} + +/*--------------------------------------------------------------------------- + * gp_set_color_pattern + * + * This routine is called to program a 8x8 color pattern into the LUT + * hardware. Unlike the other pattern routines, this routine must be called + * before any gp_declare_xxxx routines. The pattern that is programmed into + * the hardware will stay persistent for all subsequent primitives until one + * of the following conditions happens. + * - Another pattern type is programmed. + * - A color-conversion BLT rotation BLT. + *-------------------------------------------------------------------------*/ + +void +gp_set_color_pattern(unsigned long *pattern, int format, int x, int y) +{ + unsigned long size_dwords, temp; + + gp3_ch3_pat = 1; + + /* SAVE COLOR PATTERN SOURCE INFO + * Color patterns can be in a format different than the primary display. + * 4BPP patterns are not supported. + */ + + gp3_pat_pix_shift = (unsigned long)((format >> 2) & 3); + gp3_pat_format = (((unsigned long)format & 0xF) << 24) | + (((unsigned long)format & 0x10) << 17) | + GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_C3EN; + + size_dwords = (64 << gp3_pat_pix_shift) >> 2; + + /* CHECK FOR WRAP AFTER LUT LOAD */ + /* Primitive size is 12 plus the amount of data. */ + + gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | + GP3_LUT_HDR_DATA_ENABLE; + + /* WAIT FOR HARDWARE */ + /* Same logic as BLT wrapping. */ + + GP3_WAIT_WRAP(temp); + } else { + gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE; + + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + } + + /* SAVE CURRENT BUFFER POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* PREPARE FOR COMMAND BUFFER DATA WRITES */ + /* Pattern data is contiguous DWORDs at LUT address 0x100 */ + + WRITE_COMMAND32(0, gp3_cmd_header); + WRITE_COMMAND32(4, 0x100); + WRITE_COMMAND32(8, size_dwords | GP3_LUT_DATA_TYPE); + + /* WRITE ALL DATA */ + + WRITE_COMMAND_STRING32(12, pattern, 0, size_dwords); + + /* START OPERATION */ + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* SAVE PATTERN ORIGIN */ + + gp3_pat_origin = ((unsigned long)y << 29) | + (((unsigned long)x & 7) << 26); +} + +/*--------------------------------------------------------------------------- + * gp_set_mono_source + * + * This routine is called to program the colors for monochrome source data. + *-------------------------------------------------------------------------*/ + +void +gp_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + int transparent) +{ + /* UPDATE RASTER MODE REGISTER IF TRANSPARENT */ + + if (transparent) { + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE; + gp3_raster_mode |= GP3_RM_SRC_TRANS; + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); + } + + /* SET MONOCHROME SOURCE COLORS */ + /* Note that this routine only sets the colors. The actual */ + /* source type is determined by the final output routine */ + /* (gp_mono_bitmap_xxx, gp_color_bitmap_xxx, etc.) */ + + gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE | GP3_BLT_HDR_SRC_BG_ENABLE; + + WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, fgcolor); + WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, bgcolor); +} + +/*--------------------------------------------------------------------------- + * gp_set_solid_source + * + * This routine is called to program a solid source color. A solid source + * color is used primarily for vectors or antialiased text. + *-------------------------------------------------------------------------*/ + +void +gp_set_solid_source(unsigned long color) +{ + /* SET SOLID SOURCE COLOR */ + /* The solid source register is in the same place for both BLTs and */ + /* vectors. */ + + gp3_cmd_header |= GP3_BLT_HDR_SRC_FG_ENABLE; + + WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color); +} + +/*--------------------------------------------------------------------------- + * gp_set_source_transparency + * + * This routine sets the source transparency and mask to be used in future + * rendering operations. Transparency is cleared by gp_set_raster_operation, + * so this routine should never be called first. + *-------------------------------------------------------------------------*/ + +void +gp_set_source_transparency(unsigned long color, unsigned long mask) +{ + gp3_raster_mode |= GP3_RM_SRC_TRANS; + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_SRC_FG_ENABLE | + GP3_BLT_HDR_SRC_BG_ENABLE; + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_raster_mode); + WRITE_COMMAND32(GP3_BLT_SRC_COLOR_FG, color); + WRITE_COMMAND32(GP3_BLT_SRC_COLOR_BG, mask); +} + +/*--------------------------------------------------------------------------- + * gp_program_lut + * + * This routine is called to program the hardware LUT with color-conversion + * information. This routine should be called before any gp_declare_xxxx + * routines. + * + * colors - Pointer to an array of DWORDs for color expansion. + * + * full_lut - Selector between 4BPP and 8BPP expansion. The hardware is + * initialized with 16 dwords for 4BPP expansion and 256 dwords + * for 8BPP expansion. + *-------------------------------------------------------------------------*/ + +void +gp_program_lut(unsigned long *colors, int full_lut) +{ + unsigned long size_dwords, temp; + + /* SIZE IS EITHER 16 DWORDS (4BPP) or 256 DWORDS (8BPP) */ + + if (full_lut) + size_dwords = 256; + else + size_dwords = 16; + + /* CHECK FOR WRAP AFTER LUT LOAD */ + /* Primitive size is 12 plus the amount of data. */ + + gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | + GP3_LUT_HDR_DATA_ENABLE; + + /* WAIT FOR HARDWARE */ + /* Same logic as BLT wrapping. */ + + GP3_WAIT_WRAP(temp); + } else { + gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE; + + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + } + + /* SAVE CURRENT BUFFER POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* PREPARE FOR COMMAND BUFFER DATA WRITES */ + /* Pattern data is contiguous DWORDs at LUT address 0 */ + + WRITE_COMMAND32(0, gp3_cmd_header); + WRITE_COMMAND32(4, 0); + WRITE_COMMAND32(8, (size_dwords | GP3_LUT_DATA_TYPE)); + + /* WRITE ALL DATA */ + + WRITE_COMMAND_STRING32(12, colors, 0, size_dwords); + + /* START OPERATION */ + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_set_vector_pattern + * + * This routine is called to program the hardware LUT with a vector pattern. + * A vector pattern is programmed as a 32-bit mask that specifies a + * transparency pattern. A length parameter is used to specify patterns + * smaller than 32. Note that vectors in Geode LX do not continue across + * corners. The beginning of each vector will always begin with bit 0 of the + * vector pattern. It is the responsibility of the caller to update the + * pattern if an alternate behavior is desired. + * + * This routine faces the same restrictions of all routines that program + * the LUT, in that it must be called before any gp_declare_xxxx routines, + * it cannot be combined with an 8x8 color pattern, color conversion or + * rotation. + *-------------------------------------------------------------------------*/ + +void +gp_set_vector_pattern(unsigned long pattern, unsigned long color, int length) +{ + unsigned long temp, mask; + + gp3_ch3_pat = 1; + gp3_vector_pattern_color = color; + + /* CREATE SUITABLE PATTERN MASK */ + /* The GP requires a minimum of four pixels in a vector pattern. We */ + /* can get around this restriction by doubling any patterns smaller */ + /* than 4 pixels. */ + + while (length < 4) { + mask = 0xFFFFFFFF >> (32 - length); + pattern = (pattern << length) | (pattern & mask); + length <<= 1; + } + mask = 0xFFFFFFFF >> (32 - length); + + gp3_vec_pat = pattern; + + /* CHECK FOR WRAP AFTER LUT LOAD */ + + gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_PATTERN_COMMAND_SIZE; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | + GP3_LUT_HDR_DATA_ENABLE; + + /* WAIT FOR HARDWARE */ + /* Same logic as BLT wrapping. */ + + GP3_WAIT_WRAP(temp); + } else { + gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE; + + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + } + + /* SAVE CURRENT BUFFER POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* PREPARE FOR COMMAND BUFFER DATA WRITES */ + /* Pattern data is 2 DWORDs at 0x100 and 0x101 */ + + WRITE_COMMAND32(0, gp3_cmd_header); + WRITE_COMMAND32(4, 0x100); + WRITE_COMMAND32(8, (2 | GP3_LUT_DATA_TYPE)); + WRITE_COMMAND32(12, pattern); + WRITE_COMMAND32(16, mask); + + /* START OPERATION */ + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_set_strides + * + * This routine is called to program the pitch between successive lines of + * data in the frame buffer. The strides should be DWORD aligned and less + * than 64K. These restrictions are not checked by the API. + *-------------------------------------------------------------------------*/ + +void +gp_set_strides(unsigned long dst_stride, unsigned long src_stride) +{ + /* SAVE STRIDES */ + /* The source stride may be needed later for channel 3 source data and */ + /* we may need to use these strides in calculations. */ + + gp3_src_stride = src_stride; + gp3_dst_stride = dst_stride; + + /* ENABLE STRIDES */ + /* The stride register is in the same place for BLTs and vectors */ + + gp3_cmd_header |= GP3_BLT_HDR_STRIDE_ENABLE; + + WRITE_COMMAND32(GP3_BLT_STRIDE, ((src_stride << 16) | dst_stride)); +} + +/*--------------------------------------------------------------------------- + * gp_set_source_format + * + * This routine is used to program the format of source data used in + * subsequent color-conversion or rotation operations. Note that 4BPP + * indexed and 8BPP indexed source formats cannot be used when rotating, as + * the LUT will be destroyed. These formats also cannot be combined with an + * 8x8 color pattern. The supported formats mirror the hardware and are + * described as follows: + * + * 0 - 8BPP 3:3:2 + * 1 - 8BPP indexed + * 4 - 16BPP 4:4:4:4 + * 5 - 16BPP 1:5:5:5 + * 6 - 16BPP 5:6:5 + * 7 - 16BPP YUV + * 8 - 32BPP 8:8:8:8 + * 13 - 4BPP indexed + * 20 - 16BPP 4:4:4:4 BGR + * 21 - 16BPP 1:5:5:5 BGR + * 22 - 16BPP 0:5:6:5 BGR + * 24 - 32BPP 8:8:8:8 BGR + *-------------------------------------------------------------------------*/ + +void +gp_set_source_format(int format) +{ + /* SAVE FORMAT */ + /* We will combine the source format later when doing color conversion. */ + /* We also save the pixel size for host source calculations. */ + /* Conveniently, the source formats are organized such that the upper */ + /* two bits of the nibble represent the pixel shift, with a pixel shift */ + /* of 3 being a special case for 4BPP data. Clever, yes? Even more */ + /* clever, bit 4 indicates BGR ordering. */ + + gp3_src_pix_shift = (unsigned long)((format >> 2) & 3); + gp3_src_format = (((unsigned long)format & 0xF) << 24) | + (((unsigned long)format & 0x10) << 18); +} + +/*--------------------------------------------------------------------------- + * gp_pattern_fill + * + * This routine is called to perform a simple pattern fill. The pattern + * can be solid, monochrome or a preprogrammed 8x8 color pattern. If + * the ROP involves source data, that source data will be constant. + *-------------------------------------------------------------------------*/ + +void +gp_pattern_fill(unsigned long dstoffset, unsigned long width, + unsigned long height) +{ + unsigned long base_register; + + base_register = (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK) | + ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)); + + /* ENABLE RELEVANT REGISTERS */ + /* Note that we always enable and write the channel 3 mode, if only */ + /* to turn it off. Cimarron also always writes the base offset */ + /* register to allow operation with frame buffers larger than 16MB. */ + + gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */ + /* The destination base is the frame buffer base plus whatever */ + /* 4MB segment we happen to be BLTing to. */ + + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, ((width << 16) | height)); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base_register); + + /* CHECK 8X8 COLOR PATTERN CASE */ + + if (gp3_ch3_pat) { + /* SET CHANNEL 3 PATTERN ORIGINS */ + + gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE; + + /* INITIALIZE CHANNEL 3 PARAMETERS */ + + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ((width << 16) | height)); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); + } else { + /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */ + + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); + } + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_screen_to_screen_blt + * + * This routine is called to perform a BLT from one location inside video + * memory to another location inside video memory. The source and destination + * formats are assumed to be the current BPP. Whenever possible, this routine + * tries to use channel 3 to fetch source data. The BLT flags can affect this + * behavior in the following ways: + * CIMGP_BLTFLAGS_PRES_COLOR_PAT + * A color pattern is being stored in the channel 3 buffer. It is either + * being stored for a later BLT or being combined with the current source + * data. Channel 3 cannot be used to fetch source data or the pattern + * will be overwritten. + * CIMGP_BLTFLAGS_PRES_LUT + * If the first flag is not set, this flag will limit the use of the + * channel 3 buffer to 1K. + *-------------------------------------------------------------------------*/ + +void +gp_screen_to_screen_blt(unsigned long dstoffset, unsigned long srcoffset, + unsigned long width, unsigned long height, int flags) +{ + unsigned long base; + unsigned long ch3_flags = 0; + unsigned long blt_mode = gp3_blt_mode; + unsigned long size = ((width << 16) | height); + unsigned long dstbase, srcbase; + + /* CALCULATE BASE OFFSETS */ + /* We need to set the 4MB aligned base offsets before we add offsets */ + /* for negative BLTs. */ + + srcbase = srcoffset & 0xFFC00000; + dstbase = dstoffset & 0xFFC00000; + srcoffset &= 0x3FFFFF; + dstoffset &= 0x3FFFFF; + + /* ADJUST OFFSETS BASED ON FLAGS */ + /* We adjust the source and destination offsets to point to the first */ + /* byte of the first pixel of the BLT. This routine assumes that the */ + /* source and destination regions do not wrap past the end of a 16MB */ + /* region. */ + + if (flags & CIMGP_NEGXDIR) { + srcoffset += (width << gp3_pix_shift) - 1; + dstoffset += (width << gp3_pix_shift) - 1; + blt_mode |= GP3_BM_NEG_XDIR; + ch3_flags |= GP3_CH3_NEG_XDIR; + } + if (flags & CIMGP_NEGYDIR) { + srcoffset += (height - 1) * gp3_src_stride; + dstoffset += (height - 1) * gp3_dst_stride; + blt_mode |= GP3_BM_NEG_YDIR; + ch3_flags |= GP3_CH3_NEG_YDIR; + } + + /* BRANCH BASED ON CHANNEL 3 */ + /* If a color pattern is not being saved or used, channel 3 will */ + /* be used to fetch source for maximum throughput. Channel 3 */ + /* is not used if transparency or alpha blending is enabled. */ + + if (!(gp3_blt_flags & CIMGP_BLTFLAGS_PRES_COLOR_PAT) && + !(gp3_raster_mode & GP3_RM_SRC_TRANS) && !(flags & CIMGP_NEGYDIR)) { + base = ((gp3_fb_base << 24) + dstbase) | + ((gp3_fb_base << 4) + (srcbase >> 20)) | + (gp3_base_register & GP3_BASE_OFFSET_SRCMASK); + + gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset | gp3_pat_origin)); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, + GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | + gp3_ch3_bpp | gp3_src_stride | ch3_flags | + ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) | + ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + } else { + /* CALCULATE BASE OFFSET REGISTER */ + + base = ((gp3_fb_base << 24) + dstbase) | + ((gp3_fb_base << 14) + (srcbase >> 10)) | + (gp3_base_register & GP3_BASE_OFFSET_CH3MASK); + + /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ + /* We assume that a color pattern is being ROPed with source */ + /* data if the pattern type is color and the preserve pattern */ + /* was set. */ + + blt_mode |= GP3_BM_SRC_FB; + + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + if (gp3_ch3_pat) { + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format | ch3_flags); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); + } else { + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset | gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); + } + + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, srcoffset); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + } + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_screen_to_screen_convert + * + * This routine is called to color-convert a rectangular region of the frame + * buffer into the current BPP. The format of the source region is programmed + * by gp_set_source_format. + *-------------------------------------------------------------------------*/ + +void +gp_screen_to_screen_convert(unsigned long dstoffset, unsigned long srcoffset, + unsigned long width, unsigned long height, int nibble) +{ + unsigned long size = ((width << 16) | height); + unsigned long ch3_offset = srcoffset & 0x3FFFFF; + unsigned long ch3_size, base; + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) | + (gp3_base_register & GP3_BASE_OFFSET_SRCMASK); + + /* SET NIBBLE FOR 4BPP */ + /* 4BPP is a special case in that it requires subpixel addressing. The */ + /* user must supply this information via the nibble parameter. This */ + /* parameter is ignored for every other source format. */ + + ch3_size = size; + if (gp3_src_pix_shift == 3) + ch3_offset |= ((nibble & 1) << 25); + else if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) + ch3_size = ((((width * 3) + 3) >> 2) << 16) | height; + + /* SET APPROPRIATE ENABLES */ + + gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + /* WRITE ALL BLT REGISTERS */ + + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + (dstoffset & 0x3FFFFF) | gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, + GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | gp3_src_format | + ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) | + ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) | gp3_src_stride); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_color_bitmap_to_screen_blt + * + * This routine is called to BLT data from system memory into the frame + * buffer. 'srcy' is deliberately omitted to prevent extra calculations for + * simple applications that have no source indexes. + *-------------------------------------------------------------------------*/ + +void +gp_color_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, unsigned char *data, + long pitch) +{ + unsigned long indent, temp; + unsigned long total_dwords, size_dwords; + unsigned long dword_count, byte_count; + unsigned long size = ((width << 16) | height); + unsigned long srcoffset; + + /* ASSUME BITMAPS ARE DWORD ALIGNED */ + /* We will offset into the source data in DWORD increments. We */ + /* set the source index to the remaining byte offset and */ + /* increment the size of each line to account for the dont-care */ + /* pixel(s). */ + + indent = srcx << gp3_pix_shift; + srcoffset = (indent & ~3L); + indent &= 3; + + /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ + /* We assume that a color pattern is being ROPed with source */ + /* data if the pattern type is color and the preserve pattern */ + /* was set. */ + + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + if (gp3_ch3_pat) { + gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE; + + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); + } else { + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); + } + + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, indent); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, + ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000))); + WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_SRC_HOST); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* CALCULATE THE SIZE OF ONE LINE */ + + size = (width << gp3_pix_shift) + indent; + total_dwords = (size + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (size >> 2); + byte_count = (size & 3); + + /* CHECK FOR SMALL BLT CASE */ + + if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && + (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { + /* UPDATE THE COMMAND POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height)); + + while (height--) { + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + srcoffset += pitch; + cim_cmd_ptr += total_dwords << 2; + } + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } else { + /* + * Each line will be created as a separate command buffer entry to + * allow line-by-line wrapping and to allow simultaneous rendering + * by the HW. + */ + + while (height--) { + /* UPDATE THE COMMAND POINTER + * The WRITE_COMMANDXX macros use a pointer to the current buffer + * space. This is created by adding gp3_cmd_current to the base + * pointer. + */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + /* UPDATE POINTERS */ + + srcoffset += pitch; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } + } +} + +/*--------------------------------------------------------------------------- + * gp_color_convert_blt + * + * This routine is called to convert data that is stored in system memory + * into the current graphics BPP. The source format is programmed in + * gp_set_source_format. + *-------------------------------------------------------------------------*/ + +void +gp_color_convert_blt(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, + unsigned char *data, long pitch) +{ + unsigned long indent, temp; + unsigned long total_dwords, size_dwords; + unsigned long dword_count, byte_count; + unsigned long size = ((width << 16) | height); + unsigned long ch3_size; + unsigned long ch3_offset, srcoffset; + unsigned long base; + + /* ASSUME BITMAPS ARE DWORD ALIGNED */ + /* We will offset into the source data in DWORD increments. We */ + /* set the source index to the remaining byte offset and */ + /* increment the size of each line to account for the dont-care */ + /* pixel(s). For 4BPP source data, we also set the appropriate */ + /* nibble index. */ + + /* CALCULATE THE SIZE OF ONE LINE */ + + if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) { + /* HANDLE 24BPP + * Note that we do not do anything to guarantee that the source data + * is DWORD aligned. The logic here is that the source data will be + * cacheable, in which case Geode LX will not lose any clocks for + * unaligned moves. Also note that the channel 3 width is + * programmed as the number of dwords, while the normal width is + * programmed as the number of pixels. + */ + + srcoffset = srcx * 3; + ch3_offset = 0; + temp = width * 3; + ch3_size = (((temp + 3) >> 2) << 16) | height; + } else { + ch3_size = size; + + if (gp3_src_pix_shift == 3) { + /* CALCULATE INDENT AND SOURCE OFFSET */ + + indent = (srcx >> 1); + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent | ((srcx & 1) << 25); + + temp = ((width + (srcx & 1) + 1) >> 1) + indent; + } else { + indent = (srcx << gp3_src_pix_shift); + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent; + + temp = (width << gp3_src_pix_shift) + indent; + } + } + + total_dwords = (temp + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (temp >> 2); + byte_count = (temp & 3); + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); + + /* SET APPROPRIATE ENABLES */ + + gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + (dstoffset & 0x3FFFFF) | gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | + GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | + gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && + (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { + /* UPDATE THE COMMAND POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE); + } else { + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | + (total_dwords * height)); + + while (height--) { + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + srcoffset += pitch; + cim_cmd_ptr += total_dwords << 2; + } + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } else { + /* WRITE DATA LINE BY LINE + * Each line will be created as a separate command buffer entry to + * allow line-by-line wrapping and to allow simultaneous rendering + * by the HW. + */ + + while (height--) { + /* UPDATE THE COMMAND POINTER + * The WRITE_COMMANDXX macros use a pointer to the current buffer + * space. This is created by adding gp3_cmd_current to the base + * pointer. + */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + /* UPDATE POINTERS */ + + srcoffset += pitch; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } + } +} + +/*--------------------------------------------------------------------------- + * gp_custom_convert_blt + * + * This routine is identical to gp_color_convert_blt, except that the macro + * to write data to the frame buffer has been replaced with a new macro. This + * allows a user to implement custom behavior when sending data, such as + * manually converting 24BPP to 32BPP, converting 2BPP to 4BPP or + * premultiplying alpha data. + *-------------------------------------------------------------------------*/ + +void +gp_custom_convert_blt(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, + unsigned char *data, long pitch) +{ + unsigned long indent, temp; + unsigned long total_dwords, size_dwords; + unsigned long dword_count, byte_count; + unsigned long size = ((width << 16) | height); + unsigned long ch3_offset, srcoffset; + unsigned long ch3_size, base; + + /* ASSUME BITMAPS ARE DWORD ALIGNED */ + /* We will offset into the source data in DWORD increments. We */ + /* set the source index to the remaining byte offset and */ + /* increment the size of each line to account for the dont-care */ + /* pixel(s). For 4BPP source data, we also set the appropriate */ + /* nibble index. */ + + /* CALCULATE THE SIZE OF ONE LINE */ + + if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) { + /* HANDLE 24BPP + * Note that we do not do anything to guarantee that the source data + * is DWORD aligned. The logic here is that the source data will be + * cacheable, in which case Geode LX will not lose any clocks for + * unaligned moves. Also note that the channel 3 width is programmed + * as the number of dwords, while the normal width is programmed as + * the number of pixels. + */ + + srcoffset = srcx * 3; + ch3_offset = 0; + temp = width * 3; + ch3_size = (((temp + 3) >> 2) << 16) | height; + } else { + ch3_size = size; + + if (gp3_src_pix_shift == 3) { + /* CALCULATE INDENT AND SOURCE OFFSET */ + + indent = (srcx >> 1); + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent | ((srcx & 1) << 25); + + temp = ((width + (srcx & 1) + 1) >> 1) + indent; + } else { + indent = (srcx << gp3_src_pix_shift); + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent; + + temp = (width << gp3_src_pix_shift) + indent; + } + } + + total_dwords = (temp + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (temp >> 2); + byte_count = (temp & 3); + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); + + /* SET APPROPRIATE ENABLES */ + + gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + (dstoffset & 0x3FFFFF) | gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, ch3_size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | + GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | + gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && + (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { + /* UPDATE THE COMMAND POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, + GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height)); + + while (height--) { + /* WRITE DATA */ + + WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + srcoffset += pitch; + cim_cmd_ptr += total_dwords << 2; + } + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } else { + /* WRITE DATA LINE BY LINE + * Each line will be created as a separate command buffer entry to + * allow line-by-line wrapping and to allow simultaneous rendering + * by the HW. + */ + + while (height--) { + /* UPDATE THE COMMAND POINTER + * The WRITE_COMMANDXX macros use a pointer to the current buffer + * space. This is created by adding gp3_cmd_current to the base + * pointer. + */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE DATA */ + + WRITE_CUSTOM_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_CUSTOM_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + /* UPDATE POINTERS */ + + srcoffset += pitch; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } + } +} + +/*--------------------------------------------------------------------------- + * gp_rotate_blt + * + * This routine is called to rotate a rectangular area of video memory. The + * data may be color converted during the rotation. 'Degrees' must be a + * multiple of 90 and indicates a clockwise rotation. Width and height + * refer to the width and the height of the source. The output + * destinations will be equal to the rotated dimensions. + *-------------------------------------------------------------------------*/ + +void +gp_rotate_blt(unsigned long dstoffset, unsigned long srcoffset, + unsigned long width, unsigned long height, int degrees) +{ + unsigned long sizein, sizeout; + unsigned long ch3_flags; + unsigned long base; + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + ((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) | + (gp3_base_register & GP3_BASE_OFFSET_SRCMASK); + + srcoffset &= 0x3FFFFF; + dstoffset &= 0x3FFFFF; + + /* SET ROTATION PARAMETERS */ + + switch (degrees) { + case 90: + srcoffset += (height - 1) * gp3_src_stride; + sizein = ((width << 16) | height); + sizeout = ((height << 16) | width); + ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | + GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_YDIR; + break; + + case 180: + srcoffset += (height - 1) * gp3_src_stride; + srcoffset += (width << gp3_src_pix_shift) - 1; + sizein = sizeout = ((width << 16) | height); + ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | + GP3_CH3_NEG_YDIR | GP3_CH3_NEG_XDIR; + break; + + case 270: + srcoffset += (width << gp3_src_pix_shift) - 1; + sizein = ((width << 16) | height); + sizeout = ((height << 16) | width); + ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | + GP3_CH3_ROTATE_ENABLE | GP3_CH3_NEG_XDIR; + break; + + default: + sizein = sizeout = ((width << 16) | height); + ch3_flags = GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE; + break; + } + + /* SET APPROPRIATE ENABLES */ + /* We override the raster mode setting with a source */ + /* copy ROP. */ + + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + /* WRITE ALL BLT REGISTERS */ + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, gp3_bpp | 0xCC); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, sizeout); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, sizein); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, ch3_flags | gp3_src_format | + ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20) | + ((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) | gp3_src_stride); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_mono_bitmap_to_screen_blt + * + * This routine expands and BLTs a monchrome bitmap that is stored in system + * memory into the framebuffer. 'data' points to an array of monochrome data. + * 'stride' indicates the pitch between successive lines of monochrome data. + * 'srcx' indicates the x coordinate within each line of blend data + * corresponding to the first pixel. A y coordinate for the source is + * deliberately omitted to avoid extra calculation for simple cases that have + * no y index. The calling program must adjust the data pointer accordingly. + *-------------------------------------------------------------------------*/ + +void +gp_mono_bitmap_to_screen_blt(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, + unsigned char *data, long stride) +{ + unsigned long indent, temp; + unsigned long total_dwords, size_dwords; + unsigned long dword_count, byte_count; + unsigned long size = ((width << 16) | height); + unsigned long srcoffset, src_value; + + /* ASSUME BITMAPS ARE DWORD ALIGNED */ + /* We will offset into the source data in DWORD increments. We */ + /* set the source index to the remaining byte offset and */ + /* increment the size of each line to account for the dont-care */ + /* pixel(s). */ + + indent = (srcx >> 3); + srcoffset = (indent & ~3L); + indent &= 3; + src_value = (indent | ((srcx & 7) << 26)); + + /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ + /* We assume that a color pattern is being ROPed with source */ + /* data if the pattern type is color and the preserve pattern */ + /* was set. */ + + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | + GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + if (gp3_ch3_pat) { + gp3_cmd_header |= + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; + + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); + } else { + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); + } + if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_raster_mode | GP3_RM_SOURCE_INVERT); + } else { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_raster_mode & ~GP3_RM_SOURCE_INVERT); + } + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, src_value); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, + ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000))); + WRITE_COMMAND32(GP3_BLT_MODE, + gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_MONO); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* CALCULATE THE SIZE OF ONE LINE */ + + size = ((width + (srcx & 7) + 7) >> 3) + indent; + total_dwords = (size + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (size >> 2); + byte_count = (size & 3); + + /* CHECK FOR SMALL BLT CASE */ + /* If the total amount of monochrome data is less than 50K and we have */ + /* room in the command buffer, we will do all data writes in a single */ + /* data packet. */ + + if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && + (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { + /* UPDATE THE COMMAND POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | (total_dwords * height)); + + while (height--) { + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + srcoffset += stride; + cim_cmd_ptr += total_dwords << 2; + } + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } else { + /* WRITE DATA LINE BY LINE + * Each line will be created as a separate command buffer entry to + * allow line-by-line wrapping and to allow simultaneous rendering + * by the HW. + */ + + while (height--) { + /* UPDATE THE COMMAND POINTER + * The WRITE_COMMANDXX macros use a pointer to the current buffer + * space. This is created by adding gp3_cmd_current to the base + * pointer. + */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + /* UPDATE POINTERS */ + + srcoffset += stride; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } + } +} + +/*--------------------------------------------------------------------------- + * gp_text_blt + * + * This routine expands and BLTs byte-packed monochrome data to the screen. + * There is assumed to be no x clipping involved in the BLT. + *-------------------------------------------------------------------------*/ + +void +gp_text_blt(unsigned long dstoffset, unsigned long width, + unsigned long height, unsigned char *data) +{ + unsigned long temp, dwords_total; + unsigned long dword_count, byte_count; + unsigned long size = ((width << 16) | height); + unsigned long srcoffset = 0; + + /* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */ + /* We assume that a color pattern is being ROPed with source */ + /* data if the pattern type is color and the preserve pattern */ + /* was set. */ + + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | + GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + if (gp3_ch3_pat) { + gp3_cmd_header |= + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; + + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); + } else { + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); + } + if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_raster_mode | GP3_RM_SOURCE_INVERT); + } else { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_raster_mode & ~GP3_RM_SOURCE_INVERT); + } + + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, 0); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, + ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000))); + WRITE_COMMAND32(GP3_BLT_MODE, + gp3_blt_mode | GP3_BM_SRC_HOST | GP3_BM_SRC_BP_MONO); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* CALCULATE THE TOTAL NUMBER OF BYTES */ + + size = ((width + 7) >> 3) * height; + + /* WRITE ALL DATA IN CHUNKS */ + + do { + /* UPDATE THE COMMAND POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + if (size > 8192) { + dword_count = 2048; + byte_count = 0; + dwords_total = 2048; + size -= 8192; + } else { + dword_count = (size >> 2); + byte_count = (size & 3); + dwords_total = (size + 3) >> 2; + size = 0; + } + gp3_cmd_next = gp3_cmd_current + (dwords_total << 2) + 8; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_HOST_SOURCE_TYPE | dwords_total); + + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* UPDATE THE SOURCE OFFSET */ + /* We add a constant value because the code will loop only if the */ + /* data exceeds 8192 bytes. */ + + srcoffset += 8192; + + } while (size); +} + +/*--------------------------------------------------------------------------- + * gp_mono_expand_blt + * + * This routine expands monochrome data that is stored in video memory into + * the current BPP. The source and destination regions are assumed not to + * overlap. The pitch of the source data is specified in gp_set_strides. + * 'srcy' is deliberately omitted to prevent extra calculations for simple + * applications that have no source indexes. + *-------------------------------------------------------------------------*/ + +void +gp_mono_expand_blt(unsigned long dstoffset, unsigned long srcoffset, + unsigned long srcx, unsigned long width, + unsigned long height, int byte_packed) +{ + unsigned long base; + unsigned long blt_mode; + unsigned long size = ((width << 16) | height); + + /* ADJUST SOURCE OFFSET */ + + srcoffset += (srcx >> 3); + srcx &= 7; + + /* CALCULATE BASE OFFSET REGISTER */ + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + ((gp3_fb_base << 14) + ((srcoffset & 0xFFC00000) >> 10)) | + (gp3_base_register & GP3_BASE_OFFSET_CH3MASK); + + /* SET THE SOURCE TYPE */ + + if (byte_packed) + blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_BP_MONO; + else + blt_mode = gp3_blt_mode | GP3_BM_SRC_FB | GP3_BM_SRC_MONO; + + /* SET HEADER ENABLES */ + + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | + GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + /* ENABLE COLOR PATTERN IF APPLICABLE */ + + if (gp3_ch3_pat) { + gp3_cmd_header |= + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; + + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, gp3_pat_origin); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, gp3_pat_format); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); + } else { + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, + ((dstoffset & 0x3FFFFF) | gp3_pat_origin)); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, 0); + } + if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_raster_mode | GP3_RM_SOURCE_INVERT); + } else { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_raster_mode & ~GP3_RM_SOURCE_INVERT); + } + + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, + (srcoffset & 0x3FFFFF) | (srcx << 26)); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + + /* WORKAROUND FOR SIBZ #3744 + * Under extremely rare conditions, very narrow byte-packed mono BLTs + * can hang the GP. Even under the rare case, the bad condition will + * only happen once every 16 lines. The workaround is to break the + * offending BLT into a series of safer BLTs. This method is preferred + * over a two-pass approach because it does not require saving and + * restoring any GP state, such as the ROP or mono colors. + */ + + if ((gp3_blt_mode & GP3_BM_DST_REQ) && byte_packed && (gp3_pix_shift < 2) + && (width < 5) && ((srcoffset & 0x1F) == 0x1F) + && ((srcx + width) > 8)) { + unsigned long dstoff1, size1, org1; + unsigned long dstoff2, size2, org2; + unsigned long tempheight; + + size1 = ((8 - srcx) << 16) | 1; + size2 = ((width + srcx - 8) << 16) | 1; + org1 = gp3_pat_origin; + org2 = (org1 & 0xE0000000) | + ((org1 + ((8 - srcx) << 26)) & 0x1C000000); + dstoff1 = dstoffset & 0x3FFFFF; + dstoff2 = (dstoff1 + 8 - srcx) << gp3_pix_shift; + + while (height) { + /* DIVIDE THE FIRST LINE INTO TWO SINGLE LINE BLTS */ + + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size1); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size1); + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, + (srcoffset & 0x3FFFFF) | (srcx << 26)); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1); + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + gp_wait_until_idle(); + + gp_declare_blt(gp3_blt_flags); + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_BLT_MODE_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size2); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size2); + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, ((srcoffset + 1) & 0x3FFFFF)); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff2 | org2); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org2); + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + gp_wait_until_idle(); + + if (--height) { + org1 += 0x20000000; + org2 += 0x20000000; + dstoff1 += gp3_dst_stride; + dstoff2 += gp3_dst_stride; + srcoffset += 2; + + /* THE NEXT 15 LINES ARE NOW 'SAFE' - THEY DO NOT SHOW THE + * PROBLEM */ + + tempheight = 15; + if (tempheight > height) + tempheight = height; + + gp_declare_blt(gp3_blt_flags); + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_BLT_MODE_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE; + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, + (width << 16) | tempheight); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, + (width << 16) | tempheight); + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, + (srcoffset & 0x3FFFFF) | (srcx << 26)); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoff1 | org1); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, org1); + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + gp_wait_until_idle(); + + height -= tempheight; + + if (height) { + gp_declare_blt(gp3_blt_flags); + gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_BLT_MODE_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE; + + /* ADJUST ORIGIN */ + /* If we get here, we added a full 15 lines which is + * equivalent to subtracting one from the pattern y origin + * (adding 15). */ + + org1 -= 0x20000000; + org2 -= 0x20000000; + dstoff1 += (gp3_dst_stride * 15); + dstoff2 += (gp3_dst_stride * 15); + srcoffset += 30; + } + } + } + return; + } + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_BLT_MODE, blt_mode); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_antialiased_text + * + * This routine implements alpha blending between a constant source color and + * a destination region. The degree of the blend is controlled by an array + * of 4BPP/8BPP values specified in 'data'. 'stride' indicates the pitch + * between successive lines of blend data. 'srcx' indicates the x + * coordinate within each line of blend data corresponding to the first + * pixel. A y coordinate for the source is deliberately omitted to avoid + * extra calculation for simple cases that have no y index. The calling + * program must adjust the data pointer accordingly. 'fourbpp' selects + * between 4BPP and 8BPP alpha. + *-------------------------------------------------------------------------*/ + +void +gp_antialiased_text(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, + unsigned char *data, long stride, int fourbpp) +{ + unsigned long indent, temp; + unsigned long total_dwords, size_dwords; + unsigned long dword_count, byte_count; + unsigned long size = ((width << 16) | height); + unsigned long ch3_offset, srcoffset; + unsigned long base, depth_flag; + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); + + /* ENABLE ALL RELEVANT REGISTERS */ + /* We override the raster mode register to force the */ + /* correct alpha blend */ + + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + /* CALCULATIONS BASED ON ALPHA DEPTH */ + /* Although most antialiased text is 4BPP, the hardware supports */ + /* a full 8BPP. Either case is supported by this routine. */ + + if (fourbpp) { + depth_flag = GP3_CH3_SRC_4BPP_ALPHA; + indent = (srcx >> 1); + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent | ((srcx & 1) << 25); + + temp = ((width + (srcx & 1) + 1) >> 1) + indent; + } else { + depth_flag = GP3_CH3_SRC_8BPP_ALPHA; + indent = srcx; + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent; + + temp = width + indent; + } + + total_dwords = (temp + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (temp >> 2); + byte_count = (temp & 3); + + /* SET RASTER MODE REGISTER */ + /* Alpha blending will only apply to RGB when no alpha component is present. */ + /* As 8BPP is not supported for this routine, the only alpha-less mode is */ + /* 5:6:5. */ + + if (gp3_bpp == GP3_RM_BPPFMT_565) { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_bpp | + GP3_RM_ALPHA_TO_RGB | + GP3_RM_ALPHA_A_PLUS_BETA_B | GP3_RM_SELECT_ALPHA_CHAN_3); + } else { + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_bpp | + GP3_RM_ALPHA_ALL | + GP3_RM_ALPHA_A_PLUS_BETA_B | GP3_RM_SELECT_ALPHA_CHAN_3); + } + + /* WRITE ALL REMAINING REGISTERS */ + + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF)); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, size); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, size); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | + GP3_CH3_HST_SRC_ENABLE | + depth_flag | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + WRITE_COMMAND32(GP3_BLT_MODE, gp3_blt_mode | GP3_BM_DST_REQ); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* WRITE DATA LINE BY LINE + * Each line will be created as a separate command buffer entry to allow + * line-by-line wrapping and to allow simultaneous rendering by the HW. + */ + + if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE && + (gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72)) { + /* UPDATE THE COMMAND POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8; + + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, + GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height)); + + while (height--) { + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + srcoffset += stride; + cim_cmd_ptr += total_dwords << 2; + } + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } else { + while (height--) { + /* UPDATE THE COMMAND POINTER + * The WRITE_COMMANDXX macros use a pointer to the current buffer + * space. This is created by adding gp3_cmd_current to the base + * pointer. + */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), data, + srcoffset + (dword_count << 2), byte_count); + + /* UPDATE POINTERS */ + + srcoffset += stride; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } + } +} + +/*--------------------------------------------------------------------------- + * gp_masked_blt + * + * This routine copies source data to the screen. A monochrome mask is used + * to specify source transparency. + *-------------------------------------------------------------------------*/ + +void +gp_masked_blt(unsigned long dstoffset, unsigned long width, + unsigned long height, unsigned long mono_srcx, + unsigned long color_srcx, unsigned char *mono_mask, + unsigned char *color_data, long mono_pitch, long color_pitch) +{ + unsigned long indent, temp; + unsigned long total_dwords, size_dwords; + unsigned long dword_count, byte_count; + unsigned long srcoffset, size; + unsigned long i, ch3_offset, base; + unsigned long flags = 0; + + if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) + flags = GP3_RM_SOURCE_INVERT; + + /* MONO CALCULATIONS */ + + indent = (mono_srcx >> 3); + srcoffset = (indent & ~3L); + indent &= 3; + + size = ((width + (mono_srcx & 7) + 7) >> 3) + indent; + total_dwords = (size + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (size >> 2); + byte_count = (size & 3); + + base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) | + (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); + + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | + GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_WIDHI_ENABLE | GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC); + WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2)); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | + GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | + GP3_CH3_SRC_8_8_8_8 | + ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + WRITE_COMMAND32(GP3_BLT_MODE, 0); + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + + /* START THE BLT */ + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + for (i = 0; i < height; i++) { + /* UPDATE THE COMMAND POINTER + * The WRITE_COMMANDXX macros use a pointer to the current buffer + * space. This is created by adding gp3_cmd_current to the base + * pointer. + */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, mono_mask, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask, + srcoffset + (dword_count << 2), byte_count); + + /* UPDATE POINTERS */ + + srcoffset += mono_pitch; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } + + /* SECOND BLT */ + + gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD); + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + ((gp3_fb_base << 14) + (((gp3_scratch_base + + indent) & 0xFFC00000) >> 10)) | (gp3_base_register & + GP3_BASE_OFFSET_CH3MASK); + + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | + GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + /* ENABLE TRANSPARENCY AND PATTERN COPY ROP + * The monochrome data is used as a mask but is otherwise not involved in + * the BLT. The color data is routed through the pattern channel. + */ + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags); + WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF); + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, + ((gp3_scratch_base + indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26)); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + + /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA */ + /* Data may be color converted along the way. */ + + if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED) { + srcoffset = color_srcx * 3; + ch3_offset = 0; + size = width * 3; + + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, + (((size + 3) >> 2) << 16) | height); + } else if (gp3_src_pix_shift == 3) { + /* CALCULATE INDENT AND SOURCE OFFSET */ + + indent = (color_srcx >> 1); + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent | ((color_srcx & 1) << 25); + + size = ((width + (color_srcx & 1) + 1) >> 1) + indent; + } else { + indent = (color_srcx << gp3_src_pix_shift); + srcoffset = (indent & ~3L); + indent &= 3; + ch3_offset = indent; + + size = (width << gp3_src_pix_shift) + indent; + } + + total_dwords = (size + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (size >> 2); + byte_count = (size & 3); + + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, ch3_offset); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | + GP3_CH3_HST_SRC_ENABLE | + gp3_src_format | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + WRITE_COMMAND32(GP3_BLT_MODE, + gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* WRITE DATA LINE BY LINE */ + + while (height--) { + /* UPDATE THE COMMAND POINTER */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP | + GP3_DATA_LOAD_HDR_ENABLE); + } else { + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, + GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE COLOR DATA TO THE COMMAND BUFFER */ + + WRITE_COMMAND_STRING32(8, color_data, srcoffset, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), color_data, + srcoffset + (dword_count << 2), byte_count); + + /* UPDATE COMMAND BUFFER POINTERS */ + /* We do this before writing the monochrome data because otherwise */ + /* the GP could throttle the writes to the host source register */ + /* waiting for color data. If the command buffer has not been */ + /* updated to load the color data... */ + + srcoffset += color_pitch; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } +} + +/*--------------------------------------------------------------------------- + * gp_screen_to_screen_masked + * + * This routine performs a screen to screen BLT, using a monochrome mask to + * specify source transparency. The source data is assumed to be in the + * current destination format and to not overlap the destination. + *-------------------------------------------------------------------------*/ + +void +gp_screen_to_screen_masked(unsigned long dstoffset, unsigned long srcoffset, + unsigned long width, unsigned long height, + unsigned long mono_srcx, unsigned char *mono_mask, long mono_pitch) +{ + unsigned long indent, temp; + unsigned long total_dwords, size_dwords; + unsigned long dword_count, byte_count; + unsigned long srcoff, size; + unsigned long i, base; + unsigned long flags = 0; + + if (gp3_blt_flags & CIMGP_BLTFLAGS_INVERTMONO) + flags = GP3_RM_SOURCE_INVERT; + + /* MONO CALCULATIONS */ + + indent = (mono_srcx >> 3); + srcoff = (indent & ~3L); + indent &= 3; + + size = ((width + (mono_srcx & 7) + 7) >> 3) + indent; + total_dwords = (size + 3) >> 2; + size_dwords = (total_dwords << 2) + 8; + dword_count = (size >> 2); + byte_count = (size & 3); + + base = ((gp3_fb_base << 24) + (gp3_scratch_base & 0xFFC00000)) | + (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); + + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | GP3_BLT_HDR_STRIDE_ENABLE | + GP3_BLT_HDR_DST_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | GP3_BLT_HDR_CH3_OFF_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, GP3_RM_BPPFMT_8888 | 0xCC); + WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 2)); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, gp3_scratch_base & 0x3FFFFF); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (total_dwords << 16) | height); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (total_dwords << 16) | height); + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, 0); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | + GP3_CH3_REPLACE_SOURCE | GP3_CH3_HST_SRC_ENABLE | + GP3_CH3_SRC_8_8_8_8 | + ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + WRITE_COMMAND32(GP3_BLT_MODE, 0); + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + + /* START THE BLT */ + + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + for (i = 0; i < height; i++) { + /* UPDATE THE COMMAND POINTER + * The WRITE_COMMANDXX macros use a pointer to the current buffer + * space. This is created by adding gp3_cmd_current to the base + * pointer. + */ + + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + /* CHECK IF A WRAP WILL BE NEEDED */ + + gp3_cmd_next = gp3_cmd_current + size_dwords; + if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE) { + gp3_cmd_next = gp3_cmd_top; + + /* WAIT FOR HARDWARE */ + + GP3_WAIT_WRAP(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_WRAP | GP3_DATA_LOAD_HDR_ENABLE); + } else { + /* WAIT FOR AVAILABLE SPACE */ + + GP3_WAIT_PRIMITIVE(temp); + WRITE_COMMAND32(0, GP3_DATA_LOAD_HDR_TYPE | + GP3_DATA_LOAD_HDR_ENABLE); + } + + /* WRITE DWORD COUNT */ + + WRITE_COMMAND32(4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords); + + /* WRITE DATA */ + + WRITE_COMMAND_STRING32(8, mono_mask, srcoff, dword_count); + WRITE_COMMAND_STRING8(8 + (dword_count << 2), mono_mask, + srcoff + (dword_count << 2), byte_count); + + /* UPDATE POINTERS */ + + srcoff += mono_pitch; + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + } + + /* SECOND BLT */ + + gp_declare_blt(gp3_blt_flags | CIMGP_BLTFLAGS_HAZARD); + + base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) | + ((gp3_fb_base << 14) + (((gp3_scratch_base + + indent) & 0xFFC00000) >> 10)) | ((gp3_fb_base << 4) + + ((srcoffset & 0xFFC00000) >> 20)); + + gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE | + GP3_BLT_HDR_STRIDE_ENABLE | GP3_BLT_HDR_DST_OFF_ENABLE | + GP3_BLT_HDR_SRC_OFF_ENABLE | GP3_BLT_HDR_WIDHI_ENABLE | + GP3_BLT_HDR_CH3_STR_ENABLE | + GP3_BLT_HDR_CH3_WIDHI_ENABLE | + GP3_BLT_HDR_BASE_OFFSET_ENABLE | + GP3_BLT_HDR_CH3_OFF_ENABLE | GP3_BLT_HDR_BLT_MODE_ENABLE; + + /* ENABLE TRANSPARENCY AND PATTERN COPY ROP + * The monochrome data is used as a mask but is otherwise not involved + * in the BLT. The color data is routed through the pattern channel. + */ + + WRITE_COMMAND32(GP3_BLT_RASTER_MODE, + gp3_bpp | 0xF0 | GP3_RM_SRC_TRANS | flags); + WRITE_COMMAND32(GP3_BLT_STRIDE, (total_dwords << 18) | gp3_dst_stride); + WRITE_COMMAND32(GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF); + WRITE_COMMAND32(GP3_BLT_SRC_OFFSET, + ((gp3_scratch_base + indent) & 0x3FFFFF) | ((mono_srcx & 7) << 26)); + WRITE_COMMAND32(GP3_BLT_WID_HEIGHT, (width << 16) | height); + WRITE_COMMAND32(GP3_BLT_CH3_WIDHI, (width << 16) | height); + WRITE_COMMAND32(GP3_BLT_BASE_OFFSET, base); + + /* PROGRAM PARAMETERS FOR COLOR SOURCE DATA */ + + WRITE_COMMAND32(GP3_BLT_CH3_OFFSET, srcoffset & 0x3FFFFF); + WRITE_COMMAND32(GP3_BLT_CH3_MODE_STR, GP3_CH3_C3EN | gp3_ch3_bpp | + gp3_src_stride | ((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20)); + WRITE_COMMAND32(GP3_BLT_MODE, + gp3_blt_mode | GP3_BM_SRC_MONO | GP3_BM_SRC_FB); + + /* START THE BLT */ + + WRITE_COMMAND32(GP3_BLT_CMD_HEADER, gp3_cmd_header); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; +} + +/*--------------------------------------------------------------------------- + * gp_bresenham_line + * + * This routine draws a vector using the specified Bresenham parameters. + * Currently this file does not support a routine that accepts the two + * endpoints of a vector and calculates the Bresenham parameters. If it + * ever does, this routine is still required for vectors that have been + * clipped. + *-------------------------------------------------------------------------*/ + +void +gp_bresenham_line(unsigned long dstoffset, unsigned short length, + unsigned short initerr, unsigned short axialerr, + unsigned short diagerr, unsigned long flags) +{ + unsigned long base; + long offset; + + /* HANDLE NEGATIVE VECTORS */ + /* We have to be very careful with vectors that increment negatively */ + /* Our framebuffer scheme tries to align the destination of every */ + /* BLT or vector to the nearest 4MB-aligned boundary. This is */ + /* necessary because the GP only supports offsets up to 16MB, but the */ + /* framebuffer can be over 128MB. To solve this problem, the GP */ + /* base address registers are alignable to 4MB regions. However, we */ + /* cannot simply align the dest offset when the vector goes negative. */ + /* The vector offset could underflow, causing the offset to jump from */ + /* near 0 to 16MB. As we cannot accurately determine the last address */ + /* that will be written in a vector short of walking the algorithm in */ + /* software, we do a worst case approximation. */ + + offset = dstoffset; + if (!(flags & CIMGP_POSMAJOR)) { + if (flags & CIMGP_YMAJOR) + offset -= length * gp3_dst_stride; + else + offset -= (length << gp3_pix_shift); + + if (offset < 0) + offset = 0; + } + if (!(flags & CIMGP_POSMINOR)) { + if (flags & CIMGP_YMAJOR) + offset -= (length << gp3_pix_shift); + else + offset -= length * gp3_dst_stride; + + if (offset < 0) + offset = 0; + } + + offset &= 0xFFC00000; + dstoffset -= offset; + + base = ((gp3_fb_base << 24) + offset) | + (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); + + /* ENABLE RELEVANT REGISTERS */ + /* Note that we always enable and write the channel 3 mode, if only */ + /* to turn it off. Cimarron also always writes the base offset */ + /* register to allow operation with frame buffers larger than 16MB. */ + + gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE | + GP3_VEC_HDR_VEC_ERR_ENABLE | + GP3_VEC_HDR_VEC_LEN_ENABLE | + GP3_VEC_HDR_BASE_OFFSET_ENABLE | + GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE; + + /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */ + /* The destination base is the frame buffer base plus whatever */ + /* 4MB segment we happen to be drawing to. */ + + WRITE_COMMAND32(GP3_VECTOR_VEC_ERR, + (((unsigned long)axialerr << 16) | (unsigned long)diagerr)); + WRITE_COMMAND32(GP3_VECTOR_VEC_LEN, + (((unsigned long)length << 16) | (unsigned long)initerr)); + WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base); + + /* CHECK VECTOR PATTERN CASE */ + + if (gp3_ch3_pat) { + /* SET THE SOLID COLOR */ + /* The color for vector patterns from channel 3 comes from */ + /* the regular pattern registers. */ + + gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE; + + WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color); + + /* INITIALIZE CHANNEL 3 PARAMETERS + * We route the channel 3 output to the old source channel. If the + * user sets a ROP that involves source, they will get unexpected + * results. + */ + + WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset); + WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, + GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | + GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8); + } else { + /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */ + + WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0); + WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin)); + } + + /* START THE VECTOR */ + + WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags)); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + + gp3_cmd_current = gp3_cmd_next; + + /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES */ + /* We set a transparent pattern to clear the byte enables. */ + /* We then restore the previous pattern. (SiBZ #4001) */ + + if (gp3_ch3_pat) { + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); + WRITE_COMMAND32(4, 0x100); + WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE)); + WRITE_COMMAND32(12, 0); + + /* DUMMY VECTOR */ + /* We shouldn't need to write anything but vector mode and the length + */ + + WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE | + GP3_VEC_HDR_VEC_LEN_ENABLE); + WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags)); + WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN, + (1 << 16) | (unsigned long)initerr); + + WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE, + GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); + WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100); + WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, + (1 | GP3_LUT_DATA_TYPE)); + WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat); + + gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE; + } +} + +/*--------------------------------------------------------------------------- + * gp_line_from_endpoints + * + * This routine draws a vector from a set of rectangular coordinates. The + * rectangle is assumed to use the currently specified destination stride. + *-------------------------------------------------------------------------*/ + +void +gp_line_from_endpoints(unsigned long dstoffset, unsigned long x0, + unsigned long y0, unsigned long x1, unsigned long y1, int inclusive) +{ + unsigned long base; + unsigned long length; + unsigned long flags; + unsigned short initerr, axialerr, diagerr; + long dx, dy, dmaj, dmin; + long offset; + + /* ADJUST DESTINATION OFFSET BASED ON STARTING COORDINATE */ + + dstoffset += (x0 << gp3_pix_shift) + (y0 * gp3_dst_stride); + + /* CALCULATE BRESENHAM TERMS */ + + dx = (long)x1 - (long)x0; + dy = (long)y1 - (long)y0; + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + + if (dx >= dy) { + dmaj = dx; + dmin = dy; + flags = 0; + if (x1 > x0) + flags |= CIMGP_POSMAJOR; + if (y1 > y0) + flags |= CIMGP_POSMINOR; + } else { + dmaj = dy; + dmin = dx; + flags = CIMGP_YMAJOR; + if (x1 > x0) + flags |= CIMGP_POSMINOR; + if (y1 > y0) + flags |= CIMGP_POSMAJOR; + } + + axialerr = (unsigned short)(dmin << 1); + diagerr = (unsigned short)((dmin - dmaj) << 1); + initerr = (unsigned short)((dmin << 1) - dmaj); + if (!(flags & CIMGP_POSMINOR)) + initerr--; + + /* CHECK FOR NO WORK */ + + if (!dmaj) + return; + + /* CHECK INCLUSIVE OR EXCLUSIVE */ + /* An inclusive line can be accomplished by simply adding 1 to the */ + /* line length. */ + + length = dmaj; + if (inclusive) + length++; + + /* HANDLE NEGATIVE VECTORS */ + + offset = dstoffset; + if (!(flags & CIMGP_POSMAJOR)) { + if (flags & CIMGP_YMAJOR) + offset -= length * gp3_dst_stride; + else + offset -= (length << gp3_pix_shift); + + if (offset < 0) + offset = 0; + } + if (!(flags & CIMGP_POSMINOR)) { + if (flags & CIMGP_YMAJOR) + offset -= (length << gp3_pix_shift); + else + offset -= length * gp3_dst_stride; + + if (offset < 0) + offset = 0; + } + + offset &= 0xFFC00000; + dstoffset -= offset; + + base = ((gp3_fb_base << 24) + offset) | + (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK); + + /* ENABLE RELEVANT REGISTERS */ + /* Note that we always enable and write the channel 3 mode, if only */ + /* to turn it off. Cimarron also always writes the base offset */ + /* register to allow operation with frame buffers larger than 16MB. */ + + gp3_cmd_header |= GP3_VEC_HDR_DST_OFF_ENABLE | + GP3_VEC_HDR_VEC_ERR_ENABLE | + GP3_VEC_HDR_VEC_LEN_ENABLE | + GP3_VEC_HDR_BASE_OFFSET_ENABLE | + GP3_VEC_HDR_CH3_STR_ENABLE | GP3_VEC_HDR_VEC_MODE_ENABLE; + + /* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */ + /* The destination base is the frame buffer base plus whatever */ + /* 4MB segment we happen to be drawing to. */ + + WRITE_COMMAND32(GP3_VECTOR_VEC_ERR, + (((unsigned long)axialerr << 16) | (unsigned long)diagerr)); + WRITE_COMMAND32(GP3_VECTOR_VEC_LEN, + (((unsigned long)length << 16) | (unsigned long)initerr)); + WRITE_COMMAND32(GP3_VECTOR_BASE_OFFSET, base); + + /* CHECK VECTOR PATTERN CASE */ + + if (gp3_ch3_pat) { + /* SET THE SOLID COLOR */ + /* The color for vector patterns from channel 3 comes from */ + /* the regular pattern registers. */ + + gp3_cmd_header |= GP3_VEC_HDR_PAT_CLR0_ENABLE; + + WRITE_COMMAND32(GP3_VECTOR_PAT_COLOR_0, gp3_vector_pattern_color); + + /* INITIALIZE CHANNEL 3 PARAMETERS */ + /* We route the channel 3 output to the old source channel. If the + * user sets a ROP that involves source, they will get unexpected + * results. + */ + + WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, dstoffset); + WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, + GP3_CH3_C3EN | GP3_CH3_REPLACE_SOURCE | + GP3_CH3_COLOR_PAT_ENABLE | GP3_CH3_SRC_8_8_8_8); + } else { + /* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */ + + WRITE_COMMAND32(GP3_VECTOR_CH3_MODE_STR, 0); + WRITE_COMMAND32(GP3_VECTOR_DST_OFFSET, (dstoffset | gp3_pat_origin)); + } + + /* START THE VECTOR */ + + WRITE_COMMAND32(GP3_VEC_CMD_HEADER, gp3_cmd_header); + WRITE_COMMAND32(GP3_VECTOR_MODE, (gp3_vec_mode | flags)); + WRITE_GP32(GP3_CMD_WRITE, gp3_cmd_next); + gp3_cmd_current = gp3_cmd_next; + + /* ADD A SECOND VECTOR TO CLEAR THE BYTE ENABLES */ + /* We set a transparent pattern to clear the byte enables. */ + /* We then restore the previous pattern. (SiBZ #4001) */ + + if (gp3_ch3_pat) { + cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current; + + WRITE_COMMAND32(0, GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); + WRITE_COMMAND32(4, 0x100); + WRITE_COMMAND32(8, (1 | GP3_LUT_DATA_TYPE)); + WRITE_COMMAND32(12, 0); + + /* DUMMY VECTOR */ + /* We shouldn't need to write anything but vector mode and the length + */ + + WRITE_COMMAND32(16, GP3_VEC_HDR_TYPE | GP3_VEC_HDR_VEC_MODE_ENABLE | + GP3_VEC_HDR_VEC_LEN_ENABLE); + WRITE_COMMAND32(16 + GP3_VECTOR_MODE, (gp3_vec_mode | flags)); + WRITE_COMMAND32(16 + GP3_VECTOR_VEC_LEN, + (1 << 16) | (unsigned long)initerr); + + WRITE_COMMAND32(16 + GP3_VECTOR_COMMAND_SIZE, + GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE); + WRITE_COMMAND32(20 + GP3_VECTOR_COMMAND_SIZE, 0x100); + WRITE_COMMAND32(24 + GP3_VECTOR_COMMAND_SIZE, + (1 | GP3_LUT_DATA_TYPE)); + WRITE_COMMAND32(28 + GP3_VECTOR_COMMAND_SIZE, gp3_vec_pat); + + gp3_cmd_current += 32 + GP3_VECTOR_COMMAND_SIZE; + } +} + +/*--------------------------------------------------------------------------- + * gp_wait_until_idle + * + * This routine stalls execution until the GP is no longer actively rendering. + *-------------------------------------------------------------------------*/ + +void +gp_wait_until_idle(void) +{ + unsigned long temp; + + while (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) || + !(temp & GP3_BS_CB_EMPTY)) { + ; + } +} + +/*--------------------------------------------------------------------------- + * gp_test_blt_busy + *-------------------------------------------------------------------------*/ + +int +gp_test_blt_busy(void) +{ + unsigned long temp; + + if (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) || + !(temp & GP3_BS_CB_EMPTY)) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * gp_test_blt_pending + *-------------------------------------------------------------------------*/ + +int +gp_test_blt_pending(void) +{ + if ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * gp_wait_blt_pending + *-------------------------------------------------------------------------*/ + +void +gp_wait_blt_pending(void) +{ + while ((READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_PENDING) ; +} + +/*--------------------------------------------------------------------------- + * gp_save_state + * + * This routine saves all persistent GP information. + *-------------------------------------------------------------------------*/ + +void +gp_save_state(GP_SAVE_RESTORE * gp_state) +{ + Q_WORD msr_value; + + gp_wait_until_idle(); + + msr_read64(MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value); + gp_state->cmd_bottom = READ_GP32(GP3_CMD_BOT) & 0xFFFFFF; + gp_state->cmd_top = READ_GP32(GP3_CMD_TOP) & 0xFFFFFF; + gp_state->cmd_base = (msr_value.low << 4) & 0xFFF00000; + gp_state->base_offset = READ_GP32(GP3_BASE_OFFSET); + + /* RESET THE READ POINTER */ + + gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top, + gp_state->cmd_bottom); +} + +/*--------------------------------------------------------------------------- + * gp_restore_state + * + * This routine restores all persistent GP information. + *-------------------------------------------------------------------------*/ + +void +gp_restore_state(GP_SAVE_RESTORE * gp_state) +{ + gp_wait_until_idle(); + + WRITE_GP32(GP3_BASE_OFFSET, gp_state->base_offset); + + gp_set_command_buffer_base(gp_state->cmd_base, gp_state->cmd_top, + gp_state->cmd_bottom); +} diff --git a/src/cim/cim_init.c b/src/cim/cim_init.c new file mode 100644 index 0000000..71f20b6 --- /dev/null +++ b/src/cim/cim_init.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron initialization routines. These routines detect a Geode LX and + * read all hardware base addresses. + */ + +CIMARRON_STATIC unsigned long init_video_base = 0x80000900; + +/*--------------------------------------------------------------------------- + * init_detect_cpu + * + * This routine verifies that a Geode LX is present and returns the processor + * revision ID. For compatibility, this routine can also detect a Redcloud + * processor. + * bits[24:16] = minor version + * bits[15:8] = major version + * bits[7:0] = type (1 = Geode GX, 2 = Geode LX) + *---------------------------------------------------------------------------*/ + +int +init_detect_cpu(unsigned long *cpu_revision, + unsigned long *companion_revision) +{ + unsigned long bus, device, i; + unsigned long cpu_bus = 0, cpu_device = 0; + unsigned long address, data; + unsigned long num_bars, function; + int cpu_found, sb_found; + Q_WORD msr_value; + + /* SEARCH THROUGH PCI BUS */ + /* We search the PCI bus for the Geode LX or Geode GX northbridge. */ + /* We then verify that one of its functions is the graphics */ + /* controller and that all bars are filled in. */ + + cpu_found = sb_found = 0; + for (bus = 0; bus < 256; bus++) { + for (device = 0; device < 21; device++) { + address = 0x80000000 | (bus << 16) | (device << 11); + + data = init_read_pci(address); + + if (data == PCI_VENDOR_DEVICE_GEODEGX + || data == PCI_VENDOR_DEVICE_GEODELX) { + cpu_found = 1; + cpu_device = device; + cpu_bus = bus; + if (data == PCI_VENDOR_DEVICE_GEODEGX) + *cpu_revision = CIM_CPU_GEODEGX; + else + *cpu_revision = CIM_CPU_GEODELX; + } else if (data == PCI_VENDOR_5535 || data == PCI_VENDOR_5536) { + sb_found = 1; + if (data == PCI_VENDOR_5535) + *companion_revision = CIM_SB_5535; + else + *companion_revision = CIM_SB_5536; + } + + if (cpu_found && sb_found) + break; + } + if (device != 21) + break; + } + + if (bus == 256) { + *cpu_revision = 0; + return CIM_STATUS_CPUNOTFOUND; + } + + msr_init_table(); + + if (msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REVID, + &msr_value) != CIM_STATUS_OK) { + *cpu_revision = 0; + return CIM_STATUS_CPUNOTFOUND; + } + + *cpu_revision |= ((msr_value.low & 0xF0) << 4) | + ((msr_value.low & 0x0F) << 16); + + if (msr_read64(MSR_DEVICE_5535_GLCP, GLCP_REVID, + &msr_value) != CIM_STATUS_OK) { + *cpu_revision = 0; + return CIM_STATUS_CPUNOTFOUND; + } + + *companion_revision |= ((msr_value.low & 0xF0) << 4) | + ((msr_value.low & 0x0F) << 16); + + /* SEARCH ALL FUNCTIONS FOR INTEGRATED GRAPHICS */ + + num_bars = 0; + for (function = 0; function < 7; function++) { + address = 0x80000000 | (cpu_bus << 16) | (cpu_device << 11) | + (function << 8); + data = init_read_pci(address); + + if (data == PCI_VENDOR_DEVICE_GEODEGX_VIDEO) { + num_bars = 4; + break; + } else if (data == PCI_VENDOR_DEVICE_GEODELX_VIDEO) { + num_bars = 5; + break; + } + } + + /* VERIFY THAT ALL BARS ARE PRESENT */ + + if (function == 7) + return CIM_STATUS_DISPLAYUNAVAILABLE; + + for (i = 0; i < num_bars; i++) { + data = init_read_pci(address + 0x10 + (i << 2)); + + if (data == 0 || data == 0xFFFFFFFF) + break; + } + + if (i != num_bars) + return CIM_STATUS_DISPLAYUNAVAILABLE; + + /* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */ + + init_video_base = address; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * init_read_pci + * + * This routine reads an unsigned long value from a PCI address. + *---------------------------------------------------------------------------*/ + +unsigned long +init_read_pci(unsigned long address) +{ + OUTD(0xCF8, address); + return IND(0xCFC); +} + +/*--------------------------------------------------------------------------- + * init_read_base_addresses + * + * This routine reads all base addresses for the peripherals from the PCI + * BARs. + *---------------------------------------------------------------------------*/ + +int +init_read_base_addresses(INIT_BASE_ADDRESSES * base_addresses) +{ + unsigned long value; + + /* READ ALL BASE ADDRESSES */ + + base_addresses->framebuffer_base = init_read_pci(init_video_base + 0x10); + base_addresses->gp_register_base = init_read_pci(init_video_base + 0x14); + base_addresses->vg_register_base = init_read_pci(init_video_base + 0x18); + base_addresses->df_register_base = init_read_pci(init_video_base + 0x1C); + base_addresses->vip_register_base = init_read_pci(init_video_base + 0x20); + + /* READ FRAME BUFFER SIZE */ + /* The frame buffer size is reported by a VSM in VSA II */ + /* Virtual Register Class = 0x02 */ + /* VG_MEM_SIZE (1MB units) = 0x00 */ + + OUTW(0xAC1C, 0xFC53); + OUTW(0xAC1C, 0x0200); + + value = (unsigned long)(INW(0xAC1E)) & 0xFE; + + base_addresses->framebuffer_size = value << 20; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * init_read_cpu_frequency + * + * This routine returns the current CPU core frequency, in MHz. + *---------------------------------------------------------------------------*/ + +int +init_read_cpu_frequency(unsigned long *cpu_frequency) +{ + /* CPU SPEED IS REPORTED BY A VSM IN VSA II */ + /* Virtual Register Class = 0x12 (Sysinfo) */ + /* CPU Speed Register = 0x01 */ + + OUTW(0xAC1C, 0xFC53); + OUTW(0xAC1C, 0x1201); + + *cpu_frequency = (unsigned long)(INW(0xAC1E)); + + return CIM_STATUS_OK; +} diff --git a/src/cim/cim_modes.c b/src/cim/cim_modes.c new file mode 100644 index 0000000..aa8402c --- /dev/null +++ b/src/cim/cim_modes.c @@ -0,0 +1,1905 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron mode tables. + */ + +/*-------------------------------*/ +/* PREDEFINED DISPLAY TIMINGS */ +/*-------------------------------*/ + +VG_DISPLAY_MODE CimarronDisplayModes[] = { + /* 320 x 240 PANEL */ + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PANEL, /* Panel Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_PANELOUT | /* Panel output. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC | /* negative syncs */ + VG_MODEFLAG_QVGA, /* QVGA Panel size. */ + 320, 240, /* No scaling. */ + 320, 240, /* 320x240 active */ + 320, 240, /* 320x240 panel */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0140, 0x0148, 0x0162, 0x0180, 0x0188, 0x0190, /* horiz timings */ + 0x00F0, 0x00F4, 0x00F9, 0x00FD, 0x00FF, 0x0104, /* vertical timings */ + (31L << 16) | ((2000L * 65536L) / 10000L), /* freq = 31.2000 MHz */ + } + , + + /* 640 x 400 */ + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC, /* negative HSYNC */ + 640, 400, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x280, 0x288, 0x290, 0x2F0, 0x318, 0x320, /* horiz timings */ + 0x190, 0x197, 0x19C, 0x19E, 0x1BA, 0x1C1, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (25L << 16) | ((1750L * 65536L) / 10000L), /* freq = 25.175 MHz */ + } + , + + /* 640x480 */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 640, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0288, 0x0290, 0x02E8, 0x0318, 0x0320, /* horiz timings */ + 0x01E0, 0x01E8, 0x01EA, 0x01EC, 0x0205, 0x020D, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (25L << 16) | ((1750L * 65536L) / 10000L), /* freq = 25.175 MHz */ + } + , + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 640, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0280, 0x0298, 0x02D8, 0x0330, 0x0330, /* horiz timings */ + 0x01E0, 0x01E0, 0x01E2, 0x01E5, 0x01F4, 0x01F4, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (28L << 16) | ((5600L * 65536L) / 10000L), /* freq = 28.560 MHz */ + } + , + + {VG_SUPPORTFLAG_72HZ | /* refresh rate = 72 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 640, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0288, 0x0298, 0x02c0, 0x0338, 0x0340, /* horiz timings */ + 0x01e0, 0x01e8, 0x01e9, 0x01ec, 0x0200, 0x0208, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (31L << 16) | ((5000L * 65536L) / 10000L), /* freq = 31.5 MHz */ + } + , + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 640, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0280, 0x0290, 0x02D0, 0x0348, 0x0348, /* horiz timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01F4, 0x01F4, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (31L << 16) | ((5000L * 65536L) / 10000L), /* freq = 31.5 MHz */ + } + , + + {VG_SUPPORTFLAG_85HZ | /* refresh rate = 85 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 640, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0280, 0x02B8, 0x02F0, 0x0340, 0x0340, /* horiz timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FD, 0x01FD, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (36L << 16) | ((0000L * 65536L) / 10000L), /* freq = 36.0 MHz */ + } + , + + {VG_SUPPORTFLAG_90HZ | /* refresh rate = 90 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 640, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0280, 0x02A0, 0x02E0, 0x0340, 0x0340, /* horiz timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FA, 0x01FA, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (37L << 16) | ((8890L * 65536L) / 10000L), /* freq = 37.889 MHz */ + } + , + + {VG_SUPPORTFLAG_100HZ | /* refresh rate = 100 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 640, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0280, 0x02A8, 0x02E8, 0x0350, 0x0350, /* horiz timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FD, 0x01FD, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (43L << 16) | ((1630L * 65536L) / 10000L), /* freq = 43.163 MHz */ + } + , + + /* 640 x 480 PANEL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PANEL, /* Panel Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_PANELOUT | /* Panel output. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 640, 480, /* No scaling. */ + 640, 480, /* 640x480 active */ + 640, 480, /* 640x480 panel */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320, /* horiz timings */ + 0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (25L << 16) | ((1750L * 65536L) / 10000L), /* freq = 25.175 MHz */ + } + , + + /* 800x600 */ + + {VG_SUPPORTFLAG_56HZ | /* refresh rate = 56 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0338, 0x0380, 0x0400, 0x0400, /* horiz timings */ + 0x0258, 0x0258, 0x0259, 0x025B, 0x0271, 0x0271, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (36L << 16) | ((0000L * 65536L) / 10000L), /* freq = 36.0 MHz */ + } + , + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0328, 0x0348, 0x03D0, 0x0418, 0x0420, /* horiz timings */ + 0x0258, 0x0258, 0x0259, 0x025D, 0x0274, 0x0274, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (40L << 16) | ((0000L * 65536L) / 10000L), /* freq = 40.00 MHz */ + } + , + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0348, 0x0398, 0x0410, 0x0410, /* horiz timings */ + 0x0258, 0x0258, 0x025c, 0x025F, 0x0274, 0x0274, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (45L << 16) | ((7200L * 65536L) / 10000L), /* freq = 45.72 MHz */ + } + , + + {VG_SUPPORTFLAG_72HZ | /* refresh rate = 72 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0358, 0x03D0, 0x0410, 0x0410, /* horiz timings */ + 0x0258, 0x0258, 0x027D, 0x0283, 0x029A, 0x029A, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (49L << 16) | ((5000L * 65536L) / 10000L), /* freq = 49.5 MHz */ + } + , + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0330, 0x0380, 0x0420, 0x0420, /* horiz timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0271, 0x0271, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (49L << 16) | ((5000L * 65536L) / 10000L), /* freq = 49.5 MHz */ + } + , + + {VG_SUPPORTFLAG_85HZ | /* refresh rate = 85 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0340, 0x0380, 0x0418, 0x0418, /* horiz timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0277, 0x0277, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (56L << 16) | ((2500L * 65536L) / 10000L), /* freq = 56.25 MHz */ + } + , + + {VG_SUPPORTFLAG_90HZ | /* refresh rate = 90 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0348, 0x03A0, 0x0420, 0x0420, /* horiz timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0278, 0x0278, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (60L << 16) | ((650L * 65536L) / 10000L), /* freq = 60.065 MHz */ + } + , + + {VG_SUPPORTFLAG_100HZ | /* refresh rate = 100 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + 0, + 800, 600, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0350, 0x03A8, 0x0430, 0x0430, /* horiz timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0277, 0x027C, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (68L << 16) | ((1790L * 65536L) / 10000L), /* freq = 68.179 MHz */ + } + , + + /* 800x600 PANEL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PANEL, /* Panel Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_PANELOUT | /* Panel output. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 800, 600, /* No scaling. */ + 800, 600, /* 800x600 active. */ + 800, 600, /* 800x600 panel */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x0348, 0x03C8, 0x0420, 0x0420, /* horiz timings */ + 0x0258, 0x0258, 0x0259, 0x025D, 0x0274, 0x0274, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (40L << 16) | ((0000L * 65536L) / 10000L), /* freq = 40.00 MHz */ + } + , + + /* 1024x768 */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 1024, 768, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540, /* horiz timings */ + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (65L << 16) | ((0000L * 65536L) / 10000L), /* freq = 65.00 MHz */ + } + , + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 1024, 768, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0530, 0x0530, /* horiz timings */ + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (75L << 16) | ((0000L * 65536L) / 10000L), /* freq = 75.0 MHz */ + } + , + + {VG_SUPPORTFLAG_72HZ | /* refresh rate = 72 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1024, 768, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0438, 0x04A8, 0x0550, 0x0550, /* horiz timings */ + 0x0300, 0x0300, 0x0304, 0x0307, 0x0324, 0x0324, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (78L << 16) | ((7500L * 65536L) / 10000L), /* freq = 78.75 MHz */ + } + , + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1024, 768, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0410, 0x0470, 0x0520, 0x0520, /* horiz timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x0320, 0x0320, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (78L << 16) | ((7500L * 65536L) / 10000L), /* freq = 78.75 MHz */ + } + , + + {VG_SUPPORTFLAG_85HZ | /* refresh rate = 85 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1024, 768, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0430, 0x0490, 0x0560, 0x0560, /* horiz timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x0328, 0x0328, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (94L << 16) | ((5000L * 65536L) / 10000L), /* freq = 94.50 MHz */ + } + , + + {VG_SUPPORTFLAG_90HZ | /* refresh rate = 90 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1024, 768, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0440, 0x04B0, 0x0560, 0x0560, /* horiz timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x0329, 0x0329, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (100L << 16) | ((1870L * 65536L) / 10000L), /* freq = 100.187 MHz */ + } + , + + {VG_SUPPORTFLAG_100HZ | /* refresh rate = 100 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1024, 768, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0448, 0x04B8, 0x0570, 0x0570, /* horiz timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x032E, 0x032E, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (113L << 16) | ((3100L * 65536L) / 10000L), /* freq = 113.31 MHz */ + } + , + + /* 1024x768 PANEL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PANEL, /* Panel Mode. */ + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + VG_MODEFLAG_PANELOUT | /* Panel output. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 1024, 768, /* No scaling. */ + 1024, 768, /* 1024x768 active. */ + 1024, 768, /* 1024x768 panel */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540, /* horiz timings */ + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (65L << 16) | ((0000L * 65536L) / 10000L), /* freq = 65.00 MHz */ + } + , + + /* 1152x864 */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1152, 864, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04C0, 0x0538, 0x05F0, 0x05F0, /* horiz timings */ + 0x0360, 0x0360, 0x0361, 0x0364, 0x037F, 0x037F, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (81L << 16) | ((6000L * 65536L) / 10000L), /* freq = 81.60 MHz */ + } + , + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1152, 864, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04C8, 0x0540, 0x0600, 0x0600, /* horiz timings */ + 0x0360, 0x0360, 0x0368, 0x036B, 0x038B, 0x038B, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (97L << 16) | ((5200L * 65536L) / 10000L), /* freq = 97.52 MHz */ + } + , + + {VG_SUPPORTFLAG_72HZ | /* refresh rate = 72 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1152, 864, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04C8, 0x0548, 0x0610, 0x0610, /* horiz timings */ + 0x0360, 0x0360, 0x0367, 0x036A, 0x038B, 0x038B, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (101L << 16) | ((4200L * 65536L) / 10000L), /* freq = 101.42 MHz */ + } + , + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1152, 864, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04C0, 0x0540, 0x0640, 0x0640, /* horiz timings */ + 0x0360, 0x0360, 0x0361, 0x0364, 0x0384, 0x0384, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (108L << 16) | ((0000L * 65536L) / 10000L), /* freq = 108.00 MHz */ + } + , + + {VG_SUPPORTFLAG_85HZ | /* refresh rate = 85 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1152, 864, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04C8, 0x0548, 0x0610, 0x0610, /* horiz timings */ + 0x0360, 0x0360, 0x0363, 0x0366, 0x038B, 0x038B, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (119L << 16) | ((6500L * 65536L) / 10000L), /* freq = 119.65 MHz */ + } + , + + {VG_SUPPORTFLAG_90HZ | /* refresh rate = 90 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1152, 864, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04D0, 0x0550, 0x0620, 0x0620, /* horiz timings */ + 0x0360, 0x0360, 0x0369, 0x036C, 0x0396, 0x0396, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (129L << 16) | ((6000L * 65536L) / 10000L), /* freq = 129.60 MHz */ + } + , + + {VG_SUPPORTFLAG_100HZ | /* refresh rate = 100 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1152, 864, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04D0, 0x0550, 0x0620, 0x0620, /* horiz timings */ + 0x0360, 0x0360, 0x0363, 0x0366, 0x0396, 0x0396, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (144L << 16) | ((0000L * 65536L) / 10000L), /* freq = 144.00 MHz */ + } + , + + /* 1152x864 PANEL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PANEL, /* Panel Mode. */ + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + VG_MODEFLAG_PANELOUT | /* Panel output. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 1152, 864, /* No scaling. */ + 1152, 864, /* 1152x864 active. */ + 1152, 864, /* 1152x864 panel. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0480, 0x0480, 0x04C0, 0x0538, 0x05F0, 0x05F0, /* horiz timings */ + 0x0360, 0x0360, 0x0361, 0x0364, 0x037F, 0x037F, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (81L << 16) | ((6000L * 65536L) / 10000L), /* freq = 81.60 MHz */ + } + , + + /* 1280x1024 */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1280, 1024, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0530, 0x05A0, 0x0698, 0x0698, /* horiz timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (108L << 16) | ((0000L * 65536L) / 10000L), /* freq = 108.00 MHz */ + } + , + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1280, 1024, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0558, 0x05E0, 0x06C0, 0x06C0, /* horiz timings */ + 0x0400, 0x0400, 0x0406, 0x0409, 0x042F, 0x042F, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (129L << 16) | ((6000L * 65536L) / 10000L), /* freq = 129.60 MHz */ + } + , + + {VG_SUPPORTFLAG_72HZ | /* refresh rate = 72 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1280, 1024, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0558, 0x05E0, 0x06C0, 0x06C0, /* horiz timings */ + 0x0400, 0x0400, 0x0407, 0x040A, 0x0431, 0x0431, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (133L << 16) | ((5000L * 65536L) / 10000L), /* freq = 133.50 MHz */ + } + , + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1280, 1024, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0510, 0x05A0, 0x0698, 0x0698, /* horiz timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (135L << 16) | ((0000L * 65536L) / 10000L), /* freq = 135.0 MHz */ + } + , + + {VG_SUPPORTFLAG_85HZ | /* refresh rate = 85 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1280, 1024, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0540, 0x05E0, 0x06C0, 0x06C0, /* horiz timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x0430, 0x0430, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (157L << 16) | ((5000L * 65536L) / 10000L), /* freq = 157.5 MHz */ + } + , + + {VG_SUPPORTFLAG_90HZ | /* refresh rate = 90 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1280, 1024, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0560, 0x05F0, 0x06E0, 0x06E0, /* horiz timings */ + 0x0400, 0x0400, 0x040C, 0x040F, 0x0442, 0x0442, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (172L << 16) | ((8000L * 65536L) / 10000L), /* freq = 172.80 MHz */ + } + , + + {VG_SUPPORTFLAG_100HZ | /* refresh rate = 100 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + 0, + 1280, 1024, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0560, 0x05F0, 0x06E0, 0x06E0, /* horiz timings */ + 0x0400, 0x0400, 0x0406, 0x0409, 0x0442, 0x0442, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (192L << 16) | ((0000L * 65536L) / 10000L), /* freq = 192.00 MHz */ + } + , + + /* 1280x1024 PANEL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PANEL, /* Panel Mode. */ + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + VG_MODEFLAG_PANELOUT | /* Panel output. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 1280, 1024, /* No scaling. */ + 1280, 1024, /* 1280x1024 active. */ + 1280, 1024, /* 1280x1024 panel */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0530, 0x05A0, 0x0698, 0x0698, /* horiz timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (108L << 16) | ((0000L * 65536L) / 10000L), /* freq = 108.00 MHz */ + } + , + + /* 1600 x 1200 */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1600, 1200, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, /* horiz timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (162L << 16) | ((0000L * 65536L) / 10000L), /* freq = 162.0 MHz */ + } + , + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1600, 1200, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, /* horiz timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (189L << 16) | ((0000L * 65536L) / 10000L), /* freq = 189.0 MHz */ + } + , + + {VG_SUPPORTFLAG_72HZ | /* refresh rate = 72 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1600, 1200, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x06B0, 0x0760, 0x0880, 0x0880, /* horiz timings */ + 0x04B0, 0x04B0, 0x04BD, 0x04C0, 0x04EF, 0x04EF, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (198L << 16) | ((0000L * 65536L) / 10000L), /* freq = 198.0 MHz */ + } + , + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1600, 1200, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, /* horiz timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (202L << 16) | ((5000L * 65536L) / 10000L), /* freq = 202.5 MHz */ + } + , + + {VG_SUPPORTFLAG_85HZ | /* refresh rate = 85 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1600, 1200, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, /* horiz timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (229L << 16) | ((5000L * 65536L) / 10000L), /* freq = 229.5 MHz */ + } + , + + {VG_SUPPORTFLAG_90HZ | /* refresh rate = 90 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1600, 1200, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x06C0, 0x0770, 0x08A0, 0x08A0, /* horiz timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04F0, 0x04F0, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (251L << 16) | ((1820L * 65536L) / 10000L), /* freq = 251.182 MHz */ + } + , + + {VG_SUPPORTFLAG_100HZ | /* refresh rate = 100 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1600, 1200, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x06C0, 0x0770, 0x08A0, 0x08A0, /* horiz timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04F7, 0x04F7, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (280L << 16) | ((6400L * 65536L) / 10000L), /* freq = 280.64 MHz */ + } + , + + /* 1600 x 1200 PANEL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PANEL, /* Panel Mode. */ + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + VG_MODEFLAG_PANELOUT | /* Panel output. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC, /* negative syncs */ + 1600, 1200, /* No scaling. */ + 1600, 1200, /* 1600x1200 Active. */ + 1600, 1200, /* 1600x1200 Panel. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, /* horiz timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (162L << 16) | ((0000L * 65536L) / 10000L), /* freq = 162.0 MHz */ + } + , + + /* 1920x1440 */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1920, 1440, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0780, 0x0780, 0x0800, 0x08D0, 0x0A28, 0x0A28, /* horiz timings */ + 0x05A0, 0x05A0, 0x05A1, 0x05A4, 0x05DC, 0x05DC, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (234L << 16) | ((0000L * 65536L) / 10000L), /* freq = 234.0 MHz */ + } + , + + {VG_SUPPORTFLAG_70HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1920, 1440, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0780, 0x0780, 0x0818, 0x08E8, 0x0A50, 0x0A50, /* horiz timings */ + 0x05A0, 0x05A0, 0x05A8, 0x05AB, 0x05E2, 0x05E2, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (278L << 16) | ((4000L * 65536L) / 10000L), /* freq = 278.4 MHz */ + } + , + + {VG_SUPPORTFLAG_72HZ | /* refresh rate = 70 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1920, 1440, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0780, 0x0780, 0x0818, 0x08E8, 0x0A50, 0x0A50, /* horiz timings */ + 0x05A0, 0x05A0, 0x05A4, 0x05A7, 0x05EB, 0x05EB, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (288L << 16) | ((0000L * 65536L) / 10000L), /* freq = 288.0 MHz */ + } + , + + {VG_SUPPORTFLAG_75HZ | /* refresh rate = 75 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1920, 1440, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0780, 0x0780, 0x0810, 0x08F0, 0x0A50, 0x0A50, /* horiz timings */ + 0x05A0, 0x05A0, 0x05A1, 0x05A4, 0x05DC, 0x05DC, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (297L << 16) | ((0000L * 65536L) / 10000L), /* freq = 297.0 MHz */ + } + , + + {VG_SUPPORTFLAG_85HZ | /* refresh rate = 85 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP + | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | + VG_SUPPORTFLAG_32BPP, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + 0, + 1920, 1440, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0780, 0x0780, 0x0818, 0x08F0, 0x0A60, 0x0A60, /* horiz timings */ + 0x05A0, 0x05A0, 0x05A1, 0x05A4, 0x05E8, 0x05E8, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings */ + (341L << 16) | ((3490L * 65536L) / 10000L), /* freq = 341.35 MHz */ + } + , + +/*-------------------------------*/ +/* PREDEFINED TV TIMINGS */ +/*-------------------------------*/ + + /* 720 x 480i NTSC */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_NTSC | /* NTSC Mode. */ + VG_SUPPORTFLAG_ADV7171 | VG_SUPPORTFLAG_SAA7127 | + VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT, + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_INTERLACED | VG_MODEFLAG_TVOUT | /* Interlaced TV output */ + VG_MODEFLAG_HALFCLOCK | /* DotPLL = 1/2 VOP */ + VG_MODEFLAG_INT_FLICKER, /* Flicker Filter Out */ + 720, 480, /* No downscaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x02D0, 0x02D0, 0x02E1, 0x0320, 0x035A, 0x035A, /* horiz timings */ + 0x00F0, 0x00F0, 0x00F4, 0x00F8, 0x0107, 0x0107, /* vertical timings */ + 0x00F0, 0x00F0, 0x00F4, 0x00F8, 0x0106, 0x0106, /*Even field timings */ + (27L << 16) | ((0000L * 65536L) / 10000L), /* freq = 27.0 MHz */ + } + , + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_NTSC | /* NTSC Mode. */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC | /* negative syncs */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* TFT Output. */ + 640, 480, /* No downscaling. */ + 640, 480, /* 640x480 active. */ + 640, 480, /* 640x480 panel. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0280, 0x0280, 0x0333, 0x0373, 0x03A8, 0x03A8, /* horiz timings */ + 0x01E0, 0x01E0, 0x01F5, 0x01F7, 0x020D, 0x020D, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (25L << 16) | ((1750L * 65536L) / 10000L), /* freq = 25.175 MHz */ + } + , + + /* 800 x 600 NTSC */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_8X6_NTSC | /* 800x600 NTSC. */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC | /* negative syncs */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* Panel output */ + 800, 600, /* No downscaling. */ + 800, 600, /* 800x600 active. */ + 800, 600, /* 800x600 active. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x03A7, 0x03E7, 0x03F0, 0x03F0, /* horiz timings */ + 0x0258, 0x0258, 0x026A, 0x0272, 0x028A, 0x028A, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (40L << 16) | ((0000L * 65536L) / 10000L), /* freq = 40.000 MHz */ + } + , + + /* 1024 x 768 NTSC */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_10X7_NTSC | /* 1024x768 NTSC. */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_AVG_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC | /* negative syncs */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* Panel output */ + 1024, 768, /* No downscaling. */ + 1024, 768, /* 1024x768 active. */ + 1024, 768, /* 1024x768 active. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0490, 0x04D0, 0x04E0, 0x04E0, /* horiz timings */ + 0x0300, 0x0300, 0x031B, 0x031D, 0x0339, 0x0339, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (65L << 16) | ((0000L * 65536L) / 10000L), /* freq = 65.00 MHz */ + } + , + + /* 720 x 576i PAL */ + + {VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PAL | /* PAL Mode. */ + VG_SUPPORTFLAG_ADV7171 | VG_SUPPORTFLAG_SAA7127 | VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_TVOUT | VG_MODEFLAG_INTERLACED | /* Interlaced TV out. */ + VG_MODEFLAG_HALFCLOCK | /* DotPLL = 1/2 VOP */ + VG_MODEFLAG_INT_FLICKER, /* Flicker Filter Out */ + 720, 576, /* No downscaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x02D0, 0x02D0, 0x02E4, 0x0324, 0x0360, 0x0360, /* horiz timings */ + 0x0120, 0x0120, 0x0123, 0x0127, 0x0139, 0x0139, /* vertical timings */ + 0x0120, 0x0120, 0x0123, 0x0127, 0x0138, 0x0138, /* Even timings */ + (27L << 16) | ((0000L * 65536L) / 10000L), /* freq = 27.0 MHz */ + } + , + + {VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_PAL | /* PAL Mode. */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC | /* negative syncs */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* Panel output */ + 640, 480, /* No downscaling. */ + 640, 480, /* No mode dimensions. */ + 640, 480, /* 640x480 active. */ + 0, 0, 0, 0, 0, /* 640x480 panel. */ + 0x0280, 0x0280, 0x030F, 0x034F, 0x0360, 0x0360, /* horiz timings */ + 0x01E0, 0x01E0, 0x01F5, 0x01F7, 0x020D, 0x020D, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (25L << 16) | ((1750L * 65536L) / 10000L), /* freq = 25.175 MHz */ + } + , + + /* 800 x 600 PAL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_8X6_PAL | /* 800x600 PAL. */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC | /* negative syncs */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* Panel output */ + 800, 600, /* No downscaling. */ + 800, 600, /* 800x600 active. */ + 800, 600, /* 800x600 active. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0320, 0x0320, 0x03A7, 0x03E7, 0x03F0, 0x03F0, /* horiz timings */ + 0x0258, 0x0258, 0x0270, 0x0272, 0x028A, 0x028A, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (40L << 16) | ((0000L * 65536L) / 10000L), /* freq = 40.000 MHz */ + } + , + + /* 1024 x 768 PAL */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_10X7_PAL | /* 1024x768 NTSC. */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_AVG_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_NEG_HSYNC | VG_MODEFLAG_NEG_VSYNC | /* negative syncs */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* Panel output */ + 1024, 768, /* No downscaling. */ + 1024, 768, /* 1024x768 active. */ + 1024, 768, /* 1024x768 active. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0400, 0x0400, 0x0490, 0x04d0, 0x04e0, 0x04e0, /* horiz timings */ + 0x0300, 0x0300, 0x031b, 0x031d, 0x0339, 0x0339, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (65L << 16) | ((0000L * 65536L) / 10000L), /* freq = 65.00 MHz */ + } + , + + /* 720 x 480p HDTV */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_480P | /* 720x480P. */ + VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_TVOUT, /* Progressive TV out. */ + 720, 480, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x02D0, 0x02D0, 0x02E0, 0x0328, 0x035A, 0x035A, /* horiz timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E3, 0x020D, 0x020D, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (27L << 16) | ((0000L * 65536L) / 10000L), /* freq = 27.0 MHz */ + } + , + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_480P | /* 720x480P. */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_LOW_BAND | /* Low bandwidth mode. */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* Panel output */ + 720, 480, /* No scaling. */ + 720, 480, /* 720x480 active. */ + 720, 480, /* 720x480 panel. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x02D0, 0x02D0, 0x02E3, 0x0323, 0x035A, 0x035A, /* horiz timings */ + 0x01E0, 0x01E0, 0x01E4, 0x01EA, 0x020D, 0x020D, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (27L << 16) | ((0000L * 65536L) / 10000L), /* freq = 27.0 MHz */ + } + , + + /* 1280x720p HDTV */ + + {VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_720P | /* 1280x720P */ + VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + VG_MODEFLAG_TVOUT, /* Progressive TV out */ + 1280, 720, /* No scaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0546, 0x0596, 0x0672, 0x0672, /* horiz timings */ + 0x02D0, 0x02D0, 0x02D3, 0x02D8, 0x02EE, 0x02EE, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* even timings */ + (74L << 16) | ((2500L * 65536L) / 10000L), /* freq = 74.25 MHz */ + } + , + + {VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_720P | /* 1280x720P */ + VG_SUPPORTFLAG_FS454 | VG_SUPPORTFLAG_TVOUT, /* TV Mode. */ + VG_MODEFLAG_AVG_BAND | /* Avg bandwidth mode. */ + VG_MODEFLAG_PANELOUT | VG_MODEFLAG_INVERT_SHFCLK, /* Panel output */ + 1280, 720, /* No scaling. */ + 1280, 720, /* 1280x720 active. */ + 1280, 720, /* 1280x720 panel. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0500, 0x0500, 0x0547, 0x0597, 0x0672, 0x0672, /* horiz timings */ + 0x02D0, 0x02D0, 0x02D4, 0x02D9, 0x02EE, 0x02EE, /* vertical timings */ + 0, 0, 0, 0, 0, 0, /* No even timings. */ + (74L << 16) | ((2500L * 65536L) / 10000L), /* freq = 74.25 MHz */ + } + , + + /* 1920x1080i HDTV */ + + {VG_SUPPORTFLAG_60HZ | /* refresh rate = 60 */ + VG_SUPPORTFLAG_8BPP | VG_SUPPORTFLAG_12BPP | VG_SUPPORTFLAG_15BPP | VG_SUPPORTFLAG_16BPP | VG_SUPPORTFLAG_24BPP | VG_SUPPORTFLAG_32BPP | VG_SUPPORTFLAG_1080I | /* 1920x1080i Mode. */ + VG_SUPPORTFLAG_ADV7300 | VG_SUPPORTFLAG_FS454 | + VG_SUPPORTFLAG_TVOUT, + VG_MODEFLAG_HIGH_BAND | /* High bandwidth mode. */ + VG_MODEFLAG_INTERLACED | VG_MODEFLAG_TVOUT | /* Interlaced TV out */ + /* Interlaced addressing */ + VG_MODEFLAG_INT_ADDRESS | VG_MODEFLAG_INVERT_SHFCLK, + 1920, 1080, /* 2:1 downscaling. */ + 0, 0, /* No mode dimensions. */ + 0, 0, /* No panel dimensions. */ + 0, 0, 0, 0, 0, /* No panel registers */ + 0x0780, 0x0780, 0x07AD, 0x0805, 0x0898, 0x0898, /* horiz timings */ + 0x021C, 0x021C, 0x021E, 0x0226, 0x0233, 0x0233, /* vertical timings */ + 0x021C, 0x021C, 0x021E, 0x0226, 0x0232, 0x0232, /*even field timings */ + (74L << 16) | ((2500L * 65536L) / 10000L), /* freq = 74.25 MHz */ + } + , +}; + +#define NUM_CIMARRON_DISPLAY_MODES sizeof(CimarronDisplayModes) / \ + sizeof(VG_DISPLAY_MODE) + +/*-----------------------------------*/ +/* PREDEFINED PLL FREQUENCIES */ +/*-----------------------------------*/ + +PLL_FREQUENCY CimarronPLLFrequencies[] = { + {0x000031AC, (24L << 16) | ((9230L * 65536L) / 10000L)} + , /* 24.9230, - 4,27,13 */ + {0x0000215D, (25L << 16) | ((1750L * 65536L) / 10000L)} + , /* 25.1750, - 3,22,14 */ + {0x00001087, (27L << 16) | ((0000L * 65536L) / 10000L)} + , /* 27.0000, - 2, 9, 8 */ + {0x0000216C, (28L << 16) | ((3220L * 65536L) / 10000L)} + , /* 28.3220, - 3,23,13 */ + {0x0000218D, (28L << 16) | ((5600L * 65536L) / 10000L)} + , /* 28.5600, - 3,25,14 */ + {0x000010C9, (31L << 16) | ((2000L * 65536L) / 10000L)} + , /* 31.2000, - 2,13,10 */ + {0x00003147, (31L << 16) | ((5000L * 65536L) / 10000L)} + , /* 31.5000, - 4,21, 8 */ + {0x000010A7, (33L << 16) | ((320L * 65536L) / 10000L)} + , /* 33.0320, - 2,11, 8 */ + {0x00002159, (35L << 16) | ((1120L * 65536L) / 10000L)} + , /* 35.1120, - 3,22,10 */ + {0x00004249, (35L << 16) | ((5000L * 65536L) / 10000L)} + , /* 35.5000, - 5,37,10 */ + {0x00000057, (36L << 16) | ((0000L * 65536L) / 10000L)} + , /* 36.0000, - 1, 6, 8 */ + {0x0000219A, (37L << 16) | ((8890L * 65536L) / 10000L)} + , /* 37.8890, - 3,26,11 */ + {0x00002158, (39L << 16) | ((1680L * 65536L) / 10000L)} + , /* 39.1680, - 3,22, 9 */ + {0x00000045, (40L << 16) | ((0000L * 65536L) / 10000L)} + , /* 40.0000, - 1, 5, 6 */ + {0x00000089, (43L << 16) | ((1630L * 65536L) / 10000L)} + , /* 43.1630, - 1, 9,10 */ + {0x000010E7, (44L << 16) | ((9000L * 65536L) / 10000L)} + , /* 44.9000, - 2,15, 8 */ + {0x00002136, (45L << 16) | ((7200L * 65536L) / 10000L)} + , /* 45.7200, - 3,20, 7 */ + {0x00003207, (49L << 16) | ((5000L * 65536L) / 10000L)} + , /* 49.5000, - 4,33, 8 */ + {0x00002187, (50L << 16) | ((0000L * 65536L) / 10000L)} + , /* 50.0000, - 3,25, 8 */ + {0x00004286, (56L << 16) | ((2500L * 65536L) / 10000L)} + , /* 56.2500, - 5,41, 7 */ + {0x000010E5, (60L << 16) | ((650L * 65536L) / 10000L)} + , /* 60.0650, - 2,15, 6 */ + {0x00004214, (65L << 16) | ((0000L * 65536L) / 10000L)} + , /* 65.0000, - 5,34, 5 */ + {0x00001105, (68L << 16) | ((1790L * 65536L) / 10000L)} + , /* 68.1790, - 2,17, 6 */ + {0x000031E4, (74L << 16) | ((2500L * 65536L) / 10000L)} + , /* 74.2500, - 4,31, 5 */ + {0x00003183, (75L << 16) | ((0000L * 65536L) / 10000L)} + , /* 75.0000, - 4,25, 4 */ + {0x00004284, (78L << 16) | ((7500L * 65536L) / 10000L)} + , /* 78.7500, - 5,41, 5 */ + {0x00001104, (81L << 16) | ((6000L * 65536L) / 10000L)} + , /* 81.6000, - 2,17, 5 */ + {0x00006363, (94L << 16) | ((5000L * 65536L) / 10000L)} + , /* 94.5000, - 7,55, 4 */ + {0x00005303, (97L << 16) | ((5200L * 65536L) / 10000L)} + , /* 97.5200, - 6,49, 4 */ + {0x00002183, (100L << 16) | ((1870L * 65536L) / 10000L)} + , /* 100.187, - 3,25, 4 */ + {0x00002122, (101L << 16) | ((4200L * 65536L) / 10000L)} + , /* 101.420, - 3,19, 3 */ + {0x00001081, (108L << 16) | ((0000L * 65536L) / 10000L)} + , /* 108.00, - 2, 9, 2 */ + {0x00006201, (113L << 16) | ((3100L * 65536L) / 10000L)} + , /* 113.31, - 7,33, 2 */ + {0x00000041, (119L << 16) | ((6500L * 65536L) / 10000L)} + , /* 119.65, - 1, 5, 2 */ + {0x000041A1, (129L << 16) | ((6000L * 65536L) / 10000L)} + , /* 129.60, - 5,27, 2 */ + {0x00002182, (133L << 16) | ((5000L * 65536L) / 10000L)} + , /* 133.50, - 3,25, 3 */ + {0x000041B1, (135L << 16) | ((0000L * 65536L) / 10000L)} + , /* 135.00, - 5,28, 2 */ + {0x00000051, (144L << 16) | ((0000L * 65536L) / 10000L)} + , /* 144.00, - 1, 6, 2 */ + {0x000041E1, (148L << 16) | ((5000L * 65536L) / 10000L)} + , /* 148.50, - 5,31, 2 */ + {0x000062D1, (157L << 16) | ((5000L * 65536L) / 10000L)} + , /* 157.50, - 7,46, 2 */ + {0x000031A1, (162L << 16) | ((0000L * 65536L) / 10000L)} + , /* 162.00, - 4,27, 2 */ + {0x00000061, (169L << 16) | ((2030L * 65536L) / 10000L)} + , /* 169.203, - 1, 7, 2 */ + {0x00004231, (172L << 16) | ((8000L * 65536L) / 10000L)} + , /* 172.800, - 5,36, 2 */ + {0x00002151, (175L << 16) | ((5000L * 65536L) / 10000L)} + , /* 175.50, - 3,22, 2 */ + {0x000052E1, (189L << 16) | ((0000L * 65536L) / 10000L)} + , /* 189.00, - 6,47, 2 */ + {0x00000071, (192L << 16) | ((0000L * 65536L) / 10000L)} + , /* 192.00, - 1, 8, 2 */ + {0x00003201, (198L << 16) | ((0000L * 65536L) / 10000L)} + , /* 198.00, - 4,33, 2 */ + {0x00004291, (202L << 16) | ((5000L * 65536L) / 10000L)} + , /* 202.50, - 5,42, 2 */ + {0x00001101, (204L << 16) | ((7500L * 65536L) / 10000L)} + , /* 204.75, - 2,17, 2 */ + {0x00007481, (218L << 16) | ((2500L * 65536L) / 10000L)} + , /* 218.25, - 8,73, 2 */ + {0x00004170, (229L << 16) | ((5000L * 65536L) / 10000L)} + , /* 229.50, - 5,24, 1 */ + {0x00006210, (234L << 16) | ((0000L * 65536L) / 10000L)} + , /* 234.00, - 7,34, 1 */ + {0x00003140, (251L << 16) | ((1820L * 65536L) / 10000L)} + , /* 251.182, - 4,21, 1 */ + {0x00006250, (261L << 16) | ((0000L * 65536L) / 10000L)} + , /* 261.00, - 7,38, 1 */ + {0x000041C0, (278L << 16) | ((4000L * 65536L) / 10000L)} + , /* 278.40, - 5,29, 1 */ + {0x00005220, (280L << 16) | ((6400L * 65536L) / 10000L)} + , /* 280.64, - 6,35, 1 */ + {0x00000050, (288L << 16) | ((0000L * 65536L) / 10000L)} + , /* 288.00, - 1, 6, 1 */ + {0x000041E0, (297L << 16) | ((0000L * 65536L) / 10000L)} + , /* 297.00, - 5,31, 1 */ + {0x00002130, (320L << 16) | ((2070L * 65536L) / 10000L)} + , /* 320.207, - 3,20, 1 */ + {0x00006310, (341L << 16) | ((3490L * 65536L) / 10000L)} + /* 341.349, - 7,50, 1 */ +}; + +#define NUM_CIMARRON_PLL_FREQUENCIES sizeof(CimarronPLLFrequencies) / \ + sizeof(PLL_FREQUENCY) + +/*-----------------------------------*/ +/* PREDEFINED FILTER COEFFICIENTS */ +/*-----------------------------------*/ + +unsigned long CimarronHorizontalGraphicsFilter[][2] = { + {0x1284A7D5, 0x000017D5}, /* -43, 297, 296, -43, 5 */ + {0x12A497D7, 0x000013D6}, /* -41, 293, 298, -42, 4 */ + {0x12D48BD7, 0x000013D6}, /* -41, 290, 301, -42, 4 */ + {0x13147FD7, 0x000013D5}, /* -41, 287, 305, -43, 4 */ + {0x133473D8, 0x000013D5}, /* -40, 284, 307, -43, 4 */ + {0x136467D8, 0x000013D5}, /* -40, 281, 310, -43, 4 */ + {0x13945FD8, 0x000013D4}, /* -40, 279, 313, -44, 4 */ + {0x13B453D9, 0x000013D4}, /* -39, 276, 315, -44, 4 */ + {0x13E447D9, 0x000013D4}, /* -39, 273, 318, -44, 4 */ + {0x14143BDA, 0x000013D3}, /* -38, 270, 321, -45, 4 */ + {0x143433DA, 0x000013D3}, /* -38, 268, 323, -45, 4 */ + {0x146427DA, 0x000013D3}, /* -38, 265, 326, -45, 4 */ + {0x14941BDB, 0x000013D2}, /* -37, 262, 329, -46, 4 */ + {0x14C40FDB, 0x000013D2}, /* -37, 259, 332, -46, 4 */ + {0x14F407DA, 0x000017D1}, /* -38, 257, 335, -47, 5 */ + {0x1503FBDC, 0x000013D2}, /* -36, 254, 336, -46, 4 */ + {0x1543F3DB, 0x000017D0}, /* -37, 252, 340, -48, 5 */ + {0x1563E3DD, 0x000013D1}, /* -35, 248, 342, -47, 4 */ + {0x1593D7DD, 0x000013D1}, /* -35, 245, 345, -47, 4 */ + {0x15B3CFDD, 0x000013D1}, /* -35, 243, 347, -47, 4 */ + {0x15E3C3DE, 0x000013D0}, /* -34, 240, 350, -48, 4 */ + {0x1613B7DE, 0x000013D0}, /* -34, 237, 353, -48, 4 */ + {0x1633ABDF, 0x000013D0}, /* -33, 234, 355, -48, 4 */ + {0x16639FDF, 0x000013D0}, /* -33, 231, 358, -48, 4 */ + {0x167397E0, 0x000013D0}, /* -32, 229, 359, -48, 4 */ + {0x16B38BE0, 0x000013CF}, /* -32, 226, 363, -49, 4 */ + {0x16E383DF, 0x000017CE}, /* -33, 224, 366, -50, 5 */ + {0x170373E1, 0x000013CF}, /* -31, 220, 368, -49, 4 */ + {0x17236BE1, 0x000013CF}, /* -31, 218, 370, -49, 4 */ + {0x17435FE2, 0x000013CF}, /* -30, 215, 372, -49, 4 */ + {0x177353E2, 0x000013CF}, /* -30, 212, 375, -49, 4 */ + {0x17B34BE1, 0x000017CD}, /* -31, 210, 379, -51, 5 */ + {0x17C33FE3, 0x000013CE}, /* -29, 207, 380, -50, 4 */ + {0x17F333E3, 0x000013CE}, /* -29, 204, 383, -50, 4 */ + {0x181327E4, 0x000013CE}, /* -28, 201, 385, -50, 4 */ + {0x18431FE3, 0x000017CD}, /* -29, 199, 388, -51, 5 */ + {0x186313E4, 0x000013CE}, /* -28, 196, 390, -50, 4 */ + {0x188307E5, 0x000013CE}, /* -27, 193, 392, -50, 4 */ + {0x18B2FBE5, 0x000013CE}, /* -27, 190, 395, -50, 4 */ + {0x18C2F3E6, 0x000013CE}, /* -26, 188, 396, -50, 4 */ + {0x18F2E7E6, 0x000013CE}, /* -26, 185, 399, -50, 4 */ + {0x1912DBE7, 0x000013CE}, /* -25, 182, 401, -50, 4 */ + {0x1952D3E6, 0x000017CC}, /* -26, 180, 405, -52, 5 */ + {0x1972CBE6, 0x000017CC}, /* -26, 178, 407, -52, 5 */ + {0x1992BFE7, 0x000017CC}, /* -25, 175, 409, -52, 5 */ + {0x19C2B3E7, 0x000017CC}, /* -25, 172, 412, -52, 5 */ + {0x19D2A7E9, 0x000013CD}, /* -23, 169, 413, -51, 4 */ + {0x1A029FE8, 0x000017CC}, /* -24, 167, 416, -52, 5 */ + {0x1A1293E9, 0x000013CE}, /* -23, 164, 417, -50, 4 */ + {0x1A3287EA, 0x000013CE}, /* -22, 161, 419, -50, 4 */ + {0x1A627FE9, 0x000017CD}, /* -23, 159, 422, -51, 5 */ + {0x1A7273EB, 0x000013CE}, /* -21, 156, 423, -50, 4 */ + {0x1AA267EB, 0x000013CE}, /* -21, 153, 426, -50, 4 */ + {0x1AC25FEB, 0x000013CE}, /* -21, 151, 428, -50, 4 */ + {0x1AE253EC, 0x000013CE}, /* -20, 148, 430, -50, 4 */ + {0x1B124BEB, 0x000017CD}, /* -21, 146, 433, -51, 5 */ + {0x1B223FED, 0x000013CE}, /* -19, 143, 434, -50, 4 */ + {0x1B5237EC, 0x000017CD}, /* -20, 141, 437, -51, 5 */ + {0x1B622BED, 0x000013CF}, /* -19, 138, 438, -49, 4 */ + {0x1B821FEE, 0x000013CF}, /* -18, 135, 440, -49, 4 */ + {0x1BA217EE, 0x000013CF}, /* -18, 133, 442, -49, 4 */ + {0x1BC20BEF, 0x000013CF}, /* -17, 130, 444, -49, 4 */ + {0x1BE203EF, 0x000013CF}, /* -17, 128, 446, -49, 4 */ + {0x1C01FBEE, 0x000017CF}, /* -18, 126, 448, -49, 5 */ + {0x1C11EFF0, 0x000013D0}, /* -16, 123, 449, -48, 4 */ + {0x1C41E7EF, 0x000017CF}, /* -17, 121, 452, -49, 5 */ + {0x1C61DFEF, 0x000017CF}, /* -17, 119, 454, -49, 5 */ + {0x1C61D3F1, 0x000013D1}, /* -15, 116, 454, -47, 4 */ + {0x1C91CBF0, 0x000017D0}, /* -16, 114, 457, -48, 5 */ + {0x1CA1BFF2, 0x000013D1}, /* -14, 111, 458, -47, 4 */ + {0x1CC1B3F2, 0x000013D2}, /* -14, 108, 460, -46, 4 */ + {0x1CE1AFF1, 0x000017D1}, /* -15, 107, 462, -47, 5 */ + {0x1CF1A3F3, 0x000013D2}, /* -13, 104, 463, -46, 4 */ + {0x1D1197F3, 0x000013D3}, /* -13, 101, 465, -45, 4 */ + {0x1D3197F2, 0x000013D2}, /* -14, 101, 467, -46, 4 */ + {0x1D518BF3, 0x000013D2}, /* -13, 98, 469, -46, 4 */ + {0x1D6183F3, 0x000013D3}, /* -13, 96, 470, -45, 4 */ + {0x1D817BF3, 0x000013D3}, /* -13, 94, 472, -45, 4 */ + {0x1D916FF4, 0x000013D4}, /* -12, 91, 473, -44, 4 */ + {0x1DB167F4, 0x000013D4}, /* -12, 89, 475, -44, 4 */ + {0x1DC15FF4, 0x000013D5}, /* -12, 87, 476, -43, 4 */ + {0x1DE153F5, 0x000013D5}, /* -11, 84, 478, -43, 4 */ + {0x1DF14BF5, 0x000013D6}, /* -11, 82, 479, -42, 4 */ + {0x1E1143F5, 0x000013D6}, /* -11, 80, 481, -42, 4 */ + {0x1E1137F7, 0x00000FD8}, /* -9, 77, 481, -40, 3 */ + {0x1E3133F6, 0x000013D7}, /* -10, 76, 483, -41, 4 */ + {0x1E412BF6, 0x000013D8}, /* -10, 74, 484, -40, 4 */ + {0x1E611FF7, 0x000013D8}, /* -9, 71, 486, -40, 4 */ + {0x1E7117F7, 0x000013D9}, /* -9, 69, 487, -39, 4 */ + {0x1E810FF7, 0x000013DA}, /* -9, 67, 488, -38, 4 */ + {0x1E9107F8, 0x000013DA}, /* -8, 65, 489, -38, 4 */ + {0x1EA0FFF8, 0x000013DB}, /* -8, 63, 490, -37, 4 */ + {0x1EB0F3F9, 0x00000FDD}, /* -7, 60, 491, -35, 3 */ + {0x1ED0EFF8, 0x000013DC}, /* -8, 59, 493, -36, 4 */ + {0x1EE0E7F9, 0x00000FDD}, /* -7, 57, 494, -35, 3 */ + {0x1EF0DFF9, 0x00000FDE}, /* -7, 55, 495, -34, 3 */ + {0x1F00D7F9, 0x00000FDF}, /* -7, 53, 496, -33, 3 */ + {0x1F10CFFA, 0x00000FDF}, /* -6, 51, 497, -33, 3 */ + {0x1F20C7FA, 0x00000FE0}, /* -6, 49, 498, -32, 3 */ + {0x1F20C3FA, 0x00000FE1}, /* -6, 48, 498, -31, 3 */ + {0x1F30BBFA, 0x00000FE2}, /* -6, 46, 499, -30, 3 */ + {0x1F40AFFB, 0x00000FE3}, /* -5, 43, 500, -29, 3 */ + {0x1F50A7FB, 0x00000FE4}, /* -5, 41, 501, -28, 3 */ + {0x1F60A3FB, 0x00000FE4}, /* -5, 40, 502, -28, 3 */ + {0x1F709BFB, 0x00000FE5}, /* -5, 38, 503, -27, 3 */ + {0x1F7093FC, 0x00000FE6}, /* -4, 36, 503, -26, 3 */ + {0x1F808FFC, 0x00000BE7}, /* -4, 35, 504, -25, 2 */ + {0x1F9087FC, 0x00000BE8}, /* -4, 33, 505, -24, 2 */ + {0x1F9083FC, 0x00000BE9}, /* -4, 32, 505, -23, 2 */ + {0x1FA077FD, 0x00000BEA}, /* -3, 29, 506, -22, 2 */ + {0x1FA073FD, 0x00000BEB}, /* -3, 28, 506, -21, 2 */ + {0x1FB06BFD, 0x00000BEC}, /* -3, 26, 507, -20, 2 */ + {0x1FC063FD, 0x00000BED}, /* -3, 24, 508, -19, 2 */ + {0x1FC05BFE, 0x00000BEE}, /* -2, 22, 508, -18, 2 */ + {0x1FC057FE, 0x00000BEF}, /* -2, 21, 508, -17, 2 */ + {0x1FD053FE, 0x000007F0}, /* -2, 20, 509, -16, 1 */ + {0x1FD04BFE, 0x000007F2}, /* -2, 18, 509, -14, 1 */ + {0x1FE043FE, 0x000007F3}, /* -2, 16, 510, -13, 1 */ + {0x1FE03BFF, 0x000007F4}, /* -1, 14, 510, -12, 1 */ + {0x1FE037FF, 0x000007F5}, /* -1, 13, 510, -11, 1 */ + {0x1FE033FF, 0x000007F6}, /* -1, 12, 510, -10, 1 */ + {0x1FF02BFF, 0x000007F7}, /* -1, 10, 511, -9, 1 */ + {0x1FF027FF, 0x000003F9}, /* -1, 9, 511, -7, 0 */ + {0x1FF01C00, 0x000003FA}, /* 0, 7, 511, -6, 0 */ + {0x1FF01800, 0x000003FB}, /* 0, 6, 511, -5, 0 */ + {0x1FF01400, 0x000003FC}, /* 0, 5, 511, -4, 0 */ + {0x1FF00C00, 0x000003FE}, /* 0, 3, 511, -2, 0 */ + {0x1FF00800, 0x000003FF}, /* 0, 2, 511, -1, 0 */ + {0x1FF00400, 0x00000000}, /* 0, 1, 511, 0, 0 */ + {0x1FFFFC00, 0x00000002}, /* 0, -1, 511, 2, 0 */ + {0x1FFFF800, 0x00000003}, /* 0, -2, 511, 3, 0 */ + {0x1FFFF000, 0x00000005}, /* 0, -4, 511, 5, 0 */ + {0x1FFFEC00, 0x00000006}, /* 0, -5, 511, 6, 0 */ + {0x1FFFE800, 0x00000007}, /* 0, -6, 511, 7, 0 */ + {0x1FFFE400, 0x000FFC09}, /* 0, -7, 511, 9, -1 */ + {0x1FFFDC01, 0x000FFC0A}, /* 1, -9, 511, 10, -1 */ + {0x1FEFDC01, 0x000FFC0B}, /* 1, -9, 510, 11, -1 */ + {0x1FEFD401, 0x000FFC0D}, /* 1, -11, 510, 13, -1 */ + {0x1FEFD001, 0x000FFC0E}, /* 1, -12, 510, 14, -1 */ + {0x1FEFCC01, 0x000FF810}, /* 1, -13, 510, 16, -2 */ + {0x1FDFCC01, 0x000FF811}, /* 1, -13, 509, 17, -2 */ + {0x1FDFC401, 0x000FF813}, /* 1, -15, 509, 19, -2 */ + {0x1FCFC002, 0x000FF814}, /* 2, -16, 508, 20, -2 */ + {0x1FCFB802, 0x000FF816}, /* 2, -18, 508, 22, -2 */ + {0x1FCFB402, 0x000FF418}, /* 2, -19, 508, 24, -3 */ + {0x1FBFB402, 0x000FF419}, /* 2, -19, 507, 25, -3 */ + {0x1FAFB002, 0x000FF41B}, /* 2, -20, 506, 27, -3 */ + {0x1FAFA802, 0x000FF41D}, /* 2, -22, 506, 29, -3 */ + {0x1F9FA802, 0x000FF01F}, /* 2, -22, 505, 31, -4 */ + {0x1F9FA402, 0x000FF020}, /* 2, -23, 505, 32, -4 */ + {0x1F8FA002, 0x000FF022}, /* 2, -24, 504, 34, -4 */ + {0x1F7F9803, 0x000FF024}, /* 3, -26, 503, 36, -4 */ + {0x1F7F9403, 0x000FEC26}, /* 3, -27, 503, 38, -5 */ + {0x1F6F9003, 0x000FEC28}, /* 3, -28, 502, 40, -5 */ + {0x1F5F9003, 0x000FEC29}, /* 3, -28, 501, 41, -5 */ + {0x1F4F8C03, 0x000FEC2B}, /* 3, -29, 500, 43, -5 */ + {0x1F3F8C03, 0x000FE82D}, /* 3, -29, 499, 45, -6 */ + {0x1F2F8803, 0x000FE82F}, /* 3, -30, 498, 47, -6 */ + {0x1F2F8003, 0x000FE831}, /* 3, -32, 498, 49, -6 */ + {0x1F1F7C03, 0x000FE833}, /* 3, -33, 497, 51, -6 */ + {0x1F0F7C03, 0x000FE435}, /* 3, -33, 496, 53, -7 */ + {0x1EFF7803, 0x000FE437}, /* 3, -34, 495, 55, -7 */ + {0x1EEF7403, 0x000FE439}, /* 3, -35, 494, 57, -7 */ + {0x1EDF7004, 0x000FE03B}, /* 4, -36, 493, 59, -8 */ + {0x1EBF7403, 0x000FE43C}, /* 3, -35, 491, 60, -7 */ + {0x1EAF6C04, 0x000FE03F}, /* 4, -37, 490, 63, -8 */ + {0x1E9F6804, 0x000FE041}, /* 4, -38, 489, 65, -8 */ + {0x1E8F6804, 0x000FDC43}, /* 4, -38, 488, 67, -9 */ + {0x1E7F6404, 0x000FDC45}, /* 4, -39, 487, 69, -9 */ + {0x1E6F6004, 0x000FDC47}, /* 4, -40, 486, 71, -9 */ + {0x1E4F6404, 0x000FD849}, /* 4, -39, 484, 73, -10 */ + {0x1E3F6004, 0x000FD84B}, /* 4, -40, 483, 75, -10 */ + {0x1E1F6003, 0x000FDC4D}, /* 3, -40, 481, 77, -9 */ + {0x1E1F5804, 0x000FD450}, /* 4, -42, 481, 80, -11 */ + {0x1DFF5804, 0x000FD452}, /* 4, -42, 479, 82, -11 */ + {0x1DEF5404, 0x000FD454}, /* 4, -43, 478, 84, -11 */ + {0x1DCF5804, 0x000FD056}, /* 4, -42, 476, 86, -12 */ + {0x1DBF5004, 0x000FD059}, /* 4, -44, 475, 89, -12 */ + {0x1D9F5004, 0x000FD05B}, /* 4, -44, 473, 91, -12 */ + {0x1D8F5004, 0x000FCC5D}, /* 4, -44, 472, 93, -13 */ + {0x1D6F5004, 0x000FCC5F}, /* 4, -44, 470, 95, -13 */ + {0x1D5F4804, 0x000FCC62}, /* 4, -46, 469, 98, -13 */ + {0x1D3F4C04, 0x000FC864}, /* 4, -45, 467, 100, -14 */ + {0x1D1F4C04, 0x000FCC65}, /* 4, -45, 465, 101, -13 */ + {0x1CFF4804, 0x000FCC68}, /* 4, -46, 463, 104, -13 */ + {0x1CEF4405, 0x000FC46B}, /* 5, -47, 462, 107, -15 */ + {0x1CCF4804, 0x000FC86C}, /* 4, -46, 460, 108, -14 */ + {0x1CAF4404, 0x000FC86F}, /* 4, -47, 458, 111, -14 */ + {0x1C9F4005, 0x000FC072}, /* 5, -48, 457, 114, -16 */ + {0x1C6F4404, 0x000FC474}, /* 4, -47, 454, 116, -15 */ + {0x1C6F3C05, 0x000FBC77}, /* 5, -49, 454, 119, -17 */ + {0x1C4F3C05, 0x000FBC79}, /* 5, -49, 452, 121, -17 */ + {0x1C1F4004, 0x000FC07B}, /* 4, -48, 449, 123, -16 */ + {0x1C0F3C05, 0x000FB87E}, /* 5, -49, 448, 126, -18 */ + {0x1BEF3C04, 0x000FBC80}, /* 4, -49, 446, 128, -17 */ + {0x1BCF3C04, 0x000FBC82}, /* 4, -49, 444, 130, -17 */ + {0x1BAF3C04, 0x000FB885}, /* 4, -49, 442, 133, -18 */ + {0x1B8F3C04, 0x000FB887}, /* 4, -49, 440, 135, -18 */ + {0x1B6F3C04, 0x000FB48A}, /* 4, -49, 438, 138, -19 */ + {0x1B5F3405, 0x000FB08D}, /* 5, -51, 437, 141, -20 */ + {0x1B2F3804, 0x000FB48F}, /* 4, -50, 434, 143, -19 */ + {0x1B1F3405, 0x000FAC92}, /* 5, -51, 433, 146, -21 */ + {0x1AEF3804, 0x000FB094}, /* 4, -50, 430, 148, -20 */ + {0x1ACF3804, 0x000FAC97}, /* 4, -50, 428, 151, -21 */ + {0x1AAF3804, 0x000FAC99}, /* 4, -50, 426, 153, -21 */ + {0x1A7F3804, 0x000FAC9C}, /* 4, -50, 423, 156, -21 */ + {0x1A6F3405, 0x000FA49F}, /* 5, -51, 422, 159, -23 */ + {0x1A3F3804, 0x000FA8A1}, /* 4, -50, 419, 161, -22 */ + {0x1A1F3804, 0x000FA4A4}, /* 4, -50, 417, 164, -23 */ + {0x1A0F3005, 0x000FA0A7}, /* 5, -52, 416, 167, -24 */ + {0x19DF3404, 0x000FA4A9}, /* 4, -51, 413, 169, -23 */ + {0x19CF3005, 0x000F9CAC}, /* 5, -52, 412, 172, -25 */ + {0x199F3005, 0x000F9CAF}, /* 5, -52, 409, 175, -25 */ + {0x197F3005, 0x000F98B2}, /* 5, -52, 407, 178, -26 */ + {0x195F3005, 0x000F98B4}, /* 5, -52, 405, 180, -26 */ + {0x191F3804, 0x000F9CB6}, /* 4, -50, 401, 182, -25 */ + {0x18FF3804, 0x000F98B9}, /* 4, -50, 399, 185, -26 */ + {0x18CF3804, 0x000F98BC}, /* 4, -50, 396, 188, -26 */ + {0x18BF3804, 0x000F94BE}, /* 4, -50, 395, 190, -27 */ + {0x188F3804, 0x000F94C1}, /* 4, -50, 392, 193, -27 */ + {0x186F3804, 0x000F90C4}, /* 4, -50, 390, 196, -28 */ + {0x184F3405, 0x000F8CC7}, /* 5, -51, 388, 199, -29 */ + {0x181F3804, 0x000F90C9}, /* 4, -50, 385, 201, -28 */ + {0x17FF3804, 0x000F8CCC}, /* 4, -50, 383, 204, -29 */ + {0x17CF3804, 0x000F8CCF}, /* 4, -50, 380, 207, -29 */ + {0x17BF3405, 0x000F84D2}, /* 5, -51, 379, 210, -31 */ + {0x177F3C04, 0x000F88D4}, /* 4, -49, 375, 212, -30 */ + {0x174F3C04, 0x000F88D7}, /* 4, -49, 372, 215, -30 */ + {0x172F3C04, 0x000F84DA}, /* 4, -49, 370, 218, -31 */ + {0x170F3C04, 0x000F84DC}, /* 4, -49, 368, 220, -31 */ + {0x16EF3805, 0x000F7CE0}, /* 5, -50, 366, 224, -33 */ + {0x16BF3C04, 0x000F80E2}, /* 4, -49, 363, 226, -32 */ + {0x167F4004, 0x000F80E5}, /* 4, -48, 359, 229, -32 */ + {0x166F4004, 0x000F7CE7}, /* 4, -48, 358, 231, -33 */ + {0x163F4004, 0x000F7CEA}, /* 4, -48, 355, 234, -33 */ + {0x161F4004, 0x000F78ED}, /* 4, -48, 353, 237, -34 */ + {0x15EF4004, 0x000F78F0}, /* 4, -48, 350, 240, -34 */ + {0x15BF4404, 0x000F74F3}, /* 4, -47, 347, 243, -35 */ + {0x159F4404, 0x000F74F5}, /* 4, -47, 345, 245, -35 */ + {0x156F4404, 0x000F74F8}, /* 4, -47, 342, 248, -35 */ + {0x154F4005, 0x000F6CFC}, /* 5, -48, 340, 252, -37 */ + {0x150F4804, 0x000F70FE}, /* 4, -46, 336, 254, -36 */ + {0x14FF4405, 0x000F6901}, /* 5, -47, 335, 257, -38 */ + {0x14CF4804, 0x000F6D03}, /* 4, -46, 332, 259, -37 */ + {0x149F4804, 0x000F6D06}, /* 4, -46, 329, 262, -37 */ + {0x146F4C04, 0x000F6909}, /* 4, -45, 326, 265, -38 */ + {0x143F4C04, 0x000F690C}, /* 4, -45, 323, 268, -38 */ + {0x141F4C04, 0x000F690E}, /* 4, -45, 321, 270, -38 */ + {0x13EF5004, 0x000F6511}, /* 4, -44, 318, 273, -39 */ + {0x13BF5004, 0x000F6514}, /* 4, -44, 315, 276, -39 */ + {0x139F5004, 0x000F6117}, /* 4, -44, 313, 279, -40 */ + {0x136F5404, 0x000F6119}, /* 4, -43, 310, 281, -40 */ + {0x133F5404, 0x000F611C}, /* 4, -43, 307, 284, -40 */ + {0x131F5404, 0x000F5D1F}, /* 4, -43, 305, 287, -41 */ + {0x12DF5C04, 0x000F5D21}, /* 4, -41, 301, 289, -41 */ + {0x12AF5C04, 0x000F5D24}, /* 4, -41, 298, 292, -41 */ +}; + +unsigned long CimarronVerticalGraphicsFilter[] = { + 0x3F840D05, /* 261, 259, -8 */ + 0x3F841D01, /* 257, 263, -8 */ + 0x3F8428FE, /* 254, 266, -8 */ + 0x3F8438FA, /* 250, 270, -8 */ + 0x3F8444F7, /* 247, 273, -8 */ + 0x3F8450F4, /* 244, 276, -8 */ + 0x3F845CF1, /* 241, 279, -8 */ + 0x3F8468EE, /* 238, 282, -8 */ + 0x3F8474EB, /* 235, 285, -8 */ + 0x3F8480E8, /* 232, 288, -8 */ + 0x3F7490E5, /* 229, 292, -9 */ + 0x3F749CE2, /* 226, 295, -9 */ + 0x3F74ACDE, /* 222, 299, -9 */ + 0x3F74B8DB, /* 219, 302, -9 */ + 0x3F74C0D9, /* 217, 304, -9 */ + 0x3F74CCD6, /* 214, 307, -9 */ + 0x3F74D8D3, /* 211, 310, -9 */ + 0x3F74E8CF, /* 207, 314, -9 */ + 0x3F74F4CC, /* 204, 317, -9 */ + 0x3F7500C9, /* 201, 320, -9 */ + 0x3F750CC6, /* 198, 323, -9 */ + 0x3F7518C3, /* 195, 326, -9 */ + 0x3F7520C1, /* 193, 328, -9 */ + 0x3F7530BD, /* 189, 332, -9 */ + 0x3F753CBA, /* 186, 335, -9 */ + 0x3F7548B7, /* 183, 338, -9 */ + 0x3F6558B4, /* 180, 342, -10 */ + 0x3F6560B2, /* 178, 344, -10 */ + 0x3F656CAF, /* 175, 347, -10 */ + 0x3F6578AC, /* 172, 350, -10 */ + 0x3F6584A9, /* 169, 353, -10 */ + 0x3F658CA7, /* 167, 355, -10 */ + 0x3F6598A4, /* 164, 358, -10 */ + 0x3F65A8A0, /* 160, 362, -10 */ + 0x3F65B09E, /* 158, 364, -10 */ + 0x3F65BC9B, /* 155, 367, -10 */ + 0x3F65C499, /* 153, 369, -10 */ + 0x3F65D096, /* 150, 372, -10 */ + 0x3F55E093, /* 147, 376, -11 */ + 0x3F55E891, /* 145, 378, -11 */ + 0x3F55F48E, /* 142, 381, -11 */ + 0x3F56008B, /* 139, 384, -11 */ + 0x3F560C88, /* 136, 387, -11 */ + 0x3F561486, /* 134, 389, -11 */ + 0x3F562083, /* 131, 392, -11 */ + 0x3F562881, /* 129, 394, -11 */ + 0x3F56347E, /* 126, 397, -11 */ + 0x3F56407B, /* 123, 400, -11 */ + 0x3F564879, /* 121, 402, -11 */ + 0x3F465876, /* 118, 406, -12 */ + 0x3F466074, /* 116, 408, -12 */ + 0x3F466872, /* 114, 410, -12 */ + 0x3F46746F, /* 111, 413, -12 */ + 0x3F467C6D, /* 109, 415, -12 */ + 0x3F46846B, /* 107, 417, -12 */ + 0x3F468C69, /* 105, 419, -12 */ + 0x3F469866, /* 102, 422, -12 */ + 0x3F46A064, /* 100, 424, -12 */ + 0x3F46AC61, /* 97, 427, -12 */ + 0x3F46B45F, /* 95, 429, -12 */ + 0x3F46BC5D, /* 93, 431, -12 */ + 0x3F46C45B, /* 91, 433, -12 */ + 0x3F46CC59, /* 89, 435, -12 */ + 0x3F36DC56, /* 86, 439, -13 */ + 0x3F36E454, /* 84, 441, -13 */ + 0x3F36EC52, /* 82, 443, -13 */ + 0x3F36F450, /* 80, 445, -13 */ + 0x3F36FC4E, /* 78, 447, -13 */ + 0x3F37004D, /* 77, 448, -13 */ + 0x3F370C4A, /* 74, 451, -13 */ + 0x3F371448, /* 72, 453, -13 */ + 0x3F371C46, /* 70, 455, -13 */ + 0x3F372444, /* 68, 457, -13 */ + 0x3F372C42, /* 66, 459, -13 */ + 0x3F373440, /* 64, 461, -13 */ + 0x3F37383F, /* 63, 462, -13 */ + 0x3F37403D, /* 61, 464, -13 */ + 0x3F37483B, /* 59, 466, -13 */ + 0x3F375039, /* 57, 468, -13 */ + 0x3F375438, /* 56, 469, -13 */ + 0x3F375C36, /* 54, 471, -13 */ + 0x3F376434, /* 52, 473, -13 */ + 0x3F376833, /* 51, 474, -13 */ + 0x3F377031, /* 49, 476, -13 */ + 0x3F377430, /* 48, 477, -13 */ + 0x3F377C2E, /* 46, 479, -13 */ + 0x3F37842C, /* 44, 481, -13 */ + 0x3F37882B, /* 43, 482, -13 */ + 0x3F47882A, /* 42, 482, -12 */ + 0x3F479028, /* 40, 484, -12 */ + 0x3F479427, /* 39, 485, -12 */ + 0x3F479C25, /* 37, 487, -12 */ + 0x3F47A024, /* 36, 488, -12 */ + 0x3F47A822, /* 34, 490, -12 */ + 0x3F47AC21, /* 33, 491, -12 */ + 0x3F47B020, /* 32, 492, -12 */ + 0x3F57B01F, /* 31, 492, -11 */ + 0x3F57B81D, /* 29, 494, -11 */ + 0x3F57BC1C, /* 28, 495, -11 */ + 0x3F57C01B, /* 27, 496, -11 */ + 0x3F57C41A, /* 26, 497, -11 */ + 0x3F67C818, /* 24, 498, -10 */ + 0x3F67CC17, /* 23, 499, -10 */ + 0x3F67D016, /* 22, 500, -10 */ + 0x3F67D415, /* 21, 501, -10 */ + 0x3F67D814, /* 20, 502, -10 */ + 0x3F77D813, /* 19, 502, -9 */ + 0x3F77DC12, /* 18, 503, -9 */ + 0x3F77E011, /* 17, 504, -9 */ + 0x3F87E010, /* 16, 504, -8 */ + 0x3F87E40F, /* 15, 505, -8 */ + 0x3F87E80E, /* 14, 506, -8 */ + 0x3F97E80D, /* 13, 506, -7 */ + 0x3F97EC0C, /* 12, 507, -7 */ + 0x3F97F00B, /* 11, 508, -7 */ + 0x3FA7F00A, /* 10, 508, -6 */ + 0x3FA7F409, /* 9, 509, -6 */ + 0x3FB7F408, /* 8, 509, -5 */ + 0x3FB7F408, /* 8, 509, -5 */ + 0x3FC7F806, /* 6, 510, -4 */ + 0x3FC7F806, /* 6, 510, -4 */ + 0x3FD7F805, /* 5, 510, -3 */ + 0x3FD7FC04, /* 4, 511, -3 */ + 0x3FE7FC03, /* 3, 511, -2 */ + 0x3FE7FC03, /* 3, 511, -2 */ + 0x3FF7FC02, /* 2, 511, -1 */ + 0x3FF7FC02, /* 2, 511, -1 */ + 0x0007FC01, /* 1, 511, 0 */ + 0x0007FC01, /* 1, 511, 0 */ + 0x0007FC01, /* 1, 511, 0 */ + 0x0027FFFF, /* -1, 511, 2 */ + 0x0027FFFF, /* -1, 511, 2 */ + 0x0037FFFE, /* -2, 511, 3 */ + 0x0037FFFE, /* -2, 511, 3 */ + 0x0047FFFD, /* -3, 511, 4 */ + 0x0047FBFE, /* -2, 510, 4 */ + 0x0057FBFD, /* -3, 510, 5 */ + 0x0067FBFC, /* -4, 510, 6 */ + 0x0077F7FC, /* -4, 509, 7 */ + 0x0077F7FC, /* -4, 509, 7 */ + 0x0087F7FB, /* -5, 509, 8 */ + 0x0097F3FB, /* -5, 508, 9 */ + 0x00A7F3FA, /* -6, 508, 10 */ + 0x00B7EFFA, /* -6, 507, 11 */ + 0x00C7EBFA, /* -6, 506, 12 */ + 0x00D7EBF9, /* -7, 506, 13 */ + 0x00E7E7F9, /* -7, 505, 14 */ + 0x00F7E3F9, /* -7, 504, 15 */ + 0x0107E3F8, /* -8, 504, 16 */ + 0x0117DFF8, /* -8, 503, 17 */ + 0x0127DBF8, /* -8, 502, 18 */ + 0x0137DBF7, /* -9, 502, 19 */ + 0x0147D7F7, /* -9, 501, 20 */ + 0x0157D3F7, /* -9, 500, 21 */ + 0x0167CFF7, /* -9, 499, 22 */ + 0x0177CBF7, /* -9, 498, 23 */ + 0x0197C7F6, /* -10, 497, 25 */ + 0x01A7C3F6, /* -10, 496, 26 */ + 0x01B7BFF6, /* -10, 495, 27 */ + 0x01C7BBF6, /* -10, 494, 28 */ + 0x01E7B3F6, /* -10, 492, 30 */ + 0x01F7B3F5, /* -11, 492, 31 */ + 0x0207AFF5, /* -11, 491, 32 */ + 0x0217ABF5, /* -11, 490, 33 */ + 0x0237A3F5, /* -11, 488, 35 */ + 0x02479FF5, /* -11, 487, 36 */ + 0x026797F5, /* -11, 485, 38 */ + 0x027793F5, /* -11, 484, 39 */ + 0x02978BF5, /* -11, 482, 41 */ + 0x02A78BF4, /* -12, 482, 42 */ + 0x02B787F4, /* -12, 481, 43 */ + 0x02D77FF4, /* -12, 479, 45 */ + 0x02F777F4, /* -12, 477, 47 */ + 0x030773F4, /* -12, 476, 48 */ + 0x03276BF4, /* -12, 474, 50 */ + 0x033767F4, /* -12, 473, 51 */ + 0x03575FF4, /* -12, 471, 53 */ + 0x037757F4, /* -12, 469, 55 */ + 0x038753F4, /* -12, 468, 56 */ + 0x03A74BF4, /* -12, 466, 58 */ + 0x03C743F4, /* -12, 464, 60 */ + 0x03E73BF4, /* -12, 462, 62 */ + 0x040737F3, /* -13, 461, 64 */ + 0x04272FF3, /* -13, 459, 66 */ + 0x044727F3, /* -13, 457, 68 */ + 0x04671FF3, /* -13, 455, 70 */ + 0x048717F3, /* -13, 453, 72 */ + 0x04A70FF3, /* -13, 451, 74 */ + 0x04C703F4, /* -12, 448, 76 */ + 0x04D6FFF4, /* -12, 447, 77 */ + 0x04F6F7F4, /* -12, 445, 79 */ + 0x0516EFF4, /* -12, 443, 81 */ + 0x0536E7F4, /* -12, 441, 83 */ + 0x0556DFF4, /* -12, 439, 85 */ + 0x0586CFF5, /* -11, 435, 88 */ + 0x05A6C7F5, /* -11, 433, 90 */ + 0x05C6BFF5, /* -11, 431, 92 */ + 0x05F6B7F4, /* -12, 429, 95 */ + 0x0616AFF4, /* -12, 427, 97 */ + 0x0636A3F5, /* -11, 424, 99 */ + 0x06569BF5, /* -11, 422, 101 */ + 0x06868FF5, /* -11, 419, 104 */ + 0x06A687F5, /* -11, 417, 106 */ + 0x06C67FF5, /* -11, 415, 108 */ + 0x06E677F5, /* -11, 413, 110 */ + 0x07166BF5, /* -11, 410, 113 */ + 0x073663F5, /* -11, 408, 115 */ + 0x07665BF4, /* -12, 406, 118 */ + 0x07964BF5, /* -11, 402, 121 */ + 0x07B643F5, /* -11, 400, 123 */ + 0x07D637F6, /* -10, 397, 125 */ + 0x08062BF6, /* -10, 394, 128 */ + 0x082623F6, /* -10, 392, 130 */ + 0x085617F6, /* -10, 389, 133 */ + 0x08760FF6, /* -10, 387, 135 */ + 0x08B603F5, /* -11, 384, 139 */ + 0x08D5F7F6, /* -10, 381, 141 */ + 0x0905EBF6, /* -10, 378, 144 */ + 0x0925E3F6, /* -10, 376, 146 */ + 0x0955D3F7, /* -9, 372, 149 */ + 0x0985C7F7, /* -9, 369, 152 */ + 0x09A5BFF7, /* -9, 367, 154 */ + 0x09D5B3F7, /* -9, 364, 157 */ + 0x0A05ABF6, /* -10, 362, 160 */ + 0x0A359BF7, /* -9, 358, 163 */ + 0x0A658FF7, /* -9, 355, 166 */ + 0x0A9587F6, /* -10, 353, 169 */ + 0x0AB57BF7, /* -9, 350, 171 */ + 0x0AE56FF7, /* -9, 347, 174 */ + 0x0B1563F7, /* -9, 344, 177 */ + 0x0B455BF6, /* -10, 342, 180 */ + 0x0B754BF7, /* -9, 338, 183 */ + 0x0BA53FF7, /* -9, 335, 186 */ + 0x0BD533F7, /* -9, 332, 189 */ + 0x0C0523F8, /* -8, 328, 192 */ + 0x0C251BF8, /* -8, 326, 194 */ + 0x0C550FF8, /* -8, 323, 197 */ + 0x0C9503F7, /* -9, 320, 201 */ + 0x0CC4F7F7, /* -9, 317, 204 */ + 0x0CF4EBF7, /* -9, 314, 207 */ + 0x0D24DBF8, /* -8, 310, 210 */ + 0x0D54CFF8, /* -8, 307, 213 */ + 0x0D84C3F8, /* -8, 304, 216 */ + 0x0DB4BBF7, /* -9, 302, 219 */ + 0x0DE4AFF7, /* -9, 299, 222 */ + 0x0E149FF8, /* -8, 295, 225 */ + 0x0E4493F8, /* -8, 292, 228 */ + 0x0E7483F9, /* -7, 288, 231 */ + 0x0EA477F9, /* -7, 285, 234 */ + 0x0ED46BF9, /* -7, 282, 237 */ + 0x0F045FF9, /* -7, 279, 240 */ + 0x0F4453F8, /* -8, 276, 244 */ + 0x0F7447F8, /* -8, 273, 247 */ + 0x0FA43BF8, /* -8, 270, 250 */ + 0x0FD42BF9, /* -7, 266, 253 */ + 0x10041FF9, /* -7, 263, 256 */ +}; diff --git a/src/cim/cim_msr.c b/src/cim/cim_msr.c new file mode 100644 index 0000000..9e46a87 --- /dev/null +++ b/src/cim/cim_msr.c @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron MSR access routines. These routines allow the user to query the + * state of the GeodeLink Bus and read and write model-specfic registers. + */ + +/*--------------------------------------------------------------*/ +/* MSR GLOBALS */ +/* These variables hold a local copy of the GeodeLink mapping */ +/* as well as a lookup table for easy device addressing. */ +/*--------------------------------------------------------------*/ + +GEODELINK_NODE gliu_nodes[24]; +GEODELINK_NODE msr_dev_lookup[MSR_DEVICE_EMPTY]; + +#define GET_DEVICE_ID(macrohigh, macrolow) ((macrolow >> 12) & 0xFF) + +/*--------------------------------------------------------------------------- + * msr_init_table + * + * This routine intializes the internal MSR table in Cimarron. This table is + * used for any MSR device accesses. + *--------------------------------------------------------------------------*/ + +int +msr_init_table(void) +{ + Q_WORD msr_value; + unsigned int i, j; + int return_value = CIM_STATUS_OK; + + /* CHECK FOR VALID GEODELINK CONFIGURATION + * The CPU and the three GLIUs are assumed to be at known static + * addresses, so we will check the device IDs at these addresses as proof + * of a valid GeodeLink configuration + */ + + MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_VAIL, &msr_value); + if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_VAIL) + return_value = CIM_STATUS_ERROR; + + MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU0, &msr_value); + if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) + return_value = CIM_STATUS_ERROR; + + MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU1, &msr_value); + if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) + return_value = CIM_STATUS_ERROR; + + MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU2, &msr_value); + if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) + return_value = CIM_STATUS_ERROR; + + if (return_value == CIM_STATUS_OK) { + /* BUILD LOCAL COPY OF THE GEODELINK BUS */ + + msr_create_geodelink_table(gliu_nodes); + + /* CLEAR TABLE STATUS */ + + for (i = 0; i < MSR_DEVICE_EMPTY; i++) + msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; + + /* CREATE EASY LOOKUP TABLE FOR FUTURE HARDWARE ACCESS */ + /* Note that MSR_DEVICE_EMPTY is the index after the last */ + /* available device. Also note that we fill in known */ + /* devices before filling in the rest of the table. */ + + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].address_from_cpu = + MSR_ADDRESS_GLIU0; + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].device_id = + MSR_DEVICE_PRESENT; + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].address_from_cpu = + MSR_ADDRESS_GLIU1; + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].device_id = + MSR_DEVICE_PRESENT; + msr_dev_lookup[MSR_DEVICE_5535_GLIU].address_from_cpu = + MSR_ADDRESS_GLIU2; + msr_dev_lookup[MSR_DEVICE_5535_GLIU].device_id = MSR_DEVICE_PRESENT; + msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].address_from_cpu = + MSR_ADDRESS_VAIL; + msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].device_id = + MSR_DEVICE_PRESENT; + + for (i = 0; i < MSR_DEVICE_EMPTY; i++) { + if (msr_dev_lookup[i].device_id == MSR_DEVICE_NOTFOUND) { + for (j = 0; j < 24; j++) { + if (gliu_nodes[j].device_id == i) + break; + } + + if (j == 24) + msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; + else { + msr_dev_lookup[i].device_id = MSR_DEVICE_PRESENT; + msr_dev_lookup[i].address_from_cpu = + gliu_nodes[j].address_from_cpu; + } + } + } + } else { + /* ERROR OUT THE GEODELINK TABLES */ + + for (i = 0; i < 24; i++) { + gliu_nodes[i].address_from_cpu = 0xFFFFFFFF; + gliu_nodes[i].device_id = MSR_DEVICE_EMPTY; + } + + for (i = 0; i < MSR_DEVICE_EMPTY; i++) { + msr_dev_lookup[i].address_from_cpu = 0xFFFFFFFF; + msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; + } + } + return return_value; +} + +/*--------------------------------------------------------------------------- + * msr_create_geodelink_table + * + * This routine dumps the contents of the GeodeLink bus into an array of + * 24 GEODELINK_NODE structures. Indexes 0-7 represent ports 0-7 of GLIU0, + * indexes 8-15 represent ports 0-7 of GLIU1 and indexes 16-23 represent + * ports 0-7 of GLIU2 (5535). + *--------------------------------------------------------------------------*/ + +int +msr_create_geodelink_table(GEODELINK_NODE * gliu_nodes) +{ + unsigned long mbiu_port_count, reflective; + unsigned long port, index; + unsigned long gliu_count = 0; + int glcp_count = 0; + int usb_count = 0; + int mpci_count = 0; + Q_WORD msr_value; + + /* ALL THREE GLIUS ARE IN ONE ARRAY */ + /* Entries 0-7 contain the port information for GLIU0, entries */ + /* 8-15 contain GLIU1 and 15-23 contain GLIU2. We perform the */ + /* enumeration in two passes. The first simply fills in the */ + /* addresses and class codes at each node. The second pass */ + /* translates the class codes into indexes into Cimarron's device */ + /* lookup table. */ + + /* COUNT GLIU0 PORTS */ + + MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU0, &msr_value); + mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; + + /* FIND REFLECTIVE PORT */ + /* Query the GLIU for the port through which we are communicating. */ + /* We will avoid accesses to this port to avoid a self-reference. */ + + MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU0, &msr_value); + reflective = msr_value.low & WHOAMI_MASK; + + /* SPECIAL CASE FOR PORT 0 */ + /* GLIU0 port 0 is a special case, as it points back to GLIU0. GLIU0 */ + /* responds at address 0x10000xxx, which does not equal 0 << 29. */ + + gliu_nodes[0].address_from_cpu = MSR_ADDRESS_GLIU0; + gliu_nodes[0].device_id = MSR_CLASS_CODE_GLIU; + + /* ENUMERATE ALL PORTS */ + + for (port = 1; port < 8; port++) { + /* FILL IN ADDRESS */ + + gliu_nodes[port].address_from_cpu = port << 29; + + if (port == reflective) + gliu_nodes[port].device_id = MSR_CLASS_CODE_REFLECTIVE; + else if (port > mbiu_port_count) + gliu_nodes[port].device_id = MSR_CLASS_CODE_UNPOPULATED; + else { + MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[port].address_from_cpu, + &msr_value); + gliu_nodes[port].device_id = + GET_DEVICE_ID(msr_value.high, msr_value.low); + } + } + + /* COUNT GLIU1 PORTS */ + + MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU1, &msr_value); + mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; + + /* FIND REFLECTIVE PORT */ + + MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU1, &msr_value); + reflective = msr_value.low & WHOAMI_MASK; + + /* ENUMERATE ALL PORTS */ + + for (port = 0; port < 8; port++) { + index = port + 8; + + /* FILL IN ADDRESS */ + + gliu_nodes[index].address_from_cpu = (0x02l << 29) + (port << 26); + + if (port == reflective) + gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; + else if (port > mbiu_port_count) + gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; + else { + MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, + &msr_value); + gliu_nodes[index].device_id = + GET_DEVICE_ID(msr_value.high, msr_value.low); + } + } + + /* COUNT GLIU2 PORTS */ + + MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU2, &msr_value); + mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; + + /* FIND REFLECTIVE PORT */ + + MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU2, &msr_value); + reflective = msr_value.low & WHOAMI_MASK; + + /* FILL IN PORT 0 AND 1 */ + /* Port 0 on 5535 is MBIU2. Port 1 is MPCI, but it is referenced at */ + /* a special address. */ + + gliu_nodes[16].address_from_cpu = MSR_ADDRESS_GLIU2; + gliu_nodes[16].device_id = MSR_CLASS_CODE_GLIU; + + gliu_nodes[17].address_from_cpu = MSR_ADDRESS_5535MPCI; + gliu_nodes[17].device_id = MSR_CLASS_CODE_MPCI; + + /* ENUMERATE ALL PORTS */ + + for (port = 2; port < 8; port++) { + index = port + 16; + + /* FILL IN ADDRESS */ + + gliu_nodes[index].address_from_cpu = + (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); + + if (port == reflective) + gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; + else if (port > mbiu_port_count) + gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; + else { + MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, + &msr_value); + gliu_nodes[index].device_id = + GET_DEVICE_ID(msr_value.high, msr_value.low); + } + } + + /* SECOND PASS - TRANSLATION */ + /* Now that the class codes for each device are stored in the */ + /* array, we walk through the array and translate the class */ + /* codes to table indexes. For class codes that have multiple */ + /* instances, the table indexes are sequential. */ + + for (port = 0; port < 24; port++) { + /* SPECIAL CASE FOR GLIU UNITS */ + /* A GLIU can be both on another port and on its own port. These */ + /* end up as the same address, but are shown as duplicate nodes in */ + /* the GeodeLink table. */ + + if ((port & 7) == 0) + gliu_count = port >> 3; + + switch (gliu_nodes[port].device_id) { + /* UNPOPULATED OR REFLECTIVE NODES */ + + case MSR_CLASS_CODE_UNPOPULATED: + index = MSR_DEVICE_EMPTY; + break; + case MSR_CLASS_CODE_REFLECTIVE: + index = MSR_DEVICE_REFLECTIVE; + break; + + /* KNOWN CLASS CODES */ + + case MSR_CLASS_CODE_GLIU: + index = MSR_DEVICE_GEODELX_GLIU0 + gliu_count++; + break; + case MSR_CLASS_CODE_GLCP: + index = MSR_DEVICE_GEODELX_GLCP + glcp_count++; + break; + case MSR_CLASS_CODE_MPCI: + index = MSR_DEVICE_GEODELX_MPCI + mpci_count++; + break; + case MSR_CLASS_CODE_USB: + index = MSR_DEVICE_5535_USB2 + usb_count++; + break; + case MSR_CLASS_CODE_USB2: + index = MSR_DEVICE_5536_USB_2_0; + break; + case MSR_CLASS_CODE_ATAC: + index = MSR_DEVICE_5535_ATAC; + break; + case MSR_CLASS_CODE_MDD: + index = MSR_DEVICE_5535_MDD; + break; + case MSR_CLASS_CODE_ACC: + index = MSR_DEVICE_5535_ACC; + break; + case MSR_CLASS_CODE_MC: + index = MSR_DEVICE_GEODELX_MC; + break; + case MSR_CLASS_CODE_GP: + index = MSR_DEVICE_GEODELX_GP; + break; + case MSR_CLASS_CODE_VG: + index = MSR_DEVICE_GEODELX_VG; + break; + case MSR_CLASS_CODE_DF: + index = MSR_DEVICE_GEODELX_DF; + break; + case MSR_CLASS_CODE_FG: + index = MSR_DEVICE_GEODELX_FG; + break; + case MSR_CLASS_CODE_VIP: + index = MSR_DEVICE_GEODELX_VIP; + break; + case MSR_CLASS_CODE_AES: + index = MSR_DEVICE_GEODELX_AES; + break; + case MSR_CLASS_CODE_VAIL: + index = MSR_DEVICE_GEODELX_VAIL; + break; + default: + index = MSR_DEVICE_EMPTY; + break; + } + + gliu_nodes[port].device_id = index; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * msr_create_device_list + * + * This routine dumps a list of all known GeodeLX/5535 devices as well as their + * respective status and address. + *--------------------------------------------------------------------------*/ + +int +msr_create_device_list(GEODELINK_NODE * gliu_nodes, int max_devices) +{ + int i, count; + + if (max_devices < MSR_DEVICE_EMPTY) + count = max_devices; + else + count = MSR_DEVICE_EMPTY; + + for (i = 0; i < count; i++) { + gliu_nodes[i].address_from_cpu = msr_dev_lookup[i].address_from_cpu; + gliu_nodes[i].device_id = msr_dev_lookup[i].device_id; + } + + return CIM_STATUS_OK; +} + +/*-------------------------------------------------------------------- + * msr_read64 + * + * Performs a 64-bit read from 'msr_register' in device 'device'. 'device' is + * an index into Cimarron's table of known GeodeLink devices. + *-------------------------------------------------------------------*/ + +int +msr_read64(unsigned long device, unsigned long msr_register, + Q_WORD * msr_value) +{ + if (device < MSR_DEVICE_EMPTY) { + if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) { + MSR_READ(msr_register, msr_dev_lookup[device].address_from_cpu, + msr_value); + return CIM_STATUS_OK; + } + } + + msr_value->low = msr_value->high = 0; + return CIM_STATUS_DEVNOTFOUND; +} + +/*-------------------------------------------------------------------- + * msr_write64 + * + * Performs a 64-bit write to 'msr_register' in device 'device'. 'device' is + * an index into Cimarron's table of known GeodeLink devices. + *-------------------------------------------------------------------*/ + +int +msr_write64(unsigned long device, unsigned long msr_register, + Q_WORD * msr_value) +{ + if (device < MSR_DEVICE_EMPTY) { + if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) { + MSR_WRITE(msr_register, msr_dev_lookup[device].address_from_cpu, + msr_value); + return CIM_STATUS_OK; + } + } + return CIM_STATUS_DEVNOTFOUND; +} diff --git a/src/cim/cim_parm.h b/src/cim/cim_parm.h new file mode 100644 index 0000000..ed1df8b --- /dev/null +++ b/src/cim/cim_parm.h @@ -0,0 +1,1284 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron user definitions. + */ + +#ifndef _cim_parm_h +#define _cim_parm_h + +/*===================================================*/ +/* CIMARRON RETURN VALUE DEFINITIONS */ +/*===================================================*/ + +#define CIM_STATUS_OK 0x00000000 +#define CIM_STATUS_ERROR 0x00000001 +#define CIM_STATUS_INVALIDPARAMS 0x00000002 +#define CIM_STATUS_DEVNOTFOUND 0x00000004 +#define CIM_STATUS_INVALIDSCALE 0x00000008 +#define CIM_STATUS_INEXACTMATCH 0x00000010 +#define CIM_STATUS_NOLOCK 0x00000020 +#define CIM_STATUS_CPUNOTFOUND 0x00000040 +#define CIM_STATUS_DISPLAYUNAVAILABLE 0x00000080 +#define CIM_STATUS_NOTFOUND 0x00000100 + +/*===================================================*/ +/* CIMARRON CPU DEFINITIONS */ +/*===================================================*/ + +#define CIM_CPU_GEODEGX 0x00000001 +#define CIM_CPU_GEODELX 0x00000002 + +#define CIM_SB_5535 0x00000001 +#define CIM_SB_5536 0x00000002 + +/*===================================================*/ +/* MSR PARAMETERS */ +/*===================================================*/ + +/*-------------------------------------------------------------*/ +/* GEODELINK DEVICE IDS */ +/* These values uniquely identify all known GeodeLink devices */ +/* in GeodeLX and its companion, 5535/6. For multiple devices */ +/* of the same class (GLIU, USB, etc.) the table order is used */ +/* to to identify the expected device order, in terms of on */ +/* which GLIU the device is found, and on which port. */ +/*-------------------------------------------------------------*/ + +#define MSR_DEVICE_GEODELX_GLIU0 0x00 +#define MSR_DEVICE_GEODELX_GLIU1 0x01 +#define MSR_DEVICE_5535_GLIU 0x02 +#define MSR_DEVICE_GEODELX_GLCP 0x03 +#define MSR_DEVICE_5535_GLCP 0x04 +#define MSR_DEVICE_GEODELX_MPCI 0x05 +#define MSR_DEVICE_5535_MPCI 0x06 +#define MSR_DEVICE_GEODELX_MC 0x07 +#define MSR_DEVICE_GEODELX_GP 0x08 +#define MSR_DEVICE_GEODELX_VG 0x09 +#define MSR_DEVICE_GEODELX_VIP 0x0A +#define MSR_DEVICE_GEODELX_AES 0x0B +#define MSR_DEVICE_GEODELX_DF 0x0C +#define MSR_DEVICE_GEODELX_FG 0x0D +#define MSR_DEVICE_GEODELX_VAIL 0x0E +#define MSR_DEVICE_5536_USB_2_0 0x0F +#define MSR_DEVICE_5535_USB2 0x10 +#define MSR_DEVICE_5535_USB1 0x11 +#define MSR_DEVICE_5535_ATAC 0x12 +#define MSR_DEVICE_5535_MDD 0x13 +#define MSR_DEVICE_5535_ACC 0x14 +#define MSR_DEVICE_EMPTY 0x15 +#define MSR_DEVICE_REFLECTIVE 0x16 +#define MSR_DEVICE_PRESENT 0x17 +#define MSR_DEVICE_NOTFOUND 0x18 + +/*---------------------------------------------*/ +/* GEODELINK TABLE ENTRY */ +/* The following structure represents one port */ +/* on a GeodeLink Interface Unit (GLIU) */ +/*---------------------------------------------*/ + +typedef struct tagGeodeLinkNode +{ + unsigned long address_from_cpu; + unsigned long device_id; + +} GEODELINK_NODE; + +/*---------------------------------------------*/ +/* QWORD DATA STRUCTURE */ +/* 64-bit data structure for MSR acess. */ +/*---------------------------------------------*/ + +typedef struct tagQ_WORD +{ + unsigned long high; + unsigned long low; + +} Q_WORD; + +/*===================================================*/ +/* INITIALIZATION USER PARAMETERS */ +/*===================================================*/ + +typedef struct tagInitBaseAddresses +{ + unsigned long framebuffer_base; + unsigned long gp_register_base; + unsigned long vg_register_base; + unsigned long df_register_base; + unsigned long vip_register_base; + unsigned long framebuffer_size; + +} INIT_BASE_ADDRESSES; + +/*===================================================*/ +/* GP USER PARAMETER DEFINITIONS */ +/*===================================================*/ + +/*---------------------------*/ +/* GP_DECLARE_BLT PARAMETERS */ +/*---------------------------*/ + +#define CIMGP_BLTFLAGS_PRES_LUT 0x0001 +#define CIMGP_BLTFLAGS_PRES_COLOR_PAT 0x0002 +#define CIMGP_ENABLE_PREFETCH 0x0004 +#define CIMGP_BLTFLAGS_HAZARD 0x0008 +#define CIMGP_BLTFLAGS_INVERTMONO 0x0010 +#define CIMGP_BLTFLAGS_LIMITBUFFER 0x0020 + +/*-----------------------------------*/ +/* GP_SET_ALPHA_OPERATION PARAMETERS */ +/*-----------------------------------*/ + +#define CIMGP_APPLY_BLEND_TO_RGB 1 +#define CIMGP_APPLY_BLEND_TO_ALPHA 2 +#define CIMGP_APPLY_BLEND_TO_ALL 3 + +#define CIMGP_ALPHA_TIMES_A 0 +#define CIMGP_BETA_TIMES_B 1 +#define CIMGP_A_PLUS_BETA_B 2 +#define CIMGP_ALPHA_A_PLUS_BETA_B 3 + +#define CIMGP_CHANNEL_A_ALPHA 0 +#define CIMGP_CHANNEL_B_ALPHA 1 +#define CIMGP_CONSTANT_ALPHA 2 +#define CIMGP_ALPHA_EQUALS_ONE 3 +#define CIMGP_ALPHA_FROM_RGB_A 4 +#define CIMGP_ALPHA_FROM_RGB_B 5 +#define CIMGP_CONVERTED_ALPHA 6 + +#define CIMGP_CHANNEL_A_SOURCE 0 +#define CIMGP_CHANNEL_A_DEST 1 + +/*---------------------------------*/ +/* GP_SET_SOURCE_FORMAT PARAMETERS */ +/*---------------------------------*/ + +#define CIMGP_SOURCE_FMT_3_3_2 0x00 +#define CIMGP_SOURCE_FMT_8BPP_INDEXED 0x01 +#define CIMGP_SOURCE_FMT_4_4_4_4 0x04 +#define CIMGP_SOURCE_FMT_12BPP_BGR 0x14 +#define CIMGP_SOURCE_FMT_1_5_5_5 0x05 +#define CIMGP_SOURCE_FMT_15BPP_BGR 0x15 +#define CIMGP_SOURCE_FMT_0_5_6_5 0x06 +#define CIMGP_SOURCE_FMT_16BPP_BGR 0x16 +#define CIMGP_SOURCE_FMT_YUYV 0x07 +#define CIMGP_SOURCE_FMT_UYVY 0x17 +#define CIMGP_SOURCE_FMT_8_8_8_8 0x08 +#define CIMGP_SOURCE_FMT_32BPP_BGR 0x18 +#define CIMGP_SOURCE_FMT_24BPP 0x0B +#define CIMGP_SOURCE_FMT_4BPP_INDEXED 0x0D + +/*------------------------------------*/ +/* GP_SCREEN_TO_SCREEN_BLT PARAMETERS */ +/*------------------------------------*/ + +#define CIMGP_NEGXDIR 1 +#define CIMGP_NEGYDIR 2 + +/*------------------------------------*/ +/* GP_BRESENHAM_LINE PARAMETERS */ +/*------------------------------------*/ + +#define CIMGP_YMAJOR 1 +#define CIMGP_POSMAJOR 2 +#define CIMGP_POSMINOR 4 + +/*----------------------------------------------*/ +/* USER STRUCTURE FOR SAVING/RESTORING GP STATE */ +/*----------------------------------------------*/ + +typedef struct tagGPSaveRestore +{ + unsigned long base_offset; + unsigned long cmd_top; + unsigned long cmd_bottom; + unsigned long cmd_base; + unsigned long cmd_read; + +} GP_SAVE_RESTORE; + +/*===================================================*/ +/* VG USER PARAMETER DEFINITIONS */ +/*===================================================*/ + +/*-------------------------------------------*/ +/* SUPPORTED TV ENCODERS */ +/*-------------------------------------------*/ + +#define VG_ENCODER_ADV7171 0x0001 +#define VG_ENCODER_SAA7127 0x0002 +#define VG_ENCODER_FS454 0x0003 +#define VG_ENCODER_ADV7300 0x0004 + +/*-------------------------------------------*/ +/* SUPPORTED TV RESOLUTIONS */ +/*-------------------------------------------*/ + +#define VG_TVMODE_NTSC 0x00000000 +#define VG_TVMODE_PAL 0x00000001 +#define VG_TVMODE_480P 0x00000002 +#define VG_TVMODE_720P 0x00000003 +#define VG_TVMODE_1080I 0x00000004 +#define VG_TVMODE_6X4_NTSC 0x00000005 +#define VG_TVMODE_8X6_NTSC 0x00000006 +#define VG_TVMODE_10X7_NTSC 0x00000007 +#define VG_TVMODE_6X4_PAL 0x00000008 +#define VG_TVMODE_8X6_PAL 0x00000009 +#define VG_TVMODE_10X7_PAL 0x0000000A + +/*-------------------------------------------*/ +/* USER STRUCTURE FOR SETTING A DISPLAY MODE */ +/*-------------------------------------------*/ + +#define VG_SUPPORTFLAG_8BPP 0x00000001 +#define VG_SUPPORTFLAG_12BPP 0x00000002 +#define VG_SUPPORTFLAG_15BPP 0x00000004 +#define VG_SUPPORTFLAG_16BPP 0x00000008 +#define VG_SUPPORTFLAG_24BPP 0x00000010 +#define VG_SUPPORTFLAG_32BPP 0x00000020 +#define VG_SUPPORTFLAG_56HZ 0x00000040 +#define VG_SUPPORTFLAG_60HZ 0x00000080 +#define VG_SUPPORTFLAG_70HZ 0x00000100 +#define VG_SUPPORTFLAG_72HZ 0x00000200 +#define VG_SUPPORTFLAG_75HZ 0x00000400 +#define VG_SUPPORTFLAG_85HZ 0x00000800 +#define VG_SUPPORTFLAG_90HZ 0x00001000 +#define VG_SUPPORTFLAG_100HZ 0x00002000 +#define VG_SUPPORTFLAG_HZMASK 0x00003FC0 +#define VG_SUPPORTFLAG_ADV7171 0x00004000 +#define VG_SUPPORTFLAG_SAA7127 0x00008000 +#define VG_SUPPORTFLAG_FS454 0x00010000 +#define VG_SUPPORTFLAG_ADV7300 0x00020000 +#define VG_SUPPORTFLAG_ENCODERMASK 0x0003C000 +#define VG_SUPPORTFLAG_PANEL 0x00040000 +#define VG_SUPPORTFLAG_TVOUT 0x00080000 +#define VG_SUPPORTFLAG_NTSC 0x00000000 +#define VG_SUPPORTFLAG_PAL 0x00100000 +#define VG_SUPPORTFLAG_480P 0x00200000 +#define VG_SUPPORTFLAG_720P 0x00300000 +#define VG_SUPPORTFLAG_1080I 0x00400000 +#define VG_SUPPORTFLAG_6X4_NTSC 0x00500000 +#define VG_SUPPORTFLAG_8X6_NTSC 0x00600000 +#define VG_SUPPORTFLAG_10X7_NTSC 0x00700000 +#define VG_SUPPORTFLAG_6X4_PAL 0x00800000 +#define VG_SUPPORTFLAG_8X6_PAL 0x00900000 +#define VG_SUPPORTFLAG_10X7_PAL 0x00A00000 +#define VG_SUPPORTFLAG_TVMODEMASK 0x00F00000 + +#define VG_MODEFLAG_NEG_HSYNC 0x00000001 +#define VG_MODEFLAG_NEG_VSYNC 0x00000002 +#define VG_MODEFLAG_INTERLACED 0x00000004 +#define VG_MODEFLAG_PANELOUT 0x00000008 +#define VG_MODEFLAG_CENTERED 0x00000010 +#define VG_MODEFLAG_LINEARPITCH 0x00000020 +#define VG_MODEFLAG_TVOUT 0x00000040 +#define VG_MODEFLAG_HALFCLOCK 0x00000080 +#define VG_MODEFLAG_QVGA 0x00000100 +#define VG_MODEFLAG_EXCLUDEPLL 0x00000200 +#define VG_MODEFLAG_NOPANELTIMINGS 0x00000400 +#define VG_MODEFLAG_XVGA_TFT 0x00000800 +#define VG_MODEFLAG_CUSTOM_PANEL 0x00001000 +#define VG_MODEFLAG_CRT_AND_FP 0x00002000 +#define VG_MODEFLAG_LOW_BAND 0x00000000 +#define VG_MODEFLAG_AVG_BAND 0x00004000 +#define VG_MODEFLAG_HIGH_BAND 0x00008000 +#define VG_MODEFLAG_LEGACY_BAND 0x0000C000 +#define VG_MODEFLAG_BANDWIDTHMASK 0x0000C000 +#define VG_MODEFLAG_OVERRIDE_BAND 0x00010000 +#define VG_MODEFLAG_INT_ADDRESS 0x00000000 +#define VG_MODEFLAG_INT_LINEDOUBLE 0x00020000 +#define VG_MODEFLAG_INT_FLICKER 0x00040000 +#define VG_MODEFLAG_INT_MASK 0x00060000 +#define VG_MODEFLAG_INT_OVERRIDE 0x00080000 +#define VG_MODEFLAG_INVERT_SHFCLK 0x00100000 +#define VG_MODEFLAG_MANUAL_FREQUENCY 0x00200000 +#define VG_MODEFLAG_PLL_BYPASS 0x00400000 +#define VG_MODEFLAG_VIP_TO_DOT_CLOCK 0x00800000 + +#define VG_MODEFLAG_VALIDUSERFLAGS (VG_MODEFLAG_CRT_AND_FP | \ + VG_MODEFLAG_XVGA_TFT | \ + VG_MODEFLAG_NOPANELTIMINGS | \ + VG_MODEFLAG_EXCLUDEPLL | \ + VG_MODEFLAG_LINEARPITCH) + +typedef struct tagVGDisplayMode +{ + /* DISPLAY MODE FLAGS */ + /* Includes BPP, refresh rate information, interlacing, etc. */ + + unsigned long internal_flags; + unsigned long flags; + + /* SOURCE RESOLUTION */ + /* The following values reflect the resolution of the data in the frame */ + /* buffer. These values are used to enable scaling and filtering. */ + + unsigned long src_width; + unsigned long src_height; + + /* PANEL SETTINGS + * These allow a user to set a panel mode through the vg_set_custom_mode + * routine. These values are only relevant if the VG_MODEFLAG_PANEL is + * also set. + */ + + unsigned long mode_width; + unsigned long mode_height; + unsigned long panel_width; + unsigned long panel_height; + unsigned long panel_tim1; + unsigned long panel_tim2; + unsigned long panel_dither_ctl; + unsigned long panel_pad_sel_low; + unsigned long panel_pad_sel_high; + + /* OUTPUT TIMINGS */ + /* If the active width and height do not match the source */ + /* dimensions the graphics data will be scaled. */ + + unsigned long hactive; + unsigned long hblankstart; + unsigned long hsyncstart; + unsigned long hsyncend; + unsigned long hblankend; + unsigned long htotal; + + unsigned long vactive; + unsigned long vblankstart; + unsigned long vsyncstart; + unsigned long vsyncend; + unsigned long vblankend; + unsigned long vtotal; + + unsigned long vactive_even; + unsigned long vblankstart_even; + unsigned long vsyncstart_even; + unsigned long vsyncend_even; + unsigned long vblankend_even; + unsigned long vtotal_even; + + /* CLOCK FREQUENCY */ + + unsigned long frequency; + +} VG_DISPLAY_MODE; + +/*-------------------------------------------*/ +/* PLL FLAGS */ +/*-------------------------------------------*/ + +#define VG_PLL_DIVIDE_BY_2 0x00000001 +#define VG_PLL_DIVIDE_BY_4 0x00000002 +#define VG_PLL_BYPASS 0x00000004 +#define VG_PLL_MANUAL 0x00000008 +#define VG_PLL_VIP_CLOCK 0x00000010 + +/*-------------------------------------------*/ +/* USER STRUCTURE FOR QUERYING DISPLAY MODES */ +/*-------------------------------------------*/ + +typedef struct tagQueryDisplayMode +{ + int interlaced; + int halfclock; + unsigned long active_width; + unsigned long active_height; + unsigned long panel_width; + unsigned long panel_height; + unsigned long total_width; + unsigned long total_height; + unsigned long bpp; + unsigned long hz; + unsigned long frequency; + unsigned long query_flags; + unsigned long encoder; + unsigned long tvmode; + +} VG_QUERY_MODE; + +/*-------------------------------------------*/ +/* USER STRUCTURE FOR QUERYING CURSOR DATA */ +/*-------------------------------------------*/ + +typedef struct tagCursorData +{ + int enable; + int color_cursor; + unsigned long cursor_offset; + unsigned long cursor_x; + unsigned long cursor_y; + unsigned long clipx; + unsigned long clipy; + unsigned long mono_color0; + unsigned long mono_color1; + unsigned long flags; + +} VG_CURSOR_DATA; + +/*------------------------------------------------*/ +/* VG INTERRUPT STATUS SOURCES */ +/*------------------------------------------------*/ + +#define VG_INT_LINE_MATCH 0x00010000 +#define VG_INT_VSYNC_LOSS 0x00020000 + +/*------------------------------------------------*/ +/* USER STRUCTURE FOR SETTING COMPRESSION DATA */ +/*------------------------------------------------*/ + +typedef struct tagCompressionData +{ + unsigned long compression_offset; + unsigned long pitch; + unsigned long size; + unsigned long flags; + +} VG_COMPRESSION_DATA; + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING LINE INTERRUPTS */ +/*-------------------------------------------------*/ + +typedef struct tagInterruptInfo +{ + unsigned long line; + unsigned long flags; + int enable; + +} VG_INTERRUPT_PARAMS; + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR PANNING THE DESKTOP */ +/*-------------------------------------------------*/ + +typedef struct tagPanningInfo +{ + unsigned long start_x; + unsigned long start_y; + int start_updated; + +} VG_PANNING_COORDINATES; + +/*--------------------------------------------------*/ +/* USER STRUCTURE FOR SAVING/RESTORING THE VG STATE */ +/*--------------------------------------------------*/ + +typedef struct tagVGSaveRestore +{ + /* VG REGISTERS */ + + unsigned long unlock; + unsigned long gcfg; + unsigned long dcfg; + unsigned long arb_cfg; + unsigned long fb_offset; + unsigned long cb_offset; + unsigned long cursor_offset; + unsigned long video_y_offset; + unsigned long video_u_offset; + unsigned long video_v_offset; + unsigned long dv_top; + unsigned long line_size; + unsigned long gfx_pitch; + unsigned long video_yuv_pitch; + unsigned long h_active; + unsigned long h_blank; + unsigned long h_sync; + unsigned long v_active; + unsigned long v_blank; + unsigned long v_sync; + unsigned long fb_active; + unsigned long cursor_x; + unsigned long cursor_y; + unsigned long vid_ds_delta; + unsigned long fb_base; + unsigned long dv_ctl; + unsigned long gfx_scale; + unsigned long irq_ctl; + unsigned long vbi_even_ctl; + unsigned long vbi_odd_ctl; + unsigned long vbi_hor_ctl; + unsigned long vbi_odd_line_enable; + unsigned long vbi_even_line_enable; + unsigned long vbi_pitch; + unsigned long color_key; + unsigned long color_key_mask; + unsigned long color_key_x; + unsigned long color_key_y; + unsigned long irq; + unsigned long genlk_ctl; + unsigned long vid_y_even_offset; + unsigned long vid_u_even_offset; + unsigned long vid_v_even_offset; + unsigned long vactive_even; + unsigned long vblank_even; + unsigned long vsync_even; + unsigned long h_coeff[512]; + unsigned long v_coeff[256]; + unsigned long palette[261]; + unsigned long cursor_data[3072]; + unsigned long dot_pll; + unsigned long pll_flags; + + /* VG MSRS */ + + Q_WORD msr_cap; + Q_WORD msr_config; + Q_WORD msr_smi; + Q_WORD msr_error; + Q_WORD msr_pm; + Q_WORD msr_diag; + Q_WORD msr_spare; + Q_WORD msr_ram_ctl; + +} VG_SAVE_RESTORE; + +/*-------------------------------------------*/ +/* VG_GET_DISPLAY_MODE_INDEX PARAMETERS */ +/*-------------------------------------------*/ + +#define VG_QUERYFLAG_ACTIVEWIDTH 0x00000001 +#define VG_QUERYFLAG_ACTIVEHEIGHT 0x00000002 +#define VG_QUERYFLAG_TOTALWIDTH 0x00000004 +#define VG_QUERYFLAG_TOTALHEIGHT 0x00000008 +#define VG_QUERYFLAG_BPP 0x00000010 +#define VG_QUERYFLAG_REFRESH 0x00000020 +#define VG_QUERYFLAG_PIXELCLOCK 0x00000040 +#define VG_QUERYFLAG_PIXELCLOCK_APPROX 0x00000080 +#define VG_QUERYFLAG_PANEL 0x00000100 +#define VG_QUERYFLAG_PANELWIDTH 0x00000200 +#define VG_QUERYFLAG_PANELHEIGHT 0x00000400 +#define VG_QUERYFLAG_TVOUT 0x00000800 +#define VG_QUERYFLAG_INTERLACED 0x00001000 +#define VG_QUERYFLAG_HALFCLOCK 0x00002000 +#define VG_QUERYFLAG_ENCODER 0x00004000 +#define VG_QUERYFLAG_TVMODE 0x00008000 + +/*-----------------------------------------------*/ +/* VG FLICKER FILTER SETTINGS */ +/*-----------------------------------------------*/ + +#define VG_FLICKER_FILTER_NONE 0x00000000 +#define VG_FLICKER_FILTER_1_16 0x10000000 +#define VG_FLICKER_FILTER_1_8 0x20000000 +#define VG_FLICKER_FILTER_1_4 0x40000000 +#define VG_FLICKER_FILTER_5_16 0x50000000 +#define VG_FLICKER_FILTER_MASK 0xF0000000 + +/*-----------------------------------------------*/ +/* VG CRC SOURCES */ +/*-----------------------------------------------*/ + +#define VG_CRC_SOURCE_PREFILTER 0x00000000 +#define VG_CRC_SOURCE_PREFLICKER 0x00000001 +#define VG_CRC_SOURCE_POSTFLICKER 0x00000002 +#define VG_CRC_SOURCE_PREFILTER_EVEN 0x00000010 +#define VG_CRC_SOURCE_PREFLICKER_EVEN 0x00000011 +#define VG_CRC_SOURCE_POSTFLICKER_EVEN 0x00000012 +#define VG_CRC_SOURCE_EVEN 0x00000010 + +/*===================================================*/ +/* DISPLAY FILTER PARAMETERS */ +/*===================================================*/ + +/*-----------------------------------------------*/ +/* VIDEO FORMAT DEFINITIONS */ +/*-----------------------------------------------*/ + +#define DF_VIDFMT_UYVY 0x0000 +#define DF_VIDFMT_Y2YU 0x0001 +#define DF_VIDFMT_YUYV 0x0002 +#define DF_VIDFMT_YVYU 0x0003 +#define DF_VIDFMT_Y0Y1Y2Y3 0x0004 +#define DF_VIDFMT_Y3Y2Y1Y0 0x0005 +#define DF_VIDFMT_Y1Y0Y3Y2 0x0006 +#define DF_VIDFMT_Y1Y2Y3Y0 0x0007 +#define DF_VIDFMT_RGB 0x0008 +#define DF_VIDFMT_P2M_P2L_P1M_P1L 0x0009 +#define DF_VIDFMT_P1M_P1L_P2M_P2L 0x000A +#define DF_VIDFMT_P1M_P2L_P2M_P1L 0x000B + +/*-----------------------------------------------*/ +/* CRT ENABLE STATES */ +/*-----------------------------------------------*/ + +#define DF_CRT_DISABLE 0x0000 +#define DF_CRT_ENABLE 0x0001 +#define DF_CRT_STANDBY 0x0002 +#define DF_CRT_SUSPEND 0x0003 + +/*-----------------------------------------------*/ +/* VIDEO SCALING FLAGS */ +/*-----------------------------------------------*/ + +#define DF_SCALEFLAG_CHANGEX 0x0001 +#define DF_SCALEFLAG_CHANGEY 0x0002 + +/*-----------------------------------------------*/ +/* DISPLAY FILTER COLOR SPACES */ +/*-----------------------------------------------*/ + +#define DF_OUTPUT_RGB 0x0001 +#define DF_OUTPUT_ARGB 0x0002 +#define DF_OUTPUT_SDTV 0x0003 +#define DF_OUTPUT_HDTV 0x0004 + +/*-----------------------------------------------*/ +/* DISPLAY FILTER OUTPUT PATHS */ +/*-----------------------------------------------*/ + +#define DF_DISPLAY_CRT 0x0001 +#define DF_DISPLAY_FP 0x0002 +#define DF_DISPLAY_CRT_FP 0x0003 +#define DF_DISPLAY_VOP 0x0004 +#define DF_DISPLAY_DRGB 0x0005 +#define DF_DISPLAY_CRT_DRGB 0x0006 + +/*-----------------------------------------------*/ +/* WINDOWED CRC DATA SOURCES */ +/*-----------------------------------------------*/ + +#define DF_CRC_SOURCE_GFX_DATA 0x0000 +#define DF_CRC_SOURCE_CRT_RGB 0x0001 +#define DF_CRC_SOURCE_FP_DATA 0x0002 + +/*-----------------------------------------------*/ +/* VIDEO ENABLE FLAGS */ +/*-----------------------------------------------*/ + +#define DF_ENABLEFLAG_NOCOLORKEY 0x0001 + +/*-----------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING A VIDEO SOURCE */ +/*-----------------------------------------------*/ + +#define DF_SOURCEFLAG_HDTVSOURCE 0x0001 +#define DF_SOURCEFLAG_IMPLICITSCALING 0x0002 + +typedef struct tagVideoSourceInfo +{ + unsigned long video_format; + unsigned long y_offset; + unsigned long u_offset; + unsigned long v_offset; + unsigned long y_pitch; + unsigned long uv_pitch; + unsigned long width; + unsigned long height; + unsigned long flags; + +} DF_VIDEO_SOURCE_PARAMS; + +/*---------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING THE VIDEO POSITION */ +/*---------------------------------------------------*/ + +#define DF_POSFLAG_DIRECTCLIP 0x0001 +#define DF_POSFLAG_INCLUDEBORDER 0x0002 + +typedef struct tagVideoPosition +{ + long x; + long y; + unsigned long width; + unsigned long height; + unsigned long left_clip; + unsigned long dst_clip; + unsigned long flags; + +} DF_VIDEO_POSITION; + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING THE VIDEO CURSOR */ +/*-------------------------------------------------*/ + +typedef struct tagVideoCursorInfo +{ + unsigned long key; + unsigned long mask; + unsigned long color1; + unsigned long color2; + unsigned long select_color2; + unsigned long flags; + +} DF_VIDEO_CURSOR_PARAMS; + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING AN ALPHA REGION */ +/*-------------------------------------------------*/ + +#define DF_ALPHAFLAG_COLORENABLED 0x0001 +#define DF_ALPHAFLAG_PERPIXELENABLED 0x0002 + +typedef struct tagAlphaRegionInfo +{ + unsigned long x; + unsigned long y; + unsigned long width; + unsigned long height; + unsigned long alpha_value; + unsigned long priority; + unsigned long color; + unsigned long flags; + long delta; + +} DF_ALPHA_REGION_PARAMS; + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR SAVING/RESTORING DF DATA */ +/*-------------------------------------------------*/ + +typedef struct tagDFSaveRestore +{ + unsigned long vcfg; + unsigned long dcfg; + unsigned long video_x; + unsigned long video_y; + unsigned long video_scaler; + unsigned long video_color_key; + unsigned long video_color_mask; + unsigned long sat_limit; + unsigned long vid_misc; + unsigned long video_yscale; + unsigned long video_xscale; + unsigned long vid_alpha_control; + unsigned long cursor_key; + unsigned long cursor_mask; + unsigned long cursor_color1; + unsigned long cursor_color2; + unsigned long alpha_xpos1; + unsigned long alpha_ypos1; + unsigned long alpha_color1; + unsigned long alpha_control1; + unsigned long alpha_xpos2; + unsigned long alpha_ypos2; + unsigned long alpha_color2; + unsigned long alpha_control2; + unsigned long alpha_xpos3; + unsigned long alpha_ypos3; + unsigned long alpha_color3; + unsigned long alpha_control3; + unsigned long vid_request; + unsigned long vid_ypos_even; + unsigned long alpha_ypos_even1; + unsigned long alpha_ypos_even2; + unsigned long alpha_ypos_even3; + unsigned long panel_tim1; + unsigned long panel_tim2; + unsigned long panel_pm; + unsigned long panel_dither; + + unsigned long palette[256]; + unsigned long coefficients[512]; + + /* DF MSRS */ + + Q_WORD msr_cap; + Q_WORD msr_config; + Q_WORD msr_smi; + Q_WORD msr_error; + Q_WORD msr_pm; + Q_WORD msr_diag; + Q_WORD msr_df_diag; + Q_WORD msr_pad_sel; + +} DF_SAVE_RESTORE; + +/*-----------------------------------------------*/ +/* DF CRC SOURCES */ +/*-----------------------------------------------*/ + +#define DF_CRC_SOURCE_ODD_FIELD 0x00000100 +#define DF_CRC_SOURCE_EVEN_FIELD 0x00001000 +#define DF_CRC_SOURCE_EVEN 0x00001000 + +/*===================================================*/ +/* VIP USER PARAMETER DEFINITIONS */ +/*===================================================*/ + +#define VIP_MODEFLAG_VSYNCACTIVEHIGH 0x00000001 +#define VIP_MODEFLAG_HSYNCACTIVEHIGH 0x00000002 + +/*---------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING 601 SETTINGS */ +/*---------------------------------------------*/ + +typedef struct _TAG_VIP601PARAMS +{ + unsigned long flags; + unsigned long horz_start; + unsigned long width; + unsigned long vert_start_even; + unsigned long even_height; + unsigned long vert_start_odd; + unsigned long odd_height; + unsigned long vbi_start; + unsigned long vbi_height; + unsigned long odd_detect_start; + unsigned long odd_detect_end; + +} VIP_601PARAMS; + +/*-------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING A VIP MODE */ +/*-------------------------------------------*/ + +/* VIP MODE FLAGS */ + +#define VIP_MODEFLAG_PLANARCAPTURE 0x00000001 +#define VIP_MODEFLAG_INVERTPOLARITY 0x00000002 +#define VIP_MODEFLAG_PROGRESSIVE 0x00000004 +#define VIP_MODEFLAG_DISABLEZERODETECT 0x00000008 +#define VIP_MODEFLAG_ENABLEREPEATFLAG 0x00000010 +#define VIP_MODEFLAG_10BITANCILLARY 0x00000020 +#define VIP_MODEFLAG_TOGGLEEACHFIELD 0x00000040 +#define VIP_MODEFLAG_INVERTTASKPOLARITY 0x00000080 +#define VIP_MODEFLAG_FLIPMESSAGEWHENFULL 0x00000100 + +/* VIP CAPTURE ENABLE FLAGS */ + +#define VIP_ENABLE_TASKA 0x00000100 +#define VIP_ENABLE_TASKA_VBI 0x00000200 +#define VIP_ENABLE_TASKB 0x00000400 +#define VIP_ENABLE_TASKB_VBI 0x00000800 +#define VIP_ENABLE_ANCILLARY 0x00001000 +#define VIP_ENABLE_ALL 0x00001F00 + +/* VIP CAPTURE MODE FLAGS */ + +#define VIP_MODE_IDLE 0x00000000 +#define VIP_MODE_VIP2_8BIT 0x00000002 +#define VIP_MODE_VIP2_16BIT 0x00000004 +#define VIP_MODE_VIP1_8BIT 0x00000006 +#define VIP_MODE_MSG 0x00000008 +#define VIP_MODE_DATA 0x0000000A +#define VIP_MODE_8BIT601 0x0000000C +#define VIP_MODE_16BIT601 0x0000000E + +/* 4:2:0 PLANAR CAPTURE METHODS */ + +#define VIP_420CAPTURE_EVERYLINE 0x00000001 +#define VIP_420CAPTURE_ALTERNATINGLINES 0x00000002 +#define VIP_420CAPTURE_ALTERNATINGFIELDS 0x00000003 + +typedef struct _TAG_SETMODEBUFFER +{ + unsigned long flags; + unsigned long stream_enables; + unsigned long operating_mode; + unsigned long planar_capture; + VIP_601PARAMS vip601_settings; + +} VIPSETMODEBUFFER; + +/*-----------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VG/VIP GENLOCK */ +/*-----------------------------------------------*/ + +/* LOSS OF VIDEO DETECTION FLAGS */ + +#define VIP_VDE_RUNAWAY_LINE 0x00800000 +#define VIP_VDE_VERTICAL_TIMING 0x00400000 +#define VIP_VDE_CLOCKS_PER_LINE 0x00200000 +#define VIP_VDE_LOST_CLOCK 0x00100000 + +/* VIP VSYNC SELECT FOR THE VG */ + +#define VIP_VGSYNC_NONE 0x00000000 +#define VIP_VGSYNC_START_FRAME 0x00000001 +#define VIP_VGSYNC_FALLING_EDGE_VBLANK 0x00000002 +#define VIP_VGSYNC_RISING_EDGE_VBLANK 0x00000003 +#define VIP_VGSYNC_FALLING_EDGE_FIELD 0x00000004 +#define VIP_VGSYNC_RISING_EDGE_FIELD 0x00000005 +#define VIP_VGSYNC_VIP_CURRENT_LINE 0x00000006 +#define VIP_VGSYNC_MSG_INT 0x00000007 + +/* VIP FIELD SELECT FOR THE VG */ + +#define VIP_VGFIELD_INPUT 0x00000000 +#define VIP_VGFIELD_INPUT_INV 0x00000008 +#define VIP_VGFIELD_ACTIVE_PAGE 0x00000010 +#define VIP_VGFIELD_ACTIVE_PAGE_IN 0x00000018 + +/*--------------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING THE VG VSYNC GENLOCK */ +/*--------------------------------------------------------*/ + +typedef struct _TAG_GENLOCKBUFFER +{ + unsigned long vip_signal_loss; + unsigned long vsync_to_vg; + unsigned long field_to_vg; + unsigned long genlock_skew; + int enable_timeout; + +} VIPGENLOCKBUFFER; + +/*------------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VIP ANCILLARY CAPTURE */ +/*------------------------------------------------------*/ + +typedef struct _TAG_ANCILLARYBUFFER +{ + unsigned long msg1_base; + unsigned long msg2_base; + unsigned long msg_size; + +} VIPANCILLARYBUFFER; + +/*----------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VIP CAPTURE BUFFERS */ +/*----------------------------------------------------*/ + +#define VIP_INPUTFLAG_VBI 0x00000001 +#define VIP_INPUTFLAG_INVERTPOLARITY 0x00000002 +#define VIP_INPUTFLAG_PLANAR 0x00000004 + +#define VIP_MAX_BUFFERS 10 + +#define VIP_BUFFER_TASK_A 0x0000 +#define VIP_BUFFER_TASK_B 0x0001 +#define VIP_BUFFER_MAX_TASKS 0x0002 + +#define VIP_BUFFER_A 0x0000 +#define VIP_BUFFER_B 0x0001 +#define VIP_BUFFER_ANC 0x0002 +#define VIP_BUFFER_MSG 0x0003 +#define VIP_BUFFER_601 0x0004 +#define VIP_BUFFER_A_ODD 0x0005 +#define VIP_BUFFER_A_EVEN 0x0006 +#define VIP_BUFFER_B_ODD 0x0007 +#define VIP_BUFFER_B_EVEN 0x0008 + +typedef struct _TAG_INPUTBUFFER_ADDR +{ + unsigned long even_base[VIP_MAX_BUFFERS]; + unsigned long odd_base[VIP_MAX_BUFFERS]; + unsigned long y_pitch; + unsigned long uv_pitch; + unsigned long odd_uoffset; + unsigned long odd_voffset; + unsigned long even_uoffset; + unsigned long even_voffset; + unsigned long vbi_even_base; + unsigned long vbi_odd_base; + +} VIPINPUTBUFFER_ADDR; + +typedef struct _TAG_SETINPUTBUFFER +{ + unsigned long flags; + VIPINPUTBUFFER_ADDR offsets[VIP_BUFFER_MAX_TASKS]; + unsigned long current_buffer; + + VIPANCILLARYBUFFER ancillaryData; + +} VIPINPUTBUFFER; + +/*------------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VIP SUBWINDOW CAPTURE */ +/*------------------------------------------------------*/ + +typedef struct _TAG_SUBWINDOWBUFFER +{ + int enable; + unsigned long start; + unsigned long stop; + +} VIPSUBWINDOWBUFFER; + +/*--------------------------------------------------------*/ +/* USER STRUCTURE FOR SAVING/RESTORING VIP REGISTERS */ +/*--------------------------------------------------------*/ + +typedef struct _TAG_VIPSTATEBUFFER +{ + unsigned long control1; + unsigned long control2; + unsigned long vip_int; + unsigned long current_target; + unsigned long max_address; + unsigned long taska_evenbase; + unsigned long taska_oddbase; + unsigned long taska_vbi_evenbase; + unsigned long taska_vbi_oddbase; + unsigned long taska_data_pitch; + unsigned long control3; + unsigned long taska_v_oddoffset; + unsigned long taska_u_oddoffset; + unsigned long taskb_evenbase; + unsigned long taskb_oddbase; + unsigned long taskb_vbi_evenbase; + unsigned long taskb_vbi_oddbase; + unsigned long taskb_pitch; + unsigned long taskb_voffset; + unsigned long taskb_uoffset; + unsigned long msg1_base; + unsigned long msg2_base; + unsigned long msg_size; + unsigned long page_offset; + unsigned long vert_start_stop; + unsigned long vsync_err_count; + unsigned long taska_u_evenoffset; + unsigned long taska_v_evenoffset; + + Q_WORD msr_config; + Q_WORD msr_smi; + Q_WORD msr_pm; + Q_WORD msr_diag; + +} VIPSTATEBUFFER; + +/*--------------------------------------------------------*/ +/* VIP_SET_CAPTURE_STATE USER PARAMETERS */ +/*--------------------------------------------------------*/ + +#define VIP_STOPCAPTURE 0x0000 +#define VIP_STOPCAPTUREATLINEEND 0x0001 +#define VIP_STOPCAPTUREATFIELDEND 0x0002 +#define VIP_STOPCAPTUREATFRAMEEND 0x0003 +#define VIP_STARTCAPTUREATNEXTLINE 0x0004 +#define VIP_STARTCAPTUREATNEXTFIELD 0x0005 +#define VIP_STARTCAPTUREATNEXTFRAME 0x0006 +#define VIP_STARTCAPTURE 0x0007 + +/*--------------------------------------------------------*/ +/* VIP_CONFIGURE_FIFO USER PARAMETERS */ +/*--------------------------------------------------------*/ + +#define VIP_VIDEOTHRESHOLD 0x3000 +#define VIP_ANCILLARYTHRESHOLD 0x3001 +#define VIP_VIDEOFLUSH 0x3002 +#define VIP_ANCILLARYFLUSH 0x3003 + +/*--------------------------------------------------------*/ +/* VIP_SET_INTERRUPT_ENABLE USER DEFINITIONS */ +/*--------------------------------------------------------*/ + +#define VIP_INT_FIFO_ERROR 0x80000000 +#define VIP_INT_FIFO_WRAP 0x40000000 +#define VIP_INT_FIFO_OVERFLOW 0x20000000 +#define VIP_INT_FIFO_THRESHOLD 0x10000000 +#define VIP_INT_LONGLINE 0x08000000 +#define VIP_INT_VERTICAL_TIMING 0x04000000 +#define VIP_INT_ACTIVE_PIXELS 0x02000000 +#define VIP_INT_CLOCK_INPUT 0x01000000 +#define VIP_INT_ANC_CHECKSUM_PARITY 0x00800000 +#define VIP_INT_MSG_BUFFER_FULL 0x00400000 +#define VIP_INT_END_VBLANK 0x00200000 +#define VIP_INT_START_VBLANK 0x00100000 +#define VIP_INT_START_EVEN 0x00080000 +#define VIP_INT_START_ODD 0x00040000 +#define VIP_INT_LINE_MATCH_TARGET 0x00020000 +#define VIP_ALL_INTERRUPTS 0xFFFE0000 + +/*--------------------------------------------------------*/ +/* VIP_GET_CURRENT_FIELD RETURN VALUES */ +/*--------------------------------------------------------*/ + +#define VIP_ODD_FIELD 1 +#define VIP_EVEN_FIELD 0 + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR QUERYING VIP CAPABILITIES */ +/*-------------------------------------------------*/ + +typedef struct _TAG_CAPABILITIESBUFFER +{ + unsigned long revision_id; + unsigned long device_id; + unsigned long n_clock_domains; + unsigned long n_smi_registers; + +} VIPCAPABILITIESBUFFER; + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VIP POWER */ +/*-------------------------------------------------*/ + +typedef struct _TAG_POWERBUFFER +{ + int glink_clock_mode; + int vip_clock_mode; + +} VIPPOWERBUFFER; + +/*-------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VIP PRIORITIES */ +/*-------------------------------------------------*/ + +typedef struct _TAG_PRIORITYBUFFER +{ + unsigned long secondary; + unsigned long primary; + unsigned long pid; + +} VIPPRIORITYBUFFER; + +/*--------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VIP DEBUG OUTPUTS */ +/*--------------------------------------------------*/ + +#define VIP_DIAG_UPPER_GLINK_MASTER 0x00010000 +#define VIP_DIAG_UPPER_GLINK_SLAVE 0x00020000 +#define VIP_DIAG_UPPER_GLINK_SLAVE_MMREG 0x00040000 +#define VIP_DIAG_UPPER_Y_BUFFER 0x00080000 +#define VIP_DIAG_UPPER_A_BUFFER 0x00100000 +#define VIP_DIAG_UPPER_FIFO_OUTPUT 0x00200000 +#define VIP_DIAG_UPPER_FIFO_INPUT 0x01000000 +#define VIP_DIAG_UPPER_FORMATTER 0x02000000 +#define VIP_DIAG_UPPER_INPUT_CONTROL 0x04000000 + +#define VIP_DIAG_LOWER_GLINK_MASTER 0x00000001 +#define VIP_DIAG_LOWER_GLINK_SLAVE 0x00000002 +#define VIP_DIAG_LOWER_GLINK_SLAVE_MMREG 0x00000004 +#define VIP_DIAG_LOWER_Y_BUFFER 0x00000008 +#define VIP_DIAG_LOWER_A_BUFFER 0x00000010 +#define VIP_DIAG_LOWER_FIFO_OUTPUT 0x00000020 +#define VIP_DIAG_LOWER_FIFO_INPUT 0x00000100 +#define VIP_DIAG_LOWER_FORMATTER 0x00000200 +#define VIP_DIAG_LOWER_INPUT_CONTROL 0x00000400 + +typedef struct _TAG_DEBUGBUFFER +{ + unsigned long bist; + unsigned long enable_upper; + unsigned long select_upper; + unsigned long enable_lower; + unsigned long select_lower; + +} VIPDEBUGBUFFER; + +/*===================================================*/ +/* VOP USER PARAMETER DEFINITIONS */ +/*===================================================*/ + +/*------------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VBI CAPTURE */ +/*------------------------------------------------------*/ + +typedef struct _TAG_VBIWINDOWBUFFER +{ + long horz_start; + unsigned long vbi_width; + unsigned long odd_line_capture_mask; + unsigned long even_line_capture_mask; + unsigned long odd_line_offset; + unsigned long even_line_offset; + unsigned long even_address_offset; + unsigned long odd_address_offset; + unsigned long data_size; + unsigned long data_pitch; + int enable_upscale; + int horz_from_hsync; + +} VOPVBIWINDOWBUFFER; + +/*------------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING 601 FOR VOP */ +/*------------------------------------------------------*/ + +#define VOP_601_INVERT_DISPE 0x00080000 +#define VOP_601_INVERT_VSYNC 0x00040000 +#define VOP_601_INVERT_HSYNC 0x00020000 + +#define VOP_VSYNC_EARLIER_BY4 0x00000000 +#define VOP_VSYNC_EARLIER_BY2 0x00004000 +#define VOP_VSYNC_NOSHIFT 0x00008000 +#define VOP_VSYNC_LATER_BY_X 0x0000C000 + +#define VOP_601_YUV_8BIT 0x00000000 +#define VOP_601_YUV_16BIT 0x00000001 +#define VOP_601_RGB_8_8_8 0x00000002 +#define VOP_601_YUV_4_4_4 0x00000003 + +typedef struct _TAG_VOP601 +{ + unsigned long flags; + unsigned long vsync_shift; + unsigned long vsync_shift_count; + unsigned long output_mode; + +} VOP_601DATA; + +/*------------------------------------------------------*/ +/* USER STRUCTURE FOR CONFIGURING VOP OUTPUT */ +/*------------------------------------------------------*/ + +/* VOP FLAGS */ + +#define VOP_FLAG_SINGLECHIPCOMPAT 0x00000001 +#define VOP_FLAG_EXTENDEDSAV 0x00000002 +#define VOP_FLAG_VBI 0x00000008 +#define VOP_FLAG_TASK 0x00000010 +#define VOP_FLAG_SWAP_UV 0x00000020 +#define VOP_FLAG_SWAP_VBI 0x00000040 + +/* 4:4:2 TO 4:2:2 DECIMATION */ + +#define VOP_422MODE_COSITED 0x00000000 +#define VOP_422MODE_INTERSPERSED 0x00000010 +#define VOP_422MODE_ALTERNATING 0x00000020 + +/* VOP OPERATING MODES */ + +#define VOP_MODE_DISABLED 0x00000000 +#define VOP_MODE_VIP11 0x00000001 +#define VOP_MODE_CCIR656 0x00000002 +#define VOP_MODE_VIP20_8BIT 0x00000003 +#define VOP_MODE_VIP20_16BIT 0x00000004 +#define VOP_MODE_601 0x00000005 + +/* VSYNC OUT SELECT FLAGS */ + +#define VOP_MB_SYNCSEL_DISABLED 0x00000000 +#define VOP_MB_SYNCSEL_VG 0x00000020 +#define VOP_MB_SYNCSEL_VG_INV 0x00000040 +#define VOP_MB_SYNCSEL_STATREG17 0x00000060 +#define VOP_MB_SYNCSEL_STATREG17_INV 0x00000080 + +typedef struct _TAG_VOPMODECONFIGURATIONBUFFER +{ + unsigned long flags; + unsigned long mode; + unsigned long conversion_mode; + unsigned long vsync_out; + VOP_601DATA vop601; + +} VOPCONFIGURATIONBUFFER; + +/*--------------------------------------------------------*/ +/* USER STRUCTURE FOR SAVING/RESTORING VOP REGISTERS */ +/*--------------------------------------------------------*/ + +typedef struct _TAG_VOPSTATEBUFFER +{ + unsigned long config; +} VOPSTATEBUFFER; + +#endif diff --git a/src/cim/cim_regs.h b/src/cim/cim_regs.h new file mode 100644 index 0000000..6d434a2 --- /dev/null +++ b/src/cim/cim_regs.h @@ -0,0 +1,1252 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron register definitions + */ + +#ifndef _cim_regs_h +#define _cim_regs_h + +/*----------------------------------------------------------------*/ +/* GRAPHICS PROCESSOR DEFINITIONS */ +/*----------------------------------------------------------------*/ + +/*----------------------------*/ +/* COMMAND BUFFER DEFINITIONS */ +/*----------------------------*/ + +#define GP3_BLT_COMMAND_SIZE 68 /* 18 DWORDS */ +#define GP3_VECTOR_COMMAND_SIZE 56 /* 14 DWORDS */ +#define GP3_4BPP_LUT_COMMAND_SIZE 76 /* 16 DWORDS + 3 CMD DWORDS */ +#define GP3_8BPP_LUT_COMMAND_SIZE 1036 /* 256 DWORDS + + * 3 CMD DWORDS */ +#define GP3_VECTOR_PATTERN_COMMAND_SIZE 20 /* 2 DWORDS + 3 CMD DWORDS */ +#define GP3_MAX_COMMAND_SIZE 9000 /* 8K + + * WORKAROUND SPACE */ +#define GP3_SCRATCH_BUFFER_SIZE 0x100000 /* 1MB SCRATCH + * BUFFER */ +#define GP3_BLT_1PASS_SIZE 0xC7F8 /* (50K - 8) is largest + * 1-Pass load size */ + +/*-------------------------------------*/ +/* BLT COMMAND BUFFER REGISTER OFFSETS */ +/*-------------------------------------*/ + +#define GP3_BLT_CMD_HEADER 0x00000000 +#define GP3_BLT_RASTER_MODE 0x00000004 +#define GP3_BLT_DST_OFFSET 0x00000008 +#define GP3_BLT_SRC_OFFSET 0x0000000C +#define GP3_BLT_STRIDE 0x00000010 +#define GP3_BLT_WID_HEIGHT 0x00000014 +#define GP3_BLT_SRC_COLOR_FG 0x00000018 +#define GP3_BLT_SRC_COLOR_BG 0x0000001C +#define GP3_BLT_PAT_COLOR_0 0x00000020 +#define GP3_BLT_PAT_COLOR_1 0x00000024 +#define GP3_BLT_PAT_DATA_0 0x00000028 +#define GP3_BLT_PAT_DATA_1 0x0000002C +#define GP3_BLT_CH3_OFFSET 0x00000030 +#define GP3_BLT_CH3_MODE_STR 0x00000034 +#define GP3_BLT_CH3_WIDHI 0x00000038 +#define GP3_BLT_BASE_OFFSET 0x0000003C +#define GP3_BLT_MODE 0x00000040 + +/*-----------------------------------------------------------------*/ +/* VECTOR COMMAND BUFFER REGISTER OFFSETS */ +/* Some of these are identical to the BLT registers (and we will */ +/* be assumed to be such in the Cimarron code, but they are listed */ +/* here for clarity and for future changes. */ +/*-----------------------------------------------------------------*/ + +#define GP3_VEC_CMD_HEADER 0x00000000 +#define GP3_VECTOR_RASTER_MODE 0x00000004 +#define GP3_VECTOR_DST_OFFSET 0x00000008 +#define GP3_VECTOR_VEC_ERR 0x0000000C +#define GP3_VECTOR_STRIDE 0x00000010 +#define GP3_VECTOR_VEC_LEN 0x00000014 +#define GP3_VECTOR_SRC_COLOR_FG 0x00000018 +#define GP3_VECTOR_PAT_COLOR_0 0x0000001C +#define GP3_VECTOR_PAT_COLOR_1 0x00000020 +#define GP3_VECTOR_PAT_DATA_0 0x00000024 +#define GP3_VECTOR_PAT_DATA_1 0x00000028 +#define GP3_VECTOR_CH3_MODE_STR 0x0000002C +#define GP3_VECTOR_BASE_OFFSET 0x00000030 +#define GP3_VECTOR_MODE 0x00000034 + +/*---------------------------------------------------*/ +/* GP REGISTER DEFINITIONS */ +/* Addresses for writing or reading directly to/from */ +/* the graphics processor. */ +/*---------------------------------------------------*/ + +#define GP3_DST_OFFSET 0x00000000 +#define GP3_SRC_OFFSET 0x00000004 +#define GP3_VEC_ERR 0x00000004 +#define GP3_STRIDE 0x00000008 +#define GP3_WID_HEIGHT 0x0000000C +#define GP3_VEC_LEN 0x0000000C +#define GP3_SRC_COLOR_FG 0x00000010 +#define GP3_SRC_COLOR_BG 0x00000014 +#define GP3_PAT_COLOR_0 0x00000018 +#define GP3_PAT_COLOR_1 0x0000001C +#define GP3_PAT_COLOR_2 0x00000020 +#define GP3_PAT_COLOR_3 0x00000024 +#define GP3_PAT_COLOR_4 0x00000028 +#define GP3_PAT_COLOR_5 0x0000002C +#define GP3_PAT_DATA_0 0x00000030 +#define GP3_PAT_DATA_1 0x00000034 +#define GP3_RASTER_MODE 0x00000038 +#define GP3_VEC_MODE 0x0000003C +#define GP3_BLT_MODE 0x00000040 +#define GP3_BLT_STATUS 0x00000044 +#define GP3_HST_SRC 0x00000048 +#define GP3_BASE_OFFSET 0x0000004C +#define GP3_CMD_TOP 0x00000050 +#define GP3_CMD_BOT 0x00000054 +#define GP3_CMD_READ 0x00000058 +#define GP3_CMD_WRITE 0x0000005C +#define GP3_CH3_OFFSET 0x00000060 +#define GP3_CH3_MODE_STR 0x00000064 +#define GP3_CH3_WIDHI 0x00000068 +#define GP3_CH3_HST_SRC 0x0000006C +#define GP3_LUT_ADDRESS 0x00000070 +#define GP3_LUT_DATA 0x00000074 +#define GP3_INT_CTL 0x00000078 +#define GP3_HST_SRC_RANGE 0x00000100 + +/*------------------------*/ +/* REGISTER BIT FIELDS */ +/*------------------------*/ + +/* GP3_BLT_CMD_HEADER BIT DEFINITIONS */ + +#define GP3_BLT_HDR_WRAP 0x80000000 +#define GP3_BLT_HDR_TYPE 0x00000000 +#define GP3_BLT_HDR_HAZARD_ENABLE 0x10000000 +#define GP3_BLT_HDR_RASTER_ENABLE 0x00000001 +#define GP3_BLT_HDR_DST_OFF_ENABLE 0x00000002 +#define GP3_BLT_HDR_SRC_OFF_ENABLE 0x00000004 +#define GP3_BLT_HDR_STRIDE_ENABLE 0x00000008 +#define GP3_BLT_HDR_WIDHI_ENABLE 0x00000010 +#define GP3_BLT_HDR_SRC_FG_ENABLE 0x00000020 +#define GP3_BLT_HDR_SRC_BG_ENABLE 0x00000040 +#define GP3_BLT_HDR_PAT_CLR0_ENABLE 0x00000080 +#define GP3_BLT_HDR_PAT_CLR1_ENABLE 0x00000100 +#define GP3_BLT_HDR_PAT_DATA0_ENABLE 0x00000200 +#define GP3_BLT_HDR_PAT_DATA1_ENABLE 0x00000400 +#define GP3_BLT_HDR_CH3_OFF_ENABLE 0x00000800 +#define GP3_BLT_HDR_CH3_STR_ENABLE 0x00001000 +#define GP3_BLT_HDR_CH3_WIDHI_ENABLE 0x00002000 +#define GP3_BLT_HDR_BASE_OFFSET_ENABLE 0x00004000 +#define GP3_BLT_HDR_BLT_MODE_ENABLE 0x00008000 + +/* GP3_VEC_CMD_HEADER BIT DEFINITIONS */ + +#define GP3_VEC_HDR_WRAP 0x80000000 +#define GP3_VEC_HDR_TYPE 0x20000000 +#define GP3_VEC_HDR_HAZARD_ENABLE 0x10000000 +#define GP3_VEC_HDR_RASTER_ENABLE 0x00000001 +#define GP3_VEC_HDR_DST_OFF_ENABLE 0x00000002 +#define GP3_VEC_HDR_VEC_ERR_ENABLE 0x00000004 +#define GP3_VEC_HDR_STRIDE_ENABLE 0x00000008 +#define GP3_VEC_HDR_VEC_LEN_ENABLE 0x00000010 +#define GP3_VEC_HDR_SRC_FG_ENABLE 0x00000020 +#define GP3_VEC_HDR_PAT_CLR0_ENABLE 0x00000040 +#define GP3_VEC_HDR_PAT_CLR1_ENABLE 0x00000080 +#define GP3_VEC_HDR_PAT_DATA0_ENABLE 0x00000100 +#define GP3_VEC_HDR_PAT_DATA1_ENABLE 0x00000200 +#define GP3_VEC_HDR_CH3_STR_ENABLE 0x00000400 +#define GP3_VEC_HDR_BASE_OFFSET_ENABLE 0x00000800 +#define GP3_VEC_HDR_VEC_MODE_ENABLE 0x00001000 + +/* GP3_RASTER_MODE BIT DEFINITIONS */ + +#define GP3_RM_BPPFMT_332 0x00000000 /* 8 BPP, palettized */ +#define GP3_RM_BPPFMT_4444 0x40000000 /* 16 BPP, 4:4:4:4 */ +#define GP3_RM_BPPFMT_1555 0x50000000 /* 16 BPP, 1:5:5:5 */ +#define GP3_RM_BPPFMT_565 0x60000000 /* 16 BPP, 5:6:5 */ +#define GP3_RM_BPPFMT_8888 0x80000000 /* 32 BPP, 8:8:8:8 */ +#define GP3_RM_ALPHA_ALL 0x00C00000 /* Alpha enable */ +#define GP3_RM_ALPHA_TO_RGB 0x00400000 /* Alpha applies to RGB */ +#define GP3_RM_ALPHA_TO_ALPHA 0x00800000 /* Alpha applies to alpha */ +#define GP3_RM_ALPHA_OP_MASK 0x00300000 /* Alpha operation */ +#define GP3_RM_ALPHA_TIMES_A 0x00000000 /* Alpha * A */ +#define GP3_RM_BETA_TIMES_B 0x00100000 /* (1-alpha) * B */ +#define GP3_RM_A_PLUS_BETA_B 0x00200000 /* A + (1-alpha) * B */ +#define GP3_RM_ALPHA_A_PLUS_BETA_B 0x00300000 /* alpha * A + (1 - alpha)B */ +#define GP3_RM_ALPHA_SELECT 0x000E0000 /* Alpha Select */ +#define GP3_RM_SELECT_ALPHA_A 0x00000000 /* Alpha from channel A */ +#define GP3_RM_SELECT_ALPHA_B 0x00020000 /* Alpha from channel B */ +#define GP3_RM_SELECT_ALPHA_R 0x00040000 /* Registered alpha */ +#define GP3_RM_SELECT_ALPHA_1 0x00060000 /* Constant 1 */ +#define GP3_RM_SELECT_ALPHA_CHAN_A 0x00080000 /* RGB Values from A */ +#define GP3_RM_SELECT_ALPHA_CHAN_B 0x000A0000 /* RGB Values from B */ +#define GP3_RM_SELECT_ALPHA_CHAN_3 0x000C0000 /* Alpha from channel 3 */ +#define GP3_RM_DEST_FROM_CHAN_A 0x00010000 /* Alpha channel select */ +#define GP3_RM_PATTERN_INVERT 0x00001000 /* Invert monochrome pat */ +#define GP3_RM_SOURCE_INVERT 0x00002000 /* Invert monochrome src */ +#define GP3_RM_PAT_FLAGS 0x00000700 /* pattern related bits */ +#define GP3_RM_PAT_MONO 0x00000100 /* monochrome pattern */ +#define GP3_RM_PAT_COLOR 0x00000200 /* color pattern */ +#define GP3_RM_PAT_TRANS 0x00000400 /* pattern transparency */ +#define GP3_RM_SRC_TRANS 0x00000800 /* source transparency */ + +/* GP3_VECTOR_MODE REGISTER DESCRIPTIONS */ + +#define GP3_VM_DST_REQ 0x00000008 /* dst data required */ +#define GP3_VM_THROTTLE 0x00000010 /* sync to VBLANK */ + +/* GP3_BLT_MODE REGISTER DEFINITIONS */ + +#define GP3_BM_SRC_FB 0x00000001 /* src = frame buffer */ +#define GP3_BM_SRC_HOST 0x00000002 /* src = host register */ +#define GP3_BM_DST_REQ 0x00000004 /* dst data required */ +#define GP3_BM_SRC_MONO 0x00000040 /* monochrome source data */ +#define GP3_BM_SRC_BP_MONO 0x00000080 /* Byte-packed monochrome */ +#define GP3_BM_NEG_YDIR 0x00000100 /* negative Y direction */ +#define GP3_BM_NEG_XDIR 0x00000200 /* negative X direction */ +#define GP3_BM_THROTTLE 0x00000400 /* sync to VBLANK */ + +/* GP3_BLT_STATUS REGISTER DEFINITIONS */ + +#define GP3_BS_BLT_BUSY 0x00000001 /* GP is not idle */ +#define GP3_BS_BLT_PENDING 0x00000004 /* second BLT is pending */ +#define GP3_BS_HALF_EMPTY 0x00000008 /* src FIFO half empty */ +#define GP3_BS_CB_EMPTY 0x00000010 /* Command buffer empty. */ + +/* GP3_CH3_MODE_STR REGISTER DEFINITIONS */ + +#define GP3_CH3_C3EN 0x80000000 +#define GP3_CH3_REPLACE_SOURCE 0x40000000 +#define GP3_CH3_NEG_XDIR 0x20000000 +#define GP3_CH3_NEG_YDIR 0x10000000 +#define GP3_CH3_SRC_FMT_MASK 0x0f000000 +#define GP3_CH3_SRC_3_3_2 0x00000000 +#define GP3_CH3_SRC_8BPP_INDEXED 0x01000000 +#define GP3_CH3_SRC_8BPP_ALPHA 0x02000000 +#define GP3_CH3_SRC_4_4_4_4 0x04000000 +#define GP3_CH3_SRC_1_5_5_5 0x05000000 +#define GP3_CH3_SRC_0_5_6_5 0x06000000 +#define GP3_CH3_SRC_Y_U_V 0x07000000 +#define GP3_CH3_SRC_8_8_8_8 0x08000000 +#define GP3_CH3_SRC_24BPP_PACKED 0x0B000000 +#define GP3_CH3_SRC_4BPP_INDEXED 0x0D000000 +#define GP3_CH3_SRC_4BPP_ALPHA 0x0E000000 +#define GP3_CH3_SRC_MASK 0x0F000000 +#define GP3_CH3_ROTATE_ENABLE 0x00800000 +#define GP3_CH3_BGR_ORDER 0x00400000 +#define GP3_CH3_COLOR_PAT_ENABLE 0x00200000 +#define GP3_CH3_PRESERVE_LUT 0x00100000 +#define GP3_CH3_PREFETCH_ENABLE 0x00080000 +#define GP3_CH3_HST_SRC_ENABLE 0x00040000 +#define GP3_CH3_STRIDE_MASK 0x0000FFFF + +/* DATA AND LUT LOAD BIT DEFINITIONS */ + +#define GP3_LUT_HDR_WRAP 0x80000000 +#define GP3_LUT_HDR_TYPE 0x40000000 +#define GP3_LUT_HDR_DATA_ENABLE 0x00000003 +#define GP3_DATA_LOAD_HDR_WRAP 0x80000000 +#define GP3_DATA_LOAD_HDR_TYPE 0x60000000 +#define GP3_DATA_LOAD_HDR_ENABLE 0x00000001 + +#define GP3_HOST_SOURCE_TYPE 0x00000000 +#define GP3_CH3_HOST_SOURCE_TYPE 0x20000000 +#define GP3_OLD_PATTERN_COLORS 0x40000000 +#define GP3_LUT_DATA_TYPE 0x60000000 + +#define GP3_BASE_OFFSET_DSTMASK 0xFFC00000 +#define GP3_BASE_OFFSET_SRCMASK 0x003FF000 +#define GP3_BASE_OFFSET_CH3MASK 0x00000FFC + +/*----------------------------------------------------------------*/ +/* VIDEO GENERATOR DEFINITIONS */ +/*----------------------------------------------------------------*/ + +#define DC3_UNLOCK 0x00000000 /* Unlock register */ +#define DC3_GENERAL_CFG 0x00000004 /* Config registers */ +#define DC3_DISPLAY_CFG 0x00000008 +#define DC3_ARB_CFG 0x0000000C + +#define DC3_FB_ST_OFFSET 0x00000010 /* Frame buffer start offset */ +#define DC3_CB_ST_OFFSET 0x00000014 /* Compression start offset */ +#define DC3_CURS_ST_OFFSET 0x00000018 /* Cursor buffer start offset */ +#define DC3_VID_Y_ST_OFFSET 0x00000020 /* Video Y Buffer start offset */ +#define DC3_VID_U_ST_OFFSET 0x00000024 /* Video U Buffer start offset */ +#define DC3_VID_V_ST_OFFSET 0x00000028 /* Video V Buffer start offset */ +#define DC3_DV_TOP 0x0000002C /* DV Ram Limit Register */ +#define DC3_LINE_SIZE 0x00000030 /* Video, CB, and FB line sizes */ +#define DC3_GFX_PITCH 0x00000034 /* FB and DB skip counts */ +#define DC3_VID_YUV_PITCH 0x00000038 /* Y, U and V buffer skip counts */ + +#define DC3_H_ACTIVE_TIMING 0x00000040 /* Horizontal timings */ +#define DC3_H_BLANK_TIMING 0x00000044 +#define DC3_H_SYNC_TIMING 0x00000048 +#define DC3_V_ACTIVE_TIMING 0x00000050 /* Vertical Timings */ +#define DC3_V_BLANK_TIMING 0x00000054 +#define DC3_V_SYNC_TIMING 0x00000058 +#define DC3_FB_ACTIVE 0x0000005C + +#define DC3_CURSOR_X 0x00000060 /* Cursor X position */ +#define DC3_CURSOR_Y 0x00000064 /* Cursor Y Position */ +#define DC3_LINE_CNT_STATUS 0x0000006C + +#define DC3_PAL_ADDRESS 0x00000070 /* Palette Address */ +#define DC3_PAL_DATA 0x00000074 /* Palette Data */ +#define DC3_DFIFO_DIAG 0x00000078 /* Display FIFO diagnostic */ +#define DC3_CFIFO_DIAG 0x0000007C /* Compression FIFO diagnostic */ + +#define DC3_VID_DS_DELTA 0x00000080 /* Vertical Downscaling fraction */ + +#define DC3_PHY_MEM_OFFSET 0x00000084 /* VG Base Address Register */ +#define DC3_DV_CTL 0x00000088 /* Dirty-Valid Control Register */ +#define DC3_DV_ACC 0x0000008C /* Dirty-Valid RAM Access */ + +#define DC3_GFX_SCALE 0x00000090 /* Graphics Scaling */ +#define DC3_IRQ_FILT_CTL 0x00000094 /* VBlank interrupt and filters */ +#define DC3_FILT_COEFF1 0x00000098 +#define DC3_FILT_COEFF2 0x0000009C + +#define DC3_VBI_EVEN_CTL 0x000000A0 /* VBI Data Buffer Controls */ +#define DC3_VBI_ODD_CTL 0x000000A4 +#define DC3_VBI_HOR 0x000000A8 +#define DC3_VBI_LN_ODD 0x000000AC +#define DC3_VBI_LN_EVEN 0x000000B0 +#define DC3_VBI_PITCH 0x000000B4 + +#define DC3_COLOR_KEY 0x000000B8 /* Graphics color key */ +#define DC3_COLOR_MASK 0x000000BC /* Graphics color key mask */ +#define DC3_CLR_KEY_X 0x000000C0 +#define DC3_CLR_KEY_Y 0x000000C4 + +#define DC3_IRQ 0x000000C8 +#define DC3_GENLK_CTL 0x000000D4 + +#define DC3_VID_EVEN_Y_ST_OFFSET 0x000000D8 /* Even field video buffers */ +#define DC3_VID_EVEN_U_ST_OFFSET 0x000000DC +#define DC3_VID_EVEN_V_ST_OFFSET 0x000000E0 + +#define DC3_V_ACTIVE_EVEN 0x000000E4 /* Even field timing registers */ +#define DC3_V_BLANK_EVEN 0x000000E8 +#define DC3_V_SYNC_EVEN 0x000000EC + +/* UNLOCK VALUE */ + +#define DC3_UNLOCK_VALUE 0x00004758 /* used to unlock DC regs */ + +/* VG GEODELINK DEVICE SMI MSR FIELDS */ + +#define DC3_VG_BL_MASK 0x00000001 +#define DC3_MISC_MASK 0x00000002 +#define DC3_ISR0_MASK 0x00000004 +#define DC3_VGA_BL_MASK 0x00000008 +#define DC3_CRTCIO_MSK 0x00000010 +#define DC3_VG_BLANK_SMI 0x00000001 +#define DC3_MISC_SMI 0x00000002 +#define DC3_ISR0_SMI 0x00000004 +#define DC3_VGA_BLANK_SMI 0x00000008 +#define DC3_CRTCIO_SMI 0x00000010 + +/* DC3_GENERAL_CFG BIT FIELDS */ + +#define DC3_GCFG_DBUG 0x80000000 +#define DC3_GCFG_DBSL 0x40000000 +#define DC3_GCFG_CFRW 0x20000000 +#define DC3_GCFG_DIAG 0x10000000 +#define DC3_GCFG_CRC_MODE 0x08000000 +#define DC3_GCFG_SGFR 0x04000000 +#define DC3_GCFG_SGRE 0x02000000 +#define DC3_GCFG_SIGE 0x01000000 +#define DC3_GCFG_SIG_SEL 0x00800000 +#define DC3_GCFG_YUV_420 0x00100000 +#define DC3_GCFG_VDSE 0x00080000 +#define DC3_GCFG_VGAFT 0x00040000 +#define DC3_GCFG_FDTY 0x00020000 +#define DC3_GCFG_STFM 0x00010000 +#define DC3_GCFG_DFHPEL_MASK 0x0000F000 +#define DC3_GCFG_DFHPSL_MASK 0x00000F00 +#define DC3_GCFG_VGAE 0x00000080 +#define DC3_GCFG_DECE 0x00000040 +#define DC3_GCFG_CMPE 0x00000020 +#define DC3_GCFG_FILT_SIG_SEL 0x00000010 +#define DC3_GCFG_VIDE 0x00000008 +#define DC3_GCFG_CLR_CUR 0x00000004 +#define DC3_GCFG_CURE 0x00000002 +#define DC3_GCFG_DFLE 0x00000001 + +/* DC3_DISPLAY_CFG BIT FIELDS */ + +#define DC3_DCFG_VISL 0x08000000 +#define DC3_DCFG_FRLK 0x04000000 +#define DC3_DCFG_PALB 0x02000000 +#define DC3_DCFG_DCEN 0x01000000 +#define DC3_DCFG_VFHPEL_MASK 0x000F0000 +#define DC3_DCFG_VFHPSL_MASK 0x0000F000 +#define DC3_DCFG_16BPP_MODE_MASK 0x00000C00 +#define DC3_DCFG_16BPP 0x00000000 +#define DC3_DCFG_15BPP 0x00000400 +#define DC3_DCFG_12BPP 0x00000800 +#define DC3_DCFG_DISP_MODE_MASK 0x00000300 +#define DC3_DCFG_DISP_MODE_8BPP 0x00000000 +#define DC3_DCFG_DISP_MODE_16BPP 0x00000100 +#define DC3_DCFG_DISP_MODE_24BPP 0x00000200 +#define DC3_DCFG_DISP_MODE_32BPP 0x00000300 +#define DC3_DCFG_TRUP 0x00000040 +#define DC3_DCFG_VDEN 0x00000010 +#define DC3_DCFG_GDEN 0x00000008 +#define DC3_DCFG_TGEN 0x00000001 + +/* DC3_ARB_CFG BIT FIELDS */ + +#define DC3_ACFG_LB_LOAD_WM_EN 0x00100000 +#define DC3_ACFG_LB_LOAD_WM_MASK 0x000F0000 +#define DC3_ACFG_LPEN_END_COUNT_MASK 0x0000FE00 +#define DC3_ACFG_HPEN_SBINV 0x00000100 +#define DC3_ACFG_HPEN_FB_INV_HALFSB 0x00000080 +#define DC3_ACFG_HPEN_FB_INV_SBRD 0x00000040 +#define DC3_ACFG_HPEN_FB_INV 0x00000020 +#define DC3_ACFG_HPEN_1LB_INV 0x00000010 +#define DC3_ACFG_HPEN_2LB_INV 0x00000008 +#define DC3_ACFG_HPEN_3LB_INV 0x00000004 +#define DC3_ACFG_HPEN_LB_FILL 0x00000002 +#define DC3_ACFG_LPEN_VSYNC 0x00000001 + +/* DC3_FB_ST_OFFSET BIT FIELDS */ + +#define DC3_FB_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_CB_ST_OFFSET BIT FIELDS */ + +#define DC3_CB_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_CURS_ST_OFFSET BIT FIELDS */ + +#define DC3_CURS_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_ICON_ST_OFFSET BIT FIELDS */ + +#define DC3_ICON_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VID_Y_ST_OFFSET BIT FIELDS */ + +#define DC3_VID_Y_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VID_U_ST_OFFSET BIT FIELDS */ + +#define DC3_VID_U_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VID_V_ST_OFFSET BIT FIELDS */ + +#define DC3_VID_V_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_DV_TOP BIT FIELDS */ + +#define DC3_DVTOP_ENABLE 0x00000001 +#define DC3_DVTOP_MAX_MASK 0x00FFFC00 +#define DC3_DVTOP_MAX_SHIFT 10 + +/* DC3_LINE_SIZE BIT FIELDS */ + +#define DC3_LINE_SIZE_VLS_MASK 0x3FF00000 +#define DC3_LINE_SIZE_CBLS_MASK 0x0007F000 +#define DC3_LINE_SIZE_FBLS_MASK 0x000003FF +#define DC3_LINE_SIZE_CB_SHIFT 12 +#define DC3_LINE_SIZE_VB_SHIFT 20 + +/* DC3_GFX_PITCH BIT FIELDS */ + +#define DC3_GFX_PITCH_CBP_MASK 0xFFFF0000 +#define DC3_GFX_PITCH_FBP_MASK 0x0000FFFF + +/* DC3_VID_YUV_PITCH BIT FIELDS */ + +#define DC3_YUV_PITCH_UVP_MASK 0xFFFF0000 +#define DC3_YUV_PITCH_YBP_MASK 0x0000FFFF + +/* DC3_H_ACTIVE_TIMING BIT FIELDS */ + +#define DC3_HAT_HT_MASK 0x0FF80000 +#define DC3_HAT_HA_MASK 0x00000FF8 + +/* DC3_H_BLANK_TIMING BIT FIELDS */ + +#define DC3_HBT_HBE_MASK 0x0FF80000 +#define DC3_HBT_HBS_MASK 0x00000FF8 + +/* DC3_H_SYNC_TIMING BIT FIELDS */ + +#define DC3_HST_HSE_MASK 0x0FF80000 +#define DC3_HST_HSS_MASK 0x00000FF8 + +/* DC3_V_ACTIVE_TIMING BIT FIELDS */ + +#define DC3_VAT_VT_MASK 0x07FF0000 +#define DC3_VAT_VA_MASK 0x000007FF + +/* DC3_V_BLANK_TIMING BIT FIELDS */ + +#define DC3_VBT_VBE_MASK 0x07FF0000 +#define DC3_VBT_VBS_MASK 0x000007FF + +/* DC3_V_SYNC_TIMING BIT FIELDS */ + +#define DC3_VST_VSE_MASK 0x07FF0000 +#define DC3_VST_VSS_MASK 0x000007FF + +/* DC3_LINE_CNT_STATUS BIT FIELDS */ + +#define DC3_LNCNT_DNA 0x80000000 +#define DC3_LNCNT_VNA 0x40000000 +#define DC3_LNCNT_VSA 0x20000000 +#define DC3_LNCNT_VINT 0x10000000 +#define DC3_LNCNT_FLIP 0x08000000 +#define DC3_LNCNT_V_LINE_CNT 0x07FF0000 +#define DC3_LNCNT_VFLIP 0x00008000 +#define DC3_LNCNT_SIGC 0x00004000 +#define DC3_LNCNT_EVEN_FIELD 0x00002000 +#define DC3_LNCNT_SS_LINE_CMP 0x000007FF + +/* DC3_VID_DS_DELTA BIT FIELDS */ + +#define DC3_DS_DELTA_MASK 0xFFFC0000 +#define DC3_601_VSYNC_SHIFT_MASK 0x00000FFF +#define DC3_601_VSYNC_SHIFT_ENABLE 0x00008000 + +/* DC3_DV_CTL BIT DEFINITIONS */ + +#define DC3_DV_LINE_SIZE_MASK 0x00000C00 +#define DC3_DV_LINE_SIZE_1024 0x00000000 +#define DC3_DV_LINE_SIZE_2048 0x00000400 +#define DC3_DV_LINE_SIZE_4096 0x00000800 +#define DC3_DV_LINE_SIZE_8192 0x00000C00 + +/* DC3_IRQ_FILT_CTL DEFINITIONS */ + +#define DC3_IRQFILT_LB_MASK 0x80000200 +#define DC3_IRQFILT_LB_COEFF 0x00000000 +#define DC3_IRQFILT_SCALER_FILTER 0x00000200 +#define DC3_IRQFILT_SYNCHRONIZER 0x80000000 +#define DC3_IRQFILT_FLICKER_FILTER 0x80000200 +#define DC3_IRQFILT_LB_SEL_MASK 0x60000000 +#define DC3_IRQFILT_INTL_ADDR 0x10000000 +#define DC3_IRQFILT_LINE_MASK 0x07FF0000 +#define DC3_IRQFILT_ALPHA_FILT_EN 0x00004000 +#define DC3_IRQFILT_GFX_FILT_EN 0x00001000 +#define DC3_IRQFILT_INTL_EN 0x00000800 +#define DC3_IRQFILT_H_FILT_SEL 0x00000400 +#define DC3_IRQFILT_LB_ADDR 0x00000100 + +/* DC3_VBI_EVEN_CTL DEFINITIONS */ + +#define DC3_VBI_EVEN_ENABLE_CRC (1L << 31) +#define DC3_VBI_EVEN_CTL_ENABLE_16 (1L << 30) +#define DC3_VBI_EVEN_CTL_UPSCALE (1L << 29) +#define DC3_VBI_ENABLE (1L << 28) +#define DC3_VBI_EVEN_CTL_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VBI_ODD_CTL DEFINITIONS */ + +#define DC3_VBI_ODD_CTL_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VBI_HOR BIT DEFINITIONS */ + +#define DC3_VBI_HOR_END_SHIFT 16 +#define DC3_VBI_HOR_END_MASK 0x0FFF0000 +#define DC3_VBI_HOR_START_MASK 0x00000FFF + +/* DC3_VBI_LN_ODD BIT DEFINITIONS */ + +#define DC3_VBI_ODD_ENABLE_SHIFT 2 +#define DC3_VBI_ODD_ENABLE_MASK 0x01FFFFFC +#define DC3_VBI_ODD_LINE_SHIFT 25 +#define DC3_VBI_ODD_LINE_MASK 0xFE000000 + +/* DC3_VBI_LN_EVEN BIT DEFINITIONS */ + +#define DC3_VBI_EVEN_ENABLE_SHIFT 2 +#define DC3_VBI_EVEN_ENABLE_MASK 0x01FFFFFC +#define DC3_VBI_EVEN_LINE_SHIFT 25 +#define DC3_VBI_EVEN_LINE_MASK 0xFE000000 + +/* DC3_COLOR_KEY DEFINITIONS */ + +#define DC3_CLR_KEY_DATA_MASK 0x00FFFFFF +#define DC3_CLR_KEY_ENABLE 0x01000000 + +/* DC3_IRQ DEFINITIONS */ + +#define DC3_IRQ_MASK 0x00000001 +#define DC3_VSYNC_IRQ_MASK 0x00000002 +#define DC3_IRQ_STATUS 0x00010000 +#define DC3_VSYNC_IRQ_STATUS 0x00020000 + +/* DC3_GENLK_CTL DEFINITIONS */ + +#define DC3_GC_FLICKER_FILTER_NONE 0x00000000 +#define DC3_GC_FLICKER_FILTER_1_16 0x10000000 +#define DC3_GC_FLICKER_FILTER_1_8 0x20000000 +#define DC3_GC_FLICKER_FILTER_1_4 0x40000000 +#define DC3_GC_FLICKER_FILTER_5_16 0x50000000 +#define DC3_GC_FLICKER_FILTER_MASK 0xF0000000 +#define DC3_GC_ALPHA_FLICK_ENABLE 0x02000000 +#define DC3_GC_FLICKER_FILTER_ENABLE 0x01000000 +#define DC3_GC_VIP_VID_OK 0x00800000 +#define DC3_GC_GENLK_ACTIVE 0x00400000 +#define DC3_GC_SKEW_WAIT 0x00200000 +#define DC3_GC_VSYNC_WAIT 0x00100000 +#define DC3_GC_GENLOCK_TO_ENABLE 0x00080000 +#define DC3_GC_GENLOCK_ENABLE 0x00040000 +#define DC3_GC_GENLOCK_SKEW_MASK 0x0003FFFF + +/* VGA DEFINITIONS */ + +#define DC3_SEQUENCER_INDEX 0x03C4 +#define DC3_SEQUENCER_DATA 0x03C5 +#define DC3_SEQUENCER_RESET 0x00 +#define DC3_SEQUENCER_CLK_MODE 0x01 + +#define DC3_RESET_VGA_DISP_ENABLE 0x03 +#define DC3_CLK_MODE_SCREEN_OFF 0x20 + +/* DOT CLOCK FREQUENCY STRUCTURE */ +/* Note that m, n and p refer to the register m, n and p */ +/* and not the m, n and p from the PLL equation. The PLL */ +/* equation adds 1 to each value. */ + +typedef struct tagPLLFrequency +{ + unsigned long pll_value; + unsigned long frequency; + +} PLL_FREQUENCY; + +/* VG MSRS */ + +#define DC3_SPARE_MSR 0x2011 +#define DC3_RAM_CTL 0x2012 + +/* DC3_SPARE_MSR DEFINITIONS */ + +#define DC3_SPARE_DISABLE_CFIFO_HGO 0x00000800 +#define DC3_SPARE_VFIFO_ARB_SELECT 0x00000400 +#define DC3_SPARE_WM_LPEN_OVRD 0x00000200 +#define DC3_SPARE_LOAD_WM_LPEN_MASK 0x00000100 +#define DC3_SPARE_DISABLE_INIT_VID_PRI 0x00000080 +#define DC3_SPARE_DISABLE_VFIFO_WM 0x00000040 +#define DC3_SPARE_DISABLE_CWD_CHECK 0x00000020 +#define DC3_SPARE_PIX8_PAN_FIX 0x00000010 +#define DC3_SPARE_FIRST_REQ_MASK 0x00000002 + +/* VG DIAG DEFINITIONS */ + +#define DC3_MBD_DIAG_EN0 0x00008000 +#define DC3_MBD_DIAG_EN1 0x80000000 +#define DC3_DIAG_DOT_CRTC_DP 0x00000082 +#define DC3_DIAG_DOT_CRTC_DP_HIGH 0x00820000 +#define DC3_DIAG_EVEN_FIELD 0x00002000 + +/*----------------------------------------------------------------*/ +/* DISPLAY FILTER DEFINITIONS */ +/*----------------------------------------------------------------*/ + +#define DF_VIDEO_CONFIG 0x00000000 +#define DF_DISPLAY_CONFIG 0x00000008 +#define DF_VIDEO_X_POS 0x00000010 +#define DF_VIDEO_Y_POS 0x00000018 +#define DF_VIDEO_SCALER 0x00000020 +#define DF_VIDEO_COLOR_KEY 0x00000028 +#define DF_VIDEO_COLOR_MASK 0x00000030 +#define DF_PALETTE_ADDRESS 0x00000038 +#define DF_PALETTE_DATA 0x00000040 +#define DF_SATURATION_LIMIT 0x00000048 +#define DF_VID_MISC 0x00000050 +#define DF_VIDEO_YSCALE 0x00000060 +#define DF_VIDEO_XSCALE 0x00000068 +#define DF_VID_CRC 0x00000088 +#define DF_VID_CRC32 0x00000090 +#define DF_VID_ALPHA_CONTROL 0x00000098 +#define DF_CURSOR_COLOR_KEY 0x000000A0 +#define DF_CURSOR_COLOR_MASK 0x000000A8 +#define DF_CURSOR_COLOR_1 0x000000B0 +#define DF_CURSOR_COLOR_2 0x000000B8 +#define DF_ALPHA_XPOS_1 0x000000C0 +#define DF_ALPHA_YPOS_1 0x000000C8 +#define DF_ALPHA_COLOR_1 0x000000D0 +#define DF_ALPHA_CONTROL_1 0x000000D8 +#define DF_ALPHA_XPOS_2 0x000000E0 +#define DF_ALPHA_YPOS_2 0x000000E8 +#define DF_ALPHA_COLOR_2 0x000000F0 +#define DF_ALPHA_CONTROL_2 0x000000F8 +#define DF_ALPHA_XPOS_3 0x00000100 +#define DF_ALPHA_YPOS_3 0x00000108 +#define DF_ALPHA_COLOR_3 0x00000110 +#define DF_ALPHA_CONTROL_3 0x00000118 +#define DF_VIDEO_REQUEST 0x00000120 +#define DF_ALPHA_WATCH 0x00000128 +#define DF_VIDEO_TEST_MODE 0x00000130 +#define DF_VID_YPOS_EVEN 0x00000138 +#define DF_VID_ALPHA_Y_EVEN_1 0x00000140 +#define DF_VID_ALPHA_Y_EVEN_2 0x00000148 +#define DF_VID_ALPHA_Y_EVEN_3 0x00000150 +#define DF_VIDEO_PANEL_TIM1 0x00000400 +#define DF_VIDEO_PANEL_TIM2 0x00000408 +#define DF_POWER_MANAGEMENT 0x00000410 +#define DF_DITHER_CONTROL 0x00000418 +#define DF_DITHER_ACCESS 0x00000448 +#define DF_DITHER_DATA 0x00000450 +#define DF_PANEL_CRC 0x00000458 +#define DF_PANEL_CRC32 0x00000468 +#define DF_COEFFICIENT_BASE 0x00001000 + +/* DF_VIDEO_CONFIG BIT DEFINITIONS */ + +#define DF_VCFG_VID_EN 0x00000001 +#define DF_VCFG_VID_INP_FORMAT 0x0000000C +#define DF_VCFG_SC_BYP 0x00000020 +#define DF_VCFG_LINE_SIZE_LOWER_MASK 0x0000FF00 +#define DF_VCFG_INIT_READ_MASK 0x01FF0000 +#define DF_VCFG_LINE_SIZE_BIT8 0x08000000 +#define DF_VCFG_LINE_SIZE_BIT9 0x04000000 +#define DF_VCFG_4_2_0_MODE 0x10000000 +#define DF_VCFG_UYVY_FORMAT 0x00000000 +#define DF_VCFG_Y2YU_FORMAT 0x00000004 +#define DF_VCFG_YUYV_FORMAT 0x00000008 +#define DF_VCFG_YVYU_FORMAT 0x0000000C + +/* DF_DISPLAY_CONFIG BIT DEFINITIONS */ + +#define DF_DCFG_DIS_EN 0x00000001 +#define DF_DCFG_HSYNC_EN 0x00000002 +#define DF_DCFG_VSYNC_EN 0x00000004 +#define DF_DCFG_DAC_BL_EN 0x00000008 +#define DF_DCFG_CRT_HSYNC_POL 0x00000100 +#define DF_DCFG_CRT_VSYNC_POL 0x00000200 +#define DF_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 +#define DF_DCFG_CRT_SYNC_SKW_INIT 0x00010000 +#define DF_DCFG_PWR_SEQ_DLY_MASK 0x000E0000 +#define DF_DCFG_PWR_SEQ_DLY_INIT 0x00080000 +#define DF_DCFG_VG_CK 0x00100000 +#define DF_DCFG_GV_PAL_BYP 0x00200000 +#define DF_DAC_VREF 0x04000000 + +/* DF_VID_MISC BIT DEFINITIONS */ + +#define DF_GAMMA_BYPASS_BOTH 0x00000001 +#define DF_DAC_POWER_DOWN 0x00000400 +#define DF_ANALOG_POWER_DOWN 0x00000800 +#define DF_USER_IMPLICIT_SCALING 0x00001000 + +/* DF_VID_ALPHA_CONTROL DEFINITIONS */ + +#define DF_HD_VIDEO 0x00000040 +#define DF_YUV_CSC_EN 0x00000080 +#define DF_NO_CK_OUTSIDE_ALPHA 0x00000100 +#define DF_HD_GRAPHICS 0x00000200 +#define DF_CSC_VIDEO_YUV_TO_RGB 0x00000400 +#define DF_CSC_GRAPHICS_RGB_TO_YUV 0x00000800 +#define DF_CSC_VOP_RGB_TO_YUV 0x00001000 +#define DF_VIDEO_INPUT_IS_RGB 0x00002000 +#define DF_VID_ALPHA_EN 0x00004000 +#define DF_ALPHA_DRGB 0x00008000 + +/* VIDEO CURSOR COLOR KEY DEFINITIONS */ + +#define DF_CURSOR_COLOR_KEY_ENABLE 0x20000000 + +/* ALPHA COLOR BIT DEFINITION */ + +#define DF_ALPHA_COLOR_ENABLE 0x01000000 + +/* ALPHA CONTROL BIT DEFINITIONS */ + +#define DF_ACTRL_WIN_ENABLE 0x00010000 +#define DF_ACTRL_LOAD_ALPHA 0x00020000 +#define DF_ACTRL_PERPIXEL_EN 0x00040000 + +/* DF_VIDEO_SCALER DEFINITIONS */ + +#define DF_SCALE_128_PHASES 0x00002000 +#define DF_SCALE_DOUBLE_H_DOWNSCALE 0x00004000 + +/* DEFAULT PANEL TIMINGS DEFINITIONS */ + +#define DF_DEFAULT_TFT_PMTIM1 0x00000000 +#define DF_DEFAULT_XVGA_PMTIM1 0x00000000 +#define DF_DEFAULT_TFT_PMTIM2 0x08C00000 +#define DF_DEFAULT_XVGA_PMTIM2 0x08C10000 +#define DF_DEFAULT_TFT_PAD_SEL_LOW 0xDFFFFFFF +#define DF_DEFAULT_TFT_PAD_SEL_HIGH 0x0000003F +#define DF_DEFAULT_XVGA_PAD_SEL_LOW 0x00000000 +#define DF_DEFAULT_XVGA_PAD_SEL_HIGH 0x00000000 +#define DF_DEFAULT_DITHCTL 0x00000070 +#define DF_DEFAULT_TV_PAD_SEL_HIGH 0x000000BF +#define DF_DEFAULT_TV_PAD_SEL_LOW 0xDFFFFFFF +#define DF_INVERT_VOP_CLOCK 0x00000080 + +/* DF_VIDEO_PANEL_TIM2 DEFINITIONS */ + +#define DF_PMTIM2_TFT_PASSHTHROUGH 0x40000000 + +/* DF_POWER_MANAGEMENT DEFINITIONS */ + +#define DF_PM_PANEL_ON 0x01000000 +#define DF_PM_INVERT_SHFCLK 0x00002000 + +/* DISPLAY FILTER MSRS */ + +#define DF_MBD_MSR_DIAG_DF 0x2010 +#define DF_MSR_PAD_SEL 0x2011 +#define DF_DIAG_32BIT_CRC 0x80000000 + +#define DF_OUTPUT_CRT 0x00000000 +#define DF_OUTPUT_PANEL 0x00000008 +#define DF_OUTPUT_VOP 0x00000030 +#define DF_OUTPUT_DRGB 0x00000038 +#define DF_SIMULTANEOUS_CRT_FP 0x00008000 +#define DF_CONFIG_OUTPUT_MASK 0x00000038 + +/*----------------------------------------------------------------*/ +/* MSR DEFINITIONS */ +/*----------------------------------------------------------------*/ + +/*----------------------------*/ +/* STATIC GEODELINK ADRESSES */ +/*----------------------------*/ + +#define MSR_ADDRESS_GLIU0 0x10000000 +#define MSR_ADDRESS_GLIU1 0x40000000 +#define MSR_ADDRESS_GLIU2 0x51010000 +#define MSR_ADDRESS_5535MPCI 0x51000000 +#define MSR_ADDRESS_VAIL 0x00000000 + +/*----------------------------*/ +/* UNIVERSAL DEVICE MSRS */ +/*----------------------------*/ + +#define MSR_GEODELINK_CAP 0x2000 +#define MSR_GEODELINK_CONFIG 0x2001 +#define MSR_GEODELINK_SMI 0x2002 +#define MSR_GEODELINK_ERROR 0x2003 +#define MSR_GEODELINK_PM 0x2004 +#define MSR_GEODELINK_DIAG 0x2005 + +/*----------------------------*/ +/* DEVICE CLASS CODES */ +/*----------------------------*/ + +#define MSR_CLASS_CODE_GLIU 0x01 +#define MSR_CLASS_CODE_GLCP 0x02 +#define MSR_CLASS_CODE_MPCI 0x05 +#define MSR_CLASS_CODE_MC 0x20 +#define MSR_CLASS_CODE_GP 0x3D +#define MSR_CLASS_CODE_VG 0x3E +#define MSR_CLASS_CODE_DF 0x3F +#define MSR_CLASS_CODE_FG 0xF0 +#define MSR_CLASS_CODE_VAIL 0x86 +#define MSR_CLASS_CODE_USB 0x42 +#define MSR_CLASS_CODE_USB2 0x43 +#define MSR_CLASS_CODE_ATAC 0x47 +#define MSR_CLASS_CODE_MDD 0xDF +#define MSR_CLASS_CODE_ACC 0x33 +#define MSR_CLASS_CODE_AES 0x30 +#define MSR_CLASS_CODE_VIP 0x3C +#define MSR_CLASS_CODE_REFLECTIVE 0xFFF +#define MSR_CLASS_CODE_UNPOPULATED 0x7FF + +/*----------------------------*/ +/* GLIU MSR DEFINITIONS */ +/*----------------------------*/ + +#define MSR_GLIU_CAP 0x0086 +#define MSR_GLIU_WHOAMI 0x008B + +#define NUM_PORTS_MASK 0x00380000 +#define NUM_PORTS_SHIFT 19 +#define WHOAMI_MASK 0x07 + +/*----------------------------*/ +/* GLCP MSR DEFINITIONS */ +/*----------------------------*/ + +#define GLCP_CLKOFF 0x0010 +#define GLCP_CLKACTIVE 0x0011 +#define GLCP_CLKDISABLE 0x0012 +#define GLCP_CLK4ACK 0x0013 +#define GLCP_SYS_RSTPLL 0x0014 +#define GLCP_DOTPLL 0x0015 +#define GLCP_DBGCLKCTL 0x0016 +#define GLCP_REVID 0x0017 +#define GLCP_RAW_DIAG 0x0028 +#define GLCP_SETM0CTL 0x0040 +#define GLCP_SETN0CTL 0x0048 +#define GLCP_CMPVAL0 0x0050 +#define GLCP_CMPMASK0 0x0051 +#define GLCP_REGA 0x0058 +#define GLCP_REGB 0x0059 +#define GLCP_REGAMASK 0x005A +#define GLCP_REGAVAL 0x005B +#define GLCP_REGBMASK 0x005C +#define GLCP_REGBVAL 0x005D +#define GLCP_FIFOCTL 0x005E +#define GLCP_DIAGCTL 0x005F +#define GLCP_H0CTL 0x0060 +#define GLCP_XSTATE 0x0066 +#define GLCP_YSTATE 0x0067 +#define GLCP_ACTION0 0x0068 + +/* GLCP_DOTPLL DEFINITIONS */ + +#define GLCP_DOTPLL_RESET 0x00000001 +#define GLCP_DOTPLL_BYPASS 0x00008000 +#define GLCP_DOTPLL_HALFPIX 0x01000000 +#define GLCP_DOTPLL_LOCK 0x02000000 +#define GLCP_DOTPLL_VIPCLK 0x00008000 +#define GLCP_DOTPLL_DIV4 0x00010000 + +/* GLCP DIAG DEFINITIONS */ + +#define GLCP_MBD_DIAG_SEL0 0x00000007 +#define GLCP_MBD_DIAG_EN0 0x00008000 +#define GLCP_MBD_DIAG_SEL1 0x00070000 +#define GLCP_MBD_DIAG_EN1 0x80000000 + +/*--------------------------------*/ +/* DISPLAY FILTER MSR DEFINITIONS */ +/*--------------------------------*/ + +/* DISPLAY FILTER MBD_MSR_DIAG DEFINITIONS */ + +#define DF_MBD_DIAG_SEL0 0x00007FFF +#define DF_MBD_DIAG_EN0 0x00008000 +#define DF_MBD_DIAG_SEL1 0x7FFF0000 +#define DF_MBD_DIAG_EN1 0x80000000 + +/* DISPLAY FILTER MBD_MSR_CONFIG DEFINITIONS */ + +#define DF_CONFIG_FMT_MASK 0x00000038 +#define DF_CONFIG_FMT_CRT 0x00000000 +#define DF_CONFIG_FMT_FP 0x00000008 + +/*----------------------------------------------------------------*/ +/* PCI DEFINITIONS */ +/*----------------------------------------------------------------*/ + +#define PCI_VENDOR_DEVICE_GEODEGX 0x0028100B +#define PCI_VENDOR_DEVICE_GEODEGX_VIDEO 0x0030100B +#define PCI_VENDOR_DEVICE_GEODELX 0x20801022 +#define PCI_VENDOR_DEVICE_GEODELX_VIDEO 0x20811022 +#define PCI_VENDOR_5535 0x002B100B +#define PCI_VENDOR_5536 0x20901022 + +/*----------------------------------------------------------------*/ +/* VIP DEFINITIONS */ +/*----------------------------------------------------------------*/ + +#define VIP_CONTROL1 0x00000000 +#define VIP_CONTROL2 0x00000004 +#define VIP_STATUS 0x00000008 +#define VIP_INTERRUPT 0x0000000C +#define VIP_CURRENT_TARGET 0x00000010 +#define VIP_MAX_ADDRESS 0x00000014 +#define VIP_TASKA_VID_EVEN_BASE 0x00000018 +#define VIP_TASKA_VID_ODD_BASE 0x0000001C +#define VIP_TASKA_VBI_EVEN_BASE 0x00000020 +#define VIP_TASKA_VBI_ODD_BASE 0x00000024 +#define VIP_TASKA_VID_PITCH 0x00000028 +#define VIP_CONTROL3 0x0000002C +#define VIP_TASKA_V_OFFSET 0x00000030 +#define VIP_TASKA_U_OFFSET 0x00000034 +#define VIP_TASKB_VID_EVEN_BASE 0x00000038 +#define VIP_601_HORZ_END 0x00000038 +#define VIP_TASKB_VID_ODD_BASE 0x0000003C +#define VIP_601_HORZ_START 0x0000003C +#define VIP_TASKB_VBI_EVEN_BASE 0x00000040 +#define VIP_601_VBI_END 0x00000040 +#define VIP_TASKB_VBI_ODD_BASE 0x00000044 +#define VIP_601_VBI_START 0x00000044 +#define VIP_TASKB_VID_PITCH 0x00000048 +#define VIP_601_EVEN_START_STOP 0x00000048 +#define VIP_TASKB_V_OFFSET 0x00000050 +#define VIP_ODD_FIELD_DETECT 0x00000050 +#define VIP_TASKB_U_OFFSET 0x00000054 +#define VIP_ANC_MSG1_BASE 0x00000058 +#define VIP_ANC_MSG2_BASE 0x0000005C +#define VIP_ANC_MSG_SIZE 0x00000060 +#define VIP_PAGE_OFFSET 0x00000068 +#define VIP_VERTICAL_START_STOP 0x0000006C +#define VIP_601_ODD_START_STOP 0x0000006C +#define VIP_FIFO_ADDRESS 0x00000070 +#define VIP_FIFO_DATA 0x00000074 +#define VIP_VSYNC_ERR_COUNT 0x00000078 +#define VIP_TASKA_U_EVEN_OFFSET 0x0000007C +#define VIP_TASKA_V_EVEN_OFFSET 0x00000080 + +/* INDIVIDUAL REGISTER BIT DEFINITIONS */ +/* Multibit register subsets are expressed as a mask and shift. */ +/* Single bit values are represented as a mask. */ + +/* VIP_CONTROL1 REGISTER DEFINITIONS */ + +#define VIP_CONTROL1_DEFAULT_ANC_FF 2 +#define VIP_CONTROL1_ANC_FF_MASK 0xE0000000 +#define VIP_CONTROL1_ANC_FF_SHIFT 29 + +#define VIP_CONTROL1_DEFAULT_VID_FF 2 +#define VIP_CONTROL1_VID_FF_MASK 0x1F000000 +#define VIP_CONTROL1_VID_FF_SHIFT 24 + +#define VIP_CONTROL1_VDE_FF_MASK 0x00F00000 +#define VIP_CONTROL1_VDE_FF_SHIFT 20 + +#define VIP_CONTROL1_NON_INTERLACED (1L << 19) +#define VIP_CONTROL1_MSG_STRM_CTRL (1L << 18) +#define VIP_CONTROL1_DISABLE_ZERO_DETECT (1L << 17) +#define VIP_CONTROL1_DISABLE_DECIMATION (1L << 16) + +#define VIP_CONTROL1_CAPTURE_ENABLE_MASK 0x0000FF00 +#define VIP_CONTROL1_CAPTURE_ENABLE_SHIFT 8 + +#define VIP_CONTROL1_RUNMODE_MASK 0x000000E0 +#define VIP_CONTROL1_RUNMODE_SHIFT 5 + +#define VIP_CONTROL1_PLANAR (1L << 4) + +#define VIP_CONTROL1_MODE_MASK 0x0000000E +#define VIP_CONTROL1_MODE_SHIFT 1 + +#define VIP_CONTROL1_RESET 0x00000001 + +/* VIP_CONTROL2 REGISTER DEFINITIONS */ + +#define VIP_CONTROL2_INVERT_POLARITY (1L << 31) +#define VIP_CONTROL2_ADD_ERROR_ENABLE (1L << 30) +#define VIP_CONTROL2_REPEAT_ENABLE (1L << 29) +#define VIP_CONTROL2_SWC_ENABLE (1L << 28) +#define VIP_CONTROL2_ANC10 (1L << 27) +#define VIP_CONTROL2_ANCPEN (1L << 26) +#define VIP_CONTROL2_LOOPBACK_ENABLE (1L << 25) +#define VIP_CONTROL2_FIFO_ACCESS (1L << 24) +#define VIP_CONTROL2_VERTERROR_ENABLE (1L << 15) + +#define VIP_CONTROL2_PAGECNT_MASK 0x00E00000 +#define VIP_CONTROL2_PAGECNT_SHIFT 21 + +#define VIP_CONTROL2_DEFAULT_ANCTH 5 +#define VIP_CONTROL2_ANCTH_MASK 0x001F0000 +#define VIP_CONTROL2_ANCTH_SHIFT 16 + +#define VIP_CONTROL2_DEFAULT_VIDTH_420 19 +#define VIP_CONTROL2_DEFAULT_VIDTH_422 19 +#define VIP_CONTROL2_VIDTH_MASK 0x00007F00 +#define VIP_CONTROL2_VIDTH_SHIFT 8 + +#define VIP_CONTROL2_SYNC2PIN_MASK 0x000000E0 +#define VIP_CONTROL2_SYNC2PIN_SHIFT 5 + +#define VIP_CONTROL2_FIELD2VG_MASK 0x00000018 +#define VIP_CONTROL2_FIELD2VG_SHIFT 3 + +#define VIP_CONTROL2_SYNC2VG_MASK 0x00000007 +#define VIP_CONTROL2_SYNC2VG_SHIFT 0 + +/* VIP_CONTROL3 REGISTER DEFINITIONS */ + +#define VIP_CONTROL3_PLANAR_DEINT 0x00000400 +#define VIP_CONTROL3_BASE_UPDATE 0x00000200 +#define VIP_CONTROL3_DISABLE_OVERFLOW 0x00000100 +#define VIP_CONTROL3_DECIMATE_EVEN 0x00000080 +#define VIP_CONTROL3_TASK_POLARITY 0x00000040 +#define VIP_CONTROL3_VSYNC_POLARITY 0x00000020 +#define VIP_CONTROL3_HSYNC_POLARITY 0x00000010 +#define VIP_CONTROL3_FIFO_RESET 0x00000001 + +/* VIP_STATUS REGISTER DEFINITIONS */ + +#define VIP_STATUS_ANC_COUNT_MASK 0xFF000000 +#define VIP_STATUS_ANC_COUNT_SHIFT 24 + +#define VIP_STATUS_FIFO_ERROR 0x00700000 +#define VIP_STATUS_ERROR_SHIFT 20 +#define VIP_STATUS_DEC_COUNT (1L << 18) +#define VIP_STATUS_SYNCOUT (1L << 17) +#define VIP_STATUS_BASEREG_NOTUPDT (1L << 16) +#define VIP_STATUS_MSGBUFF_ERR (1L << 14) +#define VIP_STATUS_MSGBUFF2_FULL (1L << 13) +#define VIP_STATUS_MSGBUFF1_FULL (1L << 12) +#define VIP_STATUS_WRITES_COMPLETE (1L << 9) +#define VIP_STATUS_FIFO_EMPTY (1L << 8) +#define VIP_STATUS_FIELD (1L << 4) +#define VIP_STATUS_VBLANK (1L << 3) + +#define VIP_STATUS_RUN_MASK 0x00000007 +#define VIP_STATUS_RUN_SHIFT 0 + +/* VIP_CURRENT_TARGET REGISTER DEFINITIONS */ + +#define VIP_CTARGET_TLINE_MASK 0xFFFF0000 +#define VIP_CTARGET_TLINE_SHIFT 16 + +#define VIP_CTARGET_CLINE_MASK 0x0000FFFF +#define VIP_CTARGET_CLINE_SHIFT 0 + +/* VIP_MAX_ADDRESS REGISTER DEFINITIONS */ + +#define VIP_MAXADDR_MASK 0xFFFFFFFF +#define VIP_MAXADDR_SHIFT 0 + +/* VIP BUFFER PITCH DEFINITIONS */ + +#define VIP_TASK_PITCH_MASK 0x0000FFFF +#define VIP_TASK_PITCH_SHIFT 0 + +/* VERTICAL START/STOP */ + +#define VIP_VSTART_VERTEND_MASK 0x0FFF0000 +#define VIP_VSTART_VERTEND_SHIFT 16 + +#define VIP_VSTART_VERTSTART_MASK 0x00000FFF +#define VIP_VSTART_VERTSTART_SHIFT 0 + +/* VIP FIFO ADDRESS DEFINITIONS */ + +#define VIP_FIFO_ADDRESS_MASK 0x000000FF +#define VIP_FIFO_ADDRESS_SHIFT 0 + +/* VIP VSYNC ERROR DEFINITIONS */ + +#define VIP_VSYNC_ERR_WINDOW_MASK 0xFF000000 +#define VIP_VSYNC_ERR_WINDOW_SHIFT 24 + +#define VIP_VSYNC_ERR_COUNT_MASK 0x00FFFFFF +#define VIP_VSYNC_ERR_COUNT_SHIFT 0 + +/*---------------------*/ +/* VIP MSR DEFINITIONS */ +/*---------------------*/ + +/* CAPABILITIES */ + +#define VIP_MSR_CAP_NSMI_MASK 0xF8000000 +#define VIP_MSR_CAP_NSMI_SHIFT 27 +#define VIP_MSR_CAP_NCLK_MASK 0x07000000 +#define VIP_MSR_CAP_NCLK_SHIFT 24 +#define VIP_MSR_CAP_DEVID_MASK 0x00FFFF00 +#define VIP_MSR_CAP_DEVID_SHIFT 8 +#define VIP_MSR_CAP_REVID_MASK 0x000000FF +#define VIP_MSR_CAP_REVID_SHIFT 0 + +/* MASTER CONFIG */ + +#define VIP_MSR_MCR_SECOND_PRIORITY_MASK 0x00000700 +#define VIP_MSR_MCR_SECOND_PRIORITY_SHIFT 8 +#define VIP_MSR_MCR_PRIMARY_PRIORITY_MASK 0x00000070 +#define VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT 4 +#define VIP_MSR_MCR_PID_MASK 0x00000007 +#define VIP_MSR_MCR_PID_SHIFT 0 + +/* VIP SMI */ + +#define VIP_MSR_SMI_FIFO_OVERFLOW (1L << 29) +#define VIP_MSR_SMI_FIFO_THRESHOLD (1L << 28) +#define VIP_MSR_SMI_LONGLINE (1L << 27) +#define VIP_MSR_SMI_VERTICAL_TIMING (1L << 26) +#define VIP_MSR_SMI_ACTIVE_PIXELS (1L << 25) +#define VIP_MSR_SMI_CLOCK_INPUT (1L << 24) +#define VIP_MSR_SMI_ANC_CHECKSUM_PARITY (1L << 23) +#define VIP_MSR_SMI_MSG_BUFFER_FULL (1L << 22) +#define VIP_MSR_SMI_END_VBLANK (1L << 21) +#define VIP_MSR_SMI_START_VBLANK (1L << 20) +#define VIP_MSR_SMI_START_EVEN (1L << 19) +#define VIP_MSR_SMI_START_ODD (1L << 18) +#define VIP_MSR_SMI_LINE_MATCH_TARGET (1L << 17) +#define VIP_MSR_SMI_GLINK (1L << 16) + +/* VIP ERROR */ + +#define VIP_MSR_ERROR_ADDRESS_MASK (1L << 17) +#define VIP_MSR_ERROR_ADDRESS_SHIFT 17 +#define VIP_MSR_ERROR_ADDRESS_ENABLE (1L << 1) +#define VIP_MSR_ERROR_ADDRESS_EN_SHIFT 1 +#define VIP_MSR_ERROR_TYPE_MASK (1L << 16) +#define VIP_MSR_ERROR_TYPE_SHIFT 16 +#define VIP_MSR_ERROR_TYPE_ENABLE 1 +#define VIP_MSR_ERROR_TYPE_EN_SHIFT 0 + +/* VIP POWER */ + +#define VIP_MSR_POWER_GLINK (1L << 0) +#define VIP_MSR_POWER_CLOCK (1L << 2) + +/* VIP DIAG */ + +#define VIP_MSR_DIAG_BIST_WMASK 0x00000003 +#define VIP_MSR_DIAG_BIST_RMASK 0x00000007 +#define VIP_MSR_DIAG_BIST_SHIFT 0 + +#define VIP_MSR_DIAG_MSB_ENABLE (1L << 31) +#define VIP_MSR_DIAG_SEL_UPPER_MASK 0x7FFF0000 +#define VIP_MSR_DIAG_SEL_UPPER_SHIFT 16 +#define VIP_MSR_DIAG_LSB_ENABLE (1L << 15) +#define VIP_MSR_DIAG_SEL_LOWER_MASK 0x00007FFF +#define VIP_MSR_DIAG_SEL_LOWER_SHIFT 0 + +/*----------------------------------------------------------------*/ +/* VOP DEFINITIONS */ +/*----------------------------------------------------------------*/ + +#define VOP_CONFIGURATION 0x00000800 +#define VOP_SIGNATURE 0x00000808 + +/* VOP_CONFIGURATION BIT DEFINITIONS */ + +#define VOP_CONFIG_SWAPVBI 0x01000000 +#define VOP_CONFIG_RGBMODE 0x00200000 +#define VOP_CONFIG_SIGVAL 0x00100000 +#define VOP_CONFIG_INVERT_DISPE 0x00080000 +#define VOP_CONFIG_INVERT_VSYNC 0x00040000 +#define VOP_CONFIG_INVERT_HSYNC 0x00020000 +#define VOP_CONFIG_SWAPUV 0x00010000 +#define VOP_CONFIG_VSYNC_MASK 0x0000C000 +#define VOP_CONFIG_DISABLE_DECIMATE 0x00002000 +#define VOP_CONFIG_ENABLE_601 0x00001000 +#define VOP_CONFIG_VBI 0x00000800 +#define VOP_CONFIG_TASK 0x00000200 +#define VOP_CONFIG_SIG_FREE_RUN 0x00000100 +#define VOP_CONFIG_ENABLE_SIGNATURE 0x00000080 +#define VOP_CONFIG_SC_COMPATIBLE 0x00000040 +#define VOP_CONFIG_422_COSITED 0x00000000 +#define VOP_CONFIG_422_INTERSPERSED 0x00000010 +#define VOP_CONFIG_422_ALTERNATING 0x00000020 +#define VOP_CONFIG_422_MASK 0x00000030 +#define VOP_CONFIG_EXTENDED_SAV 0x00000008 +#define VOP_CONFIG_VIP2_16BIT 0x00000004 +#define VOP_CONFIG_DISABLED 0x00000000 +#define VOP_CONFIG_VIP1_1 0x00000001 +#define VOP_CONFIG_VIP2_0 0x00000002 +#define VOP_CONFIG_CCIR656 0x00000003 +#define VOP_CONFIG_MODE_MASK 0x00000003 + +#endif diff --git a/src/cim/cim_rtns.h b/src/cim/cim_rtns.h new file mode 100644 index 0000000..ce149cd --- /dev/null +++ b/src/cim/cim_rtns.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron function prototypes. + */ + +#ifndef _cim_rtns_h +#define _cim_rtns_h + +/* INCLUDE USER PARAMETER DEFINITIONS */ + +#include "cim_parm.h" + +/* COMPILER OPTION FOR C++ PROGRAMS */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*--------------------------*/ +/* CIMARRON MEMORY POINTERS */ +/*--------------------------*/ + + extern unsigned char *cim_gp_ptr; + extern unsigned char *cim_fb_ptr; + extern unsigned char *cim_cmd_base_ptr; + extern unsigned char *cim_cmd_ptr; + extern unsigned char *cim_vid_ptr; + extern unsigned char *cim_vip_ptr; + extern unsigned char *cim_vg_ptr; + +/*----------------------------------------*/ +/* INITIALIZATION ROUTINE DEFINITIONS */ +/*----------------------------------------*/ + + int init_detect_cpu(unsigned long *cpu_revision, + unsigned long *companion_revision); + unsigned long init_read_pci(unsigned long address); + int init_read_base_addresses(INIT_BASE_ADDRESSES * base_addresses); + int init_read_cpu_frequency(unsigned long *cpu_frequency); + +/*----------------------------------------*/ +/* GRAPHICS PROCESSOR ROUTINE DEFINITIONS */ +/*----------------------------------------*/ + + void gp_set_limit_on_buffer_lead(unsigned long lead); + void gp_set_command_buffer_base(unsigned long address, + unsigned long start, unsigned long stop); + void gp_set_frame_buffer_base(unsigned long address, unsigned long size); + void gp_set_bpp(int bpp); + void gp_declare_blt(unsigned long flags); + void gp_declare_vector(unsigned long flags); + void gp_write_parameters(void); + void gp_set_raster_operation(unsigned char ROP); + void gp_set_alpha_operation(int alpha_operation, int alpha_type, + int channel, int apply_alpha, unsigned char alpha); + void gp_set_solid_pattern(unsigned long color); + void gp_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, int transparent, int x, + int y); + void gp_set_pattern_origin(int x, int y); + void gp_set_color_pattern(unsigned long *pattern, int format, int x, + int y); + void gp_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + int transparent); + void gp_set_solid_source(unsigned long color); + void gp_set_source_transparency(unsigned long color, unsigned long mask); + void gp_program_lut(unsigned long *colors, int full_lut); + void gp_set_vector_pattern(unsigned long pattern, unsigned long color, + int length); + void gp_set_strides(unsigned long dst_stride, unsigned long src_stride); + void gp_set_source_format(int format); + void gp_pattern_fill(unsigned long dstoffset, unsigned long width, + unsigned long height); + void gp_screen_to_screen_blt(unsigned long dstoffset, + unsigned long srcoffset, unsigned long width, + unsigned long height, int flags); + void gp_screen_to_screen_convert(unsigned long dstoffset, + unsigned long srcoffset, unsigned long width, + unsigned long height, int nibble); + void gp_color_bitmap_to_screen_blt(unsigned long dstoffset, + unsigned long srcx, unsigned long width, unsigned long height, + unsigned char *data, long pitch); + void gp_color_convert_blt(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, unsigned char *data, + long pitch); + void gp_custom_convert_blt(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, unsigned char *data, + long pitch); + void gp_rotate_blt(unsigned long dstoffset, unsigned long srcoffset, + unsigned long width, unsigned long height, int degrees); + void gp_mono_bitmap_to_screen_blt(unsigned long dstoffset, + unsigned long srcx, unsigned long width, unsigned long height, + unsigned char *data, long stride); + void gp_text_blt(unsigned long dstoffset, unsigned long width, + unsigned long height, unsigned char *data); + void gp_mono_expand_blt(unsigned long dstoffset, unsigned long srcoffset, + unsigned long srcx, unsigned long width, unsigned long height, + int byte_packed); + void gp_antialiased_text(unsigned long dstoffset, unsigned long srcx, + unsigned long width, unsigned long height, unsigned char *data, + long stride, int fourbpp); + void gp_masked_blt(unsigned long dstoffset, unsigned long width, + unsigned long height, unsigned long mono_srcx, + unsigned long color_srcx, unsigned char *mono_mask, + unsigned char *color_data, long mono_pitch, long color_pitch); + void gp_screen_to_screen_masked(unsigned long dstoffset, + unsigned long srcoffset, unsigned long width, + unsigned long height, unsigned long mono_srcx, + unsigned char *mono_mask, long mono_pitch); + void gp_bresenham_line(unsigned long dstoffset, unsigned short length, + unsigned short initerr, unsigned short axialerr, + unsigned short diagerr, unsigned long flags); + void gp_line_from_endpoints(unsigned long dstoffset, unsigned long x0, + unsigned long y0, unsigned long x1, unsigned long y1, int inclusive); + + int gp_test_blt_pending(void); + void gp_wait_blt_pending(void); + void gp_wait_until_idle(void); + int gp_test_blt_busy(void); + void gp_save_state(GP_SAVE_RESTORE * gp_state); + void gp_restore_state(GP_SAVE_RESTORE * gp_state); + +/*----------------------------------------*/ +/* VIDEO GENERATOR ROUTINE DEFINITIONS */ +/*----------------------------------------*/ + + int vg_delay_milliseconds(unsigned long ms); + int vg_set_display_mode(unsigned long src_width, unsigned long src_height, + unsigned long dst_width, unsigned long dst_height, int bpp, int hz, + unsigned long flags); + int vg_set_panel_mode(unsigned long src_width, unsigned long src_height, + unsigned long dst_width, unsigned long dst_height, + unsigned long panel_width, unsigned long panel_height, + int bpp, unsigned long flags); + int vg_set_tv_mode(unsigned long *src_width, unsigned long *src_height, + unsigned long encoder, unsigned long tvres, int bpp, + unsigned long flags, unsigned long h_overscan, + unsigned long v_overscan); + int vg_set_custom_mode(VG_DISPLAY_MODE * mode_params, int bpp); + int vg_set_display_bpp(int bpp); + int vg_get_display_mode_index(VG_QUERY_MODE * query); + int vg_get_display_mode_information(unsigned int index, + VG_DISPLAY_MODE * vg_mode); + int vg_get_display_mode_count(void); + int vg_get_current_display_mode(VG_DISPLAY_MODE * current_display, + int *bpp); + int vg_set_scaler_filter_coefficients(long h_taps[][5], long v_taps[][3]); + int vg_configure_flicker_filter(unsigned long flicker_strength, + int flicker_alpha); + int vg_set_clock_frequency(unsigned long frequency, + unsigned long pll_flags); + int vg_set_border_color(unsigned long border_color); + int vg_set_cursor_enable(int enable); + int vg_set_mono_cursor_colors(unsigned long bkcolor, + unsigned long fgcolor); + int vg_set_cursor_position(long xpos, long ypos, + VG_PANNING_COORDINATES * panning); + int vg_set_mono_cursor_shape32(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask, + unsigned long x_hotspot, unsigned long y_hotspot); + int vg_set_mono_cursor_shape64(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask, + unsigned long x_hotspot, unsigned long y_hotspot); + int vg_set_color_cursor_shape(unsigned long memoffset, + unsigned char *data, unsigned long width, unsigned long height, + long pitch, unsigned long x_hotspot, unsigned long y_hotspot); + int vg_pan_desktop(unsigned long x, unsigned long y, + VG_PANNING_COORDINATES * panning); + int vg_set_display_offset(unsigned long address); + int vg_set_display_pitch(unsigned long pitch); + int vg_set_display_palette_entry(unsigned long index, + unsigned long palette); + int vg_set_display_palette(unsigned long *palette); + int vg_set_compression_enable(int enable); + int vg_configure_compression(VG_COMPRESSION_DATA * comp_data); + int vg_test_timing_active(void); + int vg_test_vertical_active(void); + int vg_wait_vertical_blank(void); + int vg_test_even_field(void); + int vg_configure_line_interrupt(VG_INTERRUPT_PARAMS * interrupt_info); + unsigned long vg_test_and_clear_interrupt(void); + unsigned long vg_test_flip_status(void); + int vg_save_state(VG_SAVE_RESTORE * vg_state); + int vg_restore_state(VG_SAVE_RESTORE * vg_state); + +/*----------------------------------------*/ +/* VIDEO GENERATOR READ ROUTINES */ +/*----------------------------------------*/ + + unsigned long vg_read_graphics_crc(int crc_source); + unsigned long vg_read_window_crc(int crc_source, unsigned long x, + unsigned long y, unsigned long width, unsigned long height); + int vg_get_scaler_filter_coefficients(long h_taps[][5], long v_taps[][3]); + int vg_get_flicker_filter_configuration(unsigned long *strength, + int *flicker_alpha); + unsigned long vg_get_display_pitch(void); + unsigned long vg_get_frame_buffer_line_size(void); + unsigned long vg_get_current_vline(void); + unsigned long vg_get_display_offset(void); + int vg_get_cursor_info(VG_CURSOR_DATA * cursor_data); + int vg_get_display_palette_entry(unsigned long index, + unsigned long *entry); + unsigned long vg_get_border_color(void); + int vg_get_display_palette(unsigned long *palette); + int vg_get_compression_info(VG_COMPRESSION_DATA * comp_data); + int vg_get_compression_enable(void); + int vg_get_valid_bit(int line); + +/*----------------------------------------*/ +/* DISPLAY FILTER ROUTINE DEFINITIONS */ +/*----------------------------------------*/ + + int df_set_crt_enable(int crt_output); + int df_set_panel_enable(int panel_output); + int df_configure_video_source(DF_VIDEO_SOURCE_PARAMS * video_source_odd, + DF_VIDEO_SOURCE_PARAMS * video_source_even); + int df_set_video_offsets(int even, unsigned long y_offset, + unsigned long u_offset, unsigned long v_offset); + int df_set_video_scale(unsigned long src_width, unsigned long src_height, + unsigned long dst_width, unsigned long dst_height, + unsigned long flags); + int df_set_video_position(DF_VIDEO_POSITION * video_window); + int df_set_video_filter_coefficients(long taps[][4], int phase256); + int df_set_video_enable(int enable, unsigned long flags); + int df_set_video_color_key(unsigned long key, unsigned long mask, + int graphics); + int df_set_video_palette(unsigned long *palette); + int df_set_video_palette_entry(unsigned long index, + unsigned long palette); + int df_configure_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * + cursor_color_key); + int df_set_video_cursor_color_key_enable(int enable); + int df_configure_alpha_window(int window, + DF_ALPHA_REGION_PARAMS * alpha_data); + int df_set_alpha_window_enable(int window, int enable); + int df_set_no_ck_outside_alpha(int enable); + int df_set_video_request(unsigned long x, unsigned long y); + int df_set_output_color_space(int color_space); + int df_set_output_path(int format); + unsigned long df_test_video_flip_status(void); + int df_save_state(DF_SAVE_RESTORE * gp_state); + int df_restore_state(DF_SAVE_RESTORE * gp_state); + +/*----------------------------------------*/ +/* DISPLAY FILTER READ ROUTINES */ +/*----------------------------------------*/ + + unsigned long df_read_composite_crc(int crc_source); + unsigned long df_read_composite_window_crc(unsigned long x, + unsigned long y, unsigned long width, unsigned long height, + int source); + unsigned long df_read_panel_crc(void); + int df_get_video_enable(int *enable, unsigned long *flags); + int df_get_video_source_configuration(DF_VIDEO_SOURCE_PARAMS * + video_source_odd, DF_VIDEO_SOURCE_PARAMS * video_source_even); + int df_get_video_position(DF_VIDEO_POSITION * video_window); + int df_get_video_scale(unsigned long *x_scale, unsigned long *y_scale); + int df_get_video_filter_coefficients(long taps[][4], int *phase256); + int df_get_video_color_key(unsigned long *key, unsigned long *mask, + int *graphics); + int df_get_video_palette_entry(unsigned long index, + unsigned long *palette); + int df_get_video_palette(unsigned long *palette); + int df_get_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * + cursor_color_key); + int df_get_video_cursor_color_key_enable(void); + int df_get_alpha_window_configuration(int window, + DF_ALPHA_REGION_PARAMS * alpha_data); + int df_get_alpha_window_enable(int window); + int df_get_video_request(unsigned long *x, unsigned long *y); + int df_get_output_color_space(int *color_space); + +/*----------------------------------------*/ +/* MSR ROUTINE DEFINITIONS */ +/*----------------------------------------*/ + + int msr_init_table(void); + int msr_create_geodelink_table(GEODELINK_NODE * gliu_nodes); + int msr_create_device_list(GEODELINK_NODE * gliu_nodes, int max_devices); + int msr_read64(unsigned long device, unsigned long msr_register, + Q_WORD * msr_value); + int msr_write64(unsigned long device, unsigned long msr_register, + Q_WORD * msr_value); + +/*----------------------------------------*/ +/* VIP ROUTINE DEFINITIONS */ +/*----------------------------------------*/ + + int vip_initialize(VIPSETMODEBUFFER * buffer); + int vip_update_601_params(VIP_601PARAMS * buffer); + int vip_terminate(void); + int vip_configure_capture_buffers(int buffer_type, + VIPINPUTBUFFER * buffer); + int vip_toggle_video_offsets(int buffer_type, VIPINPUTBUFFER * buffer); + int vip_max_address_enable(unsigned long max_address, int enable); + int vip_set_interrupt_enable(unsigned long mask, int enable); + unsigned long vip_get_interrupt_state(void); + int vip_set_capture_state(unsigned long state); + int vip_set_vsync_error(unsigned long vertical_count, + unsigned long window_before, unsigned long window_after, int enable); + int vip_configure_fifo(unsigned long fifo_type, unsigned long fifo_size); + int vip_set_loopback_enable(int bEnable); + int vip_configure_genlock(VIPGENLOCKBUFFER * buffer); + int vip_set_genlock_enable(int bEnable); + int vip_configure_pages(int page_count, unsigned long page_offset); + int vip_set_interrupt_line(int line); + int vip_reset(void); + int vip_set_subwindow_enable(VIPSUBWINDOWBUFFER * buffer); + int vip_reset_interrupt_state(unsigned long interrupt_mask); + + int vip_save_state(VIPSTATEBUFFER * save_buffer); + int vip_restore_state(VIPSTATEBUFFER * restore_buffer); + int vip_set_power_characteristics(VIPPOWERBUFFER * buffer); + int vip_set_priority_characteristics(VIPPRIORITYBUFFER * buffer); + int vip_set_debug_characteristics(VIPDEBUGBUFFER * buffer); + int vip_test_genlock_active(void); + int vip_test_signal_status(void); + unsigned long vip_get_current_field(void); + +/*----------------------------------------*/ +/* VIP READ ROUTINES */ +/*----------------------------------------*/ + + int vip_get_current_mode(VIPSETMODEBUFFER * buffer); + int vip_get_601_configuration(VIP_601PARAMS * buffer); + int vip_get_buffer_configuration(int buffer_type, + VIPINPUTBUFFER * buffer); + int vip_get_genlock_configuration(VIPGENLOCKBUFFER * buffer); + int vip_get_genlock_enable(void); + int vip_is_buffer_update_latched(void); + unsigned long vip_get_capture_state(void); + unsigned long vip_get_current_line(void); + unsigned long vip_read_fifo(unsigned long fifo_address); + int vip_write_fifo(unsigned long fifo_address, unsigned long fifo_data); + int vip_enable_fifo_access(int enable); + int vip_get_capability_characteristics(VIPCAPABILITIESBUFFER * buffer); + int vip_get_power_characteristics(VIPPOWERBUFFER * buffer); + int vip_get_priority_characteristics(VIPPRIORITYBUFFER * buffer); + +/*----------------------------------------*/ +/* VOP ROUTINE DEFINITIONS */ +/*----------------------------------------*/ + + int vop_set_vbi_window(VOPVBIWINDOWBUFFER * buffer); + int vop_enable_vbi_output(int enable); + int vop_set_configuration(VOPCONFIGURATIONBUFFER * config); + int vop_save_state(VOPSTATEBUFFER * save_buffer); + int vop_restore_state(VOPSTATEBUFFER * save_buffer); + +/*----------------------------------------*/ +/* VOP READ ROUTINES */ +/*----------------------------------------*/ + + int vop_get_current_mode(VOPCONFIGURATIONBUFFER * config); + int vop_get_vbi_configuration(VOPVBIWINDOWBUFFER * buffer); + int vop_get_vbi_enable(void); + unsigned long vop_get_crc(void); + unsigned long vop_read_vbi_crc(void); + +/* CLOSE BRACKET FOR C++ COMPLILATION */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cim/cim_version.h b/src/cim/cim_version.h new file mode 100644 index 0000000..ee02b2d --- /dev/null +++ b/src/cim/cim_version.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron Version information + */ + +#define CIMARRON_REVISION 30103 diff --git a/src/cim/cim_vg.c b/src/cim/cim_vg.c new file mode 100644 index 0000000..6a8ea49 --- /dev/null +++ b/src/cim/cim_vg.c @@ -0,0 +1,3711 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron display controller routines. These routines program the display + * mode and configure the hardware cursor and video buffers. + */ + +/*---------------------*/ +/* CIMARRON VG GLOBALS */ +/*---------------------*/ + +CIMARRON_STATIC unsigned long vg3_x_hotspot = 0; +CIMARRON_STATIC unsigned long vg3_y_hotspot = 0; +CIMARRON_STATIC unsigned long vg3_cursor_offset = 0; +CIMARRON_STATIC unsigned long vg3_mode_width = 0; +CIMARRON_STATIC unsigned long vg3_mode_height = 0; +CIMARRON_STATIC unsigned long vg3_panel_width = 0; +CIMARRON_STATIC unsigned long vg3_panel_height = 0; +CIMARRON_STATIC unsigned long vg3_delta_x = 0; +CIMARRON_STATIC unsigned long vg3_delta_y = 0; +CIMARRON_STATIC unsigned long vg3_bpp = 0; + +CIMARRON_STATIC unsigned long vg3_color_cursor = 0; +CIMARRON_STATIC unsigned long vg3_panel_enable = 0; + +/*--------------------------------------------------------------------------- + * vg_delay_milliseconds + * + * This routine delays for a number of milliseconds based on a crude + * delay loop. + *--------------------------------------------------------------------------*/ + +int +vg_delay_milliseconds(unsigned long ms) +{ + /* ASSUME 500 MHZ 20 CLOCKS PER READ */ + + unsigned long loop = ms * 25000; + + while (loop-- > 0) { + READ_REG32(DC3_UNLOCK); + } + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_display_mode + * + * This routine sets a CRT display mode using predefined Cimarron timings. + * The source width and height are specified to allow scaling. + *--------------------------------------------------------------------------*/ + +int +vg_set_display_mode(unsigned long src_width, unsigned long src_height, + unsigned long dst_width, unsigned long dst_height, + int bpp, int hz, unsigned long flags) +{ + VG_QUERY_MODE crt_query; + VG_DISPLAY_MODE crt_mode; + int mode; + + crt_query.active_width = dst_width; + crt_query.active_height = dst_height; + crt_query.bpp = bpp; + crt_query.hz = hz; + crt_query.query_flags = VG_QUERYFLAG_ACTIVEWIDTH | + VG_QUERYFLAG_ACTIVEHEIGHT | VG_QUERYFLAG_BPP | VG_QUERYFLAG_REFRESH; + + mode = vg_get_display_mode_index(&crt_query); + if (mode >= 0) { + crt_mode = CimarronDisplayModes[mode]; + crt_mode.src_width = src_width; + crt_mode.src_height = src_height; + + /* ADD USER-REQUESTED FLAGS */ + + crt_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS); + + if (flags & VG_MODEFLAG_OVERRIDE_BAND) { + crt_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK; + crt_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK); + } + if (flags & VG_MODEFLAG_INT_OVERRIDE) { + crt_mode.flags &= ~VG_MODEFLAG_INT_MASK; + crt_mode.flags |= (flags & VG_MODEFLAG_INT_MASK); + } + + return vg_set_custom_mode(&crt_mode, bpp); + } + return CIM_STATUS_ERROR; +} + +/*--------------------------------------------------------------------------- + * vg_set_panel_mode + * + * This routine sets a panel mode using predefined Cimarron fixed timings. + * The source width and height specify the width and height of the data in + * the frame buffer. The destination width and height specify the width and + * height of the active data to be displayed. The panel width and height + * specify the dimensions of the panel. This interface allows the user to + * scale or center graphics data or both. To perform scaling, the src width + * or height should be different than the destination width or height. To + * perform centering or panning, the destination width and height should be + * different than the panel resolution. + *--------------------------------------------------------------------------*/ + +int +vg_set_panel_mode(unsigned long src_width, unsigned long src_height, + unsigned long dst_width, unsigned long dst_height, + unsigned long panel_width, unsigned long panel_height, + int bpp, unsigned long flags) +{ + unsigned long sync_width; + unsigned long sync_offset; + VG_QUERY_MODE panel_query; + VG_DISPLAY_MODE panel_mode; + int mode; + + /* SEARCH CIMARRON'S TABLE OF PREDEFINED PANEL MODES */ + /* If the destination resolution is larger than the panel resolution, */ + /* panning will be performed. However, the timings for a panned mode */ + /* are identical to the timings without panning. To save space in the */ + /* mode tables, there are no additional table entries for modes with */ + /* panning. Instead, we read the timings for a mode without panning */ + /* and override the structure entries that specify the width and */ + /* height of the mode. We perform a similar procedure for centered */ + /* modes, except that certain timing parameters are dynamically */ + /* calculated. */ + + panel_query.active_width = panel_width; + panel_query.active_height = panel_height; + panel_query.panel_width = panel_width; + panel_query.panel_height = panel_height; + panel_query.bpp = bpp; + panel_query.query_flags = VG_QUERYFLAG_ACTIVEWIDTH | + VG_QUERYFLAG_ACTIVEHEIGHT | + VG_QUERYFLAG_PANELWIDTH | + VG_QUERYFLAG_PANELHEIGHT | VG_QUERYFLAG_PANEL | VG_QUERYFLAG_BPP; + + mode = vg_get_display_mode_index(&panel_query); + + /* COPY THE DATA FROM THE MODE TABLE TO A TEMPORARY STRUCTURE */ + + if (mode >= 0) { + panel_mode = CimarronDisplayModes[mode]; + panel_mode.mode_width = dst_width; + panel_mode.mode_height = dst_height; + panel_mode.src_width = src_width; + panel_mode.src_height = src_height; + + /* ADD USER-REQUESTED FLAGS */ + + panel_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS); + + if (flags & VG_MODEFLAG_OVERRIDE_BAND) { + panel_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK; + panel_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK); + } + if (flags & VG_MODEFLAG_INT_OVERRIDE) { + panel_mode.flags &= ~VG_MODEFLAG_INT_MASK; + panel_mode.flags |= (flags & VG_MODEFLAG_INT_MASK); + } + + /* DYNAMICALLY CALCULATE CENTERED TIMINGS */ + /* For centered timings the blank start and blank end are set to */ + /* half the difference between the mode dimension and the panel */ + /* dimension. The sync pulse preserves the width and offset from */ + /* blanking whenever possible. */ + + if (dst_width < panel_width) { + sync_width = panel_mode.hsyncend - panel_mode.hsyncstart; + sync_offset = panel_mode.hsyncstart - panel_mode.hblankstart; + + panel_mode.hactive = dst_width; + panel_mode.hblankstart = + panel_mode.hactive + ((panel_width - dst_width) >> 1); + panel_mode.hblankend = + panel_mode.htotal - ((panel_width - dst_width) >> 1); + panel_mode.hsyncstart = panel_mode.hblankstart + sync_offset; + panel_mode.hsyncend = panel_mode.hsyncstart + sync_width; + + panel_mode.flags |= VG_MODEFLAG_CENTERED; + } + if (dst_height < panel_height) { + sync_width = panel_mode.vsyncend - panel_mode.vsyncstart; + sync_offset = panel_mode.vsyncstart - panel_mode.vblankstart; + + panel_mode.vactive = dst_height; + panel_mode.vblankstart = + panel_mode.vactive + ((panel_height - dst_height) >> 1); + panel_mode.vblankend = + panel_mode.vtotal - ((panel_height - dst_height) >> 1); + panel_mode.vsyncstart = panel_mode.vblankstart + sync_offset; + panel_mode.vsyncend = panel_mode.vsyncstart + sync_width; + + panel_mode.flags |= VG_MODEFLAG_CENTERED; + } + return vg_set_custom_mode(&panel_mode, bpp); + } + return CIM_STATUS_ERROR; +} + +/*--------------------------------------------------------------------------- + * vg_set_tv_mode + * + * This routine sets a TV display mode using predefined Cimarron timings. The + * source width and height are specified to allow scaling. + *--------------------------------------------------------------------------*/ + +int +vg_set_tv_mode(unsigned long *src_width, unsigned long *src_height, + unsigned long encoder, unsigned long tvres, int bpp, + unsigned long flags, unsigned long h_overscan, unsigned long v_overscan) +{ + unsigned long sync_width; + unsigned long sync_offset; + VG_QUERY_MODE tv_query; + VG_DISPLAY_MODE tv_mode; + int mode; + + if (!src_width || !src_height) + return CIM_STATUS_INVALIDPARAMS; + + tv_query.bpp = bpp; + tv_query.encoder = encoder; + tv_query.tvmode = tvres; + tv_query.query_flags = VG_QUERYFLAG_BPP | VG_QUERYFLAG_TVOUT | + VG_QUERYFLAG_ENCODER | VG_QUERYFLAG_TVMODE; + + mode = vg_get_display_mode_index(&tv_query); + if (mode >= 0) { + /* RETRIEVE THE UNSCALED RESOLUTION + * As we are indexing here simply by a mode and encoder, the actual + * timings may vary. A 0 value for source or height will thus query + * the unscaled resolution. + */ + + if (!(*src_width) || !(*src_height)) { + *src_width = CimarronDisplayModes[mode].hactive - + (h_overscan << 1); + *src_height = CimarronDisplayModes[mode].vactive; + + if (CimarronDisplayModes[mode].flags & VG_MODEFLAG_INTERLACED) { + if (((flags & VG_MODEFLAG_INT_OVERRIDE) && + (flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_LINEDOUBLE) + || (!(flags & VG_MODEFLAG_INT_OVERRIDE) + && (CimarronDisplayModes[mode]. + flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_LINEDOUBLE)) { + if (CimarronDisplayModes[mode].vactive_even > + CimarronDisplayModes[mode].vactive) + *src_height = CimarronDisplayModes[mode].vactive_even; + + /* ONLY 1/2 THE OVERSCAN FOR LINE DOUBLED MODES */ + + *src_height -= v_overscan; + } else { + *src_height += CimarronDisplayModes[mode].vactive_even; + *src_height -= v_overscan << 1; + } + } else { + *src_height -= v_overscan << 1; + } + + return CIM_STATUS_OK; + } + + tv_mode = CimarronDisplayModes[mode]; + tv_mode.src_width = *src_width; + tv_mode.src_height = *src_height; + + /* ADD USER-REQUESTED FLAGS */ + + tv_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS); + + if (flags & VG_MODEFLAG_OVERRIDE_BAND) { + tv_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK; + tv_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK); + } + if (flags & VG_MODEFLAG_INT_OVERRIDE) { + tv_mode.flags &= ~VG_MODEFLAG_INT_MASK; + tv_mode.flags |= (flags & VG_MODEFLAG_INT_MASK); + } + + /* ADJUST FOR OVERSCAN */ + + if (h_overscan) { + sync_width = tv_mode.hsyncend - tv_mode.hsyncstart; + sync_offset = tv_mode.hsyncstart - tv_mode.hblankstart; + + tv_mode.hactive -= h_overscan << 1; + tv_mode.hblankstart = tv_mode.hactive + h_overscan; + tv_mode.hblankend = tv_mode.htotal - h_overscan; + tv_mode.hsyncstart = tv_mode.hblankstart + sync_offset; + tv_mode.hsyncend = tv_mode.hsyncstart + sync_width; + + tv_mode.flags |= VG_MODEFLAG_CENTERED; + } + if (v_overscan) { + sync_width = tv_mode.vsyncend - tv_mode.vsyncstart; + sync_offset = tv_mode.vsyncstart - tv_mode.vblankstart; + + if (tv_mode.flags & VG_MODEFLAG_INTERLACED) { + tv_mode.vactive -= v_overscan; + tv_mode.vblankstart = tv_mode.vactive + (v_overscan >> 1); + tv_mode.vblankend = tv_mode.vtotal - (v_overscan >> 1); + tv_mode.vsyncstart = tv_mode.vblankstart + sync_offset; + tv_mode.vsyncend = tv_mode.vsyncstart + sync_width; + + sync_width = tv_mode.vsyncend_even - tv_mode.vsyncstart_even; + sync_offset = tv_mode.vsyncstart_even - + tv_mode.vblankstart_even; + + tv_mode.vactive_even -= v_overscan; + tv_mode.vblankstart_even = + tv_mode.vactive_even + (v_overscan >> 1); + tv_mode.vblankend_even = + tv_mode.vtotal_even - (v_overscan >> 1); + tv_mode.vsyncstart_even = + tv_mode.vblankstart_even + sync_offset; + tv_mode.vsyncend_even = tv_mode.vsyncstart_even + sync_width; + } else { + tv_mode.vactive -= v_overscan << 1; + tv_mode.vblankstart = tv_mode.vactive + v_overscan; + tv_mode.vblankend = tv_mode.vtotal - v_overscan; + tv_mode.vsyncstart = tv_mode.vblankstart + sync_offset; + tv_mode.vsyncend = tv_mode.vsyncstart + sync_width; + } + + tv_mode.flags |= VG_MODEFLAG_CENTERED; + } + + /* TV MODES WILL NEVER ALLOW PANNING */ + + tv_mode.panel_width = tv_mode.hactive; + tv_mode.panel_height = tv_mode.vactive; + tv_mode.mode_width = tv_mode.hactive; + tv_mode.mode_height = tv_mode.vactive; + + return vg_set_custom_mode(&tv_mode, bpp); + } + return CIM_STATUS_ERROR; +} + +/*--------------------------------------------------------------------------- + * vg_set_custom_mode + * + * This routine sets a display mode. The API is structured such that this + * routine can be called from four sources: + * - vg_set_display_mode + * - vg_set_panel_mode + * - vg_set_tv_mode + * - directly by the user for a custom mode. + *--------------------------------------------------------------------------*/ + +int +vg_set_custom_mode(VG_DISPLAY_MODE * mode_params, int bpp) +{ + unsigned long config, misc, temp; + unsigned long irq_ctl, genlk_ctl; + unsigned long unlock, flags; + unsigned long acfg, gcfg, dcfg; + unsigned long size, line_size, pitch; + unsigned long bpp_mask, dv_size; + unsigned long hscale, vscale, starting_width; + unsigned long starting_height, output_height; + Q_WORD msr_value; + + /* DETERMINE DIMENSIONS FOR SCALING */ + /* Scaling is performed before flicker filtering and interlacing */ + + output_height = mode_params->vactive; + + if (mode_params->flags & VG_MODEFLAG_INTERLACED) { + /* EVEN AND ODD FIELDS ARE SEPARATE + * The composite image height is the sum of the height of both + * fields + */ + + if ((mode_params->flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_FLICKER + || (mode_params->flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_ADDRESS) { + output_height += mode_params->vactive_even; + } + + /* LINE DOUBLING + * The composite image height is the greater of the two field + * heights. + */ + + else if (mode_params->vactive_even > output_height) + output_height = mode_params->vactive_even; + } + + /* CHECK FOR VALID SCALING FACTOR + * GeodeLX supports only 2:1 vertical downscale (before interlacing) and + * 2:1 horizontal downscale. The source width when scaling must be + * less than or equal to 1024 pixels. The destination can be any size, + * except when flicker filtering is enabled. + */ + + irq_ctl = 0; + if (mode_params->flags & VG_MODEFLAG_PANELOUT) { + if (mode_params->src_width != mode_params->mode_width) { + starting_width = (mode_params->hactive * mode_params->src_width) / + mode_params->mode_width; + hscale = (mode_params->src_width << 14) / + (mode_params->mode_width - 1); + irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN); + } else { + starting_width = mode_params->hactive; + hscale = 0x4000; + } + if (mode_params->src_height != mode_params->mode_height) { + starting_height = (output_height * mode_params->src_height) / + mode_params->mode_height; + vscale = (mode_params->src_height << 14) / + (mode_params->mode_height - 1); + irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN); + } else { + starting_height = output_height; + vscale = 0x4000; + } + } else { + starting_width = mode_params->src_width; + starting_height = mode_params->src_height; + if (mode_params->src_width != mode_params->hactive) { + hscale = (mode_params->src_width << 14) / + (mode_params->hactive - 1); + irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN); + } else { + hscale = 0x4000; + } + if (mode_params->src_height != output_height) { + vscale = (mode_params->src_height << 14) / (output_height - 1); + irq_ctl |= (DC3_IRQFILT_ALPHA_FILT_EN | DC3_IRQFILT_GFX_FILT_EN); + } else { + vscale = 0x4000; + } + } + + starting_width = (starting_width + 7) & 0xFFFF8; + + if (mode_params->hactive < (starting_width >> 1) || + output_height < (starting_height >> 1) || + (irq_ctl && (starting_width > 1024))) { + return CIM_STATUS_INVALIDSCALE; + } + + /* VERIFY INTERLACED SCALING */ + /* The output width must be less than or equal to 1024 pixels when the */ + /* flicker filter is enabled. Also, scaling should be disabled when */ + /* the interlacing mode is set to interlaced addressing. */ + + if (mode_params->flags & VG_MODEFLAG_INTERLACED) { + if ((((mode_params->flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_FLICKER) && (mode_params->hactive > 1024)) + || (((mode_params->flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_ADDRESS) && irq_ctl)) { + return CIM_STATUS_INVALIDSCALE; + } + } + + /* CHECK FOR VALID BPP */ + + switch (bpp) { + case 8: + bpp_mask = DC3_DCFG_DISP_MODE_8BPP; + break; + case 24: + bpp_mask = DC3_DCFG_DISP_MODE_24BPP; + break; + case 32: + bpp_mask = DC3_DCFG_DISP_MODE_32BPP; + break; + case 12: + bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_12BPP; + break; + case 15: + bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_15BPP; + break; + case 16: + bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_16BPP; + break; + default: + return CIM_STATUS_INVALIDPARAMS; + } + + vg3_bpp = bpp; + + /* CLEAR PANNING OFFSETS */ + + vg3_delta_x = 0; + vg3_delta_y = 0; + + /* SAVE PANEL PARAMETERS */ + + if (mode_params->flags & VG_MODEFLAG_PANELOUT) { + vg3_panel_enable = 1; + vg3_panel_width = mode_params->panel_width; + vg3_panel_height = mode_params->panel_height; + vg3_mode_width = mode_params->mode_width; + vg3_mode_height = mode_params->mode_height; + + /* INVERT THE SHIFT CLOCK IF REQUESTED */ + /* Note that we avoid writing the power management register if */ + /* we can help it. */ + + temp = READ_VID32(DF_POWER_MANAGEMENT); + if ((mode_params->flags & VG_MODEFLAG_INVERT_SHFCLK) && + !(temp & DF_PM_INVERT_SHFCLK)) { + WRITE_VID32(DF_POWER_MANAGEMENT, (temp | DF_PM_INVERT_SHFCLK)); + } else if (!(mode_params->flags & VG_MODEFLAG_INVERT_SHFCLK) && + (temp & DF_PM_INVERT_SHFCLK)) { + WRITE_VID32(DF_POWER_MANAGEMENT, (temp & ~DF_PM_INVERT_SHFCLK)); + } + + /* SET PANEL TIMING VALUES */ + + if (!(mode_params->flags & VG_MODEFLAG_NOPANELTIMINGS)) { + unsigned long pmtim1, pmtim2, dith_ctl; + + if (mode_params->flags & VG_MODEFLAG_XVGA_TFT) { + pmtim1 = DF_DEFAULT_XVGA_PMTIM1; + pmtim2 = DF_DEFAULT_XVGA_PMTIM2; + dith_ctl = DF_DEFAULT_DITHCTL; + msr_value.low = DF_DEFAULT_XVGA_PAD_SEL_LOW; + msr_value.high = DF_DEFAULT_XVGA_PAD_SEL_HIGH; + } else if (mode_params->flags & VG_MODEFLAG_CUSTOM_PANEL) { + pmtim1 = mode_params->panel_tim1; + pmtim2 = mode_params->panel_tim2; + dith_ctl = mode_params->panel_dither_ctl; + msr_value.low = mode_params->panel_pad_sel_low; + msr_value.high = mode_params->panel_pad_sel_high; + } else { + pmtim1 = DF_DEFAULT_TFT_PMTIM1; + pmtim2 = DF_DEFAULT_TFT_PMTIM2; + dith_ctl = DF_DEFAULT_DITHCTL; + msr_value.low = DF_DEFAULT_TFT_PAD_SEL_LOW; + msr_value.high = DF_DEFAULT_TFT_PAD_SEL_HIGH; + + } + WRITE_VID32(DF_VIDEO_PANEL_TIM1, pmtim1); + WRITE_VID32(DF_VIDEO_PANEL_TIM2, pmtim2); + WRITE_VID32(DF_DITHER_CONTROL, dith_ctl); + msr_write64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value); + } + + /* SET APPROPRIATE PANEL OUTPUT MODE */ + + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + + msr_value.low &= ~DF_CONFIG_OUTPUT_MASK; + msr_value.low |= DF_OUTPUT_PANEL; + if (mode_params->flags & VG_MODEFLAG_CRT_AND_FP) + msr_value.low |= DF_SIMULTANEOUS_CRT_FP; + else + msr_value.low &= ~DF_SIMULTANEOUS_CRT_FP; + + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + + } else if (mode_params->flags & VG_MODEFLAG_TVOUT) { + vg3_panel_enable = 0; + + /* SET APPROPRIATE TV OUTPUT MODE */ + + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + + msr_value.low &= ~DF_CONFIG_OUTPUT_MASK; + msr_value.low |= DF_OUTPUT_PANEL; + if (mode_params->flags & VG_MODEFLAG_CRT_AND_FP) + msr_value.low |= DF_SIMULTANEOUS_CRT_FP; + else + msr_value.low &= ~DF_SIMULTANEOUS_CRT_FP; + + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + + /* CONFIGURE PADS FOR VOP OUTPUT */ + /* Note that the VOP clock is currently always inverted. */ + + msr_value.low = DF_DEFAULT_TV_PAD_SEL_LOW; + msr_value.high = DF_DEFAULT_TV_PAD_SEL_HIGH; + msr_write64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value); + } else { + vg3_panel_enable = 0; + + /* SET OUTPUT TO CRT ONLY */ + + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + msr_value.low &= ~DF_CONFIG_OUTPUT_MASK; + msr_value.low |= DF_OUTPUT_CRT; + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + } + + /* SET UNLOCK VALUE */ + + unlock = READ_REG32(DC3_UNLOCK); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + /*-------------------------------------------------------------------*/ + /* MAKE THE SYSTEM "SAFE" */ + /* Before setting a mode, we first ensure that the system is in a */ + /* benign quiescent state. This involves disabling compression and */ + /* all interrupt sources. It also involves terminating all accesses */ + /* to memory, including video, FIFO load, VIP and the GP. */ + /*-------------------------------------------------------------------*/ + + /* DISABLE VGA + * VGA *MUST* be turned off before TGEN is enabled. If not, a condition + * will result where VGA Enable is waiting for a VSync to be latched but + * a VSync will not be generated until VGA is disabled. + */ + + temp = READ_REG32(DC3_GENERAL_CFG) & ~DC3_GCFG_VGAE; + + /* DISABLE VIDEO (INCLUDING ALPHA WINDOWS) */ + + WRITE_VID32(DF_ALPHA_CONTROL_1, 0); + WRITE_VID32(DF_ALPHA_CONTROL_1 + 32, 0); + WRITE_VID32(DF_ALPHA_CONTROL_1 + 64, 0); + + WRITE_REG32(DC3_GENERAL_CFG, (temp & ~DC3_GCFG_VIDE)); + temp = READ_VID32(DF_VIDEO_CONFIG); + WRITE_VID32(DF_VIDEO_CONFIG, (temp & ~DF_VCFG_VID_EN)); + + /* DISABLE VG INTERRUPTS */ + + WRITE_REG32(DC3_IRQ, DC3_IRQ_MASK | DC3_VSYNC_IRQ_MASK | + DC3_IRQ_STATUS | DC3_VSYNC_IRQ_STATUS); + + /* DISABLE GENLOCK */ + + genlk_ctl = READ_REG32(DC3_GENLK_CTL); + WRITE_REG32(DC3_GENLK_CTL, (genlk_ctl & ~DC3_GC_GENLOCK_ENABLE)); + + /* DISABLE VIP CAPTURE AND VIP INTERRUPTS */ + + WRITE_VIP32(VIP_CONTROL1, 0); + WRITE_VIP32(VIP_CONTROL2, 0); + WRITE_VIP32(VIP_INTERRUPT, + VIP_ALL_INTERRUPTS | (VIP_ALL_INTERRUPTS >> 16)); + + /* DISABLE COLOR KEYING + * The color key mechanism should be disabled whenever a mode switch + * occurs. + */ + + temp = READ_REG32(DC3_COLOR_KEY); + WRITE_REG32(DC3_COLOR_KEY, (temp & ~DC3_CLR_KEY_ENABLE)); + + /* BLANK THE DISPLAY + * Note that we never blank the panel. Most flat panels have very long + * latency requirements when setting their power low. Some panels require + * upwards of 500ms before VDD goes high again. Needless to say, we are + * not planning to take over one half a second inside this routine. + */ + + misc = READ_VID32(DF_VID_MISC); + config = READ_VID32(DF_DISPLAY_CONFIG); + + WRITE_VID32(DF_VID_MISC, (misc | DF_DAC_POWER_DOWN)); + WRITE_VID32(DF_DISPLAY_CONFIG, + (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | + DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN))); + + /* DISABLE COMPRESSION */ + + gcfg = READ_REG32(DC3_GENERAL_CFG); + gcfg &= ~(DC3_GCFG_CMPE | DC3_GCFG_DECE); + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + + /* DISABLE THE TIMING GENERATOR */ + + dcfg = READ_REG32(DC3_DISPLAY_CFG); + dcfg &= ~DC3_DCFG_TGEN; + WRITE_REG32(DC3_DISPLAY_CFG, dcfg); + + /* WAIT FOR PENDING MEMORY REQUESTS */ + + vg_delay_milliseconds(1); + + /* DISABLE DISPLAY FIFO LOAD */ + + gcfg &= ~DC3_GCFG_DFLE; + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + gcfg = 0; + dcfg = 0; + + /* WAIT FOR THE GP TO BE IDLE (JUST IN CASE) */ + + while (((temp = READ_GP32(GP3_BLT_STATUS)) & GP3_BS_BLT_BUSY) || + !(temp & GP3_BS_CB_EMPTY)) { + ; + } + + /* SET THE DOT CLOCK FREQUENCY */ + + if (!(mode_params->flags & VG_MODEFLAG_EXCLUDEPLL)) { + if (mode_params->flags & VG_MODEFLAG_HALFCLOCK) + flags = VG_PLL_DIVIDE_BY_2; + else if (mode_params->flags & VG_MODEFLAG_QVGA) + flags = VG_PLL_DIVIDE_BY_4; + else + flags = 0; + + /* ALLOW DOTREF TO BE USED AS THE PLL */ + /* This is useful for some external TV encoders. */ + + if (mode_params->flags & VG_MODEFLAG_PLL_BYPASS) + flags |= VG_PLL_BYPASS; + + /* ALLOW THE USER TO MANUALLY ENTER THE MSR VALUE */ + + if (mode_params->flags & VG_MODEFLAG_MANUAL_FREQUENCY) + flags |= VG_PLL_MANUAL; + if (mode_params->flags & VG_MODEFLAG_VIP_TO_DOT_CLOCK) + flags |= VG_PLL_VIP_CLOCK; + + vg_set_clock_frequency(mode_params->frequency, flags); + } + + /* CLEAR ALL BUFFER OFFSETS */ + + WRITE_REG32(DC3_FB_ST_OFFSET, 0); + WRITE_REG32(DC3_CB_ST_OFFSET, 0); + WRITE_REG32(DC3_CURS_ST_OFFSET, 0); + + genlk_ctl = READ_REG32(DC3_GENLK_CTL) & ~(DC3_GC_ALPHA_FLICK_ENABLE | + DC3_GC_FLICKER_FILTER_ENABLE | DC3_GC_FLICKER_FILTER_MASK); + + /* ENABLE INTERLACING */ + + if (mode_params->flags & VG_MODEFLAG_INTERLACED) { + irq_ctl |= DC3_IRQFILT_INTL_EN; + + if ((mode_params->flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_ADDRESS) + irq_ctl |= DC3_IRQFILT_INTL_ADDR; + else if ((mode_params->flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_FLICKER) { + genlk_ctl |= DC3_GC_FLICKER_FILTER_1_8 | + DC3_GC_FLICKER_FILTER_ENABLE | DC3_GC_ALPHA_FLICK_ENABLE; + } + } + + WRITE_REG32(DC3_GFX_SCALE, (vscale << 16) | (hscale & 0xFFFF)); + WRITE_REG32(DC3_IRQ_FILT_CTL, irq_ctl); + WRITE_REG32(DC3_GENLK_CTL, genlk_ctl); + + /* SET LINE SIZE AND PITCH + * The line size and pitch are calculated from the src_width parameter + * passed in to this routine. All other parameters are ignored. + * The pitch is set either to a power of 2 to allow efficient + * compression or to a linear value to allow efficient memory management. + */ + + switch (bpp) { + case 8: + size = mode_params->src_width; + line_size = starting_width; + break; + + case 12: + case 15: + case 16: + + size = mode_params->src_width << 1; + line_size = starting_width << 1; + break; + + case 24: + case 32: + default: + + size = mode_params->src_width << 2; + line_size = starting_width << 2; + break; + } + + /* CALCULATE DV RAM SETTINGS AND POWER OF 2 PITCH */ + + pitch = 1024; + dv_size = DC3_DV_LINE_SIZE_1024; + + if (size > 1024) { + pitch = 2048; + dv_size = DC3_DV_LINE_SIZE_2048; + } + if (size > 2048) { + pitch = 4096; + dv_size = DC3_DV_LINE_SIZE_4096; + } + if (size > 4096) { + pitch = 8192; + dv_size = DC3_DV_LINE_SIZE_8192; + } + + /* OVERRIDE SETTINGS FOR LINEAR PITCH */ + + if (mode_params->flags & VG_MODEFLAG_LINEARPITCH) { + unsigned long max; + + if (pitch != size) { + /* CALCULATE MAXIMUM ADDRESS (1K ALIGNED) */ + + max = size * output_height; + max = (max + 0x3FF) & 0xFFFFFC00; + WRITE_REG32(DC3_DV_TOP, max | DC3_DVTOP_ENABLE); + + gcfg |= DC3_GCFG_FDTY; + pitch = size; + } else { + WRITE_REG32(DC3_DV_TOP, 0); + } + } + + /* WRITE PITCH AND DV RAM SETTINGS */ + /* The DV RAM line length is programmed at a power of 2 boundary */ + /* in case the user wants to toggle back to a power of 2 pitch */ + /* later. It could happen... */ + + temp = READ_REG32(DC3_DV_CTL); + WRITE_REG32(DC3_GFX_PITCH, pitch >> 3); + WRITE_REG32(DC3_DV_CTL, (temp & ~DC3_DV_LINE_SIZE_MASK) | dv_size); + + /* SET THE LINE SIZE */ + + WRITE_REG32(DC3_LINE_SIZE, (line_size + 7) >> 3); + + /* ALWAYS ENABLE VIDEO AND GRAPHICS DATA */ + /* These bits are relics from a previous design and */ + /* should always be enabled. */ + + dcfg |= (DC3_DCFG_VDEN | DC3_DCFG_GDEN); + + /* SET PIXEL FORMAT */ + + dcfg |= bpp_mask; + + /* ENABLE TIMING GENERATOR, TIM. REG. UPDATES, PALETTE BYPASS */ + /* AND VERT. INT. SELECT */ + + dcfg |= (unsigned long)(DC3_DCFG_TGEN | DC3_DCFG_TRUP | DC3_DCFG_PALB | + DC3_DCFG_VISL); + + /* SET FIFO PRIORITIES AND DISPLAY FIFO LOAD ENABLE + * Note that the bandwidth setting gets upgraded when scaling or flicker + * filtering are enabled, as they require more data throughput. + */ + + msr_read64(MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value); + msr_value.low &= ~(DC3_SPARE_DISABLE_CFIFO_HGO | + DC3_SPARE_VFIFO_ARB_SELECT | + DC3_SPARE_LOAD_WM_LPEN_MASK | DC3_SPARE_WM_LPEN_OVRD | + DC3_SPARE_DISABLE_INIT_VID_PRI | DC3_SPARE_DISABLE_VFIFO_WM); + + if ((mode_params->flags & VG_MODEFLAG_BANDWIDTHMASK) == + VG_MODEFLAG_HIGH_BAND + || ((mode_params->flags & VG_MODEFLAG_INTERLACED) + && (mode_params->flags & VG_MODEFLAG_INT_MASK) == + VG_MODEFLAG_INT_FLICKER) || (irq_ctl & DC3_IRQFILT_GFX_FILT_EN)) { + /* HIGH BANDWIDTH */ + /* Set agressive watermarks and disallow forced low priority */ + + gcfg |= 0x0000BA01; + dcfg |= 0x000EA000; + acfg = 0x001A0201; + + msr_value.low |= DC3_SPARE_DISABLE_CFIFO_HGO | + DC3_SPARE_VFIFO_ARB_SELECT | DC3_SPARE_WM_LPEN_OVRD; + } else if ((mode_params->flags & VG_MODEFLAG_BANDWIDTHMASK) == + VG_MODEFLAG_AVG_BAND) { + /* AVERAGE BANDWIDTH + * Set average watermarks and allow small regions of forced low + * priority. + */ + + gcfg |= 0x0000B601; + dcfg |= 0x00009000; + acfg = 0x00160001; + + msr_value.low |= DC3_SPARE_DISABLE_CFIFO_HGO | + DC3_SPARE_VFIFO_ARB_SELECT | DC3_SPARE_WM_LPEN_OVRD; + + /* SET THE NUMBER OF LOW PRIORITY LINES TO 1/2 THE TOTAL AVAILABLE */ + + temp = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0x7FF) + 1; + temp -= (READ_REG32(DC3_V_SYNC_TIMING) & 0x7FF) + 1; + temp >>= 1; + if (temp > 127) + temp = 127; + + acfg |= temp << 9; + } else if ((mode_params->flags & VG_MODEFLAG_BANDWIDTHMASK) == + VG_MODEFLAG_LOW_BAND) { + /* LOW BANDWIDTH + * Set low watermarks and allow larger regions of forced low priority + */ + + gcfg |= 0x00009501; + dcfg |= 0x00008000; + acfg = 0x00150001; + + msr_value.low |= DC3_SPARE_DISABLE_CFIFO_HGO | + DC3_SPARE_VFIFO_ARB_SELECT | DC3_SPARE_WM_LPEN_OVRD; + + /* SET THE NUMBER OF LOW PRIORITY LINES TO 3/4 THE TOTAL AVAILABLE */ + + temp = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0x7FF) + 1; + temp -= (READ_REG32(DC3_V_SYNC_TIMING) & 0x7FF) + 1; + temp = (temp * 3) >> 2; + if (temp > 127) + temp = 127; + + acfg |= temp << 9; + } else { + /* LEGACY CHARACTERISTICS */ + /* Arbitration from a single set of watermarks. */ + + gcfg |= 0x0000B601; + msr_value.low |= DC3_SPARE_DISABLE_VFIFO_WM | + DC3_SPARE_DISABLE_INIT_VID_PRI; + acfg = 0; + } + + msr_write64(MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value); + + /* ENABLE FLAT PANEL CENTERING */ + /* For panel modes having a resolution smaller than the */ + /* panel resolution, turn on data centering. */ + + if (mode_params->flags & VG_MODEFLAG_CENTERED) + dcfg |= DC3_DCFG_DCEN; + + /* COMBINE AND SET TIMING VALUES */ + + temp = (mode_params->hactive - 1) | ((mode_params->htotal - 1) << 16); + WRITE_REG32(DC3_H_ACTIVE_TIMING, temp); + temp = (mode_params->hblankstart - 1) | + ((mode_params->hblankend - 1) << 16); + WRITE_REG32(DC3_H_BLANK_TIMING, temp); + temp = (mode_params->hsyncstart - 1) | + ((mode_params->hsyncend - 1) << 16); + WRITE_REG32(DC3_H_SYNC_TIMING, temp); + temp = (mode_params->vactive - 1) | ((mode_params->vtotal - 1) << 16); + WRITE_REG32(DC3_V_ACTIVE_TIMING, temp); + temp = (mode_params->vblankstart - 1) | + ((mode_params->vblankend - 1) << 16); + WRITE_REG32(DC3_V_BLANK_TIMING, temp); + temp = (mode_params->vsyncstart - 1) | + ((mode_params->vsyncend - 1) << 16); + WRITE_REG32(DC3_V_SYNC_TIMING, temp); + temp = (mode_params->vactive_even - 1) | ((mode_params->vtotal_even - + 1) << 16); + WRITE_REG32(DC3_V_ACTIVE_EVEN, temp); + temp = (mode_params->vblankstart_even - 1) | + ((mode_params->vblankend_even - 1) << 16); + WRITE_REG32(DC3_V_BLANK_EVEN, temp); + temp = (mode_params->vsyncstart_even - 1) | + ((mode_params->vsyncend_even - 1) << 16); + WRITE_REG32(DC3_V_SYNC_EVEN, temp); + + /* SET THE VIDEO REQUEST REGISTER */ + + WRITE_VID32(DF_VIDEO_REQUEST, 0); + + /* SET SOURCE DIMENSIONS */ + + WRITE_REG32(DC3_FB_ACTIVE, ((starting_width - 1) << 16) | + (starting_height - 1)); + + /* SET SYNC POLARITIES */ + + temp = READ_VID32(DF_DISPLAY_CONFIG); + + temp &= ~(DF_DCFG_CRT_SYNC_SKW_MASK | DF_DCFG_PWR_SEQ_DLY_MASK | + DF_DCFG_CRT_HSYNC_POL | DF_DCFG_CRT_VSYNC_POL); + + temp |= (DF_DCFG_CRT_SYNC_SKW_INIT | + DF_DCFG_PWR_SEQ_DLY_INIT | DF_DCFG_GV_PAL_BYP); + + if (mode_params->flags & VG_MODEFLAG_NEG_HSYNC) + temp |= DF_DCFG_CRT_HSYNC_POL; + if (mode_params->flags & VG_MODEFLAG_NEG_VSYNC) + temp |= DF_DCFG_CRT_VSYNC_POL; + + WRITE_VID32(DF_DISPLAY_CONFIG, temp); + + WRITE_REG32(DC3_DISPLAY_CFG, dcfg); + WRITE_REG32(DC3_ARB_CFG, acfg); + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + + /* RESTORE VALUE OF DC3_UNLOCK */ + + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_bpp + * + * This routine changes the display BPP on the fly. It is intended only to + * switch between pixel depths of the same pixel size 24<->32 or 15<->16, NOT + * between pixel depths of differing sizes 16<->32 + *--------------------------------------------------------------------------*/ + +int +vg_set_display_bpp(int bpp) +{ + unsigned long unlock, dcfg, bpp_mask; + + switch (bpp) { + case 8: + bpp_mask = DC3_DCFG_DISP_MODE_8BPP; + break; + case 24: + bpp_mask = DC3_DCFG_DISP_MODE_24BPP; + break; + case 32: + bpp_mask = DC3_DCFG_DISP_MODE_32BPP; + break; + case 12: + bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_12BPP; + break; + case 15: + bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_15BPP; + break; + case 16: + bpp_mask = DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_16BPP; + break; + default: + return CIM_STATUS_INVALIDPARAMS; + } + + unlock = READ_REG32(DC3_UNLOCK); + dcfg = READ_REG32(DC3_DISPLAY_CFG) & ~(DC3_DCFG_DISP_MODE_MASK | + DC3_DCFG_16BPP_MODE_MASK); + dcfg |= bpp_mask; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_DISPLAY_CFG, dcfg); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_get_display_mode_index + * + * This routine searches the Cimarron mode table for a mode that matches the + * input parameters. If a match is found, the return value is the index into + * the mode table. If no match is found, the return value is -1. + *--------------------------------------------------------------------------*/ + +int +vg_get_display_mode_index(VG_QUERY_MODE * query) +{ + unsigned int mode; + unsigned long hz_flag = 0xFFFFFFFF; + unsigned long bpp_flag = 0xFFFFFFFF; + unsigned long enc_flag = 0xFFFFFFFF; + unsigned long tv_flag = 0; + unsigned long interlaced = 0; + unsigned long halfclock = 0; + long minimum = 0x7FFFFFFF; + long diff; + int match = -1; + + if (!query || !query->query_flags) + return -1; + + if (query->query_flags & VG_QUERYFLAG_REFRESH) { + /* SET FLAGS TO MATCH REFRESH RATE */ + + if (query->hz == 56) + hz_flag = VG_SUPPORTFLAG_56HZ; + else if (query->hz == 60) + hz_flag = VG_SUPPORTFLAG_60HZ; + else if (query->hz == 70) + hz_flag = VG_SUPPORTFLAG_70HZ; + else if (query->hz == 72) + hz_flag = VG_SUPPORTFLAG_72HZ; + else if (query->hz == 75) + hz_flag = VG_SUPPORTFLAG_75HZ; + else if (query->hz == 85) + hz_flag = VG_SUPPORTFLAG_85HZ; + else if (query->hz == 90) + hz_flag = VG_SUPPORTFLAG_90HZ; + else if (query->hz == 100) + hz_flag = VG_SUPPORTFLAG_100HZ; + else + hz_flag = 0; + } + + if (query->query_flags & VG_QUERYFLAG_BPP) { + /* SET BPP FLAGS TO LIMIT MODE SELECTION */ + + if (query->bpp == 8) + bpp_flag = VG_SUPPORTFLAG_8BPP; + else if (query->bpp == 12) + bpp_flag = VG_SUPPORTFLAG_12BPP; + else if (query->bpp == 15) + bpp_flag = VG_SUPPORTFLAG_15BPP; + else if (query->bpp == 16) + bpp_flag = VG_SUPPORTFLAG_16BPP; + else if (query->bpp == 24) + bpp_flag = VG_SUPPORTFLAG_24BPP; + else if (query->bpp == 32) + bpp_flag = VG_SUPPORTFLAG_32BPP; + else + bpp_flag = 0; + } + + if (query->query_flags & VG_QUERYFLAG_ENCODER) { + /* SET ENCODER FLAGS TO LIMIT MODE SELECTION */ + + if (query->encoder == VG_ENCODER_ADV7171) + enc_flag = VG_SUPPORTFLAG_ADV7171; + else if (query->encoder == VG_ENCODER_SAA7127) + enc_flag = VG_SUPPORTFLAG_SAA7127; + else if (query->encoder == VG_ENCODER_FS454) + enc_flag = VG_SUPPORTFLAG_FS454; + else if (query->encoder == VG_ENCODER_ADV7300) + enc_flag = VG_SUPPORTFLAG_ADV7300; + else + enc_flag = 0; + } + + if (query->query_flags & VG_QUERYFLAG_TVMODE) { + /* SET ENCODER FLAGS TO LIMIT MODE SELECTION */ + + if (query->tvmode == VG_TVMODE_NTSC) + tv_flag = VG_SUPPORTFLAG_NTSC; + else if (query->tvmode == VG_TVMODE_PAL) + tv_flag = VG_SUPPORTFLAG_PAL; + else if (query->tvmode == VG_TVMODE_480P) + tv_flag = VG_SUPPORTFLAG_480P; + else if (query->tvmode == VG_TVMODE_720P) + tv_flag = VG_SUPPORTFLAG_720P; + else if (query->tvmode == VG_TVMODE_1080I) + tv_flag = VG_SUPPORTFLAG_1080I; + else if (query->tvmode == VG_TVMODE_6X4_NTSC) + tv_flag = VG_SUPPORTFLAG_6X4_NTSC; + else if (query->tvmode == VG_TVMODE_8X6_NTSC) + tv_flag = VG_SUPPORTFLAG_8X6_NTSC; + else if (query->tvmode == VG_TVMODE_10X7_NTSC) + tv_flag = VG_SUPPORTFLAG_10X7_NTSC; + else if (query->tvmode == VG_TVMODE_6X4_PAL) + tv_flag = VG_SUPPORTFLAG_6X4_PAL; + else if (query->tvmode == VG_TVMODE_8X6_PAL) + tv_flag = VG_SUPPORTFLAG_8X6_PAL; + else if (query->tvmode == VG_TVMODE_10X7_PAL) + tv_flag = VG_SUPPORTFLAG_10X7_PAL; + else + tv_flag = 0xFFFFFFFF; + } + + /* SET APPROPRIATE TV AND VOP FLAGS */ + + if (query->query_flags & VG_QUERYFLAG_INTERLACED) + interlaced = query->interlaced ? VG_MODEFLAG_INTERLACED : 0; + if (query->query_flags & VG_QUERYFLAG_HALFCLOCK) + halfclock = query->halfclock ? VG_MODEFLAG_HALFCLOCK : 0; + + /* CHECK FOR INVALID REQUEST */ + + if (!hz_flag || !bpp_flag || !enc_flag || tv_flag == 0xFFFFFFFF) + return -1; + + /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */ + + for (mode = 0; mode < NUM_CIMARRON_DISPLAY_MODES; mode++) { + if ((!(query->query_flags & VG_QUERYFLAG_PANEL) || + (CimarronDisplayModes[mode]. + internal_flags & VG_SUPPORTFLAG_PANEL)) + && (!(query->query_flags & VG_QUERYFLAG_TVOUT) + || (CimarronDisplayModes[mode]. + internal_flags & VG_SUPPORTFLAG_TVOUT)) + && (!(query->query_flags & VG_QUERYFLAG_INTERLACED) + || (CimarronDisplayModes[mode]. + flags & VG_MODEFLAG_INTERLACED) == interlaced) + && (!(query->query_flags & VG_QUERYFLAG_HALFCLOCK) + || (CimarronDisplayModes[mode]. + flags & VG_MODEFLAG_HALFCLOCK) == halfclock) + && (!(query->query_flags & VG_QUERYFLAG_PANELWIDTH) + || (CimarronDisplayModes[mode].panel_width == + query->panel_width)) + && (!(query->query_flags & VG_QUERYFLAG_PANELHEIGHT) + || (CimarronDisplayModes[mode].panel_height == + query->panel_height)) + && (!(query->query_flags & VG_QUERYFLAG_ACTIVEWIDTH) + || (CimarronDisplayModes[mode].hactive == + query->active_width)) + && (!(query->query_flags & VG_QUERYFLAG_ACTIVEHEIGHT) + || (CimarronDisplayModes[mode].vactive == + query->active_height)) + && (!(query->query_flags & VG_QUERYFLAG_TOTALWIDTH) + || (CimarronDisplayModes[mode].htotal == query->total_width)) + && (!(query->query_flags & VG_QUERYFLAG_TOTALHEIGHT) + || (CimarronDisplayModes[mode].vtotal == query->total_height)) + && (!(query->query_flags & VG_QUERYFLAG_BPP) + || (CimarronDisplayModes[mode].internal_flags & bpp_flag)) + && (!(query->query_flags & VG_QUERYFLAG_REFRESH) + || (CimarronDisplayModes[mode].internal_flags & hz_flag)) + && (!(query->query_flags & VG_QUERYFLAG_ENCODER) + || (CimarronDisplayModes[mode].internal_flags & enc_flag)) + && (!(query->query_flags & VG_QUERYFLAG_TVMODE) + || ((CimarronDisplayModes[mode]. + internal_flags & VG_SUPPORTFLAG_TVMODEMASK) == + tv_flag)) + && (!(query->query_flags & VG_QUERYFLAG_PIXELCLOCK) + || (CimarronDisplayModes[mode].frequency == + query->frequency))) { + /* ALLOW SEARCHING BASED ON AN APPROXIMATE PIXEL CLOCK */ + + if (query->query_flags & VG_QUERYFLAG_PIXELCLOCK_APPROX) { + diff = query->frequency - + CimarronDisplayModes[mode].frequency; + if (diff < 0) + diff = -diff; + + if (diff < minimum) { + minimum = diff; + match = mode; + } + } else { + match = mode; + break; + } + } + } + + /* RETURN DISPLAY MODE INDEX */ + + return match; +} + +/*--------------------------------------------------------------------------- + * vg_get_display_mode_information + * + * This routine retrieves all information for a display mode contained + * within Cimarron's mode tables. + *--------------------------------------------------------------------------*/ + +int +vg_get_display_mode_information(unsigned int index, VG_DISPLAY_MODE * vg_mode) +{ + if (index > NUM_CIMARRON_DISPLAY_MODES) + return CIM_STATUS_INVALIDPARAMS; + + *vg_mode = CimarronDisplayModes[index]; + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_get_display_mode_count + * + * This routine retrieves the count of all predefined Cimarron modes. + *--------------------------------------------------------------------------*/ + +int +vg_get_display_mode_count(void) +{ + return NUM_CIMARRON_DISPLAY_MODES; +} + +/*--------------------------------------------------------------------------- + * vg_get_current_display_mode + * + * This routine retrieves the settings for the current display. This includes + * any panel settings. + *--------------------------------------------------------------------------*/ + +int +vg_get_current_display_mode(VG_DISPLAY_MODE * current_display, int *bpp) +{ + Q_WORD msr_value; + unsigned long active, blank, sync; + unsigned long i, m, n, p; + unsigned long genlk, irq, temp; + unsigned long flags = 0; + unsigned long iflags = 0; + + /* READ THE CURRENT HORIZONTAL DISPLAY TIMINGS */ + + active = READ_REG32(DC3_H_ACTIVE_TIMING); + blank = READ_REG32(DC3_H_BLANK_TIMING); + sync = READ_REG32(DC3_H_SYNC_TIMING); + + current_display->hactive = (active & 0xFFF) + 1; + current_display->hblankstart = (blank & 0xFFF) + 1; + current_display->hsyncstart = (sync & 0xFFF) + 1; + + current_display->htotal = ((active >> 16) & 0xFFF) + 1; + current_display->hblankend = ((blank >> 16) & 0xFFF) + 1; + current_display->hsyncend = ((sync >> 16) & 0xFFF) + 1; + + /* READ THE CURRENT VERTICAL DISPLAY TIMINGS */ + + active = READ_REG32(DC3_V_ACTIVE_TIMING); + blank = READ_REG32(DC3_V_BLANK_TIMING); + sync = READ_REG32(DC3_V_SYNC_TIMING); + + current_display->vactive = (active & 0x7FF) + 1; + current_display->vblankstart = (blank & 0x7FF) + 1; + current_display->vsyncstart = (sync & 0x7FF) + 1; + + current_display->vtotal = ((active >> 16) & 0x7FF) + 1; + current_display->vblankend = ((blank >> 16) & 0x7FF) + 1; + current_display->vsyncend = ((sync >> 16) & 0x7FF) + 1; + + /* READ THE CURRENT EVEN FIELD VERTICAL DISPLAY TIMINGS */ + + active = READ_REG32(DC3_V_ACTIVE_EVEN); + blank = READ_REG32(DC3_V_BLANK_EVEN); + sync = READ_REG32(DC3_V_SYNC_EVEN); + + current_display->vactive_even = (active & 0x7FF) + 1; + current_display->vblankstart_even = (blank & 0x7FF) + 1; + current_display->vsyncstart_even = (sync & 0x7FF) + 1; + + current_display->vtotal_even = ((active >> 16) & 0x7FF) + 1; + current_display->vblankend_even = ((blank >> 16) & 0x7FF) + 1; + current_display->vsyncend_even = ((sync >> 16) & 0x7FF) + 1; + + /* READ THE CURRENT SOURCE DIMENSIONS */ + /* The DC3_FB_ACTIVE register is only used when scaling is enabled. */ + /* As the goal of this routine is to return a structure that can be */ + /* passed to vg_set_custom_mode to exactly recreate the current mode, */ + /* we must check the status of the scaler/filter. */ + + genlk = READ_REG32(DC3_GENLK_CTL); + irq = READ_REG32(DC3_IRQ_FILT_CTL); + temp = READ_REG32(DC3_FB_ACTIVE); + + current_display->src_height = (temp & 0xFFFF) + 1; + current_display->src_width = ((temp >> 16) & 0xFFF8) + 8; + + /* READ THE CURRENT PANEL CONFIGURATION */ + /* We can only infer some of the panel settings based on hardware */ + /* (like when panning). We will instead assume that the current */ + /* mode was set using Cimarron and use the panel variables inside */ + /* Cimarron when returning the current mode information. */ + + if (vg3_panel_enable) { + Q_WORD msr_value; + + flags |= VG_MODEFLAG_PANELOUT; + + current_display->panel_width = vg3_panel_width; + current_display->panel_height = vg3_panel_height; + current_display->mode_width = vg3_mode_width; + current_display->mode_height = vg3_mode_height; + + if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) + flags |= VG_MODEFLAG_CENTERED; + + msr_read64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value); + current_display->panel_tim1 = READ_VID32(DF_VIDEO_PANEL_TIM1); + current_display->panel_tim2 = READ_VID32(DF_VIDEO_PANEL_TIM2); + current_display->panel_dither_ctl = READ_VID32(DF_DITHER_CONTROL); + current_display->panel_pad_sel_low = msr_value.low; + current_display->panel_pad_sel_high = msr_value.high; + } + + /* SET MISCELLANEOUS MODE FLAGS */ + + /* INTERLACED */ + + if (irq & DC3_IRQFILT_INTL_EN) { + flags |= VG_MODEFLAG_INTERLACED; + if (irq & DC3_IRQFILT_INTL_ADDR) + flags |= VG_MODEFLAG_INT_ADDRESS; + else if (genlk & DC3_GC_FLICKER_FILTER_ENABLE) + flags |= VG_MODEFLAG_INT_FLICKER; + else + flags |= VG_MODEFLAG_INT_LINEDOUBLE; + } + + /* POLARITIES */ + + temp = READ_VID32(DF_DISPLAY_CONFIG); + if (temp & DF_DCFG_CRT_HSYNC_POL) + flags |= VG_MODEFLAG_NEG_HSYNC; + if (temp & DF_DCFG_CRT_VSYNC_POL) + flags |= VG_MODEFLAG_NEG_VSYNC; + + /* BPP */ + + temp = READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DISP_MODE_MASK; + if (temp == DC3_DCFG_DISP_MODE_8BPP) { + iflags |= VG_SUPPORTFLAG_8BPP; + *bpp = 8; + } else if (temp == DC3_DCFG_DISP_MODE_24BPP) { + iflags |= VG_SUPPORTFLAG_24BPP; + *bpp = 24; + } else if (temp == DC3_DCFG_DISP_MODE_32BPP) { + iflags |= VG_SUPPORTFLAG_32BPP; + *bpp = 32; + } else if (temp == DC3_DCFG_DISP_MODE_16BPP) { + temp = READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_16BPP_MODE_MASK; + if (temp == DC3_DCFG_16BPP) { + iflags |= VG_SUPPORTFLAG_16BPP; + *bpp = 16; + } else if (temp == DC3_DCFG_15BPP) { + iflags |= VG_SUPPORTFLAG_15BPP; + *bpp = 15; + } else if (temp == DC3_DCFG_12BPP) { + iflags |= VG_SUPPORTFLAG_12BPP; + *bpp = 12; + } + } + + /* TV RELATED FLAGS */ + + msr_read64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &msr_value); + if (msr_value.high & DF_INVERT_VOP_CLOCK) + flags |= VG_MODEFLAG_TVOUT; + + /* LINEAR PITCH */ + + temp = (READ_REG32(DC3_GFX_PITCH) & 0x0000FFFF) << 3; + if (temp != 1024 && temp != 2048 && temp != 4096 && temp != 8192) + flags |= VG_MODEFLAG_LINEARPITCH; + + /* SIMULTANEOUS CRT/FP */ + + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + if (msr_value.low & DF_SIMULTANEOUS_CRT_FP) + flags |= VG_MODEFLAG_CRT_AND_FP; + + /* SET PLL-RELATED FLAGS */ + + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value); + if (msr_value.high & GLCP_DOTPLL_DIV4) + flags |= VG_MODEFLAG_QVGA; + if (msr_value.low & GLCP_DOTPLL_HALFPIX) + flags |= VG_MODEFLAG_HALFCLOCK; + + /* SAVE THE FLAGS IN THE MODE STRUCTURE */ + + current_display->internal_flags = iflags; + current_display->flags = flags; + + /* READ PIXEL CLOCK FREQUENCY */ + /* We first search for an exact match. If none is found, we try */ + /* a fixed point calculation and return CIM_STATUS_INEXACTMATCH. */ + + for (i = 0; i < NUM_CIMARRON_PLL_FREQUENCIES; i++) { + if (CimarronPLLFrequencies[i].pll_value == msr_value.high) + break; + } + + if (i == NUM_CIMARRON_PLL_FREQUENCIES) { + /* ATTEMPT 16.16 CALCULATION */ + /* We assume the input frequency is 48 MHz, which is represented */ + /* in 16.16 fixed point as 0x300000. The PLL calculation is: */ + /* n + 1 */ + /* Fout = 48.000 * -------------- */ + /* m + 1 * p + 1 */ + + p = msr_value.high & 0xF; + n = (msr_value.high >> 4) & 0xFF; + m = (msr_value.high >> 12) & 0x7; + current_display->frequency = + (0x300000 * (n + 1)) / ((p + 1) * (m + 1)); + + return CIM_STATUS_INEXACTMATCH; + } + + current_display->frequency = CimarronPLLFrequencies[i].frequency; + + /* NOW SEARCH FOR AN IDENTICAL MODE */ + /* This is just to inform the user that an exact match was found. */ + /* With an exact match, the user can use the refresh rate flag that */ + /* is returned in the VG_DISPLAY_MODE structure. */ + + for (i = 0; i < NUM_CIMARRON_DISPLAY_MODES; i++) { + if ((CimarronDisplayModes[i].flags & current_display->flags) && + CimarronDisplayModes[i].frequency == + current_display->frequency && + CimarronDisplayModes[i].hactive == current_display->hactive && + CimarronDisplayModes[i].hblankstart == + current_display->hblankstart + && CimarronDisplayModes[i].hsyncstart == + current_display->hsyncstart + && CimarronDisplayModes[i].hsyncend == + current_display->hsyncend + && CimarronDisplayModes[i].hblankend == + current_display->hblankend + && CimarronDisplayModes[i].htotal == current_display->htotal + && CimarronDisplayModes[i].vactive == current_display->vactive + && CimarronDisplayModes[i].vblankstart == + current_display->vblankstart + && CimarronDisplayModes[i].vsyncstart == + current_display->vsyncstart + && CimarronDisplayModes[i].vsyncend == + current_display->vsyncend + && CimarronDisplayModes[i].vblankend == + current_display->vblankend + && CimarronDisplayModes[i].vtotal == current_display->vtotal) { + break; + } + } + + if (i == NUM_CIMARRON_DISPLAY_MODES) + return CIM_STATUS_INEXACTMATCH; + + current_display->internal_flags |= + (CimarronDisplayModes[i].internal_flags & VG_SUPPORTFLAG_HZMASK); + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_scaler_filter_coefficients + * + * This routine sets the vertical and horizontal filter coefficients for + * graphics scaling. If either of the input arrays is specified as NULL, a + * set of default coeffecients will be used. + *--------------------------------------------------------------------------*/ + +int +vg_set_scaler_filter_coefficients(long h_taps[][5], long v_taps[][3]) +{ + unsigned long irqfilt, i; + unsigned long temp0, temp1; + unsigned long lock; + + /* ENABLE ACCESS TO THE HORIZONTAL COEFFICIENTS */ + + irqfilt = READ_REG32(DC3_IRQ_FILT_CTL); + irqfilt |= DC3_IRQFILT_H_FILT_SEL; + + /* UNLOCK THE COEFFICIENT REGISTERS */ + + lock = READ_REG32(DC3_UNLOCK); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + /* WRITE COEFFICIENTS */ + /* Coefficient indexes do not auto-increment, so we must */ + /* write the address for every phase */ + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + + if (!h_taps) { + temp0 = CimarronHorizontalGraphicsFilter[i][0]; + temp1 = CimarronHorizontalGraphicsFilter[i][1]; + } else { + temp0 = ((unsigned long)h_taps[i][0] & 0x3FF) | + (((unsigned long)h_taps[i][1] & 0x3FF) << 10) | + (((unsigned long)h_taps[i][2] & 0x3FF) << 20); + + temp1 = ((unsigned long)h_taps[i][3] & 0x3FF) | + (((unsigned long)h_taps[i][4] & 0x3FF) << 10); + } + WRITE_REG32(DC3_FILT_COEFF1, temp0); + WRITE_REG32(DC3_FILT_COEFF2, temp1); + } + + /* ENABLE ACCESS TO THE VERTICAL COEFFICIENTS */ + + irqfilt &= ~DC3_IRQFILT_H_FILT_SEL; + + /* WRITE COEFFICIENTS */ + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + + if (!v_taps) { + temp0 = CimarronVerticalGraphicsFilter[i]; + } else { + temp0 = ((unsigned long)v_taps[i][0] & 0x3FF) | + (((unsigned long)v_taps[i][1] & 0x3FF) << 10) | + (((unsigned long)v_taps[i][2] & 0x3FF) << 20); + } + + WRITE_REG32(DC3_FILT_COEFF1, temp0); + } + + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_configure_flicker_filter + * + * This routine updates the VG flicker filter settings when in an interlaced + * mode. Note that flicker filtering is enabled inside a mode set. This routine + * is provided to change from the default flicker filter setting of + * 1/4, 1/2, 1/4. + *--------------------------------------------------------------------------*/ + +int +vg_configure_flicker_filter(unsigned long flicker_strength, int flicker_alpha) +{ + unsigned long unlock; + unsigned long genlk_ctl; + + /* CHECK FOR VALID FLICKER SETTING */ + + if (flicker_strength != VG_FLICKER_FILTER_NONE && + flicker_strength != VG_FLICKER_FILTER_1_16 && + flicker_strength != VG_FLICKER_FILTER_1_8 && + flicker_strength != VG_FLICKER_FILTER_1_4 && + flicker_strength != VG_FLICKER_FILTER_5_16) { + return CIM_STATUS_INVALIDPARAMS; + } + + unlock = READ_REG32(DC3_UNLOCK); + genlk_ctl = READ_REG32(DC3_GENLK_CTL) & ~(DC3_GC_FLICKER_FILTER_MASK | + DC3_GC_ALPHA_FLICK_ENABLE); + genlk_ctl |= flicker_strength; + if (flicker_alpha) + genlk_ctl |= DC3_GC_ALPHA_FLICK_ENABLE; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_GENLK_CTL, genlk_ctl); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_clock_frequency + * + * This routine sets the frequency of the dot clock. The input to this + * routine is a 16.16 fraction. If an exact match is not found, this + * routine will program the closest available frequency and return + * CIM_STATUS_INEXACTMATCH. + *--------------------------------------------------------------------------*/ + +int +vg_set_clock_frequency(unsigned long frequency, unsigned long pll_flags) +{ + Q_WORD msr_value; + unsigned long timeout; + unsigned long index = 0; + unsigned long unlock, i; + unsigned long pll_high, pll_low; + long diff, min = 0; + + /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ + /* Search the table for the closest frequency (16.16 format). */ + /* This search is skipped if the user is manually specifying */ + /* the MSR value. */ + + pll_low = 0; + if (!(pll_flags & VG_PLL_MANUAL)) { + min = (long)CimarronPLLFrequencies[0].frequency - (long)frequency; + if (min < 0L) + min = -min; + + for (i = 1; i < NUM_CIMARRON_PLL_FREQUENCIES; i++) { + diff = (long)CimarronPLLFrequencies[i].frequency - + (long)frequency; + if (diff < 0L) + diff = -diff; + + if (diff < min) { + min = diff; + index = i; + } + } + + pll_high = CimarronPLLFrequencies[index].pll_value & 0x00007FFF; + } else { + pll_high = frequency; + } + + if (pll_flags & VG_PLL_DIVIDE_BY_2) + pll_low |= GLCP_DOTPLL_HALFPIX; + if (pll_flags & VG_PLL_DIVIDE_BY_4) + pll_high |= GLCP_DOTPLL_DIV4; + if (pll_flags & VG_PLL_BYPASS) + pll_low |= GLCP_DOTPLL_BYPASS; + if (pll_flags & VG_PLL_VIP_CLOCK) + pll_high |= GLCP_DOTPLL_VIPCLK; + + /* VERIFY THAT WE ARE NOT WRITING WHAT IS ALREADY IN THE REGISTERS */ + /* The Dot PLL reset bit is tied to VDD for flat panels. This can */ + /* cause a brief drop in flat panel power, which can cause serious */ + /* glitches on some panels. */ + + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value); + + if ((msr_value.low & GLCP_DOTPLL_LOCK) && + ((msr_value.low & (GLCP_DOTPLL_HALFPIX | GLCP_DOTPLL_BYPASS)) == + pll_low) && (msr_value.high == pll_high)) { + return CIM_STATUS_OK; + } + + /* PROGRAM THE SETTINGS WITH THE RESET BIT SET */ + /* Clear the bypass bit to ensure that the programmed */ + /* M, N and P values are being used. */ + + msr_value.high = pll_high; + msr_value.low &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX); + msr_value.low |= (pll_low | 0x00000001); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value); + + /* WAIT FOR THE LOCK BIT */ + /* The PLL spec states that the PLL may take up to 100 us to */ + /* properly lock. Furthermore, the lock signal is not 100% */ + /* reliable. To address this, we add a hefty delay followed */ + /* by a polling loop that times out after a 1000 reads. */ + + unlock = READ_REG32(DC3_UNLOCK); + for (timeout = 0; timeout < 1280; timeout++) + WRITE_REG32(DC3_UNLOCK, unlock); + + for (timeout = 0; timeout < 1000; timeout++) { + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value); + if (msr_value.low & GLCP_DOTPLL_LOCK) + break; + } + + /* CLEAR THE RESET BIT */ + + msr_value.low &= 0xFFFFFFFE; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value); + + /* DID THE PLL SUCCESSFULLY LOCK? */ + + if (!(msr_value.low & GLCP_DOTPLL_LOCK)) + return CIM_STATUS_NOLOCK; + + /* RETURN THE APPROPRIATE CODE */ + + if (min == 0) + return CIM_STATUS_OK; + else + return CIM_STATUS_INEXACTMATCH; +} + +/*--------------------------------------------------------------------------- + * vg_set_border_color + * + * This routine sets the color used as the border in centered panel modes. + *--------------------------------------------------------------------------*/ + +int +vg_set_border_color(unsigned long border_color) +{ + unsigned long lock = READ_REG32(DC3_UNLOCK); + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_PAL_ADDRESS, 0x104); + WRITE_REG32(DC3_PAL_DATA, border_color); + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_cursor_enable + * + * This routine enables or disables the hardware cursor. This routine should + * only be called after the hardware cursor has been completely configured. + *--------------------------------------------------------------------------*/ + +int +vg_set_cursor_enable(int enable) +{ + unsigned long unlock, gcfg; + + /* SET OR CLEAR CURSOR ENABLE BIT */ + + unlock = READ_REG32(DC3_UNLOCK); + gcfg = READ_REG32(DC3_GENERAL_CFG); + if (enable) + gcfg |= DC3_GCFG_CURE; + else + gcfg &= ~(DC3_GCFG_CURE); + + /* WRITE NEW REGISTER VALUE */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_mono_cursor_colors + * + * This routine sets the colors of the hardware monochrome cursor. + *--------------------------------------------------------------------------*/ + +int +vg_set_mono_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) +{ + unsigned long lock = READ_REG32(DC3_UNLOCK); + + /* SET CURSOR COLORS */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_PAL_ADDRESS, 0x100); + WRITE_REG32(DC3_PAL_DATA, bkcolor); + WRITE_REG32(DC3_PAL_DATA, fgcolor); + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_cursor_position + * + * This routine sets the position of the hardware cursor. The cursor hotspots + * and memory offset must have been specified in an earlier call to + * a vg_set_cursor_shape_XX routine. The coordinates passed to this routine + * generally specify the focal point of the cursor, NOT the upper left + * coordinate of the cursor pattern. However, for operating systems that do + * not include a hotspot the input parameters may be negative. + *--------------------------------------------------------------------------*/ + +int +vg_set_cursor_position(long xpos, long ypos, VG_PANNING_COORDINATES * panning) +{ + unsigned long unlock, memoffset; + unsigned long gcfg; + long x, xoffset; + long y, yoffset; + + memoffset = vg3_cursor_offset; + x = xpos - (long)vg3_x_hotspot; + y = ypos - (long)vg3_y_hotspot; + + /* HANDLE NEGATIVE COORDINATES */ + /* This routine supports operating systems that use negative */ + /* coordinates, instead of positive coordinates with an appropriate */ + /* hotspot. */ + + if (xpos < 0) + xpos = 0; + if (ypos < 0) + ypos = 0; + + if (x < -63) + return CIM_STATUS_INVALIDPARAMS; + if (y < -63) + return CIM_STATUS_INVALIDPARAMS; + + if (vg3_panel_enable) { + if ((vg3_mode_width > vg3_panel_width) + || (vg3_mode_height > vg3_panel_height)) { + vg_pan_desktop(xpos, ypos, panning); + x = x - (unsigned short)vg3_delta_x; + y = y - (unsigned short)vg3_delta_y; + } else { + panning->start_x = 0; + panning->start_y = 0; + panning->start_updated = 0; + } + } + + /* ADJUST OFFSETS */ + /* Cursor movement and panning work as follows: The cursor position */ + /* refers to where the hotspot of the cursor is located. However, for */ + /* non-zero hotspots, the cursor buffer actually begins before the */ + /* specified position. */ + + if (x < 0) { + xoffset = -x; + x = 0; + } else { + xoffset = 0; + } + if (y < 0) { + yoffset = -y; + y = 0; + } else { + yoffset = 0; + } + + if (vg3_color_cursor) + memoffset += (unsigned long)yoffset *192; + + else + memoffset += (unsigned long)yoffset << 4; + + /* SET COLOR CURSOR BIT */ + + gcfg = READ_REG32(DC3_GENERAL_CFG); + if (vg3_color_cursor) + gcfg |= DC3_GCFG_CLR_CUR; + else + gcfg &= ~DC3_GCFG_CLR_CUR; + + /* SET CURSOR POSITION */ + + unlock = READ_REG32(DC3_UNLOCK); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_CURS_ST_OFFSET, memoffset); + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + WRITE_REG32(DC3_CURSOR_X, (unsigned long)x | + (((unsigned long)xoffset) << 11)); + WRITE_REG32(DC3_CURSOR_Y, (unsigned long)y | + (((unsigned long)yoffset) << 11)); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_mono_cursor_shape32 + * + * This routine loads 32x32 cursor data into the cursor buffer in graphics + * memory. The outside of the GeodeLX cursor buffer is padded with + * transparency. + *--------------------------------------------------------------------------*/ + +int +vg_set_mono_cursor_shape32(unsigned long memoffset, unsigned long *andmask, + unsigned long *xormask, unsigned long x_hotspot, unsigned long y_hotspot) +{ + int i; + + /* SAVE THE CURSOR OFFSET AND HOTSPOTS */ + /* These are reused later when updating the cursor position, panning */ + /* and clipping the cursor pointer. */ + + vg3_x_hotspot = x_hotspot; + vg3_y_hotspot = y_hotspot; + vg3_cursor_offset = memoffset; + vg3_color_cursor = 0; + + for (i = 0; i < 32; i++) { + /* EVEN QWORDS CONTAIN THE AND MASK */ + + WRITE_FB32(memoffset, 0xFFFFFFFF); + WRITE_FB32(memoffset + 4, andmask[i]); + + /* ODD QWORDS CONTAIN THE XOR MASK */ + + WRITE_FB32(memoffset + 8, 0x00000000); + WRITE_FB32(memoffset + 12, xormask[i]); + + memoffset += 16; + } + + /* FILL THE LOWER HALF OF THE BUFFER WITH TRANSPARENT PIXELS */ + + for (i = 0; i < 32; i++) { + WRITE_FB32(memoffset, 0xFFFFFFFF); + WRITE_FB32(memoffset + 4, 0xFFFFFFFF); + WRITE_FB32(memoffset + 8, 0x00000000); + WRITE_FB32(memoffset + 12, 0x00000000); + + memoffset += 16; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_mono_cursor_shape64 + * + * This routine loads 64x64 cursor data into the cursor buffer in graphics + * memory. + *--------------------------------------------------------------------------*/ + +int +vg_set_mono_cursor_shape64(unsigned long memoffset, unsigned long *andmask, + unsigned long *xormask, unsigned long x_hotspot, unsigned long y_hotspot) +{ + int i; + + /* SAVE THE CURSOR OFFSET AND HOTSPOTS */ + /* These are reused later when updating the cursor position, panning */ + /* and clipping the cursor pointer. */ + + vg3_x_hotspot = x_hotspot; + vg3_y_hotspot = y_hotspot; + vg3_cursor_offset = memoffset; + vg3_color_cursor = 0; + + for (i = 0; i < 128; i += 2) { + /* EVEN QWORDS CONTAIN THE AND MASK */ + /* We invert the dwords to prevent the calling */ + /* application from having to think in terms of Qwords. */ + /* The hardware data order is actually 63:0, or 31:0 of */ + /* the second dword followed by 31:0 of the first dword. */ + + WRITE_FB32(memoffset, andmask[i + 1]); + WRITE_FB32(memoffset + 4, andmask[i]); + + /* ODD QWORDS CONTAIN THE XOR MASK */ + + WRITE_FB32(memoffset + 8, xormask[i + 1]); + WRITE_FB32(memoffset + 12, xormask[i]); + + memoffset += 16; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_color_cursor_shape + * + * This routine loads 8:8:8:8 cursor data into the color cursor buffer. + *--------------------------------------------------------------------------*/ + +int +vg_set_color_cursor_shape(unsigned long memoffset, unsigned char *data, + unsigned long width, unsigned long height, long pitch, + unsigned long x_hotspot, unsigned long y_hotspot) +{ + unsigned long y; + + /* SAVE THE CURSOR OFFSET AND HOTSPOTS */ + /* These are reused later when updating the cursor position, panning */ + /* and clipping the cursor pointer. */ + + vg3_x_hotspot = x_hotspot; + vg3_y_hotspot = y_hotspot; + vg3_cursor_offset = memoffset; + vg3_color_cursor = 1; + + /* WRITE THE CURSOR DATA */ + /* The outside edges of the color cursor are filled with transparency */ + /* The cursor buffer dimensions are 48x64. */ + + for (y = 0; y < height; y++) { + /* WRITE THE ACTIVE AND TRANSPARENT DATA */ + /* We implement this as a macro in our dedication to squeaking */ + /* every ounce of performance out of our code... */ + + WRITE_FB_STRING32(memoffset, data, width); + WRITE_FB_CONSTANT((memoffset + (width << 2)), 0, (48 - width)); + + /* INCREMENT PAST THE LINE */ + + memoffset += 192; + data += pitch; + } + + /* WRITE THE EXTRA TRANSPARENT LINES */ + /* Write the lines in one big bulk setting. */ + + WRITE_FB_CONSTANT(memoffset, 0, ((64 - height) * 48)); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_pan_desktop + * + * This routine sets the correct display offset based on the current cursor + * position. + *--------------------------------------------------------------------------*/ + +int +vg_pan_desktop(unsigned long x, unsigned long y, + VG_PANNING_COORDINATES * panning) +{ + unsigned long modeShiftPerPixel; + unsigned long modeBytesPerScanline; + unsigned long startAddress; + + /* TEST FOR NO-WORK */ + + if (x >= vg3_delta_x && x < (vg3_panel_width + vg3_delta_x) && + y >= vg3_delta_y && y < (vg3_panel_height + vg3_delta_y)) { + panning->start_x = vg3_delta_x; + panning->start_y = vg3_delta_y; + panning->start_updated = 0; + return CIM_STATUS_OK; + } + + if (vg3_bpp == 24) + modeShiftPerPixel = 2; + else + modeShiftPerPixel = (vg3_bpp + 7) >> 4; + + modeBytesPerScanline = (READ_REG32(DC3_GFX_PITCH) & 0x0000FFFF) << 3; + + /* ADJUST PANNING VARIABLES WHEN CURSOR EXCEEDS BOUNDARY */ + /* Test the boundary conditions for each coordinate and update */ + /* all variables and the starting offset accordingly. */ + + if (x < vg3_delta_x) + vg3_delta_x = x; + else if (x >= (vg3_delta_x + vg3_panel_width)) + vg3_delta_x = x - vg3_panel_width + 1; + + if (y < vg3_delta_y) + vg3_delta_y = y; + else if (y >= (vg3_delta_y + vg3_panel_height)) + vg3_delta_y = y - vg3_panel_height + 1; + + /* CALCULATE THE START OFFSET */ + + startAddress = (vg3_delta_x << modeShiftPerPixel) + + (vg3_delta_y * modeBytesPerScanline); + + vg_set_display_offset(startAddress); + + panning->start_updated = 1; + panning->start_x = vg3_delta_x; + panning->start_y = vg3_delta_y; + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_display_offset + * + * This routine sets the start address of the frame buffer. It is + * typically used to pan across a virtual desktop (frame buffer larger than + * the displayed screen) or to flip the display between multiple buffers. + *--------------------------------------------------------------------------*/ + +int +vg_set_display_offset(unsigned long address) +{ + unsigned long lock, gcfg; + + lock = READ_REG32(DC3_UNLOCK); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + /* DISABLE COMPRESSION */ + /* When setting a non-zero display offset, we must disable display */ + /* compression. We could maintain a variable and re-enable */ + /* compression when the offset returns to zero. However, that */ + /* creates additional complexity for applications that perform */ + /* graphics animation. Re-enabling compression each time would */ + /* be tedious and slow for such applications, implying that they */ + /* would have to disable compression before starting the animation. */ + /* We will instead disable compression and force the user to */ + /* re-enable compression when they are ready. */ + + if (address != 0) { + if (READ_REG32(DC3_GENERAL_CFG) & DC3_GCFG_CMPE) { + gcfg = READ_REG32(DC3_GENERAL_CFG); + WRITE_REG32(DC3_GENERAL_CFG, + (gcfg & ~(DC3_GCFG_CMPE | DC3_GCFG_DECE))); + } + } + + WRITE_REG32(DC3_FB_ST_OFFSET, address); + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_display_pitch + * + * This routine sets the stride between successive lines of data in the frame + * buffer. + *--------------------------------------------------------------------------*/ + +int +vg_set_display_pitch(unsigned long pitch) +{ + unsigned long temp, dvsize, dvtop, value; + unsigned long lock = READ_REG32(DC3_UNLOCK); + + value = READ_REG32(DC3_GFX_PITCH) & 0xFFFF0000; + value |= (pitch >> 3); + + /* PROGRAM THE DISPLAY PITCH */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_GFX_PITCH, value); + + /* SET THE COMPRESSION BEHAVIOR BASED ON THE PITCH */ + /* Strides that are not a power of two will not work with line */ + /* by line compression. For these cases, we enable full-screen */ + /* compression. In this mode, any write to the frame buffer */ + /* region marks the entire frame as dirty. Also, the DV line */ + /* size must be updated when the pitch is programmed outside of */ + /* the power of 2 range specified in a mode set. */ + + if (pitch > 4096) { + dvsize = DC3_DV_LINE_SIZE_8192; + } else if (pitch > 2048) { + dvsize = DC3_DV_LINE_SIZE_4096; + } else if (pitch > 1024) { + dvsize = DC3_DV_LINE_SIZE_2048; + } else { + dvsize = DC3_DV_LINE_SIZE_1024; + } + + temp = READ_REG32(DC3_DV_CTL); + WRITE_REG32(DC3_DV_CTL, + (temp & ~DC3_DV_LINE_SIZE_MASK) | dvsize | 0x00000001); + + value = READ_REG32(DC3_GENERAL_CFG); + + if (pitch == 1024 || pitch == 2048 || pitch == 4096 || pitch == 8192) { + value &= ~DC3_GCFG_FDTY; + dvtop = 0; + } else { + value |= DC3_GCFG_FDTY; + + dvtop = (READ_REG32(DC3_FB_ACTIVE) & 0xFFF) + 1; + dvtop = ((dvtop * pitch) + 0x3FF) & 0xFFFFFC00; + dvtop |= DC3_DVTOP_ENABLE; + } + + WRITE_REG32(DC3_GENERAL_CFG, value); + WRITE_REG32(DC3_DV_TOP, dvtop); + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_display_palette_entry + * + * This routine sets a single 8BPP palette entry in the display controller. + *--------------------------------------------------------------------------*/ + +int +vg_set_display_palette_entry(unsigned long index, unsigned long palette) +{ + unsigned long dcfg, unlock; + + if (index > 0xFF) + return CIM_STATUS_INVALIDPARAMS; + + unlock = READ_REG32(DC3_UNLOCK); + dcfg = READ_REG32(DC3_DISPLAY_CFG); + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_DISPLAY_CFG, dcfg & ~DC3_DCFG_PALB); + WRITE_REG32(DC3_UNLOCK, unlock); + + WRITE_REG32(DC3_PAL_ADDRESS, index); + WRITE_REG32(DC3_PAL_DATA, palette); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_set_display_palette + * + * This routine sets the entire palette in the display controller. + * A pointer is provided to a 256 entry table of 32-bit X:R:G:B values. + *--------------------------------------------------------------------------*/ + +int +vg_set_display_palette(unsigned long *palette) +{ + unsigned long unlock, dcfg, i; + + WRITE_REG32(DC3_PAL_ADDRESS, 0); + + if (palette) { + unlock = READ_REG32(DC3_UNLOCK); + dcfg = READ_REG32(DC3_DISPLAY_CFG); + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_DISPLAY_CFG, dcfg & ~DC3_DCFG_PALB); + WRITE_REG32(DC3_UNLOCK, unlock); + + for (i = 0; i < 256; i++) + WRITE_REG32(DC3_PAL_DATA, palette[i]); + + return CIM_STATUS_OK; + } + return CIM_STATUS_INVALIDPARAMS; +} + +/*--------------------------------------------------------------------------- + * vg_set_compression_enable + * + * This routine enables or disables display compression. + *--------------------------------------------------------------------------*/ + +int +vg_set_compression_enable(int enable) +{ + Q_WORD msr_value; + unsigned long unlock, gcfg; + unsigned long temp; + + unlock = READ_REG32(DC3_UNLOCK); + gcfg = READ_REG32(DC3_GENERAL_CFG); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + if (enable) { + /* DO NOT ENABLE IF THE DISPLAY OFFSET IS NOT ZERO */ + + if (READ_REG32(DC3_FB_ST_OFFSET) & 0x0FFFFFFF) + return CIM_STATUS_ERROR; + + /* ENABLE BIT 1 IN THE VG SPARE MSR + * The bus can hang when the VG attempts to merge compression writes. + * No performance is lost due to the GeodeLink QUACK features in + * GeodeLX. We also enable the command word check for a valid + * compression header. + */ + + msr_read64(MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value); + msr_value.low |= DC3_SPARE_FIRST_REQ_MASK; + msr_value.low &= ~DC3_SPARE_DISABLE_CWD_CHECK; + msr_write64(MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &msr_value); + + /* CLEAR DIRTY/VALID BITS IN MEMORY CONTROLLER + * We don't want the controller to think that old lines are still + * valid. Writing a 1 to bit 0 of the DV Control register will force + * the hardware to clear all the valid bits. + */ + + temp = READ_REG32(DC3_DV_CTL); + WRITE_REG32(DC3_DV_CTL, temp | 0x00000001); + + /* ENABLE COMPRESSION BITS */ + + gcfg |= DC3_GCFG_CMPE | DC3_GCFG_DECE; + } else { + gcfg &= ~(DC3_GCFG_CMPE | DC3_GCFG_DECE); + } + + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_configure_compression + * + * This routine configures all aspects of display compression, including + * pitch, size and the offset of the compression buffer. + *--------------------------------------------------------------------------*/ + +int +vg_configure_compression(VG_COMPRESSION_DATA * comp_data) +{ + unsigned long delta, size; + unsigned long comp_size, unlock; + + /* CHECK FOR VALID PARAMETERS */ + /* The maximum size for the compression buffer is 544 bytes (with */ + /* the header) Also, the pitch cannot be less than the line size */ + /* and the compression buffer offset must be 16-byte aligned. */ + + if (comp_data->size > 544 || comp_data->pitch < comp_data->size || + comp_data->compression_offset & 0x0F) { + return CIM_STATUS_INVALIDPARAMS; + } + + /* SUBTRACT 32 FROM SIZE */ + /* The display controller will actually write 4 extra QWords. So, */ + /* if we assume that "size" refers to the allocated size, we must */ + /* subtract 32 bytes. */ + + comp_size = comp_data->size - 32; + + /* CALCULATE REGISTER VALUES */ + + unlock = READ_REG32(DC3_UNLOCK); + size = READ_REG32(DC3_LINE_SIZE) & ~DC3_LINE_SIZE_CBLS_MASK; + delta = READ_REG32(DC3_GFX_PITCH) & ~DC3_GFX_PITCH_CBP_MASK; + + size |= ((comp_size >> 3) + 1) << DC3_LINE_SIZE_CB_SHIFT; + delta |= ((comp_data->pitch >> 3) << 16); + + /* WRITE COMPRESSION PARAMETERS */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_CB_ST_OFFSET, comp_data->compression_offset); + WRITE_REG32(DC3_LINE_SIZE, size); + WRITE_REG32(DC3_GFX_PITCH, delta); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_test_timing_active + * + * This routine checks the status of the display timing generator. + *--------------------------------------------------------------------------*/ + +int +vg_test_timing_active(void) +{ + if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * vg_test_vertical_active + * + * This routine checks if the display is currently in the middle of a frame + * (not in the VBlank interval) + *--------------------------------------------------------------------------*/ + +int +vg_test_vertical_active(void) +{ + if (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA) + return 0; + + return 1; +} + +/*--------------------------------------------------------------------------- + * vg_wait_vertical_blank + * + * This routine waits until the beginning of the vertical blank interval. + * When the display is already in vertical blank, this routine will wait until + * the beginning of the next vertical blank. + *--------------------------------------------------------------------------*/ + +int +vg_wait_vertical_blank(void) +{ + if (vg_test_timing_active()) { + while (!vg_test_vertical_active()) ; + while (vg_test_vertical_active()) ; + } + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_test_even_field + * + * This routine tests the odd/even status of the current VG output field. + *--------------------------------------------------------------------------*/ + +int +vg_test_even_field(void) +{ + if (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_EVEN_FIELD) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * vg_configure_line_interrupt + * + * This routine configures the display controller's line count interrupt. + * This interrupt can be used to interrupt mid-frame or to interrupt at the + * beginning of vertical blank. + *--------------------------------------------------------------------------*/ + +int +vg_configure_line_interrupt(VG_INTERRUPT_PARAMS * interrupt_info) +{ + unsigned long irq_line, irq_enable; + unsigned long lock; + + irq_line = READ_REG32(DC3_IRQ_FILT_CTL); + irq_enable = READ_REG32(DC3_IRQ); + lock = READ_REG32(DC3_UNLOCK); + + irq_line = (irq_line & ~DC3_IRQFILT_LINE_MASK) | + ((interrupt_info->line << 16) & DC3_IRQFILT_LINE_MASK); + + /* ENABLE OR DISABLE THE INTERRUPT */ + /* The line count is set before enabling and after disabling to */ + /* minimize spurious interrupts. The line count is set even */ + /* when interrupts are disabled to allow polling-based or debug */ + /* applications. */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + if (interrupt_info->enable) { + WRITE_REG32(DC3_IRQ_FILT_CTL, irq_line); + WRITE_REG32(DC3_IRQ, ((irq_enable & ~DC3_IRQ_MASK) | DC3_IRQ_STATUS)); + } else { + WRITE_REG32(DC3_IRQ, (irq_enable | DC3_IRQ_MASK)); + WRITE_REG32(DC3_IRQ_FILT_CTL, irq_line); + } + WRITE_REG32(DC3_UNLOCK, lock); + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_test_and_clear_interrupt + * + * This routine resets any pending interrupt in the video generator. The + * return value indicates the interrupt status prior to the reset. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_test_and_clear_interrupt(void) +{ + unsigned long irq_enable; + unsigned long lock; + + irq_enable = READ_REG32(DC3_IRQ); + lock = READ_REG32(DC3_UNLOCK); + + /* NO ACTION IF INTERRUPTS ARE MASKED */ + /* We are assuming that a driver or application will not want to receive */ + /* the status of the interrupt when it is masked. */ + + if ((irq_enable & (DC3_IRQ_MASK | DC3_VSYNC_IRQ_MASK)) == + (DC3_IRQ_MASK | DC3_VSYNC_IRQ_MASK)) + return 0; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_IRQ, irq_enable); + WRITE_REG32(DC3_UNLOCK, lock); + + return (irq_enable & (DC3_IRQ_STATUS | DC3_VSYNC_IRQ_STATUS)); +} + +/*--------------------------------------------------------------------------- + * vg_test_flip_status + * + * This routine tests if a new display offset has been latched. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_test_flip_status(void) +{ + return (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_FLIP); +} + +/*--------------------------------------------------------------------------- + * vg_save_state + * + * This routine saves all persistent VG state information. + *--------------------------------------------------------------------------*/ + +int +vg_save_state(VG_SAVE_RESTORE * vg_state) +{ + Q_WORD msr_value; + unsigned long irqfilt; + unsigned long offset, i; + unsigned long lock; + + /* READ ALL CURRENT REGISTER SETTINGS */ + + vg_state->unlock = READ_REG32(DC3_UNLOCK); + vg_state->gcfg = READ_REG32(DC3_GENERAL_CFG); + vg_state->dcfg = READ_REG32(DC3_DISPLAY_CFG); + vg_state->arb_cfg = READ_REG32(DC3_ARB_CFG); + vg_state->fb_offset = READ_REG32(DC3_FB_ST_OFFSET); + vg_state->cb_offset = READ_REG32(DC3_CB_ST_OFFSET); + vg_state->cursor_offset = READ_REG32(DC3_CURS_ST_OFFSET); + vg_state->video_y_offset = READ_REG32(DC3_VID_Y_ST_OFFSET); + vg_state->video_u_offset = READ_REG32(DC3_VID_U_ST_OFFSET); + vg_state->video_v_offset = READ_REG32(DC3_VID_V_ST_OFFSET); + vg_state->dv_top = READ_REG32(DC3_DV_TOP); + vg_state->line_size = READ_REG32(DC3_LINE_SIZE); + vg_state->gfx_pitch = READ_REG32(DC3_GFX_PITCH); + vg_state->video_yuv_pitch = READ_REG32(DC3_VID_YUV_PITCH); + vg_state->h_active = READ_REG32(DC3_H_ACTIVE_TIMING); + vg_state->h_blank = READ_REG32(DC3_H_BLANK_TIMING); + vg_state->h_sync = READ_REG32(DC3_H_SYNC_TIMING); + vg_state->v_active = READ_REG32(DC3_V_ACTIVE_TIMING); + vg_state->v_blank = READ_REG32(DC3_V_BLANK_TIMING); + vg_state->v_sync = READ_REG32(DC3_V_SYNC_TIMING); + vg_state->fb_active = READ_REG32(DC3_FB_ACTIVE); + vg_state->cursor_x = READ_REG32(DC3_CURSOR_X); + vg_state->cursor_y = READ_REG32(DC3_CURSOR_Y); + vg_state->vid_ds_delta = READ_REG32(DC3_VID_DS_DELTA); + vg_state->fb_base = READ_REG32(DC3_PHY_MEM_OFFSET); + vg_state->dv_ctl = READ_REG32(DC3_DV_CTL); + vg_state->gfx_scale = READ_REG32(DC3_GFX_SCALE); + vg_state->irq_ctl = READ_REG32(DC3_IRQ_FILT_CTL); + vg_state->vbi_even_ctl = READ_REG32(DC3_VBI_EVEN_CTL); + vg_state->vbi_odd_ctl = READ_REG32(DC3_VBI_ODD_CTL); + vg_state->vbi_hor_ctl = READ_REG32(DC3_VBI_HOR); + vg_state->vbi_odd_line_enable = READ_REG32(DC3_VBI_LN_ODD); + vg_state->vbi_even_line_enable = READ_REG32(DC3_VBI_LN_EVEN); + vg_state->vbi_pitch = READ_REG32(DC3_VBI_PITCH); + vg_state->color_key = READ_REG32(DC3_COLOR_KEY); + vg_state->color_key_mask = READ_REG32(DC3_COLOR_MASK); + vg_state->color_key_x = READ_REG32(DC3_CLR_KEY_X); + vg_state->color_key_y = READ_REG32(DC3_CLR_KEY_Y); + vg_state->irq = READ_REG32(DC3_IRQ); + vg_state->genlk_ctl = READ_REG32(DC3_GENLK_CTL); + vg_state->vid_y_even_offset = READ_REG32(DC3_VID_EVEN_Y_ST_OFFSET); + vg_state->vid_u_even_offset = READ_REG32(DC3_VID_EVEN_U_ST_OFFSET); + vg_state->vid_v_even_offset = READ_REG32(DC3_VID_EVEN_V_ST_OFFSET); + vg_state->vactive_even = READ_REG32(DC3_V_ACTIVE_EVEN); + vg_state->vblank_even = READ_REG32(DC3_V_BLANK_EVEN); + vg_state->vsync_even = READ_REG32(DC3_V_SYNC_EVEN); + + /* READ THE CURRENT PALETTE */ + + lock = READ_REG32(DC3_UNLOCK); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_PAL_ADDRESS, 0); + for (i = 0; i < 261; i++) + vg_state->palette[i] = READ_REG32(DC3_PAL_DATA); + + /* READ THE CURRENT FILTER COEFFICIENTS */ + + /* ENABLE ACCESS TO THE HORIZONTAL COEFFICIENTS */ + + irqfilt = READ_REG32(DC3_IRQ_FILT_CTL); + irqfilt |= DC3_IRQFILT_H_FILT_SEL; + + /* READ HORIZONTAL COEFFICIENTS */ + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + + vg_state->h_coeff[(i << 1)] = READ_REG32(DC3_FILT_COEFF1); + vg_state->h_coeff[(i << 1) + 1] = READ_REG32(DC3_FILT_COEFF2); + } + + /* ENABLE ACCESS TO THE VERTICAL COEFFICIENTS */ + + irqfilt &= ~DC3_IRQFILT_H_FILT_SEL; + + /* READ COEFFICIENTS */ + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + + vg_state->v_coeff[i] = READ_REG32(DC3_FILT_COEFF1); + } + + /* READ THE CURSOR DATA */ + + offset = READ_REG32(DC3_CURS_ST_OFFSET) & 0x0FFFFFFF; + for (i = 0; i < 3072; i++) + vg_state->cursor_data[i] = READ_FB32(offset + (i << 2)); + + /* READ THE CURRENT PLL */ + + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_DOTPLL, &msr_value); + + vg_state->pll_flags = 0; + for (i = 0; i < NUM_CIMARRON_PLL_FREQUENCIES; i++) { + if (CimarronPLLFrequencies[i].pll_value == (msr_value.high & 0x7FFF)) { + vg_state->dot_pll = CimarronPLLFrequencies[i].frequency; + break; + } + } + + if (i == NUM_CIMARRON_PLL_FREQUENCIES) { + /* NO MATCH */ + /* Enter the frequency as a manual frequency. */ + + vg_state->dot_pll = msr_value.high; + vg_state->pll_flags |= VG_PLL_MANUAL; + } + if (msr_value.low & GLCP_DOTPLL_HALFPIX) + vg_state->pll_flags |= VG_PLL_DIVIDE_BY_2; + if (msr_value.low & GLCP_DOTPLL_BYPASS) + vg_state->pll_flags |= VG_PLL_BYPASS; + if (msr_value.high & GLCP_DOTPLL_DIV4) + vg_state->pll_flags |= VG_PLL_DIVIDE_BY_4; + if (msr_value.high & GLCP_DOTPLL_VIPCLK) + vg_state->pll_flags |= VG_PLL_VIP_CLOCK; + + /* READ ALL VG MSRS */ + + msr_read64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CAP, + &(vg_state->msr_cap)); + msr_read64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CONFIG, + &(vg_state->msr_config)); + msr_read64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_SMI, + &(vg_state->msr_smi)); + msr_read64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_ERROR, + &(vg_state->msr_error)); + msr_read64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_PM, &(vg_state->msr_pm)); + msr_read64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, + &(vg_state->msr_diag)); + msr_read64(MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &(vg_state->msr_spare)); + msr_read64(MSR_DEVICE_GEODELX_VG, DC3_RAM_CTL, &(vg_state->msr_ram_ctl)); + + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_restore_state + * + * This routine restores all persistent VG state information. + *--------------------------------------------------------------------------*/ + +int +vg_restore_state(VG_SAVE_RESTORE * vg_state) +{ + unsigned long irqfilt, i; + unsigned long memoffset; + + /* TEMPORARILY UNLOCK ALL REGISTERS */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + /* RESTORE THE FRAME BUFFER OFFSET */ + + WRITE_REG32(DC3_PHY_MEM_OFFSET, vg_state->fb_base); + + /* BLANK GCFG AND DCFG */ + + WRITE_REG32(DC3_GENERAL_CFG, 0); + WRITE_REG32(DC3_DISPLAY_CFG, 0); + + /* RESTORE ALL REGISTERS */ + + WRITE_REG32(DC3_ARB_CFG, vg_state->arb_cfg); + WRITE_REG32(DC3_FB_ST_OFFSET, vg_state->fb_offset); + WRITE_REG32(DC3_CB_ST_OFFSET, vg_state->cb_offset); + WRITE_REG32(DC3_CURS_ST_OFFSET, vg_state->cursor_offset); + WRITE_REG32(DC3_VID_Y_ST_OFFSET, vg_state->video_y_offset); + WRITE_REG32(DC3_VID_U_ST_OFFSET, vg_state->video_u_offset); + WRITE_REG32(DC3_VID_V_ST_OFFSET, vg_state->video_v_offset); + WRITE_REG32(DC3_DV_TOP, vg_state->dv_top); + WRITE_REG32(DC3_LINE_SIZE, vg_state->line_size); + WRITE_REG32(DC3_GFX_PITCH, vg_state->gfx_pitch); + WRITE_REG32(DC3_VID_YUV_PITCH, vg_state->video_yuv_pitch); + WRITE_REG32(DC3_H_ACTIVE_TIMING, vg_state->h_active); + WRITE_REG32(DC3_H_BLANK_TIMING, vg_state->h_blank); + WRITE_REG32(DC3_H_SYNC_TIMING, vg_state->h_sync); + WRITE_REG32(DC3_V_ACTIVE_TIMING, vg_state->v_active); + WRITE_REG32(DC3_V_BLANK_TIMING, vg_state->v_blank); + WRITE_REG32(DC3_V_SYNC_TIMING, vg_state->v_sync); + WRITE_REG32(DC3_FB_ACTIVE, vg_state->fb_active); + WRITE_REG32(DC3_CURSOR_X, vg_state->cursor_x); + WRITE_REG32(DC3_CURSOR_Y, vg_state->cursor_y); + WRITE_REG32(DC3_VID_DS_DELTA, vg_state->vid_ds_delta); + WRITE_REG32(DC3_PHY_MEM_OFFSET, vg_state->fb_base); + WRITE_REG32(DC3_DV_CTL, vg_state->dv_ctl | 0x00000001); + WRITE_REG32(DC3_GFX_SCALE, vg_state->gfx_scale); + WRITE_REG32(DC3_IRQ_FILT_CTL, vg_state->irq_ctl); + WRITE_REG32(DC3_VBI_EVEN_CTL, vg_state->vbi_even_ctl); + WRITE_REG32(DC3_VBI_ODD_CTL, vg_state->vbi_odd_ctl); + WRITE_REG32(DC3_VBI_HOR, vg_state->vbi_hor_ctl); + WRITE_REG32(DC3_VBI_LN_ODD, vg_state->vbi_odd_line_enable); + WRITE_REG32(DC3_VBI_LN_EVEN, vg_state->vbi_even_line_enable); + WRITE_REG32(DC3_VBI_PITCH, vg_state->vbi_pitch); + WRITE_REG32(DC3_COLOR_KEY, vg_state->color_key); + WRITE_REG32(DC3_COLOR_MASK, vg_state->color_key_mask); + WRITE_REG32(DC3_CLR_KEY_X, vg_state->color_key_x); + WRITE_REG32(DC3_CLR_KEY_Y, vg_state->color_key_y); + WRITE_REG32(DC3_IRQ, vg_state->irq); + WRITE_REG32(DC3_GENLK_CTL, vg_state->genlk_ctl); + WRITE_REG32(DC3_VID_EVEN_Y_ST_OFFSET, vg_state->vid_y_even_offset); + WRITE_REG32(DC3_VID_EVEN_U_ST_OFFSET, vg_state->vid_u_even_offset); + WRITE_REG32(DC3_VID_EVEN_V_ST_OFFSET, vg_state->vid_v_even_offset); + WRITE_REG32(DC3_V_ACTIVE_EVEN, vg_state->vactive_even); + WRITE_REG32(DC3_V_BLANK_EVEN, vg_state->vblank_even); + WRITE_REG32(DC3_V_SYNC_EVEN, vg_state->vsync_even); + + /* RESTORE THE PALETTE */ + + WRITE_REG32(DC3_PAL_ADDRESS, 0); + for (i = 0; i < 261; i++) + WRITE_REG32(DC3_PAL_DATA, vg_state->palette[i]); + + /* RESTORE THE HORIZONTAL FILTER COEFFICIENTS */ + + irqfilt = READ_REG32(DC3_IRQ_FILT_CTL); + irqfilt |= DC3_IRQFILT_H_FILT_SEL; + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + WRITE_REG32(DC3_FILT_COEFF1, vg_state->h_coeff[(i << 1)]); + WRITE_REG32(DC3_FILT_COEFF2, vg_state->h_coeff[(i << 1) + 1]); + } + + /* RESTORE VERTICAL COEFFICIENTS */ + + irqfilt &= ~DC3_IRQFILT_H_FILT_SEL; + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + WRITE_REG32(DC3_FILT_COEFF1, vg_state->v_coeff[i]); + } + + /* RESTORE THE CURSOR DATA */ + + memoffset = READ_REG32(DC3_CURS_ST_OFFSET) & 0x0FFFFFFF; + WRITE_FB_STRING32(memoffset, (unsigned char *)&(vg_state->cursor_data[0]), + 3072); + + /* RESTORE THE PLL */ + /* Use a common routine to use common code to poll for lock bit */ + + vg_set_clock_frequency(vg_state->dot_pll, vg_state->pll_flags); + + /* RESTORE ALL VG MSRS */ + + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CAP, + &(vg_state->msr_cap)); + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_CONFIG, + &(vg_state->msr_config)); + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_SMI, + &(vg_state->msr_smi)); + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_ERROR, + &(vg_state->msr_error)); + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_PM, &(vg_state->msr_pm)); + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, + &(vg_state->msr_diag)); + msr_write64(MSR_DEVICE_GEODELX_VG, DC3_SPARE_MSR, &(vg_state->msr_spare)); + msr_write64(MSR_DEVICE_GEODELX_VG, DC3_RAM_CTL, &(vg_state->msr_ram_ctl)); + + /* NOW RESTORE GCFG AND DCFG */ + + WRITE_REG32(DC3_DISPLAY_CFG, vg_state->dcfg); + WRITE_REG32(DC3_GENERAL_CFG, vg_state->gcfg); + + /* FINALLY RESTORE UNLOCK */ + + WRITE_REG32(DC3_UNLOCK, vg_state->unlock); + + return CIM_STATUS_OK; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * CIMARRON VG READ ROUTINES + * These routines are included for use in diagnostics or when debugging. They + * can be optionally excluded from a project. + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +#if CIMARRON_INCLUDE_VG_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * vg_read_graphics_crc + * + * This routine reads the Cyclic Redundancy Check (CRC) value for the graphics + * frame. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_read_graphics_crc(int crc_source) +{ + unsigned long gcfg, unlock; + unsigned long crc, vbi_even; + unsigned long interlaced; + unsigned long line, field; + + if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) + return 0xFFFFFFFF; + + unlock = READ_REG32(DC3_UNLOCK); + gcfg = READ_REG32(DC3_GENERAL_CFG); + vbi_even = READ_REG32(DC3_VBI_EVEN_CTL); + + vbi_even &= ~DC3_VBI_EVEN_ENABLE_CRC; + + gcfg |= DC3_GCFG_SGRE | DC3_GCFG_CRC_MODE; + gcfg &= ~(DC3_GCFG_SGFR | DC3_GCFG_SIG_SEL | DC3_GCFG_FILT_SIG_SEL); + + switch (crc_source) { + case VG_CRC_SOURCE_PREFILTER_EVEN: + case VG_CRC_SOURCE_PREFILTER: + gcfg |= DC3_GCFG_SIG_SEL; + break; + case VG_CRC_SOURCE_PREFLICKER: + case VG_CRC_SOURCE_PREFLICKER_EVEN: + gcfg |= DC3_GCFG_FILT_SIG_SEL; + break; + case VG_CRC_SOURCE_POSTFLICKER: + case VG_CRC_SOURCE_POSTFLICKER_EVEN: /* NO WORK */ + break; + + default: + return 0xFFFFFFFF; + } + + if (crc_source & VG_CRC_SOURCE_EVEN) + field = 0; + else + field = DC3_LNCNT_EVEN_FIELD; + + if ((interlaced = (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN))) { + /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */ + /* Note that we wait for the field to be odd when CRCing the even */ + /* field and vice versa. This is because the CRC will not begin */ + /* until the following field. */ + + do { + line = READ_REG32(DC3_LINE_CNT_STATUS); + } while ((line & DC3_LNCNT_EVEN_FIELD) != field || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 10 || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 15); + } else { + /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */ + + if (crc_source & VG_CRC_SOURCE_EVEN) + return 0xFFFFFFFF; + } + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_VBI_EVEN_CTL, vbi_even); + WRITE_REG32(DC3_GENERAL_CFG, gcfg & ~DC3_GCFG_SIGE); + WRITE_REG32(DC3_GENERAL_CFG, gcfg | DC3_GCFG_SIGE); + + /* WAIT FOR THE CRC TO BE COMPLETED */ + + while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_SIGC)) ; + + /* READ THE COMPLETED CRC */ + + crc = READ_REG32(DC3_PAL_DATA); + + /* RESTORE THE PALETTE SETTINGS */ + + gcfg &= ~DC3_GCFG_SGRE; + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + WRITE_REG32(DC3_UNLOCK, unlock); + + return crc; +} + +/*--------------------------------------------------------------------------- + * vg_read_window_crc + * + * This routine reads the Cyclic Redundancy Check (CRC) value for a sub- + * section of the frame. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_read_window_crc(int crc_source, unsigned long x, unsigned long y, + unsigned long width, unsigned long height) +{ + Q_WORD msr_value; + unsigned long crc = 0; + unsigned long hactive, hblankstart; + unsigned long htotal, hblankend; + unsigned long line, field; + unsigned long diag; + + hactive = ((READ_REG32(DC3_H_ACTIVE_TIMING)) & 0xFFF) + 1; + hblankstart = ((READ_REG32(DC3_H_BLANK_TIMING)) & 0xFFF) + 1; + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + hblankend = ((READ_REG32(DC3_H_BLANK_TIMING) >> 16) & 0xFFF) + 1; + + /* TIMINGS MUST BE ACTIVE */ + + if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) + return 0xFFFFFFFF; + + /* DISABLE GLCP ACTIONS */ + + msr_value.low = 0; + msr_value.high = 0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); + + if ((x == 0 && width == 1) || x == 1) { + /* SPECIAL CASE FOR X == 0 */ + /* The comparator output is a clock late in the MCP, so we cannot */ + /* easily catch the first pixel. If the first pixel is desired, */ + /* we will insert a special state machine to CRC just the first */ + /* pixel. */ + + /* N2 - DISPE HIGH AND Y == 1 */ + /* Goto state YState = 2 */ + + msr_value.high = 0x00000002; + msr_value.low = 0x00000C00; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 2, &msr_value); + + /* M3 - DISPE HIGH AND Y == 0 */ + /* Goto YState = 1 */ + + msr_value.high = 0x00000002; + msr_value.low = 0x00000A00; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 3, &msr_value); + + /* N3 - DISPE LOW */ + /* Goto YState = 0 */ + + msr_value.high = 0x00080000; + msr_value.low = 0x00000000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 3, &msr_value); + + /* Y0 -> Y1 (SET M3) */ + + msr_value.high = 0x00000000; + msr_value.low = 0x0000C000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 18, &msr_value); + + /* Y1 -> Y0 (SET N3) */ + + msr_value.low = 0x0000A000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 17, &msr_value); + + /* Y1 -> Y2 (SET N2) */ + + msr_value.low = 0x00000A00; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 19, &msr_value); + + /* N5 (XSTATE = 10 && CMP2 <= V. COUNTER <= CMP3) &&DISPE&& Y == 0 */ + /* CRC into REGB */ + + msr_value.high = 0x00000002; + msr_value.low = 0x10800B20; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 5, &msr_value); + + /* N6 (XSTATE = 10 && CMP2 <= V. COUNTER <= CMP3) && DISPE&&Y == 1 */ + /* CRC into REGB */ + + msr_value.high = 0x00000002; + msr_value.low = 0x10800D20; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 6, &msr_value); + } + + /* M4 (XSTATE = 00 AND VSYNC HIGH) */ + /* Goto state 01 */ + /* Note: VSync = H3A */ + + msr_value.high = 0x00000001; + msr_value.low = 0x000000A0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 4, &msr_value); + + /* N0 (XSTATE = 01 AND VSYNC LOW) */ + /* Goto state 02 */ + /* Note: VSync low = H3B */ + + msr_value.high = 0x00040000; + msr_value.low = 0x000000C0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL, &msr_value); + + /* M5 (XSTATE = 10 AND VSYNC HIGH) */ + /* Goto state 11 */ + + msr_value.high = 0x00000001; + msr_value.low = 0x00000120; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 5, &msr_value); + + /* N1 (XSTATE = 10 and DISPE HIGH) */ + /* Increment H. Counter */ + /* Note: DispE = H4 */ + + msr_value.high = 0x00000002; + msr_value.low = 0x00000120; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 1, &msr_value); + + /* M0 (XSTATE = 10 and H. COUNTER == LIMIT) */ + /* Clear H. Counter and increment V. Counter */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000122; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL, &msr_value); + + /* N4 (XSTATE = 10 && CMP0 <= H. COUNTER <= CMP1 && CMP2 <= V. COUNTER + * <= CMP3) && DISPE + * CRC into REGB + */ + + msr_value.high = 0x00000002; + msr_value.low = 0x10C20120; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 4, &msr_value); + + /* COMPARATOR 0 VALUE */ + /* We subtract 1 to account for a pipeline delay in the GLCP. */ + /* When the x coordinate is 0, we must play a special game. */ + /* If the width is exactly 1, we will set up a state machine */ + /* to only CRC the first pixel. Otherwise, we will set it */ + /* as an OR combination of a state that CRCs the first pixel */ + /* and a state that CRCs 1 clock delayed width (width - 1) */ + + msr_value.high = 0; + if (x > 1) + msr_value.low = (x - 1) & 0xFFFF; + else + msr_value.low = x; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0, &msr_value); + + /* COMPARATOR 1 VALUE */ + + if ((x == 0 || x == 1) && width > 1) + msr_value.low += width - 2; + else + msr_value.low += width - 1; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 2, &msr_value); + + /* COMPARATOR 2 VALUE */ + + msr_value.low = y << 16; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 4, &msr_value); + + /* COMPARATOR 3 VALUE */ + + msr_value.low += (height - 1) << 16; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 6, &msr_value); + + /* COMPARATOR MASKS */ + /* Comparators 0 and 1 refer to lower 16 bits of RegB */ + + msr_value.low = 0x0000FFFF; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 2, &msr_value); + + /* Comparators 2 and 3 refer to upper 16 bits of RegB */ + + msr_value.low = 0xFFFF0000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 4, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 6, &msr_value); + + /* SET REGB MASK */ + /* We set the mask such that all all 32 bits of data are CRCed */ + + msr_value.low = 0xFFFFFFFF; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGBMASK, &msr_value); + + /* ACTIONS */ + + /* STATE 00->01 (SET 4M) */ + + msr_value.low = 0x000C0000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 14, &msr_value); + + /* STATE 01->10 (SET 0N) */ + + msr_value.low = 0x0000000A; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 15, &msr_value); + + /* STATE 10->11 (SET 5M) */ + + msr_value.low = 0x00C00000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 16, &msr_value); + + /* CLEAR REGA WHEN TRANSITIONING TO STATE 10 */ + /* Do not clear RegB as the initial value must be 0x00000001 */ + + msr_value.low = 0x0000000A; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0, &msr_value); + + /* REGISTER ACTION 1 + * CRC into RegB if cmp0 <= h.counter <= cmp1 && cmp2 <= v. counter < + * cmp3 && 7 xstate = 10 + * Increment h.counter if xstate = 10 and HSync is low. + */ + + msr_value.low = 0x000A00A0; + if (x == 0 && width == 1) + msr_value.low = 0x00A000A0; + else if (x == 1 && width == 1) + msr_value.low = 0x0A0000A0; + else if (x == 1 && width > 1) + msr_value.low |= 0x0A000000; + + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 1, &msr_value); + + /* REGISTER ACTION 2 */ + /* Increment V. Counter in REGA */ + + msr_value.low = 0x0000000C; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 2, &msr_value); + + /* SET REGB TO 0x00000001 */ + + msr_value.low = 0x00000001; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value); + + /* SET XSTATE TO 0 */ + + msr_value.low = 0x00000000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value); + + /* SET YSTATE TO 0 */ + + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_YSTATE, &msr_value); + + /* CLEAR ALL OTHER ACTIONS */ + /* This prevents side-effects from previous accesses to the GLCP */ + /* debug logic. */ + + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 3, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 4, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 5, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 6, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 7, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 8, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 9, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 10, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 11, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 12, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 13, &msr_value); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 20, &msr_value); + + /* SET DIAG SETTINGS BASED ON DESIRED CRC */ + + if (crc_source == VG_CRC_SOURCE_POSTFLICKER + || crc_source == VG_CRC_SOURCE_POSTFLICKER_EVEN) { + diag = 0x80808086; + + /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */ + + msr_value.high = 0; + msr_value.low = 5; + msr_write64(MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value); + msr_value.low = 0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + msr_value.low = 3; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + + /* SET REGA LIMITS */ + /* Lower counter uses pixels/line */ + /* Upper counter is 0xFFFF to prevent rollover. */ + + msr_value.low = 0xFFFF0000 | (hactive - 1); + if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) { + msr_value.low += hblankstart - hactive; + msr_value.low += htotal - hblankend; + } + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value); + + /* USE H4 FUNCTION A FOR DISPE AND H4 FUNCTION B FOR NOT DISPE */ + /* DISPE is bit 34 */ + + msr_value.high = 0x00000002; + msr_value.low = 0x20000FF0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 4, &msr_value); + + /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */ + /* VSYNC is bit 32. */ + + msr_value.high = 0x00000000; + msr_value.low = 0x002055AA; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value); + } else if (crc_source == VG_CRC_SOURCE_PREFLICKER + || crc_source == VG_CRC_SOURCE_PREFLICKER_EVEN) { + diag = 0x801F8032; + + /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO GEODELINK CLOCK */ + + msr_value.high = 0; + msr_value.low = 5; + msr_write64(MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value); + msr_value.low = 0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + msr_value.low = 2; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + + /* SET REGA LIMITS */ + /* Lower counter uses pixels/line */ + /* Upper counter is 0xFFFF to prevent rollover. */ + + msr_value.low = 0xFFFF0000 | (hactive - 1); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value); + + /* USE H4 FUNCTION A FOR DISPE AND H4 FUNCTION B FOR NOT DISPE */ + /* DISPE is bit 47 */ + + msr_value.high = 0x00000002; + msr_value.low = 0xF0000FF0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 4, &msr_value); + + /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */ + /* VSYNC is bit 45. */ + + msr_value.high = 0x00000000; + msr_value.low = 0x002D55AA; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value); + } else { + /* PREFILTER CRC */ + + diag = 0x80138048; + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, &msr_value); + + /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO GEODELINK CLOCK */ + + msr_value.high = 0; + msr_value.low = 5; + msr_write64(MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value); + msr_value.low = 0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + msr_value.low = 2; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); + + /* SET REGA LIMITS */ + /* Lower counter uses pixels/line */ + /* Upper counter is 0xFFFF to prevent rollover. */ + /* Note that we are assuming that the number of */ + /* source pixels is specified in the FB_ACTIVE register */ + + msr_value.low = + 0xFFFF0000 | ((READ_REG32(DC3_FB_ACTIVE) >> 16) & 0xFFF); + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value); + + /* USE H4 FUNCTION A FOR DISPE AND H4 FUNCTION B FOR NOT DISPE */ + /* DISPE is bit 55 */ + + msr_value.high = 0x00000003; + msr_value.low = 0x70000FF0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 4, &msr_value); + + /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */ + /* VSYNC is bit 53. */ + + msr_value.high = 0x00000000; + msr_value.low = 0x003555AA; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value); + } + + /* WAIT FOR THE CORRECT FIELD */ + /* We use the VG line count and field indicator to determine when */ + /* to kick off a CRC. */ + + if (crc_source & VG_CRC_SOURCE_EVEN) + field = 0; + else + field = DC3_LNCNT_EVEN_FIELD; + + if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { + /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */ + /* Note that we wait for the field to be odd when CRCing the even */ + /* field and vice versa. This is because the CRC will not begin */ + /* until the following field. */ + + do { + line = READ_REG32(DC3_LINE_CNT_STATUS); + } while ((line & DC3_LNCNT_EVEN_FIELD) != field || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 1 || + ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 5); + } else { + /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */ + + if (crc_source & VG_CRC_SOURCE_EVEN) + return 0xFFFFFFFF; + } + + /* UPDATE VG DIAG OUTPUT */ + + msr_value.high = 0; + msr_value.low = diag; + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, &msr_value); + + /* CONFIGURE DIAG CONTROL */ + /* Set RegA action1 to increment lower 16 bits and clear at limit. (5) */ + /* Set RegA action2 to increment upper 16 bits. (6) */ + /* Set RegB action1 to CRC32 (1) */ + /* Set all comparators to REGA override (0,1 lower mbus, 2,3 upper mbus) */ + /* Enable all actions */ + + msr_value.low = 0x80EA20A0; + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); + + /* DELAY TWO FRAMES */ + + while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA) ; + while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)) ; + while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA) ; + while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)) ; + while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA) ; + + /* VERIFY THAT XSTATE = 11 */ + + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value); + if ((msr_value.low & 3) == 3) { + msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value); + + crc = msr_value.low; + } + + /* DISABLE VG DIAG BUS OUTPUTS */ + + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + msr_write64(MSR_DEVICE_GEODELX_VG, MSR_GEODELINK_DIAG, &msr_value); + + /* DISABLE GLCP ACTIONS */ + + msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); + + return crc; +} + +/*--------------------------------------------------------------------------- + * vg_get_scaler_filter_coefficients + * + * This routine gets the vertical and horizontal filter coefficients for + * graphics scaling. The coefficients are sign extended to 32-bit values. + *--------------------------------------------------------------------------*/ + +int +vg_get_scaler_filter_coefficients(long h_taps[][5], long v_taps[][3]) +{ + unsigned long irqfilt, i; + unsigned long temp; + long coeff0, coeff1, coeff2; + unsigned long lock; + + /* ENABLE ACCESS TO THE HORIZONTAL COEFFICIENTS */ + + lock = READ_REG32(DC3_UNLOCK); + irqfilt = READ_REG32(DC3_IRQ_FILT_CTL); + irqfilt |= DC3_IRQFILT_H_FILT_SEL; + + /* WRITE COEFFICIENTS */ + /* Coefficient indexes do not auto-increment, so we must */ + /* write the address for every phase */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + + temp = READ_REG32(DC3_FILT_COEFF1); + coeff0 = (temp & 0x3FF); + coeff1 = (temp >> 10) & 0x3FF; + coeff2 = (temp >> 20) & 0x3FF; + + h_taps[i][0] = (coeff0 << 22) >> 22; + h_taps[i][1] = (coeff1 << 22) >> 22; + h_taps[i][2] = (coeff2 << 22) >> 22; + + temp = READ_REG32(DC3_FILT_COEFF2); + coeff0 = (temp & 0x3FF); + coeff1 = (temp >> 10) & 0x3FF; + + h_taps[i][3] = (coeff0 << 22) >> 22; + h_taps[i][4] = (coeff1 << 22) >> 22; + } + + /* ENABLE ACCESS TO THE VERTICAL COEFFICIENTS */ + + irqfilt &= ~DC3_IRQFILT_H_FILT_SEL; + + /* WRITE COEFFICIENTS */ + + for (i = 0; i < 256; i++) { + WRITE_REG32(DC3_IRQ_FILT_CTL, ((irqfilt & 0xFFFFFF00L) | i)); + + temp = READ_REG32(DC3_FILT_COEFF1); + coeff0 = (temp & 0x3FF); + coeff1 = (temp >> 10) & 0x3FF; + coeff2 = (temp >> 20) & 0x3FF; + + v_taps[i][0] = (coeff0 << 22) >> 22; + v_taps[i][1] = (coeff1 << 22) >> 22; + v_taps[i][2] = (coeff2 << 22) >> 22; + } + + WRITE_REG32(DC3_UNLOCK, lock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_get_flicker_filter_configuration + * + * This routine returns the current VG flicker filter configuration. + *--------------------------------------------------------------------------*/ + +int +vg_get_flicker_filter_configuration(unsigned long *strength, + int *flicker_alpha) +{ + unsigned long genlk_ctl; + + if (!strength || !flicker_alpha) + return CIM_STATUS_INVALIDPARAMS; + + genlk_ctl = READ_REG32(DC3_GENLK_CTL); + *strength = genlk_ctl & DC3_GC_FLICKER_FILTER_MASK; + if (genlk_ctl & DC3_GC_ALPHA_FLICK_ENABLE) + *flicker_alpha = 1; + else + *flicker_alpha = 0; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vg_get_display_pitch + * + * This routine returns the current stride between successive lines of frame + * buffer data. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_get_display_pitch(void) +{ + return ((READ_REG32(DC3_GFX_PITCH) & 0x0000FFFF) << 3); +} + +/*--------------------------------------------------------------------------- + * vg_get_frame_buffer_line_size + * + * This routine returns the current size in bytes of one line of frame buffer + * data. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_get_frame_buffer_line_size(void) +{ + return ((READ_REG32(DC3_LINE_SIZE) & 0x3FF) << 3); +} + +/*--------------------------------------------------------------------------- + * vg_get_current_vline + * + * This routine returns the number of the current line that is being displayed + * by the display controller. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_get_current_vline(void) +{ + unsigned long current_line; + + /* READ THE REGISTER TWICE TO ENSURE THAT THE VALUE IS NOT TRANSITIONING */ + + do { + current_line = READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_V_LINE_CNT; + } + while (current_line != + (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_V_LINE_CNT)); + + return (current_line >> 16); +} + +/*--------------------------------------------------------------------------- + * vg_get_display_offset + * + * This routine returns the offset into the frame buffer for the first pixel + * of the display. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_get_display_offset(void) +{ + return (READ_REG32(DC3_FB_ST_OFFSET) & 0x0FFFFFFF); +} + +/*--------------------------------------------------------------------------- + * vg_get_cursor_info + * + * This routine returns the current settings for the hardware cursor. + *--------------------------------------------------------------------------*/ + +int +vg_get_cursor_info(VG_CURSOR_DATA * cursor_data) +{ + unsigned long temp; + + /* CURSOR OFFSET */ + + cursor_data->cursor_offset = READ_REG32(DC3_CURS_ST_OFFSET) & 0x0FFFFFFF; + + /* CURSOR X POSITION */ + + temp = READ_REG32(DC3_CURSOR_X); + cursor_data->cursor_x = temp & 0x7FF; + cursor_data->clipx = (temp >> 11) & 0x3F; + + /* CURSOR Y POSITION */ + + temp = READ_REG32(DC3_CURSOR_Y); + cursor_data->cursor_y = temp & 0x7FF; + cursor_data->clipy = (temp >> 11) & 0x3F; + + /* CURSOR COLORS */ + + WRITE_REG32(DC3_PAL_ADDRESS, 0x100); + cursor_data->mono_color0 = READ_REG32(DC3_PAL_DATA); + cursor_data->mono_color1 = READ_REG32(DC3_PAL_DATA); + + /* CURSOR ENABLES */ + + temp = READ_REG32(DC3_GENERAL_CFG); + if (temp & DC3_GCFG_CURE) + cursor_data->enable = 1; + else + cursor_data->enable = 0; + if (temp & DC3_GCFG_CLR_CUR) + cursor_data->color_cursor = 1; + else + cursor_data->color_cursor = 0; + + return CIM_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * vg_get_display_palette_entry + * + * This routine reads a single entry in the 8BPP display palette. + *--------------------------------------------------------------------------*/ + +int +vg_get_display_palette_entry(unsigned long index, unsigned long *entry) +{ + if (index > 0xFF) + return CIM_STATUS_INVALIDPARAMS; + + WRITE_REG32(DC3_PAL_ADDRESS, index); + *entry = READ_REG32(DC3_PAL_DATA); + + return CIM_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * vg_get_border_color + * + * This routine reads the current border color for centered displays. + *--------------------------------------------------------------------------*/ + +unsigned long +vg_get_border_color(void) +{ + WRITE_REG32(DC3_PAL_ADDRESS, 0x104); + return READ_REG32(DC3_PAL_DATA); +} + +/*---------------------------------------------------------------------------- + * vg_get_display_palette + * + * This routines reads the entire contents of the display palette into a + * buffer. The display palette consists of 256 X:R:G:B values. + *--------------------------------------------------------------------------*/ + +int +vg_get_display_palette(unsigned long *palette) +{ + unsigned long i; + + if (palette) { + WRITE_REG32(DC3_PAL_ADDRESS, 0); + for (i = 0; i < 256; i++) { + palette[i] = READ_REG32(DC3_PAL_DATA); + } + return CIM_STATUS_OK; + } + return CIM_STATUS_INVALIDPARAMS; +} + +/*---------------------------------------------------------------------------- + * vg_get_compression_info + * + * This routines reads the current status of the display compression hardware. + *--------------------------------------------------------------------------*/ + +int +vg_get_compression_info(VG_COMPRESSION_DATA * comp_data) +{ + comp_data->compression_offset = READ_REG32(DC3_CB_ST_OFFSET) & 0x0FFFFFFF; + comp_data->pitch = (READ_REG32(DC3_GFX_PITCH) >> 13) & 0x7FFF8; + comp_data->size = ((READ_REG32(DC3_LINE_SIZE) >> (DC3_LINE_SIZE_CB_SHIFT - + 3)) & 0x3F8) + 24; + + return CIM_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * vg_get_compression_enable + * + * This routines reads the current enable status of the display compression + * hardware. + *--------------------------------------------------------------------------*/ + +int +vg_get_compression_enable(void) +{ + if (READ_REG32(DC3_GENERAL_CFG) & DC3_GCFG_CMPE) + return 1; + + return 0; +} + +/*---------------------------------------------------------------------------- + * vg_get_valid_bit + *--------------------------------------------------------------------------*/ + +int +vg_get_valid_bit(int line) +{ + unsigned long offset; + unsigned long valid; + unsigned long lock; + + lock = READ_REG32(DC3_UNLOCK); + offset = READ_REG32(DC3_PHY_MEM_OFFSET) & 0xFF000000; + offset |= line; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_PHY_MEM_OFFSET, offset); + WRITE_REG32(DC3_UNLOCK, lock); + valid = READ_REG32(DC3_DV_ACC) & 2; + + if (valid) + return 1; + return 0; +} + +#endif diff --git a/src/cim/cim_vip.c b/src/cim/cim_vip.c new file mode 100644 index 0000000..025449b --- /dev/null +++ b/src/cim/cim_vip.c @@ -0,0 +1,1640 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron VIP configuration routines. + */ + +/*--------------------------------------------------------------------------- + * vip_initialize + * + * This routine initializes the internal module state and prepares the + * module for subsequent VIP orientated activities. + *--------------------------------------------------------------------------*/ + +int +vip_initialize(VIPSETMODEBUFFER * buffer) +{ + unsigned long vip_control1, vip_control2, vip_control3; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 = 0; + vip_control2 = 0; + vip_control3 = 0; + + /* CONFIGURE CONTROL WORDS BASED ON MODE STRUCTURE */ + /* Note that some of the input parameters match the register fields */ + /* they represent. */ + + /* STREAM ENABLES */ + + vip_control1 |= buffer->stream_enables; + + /* VIP CAPTURE MODE */ + + vip_control1 |= buffer->operating_mode; + + /* HANDLE PLANAR CAPTURE */ + + if (buffer->flags & VIP_MODEFLAG_PLANARCAPTURE) { + vip_control1 |= VIP_CONTROL1_PLANAR; + + if (buffer->planar_capture == VIP_420CAPTURE_EVERYLINE) { + vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION; + } else if (buffer->planar_capture == VIP_420CAPTURE_ALTERNATINGFIELDS) { + if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION; + vip_control3 |= VIP_CONTROL3_DECIMATE_EVEN; + } else if (buffer->planar_capture != VIP_420CAPTURE_ALTERNATINGLINES) + return CIM_STATUS_INVALIDPARAMS; + + /* CONFIGURE THE VIDEO FIFO THRESHOLD BASED ON THE FIFO DEPTH */ + + vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_420 << + VIP_CONTROL2_VIDTH_SHIFT; + + } else { + vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_422 << + VIP_CONTROL2_VIDTH_SHIFT; + } + + /* CONFIGURE DEFAULT ANCILARRY THRESHOLD AND VIDEO FLUSH VALUES */ + + vip_control2 |= VIP_CONTROL2_DEFAULT_ANCTH << VIP_CONTROL2_ANCTH_SHIFT; + vip_control1 |= VIP_CONTROL1_DEFAULT_ANC_FF << VIP_CONTROL1_ANC_FF_SHIFT; + vip_control1 |= VIP_CONTROL1_DEFAULT_VID_FF << VIP_CONTROL1_VID_FF_SHIFT; + + /* PROGRAM VIP OPTIONS */ + /* The options are sanitized based on the current configuration. */ + + if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE) + vip_control1 |= VIP_CONTROL1_NON_INTERLACED; + else { + if (buffer->flags & VIP_MODEFLAG_TOGGLEEACHFIELD) + vip_control3 |= VIP_CONTROL3_BASE_UPDATE; + if (buffer->flags & VIP_MODEFLAG_INVERTPOLARITY) + vip_control2 |= VIP_CONTROL2_INVERT_POLARITY; + } + + if ((buffer->operating_mode == VIP_MODE_MSG || + buffer->operating_mode == VIP_MODE_DATA) && + (buffer->flags & VIP_MODEFLAG_FLIPMESSAGEWHENFULL)) { + vip_control1 |= VIP_CONTROL1_MSG_STRM_CTRL; + } + + else if (buffer->operating_mode == VIP_MODE_VIP2_8BIT || + buffer->operating_mode == VIP_MODE_VIP2_16BIT) { + if (buffer->flags & VIP_MODEFLAG_ENABLEREPEATFLAG) + vip_control2 |= VIP_CONTROL2_REPEAT_ENABLE; + if (buffer->flags & VIP_MODEFLAG_INVERTTASKPOLARITY) + vip_control3 |= VIP_CONTROL3_TASK_POLARITY; + } + + if (buffer->flags & VIP_MODEFLAG_DISABLEZERODETECT) + vip_control1 |= VIP_CONTROL1_DISABLE_ZERO_DETECT; + if (buffer->flags & VIP_MODEFLAG_10BITANCILLARY) + vip_control2 |= VIP_CONTROL2_ANC10; + + /* WRITE THE CONTROL REGISTERS */ + /* The control registers are kept 'live' to allow separate instances of */ + /* Cimarron to control the VIP hardware. */ + + WRITE_VIP32(VIP_CONTROL1, vip_control1); + WRITE_VIP32(VIP_CONTROL2, vip_control2); + WRITE_VIP32(VIP_CONTROL3, vip_control3); + + /* CONFIGURE 601 PARAMETERS */ + + if (buffer->operating_mode == VIP_MODE_8BIT601 || + buffer->operating_mode == VIP_MODE_16BIT601) { + vip_update_601_params(&buffer->vip601_settings); + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_update_601_params + * + * This routine configures all aspects of 601 VIP data capture, including + * start and stop timings and input polarities. + *--------------------------------------------------------------------------*/ + +int +vip_update_601_params(VIP_601PARAMS * buffer) +{ + unsigned long vip_control3, vip_control1; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 = READ_VIP32(VIP_CONTROL3); + vip_control3 = READ_VIP32(VIP_CONTROL3); + + if (buffer->flags & VIP_MODEFLAG_VSYNCACTIVEHIGH) + vip_control3 |= VIP_CONTROL3_VSYNC_POLARITY; + else + vip_control3 &= ~VIP_CONTROL3_VSYNC_POLARITY; + if (buffer->flags & VIP_MODEFLAG_HSYNCACTIVEHIGH) + vip_control3 |= VIP_CONTROL3_HSYNC_POLARITY; + else + vip_control3 &= ~VIP_CONTROL3_HSYNC_POLARITY; + + WRITE_VIP32(VIP_CONTROL3, vip_control3); + WRITE_VIP32(VIP_601_HORZ_START, buffer->horz_start); + WRITE_VIP32(VIP_601_VBI_START, buffer->vbi_start); + WRITE_VIP32(VIP_601_VBI_END, buffer->vbi_start + buffer->vbi_height - 1); + WRITE_VIP32(VIP_601_EVEN_START_STOP, + buffer->vert_start_even | ((buffer->vert_start_even + + buffer->even_height - 1) << 16)); + WRITE_VIP32(VIP_601_ODD_START_STOP, + buffer->vert_start_odd | ((buffer->vert_start_odd + + buffer->odd_height - 1) << 16)); + WRITE_VIP32(VIP_ODD_FIELD_DETECT, + buffer->odd_detect_start | (buffer->odd_detect_end << 16)); + + /* SPECIAL CASE FOR HORIZONTAL DATA + * 601 horizontal parameters are based on the number of clocks and not + * the number of pixels. + */ + + if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601) + WRITE_VIP32(VIP_601_HORZ_END, + buffer->horz_start + (buffer->width << 1) + 3); + else + WRITE_VIP32(VIP_601_HORZ_END, buffer->horz_start + buffer->width + 3); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_capture_buffers + * + * This routine configures the base offsets for video, ancillary or message + * mode capture. The input structure can also contain multiple offsets, such + * that the calling application can avoid updating the structure for each + * flip. + * + * The new buffer addresses are written to the hardware registers although + * they may not be latched immediately. Calling vip_is_buffer_update_latched + * allows the determination of whether the update has occured. + * + * Review the Cimarron VIP API documentation to determine which buffer + * addresses are latched immediately. + *--------------------------------------------------------------------------*/ + +int +vip_configure_capture_buffers(int buffer_type, VIPINPUTBUFFER * buffer) +{ + VIPINPUTBUFFER_ADDR *offsets; + unsigned long cur_buffer = buffer->current_buffer; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + if (buffer_type == VIP_BUFFER_A || buffer_type == VIP_BUFFER_601) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET VIDEO PITCH */ + + WRITE_VIP32(VIP_TASKA_VID_PITCH, + offsets->y_pitch | (offsets->uv_pitch << 16)); + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) { + WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, + offsets->even_base[cur_buffer]); + WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, + offsets->odd_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) { + WRITE_VIP32(VIP_TASKA_VBI_ODD_BASE, offsets->vbi_even_base); + WRITE_VIP32(VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_odd_base); + } + } else { + WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, + offsets->odd_base[cur_buffer]); + WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, + offsets->even_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) { + WRITE_VIP32(VIP_TASKA_VBI_ODD_BASE, offsets->vbi_odd_base); + WRITE_VIP32(VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_even_base); + } + } + + /* SET 4:2:0 OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_PLANAR) { + WRITE_VIP32(VIP_TASKA_U_OFFSET, offsets->odd_uoffset); + WRITE_VIP32(VIP_TASKA_V_OFFSET, offsets->odd_voffset); + WRITE_VIP32(VIP_TASKA_U_EVEN_OFFSET, offsets->even_uoffset); + WRITE_VIP32(VIP_TASKA_V_EVEN_OFFSET, offsets->even_voffset); + } + } else if (buffer_type == VIP_BUFFER_B) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET VIDEO PITCH */ + + WRITE_VIP32(VIP_TASKB_VID_PITCH, + offsets->y_pitch | (offsets->uv_pitch << 16)); + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) { + WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, + offsets->even_base[cur_buffer]); + WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, + offsets->odd_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) { + WRITE_VIP32(VIP_TASKB_VBI_ODD_BASE, offsets->vbi_even_base); + WRITE_VIP32(VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_odd_base); + } + } else { + WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, + offsets->odd_base[cur_buffer]); + WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, + offsets->even_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) { + WRITE_VIP32(VIP_TASKB_VBI_ODD_BASE, offsets->vbi_odd_base); + WRITE_VIP32(VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_even_base); + } + } + + /* SET 4:2:0 OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_PLANAR) { + WRITE_VIP32(VIP_TASKB_U_OFFSET, offsets->odd_uoffset); + WRITE_VIP32(VIP_TASKB_V_OFFSET, offsets->odd_voffset); + } + } else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG) { + WRITE_VIP32(VIP_ANC_MSG1_BASE, buffer->ancillaryData.msg1_base); + WRITE_VIP32(VIP_ANC_MSG2_BASE, buffer->ancillaryData.msg2_base); + WRITE_VIP32(VIP_ANC_MSG_SIZE, buffer->ancillaryData.msg_size); + } else { + return CIM_STATUS_INVALIDPARAMS; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_toggle_vip_video_offsets + * + * This routine updates the offsets for video capture. It is a simplified + * version of vip_configure_capture_buffers that is designed to be called from + * interrupt service routines or other buffer flipping applications that + * require low latency. + *--------------------------------------------------------------------------*/ + +int +vip_toggle_video_offsets(int buffer_type, VIPINPUTBUFFER * buffer) +{ + unsigned long cur_buffer = buffer->current_buffer; + VIPINPUTBUFFER_ADDR *offsets; + + if (buffer_type == VIP_BUFFER_A) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) { + WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, + offsets->even_base[cur_buffer]); + WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, + offsets->odd_base[cur_buffer]); + } else { + WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, + offsets->odd_base[cur_buffer]); + WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, + offsets->even_base[cur_buffer]); + } + } else if (buffer_type == VIP_BUFFER_B) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) { + WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, + offsets->even_base[cur_buffer]); + WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, + offsets->odd_base[cur_buffer]); + } else { + WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, + offsets->odd_base[cur_buffer]); + WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, + offsets->even_base[cur_buffer]); + } + } else if (buffer_type == VIP_BUFFER_A_ODD) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, + offsets->even_base[cur_buffer]); + else + WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, + offsets->odd_base[cur_buffer]); + } else if (buffer_type == VIP_BUFFER_A_EVEN) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, + offsets->odd_base[cur_buffer]); + else + WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, + offsets->even_base[cur_buffer]); + } else if (buffer_type == VIP_BUFFER_B_ODD) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, + offsets->even_base[cur_buffer]); + else + WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, + offsets->odd_base[cur_buffer]); + } else if (buffer_type == VIP_BUFFER_B_EVEN) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, + offsets->odd_base[cur_buffer]); + else + WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, + offsets->even_base[cur_buffer]); + } else + return CIM_STATUS_INVALIDPARAMS; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_capture_state + * + * This routine takes the current control word definition ( stored in locals ) + * adds in the specified state, and writes the control word. + *--------------------------------------------------------------------------*/ + +int +vip_set_capture_state(unsigned long state) +{ + unsigned long vip_control1, vip_control3; + + /* UPDATE THE CURRENT CAPTURE MODE */ + + vip_control1 = READ_VIP32(VIP_CONTROL1); + vip_control3 = READ_VIP32(VIP_CONTROL3); + vip_control1 &= ~VIP_CONTROL1_RUNMODE_MASK; + vip_control1 |= (state << VIP_CONTROL1_RUNMODE_SHIFT); + + WRITE_VIP32(VIP_CONTROL1, vip_control1); + + if (state >= VIP_STARTCAPTUREATNEXTLINE) { + /* WHACK VIP RESET + * The VIP can get confused when switching between capture settings, + * such as between linear and planar. We will thus whack VIP reset + * when enabling capture to ensure a pristine VIP state. + */ + + WRITE_VIP32(VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET); + WRITE_VIP32(VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET); + WRITE_VIP32(VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET); + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_terminate + * + * This routine stops VIP capture and resets the VIP internal state. + *--------------------------------------------------------------------------*/ + +int +vip_terminate(void) +{ + unsigned long timeout = 50000; + + /* DISABLE AND CLEAR ALL VIP INTERRUPTS */ + + WRITE_VIP32(VIP_INTERRUPT, VIP_ALL_INTERRUPTS | + (VIP_ALL_INTERRUPTS >> 16)); + + /* DISABLE VIP CAPTURE */ + /* We will try to let the VIP FIFO flush before shutting it down. */ + + WRITE_VIP32(VIP_CONTROL1, 0); + while (timeout) { + timeout--; + if (READ_VIP32(VIP_STATUS) & VIP_STATUS_WRITES_COMPLETE) + break; + } + + /* RESET THE HARDWARE REGISTERS */ + /* Note that we enable VIP reset to allow clock gating to lower VIP */ + /* power consumption. */ + + WRITE_VIP32(VIP_CONTROL1, VIP_CONTROL1_RESET); + WRITE_VIP32(VIP_CONTROL3, VIP_CONTROL3_FIFO_RESET); + WRITE_VIP32(VIP_CONTROL2, 0); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_fifo + * + * This routine sets the desired threshold or flush for the specified fifo. + *--------------------------------------------------------------------------*/ + +int +vip_configure_fifo(unsigned long fifo_type, unsigned long fifo_size) +{ + unsigned long vip_control1, vip_control2; + + vip_control1 = READ_VIP32(VIP_CONTROL1); + vip_control2 = READ_VIP32(VIP_CONTROL2); + + switch (fifo_type) { + case VIP_VIDEOTHRESHOLD: + vip_control2 &= ~VIP_CONTROL2_VIDTH_MASK; + vip_control2 |= + (fifo_size << VIP_CONTROL2_VIDTH_SHIFT) & VIP_CONTROL2_VIDTH_MASK; + break; + + case VIP_ANCILLARYTHRESHOLD: + vip_control2 &= ~VIP_CONTROL2_ANCTH_MASK; + vip_control2 |= + (fifo_size << VIP_CONTROL2_ANCTH_SHIFT) & VIP_CONTROL2_ANCTH_MASK; + break; + + case VIP_VIDEOFLUSH: + vip_control1 &= ~VIP_CONTROL1_VID_FF_MASK; + vip_control1 |= + ((fifo_size >> 2) << VIP_CONTROL1_VID_FF_SHIFT) & + VIP_CONTROL1_VID_FF_MASK; + break; + + case VIP_ANCILLARYFLUSH: + vip_control1 &= ~VIP_CONTROL1_ANC_FF_MASK; + vip_control1 |= + ((fifo_size >> 2) << VIP_CONTROL1_ANC_FF_SHIFT) & + VIP_CONTROL1_ANC_FF_MASK; + break; + + default: + return CIM_STATUS_INVALIDPARAMS; + } + + WRITE_VIP32(VIP_CONTROL1, vip_control1); + WRITE_VIP32(VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_interrupt_enable + * + * This routine accepts a mask of interrupts to be enabled/disabled and + * an enable flag. + * + * For each mask match, the interrupt will be enabled or disabled based on + * enable + *--------------------------------------------------------------------------*/ + +int +vip_set_interrupt_enable(unsigned long mask, int enable) +{ + /* CHECK IF ANY VALID INTERRUPTS ARE BEING CHANGED */ + + if (mask & VIP_ALL_INTERRUPTS) { + unsigned long int_enable = READ_VIP32(VIP_INTERRUPT) & 0xFFFF; + + /* SET OR CLEAR THE MASK BITS */ + /* Note that the upper 16-bits of the register are 0 after this */ + /* operation. This prevents us from indadvertently clearing a */ + /* pending interrupt by enabling/disabling another one. */ + + if (enable) + int_enable &= ~(mask >> 16); + else + int_enable |= (mask >> 16); + + WRITE_VIP32(VIP_INTERRUPT, int_enable); + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_vsync_error + * + * This routine defines a region that is used to determine if the vsync is + * within an acceptable range. This definition is accomplished using + * a count and a vertical window. The count specifies the exact number + * of clocks expected for one field. The window parameters specify the number + * of clocks variation allowed before and after the expected vsync. For + * example, if vertical_count is 1000, window_before is 5 and window_after + * is 12, VSync will be considered valid if it occurs between 995 and 1012 + * clocks after the last VSync. The total window size (window_before + + * window_after) cannot exceed 255. + *--------------------------------------------------------------------------*/ + +int +vip_set_vsync_error(unsigned long vertical_count, unsigned long window_before, + unsigned long window_after, int enable) +{ + unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2); + unsigned long temp; + + if (enable) { + /* CREATE THE VERTICAL WINDOW + * The VIP uses two counters. The first counter defines the minimum + * clock count before a valid VSync can occur. The second counter + * starts after the first completes and defines the acceptable + * region of variation. + */ + + temp = ((window_before + + window_after) << VIP_VSYNC_ERR_WINDOW_SHIFT) & + VIP_VSYNC_ERR_WINDOW_MASK; + temp |= (vertical_count - window_before) & VIP_VSYNC_ERR_COUNT_MASK; + + vip_control2 |= VIP_CONTROL2_VERTERROR_ENABLE; + + WRITE_VIP32(VIP_VSYNC_ERR_COUNT, temp); + } else { + vip_control2 &= ~VIP_CONTROL2_VERTERROR_ENABLE; + } + WRITE_VIP32(VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_max_address_enable + * + * This routine specifies the maximum address to which the the hardware should + * write during data storage. If this value is exceeded an error is generated, + * (this may be monitored using the appropriate interrupt flags - see + * vip_set_interrupt_enable) + *--------------------------------------------------------------------------*/ + +int +vip_max_address_enable(unsigned long max_address, int enable) +{ + unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2); + + if (enable) { + /* ENABLE THE CONTROL BIT */ + + vip_control2 |= VIP_CONTROL2_ADD_ERROR_ENABLE; + + WRITE_VIP32(VIP_MAX_ADDRESS, max_address & VIP_MAXADDR_MASK); + } else { + /* DISABLE DETECTION */ + + vip_control2 &= ~VIP_CONTROL2_ADD_ERROR_ENABLE; + } + WRITE_VIP32(VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_loopback_enable + * + * This routine enables/disables internal loopback functionality. When + * loopback is enabled, the VOP outputs are rerouted to the VIP inputs + * internal to the chip. No loopback connector is required. + *--------------------------------------------------------------------------*/ + +int +vip_set_loopback_enable(int enable) +{ + unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2); + + if (enable) + vip_control2 |= VIP_CONTROL2_LOOPBACK_ENABLE; + else + vip_control2 &= ~VIP_CONTROL2_LOOPBACK_ENABLE; + + WRITE_VIP32(VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_genlock + * + * This routine configures genlock functionality. + *---------------------------------------------------------------------------*/ + +int +vip_configure_genlock(VIPGENLOCKBUFFER * buffer) +{ + unsigned long vip_control1, vip_control2; + unsigned long unlock, genlk_ctl; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + unlock = READ_REG32(DC3_UNLOCK); + genlk_ctl = READ_REG32(DC3_GENLK_CTL); + vip_control1 = READ_VIP32(VIP_CONTROL1); + vip_control2 = READ_VIP32(VIP_CONTROL2); + + /* UPDATE VIDEO DETECTION */ + /* These flags are used to indicate the ways in which the VIP signal */ + /* can be considered 'lost'. */ + + vip_control1 &= ~VIP_CONTROL1_VDE_FF_MASK; + vip_control2 &= ~(VIP_CONTROL2_FIELD2VG_MASK | VIP_CONTROL2_SYNC2VG_MASK); + vip_control1 |= buffer->vip_signal_loss; + + /* UPDATE FIELD AND VSYNC INFORMATION */ + /* These flags control how and when the even/odd field and Vsync */ + /* information is communicated to the VG. */ + + vip_control2 |= buffer->field_to_vg; + vip_control2 |= buffer->vsync_to_vg; + + /* ENABLE OR DISABLE GENLOCK TIMEOUT */ + /* Enabling genlock timeout allows the VG to revert to its own sync */ + /* timings when the VIP input is lost. Note that the VIP will not */ + /* know the signal is lost unless the appropriate error detection */ + /* flags have been enabled inside vip_initialize. */ + + if (buffer->enable_timeout) + genlk_ctl |= DC3_GC_GENLOCK_TO_ENABLE; + else + genlk_ctl &= ~DC3_GC_GENLOCK_TO_ENABLE; + + genlk_ctl &= ~DC3_GC_GENLOCK_SKEW_MASK; + genlk_ctl |= buffer->genlock_skew & DC3_GC_GENLOCK_SKEW_MASK; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_GENLK_CTL, genlk_ctl); + WRITE_VIP32(VIP_CONTROL1, vip_control1); + WRITE_VIP32(VIP_CONTROL2, vip_control2); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_genlock_enable + * + * This routine enables/disables genlock inside the VG. + *--------------------------------------------------------------------------*/ + +int +vip_set_genlock_enable(int enable) +{ + unsigned long unlock, temp; + + unlock = READ_REG32(DC3_UNLOCK); + temp = READ_REG32(DC3_GENLK_CTL); + + if (enable) + temp |= DC3_GC_GENLOCK_ENABLE; + else + temp &= ~DC3_GC_GENLOCK_ENABLE; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_GENLK_CTL, temp); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_power_characteristics + * + * This routine takes a VIPPOWERBUFFER structure, and selectively sets the + * GeodeLink power and/or Vip clock power states. + *--------------------------------------------------------------------------*/ + +int +vip_set_power_characteristics(VIPPOWERBUFFER * buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + q_word.low = q_word.high = 0; + + /* ENABLE GEODELINK CLOCK GATING */ + + if (buffer->glink_clock_mode) + q_word.low |= VIP_MSR_POWER_GLINK; + + /* ENABLE VIP CLOCK GATING */ + + if (buffer->vip_clock_mode) + q_word.low |= VIP_MSR_POWER_CLOCK; + + /* WRITE THE NEW VALUE */ + + msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_priority_characteristics + * + * This routine programs the VIP GeodeLink priority characteristics + *--------------------------------------------------------------------------*/ + +int +vip_set_priority_characteristics(VIPPRIORITYBUFFER * buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + q_word.low = q_word.high = 0; + + q_word.low |= (buffer->secondary << + VIP_MSR_MCR_SECOND_PRIORITY_SHIFT) & VIP_MSR_MCR_SECOND_PRIORITY_MASK; + q_word.low |= (buffer->primary << + VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT) & + VIP_MSR_MCR_PRIMARY_PRIORITY_MASK; + q_word.low |= (buffer->pid << VIP_MSR_MCR_PID_SHIFT) & + VIP_MSR_MCR_PID_MASK; + + msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_debug_characteristics + * + * This routine configures the debug data that is exposed over the diag bus. + *--------------------------------------------------------------------------*/ + +int +vip_set_debug_characteristics(VIPDEBUGBUFFER * buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + q_word.low = q_word.high = 0; + + q_word.high |= (buffer->bist << VIP_MSR_DIAG_BIST_SHIFT) & + VIP_MSR_DIAG_BIST_WMASK; + q_word.low |= (buffer->enable_upper ? + VIP_MSR_DIAG_MSB_ENABLE : 0x00000000); + q_word.low |= (buffer->select_upper << VIP_MSR_DIAG_SEL_UPPER_SHIFT) & + VIP_MSR_DIAG_SEL_UPPER_MASK; + q_word.low |= (buffer->enable_lower ? + VIP_MSR_DIAG_LSB_ENABLE : 0x00000000); + q_word.low |= (buffer->select_lower << VIP_MSR_DIAG_SEL_LOWER_SHIFT) & + VIP_MSR_DIAG_SEL_LOWER_MASK; + + msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, &q_word); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_pages + * + * This routine sets the number of pages, and their offset from each other. + *--------------------------------------------------------------------------*/ + +int +vip_configure_pages(int page_count, unsigned long page_offset) +{ + unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2); + + /* SET THE NEW PAGE COUNT */ + + vip_control2 &= ~VIP_CONTROL2_PAGECNT_MASK; + vip_control2 |= (page_count << VIP_CONTROL2_PAGECNT_SHIFT) & + VIP_CONTROL2_PAGECNT_MASK; + + /* WRITE THE PAGE OFFSET */ + + WRITE_VIP32(VIP_CONTROL2, vip_control2); + WRITE_VIP32(VIP_PAGE_OFFSET, page_offset); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_interrupt_line + * + * This routine sets the line at which a line interrupt should be generated. + *--------------------------------------------------------------------------*/ + +int +vip_set_interrupt_line(int line) +{ + WRITE_VIP32(VIP_CURRENT_TARGET, + (line << VIP_CTARGET_TLINE_SHIFT) & VIP_CTARGET_TLINE_MASK); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_reset + * + * This routine does a one-shot enable of the VIP hardware. It is useful + * for handling unrecoverable VIP errors. + *--------------------------------------------------------------------------*/ + +int +vip_reset(void) +{ + unsigned long vip_control1, vip_control3; + + /* INVERT THE PAUSE BIT */ + + vip_control1 = READ_VIP32(VIP_CONTROL1); + vip_control3 = READ_VIP32(VIP_CONTROL3); + + WRITE_VIP32(VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET); + WRITE_VIP32(VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET); + WRITE_VIP32(VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_subwindow_enable + * + * This routine turns on SubWindow capture, that is a portion of the incoming + * signal is captured rather than the entire frame. The window always has + * the same width as the frame, only the vertical component can be + * modified. + *--------------------------------------------------------------------------*/ + +int +vip_set_subwindow_enable(VIPSUBWINDOWBUFFER * buffer) +{ + unsigned long vip_control2; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + vip_control2 = READ_VIP32(VIP_CONTROL2); + if (buffer->enable) { + /* WRITE THE WINDOW VALUE */ + + WRITE_VIP32(VIP_VERTICAL_START_STOP, ((buffer->stop << + VIP_VSTART_VERTEND_SHIFT) & + VIP_VSTART_VERTEND_MASK) | ((buffer->start << + VIP_VSTART_VERTSTART_SHIFT) & VIP_VSTART_VERTSTART_MASK)); + + /* ENABLE IN THE CONTROL REGISTER */ + + vip_control2 |= VIP_CONTROL2_SWC_ENABLE; + } else { + /* DISABLE SUBWINDOW CAPTURE IN THE CONTROL REGISTER */ + + vip_control2 &= ~VIP_CONTROL2_SWC_ENABLE; + } + WRITE_VIP32(VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_reset_interrupt_state + * + * This routine resets the state of one or more interrupts. + *--------------------------------------------------------------------------*/ + +int +vip_reset_interrupt_state(unsigned long interrupt_mask) +{ + unsigned long temp; + + temp = READ_VIP32(VIP_INTERRUPT); + WRITE_VIP32(VIP_INTERRUPT, temp | (interrupt_mask & VIP_ALL_INTERRUPTS)); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_save_state + * + * This routine saves the necessary register contents in order to restore + * at a later point to the same state. + * + * NOTE: Capture state is forced to OFF in this routine + *--------------------------------------------------------------------------*/ + +int +vip_save_state(VIPSTATEBUFFER * save_buffer) +{ + if (!save_buffer) + return CIM_STATUS_INVALIDPARAMS; + + /* FORCE CAPTURE TO BE DISABLED */ + + vip_set_capture_state(VIP_STOPCAPTURE); + + /* READ AND SAVE THE REGISTER CONTENTS */ + + save_buffer->control1 = READ_VIP32(VIP_CONTROL1); + save_buffer->control2 = READ_VIP32(VIP_CONTROL2); + save_buffer->vip_int = READ_VIP32(VIP_INTERRUPT); + save_buffer->current_target = READ_VIP32(VIP_CURRENT_TARGET); + save_buffer->max_address = READ_VIP32(VIP_MAX_ADDRESS); + save_buffer->taska_evenbase = READ_VIP32(VIP_TASKA_VID_EVEN_BASE); + save_buffer->taska_oddbase = READ_VIP32(VIP_TASKA_VID_ODD_BASE); + save_buffer->taska_vbi_evenbase = READ_VIP32(VIP_TASKA_VBI_EVEN_BASE); + save_buffer->taska_vbi_oddbase = READ_VIP32(VIP_TASKA_VBI_ODD_BASE); + save_buffer->taska_data_pitch = READ_VIP32(VIP_TASKA_VID_PITCH); + save_buffer->control3 = READ_VIP32(VIP_CONTROL3); + save_buffer->taska_v_oddoffset = READ_VIP32(VIP_TASKA_U_OFFSET); + save_buffer->taska_u_oddoffset = READ_VIP32(VIP_TASKA_V_OFFSET); + save_buffer->taskb_evenbase = READ_VIP32(VIP_TASKB_VID_EVEN_BASE); + save_buffer->taskb_oddbase = READ_VIP32(VIP_TASKB_VID_ODD_BASE); + save_buffer->taskb_vbi_evenbase = READ_VIP32(VIP_TASKB_VBI_EVEN_BASE); + save_buffer->taskb_vbi_oddbase = READ_VIP32(VIP_TASKB_VBI_ODD_BASE); + save_buffer->taskb_pitch = READ_VIP32(VIP_TASKB_VID_PITCH); + save_buffer->taskb_voffset = READ_VIP32(VIP_TASKB_U_OFFSET); + save_buffer->taskb_uoffset = READ_VIP32(VIP_TASKB_V_OFFSET); + save_buffer->msg1_base = READ_VIP32(VIP_ANC_MSG1_BASE); + save_buffer->msg2_base = READ_VIP32(VIP_ANC_MSG2_BASE); + save_buffer->msg_size = READ_VIP32(VIP_ANC_MSG_SIZE); + save_buffer->page_offset = READ_VIP32(VIP_PAGE_OFFSET); + save_buffer->vert_start_stop = READ_VIP32(VIP_VERTICAL_START_STOP); + save_buffer->vsync_err_count = READ_VIP32(VIP_VSYNC_ERR_COUNT); + save_buffer->taska_u_evenoffset = READ_VIP32(VIP_TASKA_U_EVEN_OFFSET); + save_buffer->taska_v_evenoffset = READ_VIP32(VIP_TASKA_V_EVEN_OFFSET); + + /* READ ALL VIP MSRS */ + + msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, + &(save_buffer->msr_config)); + msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_SMI, + &(save_buffer->msr_smi)); + msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, + &(save_buffer->msr_pm)); + msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, + &(save_buffer->msr_diag)); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_restore_state + * + * This routine restores the state of the vip registers - which were + * previously saved using vip_save_state. + *--------------------------------------------------------------------------*/ + +int +vip_restore_state(VIPSTATEBUFFER * restore_buffer) +{ + if (!restore_buffer) + return CIM_STATUS_OK; + + /* RESTORE THE REGISTERS */ + + WRITE_VIP32(VIP_CURRENT_TARGET, restore_buffer->current_target); + WRITE_VIP32(VIP_MAX_ADDRESS, restore_buffer->max_address); + WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, restore_buffer->taska_evenbase); + WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, restore_buffer->taska_oddbase); + WRITE_VIP32(VIP_TASKA_VBI_EVEN_BASE, restore_buffer->taska_vbi_evenbase); + WRITE_VIP32(VIP_TASKA_VBI_ODD_BASE, restore_buffer->taska_vbi_oddbase); + WRITE_VIP32(VIP_TASKA_VID_PITCH, restore_buffer->taska_data_pitch); + WRITE_VIP32(VIP_CONTROL3, restore_buffer->control3); + WRITE_VIP32(VIP_TASKA_U_OFFSET, restore_buffer->taska_v_oddoffset); + WRITE_VIP32(VIP_TASKA_V_OFFSET, restore_buffer->taska_u_oddoffset); + WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, restore_buffer->taskb_evenbase); + WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, restore_buffer->taskb_oddbase); + WRITE_VIP32(VIP_TASKB_VBI_EVEN_BASE, restore_buffer->taskb_vbi_evenbase); + WRITE_VIP32(VIP_TASKB_VBI_ODD_BASE, restore_buffer->taskb_vbi_oddbase); + WRITE_VIP32(VIP_TASKB_VID_PITCH, restore_buffer->taskb_pitch); + WRITE_VIP32(VIP_TASKB_U_OFFSET, restore_buffer->taskb_voffset); + WRITE_VIP32(VIP_TASKB_V_OFFSET, restore_buffer->taskb_uoffset); + WRITE_VIP32(VIP_ANC_MSG1_BASE, restore_buffer->msg1_base); + WRITE_VIP32(VIP_ANC_MSG2_BASE, restore_buffer->msg2_base); + WRITE_VIP32(VIP_ANC_MSG_SIZE, restore_buffer->msg_size); + WRITE_VIP32(VIP_PAGE_OFFSET, restore_buffer->page_offset); + WRITE_VIP32(VIP_VERTICAL_START_STOP, restore_buffer->vert_start_stop); + WRITE_VIP32(VIP_VSYNC_ERR_COUNT, restore_buffer->vsync_err_count); + WRITE_VIP32(VIP_TASKA_U_EVEN_OFFSET, restore_buffer->taska_u_evenoffset); + WRITE_VIP32(VIP_TASKA_V_EVEN_OFFSET, restore_buffer->taska_v_evenoffset); + + /* RESTORE THE VIP MSRS */ + + msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, + &(restore_buffer->msr_config)); + msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_SMI, + &(restore_buffer->msr_smi)); + msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, + &(restore_buffer->msr_pm)); + msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, + &(restore_buffer->msr_diag)); + + /* RESTORE THE CONTROL WORDS LAST */ + + WRITE_VIP32(VIP_CONTROL1, restore_buffer->control1); + WRITE_VIP32(VIP_CONTROL2, restore_buffer->control2); + WRITE_VIP32(VIP_CONTROL3, restore_buffer->control3); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_interrupt_state + * + * This routine returns the current interrupt state of the system. The + * rv can be tested with the following flags to determine if the appropriate + * event has occured. + *--------------------------------------------------------------------------*/ + +unsigned long +vip_get_interrupt_state(void) +{ + unsigned long interrupt_mask = READ_VIP32(VIP_INTERRUPT); + + return (~(interrupt_mask << 16) & interrupt_mask & VIP_ALL_INTERRUPTS); +} + +/*--------------------------------------------------------------------------- + * vip_test_genlock_active + * + * This routine reads the live status of the genlock connection between the + * VIP and VG blocks. + *--------------------------------------------------------------------------*/ + +int +vip_test_genlock_active(void) +{ + if (READ_REG32(DC3_GENLK_CTL) & DC3_GC_GENLK_ACTIVE) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * vip_test_signal_status + * + * This routine reads the live signal status coming into the VIP block. + *--------------------------------------------------------------------------*/ + +int +vip_test_signal_status(void) +{ + if (READ_REG32(DC3_GENLK_CTL) & DC3_GC_VIP_VID_OK) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * vip_get_current_field + * + * This routine returns the current field being received. + *--------------------------------------------------------------------------*/ + +unsigned long +vip_get_current_field(void) +{ + if (READ_VIP32(VIP_STATUS) & VIP_STATUS_FIELD) + return VIP_EVEN_FIELD; + + return VIP_ODD_FIELD; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * CIMARRON VIP READ ROUTINES + * These routines are included for use in diagnostics or when debugging. They + * can be optionally excluded from a project. + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +#if CIMARRON_INCLUDE_VIP_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * vip_get_current_mode + * + * This routine reads the current VIP operating mode. + *--------------------------------------------------------------------------*/ + +int +vip_get_current_mode(VIPSETMODEBUFFER * buffer) +{ + unsigned long vip_control1, vip_control2, vip_control3; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 = READ_VIP32(VIP_CONTROL1); + vip_control2 = READ_VIP32(VIP_CONTROL2); + vip_control3 = READ_VIP32(VIP_CONTROL3); + + /* READ CURRENT OPERATING MODE AND ENABLES */ + + buffer->stream_enables = vip_control1 & VIP_ENABLE_ALL; + buffer->operating_mode = vip_control1 & VIP_CONTROL1_MODE_MASK; + + /* READ CURRENT PLANAR CAPTURE SETTINGS */ + + buffer->flags = 0; + buffer->planar_capture = 0; + if (vip_control1 & VIP_CONTROL1_PLANAR) { + buffer->flags |= VIP_MODEFLAG_PLANARCAPTURE; + if (vip_control1 & VIP_CONTROL1_DISABLE_DECIMATION) { + if (vip_control3 & VIP_CONTROL3_DECIMATE_EVEN) + buffer->planar_capture = VIP_420CAPTURE_ALTERNATINGFIELDS; + else + buffer->planar_capture = VIP_420CAPTURE_EVERYLINE; + } else + buffer->planar_capture = VIP_420CAPTURE_ALTERNATINGLINES; + } + + /* READ MISCELLANEOUS FLAGS */ + + if (vip_control1 & VIP_CONTROL1_NON_INTERLACED) + buffer->flags |= VIP_MODEFLAG_PROGRESSIVE; + if (vip_control3 & VIP_CONTROL3_BASE_UPDATE) + buffer->flags |= VIP_MODEFLAG_TOGGLEEACHFIELD; + if (vip_control2 & VIP_CONTROL2_INVERT_POLARITY) + buffer->flags |= VIP_MODEFLAG_INVERTPOLARITY; + if (vip_control1 & VIP_CONTROL1_MSG_STRM_CTRL) + buffer->flags |= VIP_MODEFLAG_FLIPMESSAGEWHENFULL; + if (vip_control2 & VIP_CONTROL2_REPEAT_ENABLE) + buffer->flags |= VIP_MODEFLAG_ENABLEREPEATFLAG; + if (vip_control3 & VIP_CONTROL3_TASK_POLARITY) + buffer->flags |= VIP_MODEFLAG_INVERTTASKPOLARITY; + if (vip_control1 & VIP_CONTROL1_DISABLE_ZERO_DETECT) + buffer->flags |= VIP_MODEFLAG_DISABLEZERODETECT; + if (vip_control2 & VIP_CONTROL2_ANC10) + buffer->flags |= VIP_MODEFLAG_10BITANCILLARY; + + /* READ THE CURRENT VIP 601 SETTINGS */ + + vip_get_601_configuration(&buffer->vip601_settings); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_601_configuration + * + * This routine returns the current 601 configuration information. + *--------------------------------------------------------------------------*/ + +int +vip_get_601_configuration(VIP_601PARAMS * buffer) +{ + unsigned long vip_control3, vip_control1; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 = READ_VIP32(VIP_CONTROL3); + vip_control3 = READ_VIP32(VIP_CONTROL3); + + buffer->flags = 0; + if (vip_control3 & VIP_CONTROL3_VSYNC_POLARITY) + buffer->flags |= VIP_MODEFLAG_VSYNCACTIVEHIGH; + if (vip_control3 & VIP_CONTROL3_HSYNC_POLARITY) + buffer->flags |= VIP_MODEFLAG_HSYNCACTIVEHIGH; + + buffer->horz_start = READ_VIP32(VIP_601_HORZ_START); + buffer->vbi_start = READ_VIP32(VIP_601_VBI_START); + buffer->vbi_height = READ_VIP32(VIP_601_VBI_END) - buffer->vbi_start + 1; + buffer->vert_start_even = READ_VIP32(VIP_601_EVEN_START_STOP) & 0xFFFF; + buffer->even_height = (READ_VIP32(VIP_601_EVEN_START_STOP) >> 16) - + buffer->vert_start_even + 1; + buffer->vert_start_odd = READ_VIP32(VIP_601_ODD_START_STOP) & 0xFFFF; + buffer->odd_height = (READ_VIP32(VIP_601_ODD_START_STOP) >> 16) - + buffer->vert_start_odd + 1; + buffer->odd_detect_start = READ_VIP32(VIP_ODD_FIELD_DETECT) & 0xFFFF; + buffer->odd_detect_end = READ_VIP32(VIP_ODD_FIELD_DETECT) >> 16; + + /* SPECIAL CASE FOR HORIZONTAL DATA + * 601 horizontal parameters are based on the number of clocks and not + * the number of pixels. + */ + + if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601) + buffer->width = (READ_VIP32(VIP_601_HORZ_END) - + buffer->horz_start - 3) >> 1; + else + buffer->width = (READ_VIP32(VIP_601_HORZ_END) - + buffer->horz_start - 3); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_buffer_configuration + * + * This routine reads the current buffer configuration for Task A, Task B, + * ancillary or message data. The current_buffer member indicates which + * array index should hold the new values for Task A or Task B data. + *--------------------------------------------------------------------------*/ + +int +vip_get_buffer_configuration(int buffer_type, VIPINPUTBUFFER * buffer) +{ + unsigned long cur_buffer = buffer->current_buffer; + VIPINPUTBUFFER_ADDR *offsets; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + if (buffer_type == VIP_BUFFER_A) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* READ VIDEO PITCH */ + + offsets->y_pitch = READ_VIP32(VIP_TASKA_VID_PITCH) & 0xFFFF; + offsets->uv_pitch = READ_VIP32(VIP_TASKA_VID_PITCH) >> 16; + + /* READ BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) { + offsets->even_base[cur_buffer] = + READ_VIP32(VIP_TASKA_VID_ODD_BASE); + offsets->odd_base[cur_buffer] = + READ_VIP32(VIP_TASKA_VID_EVEN_BASE); + + if (buffer->flags & VIP_INPUTFLAG_VBI) { + offsets->vbi_even_base = READ_VIP32(VIP_TASKA_VBI_ODD_BASE); + offsets->vbi_odd_base = READ_VIP32(VIP_TASKA_VBI_EVEN_BASE); + } + } else { + offsets->even_base[cur_buffer] = + READ_VIP32(VIP_TASKA_VID_EVEN_BASE); + offsets->odd_base[cur_buffer] = + READ_VIP32(VIP_TASKA_VID_ODD_BASE); + + if (buffer->flags & VIP_INPUTFLAG_VBI) { + offsets->vbi_even_base = READ_VIP32(VIP_TASKA_VBI_EVEN_BASE); + offsets->vbi_odd_base = READ_VIP32(VIP_TASKA_VBI_ODD_BASE); + } + } + + /* READ 4:2:0 OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_PLANAR) { + offsets->odd_uoffset = READ_VIP32(VIP_TASKA_U_OFFSET); + offsets->odd_voffset = READ_VIP32(VIP_TASKA_V_OFFSET); + offsets->even_uoffset = READ_VIP32(VIP_TASKA_U_EVEN_OFFSET); + offsets->even_voffset = READ_VIP32(VIP_TASKA_V_EVEN_OFFSET); + } + } else if (buffer_type == VIP_BUFFER_B) { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* READ VIDEO PITCH */ + + offsets->y_pitch = READ_VIP32(VIP_TASKB_VID_PITCH) & 0xFFFF; + offsets->uv_pitch = READ_VIP32(VIP_TASKB_VID_PITCH) >> 16; + + /* READ BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) { + offsets->even_base[cur_buffer] = + READ_VIP32(VIP_TASKB_VID_ODD_BASE); + offsets->odd_base[cur_buffer] = + READ_VIP32(VIP_TASKB_VID_EVEN_BASE); + + if (buffer->flags & VIP_INPUTFLAG_VBI) { + offsets->vbi_even_base = READ_VIP32(VIP_TASKB_VBI_ODD_BASE); + offsets->vbi_odd_base = READ_VIP32(VIP_TASKB_VBI_EVEN_BASE); + } + } else { + offsets->even_base[cur_buffer] = + READ_VIP32(VIP_TASKB_VID_EVEN_BASE); + offsets->odd_base[cur_buffer] = + READ_VIP32(VIP_TASKB_VID_ODD_BASE); + + if (buffer->flags & VIP_INPUTFLAG_VBI) { + offsets->vbi_even_base = READ_VIP32(VIP_TASKB_VBI_EVEN_BASE); + offsets->vbi_odd_base = READ_VIP32(VIP_TASKB_VBI_ODD_BASE); + } + } + + /* READ 4:2:0 OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_PLANAR) { + offsets->odd_uoffset = READ_VIP32(VIP_TASKB_U_OFFSET); + offsets->odd_voffset = READ_VIP32(VIP_TASKB_V_OFFSET); + } + } else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG) { + buffer->ancillaryData.msg1_base = READ_VIP32(VIP_ANC_MSG1_BASE); + buffer->ancillaryData.msg2_base = READ_VIP32(VIP_ANC_MSG2_BASE); + buffer->ancillaryData.msg_size = READ_VIP32(VIP_ANC_MSG_SIZE); + } else { + return CIM_STATUS_INVALIDPARAMS; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_genlock_configuration + * + * This routine reads the current genlock configuration. + *--------------------------------------------------------------------------*/ + +int +vip_get_genlock_configuration(VIPGENLOCKBUFFER * buffer) +{ + unsigned long vip_control1, vip_control2; + unsigned long genlk_ctl; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + genlk_ctl = READ_REG32(DC3_GENLK_CTL); + vip_control1 = READ_VIP32(VIP_CONTROL1); + vip_control2 = READ_VIP32(VIP_CONTROL2); + + /* READ ERROR DETECTION, CURRENT FIELD AND CURRENT VSYNC + * These flags are used to indicate the ways in which the VIP signal can + * be considered 'lost'. + */ + + buffer->vip_signal_loss = vip_control1 & VIP_CONTROL1_VDE_FF_MASK; + buffer->field_to_vg = vip_control2 & VIP_CONTROL2_FIELD2VG_MASK; + buffer->vsync_to_vg = vip_control2 & VIP_CONTROL2_SYNC2VG_MASK; + + /* GENLOCK TIMEOUT ENABLE */ + + buffer->enable_timeout = 0; + if (genlk_ctl & DC3_GC_GENLOCK_TO_ENABLE) + buffer->enable_timeout = 1; + + /* GENLOCK SKEW */ + + buffer->genlock_skew = genlk_ctl & DC3_GC_GENLOCK_SKEW_MASK; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_genlock_enable + * + * This routine returns the current enable status of genlock in the VG. + *--------------------------------------------------------------------------*/ + +int +vip_get_genlock_enable(void) +{ + if (READ_REG32(DC3_GENLK_CTL) & DC3_GC_GENLOCK_ENABLE) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * vip_is_buffer_update_latched + * + * This routine indicates whether changes to the VIP offsets have been + * latched by the hardware. + *--------------------------------------------------------------------------*/ + +int +vip_is_buffer_update_latched(void) +{ + return (!(READ_VIP32(VIP_STATUS) & VIP_STATUS_BASEREG_NOTUPDT)); +} + +/*--------------------------------------------------------------------------- + * vip_get_capture_state + * + * This routine reads the current capture status of the VIP hardware. + *--------------------------------------------------------------------------*/ + +unsigned long +vip_get_capture_state(void) +{ + return ((READ_VIP32(VIP_CONTROL1) & VIP_CONTROL1_RUNMODE_MASK) >> + VIP_CONTROL1_RUNMODE_SHIFT); +} + +/*--------------------------------------------------------------------------- + * vip_get_current_line + * + * This routine returns the current line that is being processed. + *--------------------------------------------------------------------------*/ + +unsigned long +vip_get_current_line(void) +{ + return (READ_VIP32(VIP_CURRENT_TARGET) & VIP_CTARGET_CLINE_MASK); +} + +/*--------------------------------------------------------------------------- + * vip_read_fifo + * + * This routine reads from the specified fifo address. As the fifo access + * enable should be disabled when running in normal vip mode, this routine + * enables and disables access around the read. + * DIAGNOSTIC USE ONLY + *--------------------------------------------------------------------------*/ + +unsigned long +vip_read_fifo(unsigned long dwFifoAddress) +{ + unsigned long fifo_data; + + /* ENABLE FIFO ACCESS */ + + vip_enable_fifo_access(1); + + /* NOW READ THE DATA */ + + WRITE_VIP32(VIP_FIFO_ADDRESS, dwFifoAddress); + fifo_data = READ_VIP32(VIP_FIFO_DATA); + + /* DISABLE FIFO ACCESS */ + + vip_enable_fifo_access(0); + + return fifo_data; +} + +/*--------------------------------------------------------------------------- + * vip_write_fifo + * + * SYNOPSIS: + * This routine writes to the specified fifo address. As the fifo access + * enable should be disabled when running in normal vip mode, this routine + * enables and disables access around the write. + * DIAGNOSTIC USE ONLY + *--------------------------------------------------------------------------*/ + +int +vip_write_fifo(unsigned long dwFifoAddress, unsigned long dwFifoData) +{ + /* ENABLE FIFO ACCESS */ + + vip_enable_fifo_access(1); + + /* WRITE THE FIFO DATA */ + + WRITE_VIP32(VIP_FIFO_ADDRESS, dwFifoAddress); + WRITE_VIP32(VIP_FIFO_DATA, dwFifoData); + + /* DISABLE FIFO ACCESS */ + + vip_enable_fifo_access(0); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_enable_fifo_access + * + * This routine enables/disables access to the vip fifo. + * DIAGNOSTIC USE ONLY + *--------------------------------------------------------------------------*/ + +int +vip_enable_fifo_access(int enable) +{ + unsigned long cw2; + + cw2 = READ_VIP32(VIP_CONTROL2); + + if (enable) + cw2 |= VIP_CONTROL2_FIFO_ACCESS; + else + cw2 &= ~VIP_CONTROL2_FIFO_ACCESS; + + WRITE_VIP32(VIP_CONTROL2, cw2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_power_characteristics + * + * This routine returns the current VIP clock gating state in a + * VIPPOWERBUFFER. + *--------------------------------------------------------------------------*/ + +int +vip_get_power_characteristics(VIPPOWERBUFFER * buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + /* READ THE EXISTING STATE */ + + msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word); + + /* DECODE THE CLOCK GATING BITS */ + + buffer->glink_clock_mode = (int)(q_word.low & VIP_MSR_POWER_GLINK); + buffer->vip_clock_mode = (int)(q_word.low & VIP_MSR_POWER_CLOCK); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_priority_characteristics + * + * This routine returns the priority characteristics in the supplied + * VIPPRIORITYBUFFER. + *--------------------------------------------------------------------------*/ + +int +vip_get_priority_characteristics(VIPPRIORITYBUFFER * buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + /* READ THE CURRENT STATE */ + + msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word); + + /* DECODE THE PRIORITIES */ + + buffer->secondary = (q_word.low & VIP_MSR_MCR_SECOND_PRIORITY_MASK) >> + VIP_MSR_MCR_SECOND_PRIORITY_SHIFT; + buffer->primary = (q_word.low & VIP_MSR_MCR_PRIMARY_PRIORITY_MASK) >> + VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT; + buffer->pid = q_word.low & VIP_MSR_MCR_PID_MASK; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_get_capability_characteristics + * + * This routine returns revision information for the device. + *--------------------------------------------------------------------------*/ + +int +vip_get_capability_characteristics(VIPCAPABILITIESBUFFER * buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + /* READ THE CURRENT MSR CONTENTS */ + + msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CAP, &q_word); + + /* DECODE THE REVISIONS */ + + buffer->revision_id = (q_word.low & VIP_MSR_CAP_REVID_MASK) >> + VIP_MSR_CAP_REVID_SHIFT; + buffer->device_id = (q_word.low & VIP_MSR_CAP_DEVID_MASK) >> + VIP_MSR_CAP_DEVID_SHIFT; + buffer->n_clock_domains = (q_word.low & VIP_MSR_CAP_NCLK_MASK) >> + VIP_MSR_CAP_NCLK_SHIFT; + buffer->n_smi_registers = (q_word.low & VIP_MSR_CAP_NSMI_MASK) >> + VIP_MSR_CAP_NSMI_SHIFT; + + return CIM_STATUS_OK; +} + +#endif diff --git a/src/cim/cim_vop.c b/src/cim/cim_vop.c new file mode 100644 index 0000000..4b83c03 --- /dev/null +++ b/src/cim/cim_vop.c @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + + /* + * Cimarron VOP configuration routines. + */ + +/*--------------------------------------------------------------------------- + * vop_set_vbi_window + * + * This routine configures the output position and location in memory of + * VBI data. + *--------------------------------------------------------------------------*/ + +int +vop_set_vbi_window(VOPVBIWINDOWBUFFER * buffer) +{ + unsigned long unlock, temp; + unsigned long hstart, hstop; + unsigned long htotal, hsyncstart; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + unlock = READ_REG32(DC3_UNLOCK); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + + /* PROGRAM HORIZONTAL POSITION + * The horizontal position is a little tricky. The counter for the + * horizontal timings is reused for the VBI counter. Consequently, the + * horizontal start and stop values are based off the beginning of active + * data. However, the VG has a quirk. If the counter start position is + * before the beginning of HSync, it applies to the previous line. If + * the counter is after the beginning of HSync it applies to the current + * line. So, for one line the real range can be thought of as + * HSync_start to (HSync_start + htotal - 1). However, the counters + * must be between 0 and htotal - 1. When placing VBI data before the + * start of active data, the horizontal end position will thus be *less* + * than the horizontal start. + */ + + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + hsyncstart = (READ_REG32(DC3_H_SYNC_TIMING) & 0xFFF) + 1; + + if (buffer->horz_from_hsync) { + /* VERIFY THAT THE INPUT IS VALID */ + + if (buffer->horz_start < 0 + || (buffer->horz_start + buffer->vbi_width) > htotal) + return CIM_STATUS_INVALIDPARAMS; + + hstart = buffer->horz_start + hsyncstart; + } else { + /* VERIFY THAT THE INPUT IS VALID */ + + if (buffer->horz_start < ((long)hsyncstart - (long)htotal) || + buffer->horz_start > (long)hsyncstart || + buffer->vbi_width > htotal) { + return CIM_STATUS_INVALIDPARAMS; + } + + hstart = buffer->horz_start + htotal; + } + + hstop = hstart + buffer->vbi_width; + if (hstart > htotal) + hstart -= htotal; + if (hstop > htotal) + hstop -= htotal; + hstart--; + hstop--; + WRITE_REG32(DC3_VBI_HOR, ((hstop << DC3_VBI_HOR_END_SHIFT) & + DC3_VBI_HOR_END_MASK) | (hstart & DC3_VBI_HOR_START_MASK)); + + /* WRITE LINE CAPTURE MASKS */ + + WRITE_REG32(DC3_VBI_LN_ODD, ((buffer->odd_line_offset << + DC3_VBI_ODD_LINE_SHIFT) & DC3_VBI_ODD_LINE_MASK) | + (buffer->odd_line_capture_mask & DC3_VBI_ODD_ENABLE_MASK)); + + WRITE_REG32(DC3_VBI_LN_EVEN, ((buffer->even_line_offset << + DC3_VBI_EVEN_LINE_SHIFT) & DC3_VBI_EVEN_LINE_MASK) | + (buffer->even_line_capture_mask & DC3_VBI_EVEN_ENABLE_MASK)); + + /* PROGRAM SOURCE OFFSETS + * Start with the even offsets. Note that we always enable 16-bit VBI, + * as this is the only way to get VBI data on each VOP clock. + */ + + temp = READ_REG32(DC3_VBI_EVEN_CTL) & ~DC3_VBI_EVEN_CTL_OFFSET_MASK; + temp |= DC3_VBI_EVEN_CTL_ENABLE_16; + if (buffer->enable_upscale) + temp |= DC3_VBI_EVEN_CTL_UPSCALE; + WRITE_REG32(DC3_VBI_EVEN_CTL, temp | + (buffer->even_address_offset & DC3_VBI_EVEN_CTL_OFFSET_MASK)); + + /* ODD OFFSET */ + + temp = READ_REG32(DC3_VBI_ODD_CTL) & ~DC3_VBI_ODD_CTL_OFFSET_MASK; + WRITE_REG32(DC3_VBI_ODD_CTL, temp | + (buffer->odd_address_offset & DC3_VBI_ODD_CTL_OFFSET_MASK)); + + /* PITCH */ + + temp = ((buffer->data_size >> 3) << 16) | ((buffer->data_pitch >> 3) & + 0x0000FFFF); + WRITE_REG32(DC3_VBI_PITCH, temp); + + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vop_enable_vbi_output + * + * This routine enables/disables VBI fetching inside the video generator. + *--------------------------------------------------------------------------*/ + +int +vop_enable_vbi_output(int enable) +{ + unsigned long unlock, temp; + + unlock = READ_REG32(DC3_UNLOCK); + temp = READ_REG32(DC3_VBI_EVEN_CTL); + + if (enable) + temp |= DC3_VBI_ENABLE; + else + temp &= ~DC3_VBI_ENABLE; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_VBI_EVEN_CTL, temp); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vop_set_configuration + * + * This routine is passed a VOP_CONFIGURATION structure that contains all + * the necessary information to configure VOP output. + *--------------------------------------------------------------------------*/ + +int +vop_set_configuration(VOPCONFIGURATIONBUFFER * config) +{ + unsigned long vop_config = 0; + unsigned long alpha, control2; + unsigned long unlock; + unsigned long delta; + Q_WORD msr_value; + int rgb = 0; + + if (!config) + return CIM_STATUS_INVALIDPARAMS; + + unlock = READ_REG32(DC3_UNLOCK); + delta = READ_REG32(DC3_VID_DS_DELTA) & DC3_DS_DELTA_MASK; + + /* OVERRIDE THE OUTPUT SETTINGS TO ENABLE VOP OUTPUT */ + + if (config->mode != VOP_MODE_DISABLED) { + msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + msr_value.low &= ~DF_CONFIG_OUTPUT_MASK; + msr_value.low |= DF_OUTPUT_VOP; + msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); + } + + /* SET THE UNIVERSAL VOP OPTIONS */ + + if (config->flags & VOP_FLAG_SWAP_UV) + vop_config |= VOP_CONFIG_SWAPUV; + if (config->flags & VOP_FLAG_SWAP_VBI) + vop_config |= VOP_CONFIG_SWAPVBI; + + /* SET THE MODE SPECIFIC PARAMETERS */ + + if (config->mode == VOP_MODE_601) { + vop_config |= config->vop601.flags; + vop_config |= config->vop601.vsync_shift; + vop_config |= VOP_CONFIG_ENABLE_601 | VOP_CONFIG_VIP2_0; + + switch (config->vop601.output_mode) { + case VOP_601_YUV_16BIT: + vop_config |= VOP_CONFIG_VIP2_16BIT; + break; + case VOP_601_YUV_4_4_4: + vop_config |= VOP_CONFIG_DISABLE_DECIMATE; + break; + case VOP_601_RGB_8_8_8: + vop_config |= VOP_CONFIG_DISABLE_DECIMATE | VOP_CONFIG_RGBMODE; + rgb = 1; + break; + } + + if (config->vop601.vsync_shift == VOP_VSYNC_LATER_BY_X) { + delta |= (config->vop601.vsync_shift_count & + DC3_601_VSYNC_SHIFT_MASK); + delta |= DC3_601_VSYNC_SHIFT_ENABLE; + } + } else { + if (config->flags & VOP_FLAG_VBI) + vop_config |= VOP_CONFIG_VBI; + if (config->flags & VOP_FLAG_TASK) + vop_config |= VOP_CONFIG_TASK; + if (config->flags & VOP_FLAG_SINGLECHIPCOMPAT) + vop_config |= VOP_CONFIG_SC_COMPATIBLE; + if (config->flags & VOP_FLAG_EXTENDEDSAV) + vop_config |= VOP_CONFIG_EXTENDED_SAV; + + switch (config->mode) { + case VOP_MODE_DISABLED: + vop_config |= VOP_CONFIG_DISABLED; + break; + case VOP_MODE_VIP11: + vop_config |= VOP_CONFIG_VIP1_1; + break; + case VOP_MODE_CCIR656: + vop_config |= VOP_CONFIG_CCIR656; + break; + case VOP_MODE_VIP20_8BIT: + vop_config |= VOP_CONFIG_VIP2_0; + break; + case VOP_MODE_VIP20_16BIT: + vop_config |= VOP_CONFIG_VIP2_0 | VOP_CONFIG_VIP2_16BIT; + break; + } + } + + /* SET THE 4:4:4 TO 4:2:2 DECIMATION ALGORITHM */ + + vop_config |= (config->conversion_mode); + + /* SET THE VSYNC OUT OPTIONS */ + + control2 = READ_VIP32(VIP_CONTROL2) & ~VIP_CONTROL2_SYNC2PIN_MASK; + control2 |= config->vsync_out; + WRITE_VIP32(VIP_CONTROL2, control2); + + /* FORCE THE CORRECT VOP COLOR SPACE */ + /* The output of the mixer will be either RGB or YUV. We must enable */ + /* or disable the VOP CSC based on the desired output format. */ + + alpha = READ_VID32(DF_VID_ALPHA_CONTROL); + if (!(alpha & DF_CSC_GRAPHICS_RGB_TO_YUV)) { + /* RGB OUTPUT FROM THE MIXER */ + + if (!rgb) + alpha |= DF_CSC_VOP_RGB_TO_YUV; + else + alpha &= ~DF_CSC_VOP_RGB_TO_YUV; + } else { + /* YUV OUTPUT FROM THE MIXER */ + /* As there is no YUV->RGB VOP conversion, we simply disable the */ + /* VOP CSC and trust that the user is competent. */ + + alpha &= ~DF_CSC_VOP_RGB_TO_YUV; + } + + /* AND WRITE THE CONFIGURATION */ + + WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha); + WRITE_VOP32(VOP_CONFIGURATION, vop_config); + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_VID_DS_DELTA, delta); + WRITE_REG32(DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vop_save_state + * + * This routine saves the necessary register contents in order to restore + * at a later point to the same state. Note that the capture state is + * forced to OFF in this routine. + *--------------------------------------------------------------------------*/ + +int +vop_save_state(VOPSTATEBUFFER * save_buffer) +{ + if (!save_buffer) + return CIM_STATUS_INVALIDPARAMS; + + save_buffer->config = READ_VOP32(VOP_CONFIGURATION); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vop_restore_state + * + * This routine restores the state of the vop registers - which were + * previously saved using vop_save_state. + *--------------------------------------------------------------------------*/ + +int +vop_restore_state(VOPSTATEBUFFER * restore_buffer) +{ + if (!restore_buffer) + return CIM_STATUS_INVALIDPARAMS; + + WRITE_VOP32(VOP_CONFIGURATION, restore_buffer->config); + + return CIM_STATUS_OK; +} + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * CIMARRON VOP READ ROUTINES + * These routines are included for use in diagnostics or when debugging. They + * can be optionally excluded from a project. + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +#if CIMARRON_INCLUDE_VOP_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * vop_get_current_mode + * + * This routine reads the current VIP operating mode and stores it in the + * passed VOP_CONFIGURATION structure. + *--------------------------------------------------------------------------*/ + +int +vop_get_current_mode(VOPCONFIGURATIONBUFFER * config) +{ + unsigned long vop_config = 0; + unsigned long alpha; + + if (!config) + return CIM_STATUS_INVALIDPARAMS; + + vop_config = READ_VOP32(VOP_CONFIGURATION); + alpha = READ_VID32(DF_VID_ALPHA_CONTROL); + + /* READ THE CURRENT MODE */ + + switch (vop_config & VOP_CONFIG_MODE_MASK) { + case VOP_CONFIG_DISABLED: + config->mode = VOP_MODE_DISABLED; + break; + case VOP_CONFIG_VIP1_1: + config->mode = VOP_MODE_VIP11; + break; + case VOP_CONFIG_CCIR656: + config->mode = VOP_MODE_CCIR656; + break; + case VOP_CONFIG_VIP2_0: + + if (vop_config & VOP_CONFIG_ENABLE_601) + config->mode = VOP_MODE_601; + else if (vop_config & VOP_CONFIG_VIP2_16BIT) + config->mode = VOP_MODE_VIP20_16BIT; + else + config->mode = VOP_MODE_VIP20_8BIT; + break; + } + + /* READ 601 SETTINGS */ + + config->vop601.flags = vop_config & (VOP_CONFIG_INVERT_DISPE | + VOP_CONFIG_INVERT_HSYNC | VOP_CONFIG_INVERT_VSYNC); + + config->vop601.vsync_shift = vop_config & VOP_CONFIG_VSYNC_MASK; + config->vop601.vsync_shift_count = + READ_REG32(DC3_VID_DS_DELTA) & DC3_601_VSYNC_SHIFT_MASK; + + if ((alpha & DF_CSC_GRAPHICS_RGB_TO_YUV) || + (alpha & DF_CSC_VOP_RGB_TO_YUV)) { + /* YUV OUTPUT */ + + if (vop_config & VOP_CONFIG_DISABLE_DECIMATE) + config->vop601.output_mode = VOP_601_YUV_4_4_4; + else if (vop_config & VOP_CONFIG_VIP2_16BIT) + config->vop601.output_mode = VOP_601_YUV_16BIT; + else + config->vop601.output_mode = VOP_601_YUV_8BIT; + } else { + config->vop601.output_mode = VOP_601_RGB_8_8_8; + } + + config->flags = 0; + + /* READ THE UNIVERSAL VOP OPTIONS */ + + if (vop_config & VOP_CONFIG_SWAPUV) + config->flags |= VOP_FLAG_SWAP_UV; + if (vop_config & VOP_CONFIG_SWAPVBI) + config->flags |= VOP_FLAG_SWAP_VBI; + if (vop_config & VOP_CONFIG_VBI) + config->flags |= VOP_FLAG_VBI; + if (vop_config & VOP_CONFIG_TASK) + config->flags |= VOP_FLAG_TASK; + if (vop_config & VOP_CONFIG_SC_COMPATIBLE) + config->flags |= VOP_FLAG_SINGLECHIPCOMPAT; + if (vop_config & VOP_CONFIG_EXTENDED_SAV) + config->flags |= VOP_FLAG_EXTENDEDSAV; + + config->conversion_mode = vop_config & VOP_CONFIG_422_MASK; + + config->vsync_out = READ_VIP32(VIP_CONTROL2) & VIP_CONTROL2_SYNC2PIN_MASK; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vop_get_vbi_window + * + * This routine reads the current VBI configuration for VOP output. + *--------------------------------------------------------------------------*/ + +int +vop_get_vbi_configuration(VOPVBIWINDOWBUFFER * buffer) +{ + unsigned long temp; + unsigned long hstart, hstop; + unsigned long htotal, hsyncstart; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; + hsyncstart = (READ_REG32(DC3_H_SYNC_TIMING) & 0xFFF) + 1; + + /* DECODE HORIZONTAL POSITION */ + /* This is done according to the requested horizontal origin */ + + temp = READ_REG32(DC3_VBI_HOR); + hstart = (temp & DC3_VBI_HOR_START_MASK) + 1; + hstop = ((temp & DC3_VBI_HOR_END_MASK) >> DC3_VBI_HOR_END_SHIFT) + 1; + if (buffer->horz_from_hsync) { + buffer->horz_start = hstart + htotal - hsyncstart; + if (buffer->horz_start >= (long)htotal) + buffer->horz_start -= htotal; + } else { + if (hstart > hsyncstart) + buffer->horz_start = (long)hstart - (long)htotal; + else + buffer->horz_start = hstart; + } + + if (hstop > hstart) + buffer->vbi_width = hstop - hstart; + else + buffer->vbi_width = (htotal - hstart) + hstop; + + /* READ LINE MASKS */ + + temp = READ_REG32(DC3_VBI_LN_ODD); + buffer->odd_line_offset = (temp & DC3_VBI_ODD_LINE_MASK) >> + DC3_VBI_ODD_LINE_SHIFT; + buffer->odd_line_capture_mask = (temp & DC3_VBI_ODD_ENABLE_MASK); + + temp = READ_REG32(DC3_VBI_LN_EVEN); + buffer->even_line_offset = (temp & DC3_VBI_EVEN_LINE_MASK) >> + DC3_VBI_EVEN_LINE_SHIFT; + buffer->even_line_capture_mask = (temp & DC3_VBI_EVEN_ENABLE_MASK); + + /* READ VBI UPSCALE SETTINGS */ + + buffer->enable_upscale = 0; + temp = READ_REG32(DC3_VBI_EVEN_CTL); + if (temp & DC3_VBI_EVEN_CTL_UPSCALE) + buffer->enable_upscale = 1; + + /* READ SOURCE OFFSETS */ + + buffer->even_address_offset = temp & DC3_VBI_EVEN_CTL_OFFSET_MASK; + buffer->odd_address_offset = + READ_REG32(DC3_VBI_ODD_CTL) & DC3_VBI_ODD_CTL_OFFSET_MASK; + + /* PITCH AND SIZE */ + + temp = READ_REG32(DC3_VBI_PITCH); + buffer->data_size = (temp >> 16) << 3; + buffer->data_pitch = (temp & 0xFFFF); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vop_get_vbi_enable + * + * This routine reads the current enable status of VBI output. + *--------------------------------------------------------------------------*/ + +int +vop_get_vbi_enable(void) +{ + if (READ_REG32(DC3_VBI_EVEN_CTL) & DC3_VBI_ENABLE) + return 1; + + return 0; +} + +/*--------------------------------------------------------------------------- + * vop_get_crc + * + * This routine returns a CRC of the current VOP data + --------------------------------------------------------------------------*/ + +unsigned long +vop_get_crc(void) +{ + unsigned long crc; + unsigned long config = READ_VOP32(VOP_CONFIGURATION); + unsigned long timeout = 1000; + + if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) + return 0xFFFFFFFF; + + /* RESET CRC */ + + WRITE_VOP32(VOP_CONFIGURATION, config & ~VOP_CONFIG_ENABLE_SIGNATURE); + + /* WAIT FOR THE RESET TO BE LATCHED */ + + while ((READ_VOP32(VOP_SIGNATURE) != 0x00000001) && timeout) + timeout--; + + WRITE_VOP32(VOP_CONFIGURATION, config | VOP_CONFIG_ENABLE_SIGNATURE); + + /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ + + while (!(READ_VOP32(VOP_CONFIGURATION) & VOP_CONFIG_SIGVAL)) ; + + crc = READ_VOP32(VOP_SIGNATURE); + + return crc; +} + +/*--------------------------------------------------------------------------- + * vop_read_vbi_crc + * + * This routine returns a CRC of the current VBI data + ---------------------------------------------------------------------------*/ + +unsigned long +vop_read_vbi_crc(void) +{ + unsigned long gcfg, unlock, vbi_even; + unsigned long crc; + + if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN) || + !(READ_REG32(DC3_VBI_EVEN_CTL) & DC3_VBI_ENABLE)) { + return 0xFFFFFFFF; + } + + unlock = READ_REG32(DC3_UNLOCK); + gcfg = READ_REG32(DC3_GENERAL_CFG); + vbi_even = READ_REG32(DC3_VBI_EVEN_CTL); + + gcfg |= DC3_GCFG_SGRE | DC3_GCFG_CRC_MODE; + gcfg &= ~(DC3_GCFG_SGFR | DC3_GCFG_SIG_SEL); + vbi_even |= DC3_VBI_EVEN_ENABLE_CRC; + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_VBI_EVEN_CTL, vbi_even); + WRITE_REG32(DC3_GENERAL_CFG, gcfg & ~DC3_GCFG_SIGE); + WRITE_REG32(DC3_GENERAL_CFG, gcfg | DC3_GCFG_SIGE); + + /* WAIT FOR THE CRC TO BE COMPLETED */ + + while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_SIGC)) ; + + /* READ THE COMPLETED CRC */ + + crc = READ_REG32(DC3_PAL_DATA); + + /* RESTORE THE PALETTE SETTINGS */ + + gcfg &= ~DC3_GCFG_SGRE; + WRITE_REG32(DC3_GENERAL_CFG, gcfg); + WRITE_REG32(DC3_UNLOCK, unlock); + + return crc; +} + +#endif diff --git a/src/cim/doc/release.txt b/src/cim/doc/release.txt new file mode 100644 index 0000000..716e8f4 --- /dev/null +++ b/src/cim/doc/release.txt @@ -0,0 +1,48 @@ +Cimarron API Release Notes +Version 02.02.0100 +March 4, 2005 +Developer - + +----------------------------------------------------------------------------- +PRODUCT INFORMATION +----------------------------------------------------------------------------- +Cimarron is a graphics/video support package designed to implement common +functionality for GX3 (Castle). The design of this package is similar to its +predecessor, Durango; many of the Cimarron routines have functional +equivalents in the Durango library. However, Cimarron does not attempt to +maintain legacy by completely preserving the original Durango API. The API +has been restructured to more closely match current hardware. + +----------------------------------------------------------------------------- +INSTALLATION INSTRUCTIONS +----------------------------------------------------------------------------- +NA + +----------------------------------------------------------------------------- +BUILD INSTRUCTIONS +----------------------------------------------------------------------------- +NA + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +NA +----------------------------------------------------------------------------- +UNIT TEST +----------------------------------------------------------------------------- +NA +----------------------------------------------------------------------------- +FILE CHANGES +----------------------------------------------------------------------------- +None +----------------------------------------------------------------------------- +DEFECTS CORRECTED +----------------------------------------------------------------------------- +NA +----------------------------------------------------------------------------- +KNOWN ERRATA +----------------------------------------------------------------------------- +NA +----------------------------------------------------------------------------- +REVISION HISTORY +----------------------------------------------------------------------------- |