NEC VR5701 support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Source: MontaVista Software, Inc. Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
MR: 11590
Type: Enhancement
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
Description:
    NEC Electronics Corporation VR5701 SolutionGearII board LSP

Index: linux-2.6.10/arch/mips/vr5701/tcube/irq_vr5701.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/irq_vr5701.c
@@ -0,0 +1,194 @@
+/*
+ * arch/mips/vr5701/tcube/irq_vr5701.c
+ *
+ * This file defines the irq handler for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+/*
+ * NEC Electronics Corporation VR5701 SolutionGearII defines 32 IRQs.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+static int vr5701_irq_base = -1;
+
+void ll_vr5701_irq_disable(int vr5701_irq, int ack);
+
+static void vr5701_irq_enable(unsigned int irq)
+{
+	ll_vr5701_irq_enable(irq - vr5701_irq_base);
+}
+
+static void vr5701_irq_disable(unsigned int irq)
+{
+	ll_vr5701_irq_disable(irq - vr5701_irq_base, 0);
+}
+
+static unsigned int vr5701_irq_startup(unsigned int irq)
+{
+	vr5701_irq_enable(irq);
+	return 0;
+}
+
+static void vr5701_irq_ack(unsigned int irq)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+
+	/* clear the interrupt bit for edge trigger */
+	/* some irqs require the driver to clear the sources */
+	if (irq < vr5701_irq_base + NUM_5701_IRQ) {
+		ddb_out32(INT_CLR, 1 << (irq - vr5701_irq_base));
+	}
+	/* don't need for PCIs, for they are level triger */
+
+	/* disable interrupt - some handler will re-enable the irq
+	 * and if the interrupt is leveled, we will have infinite loop
+	 */
+	ll_vr5701_irq_disable(irq - vr5701_irq_base, 1);
+	local_irq_restore(flags);
+}
+
+static void vr5701_irq_end(unsigned int irq)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		ll_vr5701_irq_enable(irq - vr5701_irq_base);
+	}
+	local_irq_restore(flags);
+}
+
+struct hw_interrupt_type vr5701_irq_type = {
+	"vr5701_irq",
+	vr5701_irq_startup,
+	vr5701_irq_disable,
+	vr5701_irq_enable,
+	vr5701_irq_disable,
+	vr5701_irq_ack,
+	vr5701_irq_end,
+	NULL			/* no affinity stuff for UP */
+};
+
+void vr5701_irq_init(u32 irq_base)
+{
+	extern irq_desc_t irq_desc[];
+	u32 i;
+	vr5701_irq_base = irq_base;
+	for (i = irq_base;
+	     i < irq_base + NUM_5701_IRQ + NUM_EPCI_IRQ + NUM_IPCI_IRQ; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &vr5701_irq_type;
+	}
+}
+
+int vr5701_irq_to_irq(int irq)
+{
+	return irq + vr5701_irq_base;
+}
+
+void ll_vr5701_irq_route(int vr5701_irq, int ip)
+{
+	u32 reg_value;
+	u32 reg_bitmask;
+	u32 reg_index;
+
+	if (vr5701_irq >= NUM_5701_IRQ) {
+		if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+			vr5701_irq = 7;
+		} else {
+			vr5701_irq = 6;
+		}
+	}
+	reg_index = INT_ROUTE0 + vr5701_irq / 8 * 4;
+	reg_value = ddb_in32(reg_index);
+	reg_bitmask = 7 << (vr5701_irq % 8 * 4);
+	reg_value &= ~reg_bitmask;
+	reg_value |= ip << (vr5701_irq % 8 * 4);
+	ddb_out32(reg_index, reg_value);
+}
+
+void ll_vr5701_irq_enable(int vr5701_irq)
+{
+	u16 reg_value;
+	u32 reg_bitmask;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	irq_desc[vr5701_irq_base + vr5701_irq].depth++;
+
+	if (vr5701_irq >= NUM_5701_IRQ) {
+		if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+			reg_value = ddb_in32(IPCI_INTM);
+			reg_bitmask =
+			    1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
+			ddb_out32(IPCI_INTM, reg_value | reg_bitmask);
+			vr5701_irq = 7;
+		} else {
+			reg_value = ddb_in32(EPCI_INTM);
+			reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
+			ddb_out32(EPCI_INTM, reg_value | reg_bitmask);
+			vr5701_irq = 6;
+		}
+	}
+	reg_value = ddb_in32(INT_MASK);
+	ddb_out32(INT_MASK, reg_value | (1 << vr5701_irq));
+	local_irq_restore(flags);
+}
+
+void ll_vr5701_irq_disable(int vr5701_irq, int ack)
+{
+	u16 reg_value;
+	u32 udummy;
+	u32 reg_bitmask;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (!ack) {
+		irq_desc[vr5701_irq_base + vr5701_irq].depth--;
+		if (irq_desc[vr5701_irq_base + vr5701_irq].depth) {
+			local_irq_restore(flags);
+			return;
+		}
+	}
+
+	if (vr5701_irq >= NUM_5701_IRQ) {
+		if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+			goto DISABLE_IRQ_IPCI;
+		} else {
+			goto DISABLE_IRQ_EPCI;
+		}
+	}
+	reg_value = ddb_in32(INT_MASK);
+	ddb_out32(INT_MASK, reg_value & ~(1 << vr5701_irq));
+	udummy = ddb_in32(INT_MASK);
+	local_irq_restore(flags);
+	return;
+
+      DISABLE_IRQ_IPCI:
+	reg_value = ddb_in32(IPCI_INTM);
+	reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
+	ddb_out32(IPCI_INTM, reg_value & ~reg_bitmask);
+	local_irq_restore(flags);
+	return;
+
+      DISABLE_IRQ_EPCI:
+	reg_value = ddb_in32(EPCI_INTM);
+	reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
+	ddb_out32(EPCI_INTM, reg_value & ~reg_bitmask);
+	local_irq_restore(flags);
+}
Index: linux-2.6.10/arch/mips/pci/pci-tcube.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/pci/pci-tcube.c
@@ -0,0 +1,126 @@
+/*
+ * arch/mips/pci/pci-tcube.c
+ *
+ * A code for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII 
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+#include <asm/byteorder.h>
+#include <asm/tcube.h>
+
+static struct resource extpci_io_resource = {
+	"ext pci IO space",
+	0x00001000,
+	0x007FFFFF,
+	IORESOURCE_IO
+};
+
+static struct resource extpci_mem_resource = {
+	"ext pci memory space",
+	0x10000000,
+	0x17FFFFFF,
+	IORESOURCE_MEM
+};
+
+static struct resource iopci_io_resource = {
+	"io pci IO space",
+	0x01000000,
+	0x017FFFFF,
+	IORESOURCE_IO
+};
+
+static struct resource iopci_mem_resource = {
+	"io pci memory space",
+	0x18800000,
+	0x18FFFFFF,
+	IORESOURCE_MEM
+};
+
+struct pci_controller VR5701_ext_controller = {
+	.pci_ops = &VR5701_ext_pci_ops,
+	.io_resource = &extpci_io_resource,
+	.mem_resource = &extpci_mem_resource
+};
+
+struct pci_controller VR5701_io_controller = {
+	.pci_ops = &VR5701_io_pci_ops,
+	.io_resource = &iopci_io_resource,
+	.mem_resource = &iopci_mem_resource
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int slot_num;
+	int k = 0;
+
+	slot_num = PCI_SLOT(dev->devfn);
+
+	if (dev->bus->number == 0) {	/* EPCI */
+		switch (slot_num) {
+		case 24 - 11:   /* INTD# */
+			k = NUM_5701_IRQS + 3;
+			break;
+		case 25 - 11:	/* INTC# */
+			k = NUM_5701_IRQS + 2;
+			break;
+		case 26 - 11:	/* INTB# */
+			k = NUM_5701_IRQS + 1;
+			break;
+		case 27 - 11:	/* INTA# */
+			k = NUM_5701_IRQS + 0;
+			break;
+		}
+	} else {		/* IPCI */
+		switch (slot_num) {
+		case 29 - 11:	/* INTC# */
+			k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 2;
+			break;
+		case 30 - 11:	/* INTB# */
+			k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 1;
+			break;
+		case 31 - 11:	/* INTA# */
+			k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 0;
+			break;
+		}
+	}
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, k);
+	dev->irq = k + 8;
+	return dev->irq;
+}
+
+void ddb_pci_reset_bus(void)
+{
+	u32 temp;
+
+	temp = ddb_in32(EPCI_CTRLH);
+	temp |= 0x80000000;
+	ddb_out32(EPCI_CTRLH, temp);
+	udelay(100);
+	temp &= ~0xc0000000;
+	ddb_out32(EPCI_CTRLH, temp);
+
+	temp = ddb_in32(IPCI_CTRLH);
+	temp |= 0x80000000;
+	ddb_out32(IPCI_CTRLH, temp);
+	udelay(100);
+	temp &= ~0xc0000000;
+	ddb_out32(IPCI_CTRLH, temp);
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
Index: linux-2.6.10/include/asm-mips/serial.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/serial.h
+++ linux-2.6.10/include/asm-mips/serial.h
@@ -412,6 +412,21 @@
 #define DDB5477_SERIAL_PORT_DEFNS
 #endif
 
+#ifdef CONFIG_TCUBE
+#include <asm/tcube.h>
+#define TCUBE_SERIAL_PORT_DEFNS                                   \
+	{ baud_base: BASE_BAUD, irq: 16, flags: STD_COM_FLAGS,          \
+	  iomem_base: (u8*)0xbe000a00, iomem_reg_shift: 3,              \
+	  io_type: SERIAL_IO_MEM},\
+	{ baud_base: BASE_BAUD, irq: 17, flags: STD_COM_FLAGS,          \
+	  iomem_base: (u8*)0xbe000a40, iomem_reg_shift: 3,              \
+	  io_type: SERIAL_IO_MEM},
+#else
+#define TCUBE_SERIAL_PORT_DEFNS
+#endif
+
+
+
 #ifdef CONFIG_SGI_IP32
 /*
  * The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory
@@ -439,6 +454,7 @@
 	MOMENCO_OCELOT_SERIAL_PORT_DEFNS		\
 	MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS		\
 	TXX927_SERIAL_PORT_DEFNS                        \
-	AU1000_SERIAL_PORT_DEFNS
+	AU1000_SERIAL_PORT_DEFNS                        \
+	TCUBE_SERIAL_PORT_DEFNS
 
 #endif /* _ASM_SERIAL_H */
Index: linux-2.6.10/drivers/ide/pci/Makefile
===================================================================
--- linux-2.6.10.orig/drivers/ide/pci/Makefile
+++ linux-2.6.10/drivers/ide/pci/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_BLK_DEV_SLC90E66)		+= slc90
 obj-$(CONFIG_BLK_DEV_TRIFLEX)		+= triflex.o
 obj-$(CONFIG_BLK_DEV_TRM290)		+= trm290.o
 obj-$(CONFIG_BLK_DEV_VIA82CXXX)		+= via82cxxx.o
+obj-$(CONFIG_BLK_DEV_NEC_VR5701_SG2)	+= nec_vr5701_sg2.o
 
 # Must appear at the end of the block
 obj-$(CONFIG_BLK_DEV_GENERIC)          += generic.o
Index: linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
@@ -0,0 +1,111 @@
+/*
+ * drivers/ide/pci/nec_vr5701_sg2.c
+ *
+ * NEC Electronics Corporation VR5701 SolutionGearII IDE controller driver
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+static unsigned int __init init_chipset_nec_vr5701(struct pci_dev *dev,
+						   const char *name)
+{
+	return 0;
+}
+
+static void __init init_hwif_nec_vr5701(ide_hwif_t * hwif)
+{
+	if (!(hwif->dma_base))
+		return;
+
+	hwif->atapi_dma = 1;
+	hwif->ultra_mask = 0x7f;
+	hwif->mwdma_mask = 0x07;
+	hwif->swdma_mask = 0x07;
+
+	if (!noautodma)
+		hwif->autodma = 1;
+	hwif->drives[0].autodma = hwif->autodma;
+	hwif->drives[1].autodma = hwif->autodma;
+}
+
+static ide_pci_device_t nec_vr5701_chipset __devinitdata = {
+	.name = "NEC Electronics Corporation VR5701 SolutionGearII",
+	.init_chipset = init_chipset_nec_vr5701,
+	.init_hwif = init_hwif_nec_vr5701,
+	.channels = 2,
+	.autodma = AUTODMA,
+	.bootable = ON_BOARD,
+};
+
+static int __devinit nec_vr5701_init_one(struct pci_dev *dev,
+					 const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &nec_vr5701_chipset;
+	u16 command;
+
+	if (dev->vendor == PCI_VENDOR_ID_NEC &&
+	    dev->device == PCI_DEVICE_ID_NEC_USB_AND_IDE &&
+	    dev->class == 0x0c0310)
+		return 1;
+	udelay(100);
+	pci_enable_device(dev);
+	*(volatile unsigned char *)0xb9001010 = 6;
+	asm("sync");
+	udelay(100);
+
+	pci_read_config_word(dev, PCI_COMMAND, &command);
+	if (!(command & PCI_COMMAND_IO)) {
+		printk(KERN_INFO "Skipping disabled %s IDE controller.\n",
+		       d->name);
+		return 1;
+	}
+	ide_setup_pci_device(dev, d);
+	return 0;
+}
+
+static struct pci_device_id nec_vr5701_pci_tbl[] = {
+	{PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB_AND_IDE, PCI_ANY_ID,
+	 PCI_ANY_ID, 0x010185, 0xffffff, 0},
+	{0,},
+};
+
+MODULE_DEVICE_TABLE(pci, nec_vr5701_pci_tbl);
+
+static struct pci_driver driver = {
+	.name = "nec_vr5701_IDE",
+	.id_table = nec_vr5701_pci_tbl,
+	.probe = nec_vr5701_init_one,
+};
+
+static int nec_vr5701_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+module_init(nec_vr5701_ide_init);
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("PCI driver module for NEC Electronics Corporation VR5701 SolutionGearII IDE");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/arch/mips/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/Makefile
+++ linux-2.6.10/arch/mips/Makefile
@@ -183,6 +183,10 @@ cflags-$(CONFIG_CPU_R5432)	+= \
 			$(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
 
+cflags-$(CONFIG_CPU_R5500)	+= \
+			$(call set_gccflags,mips32,mips4,r5000,mips4,mips2) \
+			-Wa,--trap
+
 cflags-$(CONFIG_CPU_NEVADA)	+= \
 			$(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
@@ -472,6 +476,13 @@ load-$(CONFIG_DDB5476)		+= 0xffffffff800
 core-$(CONFIG_DDB5477)		+= arch/mips/ddb5xxx/ddb5477/
 load-$(CONFIG_DDB5477)		+= 0xffffffff80100000
 
+#
+# NEC TCUBE
+#
+core-$(CONFIG_TCUBE)		+= arch/mips/vr5701/common/
+core-$(CONFIG_TCUBE)		+= arch/mips/vr5701/tcube/
+load-$(CONFIG_TCUBE)		+= 0xffffffff80080000
+
 core-$(CONFIG_LASAT)		+= arch/mips/lasat/
 cflags-$(CONFIG_LASAT)		+= -Iinclude/asm-mips/mach-lasat
 load-$(CONFIG_LASAT)		+= 0xffffffff80000000
Index: linux-2.6.10/include/asm-mips/tlb.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/tlb.h
+++ linux-2.6.10/include/asm-mips/tlb.h
@@ -6,7 +6,7 @@
  * we need to flush cache for area to be unmapped.
  */
 #ifdef CONFIG_PREEMPT_RT
-#ifdef CONFIG_CPU_MIPS32
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_R5500)
 /*
  * We need the cache flush in case of such processors, eg. MIPS Malta
  */
Index: linux-2.6.10/arch/mips/mm/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/mm/Makefile
+++ linux-2.6.10/arch/mips/mm/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_CPU_R4300)		+= c-r4k.o cex-
 obj-$(CONFIG_CPU_R4X00)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_R5000)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_R5432)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R5500)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_R8000)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r8k.o
 obj-$(CONFIG_CPU_RM7000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_RM9000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
Index: linux-2.6.10/include/asm-mips/vr5701.h
===================================================================
--- /dev/null
+++ linux-2.6.10/include/asm-mips/vr5701.h
@@ -0,0 +1,96 @@
+/*
+ * include/asm-mips/vr5701.h
+ *
+ * A header for NEC Electronics Corporation VR5701 SolutionGearII CPU
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __VR5701_H
+#define __VR5701_H
+
+#define VR5701_IO_BASE	0xbe000000
+
+/* PADR registers */
+#define PADR_SDRAM01	0x40
+#define PADR_LOCALCS0	0x80
+#define PADR_PCIW0	0xC0
+#define PADR_PCIW1	0xC8
+#define PADR_EPCIW0	0xC0
+#define PADR_IOPCIW0	0xE0
+#define PADR_IOPCIW1	0xE8
+/* INT registers */
+#define INT0_STAT	0x100
+#define INT1_STAT	0x108
+#define INT2_STAT	0x110
+#define INT3_STAT	0x118
+#define INT4_STAT	0x120
+#define NMI_STAT	0x130
+#define INT_CLR		0x140
+#define INT_MASK	0x150
+#define INT_ROUTE0	0x160
+#define INT_ROUTE1	0x168
+#define INT_ROUTE2	0x170
+#define INT_ROUTE3	0x178
+/* LOCAL registers */
+#define LOCAL_CST0	0x400
+#define LOCAL_CFG	0x440
+/* EPCI registers */
+#define EPCI_CTRLH	0x604
+#define EPCI_INIT0	0x610
+#define EPCI_INIT1	0x618
+#define EPCI_ERR	0x628
+#define EPCI_INTS	0x630
+#define EPCI_INTM	0x638
+/* PCI registers */
+#define PCI_MLTIM	0x70D
+#define PCI_BAR_MEM01	0x710
+#define PCI_BAR_LCS0	0x740
+#define PCI_BAR_LCS1	0x748
+#define PCI_BAR_LCS2	0x750
+#define PCI_BAR_LCS3	0x758
+#define PCI_BAR_IPCIW0	0x7A0
+#define PCI_BAR_IPCIW1	0x7A8
+#define PCI_BAR_IREG	0x7C0
+
+/* PIB registers*/
+#define PIB_RESET	0x800
+#define PIB_MISC	0x830
+
+/* GPIO registers*/
+#define GIU_PIO0	0x940
+#define GIU_DIR0	0x950
+#define GIU_DIR1	0x958
+#define GIU_FUNCSEL0	0x960
+#define GIU_FUNCSEL1	0x968
+
+/* CSI1 registers*/
+#define CSI1_MODE	0xB80
+#define CSI1_SIRB	0xB88
+#define CSI1_SOTB	0xB90
+#define CSI1_SOTBF	0xBA0
+#define CSI1_CNT	0xBC0
+#define CSI1_INT	0xBC8
+
+/* IPCI registers*/
+#define IPCI_CTRLH	0xE04
+#define IPCI_INIT0	0xE10
+#define IPCI_INIT1	0xE18
+#define IPCI_ERR	0xE28
+#define IPCI_INTS	0xE30
+#define IPCI_INTM	0xE38
+/* PCI registers */
+#define IPCI_MLTIM	0xF0D
+#define IPCI_BAR_LCS0	0xF40
+#define IPCI_BAR_LCS1	0xF48
+#define IPCI_BAR_LCS2	0xF50
+#define IPCI_BAR_LCS3	0xF58
+#define IPCI_BAR_EPCIW0	0xF80
+#define IPCI_BAR_EPCIW1	0xF88
+#define IPCI_BAR_IREG	0xFC0
+
+#endif				/*  __VR5701_H */
Index: linux-2.6.10/arch/mips/vr5701/tcube/int-handler.S
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/int-handler.S
@@ -0,0 +1,77 @@
+/*
+ * arch/mips/vr5701/tcube/int-handler.S
+ *
+ * First-level interrupt dispatcher for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/tcube.h>
+
+/*
+ * first level interrupt dispatcher for ocelot board -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+	.align	5
+	NESTED(tcube_handle_int, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+	.set	noreorder
+	mfc0	t0, CP0_CAUSE  
+	mfc0	t2, CP0_STATUS
+
+	and	t0, t2
+       
+	andi	t1, t0, STATUSF_IP7	/* cpu timer */
+	bnez	t1, ll_cputimer_irq
+	andi	t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 ) 
+	bnez	t1, ll_tcube_irq
+	andi	t1, t0, STATUSF_IP0	/* software int 0 */
+	bnez	t1, ll_cpu_ip0
+	andi	t1, t0, STATUSF_IP1	/* software int 1 */
+	bnez	t1, ll_cpu_ip1
+	nop
+	.set	reorder
+
+	/* wrong alarm or masked ... */
+	j	spurious_interrupt
+	nop
+	END(tcube_handle_int)
+
+	.align	5
+
+ll_tcube_irq:	
+	move	a0, sp
+	jal	tcube_irq_dispatch
+	j	ret_from_irq
+
+ll_cputimer_irq:
+	li	a0, 7
+	move	a1, sp
+	jal	do_IRQ
+	j	ret_from_irq
+
+
+ll_cpu_ip0:	
+	li	a0, 0
+	move	a1, sp
+	jal	do_IRQ
+	j	ret_from_irq
+
+ll_cpu_ip1:	
+	li	a0, 1
+	move	a1, sp
+	jal	do_IRQ
+	j	ret_from_irq
Index: linux-2.6.10/include/asm-mips/tcube.h
===================================================================
--- /dev/null
+++ linux-2.6.10/include/asm-mips/tcube.h
@@ -0,0 +1,200 @@
+/*
+ * include/asm-mips/tcube.h
+ *
+ * Flash memory access on NEC Electronics Corporation VR5701 SolutionGearII board.
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __TCUBE_H
+#define __TCUBE_H
+
+#include <asm/vr5701.h>
+
+#define TCUBE_SDRAM_SIZE 	0x10000000
+
+#ifndef __ASSEMBLY__
+#include <asm/delay.h>
+
+/*
+ *  PCI Master Registers
+ */
+
+#define DDB_PCICMD_IACK		0	/* PCI Interrupt Acknowledge */
+#define DDB_PCICMD_IO		1	/* PCI I/O Space */
+#define DDB_PCICMD_MEM		3	/* PCI Memory Space */
+#define DDB_PCICMD_CFG		5	/* PCI Configuration Space */
+
+/*
+ * additional options for pci init reg (no shifting needed)
+ */
+#define DDB_PCI_CFGTYPE1     	0x200	/* for pci init0/1 regs */
+#define DDB_PCI_ACCESS_32    	0x10	/* for pci init0/1 regs */
+#define NUM_5701_IRQS 	  	32
+#define NUM_5701_EPCI_IRQ 	4
+
+/* A Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII */
+#define SET_32_BIT		0xffffffff
+#define CLR_32_BIT		0x00000000
+
+#define GPIO_3_INTR		(0x1 <<  3)
+#define GPIO_4_CE		(0x1 <<  4)
+#define GPIO_25_S1CLK		(0x1 << 25)
+#define GPIO_26_S1DO		(0x1 << 26)
+#define GPIO_27_S1DI		(0x1 << 27)
+#define GPIO_CSI1_PIN	(GPIO_25_S1CLK | GPIO_26_S1DO | GPIO_27_S1DI)
+
+#define CSIn_MODE_CKP		(0x1 << 12)
+#define CSIn_MODE_DAP		(0x1 << 11)
+#define CSIn_MODE_CKS_MASK	(0x7 <<  8)
+#define CSIn_MODE_CKS_833333MHZ	(0x1 <<  8)
+#define CSIn_MODE_CKS_416667MHZ	(0x2 <<  8)
+#define CSIn_MODE_CKS_208333MHZ	(0x3 <<  8)
+#define CSIn_MODE_CKS_104167MHZ	(0x4 <<  8)
+#define CSIn_MODE_CKS_052083MHZ	(0x5 <<  8)
+#define CSIn_MODE_CKS_0260417HZ	(0x6 <<  8)	/* Default */
+#define CSIn_MODE_CSIE		(0x1 <<  7)
+#define CSIn_MODE_TRMD		(0x1 <<  6)
+#define CSIn_MODE_CCL_16	(0x1 <<  5)
+#define CSIn_MODE_DIR_LSB	(0x1 <<  4)
+#define CSIn_MODE_AUTO		(0x1 <<  2)
+#define CSIn_MODE_CSOT		(0x1 <<  0)
+
+#define CSIn_INT_CSIEND		(0x1 << 15)
+#define CSIn_INT_T_EMP		(0x1 <<  8)
+#define CSIn_INT_R_OVER		(0x1 <<  0)
+
+/* IRQs */
+#define ACTIVE_LOW		1
+#define ACTIVE_HIGH		0
+
+#define LEVEL_SENSE		2
+#define EDGE_TRIGGER		0
+
+#define NUM_5701_IRQS 		32
+#define NUM_5701_EPCI_IRQS 	4
+#define NUM_5701_IPCI_IRQS 	8
+#define NUM_5701_IRQ  		32
+#define NUM_EPCI_IRQ  		4
+#define NUM_IPCI_IRQ  		8
+
+#define INTA			0
+#define INTB			1
+#define INTC			2
+#define INTD			3
+#define INTE			4
+
+/* Timers */
+#define	CPU_COUNTER_FREQUENCY		166666666
+
+#define ddb_sync       		io_sync
+#define ddb_out32(x,y) 		io_out32(x,y)
+#define ddb_out16(x,y) 		io_out16(x,y)
+#define ddb_out8(x,y)  		io_out8(x,y)
+#define ddb_in32(x)    		io_in32(x)
+#define ddb_in16(x)    		io_in16(x)
+#define ddb_in8(x)     		io_in8(x)
+
+static inline void io_sync(void)
+{
+	asm("sync");
+}
+
+static inline void io_out32(u32 offset, u32 val)
+{
+	*(volatile u32 *)(VR5701_IO_BASE + offset) = val;
+	io_sync();
+}
+
+static inline u32 io_in32(u32 offset)
+{
+	u32 val = *(volatile u32 *)(VR5701_IO_BASE + offset);
+	io_sync();
+	return val;
+}
+
+static inline void io_out16(u32 offset, u16 val)
+{
+	*(volatile u16 *)(VR5701_IO_BASE + offset) = val;
+	io_sync();
+}
+
+static inline u16 io_in16(u32 offset)
+{
+	u16 val = *(volatile u16 *)(VR5701_IO_BASE + offset);
+	io_sync();
+	return val;
+}
+
+static inline void io_reset16(unsigned long adr,
+			      unsigned short val1,
+			      unsigned delay, unsigned short val2)
+{
+	io_out16(adr, val1);
+	__delay(delay);
+	io_out16(adr, val2);
+}
+
+static inline void io_out8(u32 offset, u8 val)
+{
+	*(volatile u8 *)(VR5701_IO_BASE + offset) = val;
+	io_sync();
+}
+
+static inline u8 io_in8(u32 offset)
+{
+	u8 val = *(volatile u8 *)(VR5701_IO_BASE + offset);
+	io_sync();
+	return val;
+}
+
+static inline void io_set16(u32 offset, u16 mask, u16 val)
+{
+	u16 val0 = io_in16(offset);
+	io_out16(offset, (val & mask) | (val0 & ~mask));
+}
+
+static inline void reg_set32(u32 offset, u32 mask, u32 val)
+{
+	u32 val0 = io_in32(offset);
+	io_out32(offset, (val & mask) | (val0 & ~mask));
+}
+
+static inline void csi1_reset(void)
+{
+	/* CSI1 reset */
+	reg_set32(CSI1_CNT, 0x00008000, SET_32_BIT);	/* set CSIRST bit */
+	__delay(100000);
+	reg_set32(CSI1_CNT, 0x00008000, CLR_32_BIT);	/* clear CSIRST bit */
+	/* set clock phase  */
+	while (io_in32(CSI1_MODE) & 1) ;
+	reg_set32(CSI1_MODE, CSIn_MODE_CSIE, CLR_32_BIT);
+	reg_set32(CSI1_MODE, CSIn_MODE_CKP, SET_32_BIT);
+	reg_set32(CSI1_MODE, CSIn_MODE_CKS_104167MHZ, SET_32_BIT);
+	reg_set32(CSI1_MODE, CSIn_MODE_CSIE, SET_32_BIT);
+	while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+}
+
+extern void ll_vr5701_irq_route(int vr5701_irq, int ip);
+extern void ll_vr5701_irq_enable(int vr5701_irq);
+extern void ddb_set_pdar(u32, u32, u32, int, int, int);
+extern void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options);
+extern void ddb_set_bar(u32 bar, u32 phys, int prefetchable);
+extern void ddb_pci_reset_bus(void);
+extern struct pci_ops VR5701_ext_pci_ops;
+extern struct pci_ops VR5701_io_pci_ops;
+extern struct pci_controller VR5701_ext_controller;
+extern struct pci_controller VR5701_io_controller;
+extern int shima_tcube_setup(void);
+extern void tcube_irq_init(u32 base);
+extern void mips_cpu_irq_init(u32 base);
+extern asmlinkage void tcube_handle_int(void);
+extern void vr5701_irq_init(u32 irq_base);
+extern int panic_timeout;
+
+#endif
+#endif
Index: linux-2.6.10/drivers/video/Makefile
===================================================================
--- linux-2.6.10.orig/drivers/video/Makefile
+++ linux-2.6.10/drivers/video/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_FB_I810)             += cfb
 				     vgastate.o
 obj-$(CONFIG_FB_INTEL)            += cfbfillrect.o cfbcopyarea.o \
 	                             cfbimgblt.o
