summaryrefslogtreecommitdiff
path: root/src/cim
diff options
context:
space:
mode:
authorJordan Crouse <jordan.crouse@amd.com>2006-07-06 14:56:42 -0600
committerJordan Crouse <jordan.crouse@amd.com>2006-07-06 14:56:42 -0600
commitc3ab9f1a60afe1f5e86db1cf2635acda14fae2f5 (patch)
tree00cfb19765f276220eb794553b545e9f67402688 /src/cim
Initial commit of the xf86-video-amd tree
Diffstat (limited to 'src/cim')
-rw-r--r--src/cim/cim_defs.h719
-rw-r--r--src/cim/cim_defs.h.rej45
-rw-r--r--src/cim/cim_df.c2581
-rw-r--r--src/cim/cim_filter.c547
-rw-r--r--src/cim/cim_gp.c3392
-rw-r--r--src/cim/cim_init.c223
-rw-r--r--src/cim/cim_modes.c1905
-rw-r--r--src/cim/cim_msr.c434
-rw-r--r--src/cim/cim_parm.h1284
-rw-r--r--src/cim/cim_regs.h1252
-rw-r--r--src/cim/cim_rtns.h392
-rw-r--r--src/cim/cim_version.h31
-rw-r--r--src/cim/cim_vg.c3711
-rw-r--r--src/cim/cim_vip.c1640
-rw-r--r--src/cim/cim_vop.c604
-rw-r--r--src/cim/doc/release.txt48
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
+-----------------------------------------------------------------------------