diff -urN linux-2.6.6.orig/Makefile linux-2.6.6/Makefile --- linux-2.6.6.orig/Makefile 2004-05-10 03:32:53.000000000 +0100 +++ linux-2.6.6/Makefile 2004-05-10 12:30:51.916578648 +0100 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 6 -EXTRAVERSION = +EXTRAVERSION = -xbox NAME=Zonked Quokka # *DOCUMENTATION* diff -urN linux-2.6.6.orig/arch/i386/Kconfig linux-2.6.6/arch/i386/Kconfig --- linux-2.6.6.orig/arch/i386/Kconfig 2004-05-10 03:32:01.000000000 +0100 +++ linux-2.6.6/arch/i386/Kconfig 2004-05-10 12:30:22.795005800 +0100 @@ -52,6 +52,22 @@ If unsure, choose "PC-compatible" instead. +config X86_XBOX + bool "Microsoft Xbox" + help + This option is needed to make Linux boot on XBox Gaming Systems. + + The XBox can be considered as a standard PC with a Coppermine-based Celeron 733 MHz, + IDE harddrive, DVD, Ethernet, USB and graphics. + + To boot the kernel you need "_romwell", either used as a replacement BIOS (cromwell) + or as a bootloader. + + For more information see http://xbox-linux.sourceforge.net/ + + If you do not specifically need a kernel for XBOX machine, + say N here otherwise the kernel you build will not be bootable. + config X86_VOYAGER bool "Voyager (NCR)" help @@ -521,6 +537,10 @@ If you have a system with several CPUs, you do not need to say Y here: the IO-APIC will be used automatically. +config XBOX_EJECT + bool "XBOX eject fix" + depends on X86_XBOX + config X86_LOCAL_APIC bool depends on !SMP && X86_UP_APIC @@ -1127,7 +1147,7 @@ config MCA bool "MCA support" - depends on !(X86_VISWS || X86_VOYAGER) + depends on !(X86_VISWS || X86_VOYAGER || X86_XBOX) help MicroChannel Architecture is found in some IBM PS/2 machines and laptops. It is a bus system similar to PCI or ISA. See @@ -1314,7 +1334,7 @@ config X86_BIOS_REBOOT bool - depends on !(X86_VISWS || X86_VOYAGER) + depends on !(X86_VISWS || X86_VOYAGER || X86_XBOX) default y config X86_TRAMPOLINE diff -urN linux-2.6.6.orig/arch/i386/Makefile linux-2.6.6/arch/i386/Makefile --- linux-2.6.6.orig/arch/i386/Makefile 2004-05-10 03:32:27.000000000 +0100 +++ linux-2.6.6/arch/i386/Makefile 2004-05-10 12:30:22.814002912 +0100 @@ -65,6 +65,10 @@ # Default subarch .c files mcore-y := mach-default +# Xbox subarch support +mflags-$(CONFIG_X86_XBOX) := -Iinclude/asm-i386/mach-xbox +mcore-$(CONFIG_X86_XBOX) := mach-xbox + # Voyager subarch support mflags-$(CONFIG_X86_VOYAGER) := -Iinclude/asm-i386/mach-voyager mcore-$(CONFIG_X86_VOYAGER) := mach-voyager diff -urN linux-2.6.6.orig/arch/i386/boot/compressed/Makefile linux-2.6.6/arch/i386/boot/compressed/Makefile --- linux-2.6.6.orig/arch/i386/boot/compressed/Makefile 2004-05-10 03:32:54.000000000 +0100 +++ linux-2.6.6/arch/i386/boot/compressed/Makefile 2004-05-10 12:30:22.841998656 +0100 @@ -5,6 +5,17 @@ # targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o + +# +# There is some strange interaction when paging is off, that makes +# newer v1.1+ Xboxen (manufactured August 2002 or later) crash while +# decrompressing the kernel. Compiling the decrompressor without any +# optimization reliably works around this problem. +# +ifeq ($(CONFIG_X86_XBOX),y) +CFLAGS_misc.o := -O0 +endif + EXTRA_AFLAGS := -traditional LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 diff -urN linux-2.6.6.orig/arch/i386/kernel/Makefile linux-2.6.6/arch/i386/kernel/Makefile --- linux-2.6.6.orig/arch/i386/kernel/Makefile 2004-05-10 03:32:02.000000000 +0100 +++ linux-2.6.6/arch/i386/kernel/Makefile 2004-05-10 12:30:22.864995160 +0100 @@ -25,6 +25,7 @@ obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o +obj-$(CONFIG_XBOX_EJECT) += xboxejectfix.o obj-$(CONFIG_MODULES) += module.o obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o diff -urN linux-2.6.6.orig/arch/i386/kernel/xboxejectfix.c linux-2.6.6/arch/i386/kernel/xboxejectfix.c --- linux-2.6.6.orig/arch/i386/kernel/xboxejectfix.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/arch/i386/kernel/xboxejectfix.c 2004-05-10 12:30:22.867994704 +0100 @@ -0,0 +1,147 @@ +/** + * Driver that handles the EXTSMI# interrupt on the xbox. + * Makes it possible to use the eject-button without the xbox rebooting... + * + * smbus-command sequence to prevent reboot from cromwell. + * + * Changelog: + * 2003-01-14 Anders Gustafsson + * initial version + * 2003-02-08 Milosch Meriac + * rewrote debug macros because of compiler errors + * 2003-08-06 Michael Steil + * removed Linux I2C dependency, now compiles + * without I2C in the kernel + * + * Todo: add errorhandling! + * + */ + +#include +#include +#include +#include +#include +#include + +#define IRQ 12 +#define DRIVER_NAME "xboxejectfix" + +/* just some crap */ +static char dev[]=DRIVER_NAME; + +/* External variable from ide-cd.c that specifies whether we simulate drive + locking in software */ +extern volatile int Xbox_simulate_drive_locked; + +#define BASE 0x8000 + +/* Power Management 1 Enable Register */ +#define PM02 (BASE+0x02) + +/* Power Management 1 Control Register */ +#define PM04 (BASE+0x04) + +/* ACPI GP Status Register */ +#define PM20 (BASE+0x20) + +/* ACPI GP Enable Register */ +#define PM22 (BASE+0x22) +# define EXTSMI_EN_MASK 0x0002 + +/* Global SMI Enable Register */ +#define PM2A (BASE+0x2A) + + +static DECLARE_MUTEX(extsmi_sem); +static DECLARE_COMPLETION(extsmi_exited); +static int extsmi_pid=0; + +static irqreturn_t extsmi_interupt(int unused, void *dev_id, struct pt_regs *regs) { + int reason; + + reason=inw(0x8020); + outw(reason,0x8020); /* ack IS THIS NEEDED? */ + if(reason&0x2){ + /* wake up thread */ + up(&extsmi_sem); + } + return 0; +} + +/** + * Process an event. This is run in process-context. + */ +static void extsmi_process(void){ + int reason; + reason=Xbox_SMC_read(SMC_CMD_INTERRUPT_REASON); + + if(reason&TRAYBUTTON_MASK){ /* Tray button! Respond to prevent reboot! */ + Xbox_SMC_write(SMC_CMD_INTERRUPT_RESPOND, SMC_SUBCMD_RESPOND_CONTINUE); + Xbox_SMC_write(0x00, 0x0c); + /* eject unless lock simulation is being used */ + if (!Xbox_simulate_drive_locked) + Xbox_tray_eject(); + } +} + +static int extsmi_thread(void *data){ + daemonize("extsmi"); + reparent_to_init(); + strcpy(current->comm, "xbox_extsmi"); + + do { + extsmi_process(); + down_interruptible(&extsmi_sem); + } while (!signal_pending(current)); + + complete_and_exit(&extsmi_exited, 0); +} + +static int extsmi_init(void){ + int pid; + + if (!machine_is_xbox) { + printk("This machine is no Xbox.\n"); + return -1; + } + printk("Enabling Xbox eject problem workaround.\n"); + + pid = kernel_thread(extsmi_thread, NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (pid < 0) { + return pid; + } + + extsmi_pid = pid; + + /* this shuts a lot of interrupts off! */ + outw(inw(0x80e2)&0xf8c7,0x80e2); + outw(0,0x80ac); + outb(0,0x8025); + outw(EXTSMI_EN_MASK,PM22); /* enable the EXTSMI# interupt! */ + outw(0,PM02); + outb(1,PM04); /* enable sci interrupts! */ + Xbox_SMC_write(SMC_CMD_RESET_ON_EJECT, SMC_SUBCMD_RESET_ON_EJECT_DISABLE); + + /* FIXME! retval! */ + request_irq(IRQ,extsmi_interupt,SA_INTERRUPT|SA_SHIRQ,"xboxejectfix",dev); + return 0; +} + +static void extsmi_exit(void){ + int res; + if (!machine_is_xbox) return; /* can this happen??? */ + free_irq(IRQ,dev); + + /* Kill the thread */ + res = kill_proc(extsmi_pid, SIGTERM, 1); + wait_for_completion(&extsmi_exited); + return; +} + +module_init(extsmi_init); +module_exit(extsmi_exit); + +MODULE_AUTHOR("Anders Gustafsson "); +MODULE_LICENSE("GPL"); diff -urN linux-2.6.6.orig/arch/i386/mach-xbox/Makefile linux-2.6.6/arch/i386/mach-xbox/Makefile --- linux-2.6.6.orig/arch/i386/mach-xbox/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/arch/i386/mach-xbox/Makefile 2004-05-10 12:30:22.869994400 +0100 @@ -0,0 +1,5 @@ +# +# Makefile for the linux kernel. +# + +obj-y := setup.o reboot.o diff -urN linux-2.6.6.orig/arch/i386/mach-xbox/reboot.c linux-2.6.6/arch/i386/mach-xbox/reboot.c --- linux-2.6.6.orig/arch/i386/mach-xbox/reboot.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/arch/i386/mach-xbox/reboot.c 2004-05-10 12:30:22.871994096 +0100 @@ -0,0 +1,51 @@ +/* + * arch/i386/mach-xbox/reboot.c + * Olivier Fauchon + * Anders Gustafsson + * + */ + +#include + +/* we don't use any of those, but dmi_scan.c needs 'em */ +void (*pm_power_off)(void); +int reboot_thru_bios; + +#define XBOX_SMB_IO_BASE 0xC000 +#define XBOX_SMB_HOST_ADDRESS (0x4 + XBOX_SMB_IO_BASE) +#define XBOX_SMB_HOST_COMMAND (0x8 + XBOX_SMB_IO_BASE) +#define XBOX_SMB_HOST_DATA (0x6 + XBOX_SMB_IO_BASE) +#define XBOX_SMB_GLOBAL_ENABLE (0x2 + XBOX_SMB_IO_BASE) + +#define XBOX_PIC_ADDRESS 0x10 + +#define SMC_CMD_POWER 0x02 +#define SMC_SUBCMD_POWER_RESET 0x01 +#define SMC_SUBCMD_POWER_CYCLE 0x40 +#define SMC_SUBCMD_POWER_OFF 0x80 + + +static void xbox_pic_cmd(u8 command) +{ + outw_p(((XBOX_PIC_ADDRESS) << 1), XBOX_SMB_HOST_ADDRESS); + outb_p(SMC_CMD_POWER, XBOX_SMB_HOST_COMMAND); + outw_p(command, XBOX_SMB_HOST_DATA); + outw_p(inw(XBOX_SMB_IO_BASE), XBOX_SMB_IO_BASE); + outb_p(0x0a, XBOX_SMB_GLOBAL_ENABLE); +} + +void machine_restart(char * __unused) +{ + printk(KERN_INFO "Sending POWER_CYCLE to XBOX-PIC.\n"); + xbox_pic_cmd(SMC_SUBCMD_POWER_CYCLE); +} + +void machine_power_off(void) +{ + printk(KERN_INFO "Sending POWER_OFF to XBOX-PIC.\n"); + xbox_pic_cmd(SMC_SUBCMD_POWER_OFF); +} + +void machine_halt(void) +{ +} diff -urN linux-2.6.6.orig/arch/i386/mach-xbox/setup.c linux-2.6.6/arch/i386/mach-xbox/setup.c --- linux-2.6.6.orig/arch/i386/mach-xbox/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/arch/i386/mach-xbox/setup.c 2004-05-10 12:30:22.873993792 +0100 @@ -0,0 +1,84 @@ +/* + * Machine specific setup for xbox + */ + +#include +#include +#include +#include +#include +#include + +/** + * pre_intr_init_hook - initialisation prior to setting up interrupt vectors + * + * Description: + * Perform any necessary interrupt initialisation prior to setting up + * the "ordinary" interrupt call gates. For legacy reasons, the ISA + * interrupts should be initialised here if the machine emulates a PC + * in any way. + **/ +void __init pre_intr_init_hook(void) +{ + init_ISA_irqs(); +} + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL }; + +/** + * intr_init_hook - post gate setup interrupt initialisation + * + * Description: + * Fill in any interrupts that may have been left out by the general + * init_IRQ() routine. interrupts having to do with the machine rather + * than the devices on the I/O bus (like APIC interrupts in intel MP + * systems) are started here. + **/ +void __init intr_init_hook(void) +{ +#ifdef CONFIG_X86_LOCAL_APIC + apic_intr_init(); +#endif + + setup_irq(2, &irq2); +} + +/** + * pre_setup_arch_hook - hook called prior to any setup_arch() execution + * + * Description: + * generally used to activate any machine specific identification + * routines that may be needed before setup_arch() runs. On VISWS + * this is used to get the board revision and type. + **/ +void __init pre_setup_arch_hook(void) +{ +} + +/** + * trap_init_hook - initialise system specific traps + * + * Description: + * Called as the final act of trap_init(). Used in VISWS to initialise + * the various board specific APIC traps. + **/ +void __init trap_init_hook(void) +{ +} + +static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL }; + +/** + * time_init_hook - do any specific initialisations for the system timer. + * + * Description: + * Must plug the system timer interrupt source at HZ into the IRQ listed + * in irq_vectors.h:TIMER_IRQ + **/ +void __init time_init_hook(void) +{ + setup_irq(0, &irq0); +} diff -urN linux-2.6.6.orig/arch/i386/pci/direct.c linux-2.6.6/arch/i386/pci/direct.c --- linux-2.6.6.orig/arch/i386/pci/direct.c 2004-05-10 03:32:26.000000000 +0100 +++ linux-2.6.6/arch/i386/pci/direct.c 2004-05-10 12:30:22.890991208 +0100 @@ -4,6 +4,7 @@ #include #include +#include "mach_pci_blacklist.h" #include "pci.h" /* @@ -20,6 +21,9 @@ if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; + if (mach_pci_is_blacklisted(bus, PCI_SLOT(devfn), PCI_FUNC(devfn))) + return -EINVAL; + spin_lock_irqsave(&pci_config_lock, flags); outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8); diff -urN linux-2.6.6.orig/drivers/i2c/busses/Kconfig linux-2.6.6/drivers/i2c/busses/Kconfig --- linux-2.6.6.orig/drivers/i2c/busses/Kconfig 2004-05-10 03:33:13.000000000 +0100 +++ linux-2.6.6/drivers/i2c/busses/Kconfig 2004-05-10 12:30:22.908988472 +0100 @@ -49,6 +49,10 @@ This driver can also be built as a module. If so, the module will be called i2c-amd756. +config I2C_XBOX + tristate "XBOX I2C" + depends on I2C && EXPERIMENTAL + config I2C_AMD8111 tristate "AMD 8111" depends on I2C && EXPERIMENTAL diff -urN linux-2.6.6.orig/drivers/i2c/busses/Makefile linux-2.6.6/drivers/i2c/busses/Makefile --- linux-2.6.6.orig/drivers/i2c/busses/Makefile 2004-05-10 03:32:00.000000000 +0100 +++ linux-2.6.6/drivers/i2c/busses/Makefile 2004-05-10 12:30:22.915987408 +0100 @@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o +obj-$(CONFIG_I2C_XBOX) += i2c-xbox.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o diff -urN linux-2.6.6.orig/drivers/i2c/busses/i2c-xbox.c linux-2.6.6/drivers/i2c/busses/i2c-xbox.c --- linux-2.6.6.orig/drivers/i2c/busses/i2c-xbox.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/i2c/busses/i2c-xbox.c 2004-05-10 12:30:22.919986800 +0100 @@ -0,0 +1,417 @@ +/* + i2c-xbox.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + + Copyright (c) 1999-2002 Edgar Hucek + + Shamelessly ripped from i2c-xbox.c: + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Supports XBOX, Note: we assume there can only be one device, with one SMBus interface. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* error codes */ +#include /* intr_count */ +#include +#include + + +#define GS_ABRT_STS (1 << 0) +#define GS_COL_STS (1 << 1) +#define GS_PRERR_STS (1 << 2) +#define GS_HST_STS (1 << 3) +#define GS_IRQ_ON (1 << 4) +#define GS_HCYC_STS (1 << 4) +#define GS_TO_STS (1 << 5) +#define GS_SMB_STS (1 << 11) + +#define SMB_GCTL_HOST_START (1 << 3) +#define SMB_GCTL_HOST_INTERRUPT (1 << 4) +#define SMB_GCTL_ABORT (1 << 5) +#define SMB_GCTL_SNOOP (1 << 8) +#define SMB_GCTL_SLAVE_INTERRUPT (1 << 9) +#define SMB_GCTL_ALERT_INTERRUPT (1 << 10) + +#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ + GS_HCYC_STS | GS_TO_STS) + +#define GE_CYC_TYPE_MASK (7) +#define GE_HOST_STC (1 << 3) +#define GE_ABORT (1 << 5) + +#define I2C_HW_SMBUS_XBOX 0x05 +#define SMBGCFG 0x041 /* mh */ +#define SMBBA 0x058 /* mh */ + +struct sd { + const unsigned short vendor; + const unsigned short device; + const unsigned short function; + const char* name; + int amdsetup:1; +}; + +static struct sd supported[] = { + {PCI_VENDOR_ID_NVIDIA, 0x01b4, 1, "nVidia XBOX nForce", 0}, + {0, 0, 0} +}; + +/* XBOX SMBus address offsets */ +#define SMB_ADDR_OFFSET 0x04 +#define SMB_IOSIZE 8 +#define SMB_GLOBAL_STATUS (0x0 + xbox_smba) +#define SMB_GLOBAL_ENABLE (0x2 + xbox_smba) +#define SMB_HOST_ADDRESS (0x4 + xbox_smba) +#define SMB_HOST_DATA (0x6 + xbox_smba) +#define SMB_HOST_COMMAND (0x8 + xbox_smba) + + + + + +/* Other settings */ +#define MAX_TIMEOUT 500 + +/* XBOX constants */ +#define XBOX_QUICK 0x00 +#define XBOX_BYTE 0x01 +#define XBOX_BYTE_DATA 0x02 +#define XBOX_WORD_DATA 0x03 +#define XBOX_PROCESS_CALL 0x04 +#define XBOX_BLOCK_DATA 0x05 + +/* insmod parameters */ + +#ifdef MODULE +static +#else +extern +#endif +int __init i2c_xbox_init(void); +static int __init xbox_cleanup(void); +static int xbox_setup(void); +static s32 xbox_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data); +static void xbox_do_pause(unsigned int amount); +static void xbox_abort(void); +static int xbox_transaction(void); +static u32 xbox_func(struct i2c_adapter *adapter); + +static struct i2c_algorithm smbus_algorithm = { + /* name */ "Non-I2C SMBus adapter", + /* id */ I2C_ALGO_SMBUS, + /* master_xfer */ NULL, + /* smbus_access */ xbox_access, + /* slave;_send */ NULL, + /* slave_rcv */ NULL, + /* algo_control */ NULL, + /* functionality */ xbox_func, +}; + +static struct i2c_adapter xbox_adapter = { + .owner = THIS_MODULE, + .class = I2C_ADAP_CLASS_SMBUS, + .algo = &smbus_algorithm, + .name = "unset", +}; + +static int __initdata xbox_initialized; +static unsigned short xbox_smba = 0; +spinlock_t xbox_driver_lock = SPIN_LOCK_UNLOCKED; +struct driver_data; +static struct pci_dev *XBOX_dev; + +/* Detect whether a XBOX can be found, and initialize it, where necessary. + Note the differences between kernels with the old PCI BIOS interface and + newer kernels with the real PCI interface. In compat.h some things are + defined to make the transition easier. */ +int xbox_setup(void) +{ + unsigned char temp; + struct sd *currdev; + u16 cmd; + + XBOX_dev = NULL; + + /* Look for a supported chip */ + for(currdev = supported; currdev->vendor; ) { + XBOX_dev = pci_find_device(currdev->vendor, + currdev->device, XBOX_dev); + if (XBOX_dev != NULL) { + pci_read_config_byte(XBOX_dev, SMBGCFG, &temp); + pci_read_config_word(XBOX_dev, 0x14, &xbox_smba); + + xbox_smba &= 0xfffc; + if (PCI_FUNC(XBOX_dev->devfn) == currdev->function) + { + pci_read_config_word(XBOX_dev,PCI_STATUS,&cmd); + break; + } + } else { + currdev++; + } + } + + if (XBOX_dev == NULL) { + printk + ("i2c-xbox.o: Error: No XBOX or compatible device detected!\n"); + return(-ENODEV); + } + printk(KERN_INFO "i2c-xbox.o: Found %s SMBus controller.\n", currdev->name); + + /* Everything is happy, let's grab the memory and set things up. */ + if(!request_region(xbox_smba, SMB_IOSIZE, "xbox-smbus")) { + printk + ("i2c-xbox.o: SMB region 0x%x already in use!\n", + xbox_smba); + return(-ENODEV); + } + + return 0; +} + +/* + SMBUS event = I/O 28-29 bit 11 + see E0 for the status bits and enabled in E2 + +*/ + +/* Internally used pause function */ +void xbox_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +void xbox_abort(void) +{ + printk("i2c-xbox.o: Sending abort.\n"); + outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); + xbox_do_pause(100); + outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); +} + +int xbox_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + + /* Make sure the SMBus host is ready to start transmitting */ + if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { + do { + udelay(100); + temp = inw_p(SMB_GLOBAL_STATUS); + } while ((temp & (GS_HST_STS | GS_SMB_STS)) && + (timeout++ < MAX_TIMEOUT)); + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + printk("i2c-xbox.o: Busy wait timeout! (%04x)\n", temp); + xbox_abort(); + return(-1); + } + timeout = 0; + } + + /* start the transaction by setting the start bit */ + outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC , SMB_GLOBAL_ENABLE); + + /* We will always wait for a fraction of a second! */ + temp = inw_p(SMB_GLOBAL_STATUS); + while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT)) { + udelay(100); + temp = inw_p(SMB_GLOBAL_STATUS); + } + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + printk("i2c-xbox.o: Completion timeout!\n"); + xbox_abort (); + return(-1); + } + + if (temp & GS_PRERR_STS) { + result = -1; + } + + if (temp & GS_COL_STS) { + result = -1; + printk("i2c-xbox.o: SMBus collision!\n"); + } + + if (temp & GS_TO_STS) { + result = -1; + } + outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); + + return result; +} + +/* Return -1 on error. */ +s32 xbox_access(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data * data) +{ + /** TODO: Should I supporte the 10-bit transfers? */ + switch (size) { + case I2C_SMBUS_PROC_CALL: + printk + ("i2c-xbox.o: I2C_SMBUS_PROC_CALL not supported!\n"); + /* TODO: Well... It is supported, I'm just not sure what to do here... */ + return -1; + case I2C_SMBUS_QUICK: + outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMB_HOST_ADDRESS); + size = XBOX_QUICK; + break; + case I2C_SMBUS_BYTE: + outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMB_HOST_ADDRESS); + /* TODO: Why only during write? */ + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMB_HOST_COMMAND); + size = XBOX_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMB_HOST_ADDRESS); + outb_p(command, SMB_HOST_COMMAND); + if (read_write == I2C_SMBUS_WRITE) + outw_p(data->byte, SMB_HOST_DATA); + size = XBOX_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMB_HOST_ADDRESS); + outb_p(command, SMB_HOST_COMMAND); + if (read_write == I2C_SMBUS_WRITE) + outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */ + size = XBOX_WORD_DATA; + break; + } + + /* How about enabling interrupts... */ + outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); + + if (xbox_transaction()) /* Error in transaction */ + return -1; + + if ((read_write == I2C_SMBUS_WRITE) || (size == XBOX_QUICK)) + return 0; + + + switch (size) { + case XBOX_BYTE: + data->byte = inw_p(SMB_HOST_DATA); + break; + case XBOX_BYTE_DATA: + data->byte = inw_p(SMB_HOST_DATA); + break; + case XBOX_WORD_DATA: + data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */ + break; + } + + return 0; +} + +u32 xbox_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL; +} + +int __init i2c_xbox_init(void) +{ + int res; + printk("i2c-xbox.o version 0.0.1\n"); + xbox_initialized = 0; + if ((res = xbox_setup())) { + printk + ("i2c-xbox.o: XBOX or compatible device not detected, module not inserted.\n"); + xbox_cleanup(); + return res; + } + xbox_initialized++; + sprintf(xbox_adapter.name, "SMBus adapter at %04x",xbox_smba); + if ((res = i2c_add_adapter(&xbox_adapter))) { + printk + ("i2c-xbox.o: Adapter registration failed, module not inserted.\n"); + xbox_cleanup(); + return res; + } + xbox_initialized++; + printk("i2c-xbox.o: SMBus bus detected and initialized\n"); + return 0; +} + +int __init xbox_cleanup(void) +{ + int res; + if (xbox_initialized >= 2) { + if ((res = i2c_del_adapter(&xbox_adapter))) { + printk + ("i2c-xbox.o: i2c_del_adapter failed, module not removed\n"); + return res; + } else + xbox_initialized--; + } + if (xbox_initialized >= 1) { + release_region(xbox_smba, SMB_IOSIZE); + xbox_initialized--; + } + free_irq(XBOX_dev->irq, XBOX_dev); + return 0; +} + +EXPORT_SYMBOL(i2c_xbox_init); + +#ifdef MODULE + +MODULE_AUTHOR("Edgar Hucek "); +MODULE_DESCRIPTION("XBOX nForce SMBus driver"); + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +int init_module(void) +{ + return i2c_xbox_init(); +} + +void cleanup_module(void) +{ + xbox_cleanup(); +} + +#endif /* MODULE */ diff -urN linux-2.6.6.orig/drivers/ide/ide-cd.c linux-2.6.6/drivers/ide/ide-cd.c --- linux-2.6.6.orig/drivers/ide/ide-cd.c 2004-05-10 03:32:29.000000000 +0100 +++ linux-2.6.6/drivers/ide/ide-cd.c 2004-05-10 12:30:22.952981784 +0100 @@ -324,6 +324,14 @@ #include "ide-cd.h" +#ifdef CONFIG_X86_XBOX +#include +/* Global flag indicating whether to simulate Xbox drive locking in + * software. There should only be one Xbox drive in a system! This + * variable is externally referenced by arch/i386/kernel/xboxejectfix.c. */ +volatile int Xbox_simulate_drive_locked = 0; +#endif /* CONFIG_X86_XBOX */ + /**************************************************************************** * Generic packet command support and error handling routines. */ @@ -2121,6 +2129,16 @@ if (sense == NULL) sense = &my_sense; +#ifdef CONFIG_X86_XBOX + /* If we're on an Xbox and this is an Xbox drive, simulate the lock + request in software. (See arch/i386/kernel/xboxejectfix.c) */ + if (CDROM_CONFIG_FLAGS(drive)->xbox_drive && machine_is_xbox) { + CDROM_STATE_FLAGS(drive)->door_locked = lockflag; + Xbox_simulate_drive_locked = lockflag; + return 0; + } +#endif /* CONFIG_X86_XBOX */ + /* If the drive cannot lock the door, just pretend. */ if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { stat = 0; @@ -2169,6 +2187,23 @@ if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) return 0; +#ifdef CONFIG_X86_XBOX + /* Older Xbox DVD drives don't understand the ATAPI command, but the SMC + can do the eject. Note that some Xbox drives support the eject + command, namely the Samsung, so for that drive we do a regular eject + sequence. */ + if (machine_is_xbox && CDROM_CONFIG_FLAGS(drive)->xbox_drive && + CDROM_CONFIG_FLAGS(drive)->xbox_eject) { + if (ejectflag) { + Xbox_tray_load(); + } else { + Xbox_simulate_drive_locked = 0; + Xbox_tray_eject(); + } + return 0; + } +#endif + cdrom_prepare_request(&req); /* only tell drive to close tray if open, if it can do that */ @@ -3258,6 +3293,67 @@ /* uses CD in slot 0 when value is set to 3 */ cdi->sanyo_slot = 3; } +#ifdef CONFIG_X86_XBOX + /* THOMSON DVD drives in the Xbox report incorrect capabilities + and do not understand the ATAPI eject command, but the SMC + can do the eject. */ + else if ((strcmp(drive->id->model, "THOMSON-DVD") == 0)) { + CDROM_CONFIG_FLAGS(drive)->audio_play = 1; + CDROM_CONFIG_FLAGS(drive)->dvd = 1; + CDROM_CONFIG_FLAGS(drive)->xbox_drive = 1; + CDROM_CONFIG_FLAGS(drive)->xbox_eject = 1; + } + /* PHILIPS drives in Xboxen manufactured pre September 2003, + report correct capabilities, but do not understand the ATAPI + eject command, hence require the SMC to do so. */ + else if ((strcmp(drive->id->model, "PHILIPS XBOX DVD DRIVE") == 0)) { + CDROM_CONFIG_FLAGS(drive)->xbox_drive = 1; + CDROM_CONFIG_FLAGS(drive)->xbox_eject = 1; + } + /* PHILIPS drives in Xboxen manufactured post September 2003, + report incorrect capabilities, but understand the ATAPI + eject command. */ + else if ((strcmp(drive->id->model, "PHILIPS J5 3235C") == 0)) { + CDROM_CONFIG_FLAGS(drive)->audio_play = 1; + CDROM_CONFIG_FLAGS(drive)->dvd = 1; + CDROM_CONFIG_FLAGS(drive)->xbox_drive = 1; + CDROM_CONFIG_FLAGS(drive)->xbox_eject = 0; + } + /* SAMSUNG drives in the Xbox report correct capabilities + and understand the ATAPI eject command. */ + else if (strcmp(drive->id->model, "SAMSUNG DVD-ROM SDG-605B") == 0) { + CDROM_CONFIG_FLAGS(drive)->xbox_drive = 1; + CDROM_CONFIG_FLAGS(drive)->xbox_eject = 0; + } +#endif + + /* Is an Xbox drive detected? */ +#ifdef CONFIG_X86_XBOX + if (CDROM_CONFIG_FLAGS(drive)->xbox_drive) { +#endif + /* If an Xbox drive is present in a regular PC, we can't eject. + Act like the drive cannot eject, unless the ATAPI eject command + is supported by the drive. If the drive doesn't support ATAPI + ejecting, act like door locking is impossible as well. */ +#ifdef CONFIG_X86_XBOX + if (!machine_is_xbox) { +#endif /* CONFIG_X86_XBOX */ + CDROM_CONFIG_FLAGS(drive)->no_doorlock = CDROM_CONFIG_FLAGS + (drive)->xbox_eject; + CDROM_CONFIG_FLAGS(drive)->no_eject = CDROM_CONFIG_FLAGS(drive) + ->xbox_eject; +#ifdef CONFIG_X86_XBOX + } else { + /* An Xbox drive in an Xbox. We can support ejecting through + the SMC and support drive locking in software by ignoring + the eject interrupt (see arch/i386/kernel/xboxejectfix.c). */ + CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0; + CDROM_CONFIG_FLAGS(drive)->no_eject = 0; + Xbox_simulate_drive_locked = 0; + } +#endif + } + #endif /* not STANDARD_ATAPI */ info->toc = NULL; diff -urN linux-2.6.6.orig/drivers/ide/ide-cd.h linux-2.6.6/drivers/ide/ide-cd.h --- linux-2.6.6.orig/drivers/ide/ide-cd.h 2004-05-10 03:33:21.000000000 +0100 +++ linux-2.6.6/drivers/ide/ide-cd.h 2004-05-10 12:30:22.962980264 +0100 @@ -93,6 +93,10 @@ __u8 close_tray : 1; /* can close the tray */ __u8 writing : 1; /* pseudo write in progress */ __u8 mo_drive : 1; /* drive is an MO device */ +#ifdef CONFIG_X86_XBOX + __u8 xbox_drive : 1; /* drive is an Xbox drive */ + __u8 xbox_eject : 1; /* use Xbox SMC eject mechanism */ +#endif __u8 reserved : 2; byte max_speed; /* Max speed of the drive */ }; diff -urN linux-2.6.6.orig/drivers/pci/pci.ids linux-2.6.6/drivers/pci/pci.ids --- linux-2.6.6.orig/drivers/pci/pci.ids 2004-05-10 03:32:37.000000000 +0100 +++ linux-2.6.6/drivers/pci/pci.ids 2004-05-10 12:30:23.026970536 +0100 @@ -2856,6 +2856,7 @@ 0286 NV28 [GeForce4 Ti 4200 Go AGP 8x] 0288 NV28GL [Quadro4 980 XGL] 0289 NV28GL [Quadro4 780 XGL] + 02a0 NV16 [GeForce3 MX - nForce GPU] 0300 NV30 [GeForce FX] 0301 NV30 [GeForce FX 5800 Ultra] 0302 NV30 [GeForce FX 5800] diff -urN linux-2.6.6.orig/drivers/usb/input/Kconfig linux-2.6.6/drivers/usb/input/Kconfig --- linux-2.6.6.orig/drivers/usb/input/Kconfig 2004-05-10 03:33:08.000000000 +0100 +++ linux-2.6.6/drivers/usb/input/Kconfig 2004-05-10 12:30:23.059965520 +0100 @@ -192,19 +192,29 @@ module will be called mtouchusb. config USB_XPAD - tristate "X-Box gamepad support" + tristate "X-Box controller (gamepad) support" depends on USB && INPUT ---help--- - Say Y here if you want to use the X-Box pad with your computer. + Say Y here if you want to use Xbox controllers with your computer. Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV) and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well. - For information about how to connect the X-Box pad to USB, see + For information about how to connect an Xbox controller to USB, see . To compile this driver as a module, choose M here: the module will be called xpad. +config USB_XPAD_MOUSE + bool "Mouse emulation for Xbox controller" + depends on USB_XPAD + ---help--- + Say Y here if you want to enable mouse emulation for your Xbox + controller. + Make sure to say Y to "Mouse support" (CONFIG_INPUT_MOUSEDEV) + and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well. + + config USB_ATI_REMOTE tristate "ATI USB RF remote control" depends on USB && INPUT diff -urN linux-2.6.6.orig/drivers/usb/input/Makefile linux-2.6.6/drivers/usb/input/Makefile --- linux-2.6.6.orig/drivers/usb/input/Makefile 2004-05-10 03:32:52.000000000 +0100 +++ linux-2.6.6/drivers/usb/input/Makefile 2004-05-10 12:32:01.583987592 +0100 @@ -4,6 +4,7 @@ # Multipart objects. usbhid-objs := hid-core.o +xpad-objs := xpad-core.o # Optional parts of multipart objects. @@ -26,6 +27,10 @@ usbhid-objs += hid-ff.o endif +ifeq ($(CONFIG_USB_XPAD_MOUSE),y) + xpad-objs += xpad-mouse.o +endif + obj-$(CONFIG_USB_AIPTEK) += aiptek.o obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_USB_HID) += usbhid.o diff -urN linux-2.6.6.orig/drivers/usb/input/xpad-core.c linux-2.6.6/drivers/usb/input/xpad-core.c --- linux-2.6.6.orig/drivers/usb/input/xpad-core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/usb/input/xpad-core.c 2004-05-10 12:30:23.070963848 +0100 @@ -0,0 +1,579 @@ +/* + * Xbox input device driver for Linux - v0.1.4 + * + * Copyright (c) 2002 - 2004 Marko Friedemann + * + * Contributors: + * Vojtech Pavlik , + * Oliver Schwartz , + * Steven Toth , + * Franz Lehner , + * Ivan Hawkes + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * This driver is based on: + * - information from http://euc.jp/periphs/xbox-controller.en.html + * - the iForce driver drivers/char/joystick/iforce.c + * - the skeleton-driver drivers/usb/usb-skeleton.c + * + * Thanks to: + * - ITO Takayuki for providing essential xpad information on his website + * - Vojtech Pavlik - iforce driver / input subsystem + * - Greg Kroah-Hartman - usb-skeleton driver + * + * TODO: + * - fine tune axes + * - fine tune mouse behaviour (should not do linear acceleration) + * - NEW: get rumble working correctly, fix all the bugs and support multiple + * simultaneous effects + * - NEW: split funtionality mouse/joustick into two source files + * - NEW: implement /proc interface (toggle mouse/rumble enable/disable, etc.) + * - NEW: implement user space daemon application that handles that interface + * + * History: moved to end of file + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xpad.h" + +static struct xpad_device xpad_device[] = { + /* please keep those ordered wrt. vendor/product ids + vendor, product, isMat, name */ + { 0x044f, 0x0f07, 0, "Thrustmaster, Inc. Controller" }, + { 0x045e, 0x0202, 0, "Microsoft Xbox Controller" }, + { 0x045e, 0x0285, 0, "Microsoft Xbox Controller S" }, + { 0x045e, 0x0289, 0, "Microsoft Xbox Controller S" }, /* microsoft is stupid */ + { 0x046d, 0xca88, 0, "Logitech Compact Controller for Xbox" }, + { 0x05fd, 0x1007, 0, "???Mad Catz Controller???" }, /* CHECKME: this seems strange */ + { 0x05fd, 0x107a, 0, "InterAct PowerPad Pro" }, + { 0x0738, 0x4516, 0, "Mad Catz Control Pad" }, + { 0x0738, 0x4522, 0, "Mad Catz LumiCON" }, + { 0x0738, 0x4526, 0, "Mad Catz Control Pad Pro" }, + { 0x0738, 0x4536, 0, "Mad Catz MicroCON" }, + { 0x0738, 0x4540, 1, "Mad Catz Beat Pad" }, + { 0x0738, 0x4556, 0, "Mad Catz Lynx Wireless Controller" }, + { 0x0738, 0x6040, 1, "Mad Catz Beat Pad Pro" }, + { 0x0c12, 0x9902, 0, "HAMA VibraX - *FAULTY HARDWARE*" }, /* these are broken */ + { 0x0e4c, 0x2390, 0, "Radica Games Jtech Controller"}, + { 0x0e6f, 0x0003, 0, "Logic3 Freebird wireless Controller" }, + { 0x0f30, 0x0202, 0, "Joytech Advanced Controller" }, + { 0x12ab, 0x8809, 1, "Xbox DDR dancepad" }, + { 0xffff, 0xffff, 0, "Chinese-made Xbox Controller" }, /* WTF are device IDs for? */ + { 0x0000, 0x0000, 0, "nothing detected - FAIL" } +}; + +static signed short xpad_btn[] = { + BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* analogue buttons */ + BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ + BTN_0, BTN_1, BTN_2, BTN_3, /* d-pad as buttons */ + -1 /* terminating entry */ +}; + +static signed short xpad_mat_btn[] = { + BTN_A, BTN_B, BTN_X, BTN_Y, /* A, B, X, Y */ + BTN_START, BTN_BACK, /* start/back */ + BTN_0, BTN_1, BTN_2, BTN_3, /* directions, LEFT/RIGHT is mouse + * so we cannot use those! */ + -1 /* terminating entry */ +}; + +static signed short xpad_abs[] = { + ABS_X, ABS_Y, /* left stick */ + ABS_RX, ABS_RY, /* right stick */ + ABS_Z, ABS_RZ, /* triggers left/right */ + ABS_HAT0X, ABS_HAT0Y, /* digital pad */ + ABS_HAT1X, ABS_HAT1Y, /* analogue buttons A + B */ + ABS_HAT2X, ABS_HAT2Y, /* analogue buttons C + X */ + ABS_HAT3X, ABS_HAT3Y, /* analogue buttons Y + Z */ + -1 /* terminating entry */ +}; + +static struct usb_device_id xpad_table [] = { + { USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not approved class */ + { USB_INTERFACE_INFO( 3 , 0 , 0) }, /* for Joytech Advanced Controller */ + { } +}; + +MODULE_DEVICE_TABLE(usb, xpad_table); + +/** + * xpad_process_packet + * + * Completes a request by converting the data into events + * for the input subsystem. + * + * The report descriptor was taken from ITO Takayukis website: + * http://euc.jp/periphs/xbox-controller.en.html + */ +static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, struct pt_regs *regs) +{ + struct input_dev *dev = &xpad->dev; + + input_regs(dev, regs); + + /* digital pad (button mode) bits (3 2 1 0) (right left down up) */ + input_report_key(dev, BTN_0, (data[2] & 0x01)); + input_report_key(dev, BTN_1, (data[2] & 0x08) >> 3); + input_report_key(dev, BTN_2, (data[2] & 0x02) >> 1); + input_report_key(dev, BTN_3, (data[2] & 0x04) >> 2); + + /* start and back buttons */ + input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); + input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); + + /* buttons A, B, X, Y digital mode */ + input_report_key(dev, BTN_A, data[4]); + input_report_key(dev, BTN_B, data[5]); + input_report_key(dev, BTN_X, data[6]); + input_report_key(dev, BTN_Y, data[7]); + + if (xpad->isMat) + return; + + /* left stick */ + input_report_abs(dev, ABS_X, ((__s16) (((__s16)data[13] << 8) | data[12]))); + input_report_abs(dev, ABS_Y, ((__s16) (((__s16)data[15] << 8) | data[14]))); + + /* right stick */ + input_report_abs(dev, ABS_RX, ((__s16) (((__s16)data[17] << 8) | data[16]))); + input_report_abs(dev, ABS_RY, ((__s16) (((__s16)data[19] << 8) | data[18]))); + + /* triggers left/right */ + input_report_abs(dev, ABS_Z, data[10]); + input_report_abs(dev, ABS_RZ, data[11]); + + /* digital pad (analogue mode): bits (3 2 1 0) (right left down up) */ + input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x01) - !!(data[2] & 0x02)); + + /* stick press left/right */ + input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); + input_report_key(dev, BTN_THUMBR, data[2] >> 7); + + /* button A, B, X, Y analogue mode */ + input_report_abs(dev, ABS_HAT1X, data[4]); + input_report_abs(dev, ABS_HAT1Y, data[5]); + input_report_abs(dev, ABS_HAT2Y, data[6]); + input_report_abs(dev, ABS_HAT3X, data[7]); + + /* button C (black) digital/analogue mode */ + input_report_key(dev, BTN_C, data[8]); + input_report_abs(dev, ABS_HAT2X, data[8]); + + /* button Z (white) digital/analogue mode */ + input_report_key(dev, BTN_Z, data[9]); + input_report_abs(dev, ABS_HAT3Y, data[9]); + + input_sync(dev); + + /* process input data for mouse event generation */ + xpad_mouse_process_packet(xpad, cmd, data); +} + +/** + * xpad_irq_in + * + * Completion handler for interrupt in transfers (user input). + * Just calls xpad_process_packet which does then emit input events. + */ +static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) +{ + struct usb_xpad *xpad = urb->context; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + goto exit; + } + + xpad_process_packet(xpad, 0, xpad->idata, regs); + +exit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + err("%s - usb_submit_urb failed with result %d", + __FUNCTION__, retval); +} + +/* xpad_init_urb + * + * initialize the input urb + * this is to be called when joystick or mouse device are opened + */ +int xpad_start_urb(struct usb_xpad *xpad) +{ + int status; + + // check if joystick or mouse device are opened + if (xpad->open_count + xpad->mouse_open_count > 0) + return 0; + + xpad->irq_in->dev = xpad->udev; + if ((status = usb_submit_urb(xpad->irq_in, GFP_KERNEL))) { + err("open input urb failed: %d", status); + return -EIO; + } + + return 0; +} + +/** + * xpad_open + * + * Called when a an application opens the device. + */ +static int xpad_open(struct input_dev *dev) +{ + struct usb_xpad *xpad = dev->private; + int status; + + if (xpad->open_count) + return 0; + + info("opening device"); + + if ((status = xpad_start_urb(xpad))) + return status; + + ++xpad->open_count; + + xpad_rumble_open(xpad); + + return 0; +} + +void xpad_stop_urb(struct usb_xpad *xpad) +{ + if (xpad->open_count + xpad->mouse_open_count > 0) + return; + + usb_unlink_urb(xpad->irq_in); +} + +/** + * xpad_close + * + * Called when an application closes the device. + */ +static void xpad_close(struct input_dev *dev) +{ + struct usb_xpad *xpad = dev->private; + + if (--xpad->open_count) + return; + + info("closing device"); + + xpad_stop_urb(xpad); + xpad_rumble_close(xpad); +} + +/** xpad_init_input_device + * + * setup the input device for the kernel + */ +static void xpad_init_input_device(struct usb_interface *intf, struct xpad_device device) +{ + struct usb_xpad *xpad = usb_get_intfdata(intf); + struct usb_device *udev = interface_to_usbdev(intf); + char path[64]; + int i; + + xpad->dev.id.bustype = BUS_USB; + xpad->dev.id.vendor = udev->descriptor.idVendor; + xpad->dev.id.product = udev->descriptor.idProduct; + xpad->dev.id.version = udev->descriptor.bcdDevice; + xpad->dev.dev = &intf->dev; + xpad->dev.private = xpad; + xpad->dev.name = device.name; + xpad->dev.phys = xpad->phys; + xpad->dev.open = xpad_open; + xpad->dev.close = xpad_close; + + usb_make_path(udev, path, 64); + snprintf(xpad->phys, 64, "%s/input0", path); + + /* this was meant to allow a user space tool on-the-fly configuration + of driver options (mouse on, rumble on, etc) + yet, Vojtech said this is better done using sysfs (linux 2.6) + plus, it needs a patch to the input subsystem */ +// xpad->dev.ioctl = xpad_ioctl; + + if (xpad->isMat) { + xpad->dev.evbit[0] = BIT(EV_KEY); + for (i = 0; xpad_mat_btn[i] >= 0; ++i) + set_bit(xpad_mat_btn[i], xpad->dev.keybit); + } else { + xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + + for (i = 0; xpad_btn[i] >= 0; ++i) + set_bit(xpad_btn[i], xpad->dev.keybit); + + for (i = 0; xpad_abs[i] >= 0; ++i) { + + signed short t = xpad_abs[i]; + + set_bit(t, xpad->dev.absbit); + + switch (t) { + case ABS_X: + case ABS_Y: + case ABS_RX: + case ABS_RY: /* the two sticks */ + xpad->dev.absmax[t] = 32767; + xpad->dev.absmin[t] = -32768; + xpad->dev.absflat[t] = 128; + xpad->dev.absfuzz[t] = 16; + break; + case ABS_Z: /* left trigger */ + case ABS_RZ: /* right trigger */ + case ABS_HAT1X: /* analogue button A */ + case ABS_HAT1Y: /* analogue button B */ + case ABS_HAT2X: /* analogue button C */ + case ABS_HAT2Y: /* analogue button X */ + case ABS_HAT3X: /* analogue button Y */ + case ABS_HAT3Y: /* analogue button Z */ + xpad->dev.absmax[t] = 255; + xpad->dev.absmin[t] = 0; + break; + case ABS_HAT0X: + case ABS_HAT0Y: /* the d-pad */ + xpad->dev.absmax[t] = 1; + xpad->dev.absmin[t] = -1; + break; + } + } + + if (xpad_rumble_probe(udev, xpad, ifnum) != 0) + err("could not init rumble"); + } + + input_register_device(&xpad->dev); + printk(KERN_INFO "input: %s on %s\n", xpad->dev.name, path); +} + +/** + * xpad_probe + * + * Called upon device detection to find a suitable driver. + * Must return NULL when no xpad is found, else setup everything. + */ +static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_xpad *xpad = NULL; + struct usb_endpoint_descriptor *ep_irq_in; + int i; + int probedDevNum = -1; /* this takes the index into the known devices + array for the recognized device */ + + // try to detect the device we are called for + for (i = 0; xpad_device[i].idVendor; ++i) { + if ((udev->descriptor.idVendor == xpad_device[i].idVendor) && + (udev->descriptor.idProduct == xpad_device[i].idProduct)) { + probedDevNum = i; + break; + } + } + + // sanity check, did we recognize this device? if not, fail + if ((probedDevNum == -1) || (!xpad_device[probedDevNum].idVendor && + !xpad_device[probedDevNum].idProduct)) + return -ENODEV; + + if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { + err("cannot allocate memory for new pad"); + return -ENOMEM; + } + memset(xpad, 0, sizeof(struct usb_xpad)); + + xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, + SLAB_ATOMIC, &xpad->idata_dma); + if (!xpad->idata) { + kfree(xpad); + return -ENOMEM; + } + + /* setup input interrupt pipe (button and axis state) */ + xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); + if (!xpad->irq_in) { + err("cannot allocate memory for new pad irq urb"); + usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); + kfree(xpad); + return -ENOMEM; + } + + ep_irq_in = &intf->altsetting[0].endpoint[0].desc; + + xpad->udev = udev; + xpad->isMat = xpad_device[probedDevNum].isMat; + + /* init input URB for USB INT transfer from device */ + usb_fill_int_urb(xpad->irq_in, udev, + usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), + xpad->idata, XPAD_PKT_LEN, + xpad_irq_in, xpad, ep_irq_in->bInterval); + xpad->irq_in->transfer_dma = xpad->idata_dma; + xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + // we set this here so we can extract it in the two functions below + usb_set_intfdata(intf, xpad); + + xpad_init_input_device(intf, xpad_device[probedDevNum]); + xpad_mouse_init_input_device(intf, xpad_device[probedDevNum]); + + return 0; +} + +/** + * xpad_disconnect + * + * Called upon device disconnect to dispose of the structures and + * close the USB connections. + */ +static void xpad_disconnect(struct usb_interface *intf) +{ + struct usb_xpad *xpad = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); + if (xpad) { + info( "disconnecting device" ); + usb_unlink_urb(xpad->irq_in); + xpad_rumble_close(xpad); + input_unregister_device(&xpad->dev); + + usb_free_urb(xpad->irq_in); + xpad_mouse_cleanup(xpad); + + usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, + xpad->idata, xpad->idata_dma); + + xpad_rumble_disconnect(xpad); + + kfree(xpad); + } +} + +/******************* Linux driver framework specific stuff ************/ + +static struct usb_driver xpad_driver = { + .owner = THIS_MODULE, + .name = "xpad", + .probe = xpad_probe, + .disconnect = xpad_disconnect, + .id_table = xpad_table, +}; + +/** + * driver init entry point + */ +static int __init usb_xpad_init(void) +{ + int result = usb_register(&xpad_driver); + if (result == 0) + info(DRIVER_DESC " " DRIVER_VERSION); + return result; +} + +/** + * driver exit entry point + */ +static void __exit usb_xpad_exit(void) +{ + usb_deregister(&xpad_driver); +} + +module_init(usb_xpad_init); +module_exit(usb_xpad_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/* + * driver history + * ---------------- + * + * 2003-05-15 - 0.1.2 : ioctls, dynamic mouse/rumble activation, /proc fs + * - added some /proc files for informational purposes (readonly right now) + * - added init parameters for mouse/rumble activation upon detection + * - added dynamic changes to mouse events / rumble effect generation via + * ioctls - NOTE: this requires a currently unofficial joydev patch! + * + * 2003-04-29 - 0.1.1 : minor cleanups, some comments + * - fixed incorrect handling of unknown devices (please try ir dongle now) + * - fixed input URB length (the 256 bytes from 0.1.0 broke everything for the + * MS controller as well as my Interact device, set back to 32 (please + * REPORT problems BEFORE any further changes here, since those can be fatal) + * - fixed rumbling for MS controllers (need 6 bytes output report) + * - dropped kernel-2.5 ifdefs, much more readable now + * - preparation for major rework under way, stay tuned + * + * 2003-03-25 - 0.1.0 : (Franz) Some Debuggin + * - Better Handling + * - X/Y support, Speed differenting + * - Landing Zone, Dead Zone, Offset kompensation, Zero-adjustment, .... aso. + * - Removed Wheel handling in Mouse Emulation .. sensless.. + * + * 2003-01-23 - 0.1.0-pre : added mouse emulation and rumble support + * - can provide mouse emulation (compile time switch) + * this code has been taken from Oliver Schwartz' xpad-mouse driver + * - basic rumble support (compile time switch) EXPERIMENTAL! + * + * 2002-08-05 - 0.0.6 : added analog button support + * + * 2002-07-17 - 0.0.5 : (Vojtech Pavlik) rework + * - simplified d-pad handling + * + * 2002-07-16 - 0.0.4 : minor changes, merge with Vojtech's v0.0.3 + * - verified the lack of HID and report descriptors + * - verified that ALL buttons WORK + * - fixed d-pad to axes mapping + * + * 2002-07-14 - 0.0.3 : (Vojtech Pavlik) rework + * - indentation fixes + * - usb + input init sequence fixes + * + * 2002-07-02 - 0.0.2 : basic working version + * - all axes and 9 of the 10 buttons work (german InterAct device) + * - the black button does not work + * + * 2002-06-27 - 0.0.1 : first version, just said "XBOX HID controller" + */ diff -urN linux-2.6.6.orig/drivers/usb/input/xpad-mouse.c linux-2.6.6/drivers/usb/input/xpad-mouse.c --- linux-2.6.6.orig/drivers/usb/input/xpad-mouse.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/usb/input/xpad-mouse.c 2004-05-10 12:30:23.073963392 +0100 @@ -0,0 +1,270 @@ +/* + * Xbox input device driver for Linux - v0.1.4 + * + * mouse emulation stuff, merged from Olivers xpad-mouse + * + * Copyright (c) 2003, 2004 Marko Friedemann + * portions Copyright (c) 2002 Oliver Schwartz , + * 2003 Franz Lehner + * + * Released under GPL. See xpad-core.c for details + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __USB_XPAD_MOUSE +#include "xpad.h" +#undef __USB_XPAD_MOUSE + +#define XPAD_WHEELBRAKE 20 +#define JOY_DeadZone_fast 6000 +#define JOY_DeadZone_slow 200 +#define XPAD_OFFSET_COUNTER 5 + + +static int mouse_on_load = 1; +MODULE_PARM( mouse_on_load, "i" ); +MODULE_PARM_DESC( mouse_on_load, "set to 0 to deactivate mouse support on insmod (default 1)" ); + + +/** + * xpad_removedeadzone + * + * Franz? Please clarify and correct. + * + * Removes the deadzone for mouse operation. + * Allows for better handling near the stick's center. + */ +static int xpad_mouse_removedeadzone(signed int position, int speed, int deadzone) +{ + if (position>31000) position=31000; + if (position<-31000) position=-31000; + + if ((position>0)&(position(-deadzone))) return 0; + + if (position>deadzone) position -= deadzone; + if (position<(-(deadzone))) position+= deadzone; + position = (int)(position / speed); + + return position; +} + +void xpad_mouse_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) +{ + struct input_dev *dev_mouse = &xpad->dev_mouse; + + int signledirection, xyspeed; + //int joy_y2; + unsigned char MouseLeft,MouseRight, MouseMiddle; + signed int left_joy_x, left_joy_y, right_joy_x, right_joy_y; + + if (!xpad->mouse_open_count || !xpad->mouse_enabled) + return; + + left_joy_x = ((__s16) (((__s16)data[13] << 8) | data[12])); + left_joy_y = ((__s16) (((__s16)data[15] << 8) | data[14])); + + right_joy_x = ((__s16) (((__s16)data[17] << 8) | data[16])); + right_joy_y = ((__s16) (((__s16)data[19] << 8) | data[18])); + + // Creates Offset when first starting + /* CHECKME: who coded this? Franz? Please clarify: + 1) is this necessary for joystick operation? + 2) offset_counter was only defined when MOUSE + support was configured (has been FIXED, see above) */ + if (xpad->offsetset_compensation>0) { + + if (xpad->offsetset_compensation == XPAD_OFFSET_COUNTER) { + xpad->left_offset_x = left_joy_x; + xpad->left_offset_y = left_joy_y; + xpad->right_offset_x = right_joy_x; + xpad->right_offset_y = right_joy_y; + } else { + xpad->left_offset_x += left_joy_x; + xpad->left_offset_y += left_joy_y; + xpad->right_offset_x += right_joy_x; + xpad->right_offset_y += right_joy_y; + } + + if (xpad->offsetset_compensation == 1) { + xpad->left_offset_x = xpad->left_offset_x / XPAD_OFFSET_COUNTER; + xpad->left_offset_y = xpad->left_offset_y / XPAD_OFFSET_COUNTER; + xpad->right_offset_x = xpad->right_offset_x / XPAD_OFFSET_COUNTER; + xpad->right_offset_y = xpad->right_offset_y / XPAD_OFFSET_COUNTER; + } + + xpad->offsetset_compensation--; + } + + left_joy_x -= xpad->left_offset_x; + left_joy_y -= xpad->left_offset_y; + + right_joy_x -= xpad->right_offset_x; + right_joy_y -= xpad->right_offset_y; + + if (data[11]<0x10) { + // Normal Speed Mode + xpad->rel_x = (xpad_mouse_removedeadzone(left_joy_x,0x1500,JOY_DeadZone_fast)); + xpad->rel_y = -(xpad_mouse_removedeadzone(left_joy_y,0x1500,JOY_DeadZone_fast)); + xyspeed = 2; + //printk("%d:",xpad->rel_y); + } else { + // Ultra Slow Mode + xpad->rel_x = (xpad_mouse_removedeadzone(left_joy_x,0x3500,JOY_DeadZone_slow)); + xpad->rel_y = -(xpad_mouse_removedeadzone(left_joy_y,0x3500,JOY_DeadZone_slow)); + xyspeed = 1; + } + + // X-Y Steering + signledirection=1; + if (signledirection&((data[2] & 0x04)!=0)) { signledirection=0; xpad->rel_x -=xyspeed; } + if (signledirection&((data[2] & 0x08)!=0)) { signledirection=0; xpad->rel_x +=xyspeed; } + if (signledirection&((data[2] & 0x02)!=0)) { signledirection=0; xpad->rel_y +=xyspeed; } + if (signledirection&((data[2] & 0x01)!=0)) { signledirection=0; xpad->rel_y -=xyspeed; } + + /* wheel handling */ + //joy_y2 = xpad_mouse_removedeadzone(joy_y2); + //xpad->rel_wheel = (joy_y2>0)?1:(joy_y2<0)?-1:0; + xpad->rel_wheel=0; + + if (data[10]==0xFF) MouseLeft=1; else MouseLeft =0; + if ((MouseLeft==0)&(data[7]!=0)) MouseLeft =1; + if ((MouseLeft==0)&(data[4]!=0)) MouseLeft = 1; + if ((MouseLeft==0)&((data[2] >> 7)!=0)) MouseLeft = 1; + if ((MouseLeft==0)&(((data[2] & 0x40) >> 6)!=0)) MouseLeft = 1; + + if (data[5]!=0) MouseRight=1; else MouseRight=0; + if (data[6]!=0) MouseMiddle =1; else MouseMiddle=0; + + // Generating Mouse Emulation Events (Button Events) + input_report_key(dev_mouse, BTN_LEFT, MouseLeft); + input_report_key(dev_mouse, BTN_RIGHT, MouseRight); + input_report_key(dev_mouse, BTN_MIDDLE, MouseMiddle); + + input_sync(dev_mouse); +} + +/** + * xpad_timer + * + * Reports the mouse events in the interval given in xpad_open. + * + * Taken from Oliver Schwartz' xpad-mouse driver to avoid strange mouse + * behaviour encountered when the input events where send directly + * in xpad_process_packet. + */ +static void xpad_timer(unsigned long data) +{ + struct usb_xpad *xpad = (struct usb_xpad *)data; + + if (xpad->mouse_enabled) { + input_report_rel(&xpad->dev_mouse, REL_X, xpad->rel_x); + input_report_rel(&xpad->dev_mouse, REL_Y, xpad->rel_y); + + input_sync(&xpad->dev_mouse); + + /*if (xpad->rel_wheeltimer == 0) { + input_report_rel(&xpad->dev_mouse, REL_WHEEL, xpad->rel_wheel); + xpad->rel_wheeltimer = XPAD_WHEELBRAKE; + } else + xpad->rel_wheeltimer--;*/ + } + + // reschedule the timer so that it fires continually + add_timer(&xpad->timer); +} + +static int xpad_mouse_open(struct input_dev *dev) +{ + struct usb_xpad *xpad = dev->private; + int status; + + if (xpad->mouse_open_count) + return 0; + + if ((status = xpad_start_urb(xpad))) + return status; + + ++xpad->mouse_open_count; + + info("opening mouse device"); + + // set up timer for mouse event generation + init_timer(&xpad->timer); + xpad->timer.expires = 1*HZ/5; /* every 200 ms */ + xpad->timer.data = (unsigned long)xpad; + xpad->timer.function = xpad_timer; + // now start the timer + add_timer(&xpad->timer); + + return 0; +} + +static void xpad_mouse_close(struct input_dev *dev) +{ + struct usb_xpad *xpad = dev->private; + + if (--xpad->mouse_open_count) + return; + + xpad_stop_urb(xpad); + + info("closing mouse device"); + del_timer(&xpad->timer); +} + +int xpad_mouse_init_input_device(struct usb_interface *intf, struct xpad_device device) +{ + struct usb_xpad *xpad = usb_get_intfdata(intf); + struct usb_device *udev = interface_to_usbdev(intf); + + /* the mouse device struct for the kernel (mouse emulation) */ + xpad->dev_mouse.id.bustype = BUS_USB; + xpad->dev_mouse.id.vendor = udev->descriptor.idVendor; + xpad->dev_mouse.id.product = udev->descriptor.idProduct; + xpad->dev_mouse.id.version = udev->descriptor.bcdDevice; + xpad->dev_mouse.dev = &intf->dev; + xpad->dev_mouse.private = xpad; + xpad->dev_mouse.name = device.name; + xpad->dev_mouse.phys = xpad->phys; + xpad->dev_mouse.open = xpad_mouse_open; + xpad->dev_mouse.close = xpad_mouse_close; + xpad->offsetset_compensation = XPAD_OFFSET_COUNTER; // Find new offset point + xpad->mouse_enabled = mouse_on_load; + + /* mouse setup */ + xpad->dev_mouse.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + + set_bit(REL_X, xpad->dev_mouse.relbit); + set_bit(REL_Y, xpad->dev_mouse.relbit); + set_bit(REL_WHEEL, xpad->dev_mouse.relbit); + + set_bit(BTN_LEFT, xpad->dev_mouse.keybit); + set_bit(BTN_RIGHT, xpad->dev_mouse.keybit); + set_bit(BTN_MIDDLE, xpad->dev_mouse.keybit); + set_bit(BTN_SIDE, xpad->dev_mouse.keybit); + set_bit(BTN_EXTRA, xpad->dev_mouse.keybit); + + input_register_device(&xpad->dev_mouse); + printk(KERN_INFO "input: mouse emulation %s@ %s\n", + (mouse_on_load ? "" : "(disabled) "), xpad->dev_mouse.name); +} + +void xpad_mouse_cleanup(struct usb_xpad *xpad) +{ + // the timer exists only when the mouse device is used + if (xpad->mouse_open_count) + del_timer(&xpad->timer); + input_unregister_device(&xpad->dev_mouse); +} diff -urN linux-2.6.6.orig/drivers/usb/input/xpad.h linux-2.6.6/drivers/usb/input/xpad.h --- linux-2.6.6.orig/drivers/usb/input/xpad.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/usb/input/xpad.h 2004-05-10 12:30:23.092960504 +0100 @@ -0,0 +1,167 @@ +/* + * Xbox Controller driver for Linux - v0.1.4 + * + * header file containing ioctl definitions + * + * Copyright (c) 2003 Marko Friedemann + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __XPAD_h +#define __XPAD_h + + +/*********** ioctl stuff, can be used outside of the driver ***********/ +#define USB_XPAD_IOC_MAGIC 'x' + +#define USB_XPAD_IOCRESET _IO( USB_XPAD_IOC_MAGIC, 0 ) +#define USB_XPAD_IOCSMOUSE _IOW( USB_XPAD_IOC_MAGIC, 1, int ) +#define USB_XPAD_IOCGMOUSE _IOR( USB_XPAD_IOC_MAGIC, 2, int ) +#define USB_XPAD_IOCSRUMBLE _IOW( USB_XPAD_IOC_MAGIC, 3, int ) +#define USB_XPAD_IOCGRUMBLE _IOR( USB_XPAD_IOC_MAGIC, 4, int ) + +#define USB_XPAD_IOCSIR _IOW( USB_XPAD_IOC_MAGIC, 5, int ) +#define USB_XPAD_IOCGIR _IOR( USB_XPAD_IOC_MAGIC, 6, int ) + +#define USB_XPAD_IOC_MAXNR 6 + + +/************************* driver internals ***************************/ +#ifdef __KERNEL__ + +#include +#include + +/****************** driver description and version ********************/ +#define DRIVER_VERSION "v0.1.4" +#define DRIVER_AUTHOR "Marko Friedemann ,\ + Oliver Schwartz , Georg Lukas " + +#ifdef CONFIG_USB_XPAD_MOUSE +#define DRIVER_DESC "driver for Xbox controllers with mouse emulation" +#else +#define DRIVER_DESC "driver for Xbox controllers" +#endif + +/****************************** constants *****************************/ +#define XPAD_MAX_DEVICES 4 +#define XPAD_PKT_LEN 32 /* input packet size */ +#define XPAD_PKT_LEN_FF 6 /* output packet size - rumble */ + +#define XPAD_TX_BUFSIZE XPAD_PKT_LEN_FF * 8 /* max. 8 requests */ + +/************************* the device struct **************************/ +struct usb_xpad { + struct input_dev dev; /* input device interface */ + struct usb_device *udev; /* usb device */ + + struct urb *irq_in; /* urb for int. in report */ + unsigned char *idata; /* input data */ + dma_addr_t idata_dma; + + char phys[65]; /* physical input dev path */ + + int open_count; /* reference count */ + + unsigned char offsetset_compensation; + int left_offset_x; + int left_offset_y; + int right_offset_x; + int right_offset_y; + + int isMat; /* is this a dancepad/mat? */ + +#ifdef CONFIG_USB_XPAD_RUMBLE + int rumble_enabled; /* ioctl can toggle rumble */ + + int ep_out_adr; /* number of out endpoint */ + unsigned char tx_data[XPAD_PKT_LEN_FF]; /* output data (rumble) */ + int strong_rumble, play_strong; /* strong rumbling */ + int weak_rumble, play_weak; /* weak rumbling */ + struct timer_list rumble_timer; /* timed urb out retry */ + wait_queue_head_t wait; /* wait for URBs on queue */ + + spinlock_t tx_lock; + struct circ_buf tx; + unsigned char tx_buf[XPAD_TX_BUFSIZE]; + long tx_flags[1]; /* transmit flags */ +#endif + +#ifdef CONFIG_USB_XPAD_MOUSE + struct input_dev dev_mouse; /* mouse device interface */ + int mouse_open_count; /* reference count */ + int mouse_enabled; /* ioctl can toggle rumble */ + + int rel_x; + int rel_y; + int rel_wheel; + int rel_wheeltimer; + struct timer_list timer; /* timed mouse input events */ +#endif +}; + +/* for the list of know devices */ +struct xpad_device { + u16 idVendor; + u16 idProduct; + u8 isMat; + char *name; +}; + +#ifdef __USB_XPAD_MOUSE + extern int xpad_start_urb(struct usb_xpad *xpad); + extern void xpad_stop_urb(struct usb_xpad *xpad); +#endif + +/************************ mouse function stubs ************************/ +#ifndef CONFIG_USB_XPAD_MOUSE + #define mouse_open_count open_count + #define xpad_mouse_process_packet(xpad, cmd, data) {} + #define xpad_mouse_init_input_device(intf, device) {} + #define xpad_mouse_cleanup(xpad) {} +#else /* CONFIG_USB_XPAD_MOUSE */ + #ifndef __USB_XPAD_MOUSE + extern void xpad_mouse_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data); + extern void xpad_mouse_init_input_device(struct usb_interface *intf, struct xpad_device device); + extern void xpad_mouse_cleanup(struct usb_xpad *xpad); + #endif /* __USB_XPAD_MOUSE */ +#endif /* CONFIG_USB_XPAD_MOUSE */ + +/************************ rumble function stubs ***********************/ +#ifndef CONFIG_USB_XPAD_RUMBLE + #define xpad_rumble_ioctl(dev, cmd, arg) -ENOTTY + #define xpad_rumble_open(xpad) {} + #define xpad_rumble_probe(udev, xpad, ifnum) 0 + #define xpad_rumble_close(xpad) {} + #define xpad_rumble_disconnect(xpad) {} +#else /* CONFIG_USB_XPAD_RUMBLE */ + + #define XPAD_TX_RUNNING 0 + #define XPAD_TX_INC(var, n) (var) += n; (var) %= XPAD_TX_BUFSIZE + + #ifndef __USB_XPAD_RUMBLE + extern int xpad_rumble_ioctl(struct input_dev *dev, unsigned int cmd, unsigned long arg); + extern void xpad_rumble_open(struct usb_xpad *xpad); + extern int xpad_rumble_probe(struct usb_device *udev, struct usb_xpad *xpad, unsigned int ifnum); + extern void xpad_rumble_close(struct usb_xpad *xpad); + extern void xpad_rumble_disconnect(struct usb_xpad *xpad); + #endif /* __USB_XPAD_RUMBLE */ +#endif /* CONFIG_USB_XPAD_RUMBLE */ + +#endif /* __KERNEL__ */ + +#endif /* __XPAD_h */ diff -urN linux-2.6.6.orig/drivers/video/Kconfig linux-2.6.6/drivers/video/Kconfig --- linux-2.6.6.orig/drivers/video/Kconfig 2004-05-10 03:31:59.000000000 +0100 +++ linux-2.6.6/drivers/video/Kconfig 2004-05-10 12:30:23.136953816 +0100 @@ -405,6 +405,16 @@ To compile this driver as a module, choose M here: the module will be called rivafb. +config FB_XBOX + tristate "nVidia Xbox support" + depends on FB && PCI && I2C_XBOX && EXPERIMENTAL + help + This driver supports the graphics chip of the Microsoft Xbox. + Say Y if you have an Xbox, N otherwise + + To compile this driver as a module, choose M here: the + module will be called xboxfb. + config FB_I810 tristate "Intel 810/815 support (EXPERIMENTAL)" depends on FB && AGP && AGP_INTEL && EXPERIMENTAL && PCI diff -urN linux-2.6.6.orig/drivers/video/Makefile linux-2.6.6/drivers/video/Makefile --- linux-2.6.6.orig/drivers/video/Makefile 2004-05-10 03:32:00.000000000 +0100 +++ linux-2.6.6/drivers/video/Makefile 2004-05-10 12:30:23.143952752 +0100 @@ -56,6 +56,7 @@ obj-$(CONFIG_FB_MATROX) += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o vgastate.o +obj-$(CONFIG_FB_XBOX) += xbox/ cfbimgblt.o vgastate.o obj-$(CONFIG_FB_SIS) += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_ATY) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_ATY128) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o diff -urN linux-2.6.6.orig/drivers/video/fbmem.c linux-2.6.6/drivers/video/fbmem.c --- linux-2.6.6.orig/drivers/video/fbmem.c 2004-05-10 03:31:55.000000000 +0100 +++ linux-2.6.6/drivers/video/fbmem.c 2004-05-10 12:30:23.151951536 +0100 @@ -123,6 +123,8 @@ extern int sgivwfb_setup(char*); extern int rivafb_init(void); extern int rivafb_setup(char*); +extern int xboxfb_init(void); +extern int xboxfb_setup(char*); extern int tdfxfb_init(void); extern int tdfxfb_setup(char*); extern int tridentfb_init(void); @@ -218,6 +220,9 @@ #ifdef CONFIG_FB_RIVA { "rivafb", rivafb_init, rivafb_setup }, #endif +#ifdef CONFIG_FB_XBOX + { "xboxfb", xboxfb_init, xboxfb_setup }, +#endif #ifdef CONFIG_FB_3DFX { "tdfxfb", tdfxfb_init, tdfxfb_setup }, #endif diff -urN linux-2.6.6.orig/drivers/video/xbox/Makefile linux-2.6.6/drivers/video/xbox/Makefile --- linux-2.6.6.orig/drivers/video/xbox/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/Makefile 2004-05-10 12:30:23.154951080 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the Xbox framebuffer driver +# + +obj-$(CONFIG_FB_XBOX) += xboxfb.o + +xboxfb-objs := fbdev.o riva_hw.o nv_driver.o encoder-i2c.o encoder.o focus.o conexant.o xlb.o diff -urN linux-2.6.6.orig/drivers/video/xbox/conexant.c linux-2.6.6/drivers/video/xbox/conexant.c --- linux-2.6.6.orig/drivers/video/xbox/conexant.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/conexant.c 2004-05-10 12:30:23.160950168 +0100 @@ -0,0 +1,639 @@ +/* + * linux/drivers/video/riva/conexant.c - Xbox driver for conexant chip + * + * Maintainer: Oliver Schwartz + * + * Contributors: + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * none + */ + +#include "conexant.h" +#include "focus.h" + +#define ADR(x) (x / 2 - 0x17) + +typedef struct { + long v_activeo; + long v_linesi; + long h_clki; + long h_clko; + long h_blanki; + long h_blanko; + long v_blanki; + long v_blanko; + long vscale; + double clk_ratio; +} xbox_tv_mode_parameter; + + + // and here is all the video timing for every standard + +static const conexant_video_parameter vidstda[] = { + { 3579545.00, 0.0000053, 0.00000782, 0.0000047, 0.000063555, 0.0000094, 0.000035667, 0.0000015, 243, 262.5, 0.0000092 }, + { 3579545.00, 0.0000053, 0.00000782, 0.0000047, 0.000064000, 0.0000094, 0.000035667, 0.0000015, 243, 262.5, 0.0000092 }, + { 4433618.75, 0.0000056, 0.00000785, 0.0000047, 0.000064000, 0.0000105, 0.000036407, 0.0000015, 288, 312.5, 0.0000105 }, + { 4433618.75, 0.0000056, 0.00000785, 0.0000047, 0.000064000, 0.0000094, 0.000035667, 0.0000015, 288, 312.5, 0.0000092 }, + { 3582056.25, 0.0000056, 0.00000811, 0.0000047, 0.000064000, 0.0000105, 0.000036407, 0.0000015, 288, 312.5, 0.0000105 }, + { 3575611.88, 0.0000058, 0.00000832, 0.0000047, 0.000063555, 0.0000094, 0.000035667, 0.0000015, 243, 262.5, 0.0000092 }, + { 4433619.49, 0.0000053, 0.00000755, 0.0000047, 0.000063555, 0.0000105, 0.000036407, 0.0000015, 243, 262.5, 0.0000092 } +}; + +static const unsigned char default_mode[] = { + 0x00, + 0x00, 0x28, 0x80, 0xE4, 0x00, 0x00, 0x80, 0x80, + 0x80, 0x13, 0xDA, 0x4B, 0x28, 0xA3, 0x9F, 0x25, + 0xA3, 0x9F, 0x25, 0x00, 0x00, 0x00, 0x00, 0x44, + 0xC7, 0x00, 0x00, 0x41, 0x35, 0x03, 0x46, 0x00, + 0x02, 0x00, 0x01, 0x60, 0x88, 0x8a, 0xa6, 0x68, + 0xc1, 0x2e, 0xf2, 0x27, 0x00, 0xb0, 0x0a, 0x0b, + 0x71, 0x5a, 0xe0, 0x36, 0x00, 0x50, 0x72, 0x1c, + 0x0d, 0x24, 0xf0, 0x58, 0x81, 0x49, 0x8c, 0x0c, + 0x8c, 0x79, 0x26, 0x52, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x9C, 0x9B, 0xC0, 0xC0, 0x19, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x57, 0x20, + 0x40, 0x6E, 0x7E, 0xF4, 0x51, 0x0F, 0xF1, 0x05, + 0xD3, 0x78, 0xA2, 0x25, 0x54, 0xA5, 0x00, 0x00 +}; + +static const double pll_base = 13.5e6; + +static void conexant_calc_blankings( + xbox_video_mode * mode, + xbox_tv_mode_parameter * param +); + +static int conexant_calc_mode_params( + xbox_video_mode * mode, + xbox_tv_mode_parameter * param +); + +static double fabs(double d) { + if (d > 0) return d; + else return -d; +} + +int conexant_calc_vga_mode( + xbox_av_type av_type, + unsigned char pll_int, + unsigned char * regs +){ + memset(regs, 0, NUM_CONEXANT_REGS); + // Protect against overclocking + if (pll_int > 36) { + pll_int = 36; // 36 / 6 * 13.5 MHz = 81 MHz, just above the limit. + } + if (pll_int == 0) { + pll_int = 1; // 0 will cause a burnout ... + } + if (av_type == AV_VGA) { + // use internal sync signals + regs[ADR(0x2e)] = 0xbd; // HDTV_EN = 1, RPR_SYNC_DIS = 1, BPB_SYNC_DIS = 1, GY_SYNC_DIS=1, HD_SYNC_EDGE = 1, RASTER_SEL = 01 + } + else { + // use sync on green + regs[ADR(0x2e)] = 0xad; // HDTV_EN = 1, RPR_SYNC_DIS = 1, BPB_SYNC_DIS = 1, HD_SYNC_EDGE = 1, RASTER_SEL = 01 + } + regs[ADR(0x32)] = 0x48; // DRVS = 2, IN_MODE[3] = 1; + regs[ADR(0x3c)] = 0x80; // MCOMPY + regs[ADR(0x3e)] = 0x80; // MCOMPU + regs[ADR(0x40)] = 0x80; // MCOMPV + regs[ADR(0xc6)] = 0x98; // IN_MODE = 24 bit RGB multiplexed + regs[ADR(0x6c)] = 0x46; // FLD_MODE = 10, EACTIVE = 1, EN_SCART = 0, EN_REG_RD = 1 + regs[ADR(0x9c)] = 0x00; // PLL_FRACT + regs[ADR(0x9e)] = 0x00; // PLL_FRACT + regs[ADR(0xa0)] = pll_int; // PLL_INT + regs[ADR(0xba)] = 0x28; // SLAVER = 1, DACDISD = 1 + regs[ADR(0xce)] = 0xe1; // OUT_MUXA = 01, OUT_MUXB = 00, OUT_MUXC = 10, OUT_MUXD = 11 + regs[ADR(0xd6)] = 0x0c; // OUT_MODE = 11 (RGB / SCART / HDTV) + + return 1; +} + +int conexant_calc_hdtv_mode( + xbox_hdtv_mode hdtv_mode, + unsigned char pll_int, + unsigned char * regs +){ + memset(regs, 0, NUM_CONEXANT_REGS); + // Protect against overclocking + if (pll_int > 36) { + pll_int = 36; // 36 / 6 * 13.5 MHz = 81 MHz, just above the limit. + } + if (pll_int == 0) { + pll_int = 1; // 0 will cause a burnout ... + } + switch (hdtv_mode) { + case HDTV_480p: + // use sync on green + regs[ADR(0x2e)] = 0xed; // HDTV_EN = 1, RGB2PRPB = 1, RPR_SYNC_DIS = 1, BPB_SYNC_DIS = 1, HD_SYNC_EDGE = 1, RASTER_SEL = 01 + regs[ADR(0x32)] = 0x48; // DRVS = 2, IN_MODE[3] = 1; + regs[ADR(0x3e)] = 0x45; // MCOMPU + regs[ADR(0x40)] = 0x51; // MCOMPV + break; + case HDTV_720p: + // use sync on green + regs[ADR(0x2e)] = 0xea; // HDTV_EN = 1, RGB2PRPB = 1, RPR_SYNC_DIS = 1, BPB_SYNC_DIS = 1, HD_SYNC_EDGE = 1, RASTER_SEL = 01 + regs[ADR(0x32)] = 0x49; // DRVS = 2, IN_MODE[3] = 1, CSC_SEL=1; + regs[ADR(0x3e)] = 0x45; // MCOMPU + regs[ADR(0x40)] = 0x51; // MCOMPV + break; + case HDTV_1080i: + // use sync on green + regs[ADR(0x2e)] = 0xeb; // HDTV_EN = 1, RGB2PRPB = 1, RPR_SYNC_DIS = 1, BPB_SYNC_DIS = 1, HD_SYNC_EDGE = 1, RASTER_SEL = 01 + regs[ADR(0x32)] = 0x49; // DRVS = 2, IN_MODE[3] = 1, CSC_SEL=1; + regs[ADR(0x3e)] = 0x48; // MCOMPU + regs[ADR(0x40)] = 0x5b; // MCOMPV + break; + } + regs[ADR(0x3c)] = 0x80; // MCOMPY + regs[ADR(0xa0)] = pll_int; // PLL_INT + regs[ADR(0xc6)] = 0x98; // IN_MODE = 24 bit RGB multiplexed + regs[ADR(0x6c)] = 0x46; // FLD_MODE = 10, EACTIVE = 1, EN_SCART = 0, EN_REG_RD = 1 + regs[ADR(0x9c)] = 0x00; // PLL_FRACT + regs[ADR(0x9e)] = 0x00; // PLL_FRACT + regs[ADR(0xba)] = 0x28; // SLAVER = 1, DACDISD = 1 + regs[ADR(0xce)] = 0xe1; // OUT_MUXA = 01, OUT_MUXB = 00, OUT_MUXC = 10, OUT_MUXD = 11 + regs[ADR(0xd6)] = 0x0c; // OUT_MODE = 11 (RGB / SCART / HDTV) + + return 1; +} + +int conexant_calc_mode(xbox_video_mode * mode, struct riva_regs * riva_out) +{ + unsigned char b; + unsigned int m = 0; + double dPllOutputFrequency; + xbox_tv_mode_parameter param; + char* regs = riva_out->encoder_mode; + + if (conexant_calc_mode_params(mode, ¶m)) + { + // copy default mode settings + memcpy(regs,default_mode,sizeof(default_mode)); + + regs[ADR(0x32)] = 0x28; // DRVS = 1, IN_MODE[3] = 1; + + // H_CLKI + b=regs[ADR(0x8e)]&(~0x07); + regs[ADR(0x8e)] = ((param.h_clki>>8)&0x07)|b; + regs[ADR(0x8a)] = ((param.h_clki)&0xff); + // H_CLKO + b=regs[ADR(0x86)]&(~0x0f); + regs[ADR(0x86)] = ((param.h_clko>>8)&0x0f)|b; + regs[ADR(0x76)] = ((param.h_clko)&0xff); + // V_LINESI + b=regs[ADR(0x38)]&(~0x02); + regs[ADR(0x38)] = ((param.v_linesi>>9)&0x02)|b; + b=regs[ADR(0x96)]&(~0x03); + regs[ADR(0x96)] = ((param.v_linesi>>8)&0x03)|b; + regs[ADR(0x90)] = ((param.v_linesi)&0xff); + // V_ACTIVEO + /* TODO: Absolutely not sure about other modes than plain NTSC / PAL */ + switch(mode->tv_encoding) { + case TV_ENC_NTSC: + case TV_ENC_NTSC60: + case TV_ENC_PALM: + case TV_ENC_PAL60: + m=param.v_activeo + 1; + break; + case TV_ENC_PALBDGHI: + m=param.v_activeo + 2; + break; + default: + m=param.v_activeo + 2; + break; + } + b=regs[ADR(0x86)]&(~0x80); + regs[ADR(0x86)] = ((m>>1)&0x80)|b; + regs[ADR(0x84)] = ((m)&0xff); + // H_ACTIVE + b=regs[ADR(0x86)]&(~0x70); + regs[ADR(0x86)] = (((mode->xres + 5)>>4)&0x70)|b; + regs[ADR(0x78)] = ((mode->xres + 5)&0xff); + // V_ACTIVEI + b=regs[ADR(0x96)]&(~0x0c); + regs[ADR(0x96)] = ((mode->yres>>6)&0x0c)|b; + regs[ADR(0x94)] = ((mode->yres)&0xff); + // H_BLANKI + b=regs[ADR(0x38)]&(~0x01); + regs[ADR(0x38)] = ((param.h_blanki>>9)&0x01)|b; + b=regs[ADR(0x8e)]&(~0x08); + regs[ADR(0x8e)] = ((param.h_blanki>>5)&0x08)|b; + regs[ADR(0x8c)] = ((param.h_blanki)&0xff); + // H_BLANKO + b=regs[ADR(0x9a)]&(~0xc0); + regs[ADR(0x9a)] = ((param.h_blanko>>2)&0xc0)|b; + regs[ADR(0x80)] = ((param.h_blanko)&0xff); + + // V_SCALE + b=regs[ADR(0x9a)]&(~0x3f); + regs[ADR(0x9a)] = ((param.vscale>>8)&0x3f)|b; + regs[ADR(0x98)] = ((param.vscale)&0xff); + // V_BLANKO + regs[ADR(0x82)] = ((param.v_blanko)&0xff); + // V_BLANKI + regs[ADR(0x92)] = ((param.v_blanki)&0xff); + { + unsigned int dwPllRatio, dwFract, dwInt; + // adjust PLL + dwPllRatio = (int)(6.0 * ((double)param.h_clko / vidstda[mode->tv_encoding].m_dSecHsyncPeriod) * + param.clk_ratio * 0x10000 / pll_base + 0.5); + dwInt = dwPllRatio / 0x10000; + dwFract = dwPllRatio - (dwInt * 0x10000); + b=regs[ADR(0xa0)]&(~0x3f); + regs[ADR(0xa0)] = ((dwInt)&0x3f)|b; + regs[ADR(0x9e)] = ((dwFract>>8)&0xff); + regs[ADR(0x9c)] = ((dwFract)&0xff); + // recalc value + dPllOutputFrequency = ((double)dwInt + ((double)dwFract)/65536.0)/(6 * param.clk_ratio / pll_base); + // enable 3:2 clocking mode + b=regs[ADR(0x38)]&(~0x20); + if (param.clk_ratio > 1.1) { + b |= 0x20; + } + regs[ADR(0x38)] = b; + + // update burst start position + m=(vidstda[mode->tv_encoding].m_dSecBurstStart) * dPllOutputFrequency + 0.5; + b=regs[ADR(0x38)]&(~0x04); + regs[ADR(0x38)] = ((m>>6)&0x04)|b; + regs[ADR(0x7c)] = (m&0xff); + // update burst end position (note +128 is in hardware) + m=(vidstda[mode->tv_encoding].m_dSecBurstEnd) * dPllOutputFrequency + 0.5; + if(m<128) m=128; + b=regs[ADR(0x38)]&(~0x08); + regs[ADR(0x38)] = (((m-128)>>5)&0x08)|b; + regs[ADR(0x7e)] = ((m-128)&0xff); + // update HSYNC width + m=(vidstda[mode->tv_encoding].m_dSecHsyncWidth) * dPllOutputFrequency + 0.5; + regs[ADR(0x7a)] = ((m)&0xff); + } + // adjust Subcarrier generation increment + { + unsigned int dwSubcarrierIncrement = (unsigned int) ( + (65536.0 * 65536.0) * ( + vidstda[mode->tv_encoding].m_dHzBurstFrequency + * vidstda[mode->tv_encoding].m_dSecHsyncPeriod + / (double)param.h_clko + ) + 0.5 + ); + regs[ADR(0xae)] = (dwSubcarrierIncrement&0xff); + regs[ADR(0xb0)] = ((dwSubcarrierIncrement>>8)&0xff); + regs[ADR(0xb2)] = ((dwSubcarrierIncrement>>16)&0xff); + regs[ADR(0xb4)] = ((dwSubcarrierIncrement>>24)&0xff); + } + // adjust WSS increment + { + unsigned int dwWssIncrement = 0; + + switch(mode->tv_encoding) { + case TV_ENC_NTSC: + case TV_ENC_NTSC60: + dwWssIncrement=(unsigned int) ((1048576.0 / ( 0.000002234 * dPllOutputFrequency))+0.5); + break; + case TV_ENC_PALBDGHI: + case TV_ENC_PALN: + case TV_ENC_PALNC: + case TV_ENC_PALM: + case TV_ENC_PAL60: + dwWssIncrement=(unsigned int) ((1048576.0 / ( 0.0000002 * dPllOutputFrequency))+0.5); + break; + default: + break; + } + + regs[ADR(0x66)] = (dwWssIncrement&0xff); + regs[ADR(0x68)] = ((dwWssIncrement>>8)&0xff); + regs[ADR(0x6a)] = ((dwWssIncrement>>16)&0xf); + } + // set mode register + b=regs[ADR(0xa2)]&(0x41); + switch(mode->tv_encoding) { + case TV_ENC_NTSC: + b |= 0x0a; // SETUP + VSYNC_DUR + break; + case TV_ENC_NTSC60: + b |= 0x08; // VSYNC_DUR + break; + case TV_ENC_PALBDGHI: + case TV_ENC_PALNC: + b |= 0x24; // PAL_MD + 625LINE + break; + case TV_ENC_PALN: + b |= 0x2e; // PAL_MD + SETUP + 625LINE + VSYNC_DUR + break; + case TV_ENC_PALM: + b |= 0x2a; // PAL_MD + SETUP + VSYNC_DUR + break; + case TV_ENC_PAL60: + b |= 0x28; // PAL_MD + VSYNC_DUR + break; + default: + break; + } + regs[ADR(0xa2)] = b; + regs[ADR(0xc6)] = 0x98; // IN_MODE = 24 bit RGB multiplexed + switch(mode->av_type) { + case AV_COMPOSITE: + case AV_SVIDEO: + regs[ADR(0x2e)] |= 0x40; // RGB2YPRPB = 1 + regs[ADR(0x6c)] = 0x46; // FLD_MODE = 10, EACTIVE = 1, EN_SCART = 0, EN_REG_RD = 1 + regs[ADR(0x5a)] = 0x00; // Y_OFF (Brightness) + regs[ADR(0xa4)] = 0xe5; // SYNC_AMP + regs[ADR(0xa6)] = 0x74; // BST_AMP + regs[ADR(0xba)] = 0x24; // SLAVER = 1, DACDISC = 1 + regs[ADR(0xce)] = 0x19; // OUT_MUXA = 01, OUT_MUXB = 10, OUT_MUXC = 10, OUT_MUXD = 00 + regs[ADR(0xd6)] = 0x00; // OUT_MODE = 00 (CVBS) + break; + case AV_SCART_RGB: + regs[ADR(0x6c)] = 0x4e; // FLD_MODE = 10, EACTIVE = 1, EN_SCART = 1, EN_REG_RD = 1 + regs[ADR(0x5a)] = 0xff; // Y_OFF (Brightness) + regs[ADR(0xa4)] = 0xe7; // SYNC_AMP + regs[ADR(0xa6)] = 0x77; // BST_AMP + regs[ADR(0xba)] = 0x20; // SLAVER = 1, enable all DACs + regs[ADR(0xce)] = 0xe1; // OUT_MUXA = 01, OUT_MUXB = 00, OUT_MUXC = 10, OUT_MUXD = 11 + regs[ADR(0xd6)] = 0x0c; // OUT_MODE = 11 (RGB / SCART / HDTV) + break; + default: + break; + } + riva_out->ext.vend = mode->yres; + riva_out->ext.vtotal = param.v_linesi - 1; + riva_out->ext.vcrtc = mode->yres; + riva_out->ext.vsyncstart = param.v_linesi - param.v_blanki; + riva_out->ext.vsyncend = riva_out->ext.vsyncstart + 3; + riva_out->ext.vvalidstart = 0; + riva_out->ext.vvalidend = mode->yres; + riva_out->ext.hend = mode->xres + 7; + riva_out->ext.htotal = param.h_clki - 1; + riva_out->ext.hcrtc = mode->xres - 1; + riva_out->ext.hsyncstart = param.h_clki - param.h_blanki - 7; + riva_out->ext.hsyncend = riva_out->ext.hsyncstart + 32; + riva_out->ext.hvalidstart = 0; + riva_out->ext.hvalidend = mode->xres - 1; + riva_out->ext.crtchdispend = mode->xres + 8; + riva_out->ext.crtcvstart = mode->yres + 34; + riva_out->ext.crtcvtotal = param.v_linesi + 32; + return 1; + } + else + { + return 0; + } +} + +static int conexant_calc_mode_params( + xbox_video_mode * mode, + xbox_tv_mode_parameter * param +){ + const double dMinHBT = 2.5e-6; // 2.5uSec time for horizontal syncing + const double invalidMetric = 1000; + + /* algorithm shamelessly ripped from nvtv/calc_bt.c */ + double dTempVOC = 0; + double dTempHOC = 0; + double dBestMetric = invalidMetric; + double dTempVSR = 0; + double dBestVSR = 0; + double dTempCLKRATIO = 1; + double dBestCLKRATIO = 1; + unsigned int minTLI = 0; + unsigned int maxTLI = 0; + unsigned int tempTLI = 0; + unsigned int bestTLI = 0; + unsigned int minHCLKO = 0; + unsigned int maxHCLKO = 0; + unsigned int minHCLKI = 0; + unsigned int tempHCLKI = 0; + unsigned int bestHCLKI = 0; + int actCLKRATIO; + unsigned int dTempHCLKO = 0; + double dTempVACTIVEO = 0; + double dDelta = 0; + double dMetric = 0; + double alo = vidstda[mode->tv_encoding].m_dwALO; + double tlo = vidstda[mode->tv_encoding].m_TotalLinesOut; + double tto = vidstda[mode->tv_encoding].m_dSecHsyncPeriod; + double ato = tto - (vidstda[mode->tv_encoding].m_dSecBlankBeginToHsync + vidstda[mode->tv_encoding].m_dSecActiveBegin); + + /* Range to search */ + double dMinHOC = mode->hoc - 0.02; + double dMaxHOC = mode->hoc + 0.02; + double dMinVOC = mode->voc - 0.02; + double dMaxVOC = mode->voc + 0.02; + + if (dMinHOC < 0) dMinHOC = 0; + if (dMinVOC < 0) dMinVOC = 0; + + minTLI= (unsigned int)(mode->yres / ((1 - dMinVOC) * alo) * tlo); + maxTLI = min((unsigned int)(mode->yres / ((1 - dMaxVOC) * alo) * tlo), (unsigned int)1023); + minHCLKO = (unsigned int) ((mode->xres * 2) / + ((1 - dMinHOC) * (ato / tto))); + maxHCLKO = (unsigned int) ((mode->xres * 2) / + ((1 - dMaxHOC) * (ato / tto))); + for (actCLKRATIO = 0; actCLKRATIO <= 1; actCLKRATIO++) + { + dTempCLKRATIO = 1.0; + if (actCLKRATIO) dTempCLKRATIO = 3.0/2.0; + for(tempTLI = minTLI; tempTLI <= maxTLI; tempTLI++) + { + dTempVSR = (double)tempTLI / tlo; + dTempVACTIVEO = (int)((((double)mode->yres * tlo) + + (tempTLI - 1)) / tempTLI); + dTempVOC = 1 - dTempVACTIVEO / alo; + + for(dTempHCLKO = minHCLKO; dTempHCLKO <= maxHCLKO; dTempHCLKO++) + { + tempHCLKI = (unsigned int)((dTempHCLKO * dTempCLKRATIO) * (tlo / tempTLI) + 0.5); + minHCLKI = ((dMinHBT / tto) * tempHCLKI) + mode->xres; + // check if solution is valid + if ((fabs((double)(tempTLI * tempHCLKI) - (tlo * dTempHCLKO * dTempCLKRATIO)) < 1e-3) && + (tempHCLKI >= minHCLKI) && (tempHCLKI < 2048)) + { + dTempHOC = 1 - (((double)mode->xres / ((double)dTempHCLKO / 2)) / + (ato / tto)); + dDelta = fabs(dTempHOC - mode->hoc) + fabs(dTempVOC - mode->voc); + dMetric = ((dTempHOC - mode->hoc) * (dTempHOC - mode->hoc)) + + ((dTempVOC - mode->voc) * (dTempVOC - mode->voc)) + + (2 * dDelta * dDelta); + if(dMetric < dBestMetric) + { + dBestVSR = dTempVSR; + dBestMetric = dMetric; + bestTLI = tempTLI; + bestHCLKI = tempHCLKI; + dBestCLKRATIO = dTempCLKRATIO; + } + } /* valid solution */ + } /* dTempHCLKO loop */ + } /* tempTLI loop */ + } /* CLKRATIO loop */ + + if(dBestMetric != invalidMetric) + { + param->v_linesi = bestTLI; + param->h_clki = bestHCLKI; + param->clk_ratio = dBestCLKRATIO; + param->v_activeo = (unsigned int)( + ( + (mode->yres * vidstda[mode->tv_encoding].m_TotalLinesOut) + + param->v_linesi - 1 + ) / param->v_linesi + ); + param->h_clko = (unsigned int)( + ( + (param->v_linesi * param->h_clki) / + (vidstda[mode->tv_encoding].m_TotalLinesOut * param->clk_ratio) + ) + + 0.5 + ); + conexant_calc_blankings(mode, param); + return 1; + } + else + { + return 0; + } +} + +static void conexant_calc_blankings( + xbox_video_mode * mode, + xbox_tv_mode_parameter * param +){ + double dTotalHBlankI; + double dFrontPorchIn; + double dFrontPorchOut; + double dMinFrontPorchIn; + double dBackPorchIn; + double dBackPorchOut; + double dTotalHBlankO; + double dHeadRoom; + double dMaxHsyncDrift; + double dFifoMargin; + double vsrq; + double dMaxHR; + double tlo = vidstda[mode->tv_encoding].m_TotalLinesOut; + const int MFP = 14; // Minimum front porch + const int MBP = 4; // Minimum back porch + const int FIFO_SIZE = 1024; + double vsr = (double)param->v_linesi / vidstda[mode->tv_encoding].m_TotalLinesOut; + + // H_BLANKO + param->h_blanko = 2 * (int)( + vidstda[mode->tv_encoding].m_dSecImageCentre / (2 * vidstda[mode->tv_encoding].m_dSecHsyncPeriod) * + param->h_clko + + 0.5 + ) - mode->xres + 15; + + // V_BLANKO + switch (mode->tv_encoding) { + case TV_ENC_NTSC: + case TV_ENC_NTSC60: + case TV_ENC_PAL60: + case TV_ENC_PALM: + param->v_blanko = (int)( 140 - ( param->v_activeo / 2.0 ) + 0.5 ); + break; + default: + param->v_blanko = (int)( 167 - ( param->v_activeo / 2.0 ) + 0.5 ); + break; + } + + // V_BLANKI + vsrq = ( (int)( vsr * 4096.0 + .5 ) ) / 4096.0; + param->vscale = (int)( ( vsr - 1 ) * 4096 + 0.5 ); + if( vsrq < vsr ) + { + // These calculations are in units of dHCLKO + dMaxHsyncDrift = ( vsrq - vsr ) * tlo / vsr * param->h_clko; + dMinFrontPorchIn = MFP / ( (double)param->h_clki * vsr ) * param->h_clko; + dFrontPorchOut = param->h_clko - param->h_blanko - mode->xres * 2; + dFifoMargin = ( FIFO_SIZE - mode->xres ) * 2; + + // Check for fifo overflow + if( dFrontPorchOut + dFifoMargin < -dMaxHsyncDrift + dMinFrontPorchIn ) + { + dTotalHBlankO = param->h_clko - mode->xres * 2; + dTotalHBlankI = ( (double)param->h_clki - (double)mode->xres ) / param->h_clki / vsr * param->h_clko; + + // Try forcing the Hsync drift the opposite direction + dMaxHsyncDrift = ( vsrq + 1.0 / 4096 - vsr ) * tlo / vsr * param->h_clko; + + // Check that fifo overflow and underflow can be avoided + if( dTotalHBlankO + dFifoMargin >= dTotalHBlankI + dMaxHsyncDrift ) + { + vsrq = vsrq + 1.0 / 4096; + param->vscale = (int)( ( vsrq - 1 ) * 4096 ); + } + + // NOTE: If fifo overflow and underflow can't be avoided, + // alternative overscan compensation ratios should + // be selected and all calculations repeated. If + // that is not feasible, the calculations for + // H_BLANKI below will delay the overflow or under- + // flow as much as possible, to minimize the visible + // artifacts. + } + } + + param->v_blanki = (int)( ( param->v_blanko - 1 ) * vsrq ); + + // H_BLANKI + + // These calculations are in units of dHCLKI + dTotalHBlankI = param->h_clki - mode->xres; + dFrontPorchIn = max( (double)MFP, min( dTotalHBlankI / 8.0, dTotalHBlankI - (double)MBP ) ); + dBackPorchIn = dTotalHBlankI - dFrontPorchIn; + dMaxHsyncDrift = ( vsrq - vsr ) * tlo * param->h_clki; + dTotalHBlankO = ( param->h_clko - mode->xres * 2.0 ) / param->h_clko * vsr * param->h_clki; + dBackPorchOut = ((double)param->h_blanko) / (double)param->h_clko * vsr * param->h_clki; + dFrontPorchOut = dTotalHBlankO - dBackPorchOut; + dFifoMargin = ( FIFO_SIZE - mode->xres ) * 2.0 / param->h_clko * vsr * param->h_clki; + // This may be excessive, but is adjusted by the code. + dHeadRoom = 32.0; + + // Check that fifo overflow and underflow can be avoided + if( ( dTotalHBlankO + dFifoMargin ) >= ( dTotalHBlankI + fabs( dMaxHsyncDrift ) ) ) + { + dMaxHR = ( dTotalHBlankO + dFifoMargin ) - ( dTotalHBlankI - fabs( dMaxHsyncDrift ) ); + if( dMaxHR < ( dHeadRoom * 2.0 ) ) + { + dHeadRoom = (int)( dMaxHR / 2.0); + } + + // Check for overflow + if( ( ( dFrontPorchOut + dFifoMargin ) - dHeadRoom ) < ( dFrontPorchIn - min( dMaxHsyncDrift, 0.0 ) ) ) + { + dFrontPorchIn = max( (double)MFP, ( dFrontPorchOut + dFifoMargin + min( dMaxHsyncDrift, 0.0 ) - dHeadRoom ) ); + dBackPorchIn = dTotalHBlankI - dFrontPorchIn; + } + + // Check for underflow + if( dBackPorchOut - dHeadRoom < dBackPorchIn + max( dMaxHsyncDrift, 0.0 ) ) + { + dBackPorchIn = max( (double)MBP, ( dBackPorchOut - max( dMaxHsyncDrift, 0.0 ) - dHeadRoom ) ); + dFrontPorchIn = dTotalHBlankI - dBackPorchIn; + } + } + else if( dMaxHsyncDrift < 0 ) + { + // Delay the overflow as long as possible + dBackPorchIn = min( ( dBackPorchOut - 1 ), ( dTotalHBlankI - MFP ) ); + dFrontPorchIn = dTotalHBlankI - dBackPorchIn; + } + else + { + // Delay the underflow as long as possible + dFrontPorchIn = min( ( dFrontPorchOut + dFifoMargin - 1 ), ( dTotalHBlankI - MBP ) ); + dBackPorchIn = dTotalHBlankI - dFrontPorchIn; + } + + param->h_blanki = (int)( dBackPorchIn ); + +} diff -urN linux-2.6.6.orig/drivers/video/xbox/conexant.h linux-2.6.6/drivers/video/xbox/conexant.h --- linux-2.6.6.orig/drivers/video/xbox/conexant.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/conexant.h 2004-05-10 12:30:23.162949864 +0100 @@ -0,0 +1,28 @@ +/* + * linux/drivers/video/riva/conexant.h - Xbox driver for conexant chip + * + * Maintainer: Oliver Schwartz + * + * Contributors: + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * none + */ + +#ifndef conexant_h +#define conexant_h + +#include +#include "xboxfb.h" +#include "encoder.h" + +int conexant_calc_mode(xbox_video_mode * mode, struct riva_regs * riva_out); +int conexant_calc_vga_mode(xbox_av_type av_type, unsigned char pll_int, unsigned char * mode_out); +int conexant_calc_hdtv_mode(xbox_hdtv_mode hdtv_mode, unsigned char pll_int, unsigned char * mode_out); + +#endif diff -urN linux-2.6.6.orig/drivers/video/xbox/encoder-i2c.c linux-2.6.6/drivers/video/xbox/encoder-i2c.c --- linux-2.6.6.orig/drivers/video/xbox/encoder-i2c.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/encoder-i2c.c 2004-05-10 12:30:23.164949560 +0100 @@ -0,0 +1,203 @@ +/* + * linux/drivers/video/riva/encoder-i2c.c - Xbox I2C driver for encoder chip + * + * Maintainer: Oliver Schwartz + * + * Contributors: + * + * Most of the code was stolen from extsmi.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * none + */ + +#include +#include +#include +#include + +#define CONEXANT_ADDRESS 0x45 +#define FOCUS_ADDRESS 0x6a +#define XLB_ADDRESS 0x70 +#define EEPROM_ADDRESS 0x54 +#define PIC_ADDRESS 0x10 + +#define DRIVER_NAME "xbox-tv-i2c" + +extern int __init i2c_xbox_init(void); + +static int tv_attach_adapter(struct i2c_adapter *adap); + +static struct i2c_driver tv_driver = { + .name = "i2c xbox conexant driver", + .id = I2C_DRIVERID_I2CDEV, + .flags = I2C_DF_NOTIFY, + .attach_adapter = tv_attach_adapter, +}; + +static struct i2c_client pic_client = { + .name = "I2C xbox pic client", + .id = 2, + .flags = 0, + .addr = PIC_ADDRESS, + .adapter = NULL, + .driver = &tv_driver, +}; + +static struct i2c_client conexant_client = { + .name = "I2C xbox conexant client", + .id = 1, + .flags = 0, + .addr = CONEXANT_ADDRESS, + .adapter = NULL, + .driver = &tv_driver, +}; + +static struct i2c_client focus_client = { + .name = "I2C xbox focus client", + .id = 1, + .flags = 0, + .addr = FOCUS_ADDRESS, + .adapter = NULL, + .driver = &tv_driver, +}; + +static struct i2c_client xlb_client = { + .name = "I2C xbox XLB client", + .id = 1, + .flags = 0, + .addr = XLB_ADDRESS, + .adapter = NULL, + .driver = &tv_driver, +}; + +static struct i2c_client eeprom_client = { + .name = "I2C xbox eeprom client", + .id = 3, + .flags = 0, + .addr = EEPROM_ADDRESS, + .adapter = NULL, + .driver = &tv_driver, +}; + +static int tv_attach_adapter(struct i2c_adapter *adap) +{ + int i; + + if ((i = i2c_adapter_id(adap)) < 0) { + printk("i2c-dev.o: Unknown adapter ?!?\n"); + return -ENODEV; + } + + printk(KERN_INFO DRIVER_NAME ": Using '%s'!\n",adap->name); + conexant_client.adapter = adap; + focus_client.adapter = adap; + xlb_client.adapter = adap; + pic_client.adapter = adap; + eeprom_client.adapter = adap; + i2c_attach_client(&conexant_client); + i2c_attach_client(&focus_client); + i2c_attach_client(&xlb_client); + i2c_attach_client(&pic_client); + i2c_attach_client(&eeprom_client); + + return 0; +} + +int tv_i2c_init(void) { + int res; + i2c_xbox_init(); + if ((res = i2c_add_driver(&tv_driver))) { + printk(KERN_ERR DRIVER_NAME ": XBox tv driver registration failed.\n"); + return res; + } + return 0; +} + +int conexant_i2c_read_reg(unsigned char adr) { + if (!conexant_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No conexant client attached.\n"); + return -1; + } + udelay(500); + return i2c_smbus_read_byte_data(&conexant_client, adr); +} + +int conexant_i2c_write_reg(unsigned char adr, unsigned char value) { + if (!conexant_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No conexant client attached.\n"); + return -1; + } + udelay(500); + return i2c_smbus_write_byte_data(&conexant_client, adr, value); +} + +int focus_i2c_read_reg(unsigned char adr) { + if (!focus_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No focus client attached.\n"); + return -1; + } + udelay(500); + return i2c_smbus_read_byte_data(&focus_client, adr); +} + +int focus_i2c_write_reg(unsigned char adr, unsigned char value) { + if (!focus_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No focus client attached.\n"); + return -1; + } + udelay(500); + return i2c_smbus_write_byte_data(&focus_client, adr, value); +} + +int xlb_i2c_read_reg(unsigned char adr) { + if (!xlb_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No XLB client attached.\n"); + return -1; + } + udelay(500); + return i2c_smbus_read_byte_data(&xlb_client, adr); +} + +int xlb_i2c_write_reg(unsigned char adr, unsigned char value) { + if (!xlb_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No XLB client attached.\n"); + return -1; + } + udelay(500); + return i2c_smbus_write_byte_data(&xlb_client, adr, value); +} + +unsigned char pic_i2c_read_reg(unsigned char adr) { + if (!pic_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No pic client attached.\n"); + return 0; + } + udelay(500); + return (unsigned char)i2c_smbus_read_byte_data(&pic_client, adr); +} + +unsigned char eeprom_i2c_read(unsigned char adr) { + if (!eeprom_client.adapter) { + printk(KERN_ERR DRIVER_NAME " : No eeprom client attached.\n"); + return 0; + } + udelay(500); + return (unsigned char)i2c_smbus_read_byte_data(&eeprom_client, adr); +} + +void tv_i2c_exit(void){ + int res; + + if ((res = i2c_del_driver(&tv_driver))) { + printk(KERN_ERR DRIVER_NAME ": XBox tv Driver deregistration failed, " + "module not removed.\n"); + } + return; +} + diff -urN linux-2.6.6.orig/drivers/video/xbox/encoder-i2c.h linux-2.6.6/drivers/video/xbox/encoder-i2c.h --- linux-2.6.6.orig/drivers/video/xbox/encoder-i2c.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/encoder-i2c.h 2004-05-10 12:30:23.166949256 +0100 @@ -0,0 +1,31 @@ +/* + * linux/drivers/video/riva/encoder-i2c.h - Xbox I2C driver for encoder chip + * + * Maintainer: Oliver Schwartz + * + * Contributors: + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * none + */ + +#ifndef encoder_i2c_h +#define encoder_i2c_h + +int tv_i2c_init(void); +void tv_i2c_exit(void); +int conexant_i2c_read_reg(unsigned char adr); +int conexant_i2c_write_reg(unsigned char adr, unsigned char value); +int focus_i2c_read_reg(unsigned char adr); +int focus_i2c_write_reg(unsigned char adr, unsigned char value); +int xlb_i2c_read_reg(unsigned char adr); +int xlb_i2c_write_reg(unsigned char adr, unsigned char value); +unsigned char pic_i2c_read_reg(unsigned char adr); +unsigned char eeprom_i2c_read(unsigned char adr); + +#endif diff -urN linux-2.6.6.orig/drivers/video/xbox/encoder.c linux-2.6.6/drivers/video/xbox/encoder.c --- linux-2.6.6.orig/drivers/video/xbox/encoder.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/encoder.c 2004-05-10 12:30:23.169948800 +0100 @@ -0,0 +1,174 @@ +/* + * linux/drivers/video/riva/encoder.c - Xbox driver for encoder chip + * + * Maintainer: Oliver Schwartz + * + * Contributors: + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * none + */ + +#include "encoder-i2c.h" +#include "encoder.h" +#include "focus.h" +#include + +#define ADR(x) (x / 2 - 0x17) + +static const conexant_video_parameter vidstda[] = { + { 3579545.00, 0.0000053, 0.00000782, 0.0000047, 0.000063555, 0.0000094, 0.000035667, 0.0000015, 243, 262.5, 0.0000092 }, + { 3579545.00, 0.0000053, 0.00000782, 0.0000047, 0.000064000, 0.0000094, 0.000035667, 0.0000015, 243, 262.5, 0.0000092 }, + { 4433618.75, 0.0000056, 0.00000785, 0.0000047, 0.000064000, 0.0000105, 0.000036407, 0.0000015, 288, 312.5, 0.0000105 }, + { 4433618.75, 0.0000056, 0.00000785, 0.0000047, 0.000064000, 0.0000094, 0.000035667, 0.0000015, 288, 312.5, 0.0000092 }, + { 3582056.25, 0.0000056, 0.00000811, 0.0000047, 0.000064000, 0.0000105, 0.000036407, 0.0000015, 288, 312.5, 0.0000105 }, + { 3575611.88, 0.0000058, 0.00000832, 0.0000047, 0.000063555, 0.0000094, 0.000035667, 0.0000015, 243, 262.5, 0.0000092 }, + { 4433619.49, 0.0000053, 0.00000755, 0.0000047, 0.000063555, 0.0000105, 0.000036407, 0.0000015, 243, 262.5, 0.0000092 } +}; + + +static const double pll_base = 13.5e6; + +xbox_encoder_type tv_get_video_encoder(void) { + unsigned char b = 0; + + b = conexant_i2c_read_reg(0x00); + if(b != 255) { + return ENCODER_CONEXANT; + } + b = focus_i2c_read_reg(0x00); + if(b != 255) { + return ENCODER_FOCUS; + } + b = xlb_i2c_read_reg(0x00); + if(b != 255) { + return ENCODER_XLB; + } + return 0; +} + +int tv_init(void) { + return tv_i2c_init(); +} + +void tv_exit(void) { + tv_i2c_exit(); +} + +void tv_load_mode(unsigned char * mode) { + int n, n1; + unsigned char b; + + switch (tv_get_video_encoder()) { + case ENCODER_CONEXANT: + conexant_i2c_write_reg(0xc4, 0x00); // EN_OUT = 1 + + // Conexant init (starts at register 0x2e) + n1=0; + for(n=0x2e;n<0x100;n+=2) { + switch(n) { + case 0x6c: // reset + conexant_i2c_write_reg(n, mode[n1] & 0x7f); + break; + case 0xc4: // EN_OUT + conexant_i2c_write_reg(n, mode[n1] & 0xfe); + break; + case 0xb8: // autoconfig + break; + + default: + conexant_i2c_write_reg(n, mode[n1]); + break; + } + n1++; + } + // Timing Reset + b=conexant_i2c_read_reg(0x6c) & (0x7f); + conexant_i2c_write_reg(0x6c, 0x80|b); + b=conexant_i2c_read_reg(0xc4) & (0xfe); + conexant_i2c_write_reg(0xc4, 0x01|b); // EN_OUT = 1 + + /* + conexant_i2c_write_reg(0xA8, (0xD9/1.3)); + conexant_i2c_write_reg(0xAA, (0x9A/1.3)); + conexant_i2c_write_reg(0xAC, (0xA4/1.3)); + */ + + conexant_i2c_write_reg(0xA8, 0x81); + conexant_i2c_write_reg(0xAA, 0x49); + conexant_i2c_write_reg(0xAC, 0x8C); + break; + case ENCODER_FOCUS: + //Set the command register soft reset + focus_i2c_write_reg(0x0c,0x03); + focus_i2c_write_reg(0x0d,0x21); + + for (n = 0; n<0xc4; n++) { + focus_i2c_write_reg(n,mode[n]); + } + //Clear soft reset flag + b = focus_i2c_read_reg(0x0c); + b &= ~0x01; + focus_i2c_write_reg(0x0c,b); + b = focus_i2c_read_reg(0x0d); + focus_i2c_write_reg(0x0d,b); + break; + case ENCODER_XLB: + //Nothing yet + break; + } +} + +void tv_save_mode(unsigned char * mode) { + int n, n1; + switch (tv_get_video_encoder()) { + case ENCODER_CONEXANT: + // Conexant init (starts at register 0x2e) + n1=0; + for(n=0x2e;n<0x100;n+=2) { + mode[n1] = conexant_i2c_read_reg(n); + n1++; + } + break; + case ENCODER_FOCUS: + for (n=0;n<0xc4;n++) { + mode[n] = focus_i2c_read_reg(n); + } + break; + case ENCODER_XLB: + break; + } +} + +xbox_tv_encoding get_tv_encoding(void) { + unsigned char eeprom_value; + xbox_tv_encoding enc = TV_ENC_PALBDGHI; + eeprom_value = eeprom_i2c_read(0x5a); + if (eeprom_value == 0x40) { + enc = TV_ENC_NTSC; + } + else { + enc = TV_ENC_PALBDGHI; + } + return enc; +} + +xbox_av_type detect_av_type(void) { + xbox_av_type avType; + switch (pic_i2c_read_reg(0x04)) { + case 0: avType = AV_SCART_RGB; break; + case 1: avType = AV_HDTV; break; + case 2: avType = AV_VGA_SOG; break; + case 4: avType = AV_SVIDEO; break; + case 6: avType = AV_COMPOSITE; break; + case 7: avType = AV_VGA; break; + default: avType = AV_COMPOSITE; break; + } + return avType; +} + diff -urN linux-2.6.6.orig/drivers/video/xbox/encoder.h linux-2.6.6/drivers/video/xbox/encoder.h --- linux-2.6.6.orig/drivers/video/xbox/encoder.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/encoder.h 2004-05-10 12:30:23.171948496 +0100 @@ -0,0 +1,64 @@ +/* + * linux/drivers/video/riva/encoder.h - Xbox driver for encoder chip + * + * Maintainer: Oliver Schwartz + * + * Contributors: + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * none + */ + + +#ifndef encoder_h +#define encoder_h + +#include + +typedef struct { + double m_dHzBurstFrequency; + double m_dSecBurstStart; + double m_dSecBurstEnd; + double m_dSecHsyncWidth; + double m_dSecHsyncPeriod; + double m_dSecActiveBegin; + double m_dSecImageCentre; + double m_dSecBlankBeginToHsync; + unsigned int m_dwALO; + double m_TotalLinesOut; + double m_dSecHsyncToBlankEnd; +} conexant_video_parameter; + +typedef struct _xbox_video_mode { + int xres; + int yres; + int bpp; + double hoc; + double voc; + xbox_av_type av_type; + xbox_tv_encoding tv_encoding; +} xbox_video_mode; + +typedef enum enumHdtvModes { + HDTV_480p, + HDTV_720p, + HDTV_1080i +} xbox_hdtv_mode; + +static const conexant_video_parameter vidstda[]; + +int tv_init(void); +void tv_exit(void); +xbox_encoder_type tv_get_video_encoder(void); + +void tv_save_mode(unsigned char * mode_out); +void tv_load_mode(unsigned char * mode); +xbox_tv_encoding get_tv_encoding(void); +xbox_av_type detect_av_type(void); + +#endif diff -urN linux-2.6.6.orig/drivers/video/xbox/fbdev.c linux-2.6.6/drivers/video/xbox/fbdev.c --- linux-2.6.6.orig/drivers/video/xbox/fbdev.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/fbdev.c 2004-05-10 12:30:23.191945456 +0100 @@ -0,0 +1,2254 @@ +/* + * linux/drivers/video/riva/fbdev.c - nVidia Xbox fb driver + * + * Maintained by Oliver Schwartz + * + * Based on the nVidia RIVA 128/TNT/TNT2 fb driver, maintained by + * Ani Joshi + * + * Copyright 1999-2000 Jeff Garzik + * + * Contributors: + * + * Ani Joshi: Lots of debugging and cleanup work, really helped + * get the driver going + * + * Ferenc Bakonyi: Bug fixes, cleanup, modularization + * + * Jindrich Makovicka: Accel code help, hw cursor, mtrr + * + * Paul Richards: Bug fixes, updates + * + * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven + * Includes riva_hw.c from nVidia, see copyright below. + * KGI code provided the basis for state storage, init, and mode switching. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * restoring text mode fails + * doublescan modes are broken + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MTRR +#include +#endif +#ifdef CONFIG_PPC_OF +#include +#include +#endif + +#include "xboxfb.h" +#include "nvreg.h" +#include +#include +#include +#include "encoder-i2c.h" +#include "conexant.h" +#include "focus.h" +#include "xlb.h" + +#ifndef CONFIG_PCI /* sanity check */ +#error This driver requires PCI support. +#endif + +/* version number of this driver */ +#define RIVAFB_VERSION "0.9.5b" + +/* ------------------------------------------------------------------------- * + * + * various helpful macros and constants + * + * ------------------------------------------------------------------------- */ + +#undef RIVAFBDEBUG +#ifdef RIVAFBDEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#ifndef RIVA_NDEBUG +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n",\ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + BUG(); \ + } +#else +#define assert(expr) +#endif + +#define PFX "xboxfb: " + +/* macro that allows you to set overflow bits */ +#define SetBitField(value,from,to) SetBF(to,GetBF(value,from)) +#define SetBit(n) (1<<(n)) +#define Set8Bits(value) ((value)&0xff) + +/* HW cursor parameters */ +#define MAX_CURS 32 + +/* ------------------------------------------------------------------------- * + * + * prototypes + * + * ------------------------------------------------------------------------- */ + +static int xboxfb_blank(int blank, struct fb_info *info); + +/* ------------------------------------------------------------------------- * + * + * card identification + * + * ------------------------------------------------------------------------- */ + +enum riva_chips { + CH_GEFORCE3_XBOX +}; + +/* directly indexed by riva_chips enum, above */ +static struct riva_chip_info { + const char *name; + unsigned arch_rev; +} riva_chip_info[] __initdata = { + { "GeForce3", NV_ARCH_20} +}; + +static struct pci_device_id xboxfb_pci_tbl[] = { + { PCI_VENDOR_ID_NVIDIA, 0x2a0, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_XBOX }, + { 0, } /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, xboxfb_pci_tbl); + +/* ------------------------------------------------------------------------- * + * + * global variables + * + * ------------------------------------------------------------------------- */ + +/* command line data, set in xboxfb_setup() */ +static u32 pseudo_palette[17]; +static int flatpanel __initdata = -1; /* Autodetect later */ +static int forceCRTC __initdata = -1; +#ifdef CONFIG_MTRR +static int nomtrr __initdata = 0; +#endif + +#ifndef MODULE +static char *mode_option __initdata = NULL; +#endif + +static xbox_tv_encoding tv_encoding __initdata = TV_ENC_INVALID; +static xbox_av_type av_type __initdata = AV_INVALID; +static int hoc __initdata = -1; +static int voc __initdata = -1; + +static struct fb_fix_screeninfo xboxfb_fix = { + .id = "Xbox", + .type = FB_TYPE_PACKED_PIXELS, + .xpanstep = 1, + .ypanstep = 1, +}; + +static struct fb_var_screeninfo xboxfb_default_var = { + .xres = 640, + .yres = 480, + .xres_virtual = 640, + .yres_virtual = 480, + .bits_per_pixel = 8, + .red = {0, 8, 0}, + .green = {0, 8, 0}, + .blue = {0, 8, 0}, + .transp = {0, 0, 0}, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .accel_flags = FB_ACCELF_TEXT, + .pixclock = 39721, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED +}; + +static struct fb_var_screeninfo xboxfb_mode_480p = { + .xres = 720, + .yres = 480, + .xres_virtual = 720, + .yres_virtual = 480, + .bits_per_pixel = 32, + .red = {0, 8, 16}, + .green = {0, 8, 8}, + .blue = {0, 8, 0}, + .transp = {0, 0, 0}, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .accel_flags = FB_ACCELF_TEXT, + .pixclock = 37000, + .left_margin = 56, + .right_margin = 18, + .upper_margin = 29, + .lower_margin = 9, + .hsync_len = 64, + .vsync_len = 7, + .vmode = FB_VMODE_NONINTERLACED +}; + +static struct fb_var_screeninfo xboxfb_mode_720p = { + .xres = 1280, + .yres = 720, + .xres_virtual = 1280, + .yres_virtual = 720, + .bits_per_pixel = 8, + .red = {0, 8, 0}, + .green = {0, 8, 0}, + .blue = {0, 8, 0}, + .transp = {0, 0, 0}, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .accel_flags = FB_ACCELF_TEXT, + .pixclock = 13468, + .left_margin = 220, + .right_margin = 70, + .upper_margin = 22, + .lower_margin = 3, + .hsync_len = 80, + .vsync_len = 5, + .vmode = FB_VMODE_NONINTERLACED +}; + +static const char* tvEncodingNames[] = { + "NTSC", + "NTSC-60", + "PAL-BDGHI", + "PAL-N", + "PAL-NC", + "PAL-M", + "PAL-60" +}; + +static const char* avTypeNames[] = { + "SCART (RGB)", + "S-Video", + "VGA (Sync on green)", + "HDTV (Component video)", + "Composite", + "VGA (internal syncs)" +}; + +/* from GGI */ +static const struct riva_regs reg_template = { + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */ + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x01, 0x0F, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CRT */ + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, /* 0x10 */ + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */ + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, /* 0x40 */ + }, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, /* GRA */ + 0xFF}, + {0x03, 0x01, 0x0F, 0x00, 0x0E}, /* SEQ */ + 0xEB /* MISC */ +}; + +/* ------------------------------------------------------------------------- * + * + * MMIO access macros + * + * ------------------------------------------------------------------------- */ + +static inline void CRTCout(struct riva_par *par, unsigned char index, + unsigned char val) +{ + VGA_WR08(par->riva.PCIO, 0x3d4, index); + VGA_WR08(par->riva.PCIO, 0x3d5, val); +} + +static inline unsigned char CRTCin(struct riva_par *par, + unsigned char index) +{ + VGA_WR08(par->riva.PCIO, 0x3d4, index); + return (VGA_RD08(par->riva.PCIO, 0x3d5)); +} + +static inline void GRAout(struct riva_par *par, unsigned char index, + unsigned char val) +{ + VGA_WR08(par->riva.PVIO, 0x3ce, index); + VGA_WR08(par->riva.PVIO, 0x3cf, val); +} + +static inline unsigned char GRAin(struct riva_par *par, + unsigned char index) +{ + VGA_WR08(par->riva.PVIO, 0x3ce, index); + return (VGA_RD08(par->riva.PVIO, 0x3cf)); +} + +static inline void SEQout(struct riva_par *par, unsigned char index, + unsigned char val) +{ + VGA_WR08(par->riva.PVIO, 0x3c4, index); + VGA_WR08(par->riva.PVIO, 0x3c5, val); +} + +static inline unsigned char SEQin(struct riva_par *par, + unsigned char index) +{ + VGA_WR08(par->riva.PVIO, 0x3c4, index); + return (VGA_RD08(par->riva.PVIO, 0x3c5)); +} + +static inline void ATTRout(struct riva_par *par, unsigned char index, + unsigned char val) +{ + VGA_WR08(par->riva.PCIO, 0x3c0, index); + VGA_WR08(par->riva.PCIO, 0x3c0, val); +} + +static inline unsigned char ATTRin(struct riva_par *par, + unsigned char index) +{ + VGA_WR08(par->riva.PCIO, 0x3c0, index); + return (VGA_RD08(par->riva.PCIO, 0x3c1)); +} + +static inline void MISCout(struct riva_par *par, unsigned char val) +{ + VGA_WR08(par->riva.PVIO, 0x3c2, val); +} + +static inline unsigned char MISCin(struct riva_par *par) +{ + return (VGA_RD08(par->riva.PVIO, 0x3cc)); +} + +static u8 byte_rev[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +static inline void reverse_order(u32 *l) +{ + u8 *a = (u8 *)l; + *a = byte_rev[*a], a++; + *a = byte_rev[*a], a++; + *a = byte_rev[*a], a++; + *a = byte_rev[*a]; +} + +/* ------------------------------------------------------------------------- * + * + * cursor stuff + * + * ------------------------------------------------------------------------- */ + +/** + * xboxfb_load_cursor_image - load cursor image to hardware + * @data: address to monochrome bitmap (1 = foreground color, 0 = background) + * @par: pointer to private data + * @w: width of cursor image in pixels + * @h: height of cursor image in scanlines + * @bg: background color (ARGB1555) - alpha bit determines opacity + * @fg: foreground color (ARGB1555) + * + * DESCRIPTiON: + * Loads cursor image based on a monochrome source and mask bitmap. The + * image bits determines the color of the pixel, 0 for background, 1 for + * foreground. Only the affected region (as determined by @w and @h + * parameters) will be updated. + * + * CALLED FROM: + * xboxfb_cursor() + */ +static void xboxfb_load_cursor_image(struct riva_par *par, u8 *data, + u8* mask, u16 bg, u16 fg, u32 w, u32 h) +{ + int i, j, k = 0; + u32 b, m, tmp; + + for (i = 0; i < h; i++) { + b = *((u32 *)data); + data = (u8 *)((u32 *)data + 1); + m = *((u32 *)mask); + mask = (u8 *)((u32 *)mask + 1); + reverse_order(&b); + + for (j = 0; j < w/2; j++) { + tmp = 0; +#if defined (__BIG_ENDIAN) + tmp = (b & (1 << 31)) ? fg << 16 : bg << 16; + if (m & (1 << 31)) { + tmp |= 1 << 31; + } + b <<= 1; + m <<= 1; + + tmp |= (b & (1 << 31)) ? fg : bg; + if (m & (1 << 31)) { + tmp |= 1 << 15; + } + b <<= 1; + m <<= 1; +#else + tmp = (b & 1) ? fg : bg; + if (m & 1) { + tmp |= 1 << 15; + } + b >>= 1; + m >>= 1; + + tmp |= (b & 1) ? fg << 16 : bg << 16; + if (m & 1) { + tmp |= 1 << 31; + } + b >>= 1; + m >>= 1; +#endif + writel(tmp, par->riva.CURSOR + k++); + } + k += (MAX_CURS - w)/2; + } +} + +/* ------------------------------------------------------------------------- * + * + * general utility functions + * + * ------------------------------------------------------------------------- */ + +/** + * riva_wclut - set CLUT entry + * @chip: pointer to RIVA_HW_INST object + * @regnum: register number + * @red: red component + * @green: green component + * @blue: blue component + * + * DESCRIPTION: + * Sets color register @regnum. + * + * CALLED FROM: + * xboxfb_setcolreg() + */ +static void riva_wclut(RIVA_HW_INST *chip, + unsigned char regnum, unsigned char red, + unsigned char green, unsigned char blue) +{ + VGA_WR08(chip->PDIO, 0x3c8, regnum); + VGA_WR08(chip->PDIO, 0x3c9, red); + VGA_WR08(chip->PDIO, 0x3c9, green); + VGA_WR08(chip->PDIO, 0x3c9, blue); +} + +/** + * riva_rclut - read fromCLUT register + * @chip: pointer to RIVA_HW_INST object + * @regnum: register number + * @red: red component + * @green: green component + * @blue: blue component + * + * DESCRIPTION: + * Reads red, green, and blue from color register @regnum. + * + * CALLED FROM: + * xboxfb_setcolreg() + */ +static void riva_rclut(RIVA_HW_INST *chip, + unsigned char regnum, unsigned char *red, + unsigned char *green, unsigned char *blue) +{ + + VGA_WR08(chip->PDIO, 0x3c8, regnum); + *red = VGA_RD08(chip->PDIO, 0x3c9); + *green = VGA_RD08(chip->PDIO, 0x3c9); + *blue = VGA_RD08(chip->PDIO, 0x3c9); +} + +/** + * riva_save_state - saves current chip state + * @par: pointer to riva_par object containing info for current riva board + * @regs: pointer to riva_regs object + * + * DESCRIPTION: + * Saves current chip state to @regs. + * + * CALLED FROM: + * xboxfb_probe() + */ +/* from GGI */ +static void riva_save_state(struct riva_par *par, struct riva_regs *regs) +{ + int i; + + par->riva.LockUnlock(&par->riva, 0); + + par->riva.UnloadStateExt(&par->riva, ®s->ext); + + regs->misc_output = MISCin(par); + + for (i = 0; i < NUM_CRT_REGS; i++) + regs->crtc[i] = CRTCin(par, i); + + for (i = 0; i < NUM_ATC_REGS; i++) + regs->attr[i] = ATTRin(par, i); + + for (i = 0; i < NUM_GRC_REGS; i++) + regs->gra[i] = GRAin(par, i); + + for (i = 0; i < NUM_SEQ_REGS; i++) + regs->seq[i] = SEQin(par, i); +} + +/** + * riva_load_state - loads current chip state + * @par: pointer to riva_par object containing info for current riva board + * @regs: pointer to riva_regs object + * + * DESCRIPTION: + * Loads chip state from @regs. + * + * CALLED FROM: + * riva_load_video_mode() + * xboxfb_probe() + * xboxfb_remove() + */ +/* from GGI */ +static void riva_load_state(struct riva_par *par, struct riva_regs *regs) +{ + RIVA_HW_STATE *state = ®s->ext; + int i; + + CRTCout(par, 0x11, 0x00); + + par->riva.LockUnlock(&par->riva, 0); + + par->riva.LoadStateExt(&par->riva, state); + + par->riva.PGRAPH[0x00000820/4] = par->riva_fb_start; + par->riva.PGRAPH[0x00000824/4] = par->riva_fb_start; + par->riva.PGRAPH[0x00000828/4] = par->riva_fb_start; + par->riva.PGRAPH[0x0000082c/4] = par->riva_fb_start; + + par->riva.PGRAPH[0x00000684/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PGRAPH[0x00000688/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PGRAPH[0x0000068c/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PGRAPH[0x00000690/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PRAMDAC[0x00000848/4] = 0x10100111; + par->riva.PRAMDAC[0x00000880/4] = 0; + par->riva.PRAMDAC[0x000008a0/4] = 0; + par->riva.PMC[0x00008908/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PMC[0x0000890c/4] = par->riva.RamAmountKBytes * 1024 - 1; + /* Switch GPU to RGB output */ + par->riva.PRAMDAC[0x00000630/4] = 0; + /* These fix the maroon borders seen when booting from Xromwell or + * xbeboot + */ + par->riva.PRAMDAC[0x0000084c/4] = 0; + par->riva.PRAMDAC[0x000008c4/4] = 0; + + /* for YCrCb: + par->riva.PRAMDAC[0x00000630/4] = 2; + par->riva.PRAMDAC[0x0000084c/4] =0x00801080; + par->riva.PRAMDAC[0x000008c4/4] =0x40801080; + */ + MISCout(par, regs->misc_output); + + for (i = 0; i < NUM_CRT_REGS; i++) { + switch (i) { + case 0x0c: + case 0x0d: + case 0x19: + case 0x20 ... 0x40: + break; + default: + CRTCout(par, i, regs->crtc[i]); + } + } + + for (i = 0; i < NUM_ATC_REGS; i++) + ATTRout(par, i, regs->attr[i]); + + for (i = 0; i < NUM_GRC_REGS; i++) + GRAout(par, i, regs->gra[i]); + + for (i = 0; i < NUM_SEQ_REGS; i++) + SEQout(par, i, regs->seq[i]); + tv_save_mode(regs->encoder_mode); +} + +static inline unsigned long xbox_memory_size(void) { + /* make a guess on the xbox memory size. There are just + two possibilities */ + if ((num_physpages << PAGE_SHIFT) > 64*1024*1024) { + return 128*1024*1024; + } else { + return 64*1024*1024; + } +} + +static inline unsigned long available_framebuffer_memory(void) { + return xbox_memory_size() - (num_physpages << PAGE_SHIFT); +} + +/** + * riva_load_video_mode - calculate timings + * @info: pointer to fb_info object containing info for current riva board + * + * DESCRIPTION: + * Calculate some timings and then send em off to riva_load_state(). + * + * CALLED FROM: + * xboxfb_set_par() + */ +static void riva_load_video_mode(struct fb_info *info) +{ + int bpp, width, height, hDisplaySize, hStart, hTotal, vStart, vTotal; + int crtc_hDisplay, crtc_hStart, crtc_hEnd, crtc_hTotal; + int crtc_vDisplay, crtc_vStart, crtc_vEnd, crtc_vTotal, dotClock; + int crtc_hBlankStart, crtc_hBlankEnd, crtc_vBlankStart, crtc_vBlankEnd; + struct riva_par *par = (struct riva_par *) info->par; + struct riva_regs newmode; + int encoder_ok = 0; + + /* time to calculate */ + xboxfb_blank(1, info); + + bpp = info->var.bits_per_pixel; + if (bpp == 16 && info->var.green.length == 5) + bpp = 15; + width = info->var.xres_virtual; + height = info->var.yres_virtual; + hDisplaySize = info->var.xres; + hStart = hDisplaySize + info->var.right_margin; + hTotal = hDisplaySize + info->var.right_margin + + info->var.hsync_len + info->var.left_margin; + vStart = info->var.yres + info->var.lower_margin; + vTotal = info->var.yres + info->var.lower_margin + + info->var.vsync_len + info->var.upper_margin; + + crtc_hDisplay = (hDisplaySize / 8) - 1; + crtc_hStart = (hTotal - 32) / 8; + /* crtc_hStart = hStart / 8 - 1; */ + crtc_hEnd = crtc_hStart + 1; + /* crtc_hEnd = (hStart + info->var.hsync_len) / 8 - 1; */ + crtc_hTotal = hTotal / 8 - 5; + crtc_hBlankStart = crtc_hDisplay; + crtc_hBlankEnd = crtc_hTotal + 4; + + crtc_vDisplay = info->var.yres - 1; + /* crtc_vStart = vStart - 1; */ + crtc_vStart = vStart - 1; + /* crtc_vEnd = vStart + info->var.vsync_len - 1; */ + crtc_vEnd = crtc_vStart + 2; + crtc_vTotal = vTotal + 2; + crtc_vDisplay = info->var.yres - 1; + crtc_vBlankStart = crtc_vDisplay; + crtc_vBlankEnd = crtc_vTotal + 1; + + dotClock = 1000000000 / info->var.pixclock; + + memcpy(&newmode, ®_template, sizeof(struct riva_regs)); + + if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) + vTotal |= 1; + + if (par->FlatPanel) { + crtc_vStart = crtc_vTotal - 3; + crtc_vEnd = crtc_vTotal - 2; + crtc_vBlankStart = crtc_vStart; + crtc_hStart = crtc_hTotal - 3; + crtc_hEnd = crtc_hTotal - 2; + crtc_hBlankEnd = crtc_hTotal + 4; + } + + newmode.ext.bpp = bpp; + newmode.ext.fb_start = par->riva_fb_start; + + if((par->av_type == AV_VGA) || (par->av_type == AV_VGA_SOG) || (par->av_type == AV_HDTV)) { + unsigned char pll_int = (unsigned char)((double)dotClock * 6.0 / 13.5e3 + 0.5); + if (par->av_type == AV_HDTV) { + xbox_hdtv_mode hdtv_mode = HDTV_480p; + if (info->var.yres > 800) { + hdtv_mode = HDTV_1080i; + crtc_vStart = vStart + 31; + crtc_vEnd = crtc_vStart + 2; + } + else if (info->var.yres > 600) { + hdtv_mode = HDTV_720p; + } + switch (par->video_encoder) { + case ENCODER_CONEXANT: + encoder_ok = conexant_calc_hdtv_mode(hdtv_mode, pll_int, newmode.encoder_mode); + break; + case ENCODER_FOCUS: + encoder_ok = focus_calc_hdtv_mode(hdtv_mode, pll_int, newmode.encoder_mode); + break; + case ENCODER_XLB: + encoder_ok = xlb_calc_hdtv_mode(hdtv_mode, pll_int, newmode.encoder_mode); + break; + default: + printk("Error - unknown encoder type detected\n"); + } + } + else { + switch (par->video_encoder) { + case ENCODER_CONEXANT: + encoder_ok = conexant_calc_vga_mode(par->av_type, pll_int, newmode.encoder_mode); + break; + case ENCODER_FOCUS: + //No vga functions as yet - so set up for 480p otherwise we dont boot at all. + encoder_ok = focus_calc_hdtv_mode(HDTV_480p, pll_int, newmode.encoder_mode); + break; + case ENCODER_XLB: + //No vga functions as yet - so set up for 480p otherwise we dont boot at all. + encoder_ok = xlb_calc_hdtv_mode(HDTV_480p, pll_int, newmode.encoder_mode); + break; + default: + printk("Error - unknown encoder type detected\n"); + } + } + newmode.ext.vend = info->var.yres - 1; + newmode.ext.vtotal = vTotal; + newmode.ext.vcrtc = info->var.yres - 1; + newmode.ext.vsyncstart = vStart; + newmode.ext.vsyncend = vStart + 3; + newmode.ext.vvalidstart = 0; + newmode.ext.vvalidend = info->var.yres - 1; + newmode.ext.hend = info->var.xres - 1; + newmode.ext.htotal = hTotal; + newmode.ext.hcrtc = info->var.xres - 1; + newmode.ext.hsyncstart = hStart; + newmode.ext.hsyncend = hStart + 32; + newmode.ext.hvalidstart = 0; + newmode.ext.hvalidend = info->var.xres - 1; + } + + /* Normal composite */ + else { + xbox_video_mode encoder_mode; + encoder_mode.xres = info->var.xres; + encoder_mode.yres = info->var.yres; + encoder_mode.tv_encoding = par->tv_encoding; + encoder_mode.bpp = bpp; + encoder_mode.hoc = par->hoc; + encoder_mode.voc = par->voc; + encoder_mode.av_type = par->av_type; + + switch (par->video_encoder) { + case ENCODER_CONEXANT: + encoder_ok = conexant_calc_mode(&encoder_mode, &newmode); + break; + case ENCODER_FOCUS: + encoder_ok = focus_calc_mode(&encoder_mode, &newmode); + break; + case ENCODER_XLB: + encoder_ok = xlb_calc_mode(&encoder_mode, &newmode); + break; + default: + printk("Error - unknown encoder type detected\n"); + } + + crtc_hDisplay = (newmode.ext.crtchdispend / 8) - 1; + crtc_hStart = (newmode.ext.htotal - 32) / 8; + crtc_hEnd = crtc_hStart + 1; + crtc_hTotal = (newmode.ext.htotal) / 8 - 5; + crtc_hBlankStart = crtc_hDisplay; + crtc_hBlankEnd = (newmode.ext.htotal) / 8 - 1; + + crtc_vDisplay = info->var.yres - 1; + crtc_vStart = newmode.ext.crtcvstart; + crtc_vEnd = newmode.ext.crtcvstart + 3; + crtc_vTotal = newmode.ext.crtcvtotal; + crtc_vBlankStart = crtc_vDisplay; + crtc_vBlankEnd = crtc_vTotal + 1; + } + + if (encoder_ok) { + newmode.crtc[0x0] = Set8Bits (crtc_hTotal); + newmode.crtc[0x1] = Set8Bits (crtc_hDisplay); + newmode.crtc[0x2] = Set8Bits (crtc_hBlankStart); + newmode.crtc[0x3] = SetBitField (crtc_hBlankEnd, 4: 0, 4:0) | SetBit (7); + newmode.crtc[0x4] = Set8Bits (crtc_hStart); + newmode.crtc[0x5] = SetBitField (crtc_hBlankEnd, 5: 5, 7:7) + | SetBitField (crtc_hEnd, 4: 0, 4:0); + newmode.crtc[0x6] = SetBitField (crtc_vTotal, 7: 0, 7:0); + newmode.crtc[0x7] = SetBitField (crtc_vTotal, 8: 8, 0:0) + | SetBitField (crtc_vDisplay, 8: 8, 1:1) + | SetBitField (crtc_vStart, 8: 8, 2:2) + | SetBitField (crtc_vBlankStart, 8: 8, 3:3) + | SetBit (4) + | SetBitField (crtc_vTotal, 9: 9, 5:5) + | SetBitField (crtc_vDisplay, 9: 9, 6:6) + | SetBitField (crtc_vStart, 9: 9, 7:7); + newmode.crtc[0x9] = SetBitField (crtc_vBlankStart, 9: 9, 5:5) + | SetBit (6); + newmode.crtc[0x10] = Set8Bits (crtc_vStart); + newmode.crtc[0x11] = SetBitField (crtc_vEnd, 3: 0, 3:0) + | SetBit (5); + newmode.crtc[0x12] = Set8Bits (crtc_vDisplay); + newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8); + newmode.crtc[0x15] = Set8Bits (crtc_vBlankStart); + newmode.crtc[0x16] = Set8Bits (crtc_vBlankEnd); + + newmode.ext.screen = SetBitField(crtc_hBlankEnd,6:6,4:4) + | SetBitField(crtc_vBlankStart,10:10,3:3) + | SetBitField(crtc_vStart,10:10,2:2) + | SetBitField(crtc_vDisplay,10:10,1:1) + | SetBitField(crtc_vTotal,10:10,0:0); + newmode.ext.horiz = SetBitField(crtc_hTotal,8:8,0:0) + | SetBitField(crtc_hDisplay,8:8,1:1) + | SetBitField(crtc_hBlankStart,8:8,2:2) + | SetBitField(crtc_hStart,8:8,3:3); + newmode.ext.extra = SetBitField(crtc_vTotal,11:11,0:0) + | SetBitField(crtc_vDisplay,11:11,2:2) + | SetBitField(crtc_vStart,11:11,4:4) + | SetBitField(crtc_vBlankStart,11:11,6:6); + + if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + int tmp = (crtc_hTotal >> 1) & ~1; + newmode.ext.interlace = Set8Bits(tmp); + newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4); + } else + newmode.ext.interlace = 0xff; /* interlace off */ + + if (par->riva.Architecture >= NV_ARCH_10) + /* use 2 KByte at top of framebuffer */ + par->riva.CURSOR = (U032 *)(info->screen_base + info->fix.smem_len - 2 * 1024); + + if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) + newmode.misc_output &= ~0x40; + else + newmode.misc_output |= 0x40; + if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) + newmode.misc_output &= ~0x80; + else + newmode.misc_output |= 0x80; + + par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, + hDisplaySize, height, dotClock); + + newmode.ext.scale = par->riva.PRAMDAC[0x00000848/4] & 0xfff000ff; + if (par->FlatPanel == 1) { + newmode.ext.pixel |= (1 << 7); + newmode.ext.scale |= (1 << 8); + } + if (par->SecondCRTC) { + newmode.ext.head = par->riva.PCRTC0[0x00000860/4] & ~0x00001000; + newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] | 0x00001000; + newmode.ext.crtcOwner = 3; + newmode.ext.pllsel |= 0x20000800; + newmode.ext.vpll2 = newmode.ext.vpll; + } else if (par->riva.twoHeads) { + newmode.ext.head = par->riva.PCRTC0[0x00000860/4] | 0x00001000; + newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] & ~0x00001000; + newmode.ext.crtcOwner = 0; + newmode.ext.vpll2 = par->riva.PRAMDAC0[0x00000520/4]; + } + if (par->FlatPanel == 1) { + newmode.ext.pixel |= (1 << 7); + newmode.ext.scale |= (1 << 8); + } + newmode.ext.cursorConfig = 0x02000100; + par->current_state = newmode; + riva_load_state(par, &par->current_state); + tv_load_mode(newmode.encoder_mode); + par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */ + } + else { + printk("Error: Unable to set encoder resolution %dx%d\n",info->var.xres, info->var.yres); + } + + xboxfb_blank(0, info); +} + +/** + * xboxfb_do_maximize - + * @info: pointer to fb_info object containing info for current riva board + * @var: + * @nom: + * @den: + * + * DESCRIPTION: + * . + * + * RETURNS: + * -EINVAL on failure, 0 on success + * + * + * CALLED FROM: + * xboxfb_check_var() + */ +static int xboxfb_do_maximize(struct fb_info *info, + struct fb_var_screeninfo *var, + int nom, int den) +{ + static struct { + int xres, yres; + } modes[] = { + {1600, 1280}, + {1280, 1024}, + {1024, 768}, + {800, 600}, + {640, 480}, + {-1, -1} + }; + int i; + + /* use highest possible virtual resolution */ + if (var->xres_virtual == -1 && var->yres_virtual == -1) { + printk(KERN_WARNING PFX + "using maximum available virtual resolution\n"); + for (i = 0; modes[i].xres != -1; i++) { + if (modes[i].xres * nom / den * modes[i].yres < + info->fix.smem_len / 2) + break; + } + if (modes[i].xres == -1) { + printk(KERN_ERR PFX + "could not find a virtual resolution that fits into video memory!!\n"); + DPRINTK("EXIT - EINVAL error\n"); + return -EINVAL; + } + var->xres_virtual = modes[i].xres; + var->yres_virtual = modes[i].yres; + + printk(KERN_INFO PFX + "virtual resolution set to maximum of %dx%d\n", + var->xres_virtual, var->yres_virtual); + } else if (var->xres_virtual == -1) { + var->xres_virtual = (info->fix.smem_len * den / + (nom * var->yres_virtual * 2)) & ~15; + printk(KERN_WARNING PFX + "setting virtual X resolution to %d\n", var->xres_virtual); + } else if (var->yres_virtual == -1) { + var->xres_virtual = (var->xres_virtual + 15) & ~15; + var->yres_virtual = info->fix.smem_len * den / + (nom * var->xres_virtual * 2); + printk(KERN_WARNING PFX + "setting virtual Y resolution to %d\n", var->yres_virtual); + } else { + var->xres_virtual = (var->xres_virtual + 15) & ~15; + if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) { + printk(KERN_ERR PFX + "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", + var->xres, var->yres, var->bits_per_pixel); + DPRINTK("EXIT - EINVAL error\n"); + return -EINVAL; + } + } + + if (var->xres_virtual * nom / den >= 8192) { + printk(KERN_WARNING PFX + "virtual X resolution (%d) is too high, lowering to %d\n", + var->xres_virtual, 8192 * den / nom - 16); + var->xres_virtual = 8192 * den / nom - 16; + } + + if (var->xres_virtual < var->xres) { + printk(KERN_ERR PFX + "virtual X resolution (%d) is smaller than real\n", var->xres_virtual); + return -EINVAL; + } + + if (var->yres_virtual < var->yres) { + printk(KERN_ERR PFX + "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual); + return -EINVAL; + } + return 0; +} + +/* acceleration routines */ +inline void wait_for_idle(struct riva_par *par) +{ + while (par->riva.Busy(&par->riva)); +} + +/* set copy ROP, no mask */ +static void riva_setup_ROP(struct riva_par *par) +{ + RIVA_FIFO_FREE(par->riva, Patt, 5); + par->riva.Patt->Shape = 0; + par->riva.Patt->Color0 = 0xffffffff; + par->riva.Patt->Color1 = 0xffffffff; + par->riva.Patt->Monochrome[0] = 0xffffffff; + par->riva.Patt->Monochrome[1] = 0xffffffff; + + RIVA_FIFO_FREE(par->riva, Rop, 1); + par->riva.Rop->Rop3 = 0xCC; +} + +void riva_setup_accel(struct riva_par *par) +{ + RIVA_FIFO_FREE(par->riva, Clip, 2); + par->riva.Clip->TopLeft = 0x0; + par->riva.Clip->WidthHeight = 0x80008000; + riva_setup_ROP(par); + wait_for_idle(par); +} + +/** + * riva_get_cmap_len - query current color map length + * @var: standard kernel fb changeable data + * + * DESCRIPTION: + * Get current color map length. + * + * RETURNS: + * Length of color map + * + * CALLED FROM: + * xboxfb_setcolreg() + */ +static int riva_get_cmap_len(const struct fb_var_screeninfo *var) +{ + int rc = 256; /* reasonable default */ + + switch (var->green.length) { + case 8: + rc = 256; /* 256 entries (2^8), 8 bpp and RGB8888 */ + break; + case 5: + rc = 32; /* 32 entries (2^5), 16 bpp, RGB555 */ + break; + case 6: + rc = 64; /* 64 entries (2^6), 16 bpp, RGB565 */ + break; + default: + /* should not occur */ + break; + } + return rc; +} + +/* ------------------------------------------------------------------------- * + * + * framebuffer operations + * + * ------------------------------------------------------------------------- */ + +static int xboxfb_open(struct fb_info *info, int user) +{ + struct riva_par *par = (struct riva_par *) info->par; + int cnt = atomic_read(&par->ref_count); + + if (!cnt) { + memset(&par->state, 0, sizeof(struct vgastate)); + par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; + /* save the DAC for Riva128 */ + if (par->riva.Architecture == NV_ARCH_03) + par->state.flags |= VGA_SAVE_CMAP; + save_vga(&par->state); + + RivaGetConfig(&par->riva, par->Chipset); + par->riva.CURSOR = (U032*)(info->screen_base + info->fix.smem_len); + par->riva.PCRTC[0x00000800/4] = par->riva_fb_start; + par->riva.PGRAPH[0x00000820/4] = par->riva_fb_start; + par->riva.PGRAPH[0x00000824/4] = par->riva_fb_start; + par->riva.PGRAPH[0x00000828/4] = par->riva_fb_start; + par->riva.PGRAPH[0x0000082c/4] = par->riva_fb_start; + + par->riva.PGRAPH[0x00000684/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PGRAPH[0x00000688/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PGRAPH[0x0000068c/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PGRAPH[0x00000690/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PMC[0x00008908/4] = par->riva.RamAmountKBytes * 1024 - 1; + par->riva.PMC[0x0000890c/4] = par->riva.RamAmountKBytes * 1024 - 1; + + /* vgaHWunlock() + riva unlock (0x7F) */ + CRTCout(par, 0x11, 0xFF); + par->riva.LockUnlock(&par->riva, 0); + + riva_save_state(par, &par->initial_state); + } + atomic_inc(&par->ref_count); + return 0; +} + +static int xboxfb_release(struct fb_info *info, int user) +{ + struct riva_par *par = (struct riva_par *) info->par; + int cnt = atomic_read(&par->ref_count); + + if (!cnt) + return -EINVAL; + if (cnt == 1) { + par->riva.LockUnlock(&par->riva, 0); + par->riva.LoadStateExt(&par->riva, &par->initial_state.ext); + riva_load_state(par, &par->initial_state); + restore_vga(&par->state); + par->riva.LockUnlock(&par->riva, 1); + } + atomic_dec(&par->ref_count); + return 0; +} + +static int xboxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + int nom, den; /* translating from pixels->bytes */ + + switch (var->bits_per_pixel) { + case 1 ... 8: + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 8; + var->bits_per_pixel = 8; + nom = den = 1; + break; + case 9 ... 15: + var->green.length = 5; + /* fall through */ + case 16: + var->bits_per_pixel = 16; + if (var->green.length == 5) { + /* 0rrrrrgg gggbbbbb */ + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + } else { + /* rrrrrggg gggbbbbb */ + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + } + nom = 2; + den = 1; + break; + case 17 ... 32: + var->red.length = var->green.length = var->blue.length = 8; + var->bits_per_pixel = 32; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + nom = 4; + den = 1; + break; + default: + printk(KERN_ERR PFX + "mode %dx%dx%d rejected...color depth not supported.\n", + var->xres, var->yres, var->bits_per_pixel); + DPRINTK("EXIT, returning -EINVAL\n"); + return -EINVAL; + } + + if (xboxfb_do_maximize(info, var, nom, den) < 0) + return -EINVAL; + + if (var->xoffset < 0) + var->xoffset = 0; + if (var->yoffset < 0) + var->yoffset = 0; + + /* truncate xoffset and yoffset to maximum if too high */ + if (var->xoffset > var->xres_virtual - var->xres) + var->xoffset = var->xres_virtual - var->xres - 1; + + if (var->yoffset > var->yres_virtual - var->yres) + var->yoffset = var->yres_virtual - var->yres - 1; + + var->red.msb_right = + var->green.msb_right = + var->blue.msb_right = + var->transp.offset = var->transp.length = var->transp.msb_right = 0; + return 0; +} + +static int xboxfb_set_par(struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *) info->par; + + riva_load_video_mode(info); + riva_setup_accel(par); + + info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3)); + info->fix.visual = (info->var.bits_per_pixel == 8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; + return 0; +} + +/** + * xboxfb_pan_display + * @var: standard kernel fb changeable data + * @con: TODO + * @info: pointer to fb_info object containing info for current riva board + * + * DESCRIPTION: + * Pan (or wrap, depending on the `vmode' field) the display using the + * `xoffset' and `yoffset' fields of the `var' structure. + * If the values don't fit, return -EINVAL. + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ +static int xboxfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *)info->par; + unsigned int base; + + if (var->xoffset > (var->xres_virtual - var->xres)) + return -EINVAL; + if (var->yoffset > (var->yres_virtual - var->yres)) + return -EINVAL; + + if (var->vmode & FB_VMODE_YWRAP) { + if (var->yoffset < 0 + || var->yoffset >= info->var.yres_virtual + || var->xoffset) return -EINVAL; + } else { + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) + return -EINVAL; + } + + base = var->yoffset * info->fix.line_length + var->xoffset; + base += par->riva_fb_start; + + par->riva.SetStartAddress(&par->riva, base); + + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + + if (var->vmode & FB_VMODE_YWRAP) + info->var.vmode |= FB_VMODE_YWRAP; + else + info->var.vmode &= ~FB_VMODE_YWRAP; + return 0; +} + +static int xboxfb_blank(int blank, struct fb_info *info) +{ + struct riva_par *par= (struct riva_par *)info->par; + unsigned char tmp, vesa; + + tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */ + vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */ + + if (blank) { + tmp |= 0x20; + switch (blank - 1) { + case VESA_NO_BLANKING: + break; + case VESA_VSYNC_SUSPEND: + vesa |= 0x80; + break; + case VESA_HSYNC_SUSPEND: + vesa |= 0x40; + break; + case VESA_POWERDOWN: + vesa |= 0xc0; + break; + } + } + SEQout(par, 0x01, tmp); + CRTCout(par, 0x1a, vesa); + return 0; +} + +/** + * xboxfb_setcolreg + * @regno: register index + * @red: red component + * @green: green component + * @blue: blue component + * @transp: transparency + * @info: pointer to fb_info object containing info for current riva board + * + * DESCRIPTION: + * Set a single color register. The values supplied have a 16 bit + * magnitude. + * + * RETURNS: + * Return != 0 for invalid regno. + * + * CALLED FROM: + * fbcmap.c:fb_set_cmap() + */ +static int xboxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *)info->par; + RIVA_HW_INST *chip = &par->riva; + int i; + + if (regno >= riva_get_cmap_len(&info->var)) + return -EINVAL; + + if (info->var.grayscale) { + /* gray = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = + (red * 77 + green * 151 + blue * 28) >> 8; + } + + switch (info->var.bits_per_pixel) { + case 8: + /* "transparent" stuff is completely ignored. */ + riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8); + break; + case 16: + if (info->var.green.length == 5) { + if (regno < 16) { + /* 0rrrrrgg gggbbbbb */ + ((u32 *)info->pseudo_palette)[regno] = + ((red & 0xf800) >> 1) | + ((green & 0xf800) >> 6) | + ((blue & 0xf800) >> 11); + } + for (i = 0; i < 8; i++) + riva_wclut(chip, regno*8+i, red >> 8, + green >> 8, blue >> 8); + } else { + u8 r, g, b; + + if (regno < 16) { + /* rrrrrggg gggbbbbb */ + ((u32 *)info->pseudo_palette)[regno] = + ((red & 0xf800) >> 0) | + ((green & 0xf800) >> 5) | + ((blue & 0xf800) >> 11); + } + if (regno < 32) { + for (i = 0; i < 8; i++) { + riva_wclut(chip, regno*8+i, red >> 8, + green >> 8, blue >> 8); + } + } + for (i = 0; i < 4; i++) { + riva_rclut(chip, regno*2+i, &r, &g, &b); + riva_wclut(chip, regno*4+i, r, green >> 8, b); + } + } + break; + case 32: + if (regno < 16) { + ((u32 *)info->pseudo_palette)[regno] = + ((red & 0xff00) << 8) | + ((green & 0xff00)) | ((blue & 0xff00) >> 8); + + } + riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8); + break; + default: + /* do nothing */ + break; + } + return 0; +} + +/** + * xboxfb_fillrect - hardware accelerated color fill function + * @info: pointer to fb_info structure + * @rect: pointer to fb_fillrect structure + * + * DESCRIPTION: + * This function fills up a region of framebuffer memory with a solid + * color with a choice of two different ROP's, copy or invert. + * + * CALLED FROM: + * framebuffer hook + */ +static void xboxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct riva_par *par = (struct riva_par *) info->par; + u_int color, rop = 0; + + if (info->var.bits_per_pixel == 8) + color = rect->color; + else + color = ((u32 *)info->pseudo_palette)[rect->color]; + + switch (rect->rop) { + case ROP_XOR: + rop = 0x66; + break; + case ROP_COPY: + default: + rop = 0xCC; + break; + } + + RIVA_FIFO_FREE(par->riva, Rop, 1); + par->riva.Rop->Rop3 = rop; + + RIVA_FIFO_FREE(par->riva, Bitmap, 1); + par->riva.Bitmap->Color1A = color; + + RIVA_FIFO_FREE(par->riva, Bitmap, 2); + par->riva.Bitmap->UnclippedRectangle[0].TopLeft = + (rect->dx << 16) | rect->dy; + par->riva.Bitmap->UnclippedRectangle[0].WidthHeight = + (rect->width << 16) | rect->height; + RIVA_FIFO_FREE(par->riva, Rop, 1); + par->riva.Rop->Rop3 = 0xCC; /* back to COPY */ +} + +/** + * xboxfb_copyarea - hardware accelerated blit function + * @info: pointer to fb_info structure + * @region: pointer to fb_copyarea structure + * + * DESCRIPTION: + * This copies an area of pixels from one location to another + * + * CALLED FROM: + * framebuffer hook + */ +static void xboxfb_copyarea(struct fb_info *info, const struct fb_copyarea *region) +{ + struct riva_par *par = (struct riva_par *) info->par; + + RIVA_FIFO_FREE(par->riva, Blt, 3); + par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx; + par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx; + par->riva.Blt->WidthHeight = (region->height << 16) | region->width; + wait_for_idle(par); +} + +static inline void convert_bgcolor_16(u32 *col) +{ + *col = ((*col & 0x00007C00) << 9) + | ((*col & 0x000003E0) << 6) + | ((*col & 0x0000001F) << 3) + | 0xFF000000; +} + +/** + * xboxfb_imageblit: hardware accelerated color expand function + * @info: pointer to fb_info structure + * @image: pointer to fb_image structure + * + * DESCRIPTION: + * If the source is a monochrome bitmap, the function fills up a a region + * of framebuffer memory with pixels whose color is determined by the bit + * setting of the bitmap, 1 - foreground, 0 - background. + * + * If the source is not a monochrome bitmap, color expansion is not done. + * In this case, it is channeled to a software function. + * + * CALLED FROM: + * framebuffer hook + */ +static void xboxfb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + struct riva_par *par = (struct riva_par *) info->par; + u32 fgx = 0, bgx = 0, width, tmp; + u8 *cdat = (u8 *) image->data; + volatile u32 *d; + int i, size; + + if (image->depth != 1) { + cfb_imageblit(info, image); + return; + } + + switch (info->var.bits_per_pixel) { + case 8: + fgx = image->fg_color; + bgx = image->bg_color; + break; + case 16: + fgx = ((u32 *)info->pseudo_palette)[image->fg_color]; + bgx = ((u32 *)info->pseudo_palette)[image->bg_color]; + if (info->var.green.length == 6) + convert_bgcolor_16(&bgx); + break; + case 32: + fgx = ((u32 *)info->pseudo_palette)[image->fg_color]; + bgx = ((u32 *)info->pseudo_palette)[image->bg_color]; + break; + } + + RIVA_FIFO_FREE(par->riva, Bitmap, 7); + par->riva.Bitmap->ClipE.TopLeft = + (image->dy << 16) | (image->dx & 0xFFFF); + par->riva.Bitmap->ClipE.BottomRight = + (((image->dy + image->height) << 16) | + ((image->dx + image->width) & 0xffff)); + par->riva.Bitmap->Color0E = bgx; + par->riva.Bitmap->Color1E = fgx; + par->riva.Bitmap->WidthHeightInE = + (image->height << 16) | ((image->width + 31) & ~31); + par->riva.Bitmap->WidthHeightOutE = + (image->height << 16) | ((image->width + 31) & ~31); + par->riva.Bitmap->PointE = + (image->dy << 16) | (image->dx & 0xFFFF); + + d = &par->riva.Bitmap->MonochromeData01E; + + width = (image->width + 31)/32; + size = width * image->height; + while (size >= 16) { + RIVA_FIFO_FREE(par->riva, Bitmap, 16); + for (i = 0; i < 16; i++) { + tmp = *((u32 *)cdat); + cdat = (u8 *)((u32 *)cdat + 1); + reverse_order(&tmp); + d[i] = tmp; + } + size -= 16; + } + if (size) { + RIVA_FIFO_FREE(par->riva, Bitmap, size); + for (i = 0; i < size; i++) { + tmp = *((u32 *) cdat); + cdat = (u8 *)((u32 *)cdat + 1); + reverse_order(&tmp); + d[i] = tmp; + } + } +} + +/** + * xboxfb_cursor - hardware cursor function + * @info: pointer to info structure + * @cursor: pointer to fbcursor structure + * + * DESCRIPTION: + * A cursor function that supports displaying a cursor image via hardware. + * Within the kernel, copy and invert rops are supported. If exported + * to user space, only the copy rop will be supported. + * + * CALLED FROM + * framebuffer hook + */ +static int xboxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + struct riva_par *par = (struct riva_par *) info->par; + u8 mask[MAX_CURS * MAX_CURS/8]; + u16 fg, bg; + + par->riva.ShowHideCursor(&par->riva, 0); + + if (cursor->set & FB_CUR_SETPOS) { + u32 xx, yy, temp; + + info->cursor.image.dx = cursor->image.dx; + info->cursor.image.dy = cursor->image.dy; + yy = cursor->image.dy - info->var.yoffset; + xx = cursor->image.dx - info->var.xoffset; + temp = xx & 0xFFFF; + temp |= yy << 16; + + par->riva.PRAMDAC[0x0000300/4] = temp; + } + + if (cursor->set & FB_CUR_SETSIZE) { + info->cursor.image.height = cursor->image.height; + info->cursor.image.width = cursor->image.width; + memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2); + } + + if (cursor->set & FB_CUR_SETCMAP) { + info->cursor.image.bg_color = cursor->image.bg_color; + info->cursor.image.fg_color = cursor->image.fg_color; + } + + if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) { + u32 bg_idx = info->cursor.image.bg_color; + u32 fg_idx = info->cursor.image.fg_color; + u32 s_pitch = (info->cursor.image.width+7) >> 3; + u32 d_pitch = MAX_CURS/8; + u8 *msk = (u8 *) info->cursor.mask; + + fb_move_buf_aligned(info, &info->sprite, mask, d_pitch, msk, s_pitch, info->cursor.image.height); + bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) | + ((info->cmap.green[bg_idx] & 0xf8) << 2) | + ((info->cmap.blue[bg_idx] & 0xf8) >> 3); + + fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) | + ((info->cmap.green[fg_idx] & 0xf8) << 2) | + ((info->cmap.blue[fg_idx] & 0xf8) >> 3); + + par->riva.LockUnlock(&par->riva, 0); + + xboxfb_load_cursor_image(par, mask, mask, bg, fg, + info->cursor.image.width, + info->cursor.image.height); + } + if (info->cursor.enable) + par->riva.ShowHideCursor(&par->riva, 1); + return 0; +} + +static int xboxfb_sync(struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *)info->par; + + wait_for_idle(par); + return 0; +} + +static int xboxfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *) info->par; + + xbox_overscan overscan; + xboxfb_config config; + xbox_tv_encoding encoding; + int ret = 0; + + switch (cmd) { + case FBIO_XBOX_SET_OVERSCAN: + if(!copy_from_user(&overscan, (xbox_overscan*)arg, sizeof(overscan))) { + par->hoc = overscan.hoc; + par->voc = overscan.voc; + riva_load_video_mode (info); + if (info->var.accel_flags & FB_ACCELF_TEXT) { + riva_setup_accel(par); + } + + } + else { + ret = -EFAULT; + } + break; + case FBIO_XBOX_GET_OVERSCAN: + overscan.hoc = par->hoc; + overscan.voc = par->voc; + if (copy_to_user((xbox_overscan*)arg, &overscan, sizeof(overscan))) { + ret = -EFAULT; + } + break; + case FBIO_XBOX_GET_CONFIG: + config.av_type = par->av_type; + config.encoder_type = par->video_encoder; + if (copy_to_user((xboxfb_config*)arg, &config, sizeof(config))) { + ret = -EFAULT; + } + break; + case FBIO_XBOX_GET_TV_ENCODING: + encoding = par->tv_encoding; + if (copy_to_user((xbox_tv_encoding*)arg, &encoding, sizeof(encoding))) { + ret = -EFAULT; + } + break; + case FBIO_XBOX_SET_TV_ENCODING: + if(!copy_from_user(&encoding, (xbox_tv_encoding*)arg, sizeof(encoding))) { + par->tv_encoding = encoding; + riva_load_video_mode (info); + if (info->var.accel_flags & FB_ACCELF_TEXT) { + riva_setup_accel(par); + } + } + else { + ret = -EFAULT; + } + break; + default: + ret = -EINVAL; + } + return ret; +} + + +/* ------------------------------------------------------------------------- * + * + * initialization helper functions + * + * ------------------------------------------------------------------------- */ + +/* kernel interface */ +static struct fb_ops riva_fb_ops = { + .owner = THIS_MODULE, + .fb_open = xboxfb_open, + .fb_release = xboxfb_release, + .fb_check_var = xboxfb_check_var, + .fb_set_par = xboxfb_set_par, + .fb_setcolreg = xboxfb_setcolreg, + .fb_pan_display = xboxfb_pan_display, + .fb_blank = xboxfb_blank, + .fb_fillrect = xboxfb_fillrect, + .fb_copyarea = xboxfb_copyarea, + .fb_imageblit = xboxfb_imageblit, + .fb_cursor = xboxfb_cursor, + .fb_sync = xboxfb_sync, + .fb_ioctl = xboxfb_ioctl, +}; + +static int __devinit riva_set_fbinfo(struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *) info->par; + unsigned int cmap_len; + + info->flags = FBINFO_FLAG_DEFAULT; + info->var = xboxfb_default_var; + info->fix = xboxfb_fix; + info->fbops = &riva_fb_ops; + info->pseudo_palette = pseudo_palette; + +#ifndef MODULE + if (mode_option) + { + if (!strncmp(mode_option, "480p", 4)) { + info->var = xboxfb_mode_480p; + } + else if (!strncmp(mode_option, "720p", 4)) { + info->var = xboxfb_mode_720p; + } + else { + fb_find_mode(&info->var, info, mode_option, + NULL, 0, NULL, 8); + } + } +#endif + if (par->use_default_var) + /* We will use the modified default var */ + info->var = xboxfb_default_var; + + cmap_len = riva_get_cmap_len(&info->var); + fb_alloc_cmap(&info->cmap, cmap_len, 0); + + info->pixmap.size = 64 * 1024; + info->pixmap.buf_align = 4; + info->pixmap.scan_align = 4; + info->pixmap.flags = FB_PIXMAP_SYSTEM; + return 0; +} + +#ifdef CONFIG_PPC_OF +static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) +{ + struct riva_par *par = (struct riva_par *) info->par; + struct device_node *dp; + unsigned char *pedid = NULL; + + dp = pci_device_to_OF_node(pd); + pedid = (unsigned char *)get_property(dp, "EDID,B", 0); + + if (pedid) { + par->EDID = pedid; + return 1; + } else + return 0; +} +#endif /* CONFIG_PPC_OF */ + +static int riva_dfp_parse_EDID(struct riva_par *par) +{ + unsigned char *block = par->EDID; + + if (!block) + return 0; + + /* jump to detailed timing block section */ + block += 54; + + par->clock = (block[0] + (block[1] << 8)); + par->panel_xres = (block[2] + ((block[4] & 0xf0) << 4)); + par->hblank = (block[3] + ((block[4] & 0x0f) << 8)); + par->panel_yres = (block[5] + ((block[7] & 0xf0) << 4)); + par->vblank = (block[6] + ((block[7] & 0x0f) << 8)); + par->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2)); + par->hSync_width = (block[9] + ((block[11] & 0x30) << 4)); + par->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2)); + par->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4)); + par->interlaced = ((block[17] & 0x80) >> 7); + par->synct = ((block[17] & 0x18) >> 3); + par->misc = ((block[17] & 0x06) >> 1); + par->hAct_high = par->vAct_high = 0; + if (par->synct == 3) { + if (par->misc & 2) + par->hAct_high = 1; + if (par->misc & 1) + par->vAct_high = 1; + } + + printk(KERN_INFO PFX + "detected DFP panel size from EDID: %dx%d\n", + par->panel_xres, par->panel_yres); + par->got_dfpinfo = 1; + return 1; +} + +static void riva_update_default_var(struct fb_info *info) +{ + struct fb_var_screeninfo *var = &xboxfb_default_var; + struct riva_par *par = (struct riva_par *) info->par; + + var->xres = par->panel_xres; + var->yres = par->panel_yres; + var->xres_virtual = par->panel_xres; + var->yres_virtual = par->panel_yres; + var->xoffset = var->yoffset = 0; + var->bits_per_pixel = 8; + var->pixclock = 100000000 / par->clock; + var->left_margin = (par->hblank - par->hOver_plus - par->hSync_width); + var->right_margin = par->hOver_plus; + var->upper_margin = (par->vblank - par->vOver_plus - par->vSync_width); + var->lower_margin = par->vOver_plus; + var->hsync_len = par->hSync_width; + var->vsync_len = par->vSync_width; + var->sync = 0; + + if (par->synct == 3) { + if (par->hAct_high) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (par->vAct_high) + var->sync |= FB_SYNC_VERT_HIGH_ACT; + } + + var->vmode = 0; + if (par->interlaced) + var->vmode |= FB_VMODE_INTERLACED; + + var->accel_flags |= FB_ACCELF_TEXT; + + par->use_default_var = 1; +} + + +static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev) +{ +#ifdef CONFIG_PPC_OF + if (!riva_get_EDID_OF(info, pdev)) + printk("xboxfb: could not retrieve EDID from OF\n"); +#else + /* XXX use other methods later */ +#endif +} + + +static void riva_get_dfpinfo(struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *) info->par; + + if (riva_dfp_parse_EDID(par)) + riva_update_default_var(info); + + /* if user specified flatpanel, we respect that */ + if (par->got_dfpinfo == 1) + par->FlatPanel = 1; +} + +/* ------------------------------------------------------------------------- * + * + * PCI bus + * + * ------------------------------------------------------------------------- */ + +static int __devinit xboxfb_probe(struct pci_dev *pd, + const struct pci_device_id *ent) +{ + struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; + struct riva_par *default_par; + struct fb_info *info; + unsigned long fb_start; + unsigned long fb_size; + + assert(pd != NULL); + assert(rci != NULL); + + info = kmalloc(sizeof(struct fb_info), GFP_KERNEL); + if (!info) + goto err_out; + + default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL); + if (!default_par) + goto err_out_kfree; + + memset(info, 0, sizeof(struct fb_info)); + memset(default_par, 0, sizeof(struct riva_par)); + + info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL); + if (info->pixmap.addr == NULL) + goto err_out_kfree1; + memset(info->pixmap.addr, 0, 64 * 1024); + + strcat(xboxfb_fix.id, rci->name); + default_par->riva.Architecture = rci->arch_rev; + + default_par->Chipset = (pd->vendor << 16) | pd->device; + printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset); + + default_par->FlatPanel = flatpanel; + if (flatpanel == 1) + printk(KERN_INFO PFX "flatpanel support enabled\n"); + default_par->forceCRTC = forceCRTC; + + xboxfb_fix.mmio_len = pci_resource_len(pd, 0); + + { + /* enable IO and mem if not already done */ + unsigned short cmd; + + pci_read_config_word(pd, PCI_COMMAND, &cmd); + cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(pd, PCI_COMMAND, cmd); + } + + xboxfb_fix.mmio_start = pci_resource_start(pd, 0); + xboxfb_fix.smem_start = pci_resource_start(pd, 1); + + if (xbox_memory_size() == 64*1024*1024) printk(KERN_INFO PFX "Detected 64MB of system RAM\n"); + else printk(KERN_INFO PFX "Detected 128MB of system RAM\n"); + + fb_size = available_framebuffer_memory(); + fb_start = xbox_memory_size() - fb_size; + printk(KERN_INFO PFX "Using %dM framebuffer memory\n", (int)(fb_size/(1024*1024))); + default_par->riva_fb_start = fb_start; + xboxfb_fix.smem_start += fb_start; + xboxfb_fix.smem_len = fb_size; + tv_init(); + if (tv_encoding == TV_ENC_INVALID) { + tv_encoding = get_tv_encoding(); + printk(KERN_INFO PFX "Setting TV mode from EEPROM (%s)\n", tvEncodingNames[tv_encoding]); + } + default_par->tv_encoding = tv_encoding; + default_par->video_encoder = tv_get_video_encoder(); + switch(default_par->video_encoder) { + case ENCODER_CONEXANT: + printk(KERN_INFO PFX "detected conexant encoder\n"); + break; + case ENCODER_FOCUS: + printk(KERN_INFO PFX "detected focus encoder\n"); + break; + case ENCODER_XLB: + printk(KERN_INFO PFX "detected Xcalibur encoder\n"); + break; + default: + printk(KERN_INFO PFX "detected unknown encoder\n"); + } + + + if (av_type == AV_INVALID) { + av_type = detect_av_type(); + printk(KERN_INFO PFX "Setting cable type from AVIP ID: %s\n", avTypeNames[av_type]); + } + default_par->av_type = av_type; + if ((hoc < 0) || (hoc > 20)) { + hoc = 10; + } + default_par->hoc = hoc / 100.0; + if ((voc < 0) || (voc > 20)) { + voc = 10; + } + default_par->voc = voc / 100.0; + + if (!request_mem_region(xboxfb_fix.mmio_start, + xboxfb_fix.mmio_len, "xboxfb")) { + printk(KERN_ERR PFX "cannot reserve MMIO region\n"); + goto err_out_kfree2; + } + + default_par->ctrl_base = ioremap(xboxfb_fix.mmio_start, + xboxfb_fix.mmio_len); + if (!default_par->ctrl_base) { + printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); + goto err_out_free_base0; + } + + info->par = default_par; + + riva_get_EDID(info, pd); + + riva_get_dfpinfo(info); + + switch (default_par->riva.Architecture) { + case NV_ARCH_03: + /* Riva128's PRAMIN is in the "framebuffer" space + * Since these cards were never made with more than 8 megabytes + * we can safely allocate this separately. + */ + if (!request_mem_region(xboxfb_fix.smem_start + 0x00C00000, + 0x00008000, "xboxfb")) { + printk(KERN_ERR PFX "cannot reserve PRAMIN region\n"); + goto err_out_iounmap_ctrl; + } + default_par->riva.PRAMIN = ioremap(xboxfb_fix.smem_start + 0x00C00000, 0x00008000); + if (!default_par->riva.PRAMIN) { + printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n"); + goto err_out_free_nv3_pramin; + } + xboxfb_fix.accel = FB_ACCEL_NV3; + break; + case NV_ARCH_04: + case NV_ARCH_10: + case NV_ARCH_20: + default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000); + default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000); + xboxfb_fix.accel = FB_ACCEL_NV4; + break; + } + + riva_common_setup(default_par); + + if (default_par->riva.Architecture == NV_ARCH_03) { + default_par->riva.PCRTC = default_par->riva.PCRTC0 = default_par->riva.PGRAPH; + } + + /* xboxfb_fix.smem_len = riva_get_memlen(default_par) * 1024; */ + default_par->dclk_max = riva_get_maxdclk(default_par) * 1000; + + if (!request_mem_region(xboxfb_fix.smem_start, xboxfb_fix.smem_len, "xboxfb")) { + printk(KERN_ERR PFX "cannot reserve FB region\n"); + goto err_out_iounmap_nv3_pramin; + } + + info->screen_base = ioremap(xboxfb_fix.smem_start, fb_size); + if (!info->screen_base) { + printk(KERN_ERR PFX "cannot ioremap FB base\n"); + goto err_out_free_base1; + } + +#ifdef CONFIG_MTRR + if (!nomtrr) { + default_par->mtrr.vram = mtrr_add(xboxfb_fix.smem_start, fb_size, + MTRR_TYPE_WRCOMB, 1); + if (default_par->mtrr.vram < 0) { + printk(KERN_ERR PFX "unable to setup MTRR\n"); + } else { + default_par->mtrr.vram_valid = 1; + /* let there be speed */ + printk(KERN_INFO PFX "RIVA MTRR set to ON\n"); + } + } +#endif /* CONFIG_MTRR */ + + if (riva_set_fbinfo(info) < 0) { + printk(KERN_ERR PFX "error setting initial video mode\n"); + goto err_out_iounmap_fb; + } + + if (register_framebuffer(info) < 0) { + printk(KERN_ERR PFX + "error registering riva framebuffer\n"); + goto err_out_iounmap_fb; + } + + pci_set_drvdata(pd, info); + + printk(KERN_INFO PFX + "PCI nVidia NV%x framebuffer ver %s (%s, %ldMB @ 0x%lX)\n", + default_par->riva.Architecture, + RIVAFB_VERSION, + info->fix.id, + fb_size / (1024 * 1024), + info->fix.smem_start); + return 0; + +err_out_iounmap_fb: + iounmap(info->screen_base); +err_out_free_base1: + release_mem_region(xboxfb_fix.smem_start, fb_size); +err_out_iounmap_nv3_pramin: + if (default_par->riva.Architecture == NV_ARCH_03) + iounmap((caddr_t)default_par->riva.PRAMIN); +err_out_free_nv3_pramin: + if (default_par->riva.Architecture == NV_ARCH_03) + release_mem_region(xboxfb_fix.smem_start + 0x00C00000, 0x00008000); +err_out_iounmap_ctrl: + iounmap(default_par->ctrl_base); +err_out_free_base0: + release_mem_region(xboxfb_fix.mmio_start, xboxfb_fix.mmio_len); +err_out_kfree2: + kfree(info->pixmap.addr); +err_out_kfree1: + kfree(default_par); +err_out_kfree: + kfree(info); +err_out: + return -ENODEV; +} + +static void __exit xboxfb_remove(struct pci_dev *pd) +{ + struct fb_info *info = pci_get_drvdata(pd); + struct riva_par *par = (struct riva_par *) info->par; + + if (!info) + return; + + unregister_framebuffer(info); +#ifdef CONFIG_MTRR + if (par->mtrr.vram_valid) + mtrr_del(par->mtrr.vram, info->fix.smem_start, info->fix.smem_len); +#endif /* CONFIG_MTRR */ + + iounmap(par->ctrl_base); + iounmap(info->screen_base); + + release_mem_region(info->fix.mmio_start, + info->fix.mmio_len); + release_mem_region(info->fix.smem_start, info->fix.smem_len); + + if (par->riva.Architecture == NV_ARCH_03) { + iounmap((caddr_t)par->riva.PRAMIN); + release_mem_region(info->fix.smem_start + 0x00C00000, 0x00008000); + } + kfree(info->pixmap.addr); + kfree(par); + kfree(info); + pci_set_drvdata(pd, NULL); +} + +/* ------------------------------------------------------------------------- * + * + * initialization + * + * ------------------------------------------------------------------------- */ + +#ifndef MODULE +int __init xboxfb_setup(char *options) +{ + char *this_opt; + + if (!options || !*options) + return 0; + + while ((this_opt = strsep(&options, ",")) != NULL) { + if (!strncmp(this_opt, "forceCRTC", 9)) { + char *p; + + p = this_opt + 9; + if (!*p || !*(++p)) continue; + forceCRTC = *p - '0'; + if (forceCRTC < 0 || forceCRTC > 1) + forceCRTC = -1; + } else if (!strncmp(this_opt, "flatpanel", 9)) { + flatpanel = 1; +#ifdef CONFIG_MTRR + } else if (!strncmp(this_opt, "nomtrr", 6)) { + nomtrr = 1; +#endif + } else if (!strncmp(this_opt, "tv=", 3)) { + if(!strncmp(this_opt + 3, "PAL", 3)) { + tv_encoding = TV_ENC_PALBDGHI; + } + else if(!strncmp(this_opt + 3, "NTSC", 4)) { + tv_encoding = TV_ENC_NTSC; + } + else if(!strncmp(this_opt + 3, "VGA", 3)) { + av_type = AV_VGA_SOG; + } + } else if (!strncmp(this_opt, "hoc=", 4)) { + sscanf(this_opt+4, "%d", &hoc); + } else if (!strncmp(this_opt, "voc=", 4)) { + sscanf(this_opt+4, "%d", &voc); + } else + mode_option = this_opt; + } + return 0; +} +#endif /* !MODULE */ + +static struct pci_driver xboxfb_driver = { + .name = "xboxfb", + .id_table = xboxfb_pci_tbl, + .probe = xboxfb_probe, + .remove = __exit_p(xboxfb_remove), +}; + + + +/* ------------------------------------------------------------------------- * + * + * modularization + * + * ------------------------------------------------------------------------- */ + +int __init xboxfb_init(void) +{ + if (pci_register_driver(&xboxfb_driver) > 0) + return 0; + pci_unregister_driver(&xboxfb_driver); + return -ENODEV; +} + + +#ifdef MODULE +static void __exit xboxfb_exit(void) +{ + pci_unregister_driver(&xboxfb_driver); +} + +module_init(xboxfb_init); +module_exit(xboxfb_exit); + +MODULE_PARM(flatpanel, "i"); +MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)"); +MODULE_PARM(forceCRTC, "i"); +MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)"); + +#ifdef CONFIG_MTRR +MODULE_PARM(nomtrr, "i"); +MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)"); +#endif + +MODULE_PARM(tv, "s"); +MODULE_PARM_DESC(tv, "Specifies the TV encoding (\"PAL\", \"NTSC\" or \"VGA\")."); +MODULE_PARM(hoc, "i"); +MODULE_PARM_DESC(hoc, "Horizontal overscan compensation ratio, in % (0-20)"); +MODULE_PARM(voc, "i"); +MODULE_PARM_DESC(voc, "Vertical overscan compensation ratio, in % (0-20)"); + +#endif /* MODULE */ + +MODULE_AUTHOR("Oliver Schwartz"); +MODULE_DESCRIPTION("Framebuffer driver for Xbox"); +MODULE_LICENSE("GPL"); diff -urN linux-2.6.6.orig/drivers/video/xbox/focus.c linux-2.6.6/drivers/video/xbox/focus.c --- linux-2.6.6.orig/drivers/video/xbox/focus.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/focus.c 2004-05-10 12:30:23.195944848 +0100 @@ -0,0 +1,328 @@ +/* + * linux/drivers/video/riva/focus.c - Xbox driver for Focus encoder + * + * Maintainer: David Pye (dmp) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * VGA SoG/internal sync not yet implemented +*/ +#include "focus.h" +#include "encoder.h" + + +static const unsigned char focus_defaults[0xc4] = { + /*0x00*/ 0x00,0x00,0x00,0x00,0x80,0x02,0xaa,0x0a, + /*0x08*/ 0x00,0x10,0x00,0x00,0x03,0x21,0x15,0x04, + /*0x10*/ 0x00,0xe9,0x07,0x00,0x80,0xf5,0x20,0x00, + /*0x18*/ 0xef,0x21,0x1f,0x00,0x03,0x03,0x00,0x00, + /*0x20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00, + /*0x28*/ 0x0c,0x01,0x00,0x00,0x00,0x00,0x08,0x11, + /*0x30*/ 0x00,0x0f,0x05,0xfe,0x0b,0x80,0x00,0x00, + /*0x38*/ 0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /*0x40*/ 0x2a,0x09,0x8a,0xcb,0x00,0x00,0x8d,0x00, + /*0x48*/ 0x7c,0x3c,0x9a,0x2f,0x21,0x01,0x3f,0x00, + /*0x50*/ 0x3e,0x03,0x17,0x21,0x1b,0x1b,0x24,0x9c, + /*0x58*/ 0x01,0x3e,0x0f,0x0f,0x60,0x05,0xc8,0x00, + /*0x60*/ 0x9d,0x04,0x9d,0x01,0x02,0x00,0x0a,0x05, + /*0x68*/ 0x00,0x1a,0xff,0x03,0x1e,0x0f,0x78,0x00, + /*0x70*/ 0x00,0xb1,0x04,0x15,0x49,0x10,0x00,0xa3, + /*0x78*/ 0xc8,0x15,0x05,0x15,0x3e,0x03,0x00,0x20, + /*0x80*/ 0x57,0x2f,0x07,0x00,0x00,0x08,0x00,0x00, + /*0x88*/ 0x08,0x16,0x16,0x9c,0x03,0x00,0x00,0x00, + /*0x90*/ 0x00,0x00,0xc4,0x48,0x00,0x00,0x00,0x00, + /*0x98*/ 0x00,0x00,0x00,0x80,0x00,0x00,0xe4,0x00, + /*0xa0*/ 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, + /*0xa8*/ 0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00, + /*0xb0*/ 0x00,0x00,0xd7,0x05,0x00,0x00,0xf0,0x00, + /*0xb8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /*0xc0*/ 0x00,0x00,0xee,0x00 +}; + +int focus_calc_hdtv_mode( + xbox_hdtv_mode hdtv_mode, + unsigned char pll_int, + unsigned char * regs + ){ + unsigned char b; + int m=0; + int tv_vtotal, tv_htotal, tv_vactive, tv_hactive, vga_htotal, vga_vtotal; + int pll_n, pll_m, pll_p, ncon, ncod; + + memcpy(regs,focus_defaults,sizeof(focus_defaults)); + /* Uncomment for HDTV 480p colour bars */ + //regs[0x0d]|=0x02; + + /* Turn on bridge bypass */ + regs[0x0a] |= 0x10; + /* Turn on the HDTV clock, and turn off the SDTV one */ + regs[0xa1] = 0x04; + + /* HDTV Hor start */ + regs[0xb8] = 0xbe; + + /*Set up video mode to HDTV, progressive, + * and disable YUV matrix bypass */ + regs[0x92] = 0x1a; + regs[0x93] &= ~0x40; + + switch (hdtv_mode) { + case HDTV_480p: + /* PLL settings */ + regs[0x10] = 0x00; + regs[0x11] = 0x00; + regs[0x12] = 0x00; + regs[0x13] = 0x00; + regs[0x14] = 0x00; + regs[0x15] = 0x00; + regs[0x16] = 0x00; + regs[0x17] = 0x00; + regs[0x18] = 0xD7; + regs[0x19] = 0x03; + regs[0x1A] = 0x7C; + regs[0x1B] = 0x00; + regs[0x1C] = 0x07; + regs[0x1D] = 0x07; + /* Porches/HSync width/Luma offset */ + regs[0x94] = 0x3F; + regs[0x95] = 0x2D; + regs[0x96] = 0x3B; + regs[0x97] = 0x00; + regs[0x98] = 0x1B; + regs[0x99] = 0x03; + /* Colour scaling */ + regs[0xA2] = 0x4D; + regs[0xA4] = 0x96; + regs[0xA6] = 0x1D; + regs[0xA8] = 0x58; + regs[0xAA] = 0x8A; + regs[0xAC] = 0x4A; + break; + case HDTV_720p: + /* PLL settings */ + regs[0x10] = 0x00; + regs[0x11] = 0x00; + regs[0x12] = 0x00; + regs[0x13] = 0x00; + regs[0x14] = 0x00; + regs[0x15] = 0x00; + regs[0x16] = 0x00; + regs[0x17] = 0x00; + regs[0x18] = 0x3B; + regs[0x19] = 0x04; + regs[0x1A] = 0xC7; + regs[0x1B] = 0x00; + regs[0x1C] = 0x01; + regs[0x1D] = 0x01; + /* Porches/HSync width/Luma offset */ + regs[0x94] = 0x28; + regs[0x95] = 0x46; + regs[0x96] = 0xDC; + regs[0x97] = 0x00; + regs[0x98] = 0x2C; + regs[0x99] = 0x06; + /* Colour scaling */ + regs[0xA2] = 0x36; + regs[0xA4] = 0xB7; + regs[0xA6] = 0x13; + regs[0xA8] = 0x58; + regs[0xAA] = 0x8A; + regs[0xAC] = 0x4A; + /* HSync timing invert - needed to centre picture */ + regs[0x93] |= 0x01; + + break; + case HDTV_1080i: + /* PLL settings */ + regs[0x10] = 0x00; + regs[0x11] = 0x00; + regs[0x12] = 0x00; + regs[0x13] = 0x00; + regs[0x14] = 0x00; + regs[0x15] = 0x00; + regs[0x16] = 0x00; + regs[0x17] = 0x00; + regs[0x18] = 0x3B; + regs[0x19] = 0x04; + regs[0x1A] = 0xC7; + regs[0x1B] = 0x00; + regs[0x1C] = 0x01; + regs[0x1D] = 0x01; + /* Porches/HSync width/Luma offset */ + regs[0x94] = 0x2C; + regs[0x95] = 0x2C; + regs[0x96] = 0x58; + regs[0x97] = 0x00; + regs[0x98] = 0x6C; + regs[0x99] = 0x08; + /* Colour scaling */ + regs[0xA2] = 0x36; + regs[0xA4] = 0xB7; + regs[0xA6] = 0x13; + regs[0xA8] = 0x58; + regs[0xAA] = 0x8A; + regs[0xAC] = 0x4A; + /* Set mode to interlaced */ + regs[0x92] |= 0x80; + break; + } + return 1; +} + +int focus_calc_mode(xbox_video_mode * mode, struct riva_regs * riva_out) +{ + unsigned char b; + char* regs = riva_out->encoder_mode; + int m = 0; + int tv_htotal, tv_vtotal, tv_vactive, tv_hactive; + int vga_htotal, vga_vtotal; + long ncon, ncod; + int pll_m, pll_n, pll_p, vsc, hsc; + + memcpy(regs,focus_defaults,sizeof(focus_defaults)); + + /* Uncomment for SDTV colour bars */ + //regs[0x45]=0x02; + + switch(mode->tv_encoding) { + case TV_ENC_NTSC: + tv_vtotal=525; + tv_vactive=480; + tv_hactive = 710; + tv_htotal = 858; + regs[0x0d] &= ~0x01; + regs[0x40] = 0x21; + regs[0x41] = 0xF0; + regs[0x42] = 0x7C; + regs[0x43] = 0x1F; + regs[0x49] = 0x44; + regs[0x4a] = 0x76; + regs[0x4b] = 0x3B; + regs[0x4c] = 0x00; + regs[0x60] = 0x89; + regs[0x62] = 0x89; + regs[0x69] = 0x16; + regs[0x6C] = 0x20; + regs[0x74] = 0x04; + regs[0x75] = 0x10; + regs[0x80] = 0x67; + regs[0x81] = 0x21; + regs[0x82] = 0x0C; + regs[0x83] = 0x18; + regs[0x86] = 0x18; + regs[0x89] = 0x13; + regs[0x8A] = 0x13; + break; + case TV_ENC_PALBDGHI: + tv_vtotal = 625; + tv_vactive = 576; + tv_hactive = 702; + tv_htotal = 864; + break; + default: + /* Default to PAL */ + tv_vtotal = 625; + tv_vactive = 576; + tv_hactive = 702; + tv_htotal = 864; + break; + } + + /* Video control - set to RGB input*/ + b = (regs[0x92] &= ~0x04); + regs[0x92] = (b|= 0x01); + regs[0x93] &= ~0x40; + /* Colour scaling */ + regs[0xA2] = 0x4D; + regs[0xA4] = 0x96; + regs[0xA6] = 0x1D; + regs[0xA8] = 0xA0; + regs[0xAA] = 0xDB; + regs[0xAC] = 0x7E; + + tv_vactive = tv_vactive * (1.0f-mode->voc); + vga_vtotal = mode->yres * ((float)tv_vtotal/tv_vactive); + vga_htotal = mode->xres * 1.25f; + tv_hactive = tv_hactive * (1.0f-mode->hoc); + /*These should be calculated or at least deduced. + *However they are good enough for 640x480 -> 800x600 now*/ + pll_n = 32; + pll_m = 512; + pll_p = 4; + + ncon = vga_htotal * vga_vtotal; + ncod = tv_htotal * tv_vtotal * pll_p; + + regs[0x04] = (mode->xres+64)&0xFF; + regs[0x05] = ((mode->xres+64)>>8)&0xFF; + + if (tv_vtotal>vga_vtotal) { + /* Upscaling */ + vsc = ((((float)tv_vtotal/(float)vga_vtotal)-1)*65536); + /* For upscaling, adjust FIFO_LAT (FIFO latency) */ + regs[0x38] = 0x82; + } + else { + /* Downscaling */ + vsc = ((((float)tv_vtotal/(float)vga_vtotal))*65536); + } + regs[0x06] = (vsc)&0xFF; + regs[0x07] = (vsc>>8)&0xFF; + + hsc = 128*((float)tv_hactive/(float)mode->xres-1); + if (tv_hactive > mode->xres) { + /* Upscaling */ + regs[0x08] = 0; + regs[0x09] = hsc&0xFF; + } + else { /* Downscaling */ + hsc = 256 + hsc; + regs[0x08] = hsc&0xFF; + regs[0x09] = 0; + } + + + regs[0x10] = (ncon)&0xFF; + regs[0x11] = (ncon>>8)&0xFF ; + regs[0x12] = (ncon>>16)&0xFF ; + regs[0x13] = (ncon>>24)&0xFF ; + regs[0x14] = (ncod)&0xFF ; + regs[0x15] = (ncod>>8)&0xFF ; + regs[0x16] = (ncod>>16)&0xFF ; + regs[0x17] = (ncod>>24)&0xFF ; + regs[0x18] = (pll_m-17)&0xFF; + regs[0x19] = ((pll_m-17)>>8)&0xFF; + regs[0x1A] = (pll_n-1)&0xFF ; + regs[0x1B] = ((pll_n-1)>>8)&0xFF ; + regs[0x1C] = (pll_p-1)&0xFF; + regs[0x1D] = (pll_p-1)&0xFF; + + /* Guesswork */ + riva_out->ext.vsyncstart = vga_vtotal * 0.95; + riva_out->ext.hsyncstart = vga_htotal * 0.95; + + riva_out->ext.width = mode->xres; + riva_out->ext.height = mode->yres; + riva_out->ext.htotal = vga_htotal - 1; + riva_out->ext.vend = mode->yres - 1; + riva_out->ext.vtotal = vga_vtotal- 1; + riva_out->ext.vcrtc = mode->yres - 1; + riva_out->ext.vsyncend = riva_out->ext.vsyncstart + 3; + riva_out->ext.vvalidstart = 0; + riva_out->ext.vvalidend = mode->yres - 1; + riva_out->ext.hend = mode->xres + 7 ; + riva_out->ext.hcrtc = mode->xres - 1; + riva_out->ext.hsyncend = riva_out->ext.hsyncstart + 32; + riva_out->ext.hvalidstart = 0; + riva_out->ext.hvalidend = mode->xres - 1; + riva_out->ext.crtchdispend = mode->xres; + riva_out->ext.crtcvstart = mode->yres + 32; + //increased from 32 + riva_out->ext.crtcvtotal = mode->yres + 64; + + return 1; +} diff -urN linux-2.6.6.orig/drivers/video/xbox/focus.h linux-2.6.6/drivers/video/xbox/focus.h --- linux-2.6.6.orig/drivers/video/xbox/focus.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/focus.h 2004-05-10 12:30:23.197944544 +0100 @@ -0,0 +1,24 @@ +/* + * linux/drivers/video/riva/focus.c - Xbox driver for Focus encoder + * + * Maintainer: David Pye (dmp) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Known bugs and issues: + * + * none + */ + + +#ifndef focus_h_ +#define focus_h_ + +#include "encoder.h" +#include "xboxfb.h" + +int focus_calc_mode(xbox_video_mode * mode, struct riva_regs * riva_out ); +int focus_calc_hdtv_mode(xbox_hdtv_mode hdtv_mode, unsigned char pll_int, unsigned char * mode_out); +#endif diff -urN linux-2.6.6.orig/drivers/video/xbox/nv_driver.c linux-2.6.6/drivers/video/xbox/nv_driver.c --- linux-2.6.6.orig/drivers/video/xbox/nv_driver.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/nv_driver.c 2004-05-10 12:30:23.201943936 +0100 @@ -0,0 +1,364 @@ +/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * 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 + * DAVID J. MCKAY 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. + */ + +/* + * GPL licensing note -- nVidia is allowing a liberal interpretation of + * the documentation restriction above, to merely say that this nVidia's + * copyright and disclaimer should be included with all code derived + * from this source. -- Jeff Garzik , 01/Nov/99 + */ + +/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.18 2002/08/0 +5 20:47:06 mvojkovi Exp $ */ + +#include +#include +#include +#include "nv_type.h" +#include "xboxfb.h" +#include "nvreg.h" + + +#ifndef CONFIG_PCI /* sanity check */ +#error This driver requires PCI support. +#endif + +#define PFX "rivafb: " + +static inline unsigned char MISCin(struct riva_par *par) +{ + return (VGA_RD08(par->riva.PVIO, 0x3cc)); +} + +static Bool +riva_is_connected(struct riva_par *par, Bool second) +{ + volatile U032 *PRAMDAC = par->riva.PRAMDAC0; + U032 reg52C, reg608; + Bool present; + + if(second) PRAMDAC += 0x800; + + reg52C = PRAMDAC[0x052C/4]; + reg608 = PRAMDAC[0x0608/4]; + + PRAMDAC[0x0608/4] = reg608 & ~0x00010000; + + PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE; + mdelay(1); + PRAMDAC[0x052C/4] |= 1; + + par->riva.PRAMDAC0[0x0610/4] = 0x94050140; + par->riva.PRAMDAC0[0x0608/4] |= 0x00001000; + + mdelay(1); + + present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE; + + par->riva.PRAMDAC0[0x0608/4] &= 0x0000EFFF; + + PRAMDAC[0x052C/4] = reg52C; + PRAMDAC[0x0608/4] = reg608; + + return present; +} + +static void +riva_override_CRTC(struct riva_par *par) +{ + printk(KERN_INFO PFX + "Detected CRTC controller %i being used\n", + par->SecondCRTC ? 1 : 0); + + if(par->forceCRTC != -1) { + printk(KERN_INFO PFX + "Forcing usage of CRTC %i\n", par->forceCRTC); + par->SecondCRTC = par->forceCRTC; + } +} + +static void +riva_is_second(struct riva_par *par) +{ + if (par->FlatPanel == 1) { + switch(par->Chipset) { + case NV_CHIP_GEFORCE4_440_GO: + case NV_CHIP_GEFORCE4_440_GO_M64: + case NV_CHIP_GEFORCE4_420_GO: + case NV_CHIP_GEFORCE4_420_GO_M32: + case NV_CHIP_QUADRO4_500_GOGL: + par->SecondCRTC = TRUE; + break; + default: + par->SecondCRTC = FALSE; + break; + } + } else { + if(riva_is_connected(par, 0)) { + if(par->riva.PRAMDAC0[0x0000052C/4] & 0x100) + par->SecondCRTC = TRUE; + else + par->SecondCRTC = FALSE; + } else + if (riva_is_connected(par, 1)) { + if(par->riva.PRAMDAC0[0x0000252C/4] & 0x100) + par->SecondCRTC = TRUE; + else + par->SecondCRTC = FALSE; + } else /* default */ + par->SecondCRTC = FALSE; + } + riva_override_CRTC(par); +} + +unsigned long riva_get_memlen(struct riva_par *par) +{ + RIVA_HW_INST *chip = &par->riva; + unsigned long memlen = 0; + unsigned int chipset = par->Chipset; + struct pci_dev* dev; + int amt; + + switch (chip->Architecture) { + case NV_ARCH_03: + if (chip->PFB[0x00000000/4] & 0x00000020) { + if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) + && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) { + /* + * SDRAM 128 ZX. + */ + switch (chip->PFB[0x00000000/4] & 0x03) { + case 2: + memlen = 1024 * 4; + break; + case 1: + memlen = 1024 * 2; + break; + default: + memlen = 1024 * 8; + break; + } + } else { + memlen = 1024 * 8; + } + } else { + /* + * SGRAM 128. + */ + switch (chip->PFB[0x00000000/4] & 0x00000003) { + case 0: + memlen = 1024 * 8; + break; + case 2: + memlen = 1024 * 4; + break; + default: + memlen = 1024 * 2; + break; + } + } + break; + case NV_ARCH_04: + if (chip->PFB[0x00000000/4] & 0x00000100) { + memlen = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * + 1024 * 2 + 1024 * 2; + } else { + switch (chip->PFB[0x00000000/4] & 0x00000003) { + case 0: + memlen = 1024 * 32; + break; + case 1: + memlen = 1024 * 4; + break; + case 2: + memlen = 1024 * 8; + break; + case 3: + default: + memlen = 1024 * 16; + break; + } + } + break; + case NV_ARCH_10: + case NV_ARCH_20: + if(chipset == NV_CHIP_IGEFORCE2) { + + dev = pci_find_slot(0, 1); + pci_read_config_dword(dev, 0x7C, &amt); + memlen = (((amt >> 6) & 31) + 1) * 1024; + } else if (chipset == NV_CHIP_0x01F0) { + dev = pci_find_slot(0, 1); + pci_read_config_dword(dev, 0x84, &amt); + memlen = (((amt >> 4) & 127) + 1) * 1024; + } else { + switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF){ + case 0x02: + memlen = 1024 * 2; + break; + case 0x04: + memlen = 1024 * 4; + break; + case 0x08: + memlen = 1024 * 8; + break; + case 0x10: + memlen = 1024 * 16; + break; + case 0x20: + memlen = 1024 * 32; + break; + case 0x40: + memlen = 1024 * 64; + break; + case 0x80: + memlen = 1024 * 128; + break; + default: + memlen = 1024 * 16; + break; + } + } + break; + } + return memlen; +} + +unsigned long riva_get_maxdclk(struct riva_par *par) +{ + RIVA_HW_INST *chip = &par->riva; + unsigned long dclk = 0; + + switch (chip->Architecture) { + case NV_ARCH_03: + if (chip->PFB[0x00000000/4] & 0x00000020) { + if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) + && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) { + /* + * SDRAM 128 ZX. + */ + dclk = 800000; + } else { + dclk = 1000000; + } + } else { + /* + * SGRAM 128. + */ + dclk = 1000000; + } + break; + case NV_ARCH_04: + case NV_ARCH_10: + case NV_ARCH_20: + switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) { + case 3: + dclk = 800000; + break; + default: + dclk = 1000000; + break; + } + break; + } + return dclk; +} + +void +riva_common_setup(struct riva_par *par) +{ + par->riva.EnableIRQ = 0; + par->riva.PRAMDAC0 = (unsigned *)(par->ctrl_base + 0x00680000); + par->riva.PFB = (unsigned *)(par->ctrl_base + 0x00100000); + par->riva.PFIFO = (unsigned *)(par->ctrl_base + 0x00002000); + par->riva.PGRAPH = (unsigned *)(par->ctrl_base + 0x00400000); + par->riva.PEXTDEV = (unsigned *)(par->ctrl_base + 0x00101000); + par->riva.PTIMER = (unsigned *)(par->ctrl_base + 0x00009000); + par->riva.PMC = (unsigned *)(par->ctrl_base + 0x00000000); + par->riva.FIFO = (unsigned *)(par->ctrl_base + 0x00800000); + par->riva.PCIO0 = (U008 *)(par->ctrl_base + 0x00601000); + par->riva.PDIO0 = (U008 *)(par->ctrl_base + 0x00681000); + par->riva.PVIO = (U008 *)(par->ctrl_base + 0x000C0000); + + par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0; + + if (par->FlatPanel == -1) { + switch (par->Chipset) { + case NV_CHIP_GEFORCE4_440_GO: + case NV_CHIP_GEFORCE4_440_GO_M64: + case NV_CHIP_GEFORCE4_420_GO: + case NV_CHIP_GEFORCE4_420_GO_M32: + case NV_CHIP_QUADRO4_500_GOGL: + case NV_CHIP_GEFORCE2_GO: + printk(KERN_INFO PFX + "On a laptop. Assuming Digital Flat Panel\n"); + par->FlatPanel = 1; + break; + default: + break; + } + } + + switch (par->Chipset & 0x0ff0) { + case 0x0110: + if (par->Chipset == NV_CHIP_GEFORCE2_GO) + par->SecondCRTC = TRUE; +#if defined(__powerpc__) + if (par->FlatPanel == 1) + par->SecondCRTC = TRUE; +#endif + riva_override_CRTC(par); + break; + case 0x0170: + case 0x0180: + case 0x01F0: + case 0x0250: + case 0x0280: + riva_is_second(par); + break; + default: + break; + } + + if (par->SecondCRTC) { + par->riva.PCIO = par->riva.PCIO0 + 0x2000; + par->riva.PCRTC = par->riva.PCRTC0 + 0x800; + par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800; + par->riva.PDIO = par->riva.PDIO0 + 0x2000; + } else { + par->riva.PCIO = par->riva.PCIO0; + par->riva.PCRTC = par->riva.PCRTC0; + par->riva.PRAMDAC = par->riva.PRAMDAC0; + par->riva.PDIO = par->riva.PDIO0; + } + + if (par->FlatPanel == -1) { + /* Fix me, need x86 DDC code */ + par->FlatPanel = 0; + } + par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE; +} + diff -urN linux-2.6.6.orig/drivers/video/xbox/nv_type.h linux-2.6.6/drivers/video/xbox/nv_type.h --- linux-2.6.6.orig/drivers/video/xbox/nv_type.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/nv_type.h 2004-05-10 12:30:23.204943480 +0100 @@ -0,0 +1,58 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_type.h,v 1.35 2002/08/05 20:47:06 mvojkovi Exp $ */ + +#ifndef __NV_STRUCT_H__ +#define __NV_STRUCT_H__ + +#define NV_CHIP_RIVA_128 ((PCI_VENDOR_ID_NVIDIA_SGS << 16)| PCI_DEVICE_ID_NVIDIA_RIVA128) +#define NV_CHIP_TNT ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT) +#define NV_CHIP_TNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT2) +#define NV_CHIP_UTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UTNT2) +#define NV_CHIP_VTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_VTNT2) +#define NV_CHIP_UVTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UVTNT2) +#define NV_CHIP_ITNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_ITNT2) +#define NV_CHIP_GEFORCE_256 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_256) +#define NV_CHIP_GEFORCE_DDR ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR) +#define NV_CHIP_QUADRO ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_QUADRO) +#define NV_CHIP_GEFORCE2_MX ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX) +#define NV_CHIP_GEFORCE2_MX_100 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX_100) +#define NV_CHIP_QUADRO2_MXR ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR) +#define NV_CHIP_GEFORCE2_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO) +#define NV_CHIP_GEFORCE2_GTS ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS) +#define NV_CHIP_GEFORCE2_TI ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_TI) +#define NV_CHIP_GEFORCE2_ULTRA ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA) +#define NV_CHIP_QUADRO2_PRO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO) +#define NV_CHIP_GEFORCE4_MX_460 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460) +#define NV_CHIP_GEFORCE4_MX_440 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440) +#define NV_CHIP_GEFORCE4_MX_420 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420) +#define NV_CHIP_GEFORCE4_440_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO) +#define NV_CHIP_GEFORCE4_420_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO) +#define NV_CHIP_GEFORCE4_420_GO_M32 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32) +#define NV_CHIP_QUADRO4_500XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL) +#define NV_CHIP_GEFORCE4_440_GO_M64 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64) +#define NV_CHIP_QUADRO4_200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_200) +#define NV_CHIP_QUADRO4_550XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL) +#define NV_CHIP_QUADRO4_500_GOGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL) +#define NV_CHIP_0x0180 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0180) +#define NV_CHIP_0x0181 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0181) +#define NV_CHIP_0x0182 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0182) +#define NV_CHIP_0x0188 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0188) +#define NV_CHIP_0x018A ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018A) +#define NV_CHIP_0x018B ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018B) +#define NV_CHIP_IGEFORCE2 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_IGEFORCE2) +#define NV_CHIP_0x01F0 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x01F0) +#define NV_CHIP_GEFORCE3 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3) +#define NV_CHIP_GEFORCE3_TI_200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_200) +#define NV_CHIP_GEFORCE3_TI_500 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_500) +#define NV_CHIP_QUADRO_DCC ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO_DCC) +#define NV_CHIP_GEFORCE4_TI_4600 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600) +#define NV_CHIP_GEFORCE4_TI_4400 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400) +#define NV_CHIP_GEFORCE4_TI_4200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200) +#define NV_CHIP_QUADRO4_900XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL) +#define NV_CHIP_QUADRO4_750XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL) +#define NV_CHIP_QUADRO4_700XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL) +#define NV_CHIP_0x0280 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0280) +#define NV_CHIP_0x0281 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0281) +#define NV_CHIP_0x0288 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0288) +#define NV_CHIP_0x0289 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0289) + +#endif /* __NV_STRUCT_H__ */ diff -urN linux-2.6.6.orig/drivers/video/xbox/nvreg.h linux-2.6.6/drivers/video/xbox/nvreg.h --- linux-2.6.6.orig/drivers/video/xbox/nvreg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/nvreg.h 2004-05-10 12:30:23.228939832 +0100 @@ -0,0 +1,188 @@ +/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * 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 + * DAVID J. MCKAY 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. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/nvreg.h,v 3.2.2.1 1998/01/18 10:35:36 hohndel Exp $ */ + +#ifndef __NVREG_H_ +#define __NVREG_H_ + +/* Little macro to construct bitmask for contiguous ranges of bits */ +#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b)) +#define MASKEXPAND(mask) BITMASK(1?mask,0?mask) + +/* Macro to set specific bitfields (mask has to be a macro x:y) ! */ +#define SetBF(mask,value) ((value) << (0?mask)) +#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) ) + +#define MaskAndSetBF(var,mask,value) (var)=(((var)&(~MASKEXPAND(mask)) \ + | SetBF(mask,value))) + +#define DEVICE_BASE(device) (0?NV##_##device) +#define DEVICE_SIZE(device) ((1?NV##_##device) - DEVICE_BASE(device)+1) + +/* This is where we will have to have conditional compilation */ +#define DEVICE_ACCESS(device,reg) \ + nvCONTROL[(NV_##device##_##reg)/4] + +#define DEVICE_WRITE(device,reg,value) DEVICE_ACCESS(device,reg)=(value) +#define DEVICE_READ(device,reg) DEVICE_ACCESS(device,reg) +#define DEVICE_PRINT(device,reg) \ + ErrorF("NV_"#device"_"#reg"=#%08lx\n",DEVICE_ACCESS(device,reg)) +#define DEVICE_DEF(device,mask,value) \ + SetBF(NV_##device##_##mask,NV_##device##_##mask##_##value) +#define DEVICE_VALUE(device,mask,value) SetBF(NV_##device##_##mask,value) +#define DEVICE_MASK(device,mask) MASKEXPAND(NV_##device##_##mask) + +#define PDAC_Write(reg,value) DEVICE_WRITE(PDAC,reg,value) +#define PDAC_Read(reg) DEVICE_READ(PDAC,reg) +#define PDAC_Print(reg) DEVICE_PRINT(PDAC,reg) +#define PDAC_Def(mask,value) DEVICE_DEF(PDAC,mask,value) +#define PDAC_Val(mask,value) DEVICE_VALUE(PDAC,mask,value) +#define PDAC_Mask(mask) DEVICE_MASK(PDAC,mask) + +#define PFB_Write(reg,value) DEVICE_WRITE(PFB,reg,value) +#define PFB_Read(reg) DEVICE_READ(PFB,reg) +#define PFB_Print(reg) DEVICE_PRINT(PFB,reg) +#define PFB_Def(mask,value) DEVICE_DEF(PFB,mask,value) +#define PFB_Val(mask,value) DEVICE_VALUE(PFB,mask,value) +#define PFB_Mask(mask) DEVICE_MASK(PFB,mask) + +#define PRM_Write(reg,value) DEVICE_WRITE(PRM,reg,value) +#define PRM_Read(reg) DEVICE_READ(PRM,reg) +#define PRM_Print(reg) DEVICE_PRINT(PRM,reg) +#define PRM_Def(mask,value) DEVICE_DEF(PRM,mask,value) +#define PRM_Val(mask,value) DEVICE_VALUE(PRM,mask,value) +#define PRM_Mask(mask) DEVICE_MASK(PRM,mask) + +#define PGRAPH_Write(reg,value) DEVICE_WRITE(PGRAPH,reg,value) +#define PGRAPH_Read(reg) DEVICE_READ(PGRAPH,reg) +#define PGRAPH_Print(reg) DEVICE_PRINT(PGRAPH,reg) +#define PGRAPH_Def(mask,value) DEVICE_DEF(PGRAPH,mask,value) +#define PGRAPH_Val(mask,value) DEVICE_VALUE(PGRAPH,mask,value) +#define PGRAPH_Mask(mask) DEVICE_MASK(PGRAPH,mask) + +#define PDMA_Write(reg,value) DEVICE_WRITE(PDMA,reg,value) +#define PDMA_Read(reg) DEVICE_READ(PDMA,reg) +#define PDMA_Print(reg) DEVICE_PRINT(PDMA,reg) +#define PDMA_Def(mask,value) DEVICE_DEF(PDMA,mask,value) +#define PDMA_Val(mask,value) DEVICE_VALUE(PDMA,mask,value) +#define PDMA_Mask(mask) DEVICE_MASK(PDMA,mask) + +#define PTIMER_Write(reg,value) DEVICE_WRITE(PTIMER,reg,value) +#define PTIMER_Read(reg) DEVICE_READ(PTIMER,reg) +#define PTIMER_Print(reg) DEVICE_PRINT(PTIMER,reg) +#define PTIMER_Def(mask,value) DEVICE_DEF(PTIMER,mask,value) +#define PTIMER_Val(mask,value) DEVICE_VALUE(PTIEMR,mask,value) +#define PTIMER_Mask(mask) DEVICE_MASK(PTIMER,mask) + +#define PEXTDEV_Write(reg,value) DEVICE_WRITE(PEXTDEV,reg,value) +#define PEXTDEV_Read(reg) DEVICE_READ(PEXTDEV,reg) +#define PEXTDEV_Print(reg) DEVICE_PRINT(PEXTDEV,reg) +#define PEXTDEV_Def(mask,value) DEVICE_DEF(PEXTDEV,mask,value) +#define PEXTDEV_Val(mask,value) DEVICE_VALUE(PEXTDEV,mask,value) +#define PEXTDEV_Mask(mask) DEVICE_MASK(PEXTDEV,mask) + +#define PFIFO_Write(reg,value) DEVICE_WRITE(PFIFO,reg,value) +#define PFIFO_Read(reg) DEVICE_READ(PFIFO,reg) +#define PFIFO_Print(reg) DEVICE_PRINT(PFIFO,reg) +#define PFIFO_Def(mask,value) DEVICE_DEF(PFIFO,mask,value) +#define PFIFO_Val(mask,value) DEVICE_VALUE(PFIFO,mask,value) +#define PFIFO_Mask(mask) DEVICE_MASK(PFIFO,mask) + +#define PRAM_Write(reg,value) DEVICE_WRITE(PRAM,reg,value) +#define PRAM_Read(reg) DEVICE_READ(PRAM,reg) +#define PRAM_Print(reg) DEVICE_PRINT(PRAM,reg) +#define PRAM_Def(mask,value) DEVICE_DEF(PRAM,mask,value) +#define PRAM_Val(mask,value) DEVICE_VALUE(PRAM,mask,value) +#define PRAM_Mask(mask) DEVICE_MASK(PRAM,mask) + +#define PRAMFC_Write(reg,value) DEVICE_WRITE(PRAMFC,reg,value) +#define PRAMFC_Read(reg) DEVICE_READ(PRAMFC,reg) +#define PRAMFC_Print(reg) DEVICE_PRINT(PRAMFC,reg) +#define PRAMFC_Def(mask,value) DEVICE_DEF(PRAMFC,mask,value) +#define PRAMFC_Val(mask,value) DEVICE_VALUE(PRAMFC,mask,value) +#define PRAMFC_Mask(mask) DEVICE_MASK(PRAMFC,mask) + +#define PMC_Write(reg,value) DEVICE_WRITE(PMC,reg,value) +#define PMC_Read(reg) DEVICE_READ(PMC,reg) +#define PMC_Print(reg) DEVICE_PRINT(PMC,reg) +#define PMC_Def(mask,value) DEVICE_DEF(PMC,mask,value) +#define PMC_Val(mask,value) DEVICE_VALUE(PMC,mask,value) +#define PMC_Mask(mask) DEVICE_MASK(PMC,mask) + +#define PMC_Write(reg,value) DEVICE_WRITE(PMC,reg,value) +#define PMC_Read(reg) DEVICE_READ(PMC,reg) +#define PMC_Print(reg) DEVICE_PRINT(PMC,reg) +#define PMC_Def(mask,value) DEVICE_DEF(PMC,mask,value) +#define PMC_Val(mask,value) DEVICE_VALUE(PMC,mask,value) +#define PMC_Mask(mask) DEVICE_MASK(PMC,mask) + + +#define PBUS_Write(reg,value) DEVICE_WRITE(PBUS,reg,value) +#define PBUS_Read(reg) DEVICE_READ(PBUS,reg) +#define PBUS_Print(reg) DEVICE_PRINT(PBUS,reg) +#define PBUS_Def(mask,value) DEVICE_DEF(PBUS,mask,value) +#define PBUS_Val(mask,value) DEVICE_VALUE(PBUS,mask,value) +#define PBUS_Mask(mask) DEVICE_MASK(PBUS,mask) + + +#define PRAMDAC_Write(reg,value) DEVICE_WRITE(PRAMDAC,reg,value) +#define PRAMDAC_Read(reg) DEVICE_READ(PRAMDAC,reg) +#define PRAMDAC_Print(reg) DEVICE_PRINT(PRAMDAC,reg) +#define PRAMDAC_Def(mask,value) DEVICE_DEF(PRAMDAC,mask,value) +#define PRAMDAC_Val(mask,value) DEVICE_VALUE(PRAMDAC,mask,value) +#define PRAMDAC_Mask(mask) DEVICE_MASK(PRAMDAC,mask) + + +#define PDAC_ReadExt(reg) \ + ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\ + (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\ + (PDAC_Read(INDEX_DATA))) + +#define PDAC_WriteExt(reg,value)\ + ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\ + (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\ + (PDAC_Write(INDEX_DATA,(value)))) + +#define CRTC_Write(index,value) outb((index), 0x3d4); outb(value, 0x3d5) +#define CRTC_Read(index) (outb(index, 0x3d4),inb(0x3d5)) + +#define PCRTC_Write(index,value) CRTC_Write(NV_PCRTC_##index,value) +#define PCRTC_Read(index) CRTC_Read(NV_PCRTC_##index) + +#define PCRTC_Def(mask,value) DEVICE_DEF(PCRTC,mask,value) +#define PCRTC_Val(mask,value) DEVICE_VALUE(PCRTC,mask,value) +#define PCRTC_Mask(mask) DEVICE_MASK(PCRTC,mask) + +#define SR_Write(index,value) outb(0x3c4,(index));outb(0x3c5,value) +#define SR_Read(index) (outb(0x3c4,index),inb(0x3c5)) + +extern volatile unsigned *nvCONTROL; + +typedef enum {NV1,NV3,NV4,NumNVChips} NVChipType; + +NVChipType GetChipType(void); + +#endif + + diff -urN linux-2.6.6.orig/drivers/video/xbox/riva_hw.c linux-2.6.6/drivers/video/xbox/riva_hw.c --- linux-2.6.6.orig/drivers/video/xbox/riva_hw.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/riva_hw.c 2004-05-10 12:30:23.252936184 +0100 @@ -0,0 +1,2253 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ + +/* + * GPL licensing note -- nVidia is allowing a liberal interpretation of + * the documentation restriction above, to merely say that this nVidia's + * copyright and disclaimer should be included with all code derived + * from this source. -- Jeff Garzik , 01/Nov/99 + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.33 2002/08/05 20:47:06 mvojkovi Exp $ */ + +#include +#include +#include "riva_hw.h" +#include "riva_tbl.h" +#include "nv_type.h" + +/* + * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT + * operate identically (except TNT has more memory and better 3D quality. + */ +static int nv3Busy +( + RIVA_HW_INST *chip +) +{ + return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x000006B0/4] & 0x01)); +} +static int nv4Busy +( + RIVA_HW_INST *chip +) +{ + return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01)); +} +static int nv10Busy +( + RIVA_HW_INST *chip +) +{ + return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01)); +} + +static void vgaLockUnlock +( + RIVA_HW_INST *chip, + int Lock +) +{ + U008 cr11; + VGA_WR08(chip->PCIO, 0x3D4, 0x11); + cr11 = VGA_RD08(chip->PCIO, 0x3D5); + if(Lock) cr11 |= 0x80; + else cr11 &= ~0x80; + VGA_WR08(chip->PCIO, 0x3D5, cr11); +} +static void nv3LockUnlock +( + RIVA_HW_INST *chip, + int Lock +) +{ + VGA_WR08(chip->PVIO, 0x3C4, 0x06); + VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57); + vgaLockUnlock(chip, Lock); +} +static void nv4LockUnlock +( + RIVA_HW_INST *chip, + int Lock +) +{ + VGA_WR08(chip->PCIO, 0x3D4, 0x1F); + VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57); + vgaLockUnlock(chip, Lock); +} + +static int ShowHideCursor +( + RIVA_HW_INST *chip, + int ShowHide +) +{ + int cursor; + cursor = chip->CurrentState->cursor1; + chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) | + (ShowHide & 0x01); + VGA_WR08(chip->PCIO, 0x3D4, 0x31); + VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1); + return (cursor & 0x01); +} + +static int nv10ShowHideCursor +( + RIVA_HW_INST *chip, + int ShowHide +) +{ + unsigned int cursor; + cursor = chip->CurrentState->cursorConfig; + chip->CurrentState->cursorConfig = (chip->PCRTC[0x00000810/4] & 0xFFFFFFFE) | + (ShowHide & 0x01); + chip->PCRTC[0x00000810/4] = chip->CurrentState->cursorConfig; + return (cursor & 0x01); +} + +/****************************************************************************\ +* * +* The video arbitration routines calculate some "magic" numbers. Fixes * +* the snow seen when accessing the framebuffer without it. * +* It just works (I hope). * +* * +\****************************************************************************/ + +#define DEFAULT_GR_LWM 100 +#define DEFAULT_VID_LWM 100 +#define DEFAULT_GR_BURST_SIZE 256 +#define DEFAULT_VID_BURST_SIZE 128 +#define VIDEO 0 +#define GRAPHICS 1 +#define MPORT 2 +#define ENGINE 3 +#define GFIFO_SIZE 320 +#define GFIFO_SIZE_128 256 +#define MFIFO_SIZE 120 +#define VFIFO_SIZE 256 +#define ABS(a) (a>0?a:-a) +typedef struct { + int gdrain_rate; + int vdrain_rate; + int mdrain_rate; + int gburst_size; + int vburst_size; + char vid_en; + char gr_en; + int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm; + int by_gfacc; + char vid_only_once; + char gr_only_once; + char first_vacc; + char first_gacc; + char first_macc; + int vocc; + int gocc; + int mocc; + char cur; + char engine_en; + char converged; + int priority; +} nv3_arb_info; +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int graphics_hi_priority; + int media_hi_priority; + int rtl_values; + int valid; +} nv3_fifo_info; +typedef struct { + char pix_bpp; + char enable_video; + char gr_during_vid; + char enable_mp; + int memory_width; + int video_scale; + int pclk_khz; + int mclk_khz; + int mem_page_miss; + int mem_latency; + char mem_aligned; +} nv3_sim_state; +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int valid; +} nv4_fifo_info; +typedef struct { + int pclk_khz; + int mclk_khz; + int nvclk_khz; + char mem_page_miss; + char mem_latency; + int memory_width; + char enable_video; + char gr_during_vid; + char pix_bpp; + char mem_aligned; + char enable_mp; +} nv4_sim_state; +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int valid; +} nv10_fifo_info; +typedef struct { + int pclk_khz; + int mclk_khz; + int nvclk_khz; + char mem_page_miss; + char mem_latency; + int memory_type; + int memory_width; + char enable_video; + char gr_during_vid; + char pix_bpp; + char mem_aligned; + char enable_mp; +} nv10_sim_state; +static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo) +{ + int iter = 0; + int tmp; + int vfsize, mfsize, gfsize; + int mburst_size = 32; + int mmisses, gmisses, vmisses; + int misses; + int vlwm, glwm, mlwm; + int last, next, cur; + int max_gfsize ; + long ns; + + vlwm = 0; + glwm = 0; + mlwm = 0; + vfsize = 0; + gfsize = 0; + cur = ainfo->cur; + mmisses = 2; + gmisses = 2; + vmisses = 2; + if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128; + else max_gfsize = GFIFO_SIZE; + max_gfsize = GFIFO_SIZE; + while (1) + { + if (ainfo->vid_en) + { + if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc; + if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ; + ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz; + vfsize = ns * ainfo->vdrain_rate / 1000000; + vfsize = ainfo->wcvlwm - ainfo->vburst_size + vfsize; + } + if (state->enable_mp) + { + if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc; + } + if (ainfo->gr_en) + { + if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ; + if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc; + ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz; + gfsize = (ns * (long) ainfo->gdrain_rate)/1000000; + gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize; + } + mfsize = 0; + if (!state->gr_during_vid && ainfo->vid_en) + if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once) + next = VIDEO; + else if (ainfo->mocc < 0) + next = MPORT; + else if (ainfo->gocc< ainfo->by_gfacc) + next = GRAPHICS; + else return (0); + else switch (ainfo->priority) + { + case VIDEO: + if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) + next = VIDEO; + else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) + next = GRAPHICS; + else if (ainfo->mocc<0) + next = MPORT; + else return (0); + break; + case GRAPHICS: + if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) + next = GRAPHICS; + else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) + next = VIDEO; + else if (ainfo->mocc<0) + next = MPORT; + else return (0); + break; + default: + if (ainfo->mocc<0) + next = MPORT; + else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) + next = GRAPHICS; + else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) + next = VIDEO; + else return (0); + break; + } + last = cur; + cur = next; + iter++; + switch (cur) + { + case VIDEO: + if (last==cur) misses = 0; + else if (ainfo->first_vacc) misses = vmisses; + else misses = 1; + ainfo->first_vacc = 0; + if (last!=cur) + { + ns = 1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; + vlwm = ns * ainfo->vdrain_rate/ 1000000; + vlwm = ainfo->vocc - vlwm; + } + ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz; + ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000; + ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000; + break; + case GRAPHICS: + if (last==cur) misses = 0; + else if (ainfo->first_gacc) misses = gmisses; + else misses = 1; + ainfo->first_gacc = 0; + if (last!=cur) + { + ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ; + glwm = ns * ainfo->gdrain_rate/1000000; + glwm = ainfo->gocc - glwm; + } + ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz; + ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000; + ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000; + break; + default: + if (last==cur) misses = 0; + else if (ainfo->first_macc) misses = mmisses; + else misses = 1; + ainfo->first_macc = 0; + ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz; + ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000; + ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000; + break; + } + if (iter>100) + { + ainfo->converged = 0; + return (1); + } + ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz; + tmp = ns * ainfo->gdrain_rate/1000000; + if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize) + { + ainfo->converged = 0; + return (1); + } + ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz; + tmp = ns * ainfo->vdrain_rate/1000000; + if (ABS(ainfo->vburst_size) + (ABS(ainfo->wcvlwm + 32) & ~0xf) - tmp> VFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(ainfo->gocc) > max_gfsize) + { + ainfo->converged = 0; + return (1); + } + if (ABS(ainfo->vocc) > VFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(ainfo->mocc) > MFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(vfsize) > VFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(gfsize) > max_gfsize) + { + ainfo->converged = 0; + return (1); + } + if (ABS(mfsize) > MFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + } +} +static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state, nv3_arb_info *ainfo) +{ + long ens, vns, mns, gns; + int mmisses, gmisses, vmisses, eburst_size, mburst_size; + int refresh_cycle; + + refresh_cycle = 0; + refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5; + mmisses = 2; + if (state->mem_aligned) gmisses = 2; + else gmisses = 3; + vmisses = 2; + eburst_size = state->memory_width * 1; + mburst_size = 32; + gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; + ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000; + ainfo->wcmocc = 0; + ainfo->wcgocc = 0; + ainfo->wcvocc = 0; + ainfo->wcvlwm = 0; + ainfo->wcglwm = 0; + ainfo->engine_en = 1; + ainfo->converged = 1; + if (ainfo->engine_en) + { + ens = 1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz; + ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0; + ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0; + ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0; + ainfo->cur = ENGINE; + ainfo->first_vacc = 1; + ainfo->first_gacc = 1; + ainfo->first_macc = 1; + nv3_iterate(res_info, state,ainfo); + } + if (state->enable_mp) + { + mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; + ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000; + ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000; + ainfo->cur = MPORT; + ainfo->first_vacc = 1; + ainfo->first_gacc = 1; + ainfo->first_macc = 0; + nv3_iterate(res_info, state,ainfo); + } + if (ainfo->gr_en) + { + ainfo->first_vacc = 1; + ainfo->first_gacc = 0; + ainfo->first_macc = 1; + gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; + ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000; + ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0; + ainfo->mocc = state->enable_mp ? 0-gns*ainfo->mdrain_rate/1000000: 0; + ainfo->cur = GRAPHICS; + nv3_iterate(res_info, state,ainfo); + } + if (ainfo->vid_en) + { + ainfo->first_vacc = 0; + ainfo->first_gacc = 1; + ainfo->first_macc = 1; + vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; + ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0; + ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ; + ainfo->cur = VIDEO; + nv3_iterate(res_info, state, ainfo); + } + if (ainfo->converged) + { + res_info->graphics_lwm = (int)ABS(ainfo->wcglwm) + 16; + res_info->video_lwm = (int)ABS(ainfo->wcvlwm) + 32; + res_info->graphics_burst_size = ainfo->gburst_size; + res_info->video_burst_size = ainfo->vburst_size; + res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS); + res_info->media_hi_priority = (ainfo->priority == MPORT); + if (res_info->video_lwm > 160) + { + res_info->graphics_lwm = 256; + res_info->video_lwm = 128; + res_info->graphics_burst_size = 64; + res_info->video_burst_size = 64; + res_info->graphics_hi_priority = 0; + res_info->media_hi_priority = 0; + ainfo->converged = 0; + return (0); + } + if (res_info->video_lwm > 128) + { + res_info->video_lwm = 128; + } + return (1); + } + else + { + res_info->graphics_lwm = 256; + res_info->video_lwm = 128; + res_info->graphics_burst_size = 64; + res_info->video_burst_size = 64; + res_info->graphics_hi_priority = 0; + res_info->media_hi_priority = 0; + return (0); + } +} +static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo) +{ + int done, g,v, p; + + done = 0; + for (p=0; p < 2; p++) + { + for (g=128 ; g > 32; g= g>> 1) + { + for (v=128; v >=32; v = v>> 1) + { + ainfo->priority = p; + ainfo->gburst_size = g; + ainfo->vburst_size = v; + done = nv3_arb(res_info, state,ainfo); + if (done && (g==128)) + if ((res_info->graphics_lwm + g) > 256) + done = 0; + if (done) + goto Done; + } + } + } + + Done: + return done; +} +static void nv3CalcArbitration +( + nv3_fifo_info * res_info, + nv3_sim_state * state +) +{ + nv3_fifo_info save_info; + nv3_arb_info ainfo; + char res_gr, res_vid; + + ainfo.gr_en = 1; + ainfo.vid_en = state->enable_video; + ainfo.vid_only_once = 0; + ainfo.gr_only_once = 0; + ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8); + ainfo.vdrain_rate = (int) state->pclk_khz * 2; + if (state->video_scale != 0) + ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale; + ainfo.mdrain_rate = 33000; + res_info->rtl_values = 0; + if (!state->gr_during_vid && state->enable_video) + { + ainfo.gr_only_once = 1; + ainfo.gr_en = 1; + ainfo.gdrain_rate = 0; + res_vid = nv3_get_param(res_info, state, &ainfo); + res_vid = ainfo.converged; + save_info.video_lwm = res_info->video_lwm; + save_info.video_burst_size = res_info->video_burst_size; + ainfo.vid_en = 1; + ainfo.vid_only_once = 1; + ainfo.gr_en = 1; + ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8); + ainfo.vdrain_rate = 0; + res_gr = nv3_get_param(res_info, state, &ainfo); + res_gr = ainfo.converged; + res_info->video_lwm = save_info.video_lwm; + res_info->video_burst_size = save_info.video_burst_size; + res_info->valid = res_gr & res_vid; + } + else + { + if (!ainfo.gr_en) ainfo.gdrain_rate = 0; + if (!ainfo.vid_en) ainfo.vdrain_rate = 0; + res_gr = nv3_get_param(res_info, state, &ainfo); + res_info->valid = ainfo.converged; + } +} +static void nv3UpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv3_fifo_info fifo_data; + nv3_sim_state sim_data; + unsigned int M, N, P, pll, MClk; + + pll = chip->PRAMDAC0[0x00000504/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + MClk = (N * chip->CrystalFreqKHz / M) >> P; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.video_scale = 1; + sim_data.memory_width = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64; + sim_data.memory_width = 128; + + sim_data.mem_latency = 9; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = 11; + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + nv3CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } + else + { + *lwm = 0x24; + *burst = 0x2; + } +} +static void nv4CalcArbitration +( + nv4_fifo_info *fifo, + nv4_sim_state *arb +) +{ + int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align; + int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; + int found, mclk_extra, mclk_loop, cbs, m1, p1; + int mclk_freq, pclk_freq, nvclk_freq, mp_enable; + int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate; + int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm; + int craw, vraw; + + fifo->valid = 1; + pclk_freq = arb->pclk_khz; + mclk_freq = arb->mclk_khz; + nvclk_freq = arb->nvclk_khz; + pagemiss = arb->mem_page_miss; + cas = arb->mem_latency; + width = arb->memory_width >> 6; + video_enable = arb->enable_video; + color_key_enable = arb->gr_during_vid; + bpp = arb->pix_bpp; + align = arb->mem_aligned; + mp_enable = arb->enable_mp; + clwm = 0; + vlwm = 0; + cbs = 128; + pclks = 2; + nvclks = 2; + nvclks += 2; + nvclks += 1; + mclks = 5; + mclks += 3; + mclks += 1; + mclks += cas; + mclks += 1; + mclks += 1; + mclks += 1; + mclks += 1; + mclk_extra = 3; + nvclks += 2; + nvclks += 1; + nvclks += 1; + nvclks += 1; + if (mp_enable) + mclks+=4; + nvclks += 0; + pclks += 0; + found = 0; + vbs = 0; + while (found != 1) + { + fifo->valid = 1; + found = 1; + mclk_loop = mclks+mclk_extra; + us_m = mclk_loop *1000*1000 / mclk_freq; + us_n = nvclks*1000*1000 / nvclk_freq; + us_p = nvclks*1000*1000 / pclk_freq; + if (video_enable) + { + video_drain_rate = pclk_freq * 2; + crtc_drain_rate = pclk_freq * bpp/8; + vpagemiss = 2; + vpagemiss += 1; + crtpagemiss = 2; + vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq; + if (nvclk_freq * 2 > mclk_freq * width) + video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ; + else + video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq; + us_video = vpm_us + us_m + us_n + us_p + video_fill_us; + vlwm = us_video * video_drain_rate/(1000*1000); + vlwm++; + vbs = 128; + if (vlwm > 128) vbs = 64; + if (vlwm > (256-64)) vbs = 32; + if (nvclk_freq * 2 > mclk_freq * width) + video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ; + else + video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq; + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = + us_video + +video_fill_us + +cpm_us + +us_m + us_n +us_p + ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; + } + else + { + crtc_drain_rate = pclk_freq * bpp/8; + crtpagemiss = 2; + crtpagemiss += 1; + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = cpm_us + us_m + us_n + us_p ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; + } + m1 = clwm + cbs - 512; + p1 = m1 * pclk_freq / mclk_freq; + p1 = p1 * bpp / 8; + if ((p1 < m1) && (m1 > 0)) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + else if (video_enable) + { + if ((clwm > 511) || (vlwm > 255)) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + } + else + { + if (clwm > 519) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + } + craw = clwm; + vraw = vlwm; + if (clwm < 384) clwm = 384; + if (vlwm < 128) vlwm = 128; + data = (int)(clwm); + fifo->graphics_lwm = data; + fifo->graphics_burst_size = 128; + data = (int)((vlwm+15)); + fifo->video_lwm = data; + fifo->video_burst_size = vbs; + } +} +static void nv4UpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv4_fifo_info fifo_data; + nv4_sim_state sim_data; + unsigned int M, N, P, pll, MClk, NVClk, cfg1; + + pll = chip->PRAMDAC0[0x00000504/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + MClk = (N * chip->CrystalFreqKHz / M) >> P; + pll = chip->PRAMDAC0[0x00000500/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + NVClk = (N * chip->CrystalFreqKHz / M) >> P; + cfg1 = chip->PFB[0x00000204/4]; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.memory_width = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64; + sim_data.mem_latency = (char)cfg1 & 0x0F; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01)); + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv4CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} +static void nv10CalcArbitration +( + nv10_fifo_info *fifo, + nv10_sim_state *arb +) +{ + int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align; + int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; + int nvclk_fill, us_extra; + int found, mclk_extra, mclk_loop, cbs, m1; + int mclk_freq, pclk_freq, nvclk_freq, mp_enable; + int us_m, us_m_min, us_n, us_p, video_drain_rate, crtc_drain_rate; + int vus_m, vus_n, vus_p; + int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm; + int clwm_rnd_down; + int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2; + int pclks_2_top_fifo, min_mclk_extra; + int us_min_mclk_extra; + + fifo->valid = 1; + pclk_freq = arb->pclk_khz; /* freq in KHz */ + mclk_freq = arb->mclk_khz; + nvclk_freq = arb->nvclk_khz; + pagemiss = arb->mem_page_miss; + cas = arb->mem_latency; + width = arb->memory_width/64; + video_enable = arb->enable_video; + color_key_enable = arb->gr_during_vid; + bpp = arb->pix_bpp; + align = arb->mem_aligned; + mp_enable = arb->enable_mp; + clwm = 0; + vlwm = 1024; + + cbs = 512; + vbs = 512; + + pclks = 4; /* lwm detect. */ + + nvclks = 3; /* lwm -> sync. */ + nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */ + + mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */ + + mclks += 1; /* arb_hp_req */ + mclks += 5; /* ap_hp_req tiling pipeline */ + + mclks += 2; /* tc_req latency fifo */ + mclks += 2; /* fb_cas_n_ memory request to fbio block */ + mclks += 7; /* sm_d_rdv data returned from fbio block */ + + /* fb.rd.d.Put_gc need to accumulate 256 bits for read */ + if (arb->memory_type == 0) + if (arb->memory_width == 64) /* 64 bit bus */ + mclks += 4; + else + mclks += 2; + else + if (arb->memory_width == 64) /* 64 bit bus */ + mclks += 2; + else + mclks += 1; + + if ((!video_enable) && (arb->memory_width == 128)) + { + mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */ + min_mclk_extra = 17; + } + else + { + mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */ + /* mclk_extra = 4; */ /* Margin of error */ + min_mclk_extra = 18; + } + + nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */ + nvclks += 1; /* fbi_d_rdv_n */ + nvclks += 1; /* Fbi_d_rdata */ + nvclks += 1; /* crtfifo load */ + + if(mp_enable) + mclks+=4; /* Mp can get in with a burst of 8. */ + /* Extra clocks determined by heuristics */ + + nvclks += 0; + pclks += 0; + found = 0; + while(found != 1) { + fifo->valid = 1; + found = 1; + mclk_loop = mclks+mclk_extra; + us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */ + us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */ + us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq; + us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */ + us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */ + us_pipe = us_m + us_n + us_p; + us_pipe_min = us_m_min + us_n + us_p; + us_extra = 0; + + vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */ + vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */ + vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */ + vus_pipe = vus_m + vus_n + vus_p; + + if(video_enable) { + video_drain_rate = pclk_freq * 4; /* MB/s */ + crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */ + + vpagemiss = 1; /* self generating page miss */ + vpagemiss += 1; /* One higher priority before */ + + crtpagemiss = 2; /* self generating page miss */ + if(mp_enable) + crtpagemiss += 1; /* if MA0 conflict */ + + vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq; + + us_video = vpm_us + vus_m; /* Video has separate read return path */ + + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = + us_video /* Wait for video */ + +cpm_us /* CRT Page miss */ + +us_m + us_n +us_p /* other latency */ + ; + + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; /* fixed point <= float_point - 1. Fixes that */ + } else { + crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */ + + crtpagemiss = 1; /* self generating page miss */ + crtpagemiss += 1; /* MA0 page miss */ + if(mp_enable) + crtpagemiss += 1; /* if MA0 conflict */ + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = cpm_us + us_m + us_n + us_p ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; /* fixed point <= float_point - 1. Fixes that */ + + /* + // + // Another concern, only for high pclks so don't do this + // with video: + // What happens if the latency to fetch the cbs is so large that + // fifo empties. In that case we need to have an alternate clwm value + // based off the total burst fetch + // + us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ; + us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq; + clwm_mt = us_crt * crtc_drain_rate/(1000*1000); + clwm_mt ++; + if(clwm_mt > clwm) + clwm = clwm_mt; + */ + /* Finally, a heuristic check when width == 64 bits */ + if(width == 1){ + nvclk_fill = nvclk_freq * 8; + if(crtc_drain_rate * 100 >= nvclk_fill * 102) + clwm = 0xfff; /*Large number to fail */ + + else if(crtc_drain_rate * 100 >= nvclk_fill * 98) { + clwm = 1024; + cbs = 512; + us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ; + } + } + } + + + /* + Overfill check: + + */ + + clwm_rnd_down = ((int)clwm/8)*8; + if (clwm_rnd_down < clwm) + clwm += 8; + + m1 = clwm + cbs - 1024; /* Amount of overfill */ + m2us = us_pipe_min + us_min_mclk_extra; + pclks_2_top_fifo = (1024-clwm)/(8*width); + + /* pclk cycles to drain */ + p1clk = m2us * pclk_freq/(1000*1000); + p2 = p1clk * bpp / 8; /* bytes drained. */ + + if((p2 < m1) && (m1 > 0)) { + fifo->valid = 0; + found = 0; + if(min_mclk_extra == 0) { + if(cbs <= 32) { + found = 1; /* Can't adjust anymore! */ + } else { + cbs = cbs/2; /* reduce the burst size */ + } + } else { + min_mclk_extra--; + } + } else { + if (clwm > 1023){ /* Have some margin */ + fifo->valid = 0; + found = 0; + if(min_mclk_extra == 0) + found = 1; /* Can't adjust anymore! */ + else + min_mclk_extra--; + } + } + craw = clwm; + + if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8; + data = (int)(clwm); + /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */ + fifo->graphics_lwm = data; fifo->graphics_burst_size = cbs; + + /* printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */ + fifo->video_lwm = 1024; fifo->video_burst_size = 512; + } +} +static void nv10UpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv10_fifo_info fifo_data; + nv10_sim_state sim_data; + unsigned int M, N, P, pll, MClk, NVClk, cfg1; + + pll = chip->PRAMDAC0[0x00000504/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + MClk = (N * chip->CrystalFreqKHz / M) >> P; + pll = chip->PRAMDAC0[0x00000500/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + NVClk = (N * chip->CrystalFreqKHz / M) >> P; + cfg1 = chip->PFB[0x00000204/4]; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.memory_type = (chip->PFB[0x00000200/4] & 0x01) ? 1 : 0; + sim_data.memory_width = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64; + sim_data.mem_latency = (char)cfg1 & 0x0F; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01)); + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv10CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} + +static void nForceUpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv10_fifo_info fifo_data; + nv10_sim_state sim_data; + unsigned int M, N, P, pll, MClk, NVClk; + unsigned int uMClkPostDiv; + struct pci_dev *dev; + + dev = pci_find_slot(0, 3); + pci_read_config_dword(dev, 0x6C, &uMClkPostDiv); + uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf; + + if(!uMClkPostDiv) uMClkPostDiv = 4; + MClk = 400000 / uMClkPostDiv; + + pll = chip->PRAMDAC0[0x00000500/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + NVClk = (N * chip->CrystalFreqKHz / M) >> P; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + + dev = pci_find_slot(0, 1); + pci_read_config_dword(dev, 0x7C, &sim_data.memory_type); + sim_data.memory_type = (sim_data.memory_type >> 12) & 1; + + sim_data.memory_width = 64; + sim_data.mem_latency = 3; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = 10; + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv10CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} + +/****************************************************************************\ +* * +* RIVA Mode State Routines * +* * +\****************************************************************************/ + +/* + * Calculate the Video Clock parameters for the PLL. + */ +static int CalcVClock +( + int clockIn, + int *clockOut, + int *mOut, + int *nOut, + int *pOut, + RIVA_HW_INST *chip +) +{ + unsigned lowM, highM, highP; + unsigned DeltaNew, DeltaOld; + unsigned VClk, Freq; + unsigned M, N, P; + + DeltaOld = 0xFFFFFFFF; + + VClk = (unsigned)clockIn; + + if (chip->CrystalFreqKHz == 13500) + { + lowM = 7; + highM = 13 - (chip->Architecture == NV_ARCH_03); + } + else + { + lowM = 8; + highM = 14 - (chip->Architecture == NV_ARCH_03); + } + + highP = 4 - (chip->Architecture == NV_ARCH_03); + for (P = 0; P <= highP; P ++) + { + Freq = VClk << P; + if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz)) + { + for (M = lowM; M <= highM; M++) + { + N = (VClk << P) * M / chip->CrystalFreqKHz; + if(N <= 255) { + Freq = (chip->CrystalFreqKHz * N / M) >> P; + if (Freq > VClk) + DeltaNew = Freq - VClk; + else + DeltaNew = VClk - Freq; + if (DeltaNew < DeltaOld) + { + *mOut = M; + *nOut = N; + *pOut = P; + *clockOut = Freq; + DeltaOld = DeltaNew; + } + } + } + } + } + return (DeltaOld != 0xFFFFFFFF); +} +/* + * Calculate extended mode parameters (SVGA) and save in a + * mode state structure. + */ +static void CalcStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state, + int bpp, + int width, + int hDisplaySize, + int height, + int dotClock +) +{ + int pixelDepth, VClk, m, n, p; + /* + * Save mode parameters. + */ + state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */ + state->width = width; + state->height = height; + /* + * Extended RIVA registers. + */ + pixelDepth = (bpp + 1)/8; + CalcVClock(dotClock, &VClk, &m, &n, &p, chip); + + switch (chip->Architecture) + { + case NV_ARCH_03: + nv3UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + state->cursor0 = 0x00; + state->cursor1 = 0x78; + state->cursor2 = 0x00000000; + state->pllsel = 0x10010100; + state->config = ((width + 31)/32) + | (((pixelDepth > 2) ? 3 : pixelDepth) << 8) + | 0x1000; + state->general = 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02; + break; + case NV_ARCH_04: + nv4UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + state->cursor0 = 0x00; + state->cursor1 = 0xFC; + state->cursor2 = 0x00000000; + state->pllsel = 0x10000700; + state->config = 0x00001114; + state->general = bpp == 16 ? 0x00101100 : 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; + break; + case NV_ARCH_10: + case NV_ARCH_20: + if((chip->Chipset == NV_CHIP_IGEFORCE2) || + (chip->Chipset == NV_CHIP_0x01F0)) + { + nForceUpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + } else { + nv10UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + } + state->cursor0 = chip->CursorStart; + state->pllsel = 0x10000700; + state->config = chip->PFB[0x00000200/4]; + state->general = bpp == 16 ? 0x00101100 : 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; + break; + } + + /* Paul Richards: below if block borks things in kernel for some reason */ + /* if((bpp != 8) && (chip->Architecture != NV_ARCH_03)) + state->general |= 0x00000030; */ + + state->vpll = (p << 16) | (n << 8) | m; + state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3; + state->pixel = pixelDepth > 2 ? 3 : pixelDepth; + state->pixel |= 0x80; + state->offset0 = + state->offset1 = + state->offset2 = + state->offset3 = 0; + state->pitch0 = + state->pitch1 = + state->pitch2 = + state->pitch3 = pixelDepth * width; +} +/* + * Load fixed function state and pre-calculated/stored state. + */ +#define LOAD_FIXED_STATE(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev)/8; i++) \ + chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1] +#define LOAD_FIXED_STATE_8BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1] +#define LOAD_FIXED_STATE_15BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1] +#define LOAD_FIXED_STATE_16BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1] +#define LOAD_FIXED_STATE_32BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1] +static void UpdateFifoState +( + RIVA_HW_INST *chip +) +{ + int i; + + switch (chip->Architecture) + { + case NV_ARCH_04: + LOAD_FIXED_STATE(nv4,FIFO); + chip->Tri03 = 0L; + chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]); + break; + case NV_ARCH_10: + case NV_ARCH_20: + /* + * Initialize state for the RivaTriangle3D05 routines. + */ + LOAD_FIXED_STATE(nv10tri05,PGRAPH); + LOAD_FIXED_STATE(nv10,FIFO); + chip->Tri03 = 0L; + chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]); + break; + } +} +static void LoadStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state +) +{ + int i; + + /* + * Load HW fixed function state. + */ + LOAD_FIXED_STATE(Riva,PMC); + LOAD_FIXED_STATE(Riva,PTIMER); + switch (chip->Architecture) + { + case NV_ARCH_03: + /* + * Make sure frame buffer config gets set before loading PRAMIN. + */ + chip->PFB[0x00000200/4] = state->config; + LOAD_FIXED_STATE(nv3,PFIFO); + LOAD_FIXED_STATE(nv3,PRAMIN); + LOAD_FIXED_STATE(nv3,PGRAPH); + switch (state->bpp) + { + case 15: + case 16: + LOAD_FIXED_STATE_15BPP(nv3,PRAMIN); + LOAD_FIXED_STATE_15BPP(nv3,PGRAPH); + chip->Tri03 = (RivaTexturedTriangle03 *)&(chip->FIFO[0x0000E000/4]); + break; + case 24: + case 32: + LOAD_FIXED_STATE_32BPP(nv3,PRAMIN); + LOAD_FIXED_STATE_32BPP(nv3,PGRAPH); + chip->Tri03 = 0L; + break; + case 8: + default: + LOAD_FIXED_STATE_8BPP(nv3,PRAMIN); + LOAD_FIXED_STATE_8BPP(nv3,PGRAPH); + chip->Tri03 = 0L; + break; + } + for (i = 0x00000; i < 0x00800; i++) + chip->PRAMIN[0x00000502 + i] = (i << 12) | 0x03; + chip->PGRAPH[0x00000630/4] = state->offset0; + chip->PGRAPH[0x00000634/4] = state->offset1; + chip->PGRAPH[0x00000638/4] = state->offset2; + chip->PGRAPH[0x0000063C/4] = state->offset3; + chip->PGRAPH[0x00000650/4] = state->pitch0; + chip->PGRAPH[0x00000654/4] = state->pitch1; + chip->PGRAPH[0x00000658/4] = state->pitch2; + chip->PGRAPH[0x0000065C/4] = state->pitch3; + break; + case NV_ARCH_04: + /* + * Make sure frame buffer config gets set before loading PRAMIN. + */ + chip->PFB[0x00000200/4] = state->config; + LOAD_FIXED_STATE(nv4,PFIFO); + LOAD_FIXED_STATE(nv4,PRAMIN); + LOAD_FIXED_STATE(nv4,PGRAPH); + switch (state->bpp) + { + case 15: + LOAD_FIXED_STATE_15BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_15BPP(nv4,PGRAPH); + chip->Tri03 = (RivaTexturedTriangle03 *)&(chip->FIFO[0x0000E000/4]); + break; + case 16: + LOAD_FIXED_STATE_16BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_16BPP(nv4,PGRAPH); + chip->Tri03 = (RivaTexturedTriangle03 *)&(chip->FIFO[0x0000E000/4]); + break; + case 24: + case 32: + LOAD_FIXED_STATE_32BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_32BPP(nv4,PGRAPH); + chip->Tri03 = 0L; + break; + case 8: + default: + LOAD_FIXED_STATE_8BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_8BPP(nv4,PGRAPH); + chip->Tri03 = 0L; + break; + } + chip->PGRAPH[0x00000640/4] = state->offset0; + chip->PGRAPH[0x00000644/4] = state->offset1; + chip->PGRAPH[0x00000648/4] = state->offset2; + chip->PGRAPH[0x0000064C/4] = state->offset3; + chip->PGRAPH[0x00000670/4] = state->pitch0; + chip->PGRAPH[0x00000674/4] = state->pitch1; + chip->PGRAPH[0x00000678/4] = state->pitch2; + chip->PGRAPH[0x0000067C/4] = state->pitch3; + break; + case NV_ARCH_10: + case NV_ARCH_20: + if(chip->twoHeads) { + VGA_WR08(chip->PCIO, 0x03D4, 0x44); + VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner); + chip->LockUnlock(chip, 0); + } + + LOAD_FIXED_STATE(nv10,PFIFO); + LOAD_FIXED_STATE(nv10,PRAMIN); + LOAD_FIXED_STATE(nv10,PGRAPH); + switch (state->bpp) + { + case 15: + LOAD_FIXED_STATE_15BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_15BPP(nv10,PGRAPH); + chip->Tri03 = (RivaTexturedTriangle03 *)&(chip->FIFO[0x0000E000/4]); + break; + case 16: + LOAD_FIXED_STATE_16BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_16BPP(nv10,PGRAPH); + chip->Tri03 = (RivaTexturedTriangle03 *)&(chip->FIFO[0x0000E000/4]); + break; + case 24: + case 32: + LOAD_FIXED_STATE_32BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_32BPP(nv10,PGRAPH); + chip->Tri03 = 0L; + break; + case 8: + default: + LOAD_FIXED_STATE_8BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_8BPP(nv10,PGRAPH); + chip->Tri03 = 0L; + break; + } + + if(chip->Architecture == NV_ARCH_10) { + chip->PGRAPH[0x00000640/4] = state->offset0; + chip->PGRAPH[0x00000644/4] = state->offset1; + chip->PGRAPH[0x00000648/4] = state->offset2; + chip->PGRAPH[0x0000064C/4] = state->offset3; + chip->PGRAPH[0x00000670/4] = state->pitch0; + chip->PGRAPH[0x00000674/4] = state->pitch1; + chip->PGRAPH[0x00000678/4] = state->pitch2; + chip->PGRAPH[0x0000067C/4] = state->pitch3; + chip->PGRAPH[0x00000680/4] = state->pitch3; + } else { + chip->PGRAPH[0x00000820/4] = state->offset0; + chip->PGRAPH[0x00000824/4] = state->offset1; + chip->PGRAPH[0x00000828/4] = state->offset2; + chip->PGRAPH[0x0000082C/4] = state->offset3; + chip->PGRAPH[0x00000850/4] = state->pitch0; + chip->PGRAPH[0x00000854/4] = state->pitch1; + chip->PGRAPH[0x00000858/4] = state->pitch2; + chip->PGRAPH[0x0000085C/4] = state->pitch3; + chip->PGRAPH[0x00000860/4] = state->pitch3; + chip->PGRAPH[0x00000864/4] = state->pitch3; + chip->PGRAPH[0x000009A4/4] = chip->PFB[0x00000200/4]; + chip->PGRAPH[0x000009A8/4] = chip->PFB[0x00000204/4]; + } + if(chip->twoHeads) { + chip->PCRTC0[0x00000860/4] = state->head; + chip->PCRTC0[0x00002860/4] = state->head2; + } + chip->PRAMDAC[0x00000404/4] |= (1 << 25); + + chip->PMC[0x00008704/4] = 1; + chip->PMC[0x00008140/4] = 0; + chip->PMC[0x00008920/4] = 0; + chip->PMC[0x00008924/4] = 0; + chip->PMC[0x00008908/4] = 0x01ffffff; + chip->PMC[0x0000890C/4] = 0x01ffffff; + chip->PMC[0x00001588/4] = 0; + + chip->PFB[0x00000240/4] = 0; + chip->PFB[0x00000244/4] = 0; + chip->PFB[0x00000248/4] = 0; + chip->PFB[0x0000024C/4] = 0; + chip->PFB[0x00000250/4] = 0; + chip->PFB[0x00000254/4] = 0; + chip->PFB[0x00000258/4] = 0; + chip->PFB[0x0000025C/4] = 0; + + chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4]; + chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4]; + chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4]; + chip->PGRAPH[0x00000B0C/4] = chip->PFB[0x0000024C/4]; + chip->PGRAPH[0x00000B10/4] = chip->PFB[0x00000250/4]; + chip->PGRAPH[0x00000B14/4] = chip->PFB[0x00000254/4]; + chip->PGRAPH[0x00000B18/4] = chip->PFB[0x00000258/4]; + chip->PGRAPH[0x00000B1C/4] = chip->PFB[0x0000025C/4]; + chip->PGRAPH[0x00000B20/4] = chip->PFB[0x00000260/4]; + chip->PGRAPH[0x00000B24/4] = chip->PFB[0x00000264/4]; + chip->PGRAPH[0x00000B28/4] = chip->PFB[0x00000268/4]; + chip->PGRAPH[0x00000B2C/4] = chip->PFB[0x0000026C/4]; + chip->PGRAPH[0x00000B30/4] = chip->PFB[0x00000270/4]; + chip->PGRAPH[0x00000B34/4] = chip->PFB[0x00000274/4]; + chip->PGRAPH[0x00000B38/4] = chip->PFB[0x00000278/4]; + chip->PGRAPH[0x00000B3C/4] = chip->PFB[0x0000027C/4]; + chip->PGRAPH[0x00000B40/4] = chip->PFB[0x00000280/4]; + chip->PGRAPH[0x00000B44/4] = chip->PFB[0x00000284/4]; + chip->PGRAPH[0x00000B48/4] = chip->PFB[0x00000288/4]; + chip->PGRAPH[0x00000B4C/4] = chip->PFB[0x0000028C/4]; + chip->PGRAPH[0x00000B50/4] = chip->PFB[0x00000290/4]; + chip->PGRAPH[0x00000B54/4] = chip->PFB[0x00000294/4]; + chip->PGRAPH[0x00000B58/4] = chip->PFB[0x00000298/4]; + chip->PGRAPH[0x00000B5C/4] = chip->PFB[0x0000029C/4]; + chip->PGRAPH[0x00000B60/4] = chip->PFB[0x000002A0/4]; + chip->PGRAPH[0x00000B64/4] = chip->PFB[0x000002A4/4]; + chip->PGRAPH[0x00000B68/4] = chip->PFB[0x000002A8/4]; + chip->PGRAPH[0x00000B6C/4] = chip->PFB[0x000002AC/4]; + chip->PGRAPH[0x00000B70/4] = chip->PFB[0x000002B0/4]; + chip->PGRAPH[0x00000B74/4] = chip->PFB[0x000002B4/4]; + chip->PGRAPH[0x00000B78/4] = chip->PFB[0x000002B8/4]; + chip->PGRAPH[0x00000B7C/4] = chip->PFB[0x000002BC/4]; + chip->PGRAPH[0x00000F40/4] = 0x10000000; + chip->PGRAPH[0x00000F44/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000040; + chip->PGRAPH[0x00000F54/4] = 0x00000008; + chip->PGRAPH[0x00000F50/4] = 0x00000200; + for (i = 0; i < (3*16); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000040; + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000800; + for (i = 0; i < (16*16); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F40/4] = 0x30000000; + chip->PGRAPH[0x00000F44/4] = 0x00000004; + chip->PGRAPH[0x00000F50/4] = 0x00006400; + for (i = 0; i < (59*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00006800; + for (i = 0; i < (47*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00006C00; + for (i = 0; i < (3*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00007000; + for (i = 0; i < (19*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00007400; + for (i = 0; i < (12*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00007800; + for (i = 0; i < (12*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00004400; + for (i = 0; i < (8*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000000; + for (i = 0; i < 16; i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000040; + for (i = 0; i < 4; i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + + chip->PCRTC[0x0000080c/4] = state->cursor0; + chip->PCRTC[0x00000810/4] = state->cursorConfig; + + if(chip->flatPanel) { + if((chip->Chipset & 0x0ff0) == 0x0110) { + chip->PRAMDAC[0x0528/4] = state->dither; + } else + if((chip->Chipset & 0x0ff0) >= 0x0170) { + chip->PRAMDAC[0x083C/4] = state->dither; + } + + VGA_WR08(chip->PCIO, 0x03D4, 0x53); + VGA_WR08(chip->PCIO, 0x03D5, 0); + VGA_WR08(chip->PCIO, 0x03D4, 0x54); + VGA_WR08(chip->PCIO, 0x03D5, 0); + VGA_WR08(chip->PCIO, 0x03D4, 0x21); + VGA_WR08(chip->PCIO, 0x03D5, 0xfa); + } + + VGA_WR08(chip->PCIO, 0x03D4, 0x41); + VGA_WR08(chip->PCIO, 0x03D5, state->extra); + } + LOAD_FIXED_STATE(Riva,FIFO); + UpdateFifoState(chip); + /* + * Load HW mode state. + */ + VGA_WR08(chip->PCIO, 0x03D4, 0x19); + VGA_WR08(chip->PCIO, 0x03D5, state->repaint0); + VGA_WR08(chip->PCIO, 0x03D4, 0x1A); + VGA_WR08(chip->PCIO, 0x03D5, state->repaint1); + VGA_WR08(chip->PCIO, 0x03D4, 0x25); + VGA_WR08(chip->PCIO, 0x03D5, state->screen); + VGA_WR08(chip->PCIO, 0x03D4, 0x28); + VGA_WR08(chip->PCIO, 0x03D5, state->pixel); + VGA_WR08(chip->PCIO, 0x03D4, 0x2D); + VGA_WR08(chip->PCIO, 0x03D5, state->horiz); + VGA_WR08(chip->PCIO, 0x03D4, 0x1B); + VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0); + VGA_WR08(chip->PCIO, 0x03D4, 0x20); + VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1); + VGA_WR08(chip->PCIO, 0x03D4, 0x30); + VGA_WR08(chip->PCIO, 0x03D4, 0x39); + VGA_WR08(chip->PCIO, 0x03D5, state->interlace); + + if(!chip->flatPanel) { + chip->PRAMDAC0[0x00000508/4] = state->vpll; + chip->PRAMDAC0[0x0000050C/4] = state->pllsel; + if(chip->twoHeads) + chip->PRAMDAC0[0x00000520/4] = state->vpll2; + } else { + chip->PRAMDAC[0x00000848/4] = state->scale; + } + chip->PRAMDAC[0x00000600/4] = state->general; + chip->PCRTC[0x00000800/4] = state->fb_start; + chip->PRAMDAC[0x00000800/4] = state->vend; + chip->PRAMDAC[0x00000804/4] = state->vtotal; + chip->PRAMDAC[0x00000808/4] = state->vcrtc; + chip->PRAMDAC[0x0000080c/4] = state->vsyncstart; + chip->PRAMDAC[0x00000810/4] = state->vsyncend; + chip->PRAMDAC[0x00000814/4] = state->vvalidstart; + chip->PRAMDAC[0x00000818/4] = state->vvalidend; + chip->PRAMDAC[0x00000820/4] = state->hend; + chip->PRAMDAC[0x00000824/4] = state->htotal; + chip->PRAMDAC[0x00000828/4] = state->hcrtc; + chip->PRAMDAC[0x0000082c/4] = state->hsyncstart; + chip->PRAMDAC[0x00000830/4] = state->hsyncend; + chip->PRAMDAC[0x00000834/4] = state->hvalidstart; + chip->PRAMDAC[0x00000838/4] = state->hvalidend; + chip->PRAMDAC[0x00000840/4] = state->checksum ; + + /* + * Turn off VBlank enable and reset. + */ + chip->PCRTC[0x00000140/4] = 0; + chip->PCRTC[0x00000100/4] = chip->VBlankBit; + /* + * Set interrupt enable. + */ + chip->PMC[0x00000140/4] = chip->EnableIRQ & 0x01; + /* + * Set current state pointer. + */ + chip->CurrentState = state; + /* + * Reset FIFO free and empty counts. + */ + chip->FifoFreeCount = 0; + /* Free count from first subchannel */ + chip->FifoEmptyCount = chip->Rop->FifoFree; +} +static void UnloadStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state +) +{ + /* + * Save current HW state. + */ + VGA_WR08(chip->PCIO, 0x03D4, 0x19); + state->repaint0 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x1A); + state->repaint1 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x25); + state->screen = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x28); + state->pixel = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x2D); + state->horiz = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x1B); + state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x20); + state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x39); + state->interlace = VGA_RD08(chip->PCIO, 0x03D5); + state->vpll = chip->PRAMDAC0[0x00000508/4]; + state->vpll2 = chip->PRAMDAC0[0x00000520/4]; + state->pllsel = chip->PRAMDAC0[0x0000050C/4]; + state->general = chip->PRAMDAC[0x00000600/4]; + state->scale = chip->PRAMDAC[0x00000848/4]; + state->config = chip->PFB[0x00000200/4]; + switch (chip->Architecture) + { + case NV_ARCH_03: + state->offset0 = chip->PGRAPH[0x00000630/4]; + state->offset1 = chip->PGRAPH[0x00000634/4]; + state->offset2 = chip->PGRAPH[0x00000638/4]; + state->offset3 = chip->PGRAPH[0x0000063C/4]; + state->pitch0 = chip->PGRAPH[0x00000650/4]; + state->pitch1 = chip->PGRAPH[0x00000654/4]; + state->pitch2 = chip->PGRAPH[0x00000658/4]; + state->pitch3 = chip->PGRAPH[0x0000065C/4]; + VGA_WR08(chip->PCIO, 0x03D4, 0x30); + state->cursor0 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x31); + state->cursor1 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x2F); + state->cursor2 = VGA_RD08(chip->PCIO, 0x03D5); + break; + case NV_ARCH_04: + state->offset0 = chip->PGRAPH[0x00000640/4]; + state->offset1 = chip->PGRAPH[0x00000644/4]; + state->offset2 = chip->PGRAPH[0x00000648/4]; + state->offset3 = chip->PGRAPH[0x0000064C/4]; + state->pitch0 = chip->PGRAPH[0x00000670/4]; + state->pitch1 = chip->PGRAPH[0x00000674/4]; + state->pitch2 = chip->PGRAPH[0x00000678/4]; + state->pitch3 = chip->PGRAPH[0x0000067C/4]; + VGA_WR08(chip->PCIO, 0x03D4, 0x30); + state->cursor0 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x31); + state->cursor1 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x2F); + state->cursor2 = VGA_RD08(chip->PCIO, 0x03D5); + break; + case NV_ARCH_10: + case NV_ARCH_20: + state->offset0 = chip->PGRAPH[0x00000640/4]; + state->offset1 = chip->PGRAPH[0x00000644/4]; + state->offset2 = chip->PGRAPH[0x00000648/4]; + state->offset3 = chip->PGRAPH[0x0000064C/4]; + state->pitch0 = chip->PGRAPH[0x00000670/4]; + state->pitch1 = chip->PGRAPH[0x00000674/4]; + state->pitch2 = chip->PGRAPH[0x00000678/4]; + state->pitch3 = chip->PGRAPH[0x0000067C/4]; + if(chip->twoHeads) { + state->head = chip->PCRTC0[0x00000860/4]; + state->head2 = chip->PCRTC0[0x00002860/4]; + VGA_WR08(chip->PCIO, 0x03D4, 0x44); + state->crtcOwner = VGA_RD08(chip->PCIO, 0x03D5); + } + VGA_WR08(chip->PCIO, 0x03D4, 0x41); + state->extra = VGA_RD08(chip->PCIO, 0x03D5); + state->cursorConfig = chip->PCRTC[0x00000810/4]; + + if((chip->Chipset & 0x0ff0) == 0x0110) { + state->dither = chip->PRAMDAC[0x0528/4]; + } else + if((chip->Chipset & 0x0ff0) >= 0x0170) { + state->dither = chip->PRAMDAC[0x083C/4]; + } + state->fb_start = chip->PCRTC[0x00000800/4]; + state->cursor0 = chip->PCRTC[0x0000080c/4]; + state->vend = chip->PRAMDAC[0x00000800/4]; + state->vtotal = chip->PRAMDAC[0x00000804/4]; + state->vcrtc = chip->PRAMDAC[0x00000808/4]; + state->vsyncstart = chip->PRAMDAC[0x0000080c/4]; + state->vsyncend = chip->PRAMDAC[0x00000810/4]; + state->vvalidstart = chip->PRAMDAC[0x00000814/4]; + state->vvalidend = chip->PRAMDAC[0x00000818/4]; + state->hend = chip->PRAMDAC[0x00000820/4]; + state->htotal = chip->PRAMDAC[0x00000824/4]; + state->hcrtc = chip->PRAMDAC[0x00000828/4]; + state->hsyncstart = chip->PRAMDAC[0x0000082c/4]; + state->hsyncend = chip->PRAMDAC[0x00000830/4]; + state->hvalidstart = chip->PRAMDAC[0x00000834/4]; + state->hvalidend = chip->PRAMDAC[0x00000838/4]; + state->checksum = chip->PRAMDAC[0x00000840/4]; + break; + } +} +static void SetStartAddress +( + RIVA_HW_INST *chip, + unsigned start +) +{ + chip->PCRTC[0x800/4] = start; +} + +static void SetStartAddress3 +( + RIVA_HW_INST *chip, + unsigned start +) +{ + int offset = start >> 2; + int pan = (start & 3) << 1; + unsigned char tmp; + + /* + * Unlock extended registers. + */ + chip->LockUnlock(chip, 0); + /* + * Set start address. + */ + VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset); + offset >>= 8; + VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset); + offset >>= 8; + VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5); + VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F)); + VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5); + VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60)); + /* + * 4 pixel pan register. + */ + offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A); + VGA_WR08(chip->PCIO, 0x3C0, 0x13); + VGA_WR08(chip->PCIO, 0x3C0, pan); +} +static void nv3SetSurfaces2D +( + RIVA_HW_INST *chip, + unsigned surf0, + unsigned surf1 +) +{ + RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]); + + RIVA_FIFO_FREE(*chip,Tri03,5); + chip->FIFO[0x00003800] = 0x80000003; + Surface->Offset = surf0; + chip->FIFO[0x00003800] = 0x80000004; + Surface->Offset = surf1; + chip->FIFO[0x00003800] = 0x80000013; +} +static void nv4SetSurfaces2D +( + RIVA_HW_INST *chip, + unsigned surf0, + unsigned surf1 +) +{ + RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]); + + chip->FIFO[0x00003800] = 0x80000003; + Surface->Offset = surf0; + chip->FIFO[0x00003800] = 0x80000004; + Surface->Offset = surf1; + chip->FIFO[0x00003800] = 0x80000014; +} +static void nv10SetSurfaces2D +( + RIVA_HW_INST *chip, + unsigned surf0, + unsigned surf1 +) +{ + RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]); + + chip->FIFO[0x00003800] = 0x80000003; + Surface->Offset = surf0; + chip->FIFO[0x00003800] = 0x80000004; + Surface->Offset = surf1; + chip->FIFO[0x00003800] = 0x80000014; +} +static void nv3SetSurfaces3D +( + RIVA_HW_INST *chip, + unsigned surf0, + unsigned surf1 +) +{ + RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]); + + RIVA_FIFO_FREE(*chip,Tri03,5); + chip->FIFO[0x00003800] = 0x80000005; + Surface->Offset = surf0; + chip->FIFO[0x00003800] = 0x80000006; + Surface->Offset = surf1; + chip->FIFO[0x00003800] = 0x80000013; +} +static void nv4SetSurfaces3D +( + RIVA_HW_INST *chip, + unsigned surf0, + unsigned surf1 +) +{ + RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]); + + chip->FIFO[0x00003800] = 0x80000005; + Surface->Offset = surf0; + chip->FIFO[0x00003800] = 0x80000006; + Surface->Offset = surf1; + chip->FIFO[0x00003800] = 0x80000014; +} +static void nv10SetSurfaces3D +( + RIVA_HW_INST *chip, + unsigned surf0, + unsigned surf1 +) +{ + RivaSurface3D *Surfaces3D = (RivaSurface3D *)&(chip->FIFO[0x0000E000/4]); + + RIVA_FIFO_FREE(*chip,Tri03,4); + chip->FIFO[0x00003800] = 0x80000007; + Surfaces3D->RenderBufferOffset = surf0; + Surfaces3D->ZBufferOffset = surf1; + chip->FIFO[0x00003800] = 0x80000014; +} + +/****************************************************************************\ +* * +* Probe RIVA Chip Configuration * +* * +\****************************************************************************/ + +static void nv3GetConfig +( + RIVA_HW_INST *chip +) +{ + /* + * Fill in chip configuration. + */ + if (chip->PFB[0x00000000/4] & 0x00000020) + { + if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) + && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) + { + /* + * SDRAM 128 ZX. + */ + chip->RamBandwidthKBytesPerSec = 800000; + switch (chip->PFB[0x00000000/4] & 0x03) + { + case 2: + chip->RamAmountKBytes = 1024 * 4; + break; + case 1: + chip->RamAmountKBytes = 1024 * 2; + break; + default: + chip->RamAmountKBytes = 1024 * 8; + break; + } + } + else + { + chip->RamBandwidthKBytesPerSec = 1000000; + chip->RamAmountKBytes = 1024 * 8; + } + } + else + { + /* + * SGRAM 128. + */ + chip->RamBandwidthKBytesPerSec = 1000000; + switch (chip->PFB[0x00000000/4] & 0x00000003) + { + case 0: + chip->RamAmountKBytes = 1024 * 8; + break; + case 2: + chip->RamAmountKBytes = 1024 * 4; + break; + default: + chip->RamAmountKBytes = 1024 * 2; + break; + } + } + chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; + chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]); + chip->VBlankBit = 0x00000100; + chip->MaxVClockFreqKHz = 256000; + /* + * Set chip functions. + */ + chip->Busy = nv3Busy; + chip->ShowHideCursor = ShowHideCursor; + chip->CalcStateExt = CalcStateExt; + chip->LoadStateExt = LoadStateExt; + chip->UnloadStateExt = UnloadStateExt; + chip->SetStartAddress = SetStartAddress3; + chip->SetSurfaces2D = nv3SetSurfaces2D; + chip->SetSurfaces3D = nv3SetSurfaces3D; + chip->LockUnlock = nv3LockUnlock; +} +static void nv4GetConfig +( + RIVA_HW_INST *chip +) +{ + /* + * Fill in chip configuration. + */ + if (chip->PFB[0x00000000/4] & 0x00000100) + { + chip->RamAmountKBytes = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * 1024 * 2 + + 1024 * 2; + } + else + { + switch (chip->PFB[0x00000000/4] & 0x00000003) + { + case 0: + chip->RamAmountKBytes = 1024 * 32; + break; + case 1: + chip->RamAmountKBytes = 1024 * 4; + break; + case 2: + chip->RamAmountKBytes = 1024 * 8; + break; + case 3: + default: + chip->RamAmountKBytes = 1024 * 16; + break; + } + } + switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) + { + case 3: + chip->RamBandwidthKBytesPerSec = 800000; + break; + default: + chip->RamBandwidthKBytesPerSec = 1000000; + break; + } + chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; + chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]); + chip->VBlankBit = 0x00000001; + chip->MaxVClockFreqKHz = 350000; + /* + * Set chip functions. + */ + chip->Busy = nv4Busy; + chip->ShowHideCursor = ShowHideCursor; + chip->CalcStateExt = CalcStateExt; + chip->LoadStateExt = LoadStateExt; + chip->UnloadStateExt = UnloadStateExt; + chip->SetStartAddress = SetStartAddress; + chip->SetSurfaces2D = nv4SetSurfaces2D; + chip->SetSurfaces3D = nv4SetSurfaces3D; + chip->LockUnlock = nv4LockUnlock; +} +static void nv10GetConfig +( + RIVA_HW_INST *chip, + unsigned int chipset +) +{ + struct pci_dev* dev; + int amt; + +#ifdef __BIG_ENDIAN + /* turn on big endian register access */ + chip->PMC[0x00000004/4] = 0x01000001; +#endif + + /* + * Fill in chip configuration. + */ + if(chipset == NV_CHIP_IGEFORCE2) { + dev = pci_find_slot(0, 1); + pci_read_config_dword(dev, 0x7C, &amt); + chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; + } else if(chipset == NV_CHIP_0x01F0) { + dev = pci_find_slot(0, 1); + pci_read_config_dword(dev, 0x84, &amt); + chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; + } else { + switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF) + { + case 0x02: + chip->RamAmountKBytes = 1024 * 2; + break; + case 0x04: + chip->RamAmountKBytes = 1024 * 4; + break; + case 0x08: + chip->RamAmountKBytes = 1024 * 8; + break; + case 0x10: + chip->RamAmountKBytes = 1024 * 16; + break; + case 0x20: + chip->RamAmountKBytes = 1024 * 32; + break; + case 0x40: + chip->RamAmountKBytes = 1024 * 64; + break; + case 0x80: + chip->RamAmountKBytes = 1024 * 128; + break; + default: + chip->RamAmountKBytes = 1024 * 16; + break; + } + } + switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) + { + case 3: + chip->RamBandwidthKBytesPerSec = 800000; + break; + default: + chip->RamBandwidthKBytesPerSec = 1000000; + break; + } + chip->CrystalFreqKHz = (chip->PEXTDEV[0x0000/4] & (1 << 6)) ? 14318 : + 13500; + + switch (chipset & 0x0ff0) { + case 0x0170: + case 0x0180: + case 0x01F0: + case 0x0250: + case 0x0280: + if(chip->PEXTDEV[0x0000/4] & (1 << 22)) + chip->CrystalFreqKHz = 27000; + break; + default: + break; + } + + chip->CursorStart = (chip->RamAmountKBytes - 2) * 1024; + chip->CURSOR = NULL; /* can't set this here */ + chip->VBlankBit = 0x00000001; + chip->MaxVClockFreqKHz = 350000; + /* + * Set chip functions. + */ + chip->Busy = nv10Busy; + chip->ShowHideCursor = nv10ShowHideCursor; + chip->CalcStateExt = CalcStateExt; + chip->LoadStateExt = LoadStateExt; + chip->UnloadStateExt = UnloadStateExt; + chip->SetStartAddress = SetStartAddress; + chip->SetSurfaces2D = nv10SetSurfaces2D; + chip->SetSurfaces3D = nv10SetSurfaces3D; + chip->LockUnlock = nv4LockUnlock; + + switch(chipset & 0x0ff0) { + case 0x0110: + case 0x0170: + case 0x0180: + case 0x01F0: + case 0x0250: + case 0x0280: + chip->twoHeads = TRUE; + break; + default: + chip->twoHeads = FALSE; + break; + } +} +int RivaGetConfig +( + RIVA_HW_INST *chip, + unsigned int chipset +) +{ + /* + * Save this so future SW know whats it's dealing with. + */ + chip->Version = RIVA_SW_VERSION; + /* + * Chip specific configuration. + */ + switch (chip->Architecture) + { + case NV_ARCH_03: + nv3GetConfig(chip); + break; + case NV_ARCH_04: + nv4GetConfig(chip); + break; + case NV_ARCH_10: + case NV_ARCH_20: + nv10GetConfig(chip, chipset); + break; + default: + return (-1); + } + chip->Chipset = chipset; + /* + * Fill in FIFO pointers. + */ + chip->Rop = (RivaRop *)&(chip->FIFO[0x00000000/4]); + chip->Clip = (RivaClip *)&(chip->FIFO[0x00002000/4]); + chip->Patt = (RivaPattern *)&(chip->FIFO[0x00004000/4]); + chip->Pixmap = (RivaPixmap *)&(chip->FIFO[0x00006000/4]); + chip->Blt = (RivaScreenBlt *)&(chip->FIFO[0x00008000/4]); + chip->Bitmap = (RivaBitmap *)&(chip->FIFO[0x0000A000/4]); + chip->Line = (RivaLine *)&(chip->FIFO[0x0000C000/4]); + chip->Tri03 = (RivaTexturedTriangle03 *)&(chip->FIFO[0x0000E000/4]); + return (0); +} + diff -urN linux-2.6.6.orig/drivers/video/xbox/riva_hw.h linux-2.6.6/drivers/video/xbox/riva_hw.h --- linux-2.6.6.orig/drivers/video/xbox/riva_hw.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/riva_hw.h 2004-05-10 12:30:23.257935424 +0100 @@ -0,0 +1,566 @@ +/***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| +\***************************************************************************/ + +/* + * GPL licensing note -- nVidia is allowing a liberal interpretation of + * the documentation restriction above, to merely say that this nVidia's + * copyright and disclaimer should be included with all code derived + * from this source. -- Jeff Garzik , 01/Nov/99 + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.21 2002/10/14 18:22:46 mvojkovi Exp $ */ +#ifndef __RIVA_HW_H__ +#define __RIVA_HW_H__ +#define RIVA_SW_VERSION 0x00010003 + +#ifndef Bool +typedef int Bool; +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif + +/* + * Typedefs to force certain sized values. + */ +typedef unsigned char U008; +typedef unsigned short U016; +typedef unsigned int U032; + +/* + * HW access macros. + */ +#if defined(__powerpc__) +#include +#define NV_WR08(p,i,d) out_8(p+i, d) +#define NV_RD08(p,i) in_8(p+i) +#else +#define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d)) +#define NV_RD08(p,i) (((U008 *)(p))[i]) +#endif +#define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d)) +#define NV_RD16(p,i) (((U016 *)(p))[(i)/2]) +#define NV_WR32(p,i,d) (((U032 *)(p))[(i)/4]=(d)) +#define NV_RD32(p,i) (((U032 *)(p))[(i)/4]) +#define VGA_WR08(p,i,d) NV_WR08(p,i,d) +#define VGA_RD08(p,i) NV_RD08(p,i) + +/* + * Define supported architectures. + */ +#define NV_ARCH_03 0x03 +#define NV_ARCH_04 0x04 +#define NV_ARCH_10 0x10 +#define NV_ARCH_20 0x20 + +/***************************************************************************\ +* * +* FIFO registers. * +* * +\***************************************************************************/ + +/* + * Raster OPeration. Windows style ROP3. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 Rop3; +} RivaRop; +/* + * 8X8 Monochrome pattern. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BD]; + U032 Shape; + U032 reserved03[0x001]; + U032 Color0; + U032 Color1; + U032 Monochrome[2]; +} RivaPattern; +/* + * Scissor clip rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 TopLeft; + U032 WidthHeight; +} RivaClip; +/* + * 2D filled rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop[1]; +#endif + U032 reserved01[0x0BC]; + U032 Color; + U032 reserved03[0x03E]; + U032 TopLeft; + U032 WidthHeight; +} RivaRectangle; +/* + * 2D screen-screen BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 TopLeftSrc; + U032 TopLeftDst; + U032 WidthHeight; +} RivaScreenBlt; +/* + * 2D pixel BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop[1]; +#endif + U032 reserved01[0x0BC]; + U032 TopLeft; + U032 WidthHeight; + U032 WidthHeightIn; + U032 reserved02[0x03C]; + U032 Pixels; +} RivaPixmap; +/* + * Filled rectangle combined with monochrome expand. Useful for glyphs. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 reserved03[(0x040)-1]; + U032 Color1A; + struct + { + U032 TopLeft; + U032 WidthHeight; + } UnclippedRectangle[64]; + U032 reserved04[(0x080)-3]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipB; + U032 Color1B; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClippedRectangle[64]; + U032 reserved05[(0x080)-5]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipC; + U032 Color1C; + U032 WidthHeightC; + U032 PointC; + U032 MonochromeData1C; + U032 reserved06[(0x080)+121]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipD; + U032 Color1D; + U032 WidthHeightInD; + U032 WidthHeightOutD; + U032 PointD; + U032 MonochromeData1D; + U032 reserved07[(0x080)+120]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipE; + U032 Color0E; + U032 Color1E; + U032 WidthHeightInE; + U032 WidthHeightOutE; + U032 PointE; + U032 MonochromeData01E; +} RivaBitmap; +/* + * 3D textured, Z buffered triangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BC]; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 FogColor; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 AlphaTest; + U032 reserved02[0x339]; + U032 FogAndIndex; + U032 Color; + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + float TextureS; + float TextureT; +} RivaTexturedTriangle03; +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 ColorKey; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 Blend; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 FogColor; + U032 reserved02[0x39]; + struct + { + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + U032 Color; + U032 Specular; + float TextureS; + float TextureT; + } Vertex[16]; + U032 DrawTriangle3D; +} RivaTexturedTriangle05; +/* + * 2D line. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop[1]; +#endif + U032 reserved01[0x0BC]; + U032 Color; /* source color 0304-0307*/ + U032 Reserved02[0x03e]; + struct { /* start aliased methods in array 0400- */ + U032 point0; /* y_x S16_S16 in pixels 0- 3*/ + U032 point1; /* y_x S16_S16 in pixels 4- 7*/ + } Lin[16]; /* end of aliased methods in array -047f*/ + struct { /* start aliased methods in array 0480- */ + U032 point0X; /* in pixels, 0 at left 0- 3*/ + U032 point0Y; /* in pixels, 0 at top 4- 7*/ + U032 point1X; /* in pixels, 0 at left 8- b*/ + U032 point1Y; /* in pixels, 0 at top c- f*/ + } Lin32[8]; /* end of aliased methods in array -04ff*/ + U032 PolyLin[32]; /* y_x S16_S16 in pixels 0500-057f*/ + struct { /* start aliased methods in array 0580- */ + U032 x; /* in pixels, 0 at left 0- 3*/ + U032 y; /* in pixels, 0 at top 4- 7*/ + } PolyLin32[16]; /* end of aliased methods in array -05ff*/ + struct { /* start aliased methods in array 0600- */ + U032 color; /* source color 0- 3*/ + U032 point; /* y_x S16_S16 in pixels 4- 7*/ + } ColorPolyLin[16]; /* end of aliased methods in array -067f*/ +} RivaLine; +/* + * 2D/3D surfaces + */ +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BE]; + U032 Offset; +} RivaSurface; +typedef volatile struct +{ + U032 reserved00[4]; +#ifdef __BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BD]; + U032 Pitch; + U032 RenderBufferOffset; + U032 ZBufferOffset; +} RivaSurface3D; + +/***************************************************************************\ +* * +* Virtualized RIVA H/W interface. * +* * +\***************************************************************************/ + +#define FP_ENABLE 1 +#define FP_DITHER 2 + +struct _riva_hw_inst; +struct _riva_hw_state; +/* + * Virtialized chip interface. Makes RIVA 128 and TNT look alike. + */ +typedef struct _riva_hw_inst +{ + /* + * Chip specific settings. + */ + U032 Architecture; + U032 Version; + U032 Chipset; + U032 CrystalFreqKHz; + U032 RamAmountKBytes; + U032 MaxVClockFreqKHz; + U032 RamBandwidthKBytesPerSec; + U032 EnableIRQ; + U032 IO; + U032 VBlankBit; + U032 FifoFreeCount; + U032 FifoEmptyCount; + U032 CursorStart; + U032 flatPanel; + Bool twoHeads; + /* + * Non-FIFO registers. + */ + volatile U032 *PCRTC0; + volatile U032 *PCRTC; + volatile U032 *PRAMDAC0; + volatile U032 *PFB; + volatile U032 *PFIFO; + volatile U032 *PGRAPH; + volatile U032 *PEXTDEV; + volatile U032 *PTIMER; + volatile U032 *PMC; + volatile U032 *PRAMIN; + volatile U032 *FIFO; + volatile U032 *CURSOR; + volatile U008 *PCIO0; + volatile U008 *PCIO; + volatile U008 *PVIO; + volatile U008 *PDIO0; + volatile U008 *PDIO; + volatile U032 *PRAMDAC; + /* + * Common chip functions. + */ + int (*Busy)(struct _riva_hw_inst *); + void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int); + void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*SetStartAddress)(struct _riva_hw_inst *,U032); + void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032); + void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032); + int (*ShowHideCursor)(struct _riva_hw_inst *,int); + void (*LockUnlock)(struct _riva_hw_inst *, int); + /* + * Current extended mode settings. + */ + struct _riva_hw_state *CurrentState; + /* + * FIFO registers. + */ + RivaRop *Rop; + RivaPattern *Patt; + RivaClip *Clip; + RivaPixmap *Pixmap; + RivaScreenBlt *Blt; + RivaBitmap *Bitmap; + RivaLine *Line; + RivaTexturedTriangle03 *Tri03; + RivaTexturedTriangle05 *Tri05; +} RIVA_HW_INST; +/* + * Extended mode state information. + */ +typedef struct _riva_hw_state +{ + U032 bpp; + U032 width; + U032 height; + U032 interlace; + U032 repaint0; + U032 repaint1; + U032 screen; + U032 scale; + U032 dither; + U032 extra; + U032 pixel; + U032 horiz; + U032 arbitration0; + U032 arbitration1; + U032 vpll; + U032 vpll2; + U032 pllsel; + U032 general; + U032 crtcOwner; + U032 head; + U032 head2; + U032 config; + U032 cursorConfig; + U032 cursor0; + U032 cursor1; + U032 cursor2; + U032 offset0; + U032 offset1; + U032 offset2; + U032 offset3; + U032 pitch0; + U032 pitch1; + U032 pitch2; + U032 pitch3; + U032 fb_start; + U032 vend; + U032 vtotal; + U032 vcrtc; + U032 vsyncstart; + U032 vsyncend; + U032 vvalidstart; + U032 vvalidend; + U032 hend; + U032 htotal; + U032 hcrtc; + U032 hsyncstart; + U032 hsyncend; + U032 hvalidstart; + U032 hvalidend; + U032 crtchdispend; + U032 crtcvstart; + U032 crtcvtotal; + U032 checksum; +} RIVA_HW_STATE; +/* + * External routines. + */ +int RivaGetConfig(RIVA_HW_INST *, unsigned int); +/* + * FIFO Free Count. Should attempt to yield processor if RIVA is busy. + */ + +#define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \ +{ \ + while ((hwinst).FifoFreeCount < (cnt)) \ + (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2; \ + (hwinst).FifoFreeCount -= (cnt); \ +} +#endif /* __RIVA_HW_H__ */ + diff -urN linux-2.6.6.orig/drivers/video/xbox/riva_tbl.h linux-2.6.6/drivers/video/xbox/riva_tbl.h --- linux-2.6.6.orig/drivers/video/xbox/riva_tbl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/riva_tbl.h 2004-05-10 12:30:23.268933752 +0100 @@ -0,0 +1,1008 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ + +/* + * GPL licensing note -- nVidia is allowing a liberal interpretation of + * the documentation restriction above, to merely say that this nVidia's + * copyright and disclaimer should be included with all code derived + * from this source. -- Jeff Garzik , 01/Nov/99 + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.9 2002/01/30 01:35:03 mvojkovi Exp $ */ + + +/* + * RIVA Fixed Functionality Init Tables. + */ +static unsigned RivaTablePMC[][2] = +{ + {0x00000050, 0x00000000}, + {0x00000080, 0xFFFF00FF}, + {0x00000080, 0xFFFFFFFF} +}; +static unsigned RivaTablePTIMER[][2] = +{ + {0x00000080, 0x00000008}, + {0x00000084, 0x00000003}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF} +}; +static unsigned RivaTableFIFO[][2] = +{ + {0x00000000, 0x80000000}, + {0x00000800, 0x80000001}, + {0x00001000, 0x80000002}, + {0x00001800, 0x80000010}, + {0x00002000, 0x80000011}, + {0x00002800, 0x80000012}, + {0x00003000, 0x80000016}, + {0x00003800, 0x80000013} +}; +static unsigned nv3TablePFIFO[][2] = +{ + {0x00000140, 0x00000000}, + {0x00000480, 0x00000000}, + {0x00000490, 0x00000000}, + {0x00000494, 0x00000000}, + {0x00000481, 0x00000000}, + {0x00000084, 0x00000000}, + {0x00000086, 0x00002000}, + {0x00000085, 0x00002200}, + {0x00000484, 0x00000000}, + {0x0000049C, 0x00000000}, + {0x00000104, 0x00000000}, + {0x00000108, 0x00000000}, + {0x00000100, 0x00000000}, + {0x000004A0, 0x00000000}, + {0x000004A4, 0x00000000}, + {0x000004A8, 0x00000000}, + {0x000004AC, 0x00000000}, + {0x000004B0, 0x00000000}, + {0x000004B4, 0x00000000}, + {0x000004B8, 0x00000000}, + {0x000004BC, 0x00000000}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000480, 0x00000001}, + {0x00000490, 0x00000001}, + {0x00000140, 0x00000001} +}; +static unsigned nv3TablePGRAPH[][2] = +{ + {0x00000020, 0x1230001F}, + {0x00000021, 0x10113000}, + {0x00000022, 0x1131F101}, + {0x00000023, 0x0100F531}, + {0x00000060, 0x00000000}, + {0x00000065, 0x00000000}, + {0x00000068, 0x00000000}, + {0x00000069, 0x00000000}, + {0x0000006A, 0x00000000}, + {0x0000006B, 0x00000000}, + {0x0000006C, 0x00000000}, + {0x0000006D, 0x00000000}, + {0x0000006E, 0x00000000}, + {0x0000006F, 0x00000000}, + {0x000001A8, 0x00000000}, + {0x00000440, 0xFFFFFFFF}, + {0x00000480, 0x00000001}, + {0x000001A0, 0x00000000}, + {0x000001A2, 0x00000000}, + {0x0000018A, 0xFFFFFFFF}, + {0x00000190, 0x00000000}, + {0x00000142, 0x00000000}, + {0x00000154, 0x00000000}, + {0x00000155, 0xFFFFFFFF}, + {0x00000156, 0x00000000}, + {0x00000157, 0xFFFFFFFF}, + {0x00000064, 0x10010002}, + {0x00000050, 0x00000000}, + {0x00000051, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000041, 0xFFFFFFFF}, + {0x00000440, 0xFFFFFFFF}, + {0x000001A9, 0x00000001} +}; +static unsigned nv3TablePGRAPH_8BPP[][2] = +{ + {0x000001AA, 0x00001111} +}; +static unsigned nv3TablePGRAPH_15BPP[][2] = +{ + {0x000001AA, 0x00002222} +}; +static unsigned nv3TablePGRAPH_32BPP[][2] = +{ + {0x000001AA, 0x00003333} +}; +static unsigned nv3TablePRAMIN[][2] = +{ + {0x00000500, 0x00010000}, + {0x00000501, 0x007FFFFF}, + {0x00000200, 0x80000000}, + {0x00000201, 0x00C20341}, + {0x00000204, 0x80000001}, + {0x00000205, 0x00C50342}, + {0x00000208, 0x80000002}, + {0x00000209, 0x00C60343}, + {0x0000020C, 0x80000003}, + {0x0000020D, 0x00DC0348}, + {0x00000210, 0x80000004}, + {0x00000211, 0x00DC0349}, + {0x00000214, 0x80000005}, + {0x00000215, 0x00DC034A}, + {0x00000218, 0x80000006}, + {0x00000219, 0x00DC034B}, + {0x00000240, 0x80000010}, + {0x00000241, 0x00D10344}, + {0x00000244, 0x80000011}, + {0x00000245, 0x00D00345}, + {0x00000248, 0x80000012}, + {0x00000249, 0x00CC0346}, + {0x0000024C, 0x80000013}, + {0x0000024D, 0x00D70347}, + {0x00000258, 0x80000016}, + {0x00000259, 0x00CA034C}, + {0x00000D05, 0x00000000}, + {0x00000D06, 0x00000000}, + {0x00000D07, 0x00000000}, + {0x00000D09, 0x00000000}, + {0x00000D0A, 0x00000000}, + {0x00000D0B, 0x00000000}, + {0x00000D0D, 0x00000000}, + {0x00000D0E, 0x00000000}, + {0x00000D0F, 0x00000000}, + {0x00000D11, 0x00000000}, + {0x00000D12, 0x00000000}, + {0x00000D13, 0x00000000}, + {0x00000D15, 0x00000000}, + {0x00000D16, 0x00000000}, + {0x00000D17, 0x00000000}, + {0x00000D19, 0x00000000}, + {0x00000D1A, 0x00000000}, + {0x00000D1B, 0x00000000}, + {0x00000D1D, 0x00000140}, + {0x00000D1E, 0x00000000}, + {0x00000D1F, 0x00000000}, + {0x00000D20, 0x10100200}, + {0x00000D21, 0x00000000}, + {0x00000D22, 0x00000000}, + {0x00000D23, 0x00000000}, + {0x00000D24, 0x10210200}, + {0x00000D25, 0x00000000}, + {0x00000D26, 0x00000000}, + {0x00000D27, 0x00000000}, + {0x00000D28, 0x10420200}, + {0x00000D29, 0x00000000}, + {0x00000D2A, 0x00000000}, + {0x00000D2B, 0x00000000}, + {0x00000D2C, 0x10830200}, + {0x00000D2D, 0x00000000}, + {0x00000D2E, 0x00000000}, + {0x00000D2F, 0x00000000}, + {0x00000D31, 0x00000000}, + {0x00000D32, 0x00000000}, + {0x00000D33, 0x00000000} +}; +static unsigned nv3TablePRAMIN_8BPP[][2] = +{ + /* 0xXXXXX3XX For MSB mono format */ + /* 0xXXXXX2XX For LSB mono format */ + {0x00000D04, 0x10110203}, + {0x00000D08, 0x10110203}, + {0x00000D0C, 0x1011020B}, + {0x00000D10, 0x10118203}, + {0x00000D14, 0x10110203}, + {0x00000D18, 0x10110203}, + {0x00000D1C, 0x10419208}, + {0x00000D30, 0x10118203} +}; +static unsigned nv3TablePRAMIN_15BPP[][2] = +{ + /* 0xXXXXX2XX For MSB mono format */ + /* 0xXXXXX3XX For LSB mono format */ + {0x00000D04, 0x10110200}, + {0x00000D08, 0x10110200}, + {0x00000D0C, 0x10110208}, + {0x00000D10, 0x10118200}, + {0x00000D14, 0x10110200}, + {0x00000D18, 0x10110200}, + {0x00000D1C, 0x10419208}, + {0x00000D30, 0x10118200} +}; +static unsigned nv3TablePRAMIN_32BPP[][2] = +{ + /* 0xXXXXX3XX For MSB mono format */ + /* 0xXXXXX2XX For LSB mono format */ + {0x00000D04, 0x10110201}, + {0x00000D08, 0x10110201}, + {0x00000D0C, 0x10110209}, + {0x00000D10, 0x10118201}, + {0x00000D14, 0x10110201}, + {0x00000D18, 0x10110201}, + {0x00000D1C, 0x10419208}, + {0x00000D30, 0x10118201} +}; +static unsigned nv4TableFIFO[][2] = +{ + {0x00003800, 0x80000014} +}; +static unsigned nv4TablePFIFO[][2] = +{ + {0x00000140, 0x00000000}, + {0x00000480, 0x00000000}, + {0x00000494, 0x00000000}, + {0x00000481, 0x00000000}, + {0x0000048B, 0x00000000}, + {0x00000400, 0x00000000}, + {0x00000414, 0x00000000}, + {0x00000084, 0x03000100}, + {0x00000085, 0x00000110}, + {0x00000086, 0x00000112}, + {0x00000143, 0x0000FFFF}, + {0x00000496, 0x0000FFFF}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000415, 0x00000001}, + {0x00000480, 0x00000001}, + {0x00000494, 0x00000001}, + {0x00000495, 0x00000001}, + {0x00000140, 0x00000001} +}; +static unsigned nv4TablePGRAPH[][2] = +{ + {0x00000020, 0x1231C001}, + {0x00000021, 0x72111101}, + {0x00000022, 0x11D5F071}, + {0x00000023, 0x10D4FF31}, + {0x00000060, 0x00000000}, + {0x00000068, 0x00000000}, + {0x00000070, 0x00000000}, + {0x00000078, 0x00000000}, + {0x00000061, 0x00000000}, + {0x00000069, 0x00000000}, + {0x00000071, 0x00000000}, + {0x00000079, 0x00000000}, + {0x00000062, 0x00000000}, + {0x0000006A, 0x00000000}, + {0x00000072, 0x00000000}, + {0x0000007A, 0x00000000}, + {0x00000063, 0x00000000}, + {0x0000006B, 0x00000000}, + {0x00000073, 0x00000000}, + {0x0000007B, 0x00000000}, + {0x00000064, 0x00000000}, + {0x0000006C, 0x00000000}, + {0x00000074, 0x00000000}, + {0x0000007C, 0x00000000}, + {0x00000065, 0x00000000}, + {0x0000006D, 0x00000000}, + {0x00000075, 0x00000000}, + {0x0000007D, 0x00000000}, + {0x00000066, 0x00000000}, + {0x0000006E, 0x00000000}, + {0x00000076, 0x00000000}, + {0x0000007E, 0x00000000}, + {0x00000067, 0x00000000}, + {0x0000006F, 0x00000000}, + {0x00000077, 0x00000000}, + {0x0000007F, 0x00000000}, + {0x00000058, 0x00000000}, + {0x00000059, 0x00000000}, + {0x0000005A, 0x00000000}, + {0x0000005B, 0x00000000}, + {0x00000196, 0x00000000}, + {0x000001A1, 0x01FFFFFF}, + {0x00000197, 0x00000000}, + {0x000001A2, 0x01FFFFFF}, + {0x00000198, 0x00000000}, + {0x000001A3, 0x01FFFFFF}, + {0x00000199, 0x00000000}, + {0x000001A4, 0x01FFFFFF}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x0000005C, 0x10010100}, + {0x000001C4, 0xFFFFFFFF}, + {0x000001C8, 0x00000001}, + {0x00000204, 0x00000000}, + {0x000001C3, 0x00000001} +}; +static unsigned nv4TablePGRAPH_8BPP[][2] = +{ + {0x000001C9, 0x00111111}, + {0x00000186, 0x00001010}, + {0x0000020C, 0x03020202} +}; +static unsigned nv4TablePGRAPH_15BPP[][2] = +{ + {0x000001C9, 0x00226222}, + {0x00000186, 0x00002071}, + {0x0000020C, 0x09080808} +}; +static unsigned nv4TablePGRAPH_16BPP[][2] = +{ + {0x000001C9, 0x00556555}, + {0x00000186, 0x000050C2}, + {0x0000020C, 0x0C0B0B0B} +}; +static unsigned nv4TablePGRAPH_32BPP[][2] = +{ + {0x000001C9, 0x0077D777}, + {0x00000186, 0x000070E5}, + {0x0000020C, 0x0E0D0D0D} +}; +static unsigned nv4TablePRAMIN[][2] = +{ + {0x00000000, 0x80000010}, + {0x00000001, 0x80011145}, + {0x00000002, 0x80000011}, + {0x00000003, 0x80011146}, + {0x00000004, 0x80000012}, + {0x00000005, 0x80011147}, + {0x00000006, 0x80000013}, + {0x00000007, 0x80011148}, + {0x00000008, 0x80000014}, + {0x00000009, 0x80011149}, + {0x0000000A, 0x80000015}, + {0x0000000B, 0x8001114A}, + {0x0000000C, 0x80000016}, + {0x0000000D, 0x8001114F}, + {0x00000020, 0x80000000}, + {0x00000021, 0x80011142}, + {0x00000022, 0x80000001}, + {0x00000023, 0x80011143}, + {0x00000024, 0x80000002}, + {0x00000025, 0x80011144}, + {0x00000026, 0x80000003}, + {0x00000027, 0x8001114B}, + {0x00000028, 0x80000004}, + {0x00000029, 0x8001114C}, + {0x0000002A, 0x80000005}, + {0x0000002B, 0x8001114D}, + {0x0000002C, 0x80000006}, + {0x0000002D, 0x8001114E}, + {0x00000500, 0x00003000}, + {0x00000501, 0x01FFFFFF}, + {0x00000502, 0x00000002}, + {0x00000503, 0x00000002}, + {0x00000508, 0x01008043}, + {0x0000050A, 0x00000000}, + {0x0000050B, 0x00000000}, + {0x0000050C, 0x01008019}, + {0x0000050E, 0x00000000}, + {0x0000050F, 0x00000000}, +#if 1 + {0x00000510, 0x01008018}, +#else + {0x00000510, 0x01008044}, +#endif + {0x00000512, 0x00000000}, + {0x00000513, 0x00000000}, + {0x00000514, 0x01008021}, + {0x00000516, 0x00000000}, + {0x00000517, 0x00000000}, + {0x00000518, 0x0100805F}, + {0x0000051A, 0x00000000}, + {0x0000051B, 0x00000000}, +#if 1 + {0x0000051C, 0x0100804B}, +#else + {0x0000051C, 0x0100804A}, +#endif + {0x0000051E, 0x00000000}, + {0x0000051F, 0x00000000}, + {0x00000520, 0x0100A048}, + {0x00000521, 0x00000D01}, + {0x00000522, 0x11401140}, + {0x00000523, 0x00000000}, + {0x00000524, 0x0300A054}, + {0x00000525, 0x00000D01}, + {0x00000526, 0x11401140}, + {0x00000527, 0x00000000}, + {0x00000528, 0x0300A055}, + {0x00000529, 0x00000D01}, + {0x0000052A, 0x11401140}, + {0x0000052B, 0x00000000}, + {0x0000052C, 0x00000058}, + {0x0000052E, 0x11401140}, + {0x0000052F, 0x00000000}, + {0x00000530, 0x00000059}, + {0x00000532, 0x11401140}, + {0x00000533, 0x00000000}, + {0x00000534, 0x0000005A}, + {0x00000536, 0x11401140}, + {0x00000537, 0x00000000}, + {0x00000538, 0x0000005B}, + {0x0000053A, 0x11401140}, + {0x0000053B, 0x00000000}, + {0x0000053C, 0x0300A01C}, + {0x0000053E, 0x11401140}, + {0x0000053F, 0x00000000} +}; +static unsigned nv4TablePRAMIN_8BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000302}, + {0x0000050D, 0x00000302}, + {0x00000511, 0x00000202}, + {0x00000515, 0x00000302}, + {0x00000519, 0x00000302}, + {0x0000051D, 0x00000302}, + {0x0000052D, 0x00000302}, + {0x0000052E, 0x00000302}, + {0x00000535, 0x00000000}, + {0x00000539, 0x00000000}, + {0x0000053D, 0x00000302} +}; +static unsigned nv4TablePRAMIN_15BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000902}, + {0x0000050D, 0x00000902}, + {0x00000511, 0x00000802}, + {0x00000515, 0x00000902}, + {0x00000519, 0x00000902}, + {0x0000051D, 0x00000902}, + {0x0000052D, 0x00000902}, + {0x0000052E, 0x00000902}, + {0x00000535, 0x00000702}, + {0x00000539, 0x00000702}, + {0x0000053D, 0x00000902} +}; +static unsigned nv4TablePRAMIN_16BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000C02}, + {0x0000050D, 0x00000C02}, + {0x00000511, 0x00000B02}, + {0x00000515, 0x00000C02}, + {0x00000519, 0x00000C02}, + {0x0000051D, 0x00000C02}, + {0x0000052D, 0x00000C02}, + {0x0000052E, 0x00000C02}, + {0x00000535, 0x00000702}, + {0x00000539, 0x00000702}, + {0x0000053D, 0x00000C02} +}; +static unsigned nv4TablePRAMIN_32BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000E02}, + {0x0000050D, 0x00000E02}, + {0x00000511, 0x00000D02}, + {0x00000515, 0x00000E02}, + {0x00000519, 0x00000E02}, + {0x0000051D, 0x00000E02}, + {0x0000052D, 0x00000E02}, + {0x0000052E, 0x00000E02}, + {0x00000535, 0x00000E02}, + {0x00000539, 0x00000E02}, + {0x0000053D, 0x00000E02} +}; +static unsigned nv10TableFIFO[][2] = +{ + {0x00003800, 0x80000014} +}; +static unsigned nv10TablePFIFO[][2] = +{ + {0x00000140, 0x00000000}, + {0x00000480, 0x00000000}, + {0x00000494, 0x00000000}, + {0x00000481, 0x00000000}, + {0x0000048B, 0x00000000}, + {0x00000400, 0x00000000}, + {0x00000414, 0x00000000}, + {0x00000084, 0x03000100}, + {0x00000085, 0x00000110}, + {0x00000086, 0x00000112}, + {0x00000143, 0x0000FFFF}, + {0x00000496, 0x0000FFFF}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000415, 0x00000001}, + {0x00000480, 0x00000001}, + {0x00000494, 0x00000001}, + {0x00000495, 0x00000001}, + {0x00000140, 0x00000001} +}; +static unsigned nv10TablePGRAPH[][2] = +{ + {0x00000020, 0x0003FFFF}, + {0x00000021, 0x00118701}, + {0x00000022, 0x24F82AD9}, + {0x00000023, 0x55DE0030}, + {0x00000020, 0x00000000}, + {0x00000024, 0x00000000}, + {0x00000058, 0x00000000}, + {0x00000060, 0x00000000}, + {0x00000068, 0x00000000}, + {0x00000070, 0x00000000}, + {0x00000078, 0x00000000}, + {0x00000059, 0x00000000}, + {0x00000061, 0x00000000}, + {0x00000069, 0x00000000}, + {0x00000071, 0x00000000}, + {0x00000079, 0x00000000}, + {0x0000005A, 0x00000000}, + {0x00000062, 0x00000000}, + {0x0000006A, 0x00000000}, + {0x00000072, 0x00000000}, + {0x0000007A, 0x00000000}, + {0x0000005B, 0x00000000}, + {0x00000063, 0x00000000}, + {0x0000006B, 0x00000000}, + {0x00000073, 0x00000000}, + {0x0000007B, 0x00000000}, + {0x0000005C, 0x00000000}, + {0x00000064, 0x00000000}, + {0x0000006C, 0x00000000}, + {0x00000074, 0x00000000}, + {0x0000007C, 0x00000000}, + {0x0000005D, 0x00000000}, + {0x00000065, 0x00000000}, + {0x0000006D, 0x00000000}, + {0x00000075, 0x00000000}, + {0x0000007D, 0x00000000}, + {0x0000005E, 0x00000000}, + {0x00000066, 0x00000000}, + {0x0000006E, 0x00000000}, + {0x00000076, 0x00000000}, + {0x0000007E, 0x00000000}, + {0x0000005F, 0x00000000}, + {0x00000067, 0x00000000}, + {0x0000006F, 0x00000000}, + {0x00000077, 0x00000000}, + {0x0000007F, 0x00000000}, + {0x00000053, 0x00000000}, + {0x00000054, 0x00000000}, + {0x00000055, 0x00000000}, + {0x00000056, 0x00000000}, + {0x00000057, 0x00000000}, + {0x00000196, 0x00000000}, + {0x000001A1, 0x01FFFFFF}, + {0x00000197, 0x00000000}, + {0x000001A2, 0x01FFFFFF}, + {0x00000198, 0x00000000}, + {0x000001A3, 0x01FFFFFF}, + {0x00000199, 0x00000000}, + {0x000001A4, 0x01FFFFFF}, + {0x0000019A, 0x00000000}, + {0x000001A5, 0x01FFFFFF}, + {0x0000019B, 0x00000000}, + {0x000001A6, 0x01FFFFFF}, + {0x00000050, 0x01111111}, + {0x00000040, 0xFFFFFFFF}, + {0x00000051, 0x10010100}, + {0x000001C5, 0xFFFFFFFF}, + {0x000001C8, 0x00000001}, + {0x00000204, 0x00000000}, + {0x000001C4, 0x00000001} +}; +static unsigned nv10TablePGRAPH_8BPP[][2] = +{ + {0x000001C9, 0x00111111}, + {0x00000186, 0x00001010}, + {0x0000020C, 0x03020202} +}; +static unsigned nv10TablePGRAPH_15BPP[][2] = +{ + {0x000001C9, 0x00226222}, + {0x00000186, 0x00002071}, + {0x0000020C, 0x09080808} +}; +static unsigned nv10TablePGRAPH_16BPP[][2] = +{ + {0x000001C9, 0x00556555}, + {0x00000186, 0x000050C2}, + {0x0000020C, 0x000B0B0C} +}; +static unsigned nv10TablePGRAPH_32BPP[][2] = +{ + {0x000001C9, 0x0077D777}, + {0x00000186, 0x000070E5}, + {0x0000020C, 0x0E0D0D0D} +}; +static unsigned nv10tri05TablePGRAPH[][2] = +{ + {(0x00000E00/4), 0x00000000}, + {(0x00000E04/4), 0x00000000}, + {(0x00000E08/4), 0x00000000}, + {(0x00000E0C/4), 0x00000000}, + {(0x00000E10/4), 0x00001000}, + {(0x00000E14/4), 0x00001000}, + {(0x00000E18/4), 0x4003ff80}, + {(0x00000E1C/4), 0x00000000}, + {(0x00000E20/4), 0x00000000}, + {(0x00000E24/4), 0x00000000}, + {(0x00000E28/4), 0x00000000}, + {(0x00000E2C/4), 0x00000000}, + {(0x00000E30/4), 0x00080008}, + {(0x00000E34/4), 0x00080008}, + {(0x00000E38/4), 0x00000000}, + {(0x00000E3C/4), 0x00000000}, + {(0x00000E40/4), 0x00000000}, + {(0x00000E44/4), 0x00000000}, + {(0x00000E48/4), 0x00000000}, + {(0x00000E4C/4), 0x00000000}, + {(0x00000E50/4), 0x00000000}, + {(0x00000E54/4), 0x00000000}, + {(0x00000E58/4), 0x00000000}, + {(0x00000E5C/4), 0x00000000}, + {(0x00000E60/4), 0x00000000}, + {(0x00000E64/4), 0x10000000}, + {(0x00000E68/4), 0x00000000}, + {(0x00000E6C/4), 0x00000000}, + {(0x00000E70/4), 0x00000000}, + {(0x00000E74/4), 0x00000000}, + {(0x00000E78/4), 0x00000000}, + {(0x00000E7C/4), 0x00000000}, + {(0x00000E80/4), 0x00000000}, + {(0x00000E84/4), 0x00000000}, + {(0x00000E88/4), 0x08000000}, + {(0x00000E8C/4), 0x00000000}, + {(0x00000E90/4), 0x00000000}, + {(0x00000E94/4), 0x00000000}, + {(0x00000E98/4), 0x00000000}, + {(0x00000E9C/4), 0x4B7FFFFF}, + {(0x00000EA0/4), 0x00000000}, + {(0x00000EA4/4), 0x00000000}, + {(0x00000EA8/4), 0x00000000}, + {(0x00000F00/4), 0x07FF0800}, + {(0x00000F04/4), 0x07FF0800}, + {(0x00000F08/4), 0x07FF0800}, + {(0x00000F0C/4), 0x07FF0800}, + {(0x00000F10/4), 0x07FF0800}, + {(0x00000F14/4), 0x07FF0800}, + {(0x00000F18/4), 0x07FF0800}, + {(0x00000F1C/4), 0x07FF0800}, + {(0x00000F20/4), 0x07FF0800}, + {(0x00000F24/4), 0x07FF0800}, + {(0x00000F28/4), 0x07FF0800}, + {(0x00000F2C/4), 0x07FF0800}, + {(0x00000F30/4), 0x07FF0800}, + {(0x00000F34/4), 0x07FF0800}, + {(0x00000F38/4), 0x07FF0800}, + {(0x00000F3C/4), 0x07FF0800}, + {(0x00000F40/4), 0x10000000}, + {(0x00000F44/4), 0x00000000}, + {(0x00000F50/4), 0x00006740}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F50/4), 0x00006750}, + {(0x00000F54/4), 0x40000000}, + {(0x00000F54/4), 0x40000000}, + {(0x00000F54/4), 0x40000000}, + {(0x00000F54/4), 0x40000000}, + {(0x00000F50/4), 0x00006760}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x00006770}, + {(0x00000F54/4), 0xC5000000}, + {(0x00000F54/4), 0xC5000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x00006780}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x000067A0}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F50/4), 0x00006AB0}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F50/4), 0x00006AC0}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x00006C10}, + {(0x00000F54/4), 0xBF800000}, + {(0x00000F50/4), 0x00007030}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x00007040}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x00007050}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x00007060}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x00007070}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x00007080}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x00007090}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x000070A0}, + {(0x00000F54/4), 0x7149F2CA}, + {(0x00000F50/4), 0x00006A80}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F50/4), 0x00006AA0}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x00000040}, + {(0x00000F54/4), 0x00000005}, + {(0x00000F50/4), 0x00006400}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x4B7FFFFF}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x00006410}, + {(0x00000F54/4), 0xC5000000}, + {(0x00000F54/4), 0xC5000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x00006420}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x00006430}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x000064C0}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F54/4), 0x477FFFFF}, + {(0x00000F54/4), 0x3F800000}, + {(0x00000F50/4), 0x000064D0}, + {(0x00000F54/4), 0xC5000000}, + {(0x00000F54/4), 0xC5000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x000064E0}, + {(0x00000F54/4), 0xC4FFF000}, + {(0x00000F54/4), 0xC4FFF000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F50/4), 0x000064F0}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F54/4), 0x00000000}, + {(0x00000F40/4), 0x30000000}, + {(0x00000F44/4), 0x00000004}, + {(0x00000F48/4), 0x10000000}, + {(0x00000F4C/4), 0x00000000} +}; +static unsigned nv10TablePRAMIN[][2] = +{ + {0x00000000, 0x80000010}, + {0x00000001, 0x80011145}, + {0x00000002, 0x80000011}, + {0x00000003, 0x80011146}, + {0x00000004, 0x80000012}, + {0x00000005, 0x80011147}, + {0x00000006, 0x80000013}, + {0x00000007, 0x80011148}, + {0x00000008, 0x80000014}, + {0x00000009, 0x80011149}, + {0x0000000A, 0x80000015}, + {0x0000000B, 0x8001114A}, + {0x0000000C, 0x80000016}, + {0x0000000D, 0x80011150}, + {0x00000020, 0x80000000}, + {0x00000021, 0x80011142}, + {0x00000022, 0x80000001}, + {0x00000023, 0x80011143}, + {0x00000024, 0x80000002}, + {0x00000025, 0x80011144}, + {0x00000026, 0x80000003}, + {0x00000027, 0x8001114B}, + {0x00000028, 0x80000004}, + {0x00000029, 0x8001114C}, + {0x0000002A, 0x80000005}, + {0x0000002B, 0x8001114D}, + {0x0000002C, 0x80000006}, + {0x0000002D, 0x8001114E}, + {0x0000002E, 0x80000007}, + {0x0000002F, 0x8001114F}, + {0x00000500, 0x00003000}, + {0x00000501, 0x01FFFFFF}, + {0x00000502, 0x00000002}, + {0x00000503, 0x00000002}, +#ifdef __BIG_ENDIAN + {0x00000508, 0x01088043}, +#else + {0x00000508, 0x01008043}, +#endif + {0x0000050A, 0x00000000}, + {0x0000050B, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x0000050C, 0x01088019}, +#else + {0x0000050C, 0x01008019}, +#endif + {0x0000050E, 0x00000000}, + {0x0000050F, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x00000510, 0x01088018}, +#else + {0x00000510, 0x01008018}, +#endif + {0x00000512, 0x00000000}, + {0x00000513, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x00000514, 0x01088021}, +#else + {0x00000514, 0x01008021}, +#endif + {0x00000516, 0x00000000}, + {0x00000517, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x00000518, 0x0108805F}, +#else + {0x00000518, 0x0100805F}, +#endif + {0x0000051A, 0x00000000}, + {0x0000051B, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x0000051C, 0x0108804B}, +#else + {0x0000051C, 0x0100804B}, +#endif + {0x0000051E, 0x00000000}, + {0x0000051F, 0x00000000}, + {0x00000520, 0x0100A048}, + {0x00000521, 0x00000D01}, + {0x00000522, 0x11401140}, + {0x00000523, 0x00000000}, + {0x00000524, 0x0300A094}, + {0x00000525, 0x00000D01}, + {0x00000526, 0x11401140}, + {0x00000527, 0x00000000}, + {0x00000528, 0x0300A095}, + {0x00000529, 0x00000D01}, + {0x0000052A, 0x11401140}, + {0x0000052B, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x0000052C, 0x00080058}, +#else + {0x0000052C, 0x00000058}, +#endif + {0x0000052E, 0x11401140}, + {0x0000052F, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x00000530, 0x00080059}, +#else + {0x00000530, 0x00000059}, +#endif + {0x00000532, 0x11401140}, + {0x00000533, 0x00000000}, + {0x00000534, 0x0000005A}, + {0x00000536, 0x11401140}, + {0x00000537, 0x00000000}, + {0x00000538, 0x0000005B}, + {0x0000053A, 0x11401140}, + {0x0000053B, 0x00000000}, + {0x0000053C, 0x00000093}, + {0x0000053E, 0x11401140}, + {0x0000053F, 0x00000000}, +#ifdef __BIG_ENDIAN + {0x00000540, 0x0308A01C}, +#else + {0x00000540, 0x0300A01C}, +#endif + {0x00000542, 0x11401140}, + {0x00000543, 0x00000000} +}; +static unsigned nv10TablePRAMIN_8BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000302}, + {0x0000050D, 0x00000302}, + {0x00000511, 0x00000202}, + {0x00000515, 0x00000302}, + {0x00000519, 0x00000302}, + {0x0000051D, 0x00000302}, + {0x0000052D, 0x00000302}, + {0x0000052E, 0x00000302}, + {0x00000535, 0x00000000}, + {0x00000539, 0x00000000}, + {0x0000053D, 0x00000000}, + {0x00000541, 0x00000302} +}; +static unsigned nv10TablePRAMIN_15BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000902}, + {0x0000050D, 0x00000902}, + {0x00000511, 0x00000802}, + {0x00000515, 0x00000902}, + {0x00000519, 0x00000902}, + {0x0000051D, 0x00000902}, + {0x0000052D, 0x00000902}, + {0x0000052E, 0x00000902}, + {0x00000535, 0x00000902}, + {0x00000539, 0x00000902}, + {0x0000053D, 0x00000902}, + {0x00000541, 0x00000902} +}; +static unsigned nv10TablePRAMIN_16BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000C02}, + {0x0000050D, 0x00000C02}, + {0x00000511, 0x00000B02}, + {0x00000515, 0x00000C02}, + {0x00000519, 0x00000C02}, + {0x0000051D, 0x00000C02}, + {0x0000052D, 0x00000C02}, + {0x0000052E, 0x00000C02}, + {0x00000535, 0x00000C02}, + {0x00000539, 0x00000C02}, + {0x0000053D, 0x00000C02}, + {0x00000541, 0x00000C02} +}; +static unsigned nv10TablePRAMIN_32BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000E02}, + {0x0000050D, 0x00000E02}, + {0x00000511, 0x00000D02}, + {0x00000515, 0x00000E02}, + {0x00000519, 0x00000E02}, + {0x0000051D, 0x00000E02}, + {0x0000052D, 0x00000E02}, + {0x0000052E, 0x00000E02}, + {0x00000535, 0x00000E02}, + {0x00000539, 0x00000E02}, + {0x0000053D, 0x00000E02}, + {0x00000541, 0x00000E02} +}; + diff -urN linux-2.6.6.orig/drivers/video/xbox/xboxfb.h linux-2.6.6/drivers/video/xbox/xboxfb.h --- linux-2.6.6.orig/drivers/video/xbox/xboxfb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6/drivers/video/xbox/xboxfb.h 2004-05-10 12:30:23.292930104 +0100 @@ -0,0 +1,73 @@ +#ifndef __XBOXFB_H +#define __XBOXFB_H + +#include +#include +#include