+obj-$(CONFIG_FB_SM)               += smi/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
 obj-$(CONFIG_FB_RADEON_OLD)	  += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
Index: linux-2.6.10/arch/mips/kernel/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/kernel/Makefile
+++ linux-2.6.10/arch/mips/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_CPU_R4300)		+= r4k_fpu.o r4
 obj-$(CONFIG_CPU_R4X00)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R5000)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R5432)		+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R5500)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R8000)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_RM7000)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_RM9000)	+= r4k_fpu.o r4k_switch.o
Index: linux-2.6.10/arch/mips/pci/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/pci/Makefile
+++ linux-2.6.10/arch/mips/pci/Makefile
@@ -52,3 +52,4 @@ obj-$(CONFIG_TOSHIBA_JMR3927)	+= fixup-j
 obj-$(CONFIG_TOSHIBA_RBTX4927)	+= fixup-rbtx4927.o ops-tx4927.o
 obj-$(CONFIG_VICTOR_MPC30X)	+= fixup-mpc30x.o
 obj-$(CONFIG_ZAO_CAPCELLA)	+= fixup-capcella.o
+obj-$(CONFIG_TCUBE)		+= pci-tcube.o ops-tcube.o
Index: linux-2.6.10/drivers/video/smi/smi_hw.c
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_hw.c
@@ -0,0 +1,188 @@
+/*
+ * drivers/video/smi/smi_hw.c
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include "smifb.h"
+#include "smi_hw.h"
+#include "smi_params.h"
+
+/*
+ * set mode registers
+ */
+void
+smi_set_moderegs(struct smifb_info *sinfo,
+		 int bpp, int width, int height,
+		 int hDisplaySize,
+		 int hDisplay, int hStart, int hEnd, int hTotal,
+		 int vDisplay, int vStart, int vEnd, int vTotal,
+		 int dotClock, int sync)
+{
+	int i;
+	int tmp_mode = SMI_DEFAULT_MODE;
+	int lineLength;
+	struct smi_mode_regs curMode;
+
+	pr_debug("smi_set_moderegs");
+	pr_debug("bpp = %d, width = %d, height = %d\n", bpp, width, height);
+	pr_debug("hDisplaySize = %d\n", hDisplaySize);
+	pr_debug("hDisplay = %d, hStart = %d, hEnd = %d, hTotal = %d\n",
+		 hDisplay, hStart, hEnd, hTotal);
+	pr_debug("vDisplay = %d, vStart = %d, vEnd = %d, vTotal = %d\n",
+		 vDisplay, vStart, vEnd, vTotal);
+	pr_debug("dotClock = %d\n", dotClock);
+
+	lineLength = width * bpp / 8;
+
+	switch (bpp) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		if (hDisplaySize <= 640)
+			tmp_mode = DISPLAY_640x480x8;
+		else if (width <= 800)
+			tmp_mode = DISPLAY_800x600x8;
+		else if (width <= 1024)
+			tmp_mode = DISPLAY_1024x768x8;
+		else if (width <= 1280)
+			tmp_mode = DISPLAY_1280x1024x8;
+		reg_DPR10(sinfo) = (lineLength << 16) | lineLength;	/* RowPitch */
+		reg_DPR1E(sinfo) = 0x0005;
+		reg_DPR3C(sinfo) = (lineLength << 16) | lineLength;	/* Dst & Src Window Width */
+		reg_VPR00(sinfo) = 0x0 << 16;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		if (hDisplaySize <= 400)
+			tmp_mode = DISPLAY_LCD_400x232x16;
+		if (hDisplaySize <= 640)
+			tmp_mode = DISPLAY_640x480x16;
+		else if (width <= 800)
+			tmp_mode = DISPLAY_800x600x16;
+		else if (width <= 1024)
+			tmp_mode = DISPLAY_1024x768x16;
+		reg_DPR10(sinfo) = (lineLength / 2 << 16) | lineLength / 2;	/* RowPitch */
+		reg_DPR1E(sinfo) = 0x0015;
+		reg_DPR3C(sinfo) = (lineLength / 2 << 16) | lineLength / 2;	/* Dst & Src Window Width */
+		reg_VPR00(sinfo) = 0x2 << 16;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		if (hDisplaySize <= 640)
+			tmp_mode = DISPLAY_640x480x24;
+		else if (width <= 800)
+			tmp_mode = DISPLAY_800x600x24;
+		reg_DPR10(sinfo) = (lineLength / 3 << 16) | lineLength / 3;	/* RowPitch */
+		reg_DPR1E(sinfo) = 0x0035;
+		reg_DPR3C(sinfo) = (lineLength / 3 << 16) | lineLength / 3;	/* Dst & Src Window Width */
+		reg_VPR00(sinfo) = 0x4 << 16;
+		break;
+#endif
+	};
+
+	for (i = 0; i < modeNums; i++) {
+		if (ModeInitParams[i].mode == tmp_mode)
+			break;
+	}
+	if (i == modeNums)
+		tmp_mode = SMI_DEFAULT_MODE;
+
+	memcpy(&curMode, &ModeInitParams[tmp_mode],
+	       sizeof(struct smi_mode_regs));
+
+	/*
+	 * Override some Mode Params
+	 */
+	/* MISC Reg */
+	curMode.reg_MISC = 0x30 | (hDisplay == 640) ? 0x03 : 0x0b;
+	if (sync & FB_SYNC_HOR_HIGH_ACT)
+		curMode.reg_MISC |= 0x40;
+	if (sync & FB_SYNC_VERT_HIGH_ACT)
+		curMode.reg_MISC |= 0x80;
+
+	/* CRTC */
+	curMode.reg_CR00_CR18[0x00] = (u8) (hTotal - 4);
+	curMode.reg_CR00_CR18[0x01] = (u8) hDisplay;
+	curMode.reg_CR00_CR18[0x02] = (u8) hDisplay;
+	curMode.reg_CR00_CR18[0x03] = 0x00;
+	curMode.reg_CR00_CR18[0x04] = (u8) hStart;
+	curMode.reg_CR00_CR18[0x05] = (hEnd & 0x1f);
+	curMode.reg_CR00_CR18[0x06] = (u8) (vTotal & 0xff);
+	curMode.reg_CR00_CR18[0x07] = (u8) (((vStart >> 9) & 0x01) << 7)
+	    | (u8) (((vDisplay >> 9) & 0x01) << 6)
+	    | (u8) (((vTotal >> 9) & 0x01) << 5)
+	    | 1 << 4		/* D (LC) */
+	    | (u8) (((vStart >> 8) & 0x01) << 2)
+	    | (u8) (((vDisplay >> 8) & 0x01) << 1)
+	    | (u8) ((vTotal >> 8) & 0x01);
+
+	curMode.reg_CR00_CR18[0x09] = (u8) (vDisplay >> 9) << 5 | 1 << 6;	/* D (LC bit9) */
+	curMode.reg_CR00_CR18[0x10] = (u8) (vStart & 0xff);
+	curMode.reg_CR00_CR18[0x11] = (u8) (vEnd & 0xf);
+	curMode.reg_CR00_CR18[0x12] = (u8) (vDisplay & 0xff);
+	curMode.reg_CR00_CR18[0x13] = ((width / 8) * ((bpp + 1) / 8)) & 0xFF;
+	curMode.reg_CR00_CR18[0x15] = (u8) (vDisplay & 0xff);
+	curMode.reg_CR00_CR18[0x16] = 0x00;
+	curMode.reg_CR00_CR18[0x14] = (hDisplaySize > 1024) ? 0x00 : 0x40;	/* D *//* Underline Location */
+
+	/* Extended CRTC */
+	curMode.reg_CR30_CR4D[0x30 - 0x30] = (u8) (((vTotal >> 10) & 0x01) << 3)
+	    | (u8) (((vDisplay >> 10) & 0x01) << 1)
+	    | (u8) ((vStart >> 10) & 0x1);	/* D (CRTD) (CVDER) */
+
+	curMode.reg_SR30_SR75[0x32] = 0xff;	/* (Memory Type and Timig Control Reg) */
+
+	for (i = 0; i <= SIZE_SR00_SR04; i++)
+		regSR_write(sinfo->mmio, 0x00 + i, curMode.reg_SR00_SR04[i]);
+	for (i = 0; i <= SIZE_SR10_SR24; i++)
+		regSR_write(sinfo->mmio, 0x10 + i, curMode.reg_SR10_SR24[i]);
+	for (i = 0; i <= SIZE_SR30_SR75; i++) {
+		regSR_write(sinfo->mmio, 0x30 + i, curMode.reg_SR30_SR75[i]);
+	}
+	for (i = 0; i <= SIZE_SR80_SR93; i++)
+		regSR_write(sinfo->mmio, 0x80 + i, curMode.reg_SR80_SR93[i]);
+	for (i = 0; i <= SIZE_SRA0_SRAF; i++)
+		regSR_write(sinfo->mmio, 0xA0 + i, curMode.reg_SRA0_SRAF[i]);
+	for (i = 0; i <= SIZE_GR00_GR08; i++)
+		regGR_write(sinfo->mmio, 0x00 + i, curMode.reg_GR00_GR08[i]);
+	for (i = 0; i <= SIZE_AR00_AR14; i++)
+		regAR_write(sinfo->mmio, 0x00 + i, curMode.reg_AR00_AR14[i]);
+	for (i = 0; i <= SIZE_CR00_CR18; i++)
+		regCR_write(sinfo->mmio, 0x00 + i, curMode.reg_CR00_CR18[i]);
+	for (i = 0; i <= SIZE_CR30_CR4D; i++)
+		regCR_write(sinfo->mmio, 0x30 + i, curMode.reg_CR30_CR4D[i]);
+	for (i = 0; i <= SIZE_CR90_CRA7; i++)
+		regCR_write(sinfo->mmio, 0x90 + i, curMode.reg_CR90_CRA7[i]);
+
+	/* SetMemoryMapRegisters */
+	reg_DPR14(sinfo) = 0xffffffff;	/* FG color */
+	reg_DPR18(sinfo) = 0x00000000;	/* BG color */
+	reg_DPR24(sinfo) = 0xffffffff;	/* Color Mask */
+	reg_DPR28(sinfo) = 0xffff;	/* Masks */
+	reg_DPR2C(sinfo) = 0;
+	reg_DPR30(sinfo) = 0;
+	reg_DPR34(sinfo) = 0xffffffff;
+	reg_DPR38(sinfo) = 0xffffffff;
+	reg_DPR40(sinfo) = 0;
+	reg_DPR44(sinfo) = 0;
+	reg_VPR0C(sinfo) = 0;
+	reg_VPR10(sinfo) = ((lineLength / 8 + 2) << 16) | (lineLength / 8);
+	reg_VPR40(sinfo) = 0;
+	reg_VPR28(sinfo) = 0x00000000;
+	reg_VPR2C(sinfo) = ((hDisplaySize - 1) << 16) | (vDisplay);
+	reg_VPR30(sinfo) = 0x00000000;
+	reg_VPR34(sinfo) = (lineLength << 16) | lineLength;
+}
Index: linux-2.6.10/include/linux/pci_ids.h
===================================================================
--- linux-2.6.10.orig/include/linux/pci_ids.h
+++ linux-2.6.10/include/linux/pci_ids.h
@@ -555,6 +555,7 @@
 #define PCI_DEVICE_ID_MIRO_DC30PLUS	0xd801
 
 #define PCI_VENDOR_ID_NEC		0x1033
+#define PCI_DEVICE_ID_NEC_USB_AND_IDE	0x0000 /* USB 1.1 or IDE Controller*/
 #define PCI_DEVICE_ID_NEC_CBUS_1	0x0001 /* PCI-Cbus Bridge */
 #define PCI_DEVICE_ID_NEC_LOCAL		0x0002 /* Local Bridge */
 #define PCI_DEVICE_ID_NEC_ATM		0x0003 /* ATM LAN Controller */
@@ -1643,6 +1644,11 @@
 #define PCI_DEVICE_ID_SATSAGEM_PCR2101	0x5352
 #define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
 
+#define PCI_VENDOR_ID_SMI		0x126f
+#define PCI_DEVICE_ID_SMI_LYNX_EM	0x0710
+#define PCI_DEVICE_ID_SMI_LYNX_EM_PLUS	0x0712
+#define PCI_DEVICE_ID_SMI_LYNX_3DM	0x0720
+
 #define PCI_VENDOR_ID_HUGHES		0x1273
 #define PCI_DEVICE_ID_HUGHES_DIRECPC	0x0002
 
Index: linux-2.6.10/drivers/video/smi/smi_base.c
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_base.c
@@ -0,0 +1,512 @@
+/*
+ * drivers/video/smi/smi_base.c
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver	for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/selection.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h>
+#include "../console/fbcon.h"
+#include "smifb.h"
+#include "smi_hw.h"
+
+/*
+ * Card Identification
+ *
+ */
+static struct pci_device_id smifb_pci_tbl[] __devinitdata = {
+	{PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_LYNX_EM_PLUS,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* Lynx EM+/EM4+ */
+	{PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_LYNX_3DM,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* Lynx 3DM/3DM+/3DM4+ */
+	{0,}			/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, smifb_pci_tbl);
+
+/*
+ *
+ * global variables
+ *
+ */
+
+#ifdef CONFIG_DISPLAY_1024x768
+/* 1024x768, 16bpp, 60Hz */
+static struct fb_var_screeninfo smifb_default_var = {
+      xres:1024,
+      yres:768,
+      xres_virtual:1024,
+      yres_virtual:768,
+      xoffset:0,
+      yoffset:0,
+      bits_per_pixel:16,
+      grayscale:0,
+      red:{11, 5, 0},
+      green:{5, 6, 0},
+      blue:{0, 5, 0},
+      transp:{0, 0, 0},
+      nonstd:0,
+      activate:0,
+      height:-1,
+      width:-1,
+      accel_flags:0,
+      pixclock:39721,		/* D */
+      left_margin:138,
+      right_margin:24,
+      upper_margin:24,
+      lower_margin:4,
+      hsync_len:160,
+      vsync_len:6,
+      sync:0,
+      vmode:FB_VMODE_NONINTERLACED
+};
+#else
+/* 640x480, 16bpp, 60Hz */
+static struct fb_var_screeninfo smifb_default_var = {
+      xres:640,
+      yres:480,
+      xres_virtual:640,
+      yres_virtual:480,
+      xoffset:0,
+      yoffset:0,
+      bits_per_pixel:16,
+      grayscale:0,
+      red:{11, 5, 0},
+      green:{5, 6, 0},
+      blue:{0, 5, 0},
+      transp:{0, 0, 0},
+      nonstd:0,
+      activate:0,
+      height:-1,
+      width:-1,
+      accel_flags:0,
+      pixclock:39721,		/* D */
+      left_margin:82,
+      right_margin:16,
+      upper_margin:19,
+      lower_margin:1,
+      hsync_len:152,
+      vsync_len:4,
+      sync:0,
+      vmode:FB_VMODE_NONINTERLACED
+};
+#endif
+
+static char drvrname[] = "NEC video driver for SMI LynxEM+";
+
+/*
+ *
+ * general utility functions
+ *
+ */
+
+static void
+smi_load_video_mode(struct smifb_info *sinfo,
+		    struct fb_var_screeninfo *video_mode)
+{
+	int bpp, width, height;
+	int hDisplaySize, hDisplay, hStart, hEnd, hTotal;
+	int vDisplay, vStart, vEnd, vTotal;
+	int dotClock;
+
+	pr_debug("smi_load_video_mode: video_mode->xres = %d\n",
+		 video_mode->xres);
+	pr_debug("                   :             yres = %d\n",
+		 video_mode->yres);
+	pr_debug("                   :             xres_virtual = %d\n",
+		 video_mode->xres_virtual);
+	pr_debug("                   :             yres_virtual = %d\n",
+		 video_mode->yres_virtual);
+	pr_debug("                   :             xoffset = %d\n",
+		 video_mode->xoffset);
+	pr_debug("                   :             yoffset = %d\n",
+		 video_mode->yoffset);
+	pr_debug("                   :             bits_per_pixel = %d\n",
+		 video_mode->bits_per_pixel);
+
+	/* smifb_blank(1, (struct fb_info*)sinfo); */
+	bpp = video_mode->bits_per_pixel;
+	if (bpp == 16 && video_mode->green.length == 5)
+		bpp = 15;
+
+	/* horizontal params */
+	width = video_mode->xres_virtual;
+	hDisplaySize = video_mode->xres;	/* number of pixels for one horizontal line */
+	hDisplay = (hDisplaySize / 8) - 1;	/* number of character clocks */
+	hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2;	/* h-blank start character clocks */
+	hEnd = (hDisplaySize + video_mode->right_margin + video_mode->hsync_len) / 8 - 1;	/* h-sync end */
+	hTotal = (hDisplaySize + video_mode->right_margin + video_mode->hsync_len + video_mode->left_margin) / 8 - 1;	/* character clock from h-sync to next h-sync */
+
+	/* vertical params */
+	height = video_mode->yres_virtual;
+	vDisplay = video_mode->yres - 1;	/* number of lines */
+	vStart = video_mode->yres + video_mode->lower_margin - 1;	/* v-sync pulse start */
+	vEnd = video_mode->yres + video_mode->lower_margin + video_mode->vsync_len - 1;	/* v-sync end */
+	vTotal = video_mode->yres + video_mode->lower_margin + video_mode->vsync_len + video_mode->upper_margin + 2;	/* number of scanlines (v-blank end) */
+
+	dotClock = 1000000000 / video_mode->pixclock;
+
+	smi_set_moderegs(sinfo, bpp, width, height,
+			 hDisplaySize,
+			 hDisplay, hStart, hEnd, hTotal,
+			 vDisplay, vStart, vEnd, vTotal,
+			 dotClock, video_mode->sync);
+}
+
+/*
+ *
+ * framebuffer operations
+ *
+ */
+static int
+smifb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	struct smifb_info *sinfo = (struct smifb_info *)info;
+
+	pr_debug("smifb_get_fix");
+	fix->smem_start = sinfo->fb_base_phys;
+	fix->smem_len = sinfo->fbsize;
+	fix->mmio_start = sinfo->dpr_base_phys;
+	fix->mmio_len = sinfo->dpport_size;
+
+	fix->xpanstep = 0;	/* FIXME: no xpanstep for now */
+	fix->ypanstep = 1;	/* FIXME: no ypanstep for now */
+	fix->ywrapstep = 0;	/* FIXME: no ywrap for now */
+
+	return 0;
+}
+
+static int vgxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp, struct fb_info *info)
+{
+	if (regno > 15)
+		return 1;
+
+	((u16 *) (info->pseudo_palette))[regno] =
+	    (red & 0xf800) | (green & 0xfc00 >> 5) | (blue & 0xf800 >> 11);
+	return 0;
+}
+
+/*
+ * Initialization helper functions
+ *
+ */
+/* kernel interface */
+static struct fb_ops smifb_ops = {
+	.owner = THIS_MODULE,
+	.fb_setcolreg = vgxfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = soft_cursor,
+};
+
+/*
+ * VGA registers
+ *
+ */
+static void Unlock(struct smifb_info *sinfo)
+{
+	pr_debug("Unlock");
+	regSR_write(sinfo->mmio, 0x33, regSR_read(sinfo->mmio, 0x33) & 0x20);
+}
+
+static void UnlockVGA(struct smifb_info *sinfo)
+{
+	pr_debug("UnlockVGA");
+	regCR_write(sinfo->mmio, 0x11, regCR_read(sinfo->mmio, 0x11) & 0x7f);
+}
+
+static struct fb_fix_screeninfo vgxfb_fix = {
+	.id = "vgxFB",
+	.type = FB_TYPE_PACKED_PIXELS,
+	.visual = FB_VISUAL_TRUECOLOR,
+#ifdef CONFIG_DISPLAY_1024x768
+	.line_length = 1024 * 2,
+#else
+	.line_length = 640 * 2,
+#endif
+	.accel = FB_ACCEL_NONE,
+};
+
+static u32 colreg[17];
+
+/*
+ * PCI bus
+ *
+ */
+static int __devinit
+smifb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
+{
+	int len;
+	int res;
+	u16 cmd;
+	struct smifb_info *sinfo;
+	struct fb_info *info;
+
+	pr_debug("smifb_probe");
+
+	pr_debug("vendor id        %04x\n", pd->vendor);
+	pr_debug("device id        %04x\n", pd->device);
+	pr_debug("sub vendor id    %04x\n", pd->subsystem_vendor);
+	pr_debug("sub device id    %04x\n", pd->subsystem_device);
+
+	pr_debug("base0 start addr %08x\n",
+		 (unsigned int)pci_resource_start(pd, 0));
+	pr_debug("base0 end   addr %08x\n",
+		 (unsigned int)pci_resource_end(pd, 0));
+	pr_debug("base0 region len %08x\n",
+		 (unsigned int)pci_resource_len(pd, 0));
+	pr_debug("base0 flags      %08x\n",
+		 (unsigned int)pci_resource_flags(pd, 0));
+
+	pci_read_config_word(pd, PCI_STATUS, &cmd);
+	pr_debug("PCI status      %04x\n", cmd);
+
+	pci_read_config_word(pd, PCI_COMMAND, &cmd);
+	pr_debug("PCI command      %04x\n", cmd);
+
+	cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+	pci_write_config_word(pd, PCI_COMMAND, cmd);
+
+	pci_read_config_word(pd, PCI_STATUS, &cmd);
+	pr_debug("PCI status      %04x\n", cmd);
+	pci_read_config_word(pd, PCI_COMMAND, &cmd);
+	pr_debug("PCI command      %04x\n", cmd);
+
+	/* allocate memory resources */
+	sinfo = kmalloc(sizeof(struct smifb_info), GFP_KERNEL);
+	if (!sinfo) {
+		goto err_out;
+	}
+	memset(sinfo, 0, sizeof(struct smifb_info));
+
+	/* driver name */
+	sinfo->drvr_name = drvrname;
+
+	sinfo->pd = pd;
+	sinfo->base_phys = pci_resource_start(sinfo->pd, 0);	/* Frame Buffer base address */
+	len = pci_resource_len(sinfo->pd, 0);
+	pr_debug("len = %lX\n", len);
+	if (!request_mem_region(sinfo->base_phys, len, "smifb")) {
+		printk(KERN_ERR "cannot reserve FrameBuffer and MMIO region\n");
+		goto err_out_kfree;
+	}
+
+	if ((res = pci_enable_device(sinfo->pd)) < 0) {
+		printk(KERN_ERR "smifb: failed to enable -- err %d\n", res);
+		goto err_out_free_base;
+	}
+
+	pci_read_config_word(pd, PCI_COMMAND, &cmd);
+	pr_debug(KERN_INFO "PCI command      %04x\n", cmd);
+
+	{
+		unsigned int pseudo_io, pseudo_io_len;
+		unsigned char *pseudo_io_p;
+
+		*(unsigned long *)0xbe000610 = 0x10000012;	/* CHANGE to PCI IO ACCESS */
+		asm("sync");
+		pseudo_io = pci_resource_start(sinfo->pd, 0);
+		pseudo_io_len = pci_resource_len(sinfo->pd, 0);
+		pseudo_io_p = ioremap(pseudo_io, pseudo_io_len);
+
+		VGA_WRITE8(pseudo_io_p, 0x3c3, 0x40);
+		regSR_write(pseudo_io_p, 0x00, 0x00);
+		regSR_write(pseudo_io_p, 0x17, 0xe2);
+		regSR_write(pseudo_io_p, 0x18, 0xff);
+
+		iounmap(pseudo_io_p);
+		*(unsigned long *)0xbe000610 = 0x10000016;	/* PCI MEM ACCESS */
+		asm("sync");
+	}
+	sinfo->base = ioremap(sinfo->base_phys, len);	/* FB+DPD+DPR+VPR+CPR+MMIO */
+	if (!sinfo->base) {
+		goto err_out_free_base;
+	}
+	switch ((sinfo->pd)->device) {
+	case PCI_DEVICE_ID_SMI_LYNX_EM_PLUS:
+		sinfo->dpport = (caddr_t) (sinfo->base + DPPORT_BASE_OFFSET);
+		sinfo->dpr = (caddr_t) (sinfo->base + DP_BASE_OFFSET);
+		sinfo->vpr = (caddr_t) (sinfo->base + VP_BASE_OFFSET);
+		sinfo->cpr = (caddr_t) (sinfo->base + CP_BASE_OFFSET);
+		sinfo->mmio = (caddr_t) (sinfo->base + IO_BASE_OFFSET);
+		sinfo->fb_base = (caddr_t) (sinfo->base + 0);
+		break;
+	case PCI_DEVICE_ID_SMI_LYNX_3DM:
+		sinfo->dpport =
+		    (caddr_t) (sinfo->base + LYNX3DM_DPPORT_BASE_OFFSET);
+		sinfo->dpr = (caddr_t) (sinfo->base + LYNX3DM_DP_BASE_OFFSET);
+		sinfo->vpr = (caddr_t) (sinfo->base + LYNX3DM_VP_BASE_OFFSET);
+		sinfo->cpr = (caddr_t) (sinfo->base + LYNX3DM_CP_BASE_OFFSET);
+		sinfo->mmio = (caddr_t) (sinfo->base + LYNX3DM_IO_BASE_OFFSET);
+		sinfo->fb_base =
+		    (caddr_t) (sinfo->base + LYNX3DM_FB_BASE_OFFSET);
+		break;
+	}
+	regSR_write(sinfo->mmio, 0x18, 0x11);
+
+	pr_debug("sinfo->dpport = 0x%08x\n", (u_int32_t) sinfo->dpport);
+	pr_debug("sinfo->dpr  = 0x%08x, sinfo->vpr   = 0x%08x\n",
+		 (unsigned int)sinfo->dpr, (unsigned int)sinfo->vpr);
+	pr_debug("sinfo->cpr  = 0x%08x, sinfo->mmio  = 0x%08x\n",
+		 (unsigned int)sinfo->cpr, (unsigned int)sinfo->mmio);
+
+	/* Set the chip in color mode and unlock the registers */
+	VGA_WRITE8(sinfo->mmio, 0x3c2, 0x2b);	/* Miscellaneous Output Register ( write 0x3c2, read 0x3cc ) */
+
+	Unlock(sinfo);
+	UnlockVGA(sinfo);
+
+	/* save the current chip status */
+	switch ((sinfo->pd)->device) {
+	case PCI_DEVICE_ID_SMI_LYNX_EM_PLUS:
+		regSR_write(sinfo->mmio, 0x62, 0xff);
+		regSR_write(sinfo->mmio, 0x6a, 0x0c);
+		regSR_write(sinfo->mmio, 0x6b, 0x02);
+
+		*(u32 *) (sinfo->fb_base + 4) = 0xaa551133;
+		pr_debug("       *(u32 *)(sinfo->fb_base +4) = 0x%08x\n",
+			 *(u32 *) (sinfo->fb_base + 4));
+		if (*(u32 *) (sinfo->fb_base + 4) != 0xaa551133) {
+			/* Program the MCLK to 130MHz */
+			regSR_write(sinfo->mmio, 0x6a, 0x10);
+			regSR_write(sinfo->mmio, 0x6b, 0x02);
+			regSR_write(sinfo->mmio, 0x62, 0x3e);
+			sinfo->fbsize = 2 * 1024 * 1024;	/* LynxEM+ */
+			pr_debug
+			    ("ChipID = LynxEM+. Force the MCLK to 85MHz and the memory size to 2MiB\n");
+		} else {
+			sinfo->fbsize = 4 * 1024 * 1024;	/* LynxEM4+ */
+			pr_debug
+			    ("ChipID = LynxEM4+. Force the MCLK to 85MHz and the memory size to 4MiB\n");
+		}
+		sinfo->fb_base_phys = sinfo->base_phys;
+		break;
+	case PCI_DEVICE_ID_SMI_LYNX_3DM:
+		{
+			int tmp;
+			int mem_table[4] = { 8, 16, 0, 4 };
+			tmp = (regSR_read(sinfo->mmio, 0x76) & 0xff);
+			pr_debug("%02x\n", tmp);
+			sinfo->fbsize = mem_table[(tmp >> 6)] * 1024 * 1024;
+
+			regSR_write(sinfo->mmio, 0x62, 0xff);
+			regSR_write(sinfo->mmio, 0x6a, 0x0c);
+			regSR_write(sinfo->mmio, 0x6b, 0x02);
+
+			sinfo->fb_base_phys =
+			    sinfo->base_phys + LYNX3DM_FB_BASE_OFFSET;
+		}
+		break;
+	default:
+		/* this driver supports only LynxEM+/EM4+ */
+		goto err_out_free_base;
+	};
+
+	info = &(sinfo->info);
+	smifb_get_fix(&vgxfb_fix, -1, info);
+
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &smifb_ops;
+	info->var = smifb_default_var;
+	info->fix = vgxfb_fix;
+	info->pseudo_palette = colreg;
+	info->screen_base = sinfo->fb_base;
+
+	smi_load_video_mode(sinfo, &smifb_default_var);
+
+	if (register_framebuffer(&sinfo->info) < 0) {
+		goto err_out_free_base;
+	}
+	pci_set_drvdata(pd, sinfo);
+
+	printk(KERN_INFO "smifb: " "framebuffer (%s)\n", sinfo->drvr_name);
+
+	return 0;
+
+      err_out_free_base:
+	release_mem_region(sinfo->base_phys, len);
+      err_out_kfree:
+	kfree(sinfo);
+      err_out:
+	return -ENODEV;
+}
+
+static void __devexit smifb_remove(struct pci_dev *pd)
+{
+	struct smifb_info *sinfo = pci_get_drvdata(pd);
+	pr_debug("smifb_remove");
+
+	if (!sinfo)
+		return;
+
+	unregister_framebuffer(&sinfo->info);
+
+	/* stop the lynx chip */
+	release_mem_region(sinfo->base_phys, pci_resource_len(sinfo->pd, 0));
+	kfree(sinfo);
+	pci_set_drvdata(pd, NULL);
+}
+
+/*
+ * Initialization
+ *
+ */
+#ifndef MODULE
+int __init smifb_setup(char *options)
+{
+	pr_debug("smifb_setup");
+
+	if (!options || options)
+		return 0;
+	return 0;
+}
+#endif				/* not MODULE */
+
+static struct pci_driver smifb_driver = {
+	.name = "smifb",
+	.id_table = smifb_pci_tbl,
+	.probe = smifb_probe,
+	.remove = __devexit_p(smifb_remove),
+};
+
+/*
+ * Driver initialization
+ */
+int __init smifb_init(void)
+{
+	pr_debug("smifb_init");
+	return pci_module_init(&smifb_driver);
+}
+
+void __exit smifb_exit(void)
+{
+	pci_unregister_driver(&smifb_driver);
+}
+
+module_init(smifb_init);
+module_exit(smifb_exit);
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("Framebuffer driver for NEC Electronics Corporation VR5701 SolutionGearII");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/drivers/video/smi/smi_hw.h
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_hw.h
@@ -0,0 +1,197 @@
+/*
+ * drivers/video/smi/smi_hw.h
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver	for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __SMI_HW_H__
+#define __SMI_HW_H__
+
+#include "smifb.h"
+
+#define DPPORT_BASE_OFFSET		0x400000
+#define DP_BASE_OFFSET			0x408000
+#define VP_BASE_OFFSET			0x40c000
+#define CP_BASE_OFFSET			0x40e000
+#define IO_BASE_OFFSET			0x700000
+
+#define DPPORT_REGION_SIZE		(32*1024)
+#define DPREG_REGION_SIZE		(16*1024)
+#define VPREG_REGION_SIZE		(8*1024)
+#define CPREG_REGION_SIZE		(8*1024)
+#define MMIO_REGION_SIZE		(1*1024*1024)
+
+#define LYNX3DM_DPPORT_BASE_OFFSET		0x100000
+#define LYNX3DM_DP_BASE_OFFSET			0x000000
+#define LYNX3DM_VP_BASE_OFFSET			0x000800
+#define LYNX3DM_CP_BASE_OFFSET			0x001000
+#define LYNX3DM_IO_BASE_OFFSET			0x0c0000
+#define LYNX3DM_FB_BASE_OFFSET			0x200000
+
+#define LYNX3DM_DPPORT_REGION_SIZE		(1024*1024)
+#define LYNX3DM_DPREG_REGION_SIZE		(2*1024)
+#define LYNX3DM_VPREG_REGION_SIZE		(2*1024)
+#define LYNX3DM_CPREG_REGION_SIZE		(2*1024)
+#define LYNX3DM_MMIO_REGION_SIZE		(256*1024)
+
+extern void smi_set_moderegs(struct smifb_info *sinfo,
+			     int bpp, int width, int height,
+			     int hDisplaySize,
+			     int hDisplay, int hStart, int hEnd, int hTotal,
+			     int vDisplay, int vStart, int vEnd, int vTotal,
+			     int dotClock, int sync);
+
+#define MMIO_OUT8(p, r, d)	(((volatile u8 *)(p))[r] = (d))
+#define MMIO_OUT16(p, r, d)	(((volatile u16 *)(p))[(r)>>1] = (d))
+#define MMIO_OUT32(p, r, d)	(((volatile u32 *)(p))[(r)>>2] = (d))
+#define MMIO_IN8(p, r)		(((volatile u8 *)(p))[(r)])
+#define MMIO_IN16(p, r)		(((volatile u16 *)(p))[(r)>>1])
+#define MMIO_IN32(p, r)		(((volatile u32 *)(p))[(r)>>2])
+
+static inline u8 VGA_READ8(u8 * base, uint reg)
+{
+	return MMIO_IN8(base, reg);
+}
+
+static inline void VGA_WRITE8(u8 * base, uint reg, u8 data)
+{
+	MMIO_OUT8(base, reg, data);
+}
+
+static inline u8 VGA_READ8_INDEX(u8 * base, u8 index)
+{
+	VGA_WRITE8(base, 0x3c4, index);
+	return VGA_READ8(base, 0x3c5);
+}
+
+static inline void VGA_WRITE8_INDEX(u8 * base, u8 index, u8 data)
+{
+	VGA_WRITE8(base, 0x3c4, index);
+	VGA_WRITE8(base, 0x3c5, data);
+}
+
+static inline u8 regSR_read(u8 * base, u8 index)
+{
+	VGA_WRITE8(base, 0x3c4, index);
+	return VGA_READ8(base, 0x3c5);
+}
+
+static inline void regSR_write(u8 * base, u8 index, u8 data)
+{
+	VGA_WRITE8(base, 0x3c4, index);
+	VGA_WRITE8(base, 0x3c5, data);
+}
+
+static inline u8 regCR_read(u8 * base, u8 index)
+{
+	VGA_WRITE8(base, 0x3d4, index);
+	return VGA_READ8(base, 0x3d5);
+}
+
+static inline void regCR_write(u8 * base, u8 index, u8 data)
+{
+	VGA_WRITE8(base, 0x3d4, index);
+	VGA_WRITE8(base, 0x3d5, data);
+}
+
+static inline u8 regGR_read(u8 * base, u8 index)
+{
+	VGA_WRITE8(base, 0x3ce, index);
+	return VGA_READ8(base, 0x3cf);
+}
+
+static inline void regGR_write(u8 * base, u8 index, u8 data)
+{
+	VGA_WRITE8(base, 0x3ce, index);
+	VGA_WRITE8(base, 0x3cf, data);
+}
+
+static inline u8 regAR_read(u8 * base, u8 index)
+{
+	(void)VGA_READ8(base, 0x3da);	/* reset flip-flop */
+	VGA_WRITE8(base, 0x3c0, index);
+	return VGA_READ8(base, 0x3c1);
+}
+
+static inline void regAR_write(u8 * base, u8 index, u8 data)
+{
+	(void)VGA_READ8(base, 0x3da);	/* reset flip-flop */
+	VGA_WRITE8(base, 0x3c0, index);
+	VGA_WRITE8(base, 0x3c0, data);
+}
+
+/*
+ * LynxEM+ registers
+ */
+
+/* Drawing Engine Control Registers */
+#define reg_DPR00(x)	*(u16 *)((x)->dpr+0x00)	/* Source Y or K2                                       */
+#define reg_DPR02(x)	*(u16 *)((x)->dpr+0x02)	/* Source X or K1                                       */
+#define reg_DPR04(x)	*(u16 *)((x)->dpr+0x04)	/* Destination Y or Start Y                             */
+#define reg_DPR06(x)	*(u16 *)((x)->dpr+0x06)	/* Destination X or Start X                             */
+#define reg_DPR08(x)	*(u16 *)((x)->dpr+0x08)	/* Dimension Y or Error Term                            */
+#define reg_DPR0A(x)	*(u16 *)((x)->dpr+0x0A)	/* Dimension X or Vector Length                         */
+#define reg_DPR0C(x)	*(u16 *)((x)->dpr+0x0C)	/* ROP and Miscellaneous Control                        */
+#define reg_DPR0E(x)	*(u16 *)((x)->dpr+0x0E)	/* Drawing Engine Commands and Control                  */
+#define reg_DPR10(x)	*(u16 *)((x)->dpr+0x10)	/* Source Row Pitch                                     */
+#define reg_DPR12(x)	*(u16 *)((x)->dpr+0x12)	/* Destination Row Picth                                */
+#define reg_DPR14(x)	*(u32 *)((x)->dpr+0x14)	/* Foreground Colors                                    */
+#define reg_DPR18(x)	*(u32 *)((x)->dpr+0x18)	/* Background Colors                                    */
+#define reg_DPR1C(x)	*(u16 *)((x)->dpr+0x1C)	/* Stretch Source Height Y                              */
+#define reg_DPR1E(x)	*(u16 *)((x)->dpr+0x1E)	/* Drawing Engine DataFormat and Location Format Select */
+#define reg_DPR20(x)	*(u32 *)((x)->dpr+0x20)	/* Color Compare                                        */
+#define reg_DPR24(x)	*(u32 *)((x)->dpr+0x24)	/* Color Compare Mask                                   */
+#define reg_DPR28(x)	*(u16 *)((x)->dpr+0x28)	/* Bit Mask                                             */
+#define reg_DPR2A(x)	*(u16 *)((x)->dpr+0x2A)	/* Byte Mask Enable                                     */
+#define reg_DPR2C(x)	*(u16 *)((x)->dpr+0x2C)	/* Scisors Left and Control                             */
+#define reg_DPR2E(x)	*(u16 *)((x)->dpr+0x2E)	/* Scisors Top                                          */
+#define reg_DPR30(x)	*(u16 *)((x)->dpr+0x30)	/* Scisors Right                                        */
+#define reg_DPR32(x)	*(u16 *)((x)->dpr+0x32)	/* Scisors Bottom                                       */
+#define reg_DPR34(x)	*(u32 *)((x)->dpr+0x34)	/* Mono Pattern Low                                     */
+#define reg_DPR38(x)	*(u32 *)((x)->dpr+0x38)	/* Mono Pattern High                                    */
+#define reg_DPR3C(x)	*(u32 *)((x)->dpr+0x3C)	/* XY Addressing Destination & Source Window Widths     */
+#define reg_DPR40(x)	*(u32 *)((x)->dpr+0x40)	/* Source Base Address                                  */
+#define reg_DPR44(x)	*(u32 *)((x)->dpr+0x44)	/* Destination Base Address                             */
+
+/* Video Processor Control Registers */
+#define reg_VPR00(x)	*(u32 *)((x)->vpr+0x00)	/* Miscellaneous Graphics and Video Control                 */
+#define reg_VPR04(x)	*(u32 *)((x)->vpr+0x04)	/* Color Keys                                               */
+#define reg_VPR08(x)	*(u32 *)((x)->vpr+0x08)	/* Color Key Masks                                          */
+#define reg_VPR0C(x)	*(u32 *)((x)->vpr+0x0C)	/* Data Source Start Address for Extended Graphics Modes    */
+#define reg_VPR10(x)	*(u32 *)((x)->vpr+0x10)	/* Data Source Width and Offset for Extended Graphics Modes */
+#define reg_VPR14(x)	*(u32 *)((x)->vpr+0x14)	/* Video Window I Left and Top Boundaries                   */
+#define reg_VPR18(x)	*(u32 *)((x)->vpr+0x18)	/* Video Window I Right and Bottom Boundaries               */
+#define reg_VPR1C(x)	*(u32 *)((x)->vpr+0x1C)	/* Video Window I Source Start Address                      */
+#define reg_VPR20(x)	*(u32 *)((x)->vpr+0x20)	/* Video Window I Source Width and Offset                   */
+#define reg_VPR24(x)	*(u32 *)((x)->vpr+0x24)	/* Video Window I Stretch Factor                            */
+#define reg_VPR28(x)	*(u32 *)((x)->vpr+0x28)	/* Video Window II Left and Top Boundaries              */
+#define reg_VPR2C(x)	*(u32 *)((x)->vpr+0x2C)	/* Video Window II Right and Bottom Boundaries              */
+#define reg_VPR30(x)	*(u32 *)((x)->vpr+0x30)	/* Video Window II Source Start Address                     */
+#define reg_VPR34(x)	*(u32 *)((x)->vpr+0x34)	/* Video Window II Source Width and Offset                  */
+#define reg_VPR38(x)	*(u32 *)((x)->vpr+0x38)	/* Video Window II Stretch Factor                           */
+#define reg_VPR3C(x)	*(u32 *)((x)->vpr+0x3C)	/* Graphics and Video Controll II                           */
+#define reg_VPR40(x)	*(u32 *)((x)->vpr+0x40)	/* Graphic Scale Factor                                     */
+#define reg_VPR54(x)	*(u32 *)((x)->vpr+0x54)	/* FIFO Priority Control                                    */
+#define reg_VPR58(x)	*(u32 *)((x)->vpr+0x58)	/* FIFO Empty Request level Control                         */
+#define reg_VPR5C(x)	*(u32 *)((x)->vpr+0x5C)	/* YUV to RGB Conversion Constant                           */
+#define reg_VPR60(x)	*(u32 *)((x)->vpr+0x60)	/* Current Scan Line Position                               */
+#define reg_VPR64(x)	*(u32 *)((x)->vpr+0x64)	/* Signature Analyzer Control and Status                    */
+#define reg_VPR68(x)	*(u32 *)((x)->vpr+0x68)	/* Video Window I Stretch Factor                            */
+#define reg_VPR6C(x)	*(u32 *)((x)->vpr+0x6C)	/* Video Window II Stretch Factor                           */
+
+/* Capture Processor Control Registers */
+#define reg_CPR00(x)	*(u32 *)((x)->cpr+0x00)	/* Capture Port Control                        */
+#define reg_CPR04(x)	*(u32 *)((x)->cpr+0x04)	/* Video Source Clipping Control               */
+#define reg_CPR08(x)	*(u32 *)((x)->cpr+0x08)	/* Video Source Capture Size Control           */
+#define reg_CPR0C(x)	*(u32 *)((x)->cpr+0x0C)	/* Capture Port Buffer I Source Start Address  */
+#define reg_CPR10(x)	*(u32 *)((x)->cpr+0x10)	/* Capture Port Buffer II Source Start Address */
+#define reg_CPR14(x)	*(u32 *)((x)->cpr+0x14)	/* Capture Port Source Offset Address          */
+#define reg_CPR18(x)	*(u32 *)((x)->cpr+0x18)	/* Capture FIFO Empty Request level Control    */
+
+#endif				/* __SMI_HW_H__ */
Index: linux-2.6.10/arch/mips/Kconfig
===================================================================
--- linux-2.6.10.orig/arch/mips/Kconfig
+++ linux-2.6.10/arch/mips/Kconfig
@@ -449,6 +449,17 @@ config DDB5477_BUS_FREQUENCY
 	depends on DDB5477
 	default 0
 
+config TCUBE
+	bool "Support for NEC Electronics Corporation VR5701 SolutionGearII"
+	select IRQ_CPU
+	select HW_HAS_PCI
+	select DMA_NONCOHERENT
+	help
+	  This enables support for the VR5500 - based NEC Electronics Corporation 
+	  VR5701 SolutionGearII evaluation board.
+
+
+
 config NEC_OSPREY
 	bool "Support for NEC Osprey board"
 	select DMA_NONCOHERENT
@@ -1204,6 +1215,11 @@ config CPU_R5000
 config CPU_R5432
 	bool "R5432"
 
+config CPU_R5500
+	bool "R5500"
+	help
+	  MIPS Technologies Vr5500 - series processors.
+
 config CPU_R6000
 	bool "R6000"
 	depends on MIPS32 && EXPERIMENTAL
Index: linux-2.6.10/arch/mips/vr5701/tcube/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the NEC Electronics Corporation VR5701 SolutionGearII specific kernel interface routines
+# under Linux.
+#
+
+obj-y += setup.o irq.o int-handler.o irq_vr5701.o 
+EXTRA_AFLAGS: = $(CFLAGS)
Index: linux-2.6.10/arch/mips/vr5701/common/rtc_rx5c348.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/rtc_rx5c348.c
@@ -0,0 +1,182 @@
+/*
+ * arch/mips/vr5701/common/rtc_rx5c348.c Version 0.02 April 11, 2005
+ *
+ * A Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII
+ * (RICOH Co., Ltd., Rx5C348B)
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/bcd.h>
+
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/delay.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+#undef  DEBUG
+#undef RTC_DELAY
+
+void static rtc_set_ce(u32 val)
+{
+	pr_debug("rtc_set_ce(%d)\n", val);
+	reg_set32(GIU_PIO0, GPIO_4_CE, val ? SET_32_BIT : 0);
+#ifdef RTC_DELAY
+	__delay(100000);
+#endif
+}
+
+void static rtc_write_burst(int adr, unsigned char *data, int dataLen)
+{
+	int i;
+	for (i = 0; i < dataLen; i++)
+		pr_debug(" rtc_write_burst : data=%08x\n", data[i]);
+	pr_debug(" rtc_write_burst : adr=0x%02x\n", adr);
+	csi1_reset();
+	while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+	reg_set32(CSI1_MODE, CSIn_MODE_AUTO, SET_32_BIT);
+	reg_set32(CSI1_MODE, CSIn_MODE_TRMD, SET_32_BIT);
+	io_out32(CSI1_INT, CSIn_INT_CSIEND);
+	rtc_set_ce(1);
+
+	pr_debug(" rtc_write_burst : CSI1_MODE=%08x\n", io_in32(CSI1_MODE));
+	pr_debug(" rtc_write_burst : CSI1_CNT=%08x\n", io_in32(CSI1_CNT));
+	io_out32(CSI1_SOTBF, ((adr << 4) | 0x00));
+
+	for (i = 0; i < dataLen; i++) {
+		io_out32(CSI1_SOTB, data[i]);
+		while (!(io_in32(CSI1_INT) & CSIn_INT_CSIEND)) ;
+		io_out32(CSI1_INT, CSIn_INT_CSIEND);
+	}
+	while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+	rtc_set_ce(0);
+}
+
+void static rtc_read_burst(int adr, unsigned char *data, int dataLen)
+{
+	int i;
+	pr_debug(" rtc_read_burst : adr=0x%02x\n", adr);
+	while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+	reg_set32(CSI1_MODE, CSIn_MODE_AUTO, CLR_32_BIT);
+	reg_set32(CSI1_MODE, CSIn_MODE_TRMD, SET_32_BIT);
+	io_out32(CSI1_INT, CSIn_INT_CSIEND);
+	rtc_set_ce(1);
+
+	pr_debug(" rtc_read_burst : CSI1_MODE=%08x\n", io_in32(CSI1_MODE));
+	pr_debug(" rtc_read_burst : CSI1_CNT=%08x\n", io_in32(CSI1_CNT));
+	io_out32(CSI1_SOTB, (((adr & 0xf) << 4) | 0x04));
+	while (!(io_in32(CSI1_INT) & CSIn_INT_CSIEND)) ;
+
+	while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+	reg_set32(CSI1_MODE, CSIn_MODE_TRMD, CLR_32_BIT);
+	io_out32(CSI1_INT, CSIn_INT_CSIEND);
+
+	udelay(50);
+	pr_debug(" rtc_read_burst : CSI1_MODE=%08x\n", io_in32(CSI1_MODE));
+	pr_debug(" rtc_read_burst : CSI1_CNT=%08x\n", io_in32(CSI1_CNT));
+	io_in32(CSI1_SIRB);	/* dummy read */
+
+	for (i = 0; i < dataLen; i++) {
+		while (!(io_in32(CSI1_INT) & CSIn_INT_CSIEND)) ;
+		io_out32(CSI1_INT, CSIn_INT_CSIEND);
+		data[i] = io_in32(CSI1_SIRB);
+	}
+	while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+	rtc_set_ce(0);
+	for (i = 0; i < dataLen; i++)
+		pr_debug(" rtc_read_burst : data=%08x\n", data[i]);
+}
+
+static unsigned long rtc_ricoh_rx5c348_get_time(void)
+{
+	u8 date[7];
+	unsigned int year, month, day, hour, minute, second;
+
+	rtc_read_burst(0, date, sizeof(date));
+
+	year = BCD2BIN(date[6]) + (date[5] & 0x80 ? 2000 : 1900);
+	month = BCD2BIN(date[5] & 0x1f);
+	day = BCD2BIN(date[4]);
+	hour = BCD2BIN(date[2]);
+	minute = BCD2BIN(date[1]);
+	second = BCD2BIN(date[0]);
+
+	pr_debug(KERN_INFO
+		 "rtc_ricoh_rx5c348_get_time: %d/%02d/%02d %02d:%02d:%02d\n",
+		 year, month, day, hour, minute, second);
+	return mktime(year, month, day, hour, minute, second);
+}
+
+static int rtc_ricoh_rx5c348_set_time(unsigned long t)
+{
+	u8 date[7];
+	struct rtc_time tm;
+
+	to_tm(t, &tm);
+	date[0] = BIN2BCD(tm.tm_sec);
+	date[1] = BIN2BCD(tm.tm_min);
+	date[2] = BIN2BCD(tm.tm_hour);
+	date[4] = BIN2BCD(tm.tm_mday);
+	date[5] = BIN2BCD(tm.tm_mon + 1) + (tm.tm_year > 1999 ? 0x80 : 0);
+	date[6] =
+	    BIN2BCD(tm.tm_year > 1999 ? tm.tm_year - 2000 : tm.tm_year - 1900);
+
+	rtc_write_burst(0, date, 3);
+	rtc_write_burst(4, date + 4, 3);
+
+	pr_debug(KERN_INFO
+		 "rtc_ricoh_rx5c348_set_time:t=%ld %d/%02d/%02d %02d:%02d:%02d\n",
+		 t, tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+		 tm.tm_min, tm.tm_sec);
+	return 0;
+}
+
+static int __devinit rtc_ricoh_rx5c348_init(void)
+{
+	unsigned char data;
+	/* CSI1 reset  */
+	io_set16(PIB_RESET, 0x40, 0xffff);
+	__delay(10000);
+	io_set16(PIB_RESET, 0x40, 0x0000);
+
+	/* set GPIO3 , GPIO4 */
+	reg_set32(GIU_FUNCSEL0, (GPIO_4_CE | GPIO_3_INTR), SET_32_BIT);
+	/* clear GPIO25 , GPIO26 , GPIO27 */
+	reg_set32(GIU_FUNCSEL0, GPIO_CSI1_PIN, CLR_32_BIT);
+	/* make GPIO4 output */
+	reg_set32(GIU_DIR0, GPIO_4_CE, SET_32_BIT);
+	/* make GPIO3 input  */
+	reg_set32(GIU_DIR0, GPIO_3_INTR, CLR_32_BIT);
+
+	csi1_reset();
+
+	rtc_read_burst(0x0e, &data, 1);
+	if ((data & 0x20) == 0) {	/* 24 hour */
+		data |= 0x20;
+		rtc_write_burst(0x0e, &data, 1);
+#ifdef RTC_DELAY
+		__delay(10000);
+#endif
+	}
+
+	/* set the function pointers */
+	rtc_get_time = rtc_ricoh_rx5c348_get_time;
+	rtc_set_time = rtc_ricoh_rx5c348_set_time;
+	return 0;
+}
+
+module_init(rtc_ricoh_rx5c348_init);
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/drivers/pci/pci.ids
===================================================================
--- linux-2.6.10.orig/drivers/pci/pci.ids
+++ linux-2.6.10/drivers/pci/pci.ids
@@ -1451,7 +1451,7 @@
 	6057  MiroVideo DC10/DC30+
 1032  Compaq
 1033  NEC Corporation
-	0000  Vr4181A USB Host or Function Control Unit
+	0000  Vr4181A USB Host or IDE Controller
 	0001  PCI to 486-like bus Bridge
 	0002  PCI to VL98 Bridge
 	0003  ATM Controller
@@ -1491,7 +1491,7 @@
 		1033 8014  RCV56ACF 56k Voice Modem
 	009b  Vrc5476
 	00a5  VRC4173
-	00a6  VRC5477 AC97
+	00a6  VRC5477 or VR5701 AC97 Controller
 	00cd  IEEE 1394 [OrangeLink] Host Controller
 		12ee 8011  Root hub
 	00ce  IEEE 1394 Host Controller
Index: linux-2.6.10/drivers/video/smi/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+# under Linux.
+#
+
+obj-$(CONFIG_FB_SM)	+= smfb.o
+
+smfb-objs	:= smi_base.o smi_hw.o 
+
Index: linux-2.6.10/arch/mips/vr5701/tcube/setup.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/setup.c
@@ -0,0 +1,188 @@
+/*
+ * arch/mips/vr5701/tcube/setup.c
+ *
+ * Setup file for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/fs.h>		/* for ROOT_DEV */
+#include <linux/ioport.h>
+#include <linux/param.h>	/* for HZ */
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+static void tcube_machine_restart(char *command)
+{
+	static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000;
+	back_to_prom();
+}
+
+static void tcube_machine_halt(void)
+{
+	printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted.\n");
+	while (1) ;
+}
+
+static void tcube_machine_power_off(void)
+{
+	printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted. Please turn off the power.\n");
+	while (1) ;
+}
+
+static void __init tcube_time_init(void)
+{
+	mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
+}
+
+static void __init tcube_timer_setup(struct irqaction *irq)
+{
+	unsigned int count;
+	irq->flags |= SA_NODELAY;
+
+	/* we are using the cpu counter for timer interrupts */
+	setup_irq(7, irq);
+
+	/* to generate the first timer interrupt */
+	count = read_c0_count();
+	write_c0_compare(count + 10000);
+}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end;
+#endif
+
+static void chk_init_5701_reg(unsigned long addr, unsigned long data)
+{
+	unsigned long a = ddb_in32(addr);
+
+	if (a != data) {
+		printk(KERN_INFO
+		       "Unexpected 5701 reg : addr = %08lX, expected = %08lX, read = %08lX\n",
+		       addr + VR5701_IO_BASE, data, a);
+	}
+}
+
+static void __init tcube_board_init(void)
+{
+	chk_init_5701_reg(0, 0x1e00008f);
+	chk_init_5701_reg(PADR_SDRAM01, 0x000000a8);
+	chk_init_5701_reg(PADR_LOCALCS0, 0x1f00004c);
+	chk_init_5701_reg(LOCAL_CST0, 0x00088622);
+	chk_init_5701_reg(LOCAL_CFG, 0x000f0000);
+
+	/* setup PCI windows - window0 for MEM/config, window1 for IO */
+	ddb_set_pdar(PADR_PCIW0, 0x10000000, 0x08000000, 32, 0, 1);
+	ddb_set_pdar(PADR_PCIW1, 0x18000000, 0x00800000, 32, 0, 1);
+	ddb_set_pdar(PADR_IOPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
+	ddb_set_pdar(PADR_IOPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
+	/* ------------ reset PCI bus and BARs ----------------- */
+	ddb_pci_reset_bus();
+	/* Ext. PCI memory space */
+	ddb_out32(PCI_BAR_MEM01, 0x00000008);
+	ddb_out8(PCI_MLTIM, 0x40);
+
+	ddb_out32(PCI_BAR_LCS0, 0xffffffff);
+	ddb_out32(PCI_BAR_LCS1, 0xffffffff);
+	ddb_out32(PCI_BAR_LCS2, 0xffffffff);
+	ddb_out32(PCI_BAR_LCS3, 0xffffffff);
+	/* Int. PCI memory space */
+	ddb_out8(IPCI_MLTIM, 0x40);
+
+	ddb_out32(IPCI_BAR_LCS0, 0xffffffff);
+	ddb_out32(IPCI_BAR_LCS1, 0xffffffff);
+	ddb_out32(IPCI_BAR_LCS2, 0xffffffff);
+	ddb_out32(IPCI_BAR_LCS3, 0xffffffff);
+	ddb_out32(IPCI_BAR_IREG, 0xffffffff);
+
+	/*
+	 * We use pci master register 0  for memory space / config space
+	 * And we use register 1 for IO space.
+	 * Note that for memory space, we bump up the pci base address
+	 * so that we have 1:1 mapping between PCI memory and cpu physical.
+	 * For PCI IO space, it starts from 0 in PCI IO space but with
+	 * IO_BASE in CPU physical address space.
+	 */
+	ddb_set_pmr(EPCI_INIT0, DDB_PCICMD_MEM, 0x10000000, DDB_PCI_ACCESS_32);
+	ddb_set_pmr(EPCI_INIT1, DDB_PCICMD_IO, 0x00001000, DDB_PCI_ACCESS_32);
+	ddb_set_pmr(IPCI_INIT0, DDB_PCICMD_MEM, 0x18800000, DDB_PCI_ACCESS_32);
+	ddb_set_pmr(IPCI_INIT1, DDB_PCICMD_IO, 0x01000000, DDB_PCI_ACCESS_32);
+
+	/* PCI cross window should be set properly */
+	ddb_set_pdar(PCI_BAR_IPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
+	ddb_set_pdar(PCI_BAR_IPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
+	ddb_set_pdar(IPCI_BAR_EPCIW0, 0x10000000, 0x08000000, 32, 0, 1);
+	ddb_set_pdar(IPCI_BAR_EPCIW1, 0x18000000, 0x00800000, 32, 0, 1);
+
+	/* setup GPIO */
+	ddb_out32(GIU_DIR0, 0xf7ebffdf);
+	ddb_out32(GIU_DIR1, 0x000007fa);
+	ddb_out32(GIU_FUNCSEL0, 0xf1c1ffff);
+	ddb_out32(GIU_FUNCSEL1, 0x000007f0);
+	chk_init_5701_reg(GIU_DIR0, 0xf7ebffdf);
+	chk_init_5701_reg(GIU_DIR1, 0x000007fa);
+	chk_init_5701_reg(GIU_FUNCSEL0, 0xf1c1ffff);
+	chk_init_5701_reg(GIU_FUNCSEL1, 0x000007f0);
+
+	/* enable USB input buffers */
+	ddb_out32(PIB_MISC, (ddb_in32(PIB_MISC) | 0x00000031));
+}
+
+int __init shima_tcube_setup(void)
+{
+	set_io_port_base(0xB8000000);
+
+	board_time_init = tcube_time_init;
+	board_timer_setup = tcube_timer_setup;
+
+	_machine_restart = tcube_machine_restart;
+	_machine_halt = tcube_machine_halt;
+	_machine_power_off = tcube_machine_power_off;
+
+	/* setup resource limits */
+	ioport_resource.end = 0x02000000;
+	iomem_resource.end = 0xffffffff;
+
+	/* Reboot on panic */
+	panic_timeout = 30;
+
+#ifdef CONFIG_FB
+	conswitchp = &dummy_con;
+#endif
+
+	tcube_board_init();
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	initrd_start = (unsigned long)&__rd_start;
+	initrd_end = (unsigned long)&__rd_end;
+#endif
+	register_pci_controller(&VR5701_ext_controller);
+	register_pci_controller(&VR5701_io_controller);
+	return 0;
+}
+
+void __init bus_error_init(void)
+{
+	/* do nothing */
+}
+
+early_initcall(shima_tcube_setup);
Index: linux-2.6.10/drivers/ide/Kconfig
===================================================================
--- linux-2.6.10.orig/drivers/ide/Kconfig
+++ linux-2.6.10/drivers/ide/Kconfig
@@ -836,6 +836,13 @@ config BLK_DEV_GAYLE
 	  Note that you also have to enable Zorro bus support if you want to
 	  use Gayle IDE interfaces on the Zorro expansion bus.
 
+config BLK_DEV_NEC_VR5701_SG2
+	tristate "NEC Electronics Corporation VR5701 SolutionGearII IDE interface support"
+	depends on TCUBE
+	help
+	  This is the IDE driver for the NEC Electronics Corporation VR5701 
+	  SolutionGearII IDE interface. 
+
 config BLK_DEV_IDEDOUBLER
 	bool "Amiga IDE Doubler support (EXPERIMENTAL)"
 	depends on BLK_DEV_GAYLE && EXPERIMENTAL
Index: linux-2.6.10/arch/mips/vr5701/tcube/irq.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/irq.c
@@ -0,0 +1,146 @@
+/*
+ * arch/mips/vr5701/tcube/irq.c
+ *
+ * The irq setup and misc routines for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+/*
+ * IRQ mapping
+ *
+ *  0-7: 8 CPU interrupts
+ *	0 -	software interrupt 0
+ *	1 -	software interrupt 1
+ *	2 -	most Vrc5477 interrupts are routed to this pin
+ *	3 -	(optional) some other interrupts routed to this pin for debugg
+ *	4 -	not used
+ *	5 -	not used
+ *	6 -	not used
+ *	7 -	cpu timer (used by default)
+ *
+ */
+
+void tcube_irq_setup(void)
+{
+	pr_debug("NEC Electronics Corporation VR5701 SolutionGearII irq setup invoked.\n");
+
+	/* by default, we disable all interrupts and route all vr5701
+	 * interrupts to pin 0 (irq 2) */
+	ddb_out32(INT_ROUTE0, 0);
+	ddb_out32(INT_ROUTE1, 0);
+	ddb_out32(INT_ROUTE2, 0);
+	ddb_out32(INT_ROUTE3, 0);
+	ddb_out32(INT_MASK, 0);
+	ddb_out32(INT_CLR, ~0x0);
+
+	clear_c0_status(0xff00);
+	set_c0_status(0x0400);
+
+	ll_vr5701_irq_route(24, 1);
+	ll_vr5701_irq_enable(24);
+	ll_vr5701_irq_route(25, 1);
+	ll_vr5701_irq_enable(25);
+	ll_vr5701_irq_route(28, 1);
+	ll_vr5701_irq_enable(28);
+	ll_vr5701_irq_route(29, 1);
+	ll_vr5701_irq_enable(29);
+	ll_vr5701_irq_route(30, 1);
+	ll_vr5701_irq_enable(30);
+	ll_vr5701_irq_route(31, 1);
+	ll_vr5701_irq_enable(31);
+	set_c0_status(0x0800);
+	set_except_vector(0, tcube_handle_int);
+	/* init all controllers */
+	mips_cpu_irq_init(0);
+	vr5701_irq_init(8);
+}
+
+/*
+ * the first level int-handler will jump here if it is a vr7701 irq
+ */
+
+asmlinkage void tcube_irq_dispatch(struct pt_regs *regs)
+{
+	u32 intStatus;
+	u32 bitmask;
+	u32 i;
+	u32 intPCIStatus;
+	if (ddb_in32(INT1_STAT) != 0) {
+		printk(KERN_CRIT "NMI  = %x\n", ddb_in32(NMI_STAT));
+		printk(KERN_CRIT "INT0 = %x\n", ddb_in32(INT0_STAT));
+		printk(KERN_CRIT "INT1 = %x\n", ddb_in32(INT1_STAT));
+		printk(KERN_CRIT "INT2 = %x\n", ddb_in32(INT2_STAT));
+		printk(KERN_CRIT "INT3 = %x\n", ddb_in32(INT3_STAT));
+		printk(KERN_CRIT "INT4 = %x\n", ddb_in32(INT4_STAT));
+		printk(KERN_CRIT "EPCI_ERR = %x\n", ddb_in32(EPCI_ERR));
+		printk(KERN_CRIT "IPCI_ERR = %x\n", ddb_in32(IPCI_ERR));
+
+		panic("error interrupt has happened.");
+	}
+
+	intStatus = ddb_in32(INT0_STAT);
+
+	if (intStatus & 1 << 6)
+		goto IRQ_EPCI;
+
+	if (intStatus & 1 << 7)
+		goto IRQ_IPCI;
+
+      IRQ_OTHER:
+	for (i = 0, bitmask = 1; i <= NUM_5701_IRQS; bitmask <<= 1, i++) {
+		/* do we need to "and" with the int mask? */
+		if (intStatus & bitmask) {
+			do_IRQ(8 + i, regs);
+		}
+	}
+	return;
+
+      IRQ_EPCI:
+	intStatus &= ~(1 << 6);	/* unset Status flag */
+	intPCIStatus = ddb_in32(EPCI_INTS);
+	for (i = 0, bitmask = 1; i < NUM_5701_EPCI_IRQS; bitmask <<= 1, i++) {
+		if (intPCIStatus & bitmask) {
+			do_IRQ(8 + NUM_5701_IRQS + i, regs);
+		}
+	}
+	if (!intStatus)
+		return;
+
+      IRQ_IPCI:
+	intStatus &= ~(1 << 7);
+	intPCIStatus = ddb_in32(IPCI_INTS);
+	if (!intPCIStatus)
+		goto IRQ_OTHER;
+
+	for (i = 0, bitmask = 1; i < NUM_5701_IPCI_IRQS; bitmask <<= 1, i++) {
+		if (intPCIStatus & bitmask) {
+			do_IRQ(8 + NUM_5701_IRQS + NUM_5701_EPCI_IRQS + i,
+			       regs);
+		}
+	}
+
+	if (!intStatus)
+		return;
+
+	goto IRQ_OTHER;
+}
+
+void __init arch_init_irq(void)
+{
+	/* invoke board-specific irq setup */
+	tcube_irq_setup();
+}
Index: linux-2.6.10/arch/mips/pci/ops-tcube.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/pci/ops-tcube.c
@@ -0,0 +1,267 @@
+/*
+ * arch/mips/pci/ops-tcube.c
+ *
+ * A config access for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII 
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+/*
+ * config_swap structure records what set of pdar/pmr are used
+ * to access pci config space.  It also provides a place hold the
+ * original values for future restoring.
+ */
+struct pci_config_swap {
+	u32 pdar;
+	u32 pmr;
+	u32 config_base;
+	u32 config_size;
+	u32 pdar_backup;
+	u32 pmr_backup;
+};
+
+/*
+ * On VR5701-SG2, we have two sets of swap registers, for ext PCI and IOPCI.
+ */
+struct pci_config_swap ext_pci_swap = {
+	PADR_EPCIW0,
+	EPCI_INIT0,
+	0x10000000,
+	0x08000000
+};
+struct pci_config_swap io_pci_swap = {
+	PADR_IOPCIW0,
+	IPCI_INIT0,
+	0x18800000,
+	0x00800000
+};
+
+/*
+ * access config space
+ */
+static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus,	/* 0 means top level bus */
+					 u32 slot_num)
+{
+	u32 pci_addr = 0;
+	u32 pciinit_offset = 0;
+	u32 virt_addr;
+	u32 option;
+
+	/* minimum pdar (window) size is 2MB */
+	db_assert(swap->config_size >= (2 << 20));
+	db_assert(slot_num < (1 << 5));
+	db_assert(bus < (1 << 8));
+
+	/* backup registers */
+	swap->pdar_backup = ddb_in32(swap->pdar);
+	swap->pmr_backup = ddb_in32(swap->pmr);
+
+	/* set the pdar (pci window) register */
+	ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32,	/* 32 bit wide */
+		     0,		/* not on local memory bus */
+		     0);	/* not visible from PCI bus (N/A) */
+
+	/*
+	 * calcuate the absolute pci config addr;
+	 * according to the spec, we start scanning from adr:11 (0x800)
+	 */
+	if (bus == 0) {
+		/* type 0 config */
+		pci_addr = 0x800 << slot_num;
+	} else {
+		/* type 1 config */
+		pci_addr = (bus << 16) | (slot_num << 11);
+	}
+
+	/*
+	 * if pci_addr is less than pci config window size,  we set
+	 * pciinit_offset to 0 and adjust the virt_address.
+	 * Otherwise we will try to adjust pciinit_offset.
+	 */
+	if (pci_addr < swap->config_size) {
+		virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
+		pciinit_offset = 0;
+	} else {
+		db_assert((pci_addr & (swap->config_size - 1)) == 0);
+		virt_addr = KSEG1ADDR(swap->config_base);
+		pciinit_offset = pci_addr;
+	}
+
+	/* set the pmr register */
+	option = DDB_PCI_ACCESS_32;
+	if (bus != 0)
+		option |= DDB_PCI_CFGTYPE1;
+
+	ddb_out32(swap->pmr,
+		  (DDB_PCICMD_CFG << 1) | (pciinit_offset & 0xffe00000) |
+		  option);
+	ddb_out32(swap->pmr + 4, 0);
+
+	return virt_addr;
+}
+
+static inline void ddb_close_config_base(struct pci_config_swap *swap)
+{
+	ddb_out32(swap->pdar, swap->pdar_backup);
+	ddb_out32(swap->pmr, swap->pmr_backup);
+}
+
+static int read_config_dword(struct pci_config_swap *swap,
+			     struct pci_bus *bus, u32 devfn, u32 where,
+			     u32 * val)
+{
+	u32 bus_num, slot_num, func_num;
+	u32 base;
+
+	db_assert((where & 3) == 0);
+	db_assert(where < (1 << 8));
+
+	/* check if the bus is top-level */
+	if (bus->parent != NULL) {
+		bus_num = bus->number;
+		db_assert(bus_num != 0);
+	} else {
+		bus_num = 0;
+	}
+	slot_num = PCI_SLOT(devfn);
+	func_num = PCI_FUNC(devfn);
+	base = ddb_access_config_base(swap, bus_num, slot_num);
+	*val = *(volatile u32 *)(base + (func_num << 8) + where);
+	ddb_close_config_base(swap);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int read_config_word(struct pci_config_swap *swap,
+			    struct pci_bus *bus, u32 devfn, u32 where,
+			    u16 * val)
+{
+	int status;
+	u32 result;
+
+	db_assert((where & 1) == 0);
+
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xffff;
+	return status;
+}
+
+static int read_config_byte(struct pci_config_swap *swap,
+			    struct pci_bus *bus, u32 devfn, u32 where, u8 * val)
+{
+	int status;
+	u32 result;
+
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+	if (where & 1)
+		result >>= 8;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xff;
+
+	return status;
+}
+
+static int write_config_dword(struct pci_config_swap *swap,
+			      struct pci_bus *bus, u32 devfn, u32 where,
+			      u32 val)
+{
+	u32 bus_num, slot_num, func_num;
+	u32 base;
+
+	db_assert((where & 3) == 0);
+	db_assert(where < (1 << 8));
+
+	/* check if the bus is top-level */
+	if (bus->parent != NULL) {
+		bus_num = bus->number;
+		db_assert(bus_num != 0);
+	} else {
+		bus_num = 0;
+	}
+
+	slot_num = PCI_SLOT(devfn);
+	func_num = PCI_FUNC(devfn);
+	base = ddb_access_config_base(swap, bus_num, slot_num);
+	*(volatile u32 *)(base + (func_num << 8) + where) = val;
+	ddb_close_config_base(swap);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_config_swap *swap,
+			     struct pci_bus *bus, u32 devfn, u32 where, u16 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	db_assert((where & 1) == 0);
+
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+
+	if (where & 2)
+		shift += 16;
+	result &= ~(0xffff << shift);
+	result |= val << shift;
+	return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+static int write_config_byte(struct pci_config_swap *swap,
+			     struct pci_bus *bus, u32 devfn, u32 where, u8 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+
+	if (where & 2)
+		shift += 16;
+	if (where & 1)
+		shift += 8;
+	result &= ~(0xff << shift);
+	result |= val << shift;
+	return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+#define        MAKE_PCI_OPS(prefix, rw, pciswap, star) \
+static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \
+{ \
+	if (size == 1) \
+     		return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \
+	else if (size == 2) \
+     		return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \
+	/* Size must be 4 */ \
+     	return rw##_config_dword(pciswap, bus, devfn, where, val); \
+}
+
+MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *)
+    MAKE_PCI_OPS(extpci, write, &ext_pci_swap,)
+
+    MAKE_PCI_OPS(iopci, read, &io_pci_swap, *)
+    MAKE_PCI_OPS(iopci, write, &io_pci_swap,)
+
+struct pci_ops VR5701_ext_pci_ops = {
+	.read = extpci_read_config,
+	.write = extpci_write_config
+};
+
+struct pci_ops VR5701_io_pci_ops = {
+	.read = iopci_read_config,
+	.write = iopci_write_config
+};
Index: linux-2.6.10/arch/mips/vr5701/common/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the common code of NEC Electronics Corporation VR5701 SolutionGearII board
+#
+
+obj-y += nec_vrxxxx.o prom.o rtc_rx5c348.o
Index: linux-2.6.10/include/asm-mips/bootinfo.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/bootinfo.h
+++ linux-2.6.10/include/asm-mips/bootinfo.h
@@ -213,6 +213,12 @@
 #define MACH_GROUP_TITAN       22	/* PMC-Sierra Titan		*/
 #define  MACH_TITAN_YOSEMITE	1	/* PMC-Sierra Yosemite		*/
 
+/*
+ * Valid machtype for group SHIMA
+ */
+#define MACH_GROUP_SHIMA       24 /* SHIMAFUJI                              */
+#define MACH_SHIMA_TCUBE         0      /* SHIMAFUJI T-Cube(Vr5701) */
+
 #define CL_SIZE			COMMAND_LINE_SIZE
 
 const char *get_system_type(void);
Index: linux-2.6.10/drivers/video/smi/smifb.h
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smifb.h
@@ -0,0 +1,89 @@
+/*
+ * drivers/video/smi/smifb.h
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver	for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __SMIFB_H__
+#define __SMIFB_H__
+
+#define FBCON_HAS_CFB16
+
+enum ScreenModes {
+	DISPLAY_640x480x16,
+	DISPLAY_800x600x16,
+	DISPLAY_1024x768x16,
+	DISPLAY_640x480x24,
+	DISPLAY_800x600x24,
+	DISPLAY_LCD_400x232x16,
+	modeNums,
+};
+
+#define SMI_DEFAULT_MODE	DISPLAY_640x480x16
+
+#define SIZE_SR00_SR04		(0x04 - 0x00 + 1)
+#define SIZE_SR10_SR24		(0x24 - 0x10 + 1)
+#define SIZE_SR30_SR75		(0x75 - 0x30 + 1)
+#define SIZE_SR80_SR93		(0x93 - 0x80 + 1)
+#define SIZE_SRA0_SRAF		(0xAF - 0xA0 + 1)
+#define SIZE_GR00_GR08		(0x08 - 0x00 + 1)
+#define SIZE_AR00_AR14		(0x14 - 0x00 + 1)
+#define SIZE_CR00_CR18		(0x18 - 0x00 + 1)
+#define SIZE_CR30_CR4D		(0x4D - 0x30 + 1)
+#define SIZE_CR90_CRA7		(0xA7 - 0x90 + 1)
+
+struct smi_mode_regs {
+	int mode;
+	u8 reg_MISC;
+	u8 reg_SR00_SR04[SIZE_SR00_SR04];	/* SEQ00--04 (SEQ) */
+	u8 reg_SR10_SR24[SIZE_SR10_SR24];	/* SCR10--1F, PDR20--24 (SYS),(PWR) */
+	u8 reg_SR30_SR75[SIZE_SR30_SR75];	/* FPR30--5A, MCR60--62, CCR65--6F  GPR70--75 (LCD),(MEM),(CLK),(GP) */
+	u8 reg_SR80_SR93[SIZE_SR80_SR93];	/* PHR80-81, POP82--86, HCR88-8D, POP90--93 (CURS),(ICON),(CURS),(ICON) */
+	u8 reg_SRA0_SRAF[SIZE_SRA0_SRAF];	/* FPRA0--AF (LCD) */
+	u8 reg_GR00_GR08[SIZE_GR00_GR08];	/* GR00--08 (GC) */
+	u8 reg_AR00_AR14[SIZE_AR00_AR14];	/* ATR00--14 (ATTR) */
+	u8 reg_CR00_CR18[SIZE_CR00_CR18];	/* CRT00--18 (CRTC) */
+	u8 reg_CR30_CR4D[SIZE_CR30_CR4D];	/* CRT30--3F, SVR40--4D (ECRTC),(SHADOW) */
+	u8 reg_CR90_CRA7[SIZE_CR90_CRA7];	/* CRT90--9B,9E,9F,A0--A5,A6,A7, (DDA),(EC2),(EC1)(VCLUT),(VC),(HC) */
+};
+
+typedef struct {
+	unsigned char red, green, blue, transp;
+} smi_cfb8_cmap_t;
+
+struct smifb_info;
+struct smifb_info {
+	struct fb_info info;	/* kernel framebuffer info */
+	const char *drvr_name;	/* Silicon Motion hardware board type */
+	struct pci_dev *pd;	/* descripbe the PCI device */
+	unsigned long base_phys;	/* physical base address                  */
+
+	/* PCI base physical addresses */
+	unsigned long fb_base_phys;	/* physical Frame Buffer base address                  */
+	unsigned long dpr_base_phys;	/* physical Drawing Processor base address             */
+	unsigned long vpr_base_phys;	/* physical Video Processor base address               */
+	unsigned long cpr_base_phys;	/* physical Capture Processor base address             */
+	unsigned long mmio_base_phys;	/* physical MMIO spase (VGA + SMI regs ?) base address */
+	unsigned long dpport_base_phys;	/* physical Drawing Processor Data Port base address   */
+	int dpport_size;	/* size of Drawin Processor Data Port memory space     */
+
+	/* PCI base virtual addresses */
+	caddr_t base;		/* address of base */
+	caddr_t fb_base;	/* address of frame buffer base */
+	caddr_t dpr;		/* Drawing Processor Registers  */
+	caddr_t vpr;		/* Video Processor Registers    */
+	caddr_t cpr;		/* Capture Processor Registers  */
+	caddr_t mmio;		/* Memory Mapped I/O Port       */
+	caddr_t dpport;		/* Drawing Processor Data       */
+
+	int fbsize;		/* Frame-Buffer memory size */
+};
+
+#endif				/* __SMIFB_H__ */
Index: linux-2.6.10/arch/mips/mm/tlbex.c
===================================================================
--- linux-2.6.10.orig/arch/mips/mm/tlbex.c
+++ linux-2.6.10/arch/mips/mm/tlbex.c
@@ -784,6 +784,7 @@ static __init void __attribute__((unused
 	case CPU_R5000:
 	case CPU_R5000A:
 	case CPU_NEVADA:
+	case CPU_R5500:
 		i_nop(p);
 		i_tlbp(p);
 		break;
@@ -831,6 +832,7 @@ static __init void build_tlb_write_entry
 	case CPU_R4600:
 	case CPU_R4700:
 	case CPU_R5000:
+	case CPU_R5500:             
 	case CPU_R5000A:
 	case CPU_5KC:
 	case CPU_TX49XX:
Index: linux-2.6.10/arch/mips/vr5701/common/prom.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/prom.c
@@ -0,0 +1,53 @@
+/*
+ * arch/mips/vr5701/common/prom.c
+ *
+ * A code for prom routines on NEC Electronics Corporation VR5701 SolutionGearII 
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+const char *get_system_type(void)
+{
+	return "NEC Electronics Corporation VR5701 SolutionGearII";
+}
+
+void __init prom_init(void)
+{
+	int i;
+	int argc = fw_arg0;
+	char **arg = (char **)fw_arg1;
+
+	/* if user passes kernel args, ignore the default one */
+	if (argc > 1)
+		arcs_cmdline[0] = '\0';
+
+	/* arg[0] is "g", the rest is boot parameters */
+	for (i = 1; i < argc; i++) {
+		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+		    >= sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, arg[i]);
+		strcat(arcs_cmdline, " ");
+	}
+	mips_machgroup = MACH_GROUP_SHIMA;
+	mips_machtype = MACH_SHIMA_TCUBE;
+	add_memory_region(0, TCUBE_SDRAM_SIZE, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
Index: linux-2.6.10/arch/mips/lib-64/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/lib-64/Makefile
+++ linux-2.6.10/arch/mips/lib-64/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R5500)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R6000)		+=
 obj-$(CONFIG_CPU_R8000)		+=
 obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
Index: linux-2.6.10/arch/mips/lib-32/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/lib-32/Makefile
+++ linux-2.6.10/arch/mips/lib-32/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R5500)		+= dump_tlb.o
 obj-$(CONFIG_CPU_R6000)		+=
 obj-$(CONFIG_CPU_R8000)		+=
 obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
Index: linux-2.6.10/sound/oss/Kconfig
===================================================================
--- linux-2.6.10.orig/sound/oss/Kconfig
+++ linux-2.6.10/sound/oss/Kconfig
@@ -233,6 +233,13 @@ config SOUND_VRC5477
 	  integrated, multi-function controller chip for MIPS CPUs.  Works
 	  with the AC97 codec.
 
+config SOUND_VR5701
+	tristate "NEC Electronics Corporation VR5701 SolutionGearII AC97 sound"
+	depends on SOUND_PRIME!=n && TCUBE && SOUND
+	help
+	  Say Y here to enable sound support for the NEC Electronics Corporation 
+	  VR5701 SolutionGearII AC97 sound. Works with the AC97 codec.
+
 config SOUND_AU1000
 	tristate "Au1000 Sound"
 	depends on SOUND_PRIME!=n && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SOUND
Index: linux-2.6.10/drivers/video/Kconfig
===================================================================
--- linux-2.6.10.orig/drivers/video/Kconfig
+++ linux-2.6.10/drivers/video/Kconfig
@@ -795,6 +795,25 @@ config FB_ATY_GX
 	  is at
 	  <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
 
+config FB_SM
+	tristate "Silicon Motion SM722 support"
+	depends on FB && PCI
+	help
+	  SM722
+
+choice
+	prompt "Display size"
+	depends on FB_SM
+	default DISPLAY_640x480
+
+config DISPLAY_640x480
+	bool "640x480"
+
+config DISPLAY_1024x768
+	bool "1024x768"
+
+endchoice
+
 config FB_SAVAGE
 	tristate "S3 Savage support"
 	depends on FB && PCI && EXPERIMENTAL
Index: linux-2.6.10/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-2.6.10.orig/arch/mips/kernel/cpu-probe.c
+++ linux-2.6.10/arch/mips/kernel/cpu-probe.c
@@ -98,6 +98,7 @@ static inline void check_wait(void)
 	case CPU_R4650:
 	case CPU_R4700:
 	case CPU_R5000:
+	case CPU_R5500:
 	case CPU_NEVADA:
 	case CPU_RM7000:
 	case CPU_RM9000:
Index: linux-2.6.10/drivers/video/smi/smi_params.h
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_params.h
@@ -0,0 +1,442 @@
+/*
+ * drivers/video/smi/smi_params.h
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver	for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __SMI_REGS_H__
+#define __SMI_REGS_H__
+
+/* register settings */
+struct smi_mode_regs ModeInitParams[modeNums] = {
+	/* mode#4 640 x 480 16Bpp 60Hz */
+	{
+	 DISPLAY_640x480x16,
+	 /* reg_MISC */
+	 0xE3,
+	 /* reg_SR00_SR04 */
+	 {
+	  0x03, 0x01, 0x0F, 0x00, 0x0E,
+	  },
+	 /* reg_SR10_SR24 */
+	 {
+	  0x03, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x10, 0x2C,
+	  0x59, 0x00, 0x20, 0x00, 0x00, 0x0F, 0x0F, 0x00,
+	  0xC4, 0x30, 0x02, 0x01, 0x01,
+	  },
+
+	 /* reg_SR30_SR75 */
+	 {
+	  0xAA, 0x03, 0xA0, 0x89, 0xC0, 0xAA, 0xAA, 0xAA,
+	  0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x03, 0xFF,
+	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0xAA,
+	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+	  0x04, 0x50, 0x19, 0xAA, 0xAA, 0x00, 0x00, 0xAA,
+	  0x01, 0x80, 0xFF, 0x1A, 0x1A, 0x00, 0x03, 0x00,
+	  0x50, 0x03, 0x0D, 0x02, 0x07, 0x82, 0x07, 0x04,
+	  0x00, 0x45, 0x30, 0x0C, 0x40, 0x30,
+	  },
+	 /* reg_SR80_SR93 */
+	 {
+	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0xAA,
+	  0x40, 0x01, 0xF0, 0x00, 0xFF, 0x00, 0xAA, 0xAA,
+	  0x00, 0x00, 0x00, 0x00,
+	  },
+	 /* reg_SRA0_SRAF */
+	 {
+	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+	  },
+	 /* reg_GR00_GR08 */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+	  0xFF,
+	  },
+	 /* reg_AR00_AR14 */
+	 {
+	  0x3F, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	  0x10, 0x00, 0x12, 0x00, 0x04,
+	  },
+	 /* reg_CR00_CR18 */
+	 {
+	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+	  0xFF,
+	  },
+	 /* reg_CR30_CR4D */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+	  },
+	 /* reg_CR90_CRA7 */
+	 {
+	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+	  },
+	 },
+	/* mode#5 800 x 600 16Bpp 60Hz */
+	{
+	 DISPLAY_800x600x16,
+	 /* reg_MISC */
+	 0x2B,
+	 /* reg_SR00_SR04 */
+	 {
+	  0x03, 0x01, 0x0F, 0x03, 0x0E,
+	  },
+	 /* reg_SR10_SR24 */
+	 {
+	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0xe2,
+	  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0xC4, 0x30, 0x02, 0x01, 0x01,
+	  },
+	 /* reg_SR30_SR75 */
+	 {
+	  0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
+	  0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
+	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
+	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+	  0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
+	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+	  0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
+	  },
+	 /* reg_SR80_SR93 */
+	 {
+	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
+	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
+	  0x00, 0x00, 0x00, 0x00,
+	  },
+	 /* reg_SRA0_SRAF */
+	 {
+	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+	  },
+	 /* reg_GR00_GR08 */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+	  0xFF,
+	  },
+	 /* reg_AR00_AR14 */
+	 {
+	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	  0x41, 0x00, 0x0F, 0x00, 0x00,
+	  },
+	 /* reg_CR00_CR18 */
+	 {
+	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+	  0xFF,
+	  },
+	 /* reg_CR30_CR4D */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+	  },
+	 /* reg_CR90_CRA7 */
+	 {
+	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+	  },
+	 },
+	/* mode#6 1024 x 768 16Bpp 60Hz * */
+	{
+	 DISPLAY_1024x768x16,
+	 /* reg_MISC */
+	 0xEB,
+	 /* reg_SR00_SR04 */
+	 {
+	  0x03, 0x01, 0x0F, 0x03, 0x0E,
+	  },
+	 /* reg_SR10_SR24 */
+	 {
+	  0x03, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x10, 0x2c,
+	  0x59, 0x02, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
+	  0xC4, 0x30, 0x02, 0x01, 0x01,
+	  },
+	 /* reg_SR30_SR75 */
+	 {
+	  0xAA, 0x03, 0x20, 0x89, 0xC0, 0xAA, 0xAA, 0xAA,
+	  0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x03, 0xFF,
+	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0xAA,
+	  0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+	  0x00, 0x60, 0x59, 0xAA, 0xAA, 0x00, 0x00, 0xAA,
+	  0x01, 0x80, 0xFF, 0x1A, 0x1A, 0x00, 0x03, 0x00,
+	  0x50, 0x03, 0x0D, 0x02, 0x12, 0x82, 0x09, 0x02,
+	  0x04, 0x45, 0x30, 0x0C, 0x40, 0x20,
+	  },
+	 /* reg_SR80_SR93 */
+	 {
+	  0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA,
+	  0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xAA, 0xAA,
+	  0x00, 0x00, 0x00, 0x00,
+	  },
+	 /* reg_SRA0_SRAF */
+	 {
+	  0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+	  0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+	  },
+	 /* reg_GR00_GR08 */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+	  0xFF,
+	  },
+	 /* reg_AR00_AR14 */
+	 {
+	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	  0x41, 0x11, 0x0F, 0x13, 0x00,
+	  },
+	 /* reg_CR00_CR18 */
+	 {
+	  0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+	  0xFF,
+	  },
+	 /* reg_CR30_CR4D */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+	  0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+	  0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
+	  0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
+	  },
+	 /* reg_CR90_CRA7 */
+	 {
+	  0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+	  0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+	  0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+	  },
+	 },
+	/* mode#7 640 x 480 24Bpp 60Hz */
+	{
+	 DISPLAY_640x480x24,
+	 /* reg_MISC */
+	 0xE3,
+	 /* reg_SR00_SR04 */
+	 {
+	  0x03, 0x01, 0x0F, 0x00, 0x0E,
+	  },
+	 /* reg_SR10_SR24 */
+	 {
+	  0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0xe2,
+	  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0xC4, 0x30, 0x02, 0x01, 0x01,
+	  },
+	 /* reg_SR30_SR75 */
+	 {
+	  0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+	  0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+	  0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+	  0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+	  0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+	  0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+	  },
+	 /* reg_SR80_SR93 */
+	 {
+	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+	  0x00, 0x00, 0x00, 0x00,
+	  },
+	 /* reg_SRA0_SRAF */
+	 {
+	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+	  },
+	 /* reg_GR00_GR08 */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+	  0xFF,
+	  },
+	 /* reg_AR00_AR14 */
+	 {
+	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	  0x41, 0x00, 0x0F, 0x00, 0x00,
+	  },
+	 /* reg_CR00_CR18 */
+	 {
+	  0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+	  0xFF,
+	  },
+	 /* reg_CR30_CR4D */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+	  0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+	  0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+	  },
+	 /* reg_CR90_CRA7 */
+	 {
+	  0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+	  0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+	  0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+	  },
+	 },
+	/* mode#8 800 x 600 24Bpp 60Hz */
+	{
+	 DISPLAY_800x600x24,
+	 /* reg_MISC */
+	 0x2B,
+	 /* reg_SR00_SR04 */
+	 {
+	  0x03, 0x01, 0x0F, 0x03, 0x0E,
+	  },
+	 /* reg_SR10_SR24 */
+	 {
+	  0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0xe2,
+	  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0xC4, 0x30, 0x02, 0x01, 0x01,
+	  },
+	 /* reg_SR30_SR75 */
+	 {
+	  0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
+	  0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
+	  0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+	  0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
+	  0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+	  0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
+	  0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+	  0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+	  0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
+	  },
+	 /* reg_SR80_SR93 */
+	 {
+	  0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
+	  0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
+	  0x00, 0x00, 0x00, 0x00,
+	  },
+	 /* reg_SRA0_SRAF */
+	 {
+	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+	  },
+	 /* reg_GR00_GR08 */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+	  0xFF,
+	  },
+	 /* reg_AR00_AR14 */
+	 {
+	  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	  0x41, 0x00, 0x0F, 0x00, 0x00,
+	  },
+	 /* reg_CR00_CR18 */
+	 {
+	  0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+	  0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+	  0xFF,
+	  },
+	 /* reg_CR30_CR4D */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+	  0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+	  0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+	  0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+	  },
+	 /* reg_CR90_CRA7 */
+	 {
+	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+	  0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+	  0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+	  },
+	 },
+	/* mode#9 400 x 232 16Bpp 60Hz */
+	{
+	 DISPLAY_LCD_400x232x16,
+	 /* reg_MISC */
+	 0x2B,
+	 /* reg_SR00_SR04 */
+	 {
+	  0x03, 0x01, 0x0F, 0x03, 0x0E,
+	  },
+	 /* reg_SR10_SR24 */
+	 {
+	  0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x2C,
+	  0x59, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
+	  0x84, 0x00, 0x02, 0x00, 0x31,
+	  },
+	 /* reg_SR30_SR75 */
+	 {
+	  0xB7, 0x43, 0x98, 0x01, 0xC0, 0xB7, 0xB7, 0xB7,
+	  0xB7, 0xB7, 0xB7, 0xB7, 0x00, 0x00, 0x85, 0x2C,
+	  0xC0, 0xE1, 0x00, 0x00, 0x40, 0xF0, 0x80, 0xC4,
+	  0x40, 0x3C, 0xA1, 0x40, 0x00, 0x00, 0x01, 0xB7,
+	  0x02, 0x24, 0xD9, 0xC7, 0xCC, 0x31, 0x2C, 0x2D,
+	  0x07, 0x57, 0x19, 0xB7, 0xB7, 0x00, 0x00, 0xB7,
+	  0x01, 0x00, 0xFF, 0x1A, 0x1A, 0x01, 0x03, 0x00,
+	  0xD4, 0x07, 0x0D, 0x02, 0x23, 0x3F, 0x35, 0x13,
+	  0x83, 0xDD, 0x02, 0x0C, 0x05, 0x00,
+	  },
+	 /* reg_SR80_SR93 */
+	 {
+	  0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x09, 0xB7,
+	  0x48, 0x00, 0x36, 0x00, 0xFF, 0x00, 0xB7, 0xB7,
+	  0x00, 0x00, 0x00, 0x00,
+	  },
+	 /* reg_SRA0_SRAF */
+	 {
+	  0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+	  0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+	  },
+	 /* reg_GR00_GR08 */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+	  0xFF,
+	  },
+	 /* reg_AR00_AR14 */
+	 {
+	  0x00, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	  0x10, 0x00, 0x12, 0x00, 0x04,
+	  },
+	 /* reg_CR00_CR18 */
+	 {
+	  0x3B, 0x31, 0x31, 0x00, 0x3A, 0x00, 0x06, 0x11,
+	  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0xF1, 0x85, 0xE9, 0x32, 0x40, 0xE9, 0x00, 0xEB,
+	  0xFF,
+	  },
+	 /* reg_CR30_CR4D */
+	 {
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x10,
+	  0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00,
+	  0x3B, 0x31, 0x00, 0x3A, 0x00, 0x06, 0xEA, 0x00,
+	  0xF2, 0x05, 0x01, 0x00, 0x31, 0xE9,
+	  },
+	 /* reg_CR90_CRA7 */
+	 {
+	  0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+	  0xDB, 0x2A, 0xDF, 0x33, 0xFF, 0xFF, 0x1B, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  },
+	 },
+};
+
+#endif				/* __SMI_REGS_H__ */
Index: linux-2.6.10/arch/mips/vr5701/common/nec_vrxxxx.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/nec_vrxxxx.c
@@ -0,0 +1,119 @@
+/*
+ * arch/mips/vr5701/common/nec_vrxxxx.c
+ *
+ * A code for low-level routines on NEC Electronics Corporation VR5701 SolutionGearII 
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/tcube.h>
+
+u32
+ddb_calc_pdar(u32 phys, u32 size, int width, int on_memory_bus, int pci_visible)
+{
+	u32 maskbits;
+	u32 widthbits;
+
+	switch (size) {
+	case 0x80000000:	/* 2 GB */
+		maskbits = 5;
+		break;
+	case 0x40000000:	/* 1 GB */
+		maskbits = 6;
+		break;
+	case 0x20000000:	/* 512 MB */
+		maskbits = 7;
+		break;
+	case 0x10000000:	/* 256 MB */
+		maskbits = 8;
+		break;
+	case 0x08000000:	/* 128 MB */
+		maskbits = 9;
+		break;
+	case 0x04000000:	/* 64 MB */
+		maskbits = 10;
+		break;
+	case 0x02000000:	/* 32 MB */
+		maskbits = 11;
+		break;
+	case 0x01000000:	/* 16 MB */
+		maskbits = 12;
+		break;
+	case 0x00800000:	/* 8 MB */
+		maskbits = 13;
+		break;
+	case 0x00400000:	/* 4 MB */
+		maskbits = 14;
+		break;
+	case 0x00200000:	/* 2 MB */
+		maskbits = 15;
+		break;
+	case 0:		/* OFF */
+		maskbits = 0;
+		break;
+	default:
+		panic("VR5701_set_pdar: unsupported size %p", (void *)size);
+	}
+	switch (width) {
+	case 8:
+		widthbits = 0;
+		break;
+	case 16:
+		widthbits = 1;
+		break;
+	case 32:
+		widthbits = 2;
+		break;
+	case 64:
+		widthbits = 3;
+		break;
+	default:
+		panic("VR5701_set_pdar: unsupported width %d", width);
+	}
+
+	return maskbits | (on_memory_bus ? 0x10 : 0) |
+	    (pci_visible ? 0x20 : 0) | (widthbits << 6) | (phys & 0xffe00000);
+}
+
+void
+ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+	     int on_memory_bus, int pci_visible)
+{
+	u32 temp = ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible);
+	ddb_out32(pdar, temp);
+	ddb_out32(pdar + 4, 0);
+	ddb_in32(pdar);
+	ddb_in32(pdar + 4);
+}
+
+/*
+ * routines that mess with PCIINITx registers
+ */
+
+void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options)
+{
+	switch (type) {
+	case DDB_PCICMD_IACK:	/* PCI Interrupt Acknowledge */
+	case DDB_PCICMD_IO:	/* PCI I/O Space */
+	case DDB_PCICMD_MEM:	/* PCI Memory Space */
+	case DDB_PCICMD_CFG:	/* PCI Configuration Space */
+		break;
+	default:
+		panic("VR5701_set_pmr: invalid type %d", type);
+	}
+	ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options);
+	ddb_out32(pmr + 4, 0);
+}
+
+void ddb_set_bar(u32 bar, u32 phys, int prefetchable)
+{
+	ddb_out32(bar, (phys & 0xffe00000) | (!!prefetchable << 3));
+	ddb_out32(bar + 4, 0);
+}
Index: linux-2.6.10/sound/oss/nec_vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/oss/nec_vr5701_sg2.c
@@ -0,0 +1,1368 @@
+/*
+ * sound/oss/nec_vr5701_sg2.c
+ *
+ * A sound driver for NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec. 
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include "nec_vr5701_sg2.h"
+
+static LIST_HEAD(devs);
+
+static u16 rdcodec(struct ac97_codec *codec, u8 addr)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)codec->private_data;
+	unsigned long flags;
+	u32 result;
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	/* wait until we can access codec registers */
+	while (inl(s->io + vr5701_CODEC_WR) & 0x80000000) ;
+
+	/* write the address and "read" command to codec */
+	addr = addr & 0x7f;
+	outl((addr << 16) | vr5701_CODEC_WR_RWC, s->io + vr5701_CODEC_WR);
+
+	/* get the return result */
+	udelay(100);		/* workaround hardware bug */
+	while ((result = inl(s->io + vr5701_CODEC_RD)) &
+	       (vr5701_CODEC_RD_RRDYA | vr5701_CODEC_RD_RRDYD)) {
+		/* we get either addr or data, or both */
+		if (result & vr5701_CODEC_RD_RRDYA) {
+			ASSERT(addr == ((result >> 16) & 0x7f));
+		}
+		if (result & vr5701_CODEC_RD_RRDYD) {
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	return result & 0xffff;
+}
+
+static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)codec->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	/* wait until we can access codec registers */
+	while (inl(s->io + vr5701_CODEC_WR) & 0x80000000) ;
+
+	/* write the address and value to codec */
+	outl((addr << 16) | data, s->io + vr5701_CODEC_WR);
+
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void waitcodec(struct ac97_codec *codec)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)codec->private_data;
+
+	/* wait until we can access codec registers */
+	while (inl(s->io + vr5701_CODEC_WR) & 0x80000000) ;
+}
+
+static void vr5701_ac97_delay(int msec)
+{
+	unsigned long tmo;
+	signed long tmo2;
+
+	if (in_interrupt())
+		return;
+
+	tmo = jiffies + (msec * HZ) / 1000;
+	for (;;) {
+		tmo2 = tmo - jiffies;
+		if (tmo2 <= 0)
+			break;
+		schedule_timeout(tmo2);
+	}
+}
+
+static void set_adc_rate(struct vr5701_ac97_state *s, unsigned rate)
+{
+	wrcodec(s->codec, AC97_PCM_LR_ADC_RATE, rate);
+	s->adcRate = rate;
+}
+
+static void set_dac_rate(struct vr5701_ac97_state *s, unsigned rate)
+{
+	if (s->extended_status & AC97_EXTSTAT_VRA) {
+		wrcodec(s->codec, AC97_PCM_FRONT_DAC_RATE, rate);
+		s->dacRate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
+	}
+}
+
+static int start_dac(struct vr5701_ac97_state *s)
+{
+	struct dmabuf *db = &s->dma_dac;
+	unsigned long flags;
+	u32 dmaLength;
+	u32 temp;
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	if (!db->stopped) {
+		spin_unlock_irqrestore(&s->lock, flags);
+		return -1;
+	}
+
+	/* we should have some data to do the DMA trasnfer */
+	if(db->count < db->fragSize){
+		spin_unlock_irqrestore(&s->lock, flags);
+		return -1;
+	}
+
+	/* clear pending fales interrupts */
+	outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+	     s->io + vr5701_INT_CLR);
+
+	/* enable interrupts */
+	temp = inl(s->io + vr5701_INT_MASK);
+	temp |= vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+	outl(temp, s->io + vr5701_INT_MASK);
+
+	/* setup dma base addr */
+	outl(db->lbufDma + db->nextOut, s->io + vr5701_DAC1_BADDR);
+	if (s->dacChannels == 1) {
+		outl(db->lbufDma + db->nextOut, s->io + vr5701_DAC2_BADDR);
+	} else {
+		outl(db->rbufDma + db->nextOut, s->io + vr5701_DAC2_BADDR);
+	}
+
+	/* set dma length, in the unit of 0x10 bytes */
+	dmaLength = db->fragSize >> 4;
+	outl(dmaLength, s->io + vr5701_DAC1L);
+	outl(dmaLength, s->io + vr5701_DAC2L);
+
+	/* activate dma */
+	outl(vr5701_DMA_ACTIVATION, s->io + vr5701_DAC1_CTRL);
+	outl(vr5701_DMA_ACTIVATION, s->io + vr5701_DAC2_CTRL);
+
+	/* enable dac slots - we should hear the music now! */
+	temp = inl(s->io + vr5701_CTRL);
+	temp |= (vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+	outl(temp, s->io + vr5701_CTRL);
+
+	/* it is time to setup next dma transfer */
+	ASSERT(inl(s->io + vr5701_DAC1_CTRL) & vr5701_DMA_WIP);
+	ASSERT(inl(s->io + vr5701_DAC2_CTRL) & vr5701_DMA_WIP);
+
+	temp = db->nextOut + db->fragSize;
+	if (temp >= db->fragTotalSize) {
+		ASSERT(temp == db->fragTotalSize);
+		temp = 0;
+	}
+
+	outl(db->lbufDma + temp, s->io + vr5701_DAC1_BADDR);
+	if (s->dacChannels == 1) {
+		outl(db->lbufDma + temp, s->io + vr5701_DAC2_BADDR);
+	} else {
+		outl(db->rbufDma + temp, s->io + vr5701_DAC2_BADDR);
+	}
+
+	db->stopped = 0;
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+	outTicket = *(u16 *) (db->lbuf + db->nextOut);
+	if (db->count > db->fragSize) {
+		ASSERT((u16) (outTicket + 1) == *(u16 *) (db->lbuf + temp));
+	}
+#endif
+	spin_unlock_irqrestore(&s->lock, flags);
+	return 0;
+}
+
+static void start_adc(struct vr5701_ac97_state *s)
+{
+	struct dmabuf *db = &s->dma_adc;
+	unsigned long flags;
+	u32 dmaLength;
+	u32 temp;
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	if (!db->stopped) {
+		spin_unlock_irqrestore(&s->lock, flags);
+		return;
+	}
+
+	/* we should at least have some free space in the buffer */
+	ASSERT(db->count < db->fragTotalSize - db->fragSize * 2);
+
+	/* clear pending ones */
+	outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+	     s->io + vr5701_INT_CLR);
+
+	/* enable interrupts */
+	temp = inl(s->io + vr5701_INT_MASK);
+	temp |= vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+	outl(temp, s->io + vr5701_INT_MASK);
+
+	/* setup dma base addr */
+	outl(db->lbufDma + db->nextIn, s->io + vr5701_ADC1_BADDR);
+	outl(db->rbufDma + db->nextIn, s->io + vr5701_ADC2_BADDR);
+
+	/* setup dma length */
+	dmaLength = db->fragSize >> 4;
+	outl(dmaLength, s->io + vr5701_ADC1L);
+	outl(dmaLength, s->io + vr5701_ADC2L);
+
+	/* activate dma */
+	outl(vr5701_DMA_ACTIVATION, s->io + vr5701_ADC1_CTRL);
+	outl(vr5701_DMA_ACTIVATION, s->io + vr5701_ADC2_CTRL);
+
+	/* enable adc slots */
+	temp = inl(s->io + vr5701_CTRL);
+	temp |= (vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+	outl(temp, s->io + vr5701_CTRL);
+
+	/* it is time to setup next dma transfer */
+	temp = db->nextIn + db->fragSize;
+	if (temp >= db->fragTotalSize) {
+		ASSERT(temp == db->fragTotalSize);
+		temp = 0;
+	}
+	outl(db->lbufDma + temp, s->io + vr5701_ADC1_BADDR);
+	outl(db->rbufDma + temp, s->io + vr5701_ADC2_BADDR);
+
+	db->stopped = 0;
+
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+/* return the total bytes that is copied */
+static inline int
+copy_dac_from_user(struct vr5701_ac97_state *s,
+		   const char *buffer, size_t count, int avail)
+{
+	struct dmabuf *db = &s->dma_dac;
+	int copyCount = 0;
+	int copyFragCount = 0;
+	int totalCopyCount = 0;
+	int totalCopyFragCount = 0;
+	unsigned long flags;
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+	int i;
+#endif
+
+	/* adjust count to signel channel byte count */
+	count >>= s->dacChannels - 1;
+
+	/* we may have to "copy" twice as ring buffer wraps around */
+	for (; (avail > 0) && (count > 0);) {
+		/* determine max possible copy count for single channel */
+		copyCount = count;
+		if (copyCount > avail) {
+			copyCount = avail;
+		}
+		if (copyCount + db->nextIn > db->fragTotalSize) {
+			copyCount = db->fragTotalSize - db->nextIn;
+			ASSERT(copyCount > 0);
+		}
+
+		copyFragCount = copyCount;
+		ASSERT(copyFragCount >= copyCount);
+
+		/* we copy differently based on the number channels */
+		if (s->dacChannels == 1) {
+			if (copy_from_user(db->lbuf + db->nextIn,
+					   buffer, copyCount))
+				return -1;
+			/* fill gaps with 0 */
+			memset(db->lbuf + db->nextIn + copyCount,
+			       0, copyFragCount - copyCount);
+		} else {
+			/* we have demux the stream into two separate ones */
+			if (copy_two_channel_dac_from_user
+			    (s, buffer, copyCount))
+				return -1;
+			/* fill gaps with 0 */
+			memset(db->lbuf + db->nextIn + copyCount,
+			       0, copyFragCount - copyCount);
+			memset(db->rbuf + db->nextIn + copyCount,
+			       0, copyFragCount - copyCount);
+		}
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+		for (i = 0; i < copyFragCount; i += db->fragSize) {
+			*(u16 *) (db->lbuf + db->nextIn + i) = inTicket++;
+		}
+#endif
+
+		count -= copyCount;
+		totalCopyCount += copyCount;
+		avail -= copyFragCount;
+		totalCopyFragCount += copyFragCount;
+
+		buffer += copyCount << (s->dacChannels - 1);
+
+		db->nextIn += copyFragCount;
+		if (db->nextIn >= db->fragTotalSize) {
+			ASSERT(db->nextIn == db->fragTotalSize);
+			db->nextIn = 0;
+		}
+
+		ASSERT((count == 0) || (copyCount == copyFragCount));
+	}
+
+	spin_lock_irqsave(&s->lock, flags);
+	db->count += totalCopyFragCount;
+	if (db->stopped) 
+		if(start_dac(s)){
+			spin_unlock_irqrestore(&s->lock, flags);
+			return -1;
+	}
+
+	/* nextIn should not be equal to nextOut unless we are full */
+	if(!(((db->count == db->fragTotalSize) &&
+		(db->nextIn == db->nextOut)) ||
+	       ((db->count < db->fragTotalSize) &&
+		(db->nextIn != db->nextOut)))){
+			spin_unlock_irqrestore(&s->lock, flags);
+			return -1;
+			}
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	return totalCopyCount << (s->dacChannels - 1);
+
+}
+
+static int prog_dmabuf(struct vr5701_ac97_state *s,
+		       struct dmabuf *db, unsigned rate)
+{
+	int order;
+	unsigned bufsize;
+
+	if (!db->lbuf) {
+		ASSERT(!db->rbuf);
+
+		db->ready = 0;
+		for (order = DMABUF_DEFAULTORDER;
+		     order >= DMABUF_MINORDER; order--) {
+			db->lbuf = pci_alloc_consistent(s->dev,
+							PAGE_SIZE << order,
+							&db->lbufDma);
+			db->rbuf = pci_alloc_consistent(s->dev,
+							PAGE_SIZE << order,
+							&db->rbufDma);
+			if (db->lbuf && db->rbuf)
+				break;
+			if (db->lbuf) {
+				ASSERT(!db->rbuf);
+				pci_free_consistent(s->dev,
+						    PAGE_SIZE << order,
+						    db->lbuf, db->lbufDma);
+			}
+		}
+		if (!db->lbuf) {
+			ASSERT(!db->rbuf);
+			return -ENOMEM;
+		}
+
+		db->bufOrder = order;
+	}
+
+	db->count = 0;
+	db->nextIn = db->nextOut = 0;
+
+	bufsize = PAGE_SIZE << db->bufOrder;
+	db->fragShift = ld2(rate * 2 / 100);
+	if (db->fragShift < 4)
+		db->fragShift = 4;
+
+	db->numFrag = bufsize >> db->fragShift;
+	while (db->numFrag < 4 && db->fragShift > 4) {
+		db->fragShift--;
+		db->numFrag = bufsize >> db->fragShift;
+	}
+	db->fragSize = 1 << db->fragShift;
+	db->fragTotalSize = db->numFrag << db->fragShift;
+	memset(db->lbuf, 0, db->fragTotalSize);
+	memset(db->rbuf, 0, db->fragTotalSize);
+
+	db->ready = 1;
+
+	return 0;
+}
+
+static irqreturn_t vr5701_ac97_interrupt(int irq, void *dev_id,
+					 struct pt_regs *regs)
+{
+	struct vr5701_ac97_state *s = (struct vr5701_ac97_state *)dev_id;
+	u32 irqStatus;
+	u32 adcInterrupts, dacInterrupts;
+
+	spin_lock(&s->lock);
+
+	/* get irqStatus and clear the detected ones */
+	irqStatus = inl(s->io + vr5701_INT_STATUS);
+	outl(irqStatus, s->io + vr5701_INT_CLR);
+
+	/* let us see what we get */
+	dacInterrupts = vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+	adcInterrupts = vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+	if (irqStatus & dacInterrupts) {
+		/* we should get both interrupts, but just in case ...  */
+		if (irqStatus & vr5701_INT_MASK_DAC1END) {
+			vr5701_ac97_dac_interrupt(s);
+		}
+		if ((irqStatus & dacInterrupts) != dacInterrupts) {
+			printk(KERN_WARNING
+			       "vr5701_ac97 : dac interrupts not in sync!!!\n");
+			stop_dac(s);
+			start_dac(s);
+		}
+	} else if (irqStatus & adcInterrupts) {
+		/* we should get both interrupts, but just in case ...  */
+		if (irqStatus & vr5701_INT_MASK_ADC1END) {
+			vr5701_ac97_adc_interrupt(s);
+		}
+		if ((irqStatus & adcInterrupts) != adcInterrupts) {
+			printk(KERN_WARNING
+			       "vr5701_ac97 : adc interrupts not in sync!!!\n");
+			stop_adc(s);
+			start_adc(s);
+		}
+	}
+
+	spin_unlock(&s->lock);
+	return IRQ_HANDLED;
+}
+
+static int vr5701_ac97_open_mixdev(struct inode *inode, struct file *file)
+{
+	int minor = iminor(inode);
+	struct list_head *list;
+	struct vr5701_ac97_state *s;
+
+	for (list = devs.next;; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct vr5701_ac97_state, devs);
+		if (s->codec->dev_mixer == minor)
+			break;
+	}
+	file->private_data = s;
+	return nonseekable_open(inode, file);
+}
+
+static int vr5701_ac97_release_mixdev(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
+			unsigned long arg)
+{
+	return codec->mixer_ioctl(codec, cmd, arg);
+}
+
+static int vr5701_ac97_ioctl_mixdev(struct inode *inode, struct file *file,
+				    unsigned int cmd, unsigned long arg)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)file->private_data;
+	struct ac97_codec *codec = s->codec;
+
+	return mixdev_ioctl(codec, cmd, arg);
+}
+
+static struct file_operations vr5701_ac97_mixer_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.ioctl = vr5701_ac97_ioctl_mixdev,
+	.open = vr5701_ac97_open_mixdev,
+	.release = vr5701_ac97_release_mixdev,
+};
+
+static int drain_dac(struct vr5701_ac97_state *s, int nonblock)
+{
+	unsigned long flags;
+	int count, tmo;
+
+	if (!s->dma_dac.ready)
+		return 0;
+
+	for (;;) {
+		spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (count <= 0)
+			break;
+		if (signal_pending(current))
+			break;
+		if (nonblock)
+			return -EBUSY;
+		tmo = 1000 * count / s->dacRate / 2;
+		vr5701_ac97_delay(tmo);
+	}
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
+}
+
+static ssize_t
+vr5701_ac97_read(struct file *file, char *buffer, size_t count, loff_t * ppos)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)file->private_data;
+	struct dmabuf *db = &s->dma_adc;
+	ssize_t ret = 0;
+	unsigned long flags;
+	int copyCount;
+	size_t avail;
+
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return -EFAULT;
+
+	ASSERT(db->ready);
+
+	while (count > 0) {
+		do {
+			spin_lock_irqsave(&s->lock, flags);
+			if (db->stopped)
+				start_adc(s);
+			avail = db->count;
+			spin_unlock_irqrestore(&s->lock, flags);
+			if (avail <= 0) {
+				if (file->f_flags & O_NONBLOCK) {
+					if (!ret)
+						ret = -EAGAIN;
+					return ret;
+				}
+				interruptible_sleep_on(&db->wait);
+				if (signal_pending(current)) {
+					if (!ret)
+						ret = -ERESTARTSYS;
+					return ret;
+				}
+			}
+		} while (avail <= 0);
+
+		ASSERT((avail % db->fragSize) == 0);
+		copyCount = copy_adc_to_user(s, buffer, count, avail);
+		if (copyCount <= 0) {
+			if (!ret)
+				ret = -EFAULT;
+			return ret;
+		}
+
+		count -= copyCount;
+		buffer += copyCount;
+		ret += copyCount;
+	}
+
+	return ret;
+}
+
+static ssize_t vr5701_ac97_write(struct file *file, const char *buffer,
+				 size_t count, loff_t * ppos)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)file->private_data;
+	struct dmabuf *db = &s->dma_dac;
+	ssize_t ret;
+	unsigned long flags;
+	int copyCount, avail;
+
+	if (!access_ok(VERIFY_READ, buffer, count))
+		return -EFAULT;
+	ret = 0;
+
+	while (count > 0) {
+		do {
+			spin_lock_irqsave(&s->lock, flags);
+			avail = db->fragTotalSize - db->count;
+			spin_unlock_irqrestore(&s->lock, flags);
+			if (avail <= 0) {
+				if (file->f_flags & O_NONBLOCK) {
+					if (!ret)
+						ret = -EAGAIN;
+					return ret;
+				}
+				interruptible_sleep_on(&db->wait);
+				if (signal_pending(current)) {
+					if (!ret)
+						ret = -ERESTARTSYS;
+					return ret;
+				}
+			}
+		} while (avail <= 0);
+
+		copyCount = copy_dac_from_user(s, buffer, count, avail);
+		if (copyCount < 0) {
+			if (!ret)
+				ret = -EFAULT;
+			stop_dac(s);
+			synchronize_irq(s->irq);
+			s->dma_dac.count = 0;
+			s->dma_dac.nextIn = s->dma_dac.nextOut = 0;
+			return ret;
+		}
+
+		count -= copyCount;
+		buffer += copyCount;
+		ret += copyCount;
+	}
+
+	return ret;
+}
+
+/* No kernel lock - we have our own spinlock */
+static unsigned int vr5701_ac97_poll(struct file *file,
+				     struct poll_table_struct *wait)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
+	if (file->f_mode & FMODE_WRITE)
+		poll_wait(file, &s->dma_dac.wait, wait);
+	if (file->f_mode & FMODE_READ)
+		poll_wait(file, &s->dma_adc.wait, wait);
+	spin_lock_irqsave(&s->lock, flags);
+	if (file->f_mode & FMODE_READ) {
+		if (s->dma_adc.count >= (signed)s->dma_adc.fragSize)
+			mask |= POLLIN | POLLRDNORM;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		if ((signed)s->dma_dac.fragTotalSize >=
+		    s->dma_dac.count + (signed)s->dma_dac.fragSize)
+			mask |= POLLOUT | POLLWRNORM;
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	return mask;
+}
+
+#ifdef vr5701_AC97_DEBUG
+static struct ioctl_str_t {
+	unsigned int cmd;
+	const char *str;
+} ioctl_str[] = {
+	{
+	SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET"}, {
+	SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"}, {
+	SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED"}, {
+	SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO"}, {
+	SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"}, {
+	SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT"}, {
+	SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE"}, {
+	SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS"}, {
+	SOUND_PCM_WRITE_CHANNELS, "SOUND_PCM_WRITE_CHANNELS"}, {
+	SOUND_PCM_WRITE_FILTER, "SOUND_PCM_WRITE_FILTER"}, {
+	SNDCTL_DSP_POST, "SNDCTL_DSP_POST"}, {
+	SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"}, {
+	SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT"}, {
+	SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"}, {
+	SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"}, {
+	SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"}, {
+	SNDCTL_DSP_NONBLOCK, "SNDCTL_DSP_NONBLOCK"}, {
+	SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"}, {
+	SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"}, {
+	SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER"}, {
+	SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"}, {
+	SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"}, {
+	SNDCTL_DSP_MAPINBUF, "SNDCTL_DSP_MAPINBUF"}, {
+	SNDCTL_DSP_MAPOUTBUF, "SNDCTL_DSP_MAPOUTBUF"}, {
+	SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO"}, {
+	SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"}, {
+	SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"}, {
+	SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"}, {
+	SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"}, {
+	OSS_GETVERSION, "OSS_GETVERSION"}, {
+	SOUND_PCM_READ_RATE, "SOUND_PCM_READ_RATE"}, {
+	SOUND_PCM_READ_CHANNELS, "SOUND_PCM_READ_CHANNELS"}, {
+	SOUND_PCM_READ_BITS, "SOUND_PCM_READ_BITS"}, {
+	SOUND_PCM_READ_FILTER, "SOUND_PCM_READ_FILTER"}
+};
+#endif
+
+static int vr5701_ac97_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)file->private_data;
+	unsigned long flags;
+	audio_buf_info abinfo;
+	int count;
+	int val, ret;
+
+#ifdef vr5701_AC97_DEBUG
+	for (count = 0; count < sizeof(ioctl_str) / sizeof(ioctl_str[0]);
+	     count++) {
+		if (ioctl_str[count].cmd == cmd)
+			break;
+	}
+	if (count < sizeof(ioctl_str) / sizeof(ioctl_str[0]))
+		printk(KERN_INFO PFX "ioctl %s\n", ioctl_str[count].str);
+	else
+		printk(KERN_INFO PFX "ioctl unknown, 0x%x\n", cmd);
+#endif
+
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	case SNDCTL_DSP_SYNC:
+		if (file->f_mode & FMODE_WRITE)
+			return drain_dac(s, file->f_flags & O_NONBLOCK);
+		return 0;
+
+	case SNDCTL_DSP_SETDUPLEX:
+		return 0;
+
+	case SNDCTL_DSP_GETCAPS:
+		return put_user(DSP_CAP_DUPLEX, (int *)arg);
+
+	case SNDCTL_DSP_RESET:
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			synchronize_irq(s->irq);
+			s->dma_dac.count = 0;
+			s->dma_dac.nextIn = s->dma_dac.nextOut = 0;
+		}
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			synchronize_irq(s->irq);
+			s->dma_adc.count = 0;
+			s->dma_adc.nextIn = s->dma_adc.nextOut = 0;
+		}
+		return 0;
+
+	case SNDCTL_DSP_SPEED:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val >= 0) {
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				set_adc_rate(s, val);
+				if ((ret = prog_dmabuf_adc(s)))
+					return ret;
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				set_dac_rate(s, val);
+				if ((ret = prog_dmabuf_dac(s)))
+					return ret;
+			}
+		}
+		return put_user((file->f_mode & FMODE_READ) ?
+				s->adcRate : s->dacRate, (int *)arg);
+
+	case SNDCTL_DSP_STEREO:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			if (val)
+				s->adcChannels = 2;
+			else
+				s->adcChannels = 1;
+			if ((ret = prog_dmabuf_adc(s)))
+				return ret;
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			if (val)
+				s->dacChannels = 2;
+			else
+				s->dacChannels = 1;
+			if ((ret = prog_dmabuf_dac(s)))
+				return ret;
+		}
+		return 0;
+
+	case SNDCTL_DSP_CHANNELS:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != 0) {
+			if ((val != 1) && (val != 2))
+				val = 2;
+
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dacChannels = val;
+				if ((ret = prog_dmabuf_adc(s)))
+					return ret;
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dacChannels = val;
+				if ((ret = prog_dmabuf_dac(s)))
+					return ret;
+			}
+		}
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_GETFMTS:	/* Returns a mask */
+		return put_user(AFMT_S16_LE, (int *)arg);
+
+	case SNDCTL_DSP_SETFMT:	/* Selects ONE fmt */
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != AFMT_QUERY) {
+			if (val != AFMT_S16_LE)
+				return -EINVAL;
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				if ((ret = prog_dmabuf_adc(s)))
+					return ret;
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				if ((ret = prog_dmabuf_dac(s)))
+					return ret;
+			}
+		} else {
+			val = AFMT_S16_LE;
+		}
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_POST:
+		return 0;
+
+	case SNDCTL_DSP_GETTRIGGER:
+	case SNDCTL_DSP_SETTRIGGER:
+		/* NO trigger */
+		return -EINVAL;
+
+	case SNDCTL_DSP_GETOSPACE:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		abinfo.fragsize = s->dma_dac.fragSize << (s->dacChannels - 1);
+		spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		abinfo.bytes = (s->dma_dac.fragTotalSize - count) <<
+		    (s->dacChannels - 1);
+		abinfo.fragstotal = s->dma_dac.numFrag;
+		abinfo.fragments = abinfo.bytes >> s->dma_dac.fragShift >>
+		    (s->dacChannels - 1);
+		return copy_to_user((void *)arg, &abinfo,
+				    sizeof(abinfo)) ? -EFAULT : 0;
+
+	case SNDCTL_DSP_GETISPACE:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		abinfo.fragsize = s->dma_adc.fragSize << (s->adcChannels - 1);
+		spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_adc.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (count < 0)
+			count = 0;
+		abinfo.bytes = count << (s->adcChannels - 1);
+		abinfo.fragstotal = s->dma_adc.numFrag;
+		abinfo.fragments = (abinfo.bytes >> s->dma_adc.fragShift) >>
+		    (s->adcChannels - 1);
+		return copy_to_user((void *)arg, &abinfo,
+				    sizeof(abinfo)) ? -EFAULT : 0;
+
+	case SNDCTL_DSP_NONBLOCK:
+		file->f_flags |= O_NONBLOCK;
+		return 0;
+
+	case SNDCTL_DSP_GETODELAY:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		return put_user(count, (int *)arg);
+
+	case SNDCTL_DSP_GETIPTR:
+	case SNDCTL_DSP_GETOPTR:
+		/* we cannot get DMA ptr */
+		return -EINVAL;
+
+	case SNDCTL_DSP_GETBLKSIZE:
+		if (file->f_mode & FMODE_WRITE)
+			return put_user(s->dma_dac.
+					fragSize << (s->dacChannels - 1),
+					(int *)arg);
+		else
+			return put_user(s->dma_adc.
+					fragSize << (s->adcChannels - 1),
+					(int *)arg);
+
+	case SNDCTL_DSP_SETFRAGMENT:
+		/* we ignore fragment size request */
+		return 0;
+
+	case SNDCTL_DSP_SUBDIVIDE:
+		/* what is this for? [jsun] */
+		return 0;
+
+	case SOUND_PCM_READ_RATE:
+		return put_user((file->f_mode & FMODE_READ) ?
+				s->adcRate : s->dacRate, (int *)arg);
+
+	case SOUND_PCM_READ_CHANNELS:
+		if (file->f_mode & FMODE_READ)
+			return put_user(s->adcChannels, (int *)arg);
+		else
+			return put_user(s->dacChannels ? 2 : 1, (int *)arg);
+
+	case SOUND_PCM_READ_BITS:
+		return put_user(16, (int *)arg);
+
+	case SOUND_PCM_WRITE_FILTER:
+	case SNDCTL_DSP_SETSYNCRO:
+	case SOUND_PCM_READ_FILTER:
+		return -EINVAL;
+	}
+
+	return mixdev_ioctl(s->codec, cmd, arg);
+}
+
+static int vr5701_ac97_open(struct inode *inode, struct file *file)
+{
+	int minor = iminor(inode);
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	struct list_head *list;
+	struct vr5701_ac97_state *s;
+	int ret = 0;
+
+	nonseekable_open(inode, file);
+	for (list = devs.next;; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct vr5701_ac97_state, devs);
+		if (!((s->dev_audio ^ minor) & ~0xf))
+			break;
+	}
+	file->private_data = s;
+
+	/* wait for device to become free */
+	down(&s->open_sem);
+	while (s->open_mode & file->f_mode) {
+
+		if (file->f_flags & O_NONBLOCK) {
+			up(&s->open_sem);
+			return -EBUSY;
+		}
+		add_wait_queue(&s->open_wait, &wait);
+		__set_current_state(TASK_INTERRUPTIBLE);
+		up(&s->open_sem);
+		schedule();
+		remove_wait_queue(&s->open_wait, &wait);
+		set_current_state(TASK_RUNNING);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+		down(&s->open_sem);
+	}
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	if (file->f_mode & FMODE_READ) {
+		/* set default settings */
+		set_adc_rate(s, 48000);
+		s->adcChannels = 2;
+
+		ret = prog_dmabuf_adc(s);
+		if (ret)
+			goto bailout;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		/* set default settings */
+		set_dac_rate(s, 48000);
+		s->dacChannels = 2;
+
+		ret = prog_dmabuf_dac(s);
+		if (ret)
+			goto bailout;
+	}
+
+	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+
+      bailout:
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	up(&s->open_sem);
+	return ret;
+}
+
+static int vr5701_ac97_release(struct inode *inode, struct file *file)
+{
+	struct vr5701_ac97_state *s =
+	    (struct vr5701_ac97_state *)file->private_data;
+
+	lock_kernel();
+	if (file->f_mode & FMODE_WRITE)
+		drain_dac(s, file->f_flags & O_NONBLOCK);
+	down(&s->open_sem);
+	if (file->f_mode & FMODE_WRITE) {
+		stop_dac(s);
+		dealloc_dmabuf(s, &s->dma_dac);
+	}
+	if (file->f_mode & FMODE_READ) {
+		stop_adc(s);
+		dealloc_dmabuf(s, &s->dma_adc);
+	}
+	s->open_mode &= (~file->f_mode) & (FMODE_READ | FMODE_WRITE);
+	up(&s->open_sem);
+	wake_up(&s->open_wait);
+	unlock_kernel();
+	return 0;
+}
+
+static struct file_operations vr5701_ac97_audio_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = vr5701_ac97_read,
+	.write = vr5701_ac97_write,
+	.poll = vr5701_ac97_poll,
+	.ioctl = vr5701_ac97_ioctl,
+	.open = vr5701_ac97_open,
+	.release = vr5701_ac97_release,
+};
+
+/*
+ * for debugging purposes, we'll create a proc device that dumps the
+ * CODEC chipstate
+ */
+
+#ifdef vr5701_AC97_DEBUG
+
+struct {
+	const char *regname;
+	unsigned regaddr;
+} vr5701_ac97_regs[] = {
+	{
+	"vr5701_INT_STATUS", vr5701_INT_STATUS}, {
+	"vr5701_CODEC_WR", vr5701_CODEC_WR}, {
+	"vr5701_CODEC_RD", vr5701_CODEC_RD}, {
+	"vr5701_CTRL", vr5701_CTRL}, {
+	"vr5701_ACLINK_CTRL", vr5701_ACLINK_CTRL}, {
+	"vr5701_INT_MASK", vr5701_INT_MASK}, {
+	"vr5701_DAC1_CTRL", vr5701_DAC1_CTRL}, {
+	"vr5701_DAC1L", vr5701_DAC1L}, {
+	"vr5701_DAC1_BADDR", vr5701_DAC1_BADDR}, {
+	"vr5701_DAC2_CTRL", vr5701_DAC2_CTRL}, {
+	"vr5701_DAC2L", vr5701_DAC2L}, {
+	"vr5701_DAC2_BADDR", vr5701_DAC2_BADDR}, {
+	"vr5701_DAC3_CTRL", vr5701_DAC3_CTRL}, {
+	"vr5701_DAC3L", vr5701_DAC3L}, {
+	"vr5701_DAC3_BADDR", vr5701_DAC3_BADDR}, {
+	"vr5701_ADC1_CTRL", vr5701_ADC1_CTRL}, {
+	"vr5701_ADC1L", vr5701_ADC1L}, {
+	"vr5701_ADC1_BADDR", vr5701_ADC1_BADDR}, {
+	"vr5701_ADC2_CTRL", vr5701_ADC2_CTRL}, {
+	"vr5701_ADC2L", vr5701_ADC2L}, {
+	"vr5701_ADC2_BADDR", vr5701_ADC2_BADDR}, {
+	"vr5701_ADC3_CTRL", vr5701_ADC3_CTRL}, {
+	"vr5701_ADC3L", vr5701_ADC3L}, {
+	"vr5701_ADC3_BADDR", vr5701_ADC3_BADDR}, {
+	NULL, 0x0}
+};
+
+static int proc_vr5701_ac97_dump(char *buf, char **start, off_t fpos,
+				 int length, int *eof, void *data)
+{
+	struct vr5701_ac97_state *s;
+	int cnt, len = 0;
+
+	if (list_empty(&devs))
+		return 0;
+	s = list_entry(devs.next, struct vr5701_ac97_state, devs);
+
+	/* print out header */
+	len += sprintf(buf + len, "\n\t\tvr5701 Audio Debug\n\n");
+
+	len += sprintf(buf + len, "NEC Electronics Corporation VR5701 SolutionGearII Audio Controller registers\n");
+	len += sprintf(buf + len, "---------------------------------\n");
+	for (cnt = 0; vr5701_ac97_regs[cnt].regname != NULL; cnt++) {
+		len += sprintf(buf + len, "%-20s = %08x\n",
+			       vr5701_ac97_regs[cnt].regname,
+			       inl(s->io + vr5701_ac97_regs[cnt].regaddr));
+	}
+
+	/* print out driver state */
+	len += sprintf(buf + len, "NEC Electronics Corporation VR5701 SolutionGearII Audio driver states\n");
+	len += sprintf(buf + len, "---------------------------------\n");
+	len += sprintf(buf + len, "dacChannels  = %d\n", s->dacChannels);
+	len += sprintf(buf + len, "adcChannels  = %d\n", s->adcChannels);
+	len += sprintf(buf + len, "dacRate  = %d\n", s->dacRate);
+	len += sprintf(buf + len, "adcRate  = %d\n", s->adcRate);
+
+	len += sprintf(buf + len, "dma_dac is %s ready\n",
+		       s->dma_dac.ready ? "" : "not");
+	if (s->dma_dac.ready) {
+		len += sprintf(buf + len, "dma_dac is %s stopped.\n",
+			       s->dma_dac.stopped ? "" : "not");
+		len += sprintf(buf + len, "dma_dac.fragSize = %x\n",
+			       s->dma_dac.fragSize);
+		len += sprintf(buf + len, "dma_dac.fragShift = %x\n",
+			       s->dma_dac.fragShift);
+		len += sprintf(buf + len, "dma_dac.numFrag = %x\n",
+			       s->dma_dac.numFrag);
+		len += sprintf(buf + len, "dma_dac.fragTotalSize = %x\n",
+			       s->dma_dac.fragTotalSize);
+		len += sprintf(buf + len, "dma_dac.nextIn = %x\n",
+			       s->dma_dac.nextIn);
+		len += sprintf(buf + len, "dma_dac.nextOut = %x\n",
+			       s->dma_dac.nextOut);
+		len += sprintf(buf + len, "dma_dac.count = %x\n",
+			       s->dma_dac.count);
+	}
+
+	len += sprintf(buf + len, "dma_adc is %s ready\n",
+		       s->dma_adc.ready ? "" : "not");
+	if (s->dma_adc.ready) {
+		len += sprintf(buf + len, "dma_adc is %s stopped.\n",
+			       s->dma_adc.stopped ? "" : "not");
+		len += sprintf(buf + len, "dma_adc.fragSize = %x\n",
+			       s->dma_adc.fragSize);
+		len += sprintf(buf + len, "dma_adc.fragShift = %x\n",
+			       s->dma_adc.fragShift);
+		len += sprintf(buf + len, "dma_adc.numFrag = %x\n",
+			       s->dma_adc.numFrag);
+		len += sprintf(buf + len, "dma_adc.fragTotalSize = %x\n",
+			       s->dma_adc.fragTotalSize);
+		len += sprintf(buf + len, "dma_adc.nextIn = %x\n",
+			       s->dma_adc.nextIn);
+		len += sprintf(buf + len, "dma_adc.nextOut = %x\n",
+			       s->dma_adc.nextOut);
+		len += sprintf(buf + len, "dma_adc.count = %x\n",
+			       s->dma_adc.count);
+	}
+
+	/* print out CODEC state */
+	len += sprintf(buf + len, "\nAC97 CODEC registers\n");
+	len += sprintf(buf + len, "----------------------\n");
+	for (cnt = 0; cnt <= 0x7e; cnt = cnt + 2)
+		len += sprintf(buf + len, "reg %02x = %04x\n",
+			       cnt, rdcodec(s->codec, cnt));
+
+	if (fpos >= len) {
+		*start = buf;
+		*eof = 1;
+		return 0;
+	}
+	*start = buf + fpos;
+	if ((len -= fpos) > length)
+		return length;
+	*eof = 1;
+	return len;
+
+}
+#endif				/* vr5701_AC97_DEBUG */
+
+static unsigned int devindex;
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("NEC Electronics Corporation VR5701 SolutionGearII audio (AC97) Driver");
+MODULE_LICENSE("GPL");
+
+static int __devinit vr5701_ac97_probe(struct pci_dev *pcidev,
+				       const struct pci_device_id *pciid)
+{
+	struct vr5701_ac97_state *s;
+#ifdef vr5701_AC97_DEBUG
+	char proc_str[80];
+#endif
+
+	if (pcidev->irq == 0)
+		return -1;
+
+	if (!(s = kmalloc(sizeof(struct vr5701_ac97_state), GFP_KERNEL))) {
+		printk(KERN_ERR PFX "alloc of device struct failed\n");
+		return -1;
+	}
+	memset(s, 0, sizeof(struct vr5701_ac97_state));
+
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_MUTEX(&s->open_sem);
+	spin_lock_init(&s->lock);
+
+	s->dev = pcidev;
+	s->io = pci_resource_start(pcidev, 0);
+	s->irq = pcidev->irq;
+
+	s->codec = ac97_alloc_codec();
+
+	s->codec->private_data = s;
+	s->codec->id = 0;
+	s->codec->codec_read = rdcodec;
+	s->codec->codec_write = wrcodec;
+	s->codec->codec_wait = waitcodec;
+
+	/* setting some other default values such as
+	 * adcChannels, adcRate is done in open() so that
+	 * no persistent state across file opens.
+	 */
+
+	if (!request_region(s->io, pci_resource_len(pcidev, 0),
+			    vr5701_AC97_MODULE_NAME)) {
+		printk(KERN_ERR PFX "io ports %#lx->%#lx in use\n",
+		       s->io, s->io + pci_resource_len(pcidev, 0) - 1);
+		goto err_region;
+	}
+	if (request_irq(s->irq, vr5701_ac97_interrupt, SA_INTERRUPT,
+			vr5701_AC97_MODULE_NAME, s)) {
+		printk(KERN_ERR PFX "irq %u in use\n", s->irq);
+		goto err_irq;
+	}
+
+	printk(KERN_INFO PFX "IO at %#lx, IRQ %d\n", s->io, s->irq);
+
+	/* register devices */
+	if ((s->dev_audio =
+	     register_sound_dsp(&vr5701_ac97_audio_fops, -1)) < 0)
+		goto err_dev1;
+	if ((s->codec->dev_mixer =
+	     register_sound_mixer(&vr5701_ac97_mixer_fops, -1)) < 0)
+		goto err_dev2;
+
+#ifdef vr5701_AC97_DEBUG
+	/* initialize the debug proc device */
+	s->ps = create_proc_read_entry(vr5701_AC97_MODULE_NAME, 0, NULL,
+				       proc_vr5701_ac97_dump, NULL);
+#endif				/* vr5701_AC97_DEBUG */
+
+	/* enable pci io and bus mastering */
+	if (pci_enable_device(pcidev))
+		goto err_dev3;
+	pci_set_master(pcidev);
+
+	/* cold reset the AC97 */
+	outl(vr5701_ACLINK_CTRL_RST_ON | vr5701_ACLINK_CTRL_RST_TIME,
+	     s->io + vr5701_ACLINK_CTRL);
+	while (inl(s->io + vr5701_ACLINK_CTRL) & vr5701_ACLINK_CTRL_RST_ON) ;
+
+	/* codec init */
+	if (!ac97_probe_codec(s->codec))
+		goto err_dev3;
+
+#ifdef vr5701_AC97_DEBUG
+	sprintf(proc_str, "driver/%s/%d/ac97",
+		vr5701_AC97_MODULE_NAME, s->codec->id);
+	s->ac97_ps = create_proc_read_entry(proc_str, 0, NULL,
+					    ac97_read_proc, s->codec);
+	/* TODO : why this proc file does not show up? */
+#endif
+
+	/* Try to enable variable rate audio mode. */
+	wrcodec(s->codec, AC97_EXTENDED_STATUS,
+		rdcodec(s->codec, AC97_EXTENDED_STATUS) | AC97_EXTSTAT_VRA);
+	/* Did we enable it? */
+	if (rdcodec(s->codec, AC97_EXTENDED_STATUS) & AC97_EXTSTAT_VRA)
+		s->extended_status |= AC97_EXTSTAT_VRA;
+	else {
+		s->dacRate = 48000;
+		printk(KERN_INFO PFX "VRA mode not enabled; rate fixed at %d.",
+		       s->dacRate);
+	}
+
+	/* let us get the default volumne louder */
+	wrcodec(s->codec, 0x2, 0x1010);	/* master volume, middle */
+	wrcodec(s->codec, 0xc, 0x10);	/* phone volume, middle */
+	wrcodec(s->codec, 0x10, 0x8000);	/* line-in 2 line-out disable */
+	wrcodec(s->codec, 0x18, 0x0707);	/* PCM out (line out) middle */
+
+	/* by default we select line in the input */
+	wrcodec(s->codec, 0xe, 0x10);	/* misc volume, middle */
+	wrcodec(s->codec, 0x1a, 0x0000);	/* default line is Line_mic */
+	/*	wrcodec(s->codec, 0x1a, 0x0404); *//* default line is Line_in */
+	wrcodec(s->codec, 0x1c, 0x0f0f);
+	wrcodec(s->codec, 0x1e, 0x07);
+
+	/* enable the master interrupt but disable all others */
+	outl(vr5701_INT_MASK_NMASK, s->io + vr5701_INT_MASK);
+
+	/* store it in the driver field */
+	pci_set_drvdata(pcidev, s);
+	pcidev->dma_mask = 0xffffffff;
+	/* put it into driver list */
+	list_add_tail(&s->devs, &devs);
+	/* increment devindex */
+	if (devindex < NR_DEVICE - 1)
+		devindex++;
+	return 0;
+
+      err_dev3:
+	unregister_sound_mixer(s->codec->dev_mixer);
+      err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+      err_dev1:
+	printk(KERN_ERR PFX "cannot register misc device\n");
+	free_irq(s->irq, s);
+
+      err_irq:
+	release_region(s->io, pci_resource_len(pcidev, 0));
+      err_region:
+	ac97_release_codec(s->codec);
+	kfree(s);
+	return -1;
+}
+
+static void __devexit vr5701_ac97_remove(struct pci_dev *dev)
+{
+	struct vr5701_ac97_state *s = pci_get_drvdata(dev);
+
+	if (!s)
+		return;
+	list_del(&s->devs);
+
+#ifdef vr5701_AC97_DEBUG
+	if (s->ps)
+		remove_proc_entry(vr5701_AC97_MODULE_NAME, NULL);
+#endif				/* vr5701_AC97_DEBUG */
+
+	synchronize_irq();
+	free_irq(s->irq, s);
+	release_region(s->io, pci_resource_len(dev, 0));
+	unregister_sound_dsp(s->dev_audio);
+	unregister_sound_mixer(s->codec->dev_mixer);
+	ac97_release_codec(s->codec);
+	kfree(s);
+	pci_set_drvdata(dev, NULL);
+}
+
+static struct pci_device_id id_table[] = {
+	{PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_VRC5477_AC97,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver vr5701_ac97_driver = {
+	.name = vr5701_AC97_MODULE_NAME,
+	.id_table = id_table,
+	.probe = vr5701_ac97_probe,
+	.remove = __devexit_p(vr5701_ac97_remove)
+};
+
+static int __init init_vr5701_ac97(void)
+{
+	printk(KERN_INFO "NEC Electronics Corporation VR5701 SolutionGearII AC97 driver: time " __TIME__ " " __DATE__
+	       " by Sergey Podstavin\n");
+	return pci_module_init(&vr5701_ac97_driver);
+}
+
+static void __exit cleanup_vr5701_ac97(void)
+{
+	printk(KERN_INFO PFX "unloading\n");
+	pci_unregister_driver(&vr5701_ac97_driver);
+}
+
+module_init(init_vr5701_ac97);
+module_exit(cleanup_vr5701_ac97);
Index: linux-2.6.10/sound/oss/nec_vr5701_sg2.h
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/oss/nec_vr5701_sg2.h
@@ -0,0 +1,531 @@
+/*
+ * sound/oss/nec_vr5701_sg2.h
+ *
+ * A sound driver for NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec.
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/slab.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/bitops.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/ac97_codec.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+#define         vr5701_INT_CLR         0x0
+#define         vr5701_INT_STATUS	0x0
+#define         vr5701_CODEC_WR        0x4
+#define         vr5701_CODEC_RD        0x8
+#define         vr5701_CTRL            0x18
+#define         vr5701_ACLINK_CTRL     0x1c
+#define         vr5701_INT_MASK        0x24
+
+#define		vr5701_DAC1_CTRL	0x30
+#define		vr5701_DAC1L		0x34
+#define		vr5701_DAC1_BADDR	0x38
+#define		vr5701_DAC2_CTRL	0x3c
+#define		vr5701_DAC2L		0x40
+#define		vr5701_DAC2_BADDR	0x44
+#define		vr5701_DAC3_CTRL	0x48
+#define		vr5701_DAC3L		0x4c
+#define		vr5701_DAC3_BADDR	0x50
+
+#define		vr5701_ADC1_CTRL	0x54
+#define		vr5701_ADC1L		0x58
+#define		vr5701_ADC1_BADDR	0x5c
+#define		vr5701_ADC2_CTRL	0x60
+#define		vr5701_ADC2L		0x64
+#define		vr5701_ADC2_BADDR	0x68
+#define		vr5701_ADC3_CTRL	0x6c
+#define		vr5701_ADC3L		0x70
+#define		vr5701_ADC3_BADDR	0x74
+
+#define		vr5701_CODEC_WR_RWC	(1 << 23)
+
+#define		vr5701_CODEC_RD_RRDYA	(1 << 31)
+#define		vr5701_CODEC_RD_RRDYD	(1 << 30)
+
+#define		vr5701_ACLINK_CTRL_RST_ON	(1 << 15)
+#define		vr5701_ACLINK_CTRL_RST_TIME	0x7f
+#define		vr5701_ACLINK_CTRL_SYNC_ON	(1 << 30)
+#define		vr5701_ACLINK_CTRL_CK_STOP_ON	(1 << 31)
+
+#define		vr5701_CTRL_DAC2ENB		(1 << 15)
+#define		vr5701_CTRL_ADC2ENB		(1 << 14)
+#define		vr5701_CTRL_DAC1ENB		(1 << 13)
+#define		vr5701_CTRL_ADC1ENB		(1 << 12)
+
+#define		vr5701_INT_MASK_NMASK		(1 << 31)
+#define		vr5701_INT_MASK_DAC1END	(1 << 5)
+#define		vr5701_INT_MASK_DAC2END	(1 << 4)
+#define		vr5701_INT_MASK_DAC3END	(1 << 3)
+#define		vr5701_INT_MASK_ADC1END	(1 << 2)
+#define		vr5701_INT_MASK_ADC2END	(1 << 1)
+#define		vr5701_INT_MASK_ADC3END	(1 << 0)
+
+#define		vr5701_DMA_ACTIVATION		(1 << 31)
+#define		vr5701_DMA_WIP			(1 << 30)
+
+#define vr5701_AC97_MODULE_NAME "NEC_vr5701_audio"
+#define PFX vr5701_AC97_MODULE_NAME ": "
+#define	WORK_BUF_SIZE	2048
+
+#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
+#define DMABUF_MINORDER 1
+
+/* maximum number of devices; only used for command line params */
+#define NR_DEVICE 5
+/* -------------------debug macros -------------------------------------- */
+#undef vr5701_AC97_DEBUG
+
+#undef vr5701_AC97_VERBOSE_DEBUG
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+#define vr5701_AC97_DEBUG
+#endif
+
+#if defined(vr5701_AC97_DEBUG)
+#define ASSERT(x)  if (!(x)) { \
+	panic("assertion failed at %s:%d: %s\n", __FILE__, __LINE__, #x); }
+#else
+#define	ASSERT(x)
+#endif				/* vr5701_AC97_DEBUG */
+
+static inline unsigned ld2(unsigned int x)
+{
+	unsigned r = 0;
+
+	if (x >= 0x10000) {
+		x >>= 16;
+		r += 16;
+	}
+	if (x >= 0x100) {
+		x >>= 8;
+		r += 8;
+	}
+	if (x >= 0x10) {
+		x >>= 4;
+		r += 4;
+	}
+	if (x >= 4) {
+		x >>= 2;
+		r += 2;
+	}
+	if (x >= 2)
+		r++;
+	return r;
+}
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+static u16 inTicket;		/* check sync between intr & write */
+static u16 outTicket;
+#endif
+
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+static const unsigned sample_shift[] = { 0, 1, 1, 2 };
+
+struct vr5701_ac97_state {
+	/* list of vr5701_ac97 devices */
+	struct list_head devs;
+
+	/* the corresponding pci_dev structure */
+	struct pci_dev *dev;
+
+	/* soundcore stuff */
+	int dev_audio;
+
+	/* hardware resources */
+	unsigned long io;
+	unsigned int irq;
+
+#ifdef vr5701_AC97_DEBUG
+	/* debug /proc entry */
+	struct proc_dir_entry *ps;
+	struct proc_dir_entry *ac97_ps;
+#endif				/* vr5701_AC97_DEBUG */
+
+	struct ac97_codec *codec;
+
+	unsigned dacChannels, adcChannels;
+	unsigned short dacRate, adcRate;
+	unsigned short extended_status;
+
+	spinlock_t lock;
+	struct semaphore open_sem;
+	mode_t open_mode;
+	wait_queue_head_t open_wait;
+
+	struct dmabuf {
+		void *lbuf, *rbuf;
+		dma_addr_t lbufDma, rbufDma;
+		unsigned bufOrder;
+		unsigned numFrag;
+		unsigned fragShift;
+		unsigned fragSize;	/* redundant */
+		unsigned fragTotalSize;	/* = numFrag * fragSize(real)  */
+		unsigned nextIn;
+		unsigned nextOut;
+		int count;
+		unsigned error;	/* over/underrun */
+		wait_queue_head_t wait;
+		/* OSS stuff */
+		unsigned stopped:1;
+		unsigned ready:1;
+	} dma_dac, dma_adc;
+
+	struct {
+		u16 lchannel;
+		u16 rchannel;
+	} workBuf[WORK_BUF_SIZE / 4];
+};
+static inline void stop_dac(struct vr5701_ac97_state *s)
+{
+	struct dmabuf *db = &s->dma_dac;
+	unsigned long flags;
+	u32 temp;
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	if (db->stopped) {
+		spin_unlock_irqrestore(&s->lock, flags);
+		return;
+	}
+
+	/* deactivate the dma */
+	outl(0, s->io + vr5701_DAC1_CTRL);
+	outl(0, s->io + vr5701_DAC2_CTRL);
+
+	/* wait for DAM completely stop */
+	while (inl(s->io + vr5701_DAC1_CTRL) & vr5701_DMA_WIP) ;
+	while (inl(s->io + vr5701_DAC2_CTRL) & vr5701_DMA_WIP) ;
+
+	/* disable dac slots in aclink */
+	temp = inl(s->io + vr5701_CTRL);
+	temp &= ~(vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+	outl(temp, s->io + vr5701_CTRL);
+
+	/* disable interrupts */
+	temp = inl(s->io + vr5701_INT_MASK);
+	temp &= ~(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END);
+	outl(temp, s->io + vr5701_INT_MASK);
+
+	/* clear pending ones */
+	outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+	     s->io + vr5701_INT_CLR);
+
+	db->stopped = 1;
+
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static inline void stop_adc(struct vr5701_ac97_state *s)
+{
+	struct dmabuf *db = &s->dma_adc;
+	unsigned long flags;
+	u32 temp;
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	if (db->stopped) {
+		spin_unlock_irqrestore(&s->lock, flags);
+		return;
+	}
+
+	/* deactivate the dma */
+	outl(0, s->io + vr5701_ADC1_CTRL);
+	outl(0, s->io + vr5701_ADC2_CTRL);
+
+	/* disable adc slots in aclink */
+	temp = inl(s->io + vr5701_CTRL);
+	temp &= ~(vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+	outl(temp, s->io + vr5701_CTRL);
+
+	/* disable interrupts */
+	temp = inl(s->io + vr5701_INT_MASK);
+	temp &= ~(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END);
+	outl(temp, s->io + vr5701_INT_MASK);
+
+	/* clear pending ones */
+	outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+	     s->io + vr5701_INT_CLR);
+
+	db->stopped = 1;
+
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static inline void dealloc_dmabuf(struct vr5701_ac97_state *s,
+				  struct dmabuf *db)
+{
+	if (db->lbuf) {
+		ASSERT(db->rbuf);
+		pci_free_consistent(s->dev, PAGE_SIZE << db->bufOrder,
+				    db->lbuf, db->lbufDma);
+		pci_free_consistent(s->dev, PAGE_SIZE << db->bufOrder,
+				    db->rbuf, db->rbufDma);
+		db->lbuf = db->rbuf = NULL;
+	}
+	db->nextIn = db->nextOut = 0;
+	db->ready = 0;
+}
+
+static inline int prog_dmabuf_adc(struct vr5701_ac97_state *s)
+{
+	stop_adc(s);
+	return prog_dmabuf(s, &s->dma_adc, s->adcRate);
+}
+
+static inline int prog_dmabuf_dac(struct vr5701_ac97_state *s)
+{
+	stop_dac(s);
+	return prog_dmabuf(s, &s->dma_dac, s->dacRate);
+}
+
+static inline void vr5701_ac97_adc_interrupt(struct vr5701_ac97_state *s)
+{
+	struct dmabuf *adc = &s->dma_adc;
+	unsigned temp;
+
+	/* we need two frags avaiable because one is already being used
+	 * and the other will be used when next interrupt happens.
+	 */
+	if (adc->count >= adc->fragTotalSize - adc->fragSize) {
+		stop_adc(s);
+		adc->error++;
+		printk(KERN_INFO PFX "adc overrun\n");
+		return;
+	}
+
+	/* set the base addr for next DMA transfer */
+	temp = adc->nextIn + 2 * adc->fragSize;
+	if (temp >= adc->fragTotalSize) {
+		ASSERT((temp == adc->fragTotalSize) ||
+		       (temp == adc->fragTotalSize + adc->fragSize));
+		temp -= adc->fragTotalSize;
+	}
+	outl(adc->lbufDma + temp, s->io + vr5701_ADC1_BADDR);
+	outl(adc->rbufDma + temp, s->io + vr5701_ADC2_BADDR);
+
+	/* adjust nextIn */
+	adc->nextIn += adc->fragSize;
+	if (adc->nextIn >= adc->fragTotalSize) {
+		ASSERT(adc->nextIn == adc->fragTotalSize);
+		adc->nextIn = 0;
+	}
+
+	/* adjust count */
+	adc->count += adc->fragSize;
+
+	/* wake up anybody listening */
+	if (waitqueue_active(&adc->wait)) {
+		wake_up_interruptible(&adc->wait);
+	}
+}
+
+static inline void vr5701_ac97_dac_interrupt(struct vr5701_ac97_state *s)
+{
+	struct dmabuf *dac = &s->dma_dac;
+	unsigned temp;
+
+	/* let us set for next next DMA transfer */
+	temp = dac->nextOut + dac->fragSize * 2;
+	if (temp >= dac->fragTotalSize) {
+		ASSERT((temp == dac->fragTotalSize) ||
+		       (temp == dac->fragTotalSize + dac->fragSize));
+		temp -= dac->fragTotalSize;
+	}
+	outl(dac->lbufDma + temp, s->io + vr5701_DAC1_BADDR);
+	if (s->dacChannels == 1) {
+		outl(dac->lbufDma + temp, s->io + vr5701_DAC2_BADDR);
+	} else {
+		outl(dac->rbufDma + temp, s->io + vr5701_DAC2_BADDR);
+	}
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+	if (*(u16 *) (dac->lbuf + dac->nextOut) != outTicket) {
+		printk(KERN_ERR "assert fail: - %d vs %d\n",
+		       *(u16 *) (dac->lbuf + dac->nextOut), outTicket);
+		ASSERT(1 == 0);
+	}
+#endif
+
+	/* adjust nextOut pointer */
+	dac->nextOut += dac->fragSize;
+	if (dac->nextOut >= dac->fragTotalSize) {
+		ASSERT(dac->nextOut == dac->fragTotalSize);
+		dac->nextOut = 0;
+	}
+
+	/* adjust count */
+	dac->count -= dac->fragSize;
+	if (dac->count <= 0) {
+		/* buffer under run */
+		dac->count = 0;
+		dac->nextIn = dac->nextOut;
+		stop_dac(s);
+	}
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+	if (dac->count) {
+		outTicket++;
+		ASSERT(*(u16 *) (dac->lbuf + dac->nextOut) == outTicket);
+	}
+#endif
+
+	/* we cannot have both under run and someone is waiting on us */
+	ASSERT(!(waitqueue_active(&dac->wait) && (dac->count <= 0)));
+
+	/* wake up anybody listening */
+	if (waitqueue_active(&dac->wait))
+		wake_up_interruptible(&dac->wait);
+}
+
+static inline int
+copy_two_channel_adc_to_user(struct vr5701_ac97_state *s,
+			     char *buffer, int copyCount)
+{
+	struct dmabuf *db = &s->dma_adc;
+	int bufStart = db->nextOut;
+	for (; copyCount > 0;) {
+		int i;
+		int count = copyCount;
+		if (count > WORK_BUF_SIZE / 2)
+			count = WORK_BUF_SIZE / 2;
+		for (i = 0; i < count / 2; i++) {
+			s->workBuf[i].lchannel =
+			    *(u16 *) (db->lbuf + bufStart + i * 2);
+			s->workBuf[i].rchannel =
+			    *(u16 *) (db->rbuf + bufStart + i * 2);
+		}
+		if (copy_to_user(buffer, s->workBuf, count * 2)) {
+			return -1;
+		}
+
+		copyCount -= count;
+		bufStart += count;
+		ASSERT(bufStart <= db->fragTotalSize);
+		buffer += count * 2;
+	}
+	return 0;
+}
+
+/* return the total bytes that is copied */
+static inline int
+copy_adc_to_user(struct vr5701_ac97_state *s,
+		 char *buffer, size_t count, int avail)
+{
+	struct dmabuf *db = &s->dma_adc;
+	int copyCount = 0;
+	int copyFragCount = 0;
+	int totalCopyCount = 0;
+	int totalCopyFragCount = 0;
+	unsigned long flags;
+
+	/* adjust count to signel channel byte count */
+	count >>= s->adcChannels - 1;
+
+	/* we may have to "copy" twice as ring buffer wraps around */
+	for (; (avail > 0) && (count > 0);) {
+		/* determine max possible copy count for single channel */
+		copyCount = count;
+		if (copyCount > avail) {
+			copyCount = avail;
+		}
+		if (copyCount + db->nextOut > db->fragTotalSize) {
+			copyCount = db->fragTotalSize - db->nextOut;
+			ASSERT((copyCount % db->fragSize) == 0);
+		}
+
+		copyFragCount = (copyCount - 1) >> db->fragShift;
+		copyFragCount = (copyFragCount + 1) << db->fragShift;
+		ASSERT(copyFragCount >= copyCount);
+
+		/* we copy differently based on adc channels */
+		if (s->adcChannels == 1) {
+			if (copy_to_user(buffer,
+					 db->lbuf + db->nextOut, copyCount))
+				return -1;
+		} else {
+			/* *sigh* we have to mix two streams into one  */
+			if (copy_two_channel_adc_to_user(s, buffer, copyCount))
+				return -1;
+		}
+
+		count -= copyCount;
+		totalCopyCount += copyCount;
+		avail -= copyFragCount;
+		totalCopyFragCount += copyFragCount;
+
+		buffer += copyCount << (s->adcChannels - 1);
+
+		db->nextOut += copyFragCount;
+		if (db->nextOut >= db->fragTotalSize) {
+			ASSERT(db->nextOut == db->fragTotalSize);
+			db->nextOut = 0;
+		}
+
+		ASSERT((copyFragCount % db->fragSize) == 0);
+		ASSERT((count == 0) || (copyCount == copyFragCount));
+	}
+
+	spin_lock_irqsave(&s->lock, flags);
+	db->count -= totalCopyFragCount;
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	return totalCopyCount << (s->adcChannels - 1);
+}
+
+static inline int
+copy_two_channel_dac_from_user(struct vr5701_ac97_state *s,
+			       const char *buffer, int copyCount)
+{
+	struct dmabuf *db = &s->dma_dac;
+	int bufStart = db->nextIn;
+
+	ASSERT(db->ready);
+
+	for (; copyCount > 0;) {
+		int i;
+		int count = copyCount;
+		if (count > WORK_BUF_SIZE / 2)
+			count = WORK_BUF_SIZE / 2;
+		if (copy_from_user(s->workBuf, buffer, count * 2)) {
+			return -1;
+		}
+		for (i = 0; i < count / 2; i++) {
+			*(u16 *) (db->lbuf + bufStart + i * 2) =
+			    s->workBuf[i].lchannel;
+			*(u16 *) (db->rbuf + bufStart + i * 2) =
+			    s->workBuf[i].rchannel;
+		}
+
+		copyCount -= count;
+		bufStart += count;
+		ASSERT(bufStart <= db->fragTotalSize);
+		buffer += count * 2;
+	}
+	return 0;
+
+}
Index: linux-2.6.10/sound/oss/Makefile
===================================================================
--- linux-2.6.10.orig/sound/oss/Makefile
+++ linux-2.6.10/sound/oss/Makefile
@@ -67,6 +67,7 @@ endif
 obj-$(CONFIG_SOUND_ES1370)	+= es1370.o
 obj-$(CONFIG_SOUND_ES1371)	+= es1371.o ac97_codec.o
 obj-$(CONFIG_SOUND_VRC5477)	+= nec_vrc5477.o ac97_codec.o
+obj-$(CONFIG_SOUND_VR5701)	+= nec_vr5701_sg2.o ac97_codec.o
 obj-$(CONFIG_SOUND_AU1000)	+= au1000.o ac97_codec.o  
 obj-$(CONFIG_SOUND_AU1550_AC97)	+= au1550_ac97.o ac97_codec.o  
 obj-$(CONFIG_SOUND_ESSSOLO1)	+= esssolo1.o
Index: linux-2.6.10/arch/mips/configs/nec_vr5701_defconfig
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/configs/nec_vr5701_defconfig
@@ -0,0 +1,1250 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10_dev
+# Thu Aug  4 14:29:56 2005
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SEMMNI=128
+CONFIG_SYSVIPC_SEMMSL=250
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_BOOT_FLIGHT_RECORDER is not set
+CONFIG_LOCKLESS=y
+CONFIG_BOOT_FLIGHT_BUFFERS=4
+CONFIG_BOOT_FLIGHT_SIZE=524288
+CONFIG_FLIGHT_PROC_BUFFERS=8
+CONFIG_FLIGHT_PROC_SIZE=8192
+CONFIG_NEWEV=y
+CONFIG_CSTM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+CONFIG_TCUBE=y
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT_DESKTOP=y
+# CONFIG_PREEMPT_RT is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_SOFTIRQS is not set
+# CONFIG_PREEMPT_HARDIRQS is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_SPINLOCK_BKL is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ASM_SEMAPHORES=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+CONFIG_CPU_R5500=y
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_ADVANCED=y
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_LLDSCD is not set
+# CONFIG_CPU_HAS_WB is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_HIGH_RES_RESOLUTION=10000
+CONFIG_CPU_TIMER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CONCAT=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x1C000000
+CONFIG_MTD_PHYSMAP_LEN=0x01a00000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_NEC_VR5701_SG2=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADP94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_USE_POLICY_FWD=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_ADVANCED_ROUTER is not set
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP6_NF_CONNTRACK is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_TSLIBDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_BLOCKER is not set
+CONFIG_GEN_RTC=y
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_SM=y
+# CONFIG_DISPLAY_640x480 is not set
+CONFIG_DISPLAY_1024x768=y
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=y
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_VR5701=y
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+CONFIG_JFS_FS=y
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_CRAMFS_LINEAR is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_YAFFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# MontaVista System tools
+#
+# CONFIG_ILATENCY is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_WAKEUP_TIMING is not set
+# CONFIG_CRITICAL_PREEMPT_TIMING is not set
+# CONFIG_CRITICAL_IRQSOFF_TIMING is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw "
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Fast Real-Time Domain
+#
+
+#
+# Fast Real-Time Domain Advanced Options
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
Index: linux-2.6.10/sound/pci/Makefile
===================================================================
--- linux-2.6.10.orig/sound/pci/Makefile
+++ linux-2.6.10/sound/pci/Makefile
@@ -57,4 +57,5 @@ obj-$(CONFIG_SND) += \
 	rme9652/ \
 	trident/ \
 	ymfpci/ \
+	vr5701/ \
 	vx222/
Index: linux-2.6.10/sound/pci/Kconfig
===================================================================
--- linux-2.6.10.orig/sound/pci/Kconfig
+++ linux-2.6.10/sound/pci/Kconfig
@@ -262,6 +262,16 @@ config SND_TRIDENT
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-trident.
 
+config SND_VR5701
+	tristate "NEC VR5701-SG2 Audio"
+	depends on SND
+	select SND_AC97_CODEC
+	help
+	  Say Y here to include support for NEC VR5701-SG2 Audio.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called nec_vr5701_sg2.
+
 config SND_YMFPCI
 	tristate "Yamaha YMF724/740/744/754"
 	depends on SND
Index: linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
@@ -0,0 +1,795 @@
+/*
+ * sound/pci/vr5701/nec_vr5701_sg2.c
+ *
+ * An ALSA sound driver for 
+ * NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec.
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include "nec_vr5701_sg2.h"
+
+static unsigned short snd_vr5701_ac97_read(ac97_t *ac97,
+                                             unsigned short reg)
+{
+	vr5701_t *chip = ac97->private_data;
+	u32 the_register_value;
+	
+	/* wait until we can access codec registers */
+	while (inl(chip->port + vr5701_CODEC_WR) & 0x80000000) ;
+
+	/* write the address and "read" command to codec */
+	reg = reg & 0x7f;
+	outl((reg << 16) | vr5701_CODEC_WR_RWC, chip->port + vr5701_CODEC_WR);
+
+	/* get the return result */
+	udelay(100);		/* workaround hardware bug */
+	while ((the_register_value = inl(chip->port + vr5701_CODEC_RD)) &
+		(vr5701_CODEC_RD_RRDYA | vr5701_CODEC_RD_RRDYD)) {
+		/* we get either addr or data, or both */
+		if (the_register_value & vr5701_CODEC_RD_RRDYD) {
+			break;
+		}
+	}
+
+	return the_register_value & 0xffff;
+}
+
+static void snd_vr5701_ac97_write(ac97_t *ac97,
+                                   unsigned short reg, unsigned short val)
+{
+	vr5701_t *chip = ac97->private_data;
+
+	/* wait until we can access codec registers */
+	while (inl(chip->port + vr5701_CODEC_WR) & 0x80000000) ;
+
+	/* write the address and value to codec */
+	outl((reg << 16) | val, chip->port + vr5701_CODEC_WR);
+}
+
+static void snd_vr5701_ac97_reset(ac97_t *ac97)
+{
+	vr5701_t *chip = ac97->private_data;
+	outl(vr5701_ACLINK_CTRL_RST_ON | vr5701_ACLINK_CTRL_RST_TIME,
+		chip->port + vr5701_ACLINK_CTRL);
+	while (inl(chip->port + vr5701_ACLINK_CTRL) & vr5701_ACLINK_CTRL_RST_ON) ;
+	return;
+}
+
+static void snd_vr5701_ac97_wait(ac97_t *ac97)
+{
+	vr5701_t *chip = ac97->private_data;
+
+	/* wait until we can access codec registers */
+	while (inl(chip->port + vr5701_CODEC_WR) & 0x80000000) ;
+}
+
+static int snd_vr5701_ac97(vr5701_t *chip)
+{
+	ac97_bus_t *bus;
+	ac97_template_t ac97;
+	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_vr5701_ac97_write,
+		.read = snd_vr5701_ac97_read,
+		.reset = snd_vr5701_ac97_reset,
+		.wait = snd_vr5701_ac97_wait,
+	};
+
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
+		return err;
+	memset(&ac97, 0, sizeof(ac97));
+	ac97.private_data = chip;
+	return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+}
+
+/* open callback */
+static int snd_vr5701_playback_open(snd_pcm_substream_t *substream)
+{
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	chip->substream[PLAYBACK] = substream;
+	substream->runtime->hw = snd_vr5701_playback_hw;
+	chip->next_playback = 0;
+
+	return (snd_pcm_hw_constraint_list(substream->runtime, 0,
+		SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); 
+}
+
+
+/* open callback */
+static int snd_vr5701_capture_open(snd_pcm_substream_t *substream)
+{
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	chip->substream[CAPTURE] = substream;
+	substream->runtime->hw = snd_vr5701_capture_hw;
+	chip->next_capture = 0;
+
+	return (snd_pcm_hw_constraint_list(substream->runtime, 0,
+		SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
+}
+
+/* hw_params callback */
+static int snd_vr5701_pcm_hw_params(snd_pcm_substream_t *substream,
+                               snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream,
+		params_buffer_bytes(hw_params));
+}
+
+/* hw_free callback */
+static int snd_vr5701_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+/* playback prepare callback */
+static int snd_vr5701_pcm_prepare_playback(snd_pcm_substream_t *substream)
+{
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
+	return 0;
+}
+
+/* capture prepare callback */
+static int snd_vr5701_pcm_prepare_capture(snd_pcm_substream_t *substream)
+{
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
+	return 0;
+}
+
+static void vr5701_dma_stop_playback(snd_pcm_substream_t *substream)
+{
+	u32 temp;
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	chip->next_playback = 0;
+
+	/* deactivate the dma */
+	outl(0, chip->port + vr5701_DAC1_CTRL);
+	outl(0, chip->port + vr5701_DAC2_CTRL);
+
+	/* wait for DMA completely stop */
+	while (inl(chip->port + vr5701_DAC1_CTRL) & vr5701_DMA_WIP);
+	while (inl(chip->port + vr5701_DAC2_CTRL) & vr5701_DMA_WIP);
+
+	/* disable dac slots in aclink */
+	temp = inl(chip->port + vr5701_CTRL);
+	temp &= ~(vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+	outl(temp, chip->port + vr5701_CTRL);
+
+	/* disable interrupts */
+	temp = inl(chip->port + vr5701_INT_MASK);
+	temp &= ~(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END);
+	outl(temp, chip->port + vr5701_INT_MASK);
+
+	/* clear pending ones */
+	outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+		chip->port + vr5701_INT_CLR);
+
+}
+
+/* close callback */
+static int snd_vr5701_playback_close(snd_pcm_substream_t *substream)
+{
+	vr5701_dma_stop_playback(substream);
+	return 0;
+}
+
+static void vr5701_dma_stop_capture(snd_pcm_substream_t *substream)
+{
+	u32 temp;
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	chip->next_capture = 0;
+
+	/* deactivate the dma */
+	outl(0, chip->port + vr5701_ADC1_CTRL);
+	outl(0, chip->port + vr5701_ADC2_CTRL);
+
+	/* disable dac slots in aclink */
+	temp = inl(chip->port + vr5701_CTRL);
+	temp &= ~(vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+	outl(temp, chip->port + vr5701_CTRL);
+
+	/* disable interrupts */
+	temp = inl(chip->port + vr5701_INT_MASK);
+	temp &= ~(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END);
+	outl(temp, chip->port + vr5701_INT_MASK);
+
+	/* clear pending ones */
+	outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+		chip->port + vr5701_INT_CLR);
+}
+
+/* close callback */
+static int snd_vr5701_capture_close(snd_pcm_substream_t *substream)
+{
+	vr5701_dma_stop_capture(substream);
+	return 0;
+}
+
+static void vr5701_dma_start_playback(snd_pcm_substream_t *substream)
+{
+	u32 temp;
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	unsigned long period_size;
+
+	/* clear pending fales interrupts */
+	outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+		chip->port + vr5701_INT_CLR);
+
+	/* enable interrupts */
+	temp = inl(chip->port + vr5701_INT_MASK);
+	temp |= vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+	outl(temp, chip->port + vr5701_INT_MASK);
+
+	/* setup dma base addr */
+	if (substream->runtime->channels == 1) {
+		outl(substream->runtime->dma_addr + chip->next_playback, 
+						chip->port + vr5701_DAC1_BADDR);
+		outl(substream->runtime->dma_addr + chip->next_playback, 
+						chip->port + vr5701_DAC2_BADDR);
+	} else {
+		outl(substream->runtime->dma_addr + chip->next_playback, 
+						chip->port + vr5701_DAC1_BADDR);
+		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2 
+				+ chip->next_playback, chip->port + vr5701_DAC2_BADDR);
+	}
+
+	/* set dma length, in the unit of 0x10 bytes */
+	period_size = (frames_to_bytes(substream->runtime, 
+			substream->runtime->period_size)) >> 4;
+	outl(period_size, chip->port + vr5701_DAC1L);
+	outl(period_size, chip->port + vr5701_DAC2L);
+
+	/* activate dma */
+	outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_DAC1_CTRL);
+	outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_DAC2_CTRL);
+
+	/* enable dac slots - we should hear the music now! */
+	temp = inl(chip->port + vr5701_CTRL);
+	temp |= (vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+	outl(temp, chip->port + vr5701_CTRL);
+
+	/* it is time to setup next dma transfer */
+	temp = chip->next_playback + frames_to_bytes(substream->runtime, 
+			substream->runtime->period_size);
+
+	if (substream->runtime->channels == 1) {
+		if (temp >= substream->runtime->dma_bytes) {
+			temp = 0;
+		}
+		outl(substream->runtime->dma_addr + temp, 
+				chip->port + vr5701_DAC1_BADDR);
+		outl(substream->runtime->dma_addr + temp, 
+				chip->port + vr5701_DAC2_BADDR);
+	} else {
+		if (temp >= substream->runtime->dma_bytes/2) {
+			temp = 0;
+		}
+		outl(substream->runtime->dma_addr + temp, 
+				chip->port + vr5701_DAC1_BADDR);
+		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+						+ temp, chip->port + vr5701_DAC2_BADDR);
+	}
+	return ;
+}
+
+static void vr5701_dma_start_capture(snd_pcm_substream_t *substream)
+{
+	u32 temp;
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	unsigned long period_size;
+
+	/* clear pending fales interrupts */
+	outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+		chip->port + vr5701_INT_CLR);
+
+	/* enable interrupts */
+	temp = inl(chip->port + vr5701_INT_MASK);
+	temp |= vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+	outl(temp, chip->port + vr5701_INT_MASK);
+
+	/* setup dma base addr */
+	if (substream->runtime->channels == 1) {
+		outl(substream->runtime->dma_addr + chip->next_capture, 
+					chip->port + vr5701_ADC1_BADDR);
+	} else {
+		outl(substream->runtime->dma_addr+ chip->next_capture, 
+					chip->port + vr5701_ADC1_BADDR);
+		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2 
+				+ chip->next_capture, chip->port + vr5701_ADC2_BADDR);
+	}
+
+	/* set dma length, in the unit of 0x10 bytes */
+	period_size = (frames_to_bytes(substream->runtime, 
+			substream->runtime->period_size))  >> 4;
+	if (substream->runtime->channels == 1) {
+		outl(period_size, chip->port + vr5701_ADC1L);
+	} else {
+		outl(period_size, chip->port + vr5701_ADC1L);
+		outl(period_size, chip->port + vr5701_ADC2L);
+	}
+
+	/* activate dma */
+	if (substream->runtime->channels == 1) {
+		outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_ADC1_CTRL);
+	} else {
+		outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_ADC1_CTRL);
+		outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_ADC2_CTRL);
+	}
+
+	/* enable adc slots */
+	temp = inl(chip->port + vr5701_CTRL);
+	temp |= (vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+	outl(temp, chip->port + vr5701_CTRL);
+
+	/* it is time to setup next dma transfer */
+	temp = chip->next_capture + frames_to_bytes(substream->runtime, 
+			substream->runtime->period_size);
+	if (substream->runtime->channels == 1) {
+		if (temp >= substream->runtime->dma_bytes) {
+			temp = 0;
+		}
+		outl(substream->runtime->dma_addr + temp, 
+				chip->port + vr5701_ADC1_BADDR);
+	} else {
+		if (temp >= substream->runtime->dma_bytes/2) {
+			temp = 0;
+		}
+		outl(substream->runtime->dma_addr + temp, 
+				chip->port + vr5701_ADC1_BADDR);
+		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+						+ temp,	chip->port + vr5701_ADC2_BADDR);
+	}
+	return ;
+}
+
+/* trigger callback */
+static int snd_vr5701_pcm_trigger(snd_pcm_substream_t *substream,
+                                    int cmd)
+{
+	int err = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		if (substream->stream) {
+			vr5701_dma_start_capture(substream);
+		}
+		else {
+			vr5701_dma_start_playback(substream);
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		if (substream->stream)
+			vr5701_dma_stop_capture(substream);
+		else
+			vr5701_dma_stop_playback(substream);
+		break;
+	default:
+		err = -EINVAL;
+		printk(KERN_WARNING
+			"vr5701_ac97 : wrong trigger callback!!!\n");
+		break;
+	}
+	return err;
+}
+
+/* playback pointer callback */
+static snd_pcm_uframes_t
+snd_vr5701_pcm_pointer_playback(snd_pcm_substream_t *substream)
+{
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	return 	 bytes_to_frames(substream->runtime, 
+					chip->next_playback);	
+}
+
+/* capture pointer callback */
+static snd_pcm_uframes_t
+snd_vr5701_pcm_pointer_capture(snd_pcm_substream_t *substream)
+{
+	vr5701_t *chip = snd_pcm_substream_chip(substream);
+	return 	 bytes_to_frames(substream->runtime, 
+					chip->next_capture);	
+}
+/* operators */
+static snd_pcm_ops_t snd_vr5701_playback_ops = {
+	.open =        snd_vr5701_playback_open,
+	.close =       snd_vr5701_playback_close,
+	.ioctl =       snd_pcm_lib_ioctl,
+	.hw_params =   snd_vr5701_pcm_hw_params,
+	.hw_free =     snd_vr5701_pcm_hw_free,
+	.prepare =     snd_vr5701_pcm_prepare_playback,
+	.trigger =     snd_vr5701_pcm_trigger,
+	.pointer =     snd_vr5701_pcm_pointer_playback,
+};
+
+/* operators */
+static snd_pcm_ops_t snd_vr5701_capture_ops = {
+	.open =        snd_vr5701_capture_open,
+	.close =       snd_vr5701_capture_close,
+	.ioctl =       snd_pcm_lib_ioctl,
+	.hw_params =   snd_vr5701_pcm_hw_params,
+	.hw_free =     snd_vr5701_pcm_hw_free,
+	.prepare =     snd_vr5701_pcm_prepare_capture,
+	.trigger =     snd_vr5701_pcm_trigger,
+	.pointer =     snd_vr5701_pcm_pointer_capture,
+};
+
+/* create a pcm device */
+static int __devinit snd_vr5701_new_pcm(vr5701_t *chip)
+{
+	snd_pcm_t *pcm;
+	int err;
+	if ((err = snd_pcm_new(chip->card, vr5701_AC97_MODULE_NAME, 0, 1, 1,
+		&pcm)) < 0) 
+			return err;
+	pcm->private_data = chip;
+	strcpy(pcm->name, vr5701_AC97_MODULE_NAME);
+	chip->pcm = pcm;
+
+	/* set operators */
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+		&snd_vr5701_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+		&snd_vr5701_capture_ops);
+	
+	/* pre-allocation of buffers */
+	/* NOTE: this may fail */
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+		snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
+	return 0;
+}
+          
+/* chip-specific destructor
+ */
+static int snd_vr5701_free(vr5701_t *chip)
+{
+	/* release the irq */
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
+	
+	/* release the i/o ports & memory */
+	pci_release_regions(chip->pci);
+	
+	/* disable the PCI entry */
+	pci_disable_device(chip->pci);
+	
+	/* release the data */
+	kfree(chip);
+	return 0;
+}
+
+/* component-destructor
+ */
+static int snd_vr5701_dev_free(snd_device_t *device)
+{
+	vr5701_t *chip = device->device_data;
+	return snd_vr5701_free(chip);
+}
+static void vr5701_ac97_adc_interrupt(struct snd_vr5701 *chip)
+{
+	unsigned temp;
+
+	/* set the base addr for next DMA transfer */
+	temp = chip->next_capture + 2*(frames_to_bytes(chip->substream[CAPTURE]->runtime, 
+			chip->substream[CAPTURE]->runtime->period_size));
+	if (chip->substream[CAPTURE]->runtime->channels == 1) {
+		if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes) {
+			temp -= chip->substream[CAPTURE]->runtime->dma_bytes;
+		}
+	} else {
+		if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes/2) {
+			temp -= chip->substream[CAPTURE]->runtime->dma_bytes/2;
+		}
+	}
+
+	if (chip->substream[CAPTURE]->runtime->channels == 1) {
+		outl(chip->substream[CAPTURE]->runtime->dma_addr 
+				+ temp, chip->port + vr5701_ADC1_BADDR);
+	} else {
+		outl(chip->substream[CAPTURE]->runtime->dma_addr 
+				+ temp, chip->port + vr5701_ADC1_BADDR);
+		outl(chip->substream[CAPTURE]->runtime->dma_addr 
+		+ chip->substream[CAPTURE]->runtime->dma_bytes/2+ temp, 
+						chip->port + vr5701_ADC2_BADDR);
+	}
+
+	/* adjust next pointer */
+	chip->next_capture += frames_to_bytes(chip->substream[CAPTURE]->runtime, 
+					chip->substream[CAPTURE]->runtime->period_size);
+	if (chip->substream[CAPTURE]->runtime->channels == 1) {
+		if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes){
+			chip->next_capture = 0;
+		}
+	} else {
+		if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes/2){
+			chip->next_capture = 0;
+		}
+	}
+}
+
+static void vr5701_ac97_dac_interrupt(struct snd_vr5701 *chip)
+{
+	unsigned temp;
+
+	/* let us set for next next DMA transfer */
+	temp = chip->next_playback + 2*(frames_to_bytes(chip->substream[PLAYBACK]->runtime, 
+			chip->substream[PLAYBACK]->runtime->period_size));
+	if (chip->substream[PLAYBACK]->runtime->channels == 1) {
+		if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes) {
+			temp -= chip->substream[PLAYBACK]->runtime->dma_bytes;
+		}
+	} else {
+		if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes/2) {
+			temp -= chip->substream[PLAYBACK]->runtime->dma_bytes/2;
+		}
+	}
+
+	if (chip->substream[PLAYBACK]->runtime->channels == 1) {
+		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
+				+ temp, chip->port + vr5701_DAC1_BADDR);
+		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
+				+ temp, chip->port + vr5701_DAC2_BADDR);
+	} else {
+		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
+				+ temp, chip->port + vr5701_DAC1_BADDR);
+		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
+			+ chip->substream[PLAYBACK]->runtime->dma_bytes/2
+				+ temp,	chip->port + vr5701_DAC2_BADDR);
+	}
+
+	/* adjust next pointer */
+	chip->next_playback += frames_to_bytes(chip->substream[PLAYBACK]->runtime, 
+					chip->substream[PLAYBACK]->runtime->period_size);
+	if (chip->substream[PLAYBACK]->runtime->channels == 1) {
+		if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes){
+			chip->next_playback = 0;
+		}
+	} else {
+		if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes/2){
+			chip->next_playback = 0;
+		}
+	}
+}
+static irqreturn_t snd_vr5701_interrupt(int irq, void *dev_id,
+                                          struct pt_regs *regs)
+{
+	vr5701_t *chip = dev_id;
+	u32 irqStatus;
+	u32 adcInterrupts, dacInterrupts;
+
+	/* get irqStatus and clear the detected ones */
+	irqStatus = inl(chip->port + vr5701_INT_STATUS);
+	outl(irqStatus, chip->port + vr5701_INT_CLR);
+
+	/* let us see what we get */
+	dacInterrupts = vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+	adcInterrupts = vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+	if (irqStatus & dacInterrupts) {
+		/* we should get both interrupts */
+		if (irqStatus & vr5701_INT_MASK_DAC1END) {
+			vr5701_ac97_dac_interrupt(chip);
+		}
+		if ((irqStatus & dacInterrupts) != dacInterrupts) {
+			printk(KERN_WARNING
+			       "vr5701_ac97 : playback interrupts not in sync!!!\n");
+			vr5701_dma_stop_playback(chip->substream[PLAYBACK]);
+			vr5701_dma_start_playback(chip->substream[PLAYBACK]);
+		}
+		snd_pcm_period_elapsed(chip->substream[PLAYBACK]);
+	} else if (irqStatus & adcInterrupts) {
+		/* we should get both interrupts, but just in stereo case */
+		if (irqStatus & vr5701_INT_MASK_ADC1END) {
+			vr5701_ac97_adc_interrupt(chip);
+		}
+		if (((irqStatus & adcInterrupts) != adcInterrupts)
+			&&(chip->substream[CAPTURE]->runtime->channels == 2)) {
+			printk(KERN_WARNING
+			       "vr5701_ac97 : capture interrupts not in sync!!!\n");
+			vr5701_dma_stop_capture(chip->substream[CAPTURE]);
+			vr5701_dma_start_capture(chip->substream[CAPTURE]);
+		}
+		snd_pcm_period_elapsed(chip->substream[CAPTURE]);
+	}
+	
+	return IRQ_HANDLED;
+}
+
+/* chip-specific constructor
+ */
+static int __devinit snd_vr5701_create(snd_card_t *card,
+	struct pci_dev *pci, vr5701_t **rchip)
+{
+	vr5701_t *chip;
+	int err;
+	static snd_device_ops_t ops = {
+		.dev_free = snd_vr5701_dev_free,
+	};
+
+	*rchip = NULL;
+
+	/* initialize the PCI entry */
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+	pci_set_master(pci);
+
+	/* check PCI availability (28bit DMA) */
+	if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
+		pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+			printk(KERN_ERR "error to set 28bit mask DMA\n");
+			pci_disable_device(pci);
+			return -ENXIO;
+	}
+
+	/* allocate a chip-specific data with zero filled */
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL) {
+		pci_disable_device(pci);
+		return -ENOMEM;
+	}
+
+	/* initialize the stuff */
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+
+	/* so that snd_chip_free will work as intended */
+	chip->card->private_data = chip;
+
+	/* PCI resource allocation */
+	if ((err = pci_request_regions(pci, vr5701_AC97_MODULE_NAME)) < 0) {
+		kfree(chip);
+		pci_disable_device(pci);
+		return err;
+	}
+	chip->port = pci_resource_start(pci, 0);
+	if (request_irq(pci->irq, snd_vr5701_interrupt,
+		SA_INTERRUPT|SA_SHIRQ, vr5701_AC97_MODULE_NAME,
+			(void *)chip)) {
+				printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+				snd_vr5701_free(chip);
+				return -EBUSY;
+	}
+	chip->irq = pci->irq;
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+		chip, &ops)) < 0) {
+			snd_vr5701_free(chip);
+			return err;
+	}
+
+	snd_card_set_dev(card, &pci->dev);
+
+	*rchip = chip;
+	return 0;
+}
+
+/* constructor */
+static int __devinit snd_vr5701_probe(struct pci_dev *pci,
+                               const struct pci_device_id *pci_id)
+{
+	static int dev;
+	snd_card_t *card;
+	vr5701_t *chip;
+	int err;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (card == NULL)
+		return -ENOMEM;
+
+	if ((err = snd_vr5701_create(card, pci, &chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	strcpy(card->driver, vr5701_AC97_MODULE_NAME);
+	strcpy(card->shortname, "NEC Electronics Corporation ");
+	sprintf(card->longname, "%s at 0x%lx irq %i",
+		card->shortname, chip->port, chip->irq);
+
+	printk(KERN_INFO "IO at %#lx, IRQ %d\n", chip->port, chip->irq);
+ 
+	/* codec init */
+	if ((err = snd_vr5701_ac97(chip)) < 0)
+		return err;
+
+	snd_vr5701_ac97_reset(chip->ac97);
+	
+	/* Try to enable variable rate audio mode. */
+	snd_vr5701_ac97_write(chip->ac97, AC97_EXTENDED_STATUS,
+		snd_vr5701_ac97_read(chip->ac97, AC97_EXTENDED_STATUS) | AC97_EI_VRA);
+
+	/* Did we enable it? */
+	if (!(snd_vr5701_ac97_read(chip->ac97, AC97_EXTENDED_STATUS) & AC97_EI_VRA))
+		printk(KERN_INFO "VRA mode not enabled; rate fixed at %d.",
+		       48000);
+
+	/* let us get the default volumne louder */
+	snd_vr5701_ac97_write(chip->ac97, 0x2, 0x1010);	/* master volume, middle */
+	snd_vr5701_ac97_write(chip->ac97, 0xc, 0x10);	/* phone volume, middle */
+	snd_vr5701_ac97_write(chip->ac97, 0x10, 0x8000);/* line-in 2 line-out disable */
+	snd_vr5701_ac97_write(chip->ac97, 0x18, 0x0707);/* PCM out (line out) middle */
+
+	/* by default we select line in the input */
+	snd_vr5701_ac97_write(chip->ac97, 0xe, 0x10);	/* misc volume, middle */
+	snd_vr5701_ac97_write(chip->ac97, 0x1a, 0x0000);/* default line is Line_mic */
+	snd_vr5701_ac97_write(chip->ac97, 0x1c, 0x0f0f);
+	snd_vr5701_ac97_write(chip->ac97, 0x1e, 0x07);
+
+	/* enable the master interrupt but disable all others */
+	outl(vr5701_INT_MASK_NMASK, chip->port + vr5701_INT_MASK);
+
+	if ((err = snd_vr5701_new_pcm(chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	if ((err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	pci_set_drvdata(pci, card);
+	dev++;
+	return 0;
+}
+
+/* destructor */
+static void __devexit snd_vr5701_remove(struct pci_dev *pci)
+{
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+/* PCI IDs */
+static struct pci_device_id snd_vr5701_ids[] = {
+	{ PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_VRC5477_AC97,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, snd_vr5701_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+	.name = vr5701_AC97_MODULE_NAME,
+	.id_table = snd_vr5701_ids,
+	.probe = snd_vr5701_probe,
+	.remove = __devexit_p(snd_vr5701_remove),
+	SND_PCI_PM_CALLBACKS
+};
+
+/* initialization of the module */
+static int __init alsa_card_vr5701_init(void)
+{
+	printk(KERN_INFO "ALSA NEC Electronics Corporation VR5701 SolutionGearII AC97 driver: time "
+					 __TIME__ " " __DATE__" by Sergey Podstavin\n");
+	return pci_register_driver(&driver);
+}
+
+/* clean up the module */
+static void __exit alsa_card_vr5701_exit(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_vr5701_init)
+module_exit(alsa_card_vr5701_exit)
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("NEC Electronics Corporation VR5701 SolutionGearII audio (AC97) Driver");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.h
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.h
@@ -0,0 +1,155 @@
+/*
+ * sound/pci/vr5701/nec_vr5701_sg2.h
+ *
+ * An ALSA sound driver for 
+ * NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec.
+ *
+ * Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <sound/pcm_params.h>
+
+#define         vr5701_INT_CLR         	0x0
+#define         vr5701_INT_STATUS	0x0
+#define         vr5701_CODEC_WR        	0x4
+#define         vr5701_CODEC_RD        	0x8
+#define         vr5701_CTRL            	0x18
+#define         vr5701_ACLINK_CTRL     	0x1c
+#define         vr5701_INT_MASK        	0x24
+
+#define		vr5701_DAC1_CTRL	0x30
+#define		vr5701_DAC1L		0x34
+#define		vr5701_DAC1_BADDR	0x38
+#define		vr5701_DAC2_CTRL	0x3c
+#define		vr5701_DAC2L		0x40
+#define		vr5701_DAC2_BADDR	0x44
+#define		vr5701_DAC3_CTRL	0x48
+#define		vr5701_DAC3L		0x4c
+#define		vr5701_DAC3_BADDR	0x50
+
+#define		vr5701_ADC1_CTRL	0x54
+#define		vr5701_ADC1L		0x58
+#define		vr5701_ADC1_BADDR	0x5c
+#define		vr5701_ADC2_CTRL	0x60
+#define		vr5701_ADC2L		0x64
+#define		vr5701_ADC2_BADDR	0x68
+#define		vr5701_ADC3_CTRL	0x6c
+#define		vr5701_ADC3L		0x70
+#define		vr5701_ADC3_BADDR	0x74
+
+#define		vr5701_CODEC_WR_RWC	(1 << 23)
+
+#define		vr5701_CODEC_RD_RRDYA	(1 << 31)
+#define		vr5701_CODEC_RD_RRDYD	(1 << 30)
+
+#define		vr5701_ACLINK_CTRL_RST_ON	(1 << 15)
+#define		vr5701_ACLINK_CTRL_RST_TIME	0x7f
+#define		vr5701_ACLINK_CTRL_SYNC_ON	(1 << 30)
+#define		vr5701_ACLINK_CTRL_CK_STOP_ON	(1 << 31)
+
+#define		vr5701_CTRL_DAC2ENB		(1 << 15)
+#define		vr5701_CTRL_ADC2ENB		(1 << 14)
+#define		vr5701_CTRL_DAC1ENB		(1 << 13)
+#define		vr5701_CTRL_ADC1ENB		(1 << 12)
+
+#define		vr5701_INT_MASK_NMASK		(1 << 31)
+#define		vr5701_INT_MASK_DAC1END		(1 << 5)
+#define		vr5701_INT_MASK_DAC2END		(1 << 4)
+#define		vr5701_INT_MASK_DAC3END		(1 << 3)
+#define		vr5701_INT_MASK_ADC1END		(1 << 2)
+#define		vr5701_INT_MASK_ADC2END		(1 << 1)
+#define		vr5701_INT_MASK_ADC3END		(1 << 0)
+
+#define		vr5701_DMA_ACTIVATION		(1 << 31)
+#define		vr5701_DMA_WIP			(1 << 30)
+
+#define vr5701_AC97_MODULE_NAME "NEC_vr5701_audio"
+#define PLAYBACK 0
+#define CAPTURE  1
+
+/* module parameters */
+static int index[SNDRV_CARDS]  = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS]   = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+/* definition of the chip-specific record */
+typedef struct snd_vr5701 vr5701_t;
+
+struct snd_vr5701 {
+        snd_card_t *card;
+        struct pci_dev *pci;
+	ac97_t *ac97;      
+        unsigned long port; 
+        int irq;  
+	snd_pcm_t	*pcm;
+	snd_pcm_substream_t * substream[2]; 
+	unsigned next_playback;
+	unsigned next_capture;
+};
+
+static unsigned int rates[] = {
+	8000,  11025, 16000, 22050,
+	32000, 44100, 48000,
+};
+
+static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+	.count	= ARRAY_SIZE(rates),
+	.list	= rates,
+	.mask	= 0,
+};
+
+/* hardware definition */
+static snd_pcm_hardware_t snd_vr5701_playback_hw = {
+	.info = (  SNDRV_PCM_INFO_MMAP |
+                   SNDRV_PCM_INFO_NONINTERLEAVED |
+                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                   SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =          SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =            SNDRV_PCM_RATE_8000_48000,
+	.rate_min =         8000,
+	.rate_max =         48000,
+	.channels_min =     1,
+	.channels_max =     2,
+	.buffer_bytes_max = (128*1024),
+	.period_bytes_min = 32,
+	.period_bytes_max = (128*1024),
+	.periods_min =      1,
+	.periods_max =      1024,
+};
+
+/* hardware definition */
+static snd_pcm_hardware_t snd_vr5701_capture_hw = {
+	.info = (SNDRV_PCM_INFO_MMAP |
+                   SNDRV_PCM_INFO_INTERLEAVED |
+                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                   SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =          SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =            SNDRV_PCM_RATE_8000_48000,
+	.rate_min =         8000,
+	.rate_max =         48000,
+	.channels_min =     1,
+	.channels_max =     2,
+	.buffer_bytes_max = (128*1024),
+	.period_bytes_min = 32,
+	.period_bytes_max = (128*1024),
+	.periods_min =      1,
+	.periods_max =      1024,
+};
Index: linux-2.6.10/sound/pci/vr5701/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/pci/vr5701/Makefile
@@ -0,0 +1,16 @@
+#
+# sound/pci/vr5701/Makefile
+#
+# Makefile for ALSA
+#
+# Author: Sergey Podstavin <spodstavin@xxxxxxxxxxxxx>
+#
+# 2005 (c) MontaVista Software, Inc. This file is licensed under
+# the terms of the GNU General Public License version 2. This program
+# is licensed "as is" without any warranty of any kind, whether express
+# or implied.
+#
+
+snd-nec_vr5701_sg2-objs := nec_vr5701_sg2.o
+
+obj-$(CONFIG_SND_VR5701) += snd-nec_vr5701_sg2.o
Index: linux-2.6.10/mvl_patches/pro-0004.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0004.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@xxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+        return mvl_register_patch(4);
+}
+module_init(regpatch);
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-#define LSP_PATCH_LEVEL "3"
+#define LSP_PATCH_LEVEL "4"

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux