Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (94 commits)
  USB: remove err() macro from more usb drivers
  USB: remove err() macro from usb misc drivers
  USB: remove err() macro from usb core code
  USB: remove err() macro from usb class drivers
  USB: remove use of err() in drivers/usb/serial
  USB: remove info() macro from usb mtd drivers
  USB: remove info() macro from usb input drivers
  USB: remove info() macro from usb network drivers
  USB: remove info() macro from remaining usb drivers
  USB: remove info() macro from usb/misc drivers
  USB: remove info() macro from usb/serial drivers
  USB: remove warn macro from HID core
  USB: remove warn() macro from usb drivers
  USB: remove warn() macro from usb net drivers
  USB: remove warn() macro from usb media drivers
  USB: remove warn() macro from usb input drivers
  usb/fsl_qe_udc: clear data toggle on clear halt request
  usb/fsl_qe_udc: fix response to get status request
  fsl_usb2_udc: Fix oops on probe failure.
  fsl_usb2_udc: Add a wmb before priming endpoint.
  ...
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index eb154ef..174eaff 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -2,19 +2,24 @@
 Ext4 Filesystem
 ===============
 
-This is a development version of the ext4 filesystem, an advanced level
-of the ext3 filesystem which incorporates scalability and reliability
-enhancements for supporting large filesystems (64 bit) in keeping with
-increasing disk capacities and state-of-the-art feature requirements.
+Ext4 is an an advanced level of the ext3 filesystem which incorporates
+scalability and reliability enhancements for supporting large filesystems
+(64 bit) in keeping with increasing disk capacities and state-of-the-art
+feature requirements.
 
-Mailing list: linux-ext4@vger.kernel.org
+Mailing list:	linux-ext4@vger.kernel.org
+Web site:	http://ext4.wiki.kernel.org
 
 
 1. Quick usage instructions:
 ===========================
 
+Note: More extensive information for getting started with ext4 can be
+      found at the ext4 wiki site at the URL:
+      http://ext4.wiki.kernel.org/index.php/Ext4_Howto
+
   - Compile and install the latest version of e2fsprogs (as of this
-    writing version 1.41) from:
+    writing version 1.41.3) from:
 
     http://sourceforge.net/project/showfiles.php?group_id=2406
 	
@@ -36,11 +41,9 @@
 
     	# mke2fs -t ext4 /dev/hda1
 
-    Or configure an existing ext3 filesystem to support extents and set
-    the test_fs flag to indicate that it's ok for an in-development
-    filesystem to touch this filesystem:
+    Or to configure an existing ext3 filesystem to support extents: 
 
-	# tune2fs -O extents -E test_fs /dev/hda1
+	# tune2fs -O extents /dev/hda1
 
     If the filesystem was created with 128 byte inodes, it can be
     converted to use 256 byte for greater efficiency via:
@@ -104,8 +107,8 @@
 The big performance win will come with mballoc, delalloc and flex_bg
 grouping of bitmaps and inode tables.  Some test results available here:
 
- - http://www.bullopensource.org/ext4/20080530/ffsb-write-2.6.26-rc2.html
- - http://www.bullopensource.org/ext4/20080530/ffsb-readwrite-2.6.26-rc2.html
+ - http://www.bullopensource.org/ext4/20080818-ffsb/ffsb-write-2.6.27-rc1.html
+ - http://www.bullopensource.org/ext4/20080818-ffsb/ffsb-readwrite-2.6.27-rc1.html
 
 3. Options
 ==========
@@ -214,9 +217,6 @@
 bsddf		(*)	Make 'df' act like BSD.
 minixdf			Make 'df' act like Minix.
 
-check=none		Don't do extra checking of bitmaps on mount.
-nocheck
-
 debug			Extra debugging information is sent to syslog.
 
 errors=remount-ro(*)	Remount the filesystem read-only on an error.
@@ -253,8 +253,6 @@
 			"nobh" option tries to avoid associating buffer
 			heads (supported only for "writeback" mode).
 
-mballoc		(*)	Use the multiple block allocator for block allocation
-nomballoc		disabled multiple block allocator for block allocation.
 stripe=n		Number of filesystem blocks that mballoc will try
 			to use for allocation size and alignment. For RAID5/6
 			systems this should be the number of data
diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828
index aa05e5b..d5cb4ea 100644
--- a/Documentation/video4linux/CARDLIST.au0828
+++ b/Documentation/video4linux/CARDLIST.au0828
@@ -1,5 +1,5 @@
   0 -> Unknown board                            (au0828)
-  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008]
+  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721e,2040:721f,2040:7280,0fd9:0008]
   2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
   3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
   4 -> Hauppauge HVR950Q rev xxF8               (au0828)        [2040:7201,2040:7211,2040:7281]
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index 30bbdda..691d2f3 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -75,3 +75,4 @@
 tuner=75 - Philips TEA5761 FM Radio
 tuner=76 - Xceive 5000 tuner
 tuner=77 - TCL tuner MF02GIP-5N-E
+tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
index 165c871..bcc079c 100644
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -137,6 +137,7 @@
 
 	return (void*) vaddr;
 }
+EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */
 
 struct page *kmap_atomic_to_page(void *ptr)
 {
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 610d6fd..9097500 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -6,7 +6,7 @@
 #
 menuconfig DRM
 	tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
-	depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG
+	depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && SHMEM
 	help
 	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
 	  introduced in XFree86 4.0. If you say Y here, you need to select
@@ -87,6 +87,7 @@
 config DRM_SIS
 	tristate "SiS video cards"
 	depends on DRM && AGP
+	depends on FB_SIS || FB_SIS=n
 	help
 	  Choose this option if you have a SiS 630 or compatible video
           chipset. If M is selected the module will be called sis. AGP
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e9f9a97..74da994 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -4,8 +4,9 @@
 
 ccflags-y := -Iinclude/drm
 
-drm-y       :=	drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
-		drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
+drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
+		drm_context.o drm_dma.o drm_drawable.o \
+		drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
 		drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
 		drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
 		drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
index aefa5ac..3d33b82 100644
--- a/drivers/gpu/drm/drm_agpsupport.c
+++ b/drivers/gpu/drm/drm_agpsupport.c
@@ -33,6 +33,7 @@
 
 #include "drmP.h"
 #include <linux/module.h>
+#include <asm/agp.h>
 
 #if __OS_HAS_AGP
 
@@ -452,4 +453,53 @@
 	return agp_unbind_memory(handle);
 }
 
-#endif				/* __OS_HAS_AGP */
+/**
+ * Binds a collection of pages into AGP memory at the given offset, returning
+ * the AGP memory structure containing them.
+ *
+ * No reference is held on the pages during this time -- it is up to the
+ * caller to handle that.
+ */
+DRM_AGP_MEM *
+drm_agp_bind_pages(struct drm_device *dev,
+		   struct page **pages,
+		   unsigned long num_pages,
+		   uint32_t gtt_offset,
+		   u32 type)
+{
+	DRM_AGP_MEM *mem;
+	int ret, i;
+
+	DRM_DEBUG("\n");
+
+	mem = drm_agp_allocate_memory(dev->agp->bridge, num_pages,
+				      type);
+	if (mem == NULL) {
+		DRM_ERROR("Failed to allocate memory for %ld pages\n",
+			  num_pages);
+		return NULL;
+	}
+
+	for (i = 0; i < num_pages; i++)
+		mem->memory[i] = phys_to_gart(page_to_phys(pages[i]));
+	mem->page_count = num_pages;
+
+	mem->is_flushed = true;
+	ret = drm_agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
+	if (ret != 0) {
+		DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
+		agp_free_memory(mem);
+		return NULL;
+	}
+
+	return mem;
+}
+EXPORT_SYMBOL(drm_agp_bind_pages);
+
+void drm_agp_chipset_flush(struct drm_device *dev)
+{
+	agp_flush_chipset(dev->agp->bridge);
+}
+EXPORT_SYMBOL(drm_agp_chipset_flush);
+
+#endif /* __OS_HAS_AGP */
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
new file mode 100644
index 0000000..0e994a0
--- /dev/null
+++ b/drivers/gpu/drm/drm_cache.c
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+
+#if defined(CONFIG_X86)
+static void
+drm_clflush_page(struct page *page)
+{
+	uint8_t *page_virtual;
+	unsigned int i;
+
+	if (unlikely(page == NULL))
+		return;
+
+	page_virtual = kmap_atomic(page, KM_USER0);
+	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+		clflush(page_virtual + i);
+	kunmap_atomic(page_virtual, KM_USER0);
+}
+#endif
+
+void
+drm_clflush_pages(struct page *pages[], unsigned long num_pages)
+{
+
+#if defined(CONFIG_X86)
+	if (cpu_has_clflush) {
+		unsigned long i;
+
+		mb();
+		for (i = 0; i < num_pages; ++i)
+			drm_clflush_page(*pages++);
+		mb();
+
+		return;
+	}
+
+	wbinvd();
+#endif
+}
+EXPORT_SYMBOL(drm_clflush_pages);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 452c2d8..96f416a 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -116,7 +116,13 @@
 
 	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
 
+	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
+
 	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 851a53f..0d46627 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -246,7 +246,7 @@
 	memset(priv, 0, sizeof(*priv));
 	filp->private_data = priv;
 	priv->filp = filp;
-	priv->uid = current->euid;
+	priv->uid = current_euid();
 	priv->pid = task_pid_nr(current);
 	priv->minor = idr_find(&drm_minors_idr, minor_id);
 	priv->ioctl_count = 0;
@@ -256,6 +256,9 @@
 
 	INIT_LIST_HEAD(&priv->lhead);
 
+	if (dev->driver->driver_features & DRIVER_GEM)
+		drm_gem_open(dev, priv);
+
 	if (dev->driver->open) {
 		ret = dev->driver->open(dev, priv);
 		if (ret < 0)
@@ -400,6 +403,9 @@
 		dev->driver->reclaim_buffers(dev, file_priv);
 	}
 
+	if (dev->driver->driver_features & DRIVER_GEM)
+		drm_gem_release(dev, file_priv);
+
 	drm_fasync(-1, filp, 0);
 
 	mutex_lock(&dev->ctxlist_mutex);
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
new file mode 100644
index 0000000..ccd1afd
--- /dev/null
+++ b/drivers/gpu/drm/drm_gem.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/module.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include "drmP.h"
+
+/** @file drm_gem.c
+ *
+ * This file provides some of the base ioctls and library routines for
+ * the graphics memory manager implemented by each device driver.
+ *
+ * Because various devices have different requirements in terms of
+ * synchronization and migration strategies, implementing that is left up to
+ * the driver, and all that the general API provides should be generic --
+ * allocating objects, reading/writing data with the cpu, freeing objects.
+ * Even there, platform-dependent optimizations for reading/writing data with
+ * the CPU mean we'll likely hook those out to driver-specific calls.  However,
+ * the DRI2 implementation wants to have at least allocate/mmap be generic.
+ *
+ * The goal was to have swap-backed object allocation managed through
+ * struct file.  However, file descriptors as handles to a struct file have
+ * two major failings:
+ * - Process limits prevent more than 1024 or so being used at a time by
+ *   default.
+ * - Inability to allocate high fds will aggravate the X Server's select()
+ *   handling, and likely that of many GL client applications as well.
+ *
+ * This led to a plan of using our own integer IDs (called handles, following
+ * DRM terminology) to mimic fds, and implement the fd syscalls we need as
+ * ioctls.  The objects themselves will still include the struct file so
+ * that we can transition to fds if the required kernel infrastructure shows
+ * up at a later date, and as our interface with shmfs for memory allocation.
+ */
+
+/**
+ * Initialize the GEM device fields
+ */
+
+int
+drm_gem_init(struct drm_device *dev)
+{
+	spin_lock_init(&dev->object_name_lock);
+	idr_init(&dev->object_name_idr);
+	atomic_set(&dev->object_count, 0);
+	atomic_set(&dev->object_memory, 0);
+	atomic_set(&dev->pin_count, 0);
+	atomic_set(&dev->pin_memory, 0);
+	atomic_set(&dev->gtt_count, 0);
+	atomic_set(&dev->gtt_memory, 0);
+	return 0;
+}
+
+/**
+ * Allocate a GEM object of the specified size with shmfs backing store
+ */
+struct drm_gem_object *
+drm_gem_object_alloc(struct drm_device *dev, size_t size)
+{
+	struct drm_gem_object *obj;
+
+	BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+
+	obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
+
+	obj->dev = dev;
+	obj->filp = shmem_file_setup("drm mm object", size, 0);
+	if (IS_ERR(obj->filp)) {
+		kfree(obj);
+		return NULL;
+	}
+
+	kref_init(&obj->refcount);
+	kref_init(&obj->handlecount);
+	obj->size = size;
+	if (dev->driver->gem_init_object != NULL &&
+	    dev->driver->gem_init_object(obj) != 0) {
+		fput(obj->filp);
+		kfree(obj);
+		return NULL;
+	}
+	atomic_inc(&dev->object_count);
+	atomic_add(obj->size, &dev->object_memory);
+	return obj;
+}
+EXPORT_SYMBOL(drm_gem_object_alloc);
+
+/**
+ * Removes the mapping from handle to filp for this object.
+ */
+static int
+drm_gem_handle_delete(struct drm_file *filp, int handle)
+{
+	struct drm_device *dev;
+	struct drm_gem_object *obj;
+
+	/* This is gross. The idr system doesn't let us try a delete and
+	 * return an error code.  It just spews if you fail at deleting.
+	 * So, we have to grab a lock around finding the object and then
+	 * doing the delete on it and dropping the refcount, or the user
+	 * could race us to double-decrement the refcount and cause a
+	 * use-after-free later.  Given the frequency of our handle lookups,
+	 * we may want to use ida for number allocation and a hash table
+	 * for the pointers, anyway.
+	 */
+	spin_lock(&filp->table_lock);
+
+	/* Check if we currently have a reference on the object */
+	obj = idr_find(&filp->object_idr, handle);
+	if (obj == NULL) {
+		spin_unlock(&filp->table_lock);
+		return -EINVAL;
+	}
+	dev = obj->dev;
+
+	/* Release reference and decrement refcount. */
+	idr_remove(&filp->object_idr, handle);
+	spin_unlock(&filp->table_lock);
+
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+/**
+ * Create a handle for this object. This adds a handle reference
+ * to the object, which includes a regular reference count. Callers
+ * will likely want to dereference the object afterwards.
+ */
+int
+drm_gem_handle_create(struct drm_file *file_priv,
+		       struct drm_gem_object *obj,
+		       int *handlep)
+{
+	int	ret;
+
+	/*
+	 * Get the user-visible handle using idr.
+	 */
+again:
+	/* ensure there is space available to allocate a handle */
+	if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
+		return -ENOMEM;
+
+	/* do the allocation under our spinlock */
+	spin_lock(&file_priv->table_lock);
+	ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
+	spin_unlock(&file_priv->table_lock);
+	if (ret == -EAGAIN)
+		goto again;
+
+	if (ret != 0)
+		return ret;
+
+	drm_gem_object_handle_reference(obj);
+	return 0;
+}
+EXPORT_SYMBOL(drm_gem_handle_create);
+
+/** Returns a reference to the object named by the handle. */
+struct drm_gem_object *
+drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
+		      int handle)
+{
+	struct drm_gem_object *obj;
+
+	spin_lock(&filp->table_lock);
+
+	/* Check if we currently have a reference on the object */
+	obj = idr_find(&filp->object_idr, handle);
+	if (obj == NULL) {
+		spin_unlock(&filp->table_lock);
+		return NULL;
+	}
+
+	drm_gem_object_reference(obj);
+
+	spin_unlock(&filp->table_lock);
+
+	return obj;
+}
+EXPORT_SYMBOL(drm_gem_object_lookup);
+
+/**
+ * Releases the handle to an mm object.
+ */
+int
+drm_gem_close_ioctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	struct drm_gem_close *args = data;
+	int ret;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	ret = drm_gem_handle_delete(file_priv, args->handle);
+
+	return ret;
+}
+
+/**
+ * Create a global name for an object, returning the name.
+ *
+ * Note that the name does not hold a reference; when the object
+ * is freed, the name goes away.
+ */
+int
+drm_gem_flink_ioctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	struct drm_gem_flink *args = data;
+	struct drm_gem_object *obj;
+	int ret;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EBADF;
+
+again:
+	if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
+		return -ENOMEM;
+
+	spin_lock(&dev->object_name_lock);
+	if (obj->name) {
+		args->name = obj->name;
+		spin_unlock(&dev->object_name_lock);
+		return 0;
+	}
+	ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
+				 &obj->name);
+	spin_unlock(&dev->object_name_lock);
+	if (ret == -EAGAIN)
+		goto again;
+
+	if (ret != 0) {
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_unreference(obj);
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+
+	/*
+	 * Leave the reference from the lookup around as the
+	 * name table now holds one
+	 */
+	args->name = (uint64_t) obj->name;
+
+	return 0;
+}
+
+/**
+ * Open an object using the global name, returning a handle and the size.
+ *
+ * This handle (of course) holds a reference to the object, so the object
+ * will not go away until the handle is deleted.
+ */
+int
+drm_gem_open_ioctl(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv)
+{
+	struct drm_gem_open *args = data;
+	struct drm_gem_object *obj;
+	int ret;
+	int handle;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	spin_lock(&dev->object_name_lock);
+	obj = idr_find(&dev->object_name_idr, (int) args->name);
+	if (obj)
+		drm_gem_object_reference(obj);
+	spin_unlock(&dev->object_name_lock);
+	if (!obj)
+		return -ENOENT;
+
+	ret = drm_gem_handle_create(file_priv, obj, &handle);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	args->handle = handle;
+	args->size = obj->size;
+
+	return 0;
+}
+
+/**
+ * Called at device open time, sets up the structure for handling refcounting
+ * of mm objects.
+ */
+void
+drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
+{
+	idr_init(&file_private->object_idr);
+	spin_lock_init(&file_private->table_lock);
+}
+
+/**
+ * Called at device close to release the file's
+ * handle references on objects.
+ */
+static int
+drm_gem_object_release_handle(int id, void *ptr, void *data)
+{
+	struct drm_gem_object *obj = ptr;
+
+	drm_gem_object_handle_unreference(obj);
+
+	return 0;
+}
+
+/**
+ * Called at close time when the filp is going away.
+ *
+ * Releases any remaining references on objects by this filp.
+ */
+void
+drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
+{
+	mutex_lock(&dev->struct_mutex);
+	idr_for_each(&file_private->object_idr,
+		     &drm_gem_object_release_handle, NULL);
+
+	idr_destroy(&file_private->object_idr);
+	mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * Called after the last reference to the object has been lost.
+ *
+ * Frees the object
+ */
+void
+drm_gem_object_free(struct kref *kref)
+{
+	struct drm_gem_object *obj = (struct drm_gem_object *) kref;
+	struct drm_device *dev = obj->dev;
+
+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	if (dev->driver->gem_free_object != NULL)
+		dev->driver->gem_free_object(obj);
+
+	fput(obj->filp);
+	atomic_dec(&dev->object_count);
+	atomic_sub(obj->size, &dev->object_memory);
+	kfree(obj);
+}
+EXPORT_SYMBOL(drm_gem_object_free);
+
+/**
+ * Called after the last handle to the object has been closed
+ *
+ * Removes any name for the object. Note that this must be
+ * called before drm_gem_object_free or we'll be touching
+ * freed memory
+ */
+void
+drm_gem_object_handle_free(struct kref *kref)
+{
+	struct drm_gem_object *obj = container_of(kref,
+						  struct drm_gem_object,
+						  handlecount);
+	struct drm_device *dev = obj->dev;
+
+	/* Remove any name for this object */
+	spin_lock(&dev->object_name_lock);
+	if (obj->name) {
+		idr_remove(&dev->object_name_idr, obj->name);
+		spin_unlock(&dev->object_name_lock);
+		/*
+		 * The object name held a reference to this object, drop
+		 * that now.
+		 */
+		drm_gem_object_unreference(obj);
+	} else
+		spin_unlock(&dev->object_name_lock);
+
+}
+EXPORT_SYMBOL(drm_gem_object_handle_free);
+
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 53f0e5a..4091b9e 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -63,7 +63,7 @@
 	    p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
 		return -EINVAL;
 
-	p->irq = dev->irq;
+	p->irq = dev->pdev->irq;
 
 	DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
 		  p->irq);
@@ -71,25 +71,137 @@
 	return 0;
 }
 
+static void vblank_disable_fn(unsigned long arg)
+{
+	struct drm_device *dev = (struct drm_device *)arg;
+	unsigned long irqflags;
+	int i;
+
+	if (!dev->vblank_disable_allowed)
+		return;
+
+	for (i = 0; i < dev->num_crtcs; i++) {
+		spin_lock_irqsave(&dev->vbl_lock, irqflags);
+		if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
+		    dev->vblank_enabled[i]) {
+			DRM_DEBUG("disabling vblank on crtc %d\n", i);
+			dev->last_vblank[i] =
+				dev->driver->get_vblank_counter(dev, i);
+			dev->driver->disable_vblank(dev, i);
+			dev->vblank_enabled[i] = 0;
+		}
+		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+	}
+}
+
+static void drm_vblank_cleanup(struct drm_device *dev)
+{
+	/* Bail if the driver didn't call drm_vblank_init() */
+	if (dev->num_crtcs == 0)
+		return;
+
+	del_timer(&dev->vblank_disable_timer);
+
+	vblank_disable_fn((unsigned long)dev);
+
+	drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
+		 DRM_MEM_DRIVER);
+	drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
+		 DRM_MEM_DRIVER);
+	drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
+		 dev->num_crtcs, DRM_MEM_DRIVER);
+	drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
+		 dev->num_crtcs, DRM_MEM_DRIVER);
+	drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
+		 dev->num_crtcs, DRM_MEM_DRIVER);
+	drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
+		 DRM_MEM_DRIVER);
+	drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
+		 dev->num_crtcs, DRM_MEM_DRIVER);
+
+	dev->num_crtcs = 0;
+}
+
+int drm_vblank_init(struct drm_device *dev, int num_crtcs)
+{
+	int i, ret = -ENOMEM;
+
+	setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
+		    (unsigned long)dev);
+	spin_lock_init(&dev->vbl_lock);
+	atomic_set(&dev->vbl_signal_pending, 0);
+	dev->num_crtcs = num_crtcs;
+
+	dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
+				   DRM_MEM_DRIVER);
+	if (!dev->vbl_queue)
+		goto err;
+
+	dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
+				  DRM_MEM_DRIVER);
+	if (!dev->vbl_sigs)
+		goto err;
+
+	dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
+				      DRM_MEM_DRIVER);
+	if (!dev->_vblank_count)
+		goto err;
+
+	dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
+					 DRM_MEM_DRIVER);
+	if (!dev->vblank_refcount)
+		goto err;
+
+	dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
+					 DRM_MEM_DRIVER);
+	if (!dev->vblank_enabled)
+		goto err;
+
+	dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+	if (!dev->last_vblank)
+		goto err;
+
+	dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int),
+					 DRM_MEM_DRIVER);
+	if (!dev->vblank_inmodeset)
+		goto err;
+
+	/* Zero per-crtc vblank stuff */
+	for (i = 0; i < num_crtcs; i++) {
+		init_waitqueue_head(&dev->vbl_queue[i]);
+		INIT_LIST_HEAD(&dev->vbl_sigs[i]);
+		atomic_set(&dev->_vblank_count[i], 0);
+		atomic_set(&dev->vblank_refcount[i], 0);
+	}
+
+	dev->vblank_disable_allowed = 0;
+
+	return 0;
+
+err:
+	drm_vblank_cleanup(dev);
+	return ret;
+}
+EXPORT_SYMBOL(drm_vblank_init);
+
 /**
  * Install IRQ handler.
  *
  * \param dev DRM device.
- * \param irq IRQ number.
  *
- * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
+ * Initializes the IRQ related data. Installs the handler, calling the driver
  * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
  * before and after the installation.
  */
-static int drm_irq_install(struct drm_device * dev)
+int drm_irq_install(struct drm_device *dev)
 {
-	int ret;
+	int ret = 0;
 	unsigned long sh_flags = 0;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
 
-	if (dev->irq == 0)
+	if (dev->pdev->irq == 0)
 		return -EINVAL;
 
 	mutex_lock(&dev->struct_mutex);
@@ -107,18 +219,7 @@
 	dev->irq_enabled = 1;
 	mutex_unlock(&dev->struct_mutex);
 
-	DRM_DEBUG("irq=%d\n", dev->irq);
-
-	if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
-		init_waitqueue_head(&dev->vbl_queue);
-
-		spin_lock_init(&dev->vbl_lock);
-
-		INIT_LIST_HEAD(&dev->vbl_sigs);
-		INIT_LIST_HEAD(&dev->vbl_sigs2);
-
-		dev->vbl_pending = 0;
-	}
+	DRM_DEBUG("irq=%d\n", dev->pdev->irq);
 
 	/* Before installing handler */
 	dev->driver->irq_preinstall(dev);
@@ -127,8 +228,9 @@
 	if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
 		sh_flags = IRQF_SHARED;
 
-	ret = request_irq(dev->irq, dev->driver->irq_handler,
+	ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler,
 			  sh_flags, dev->devname, dev);
+
 	if (ret < 0) {
 		mutex_lock(&dev->struct_mutex);
 		dev->irq_enabled = 0;
@@ -137,10 +239,16 @@
 	}
 
 	/* After installing handler */
-	dev->driver->irq_postinstall(dev);
+	ret = dev->driver->irq_postinstall(dev);
+	if (ret < 0) {
+		mutex_lock(&dev->struct_mutex);
+		dev->irq_enabled = 0;
+		mutex_unlock(&dev->struct_mutex);
+	}
 
-	return 0;
+	return ret;
 }
+EXPORT_SYMBOL(drm_irq_install);
 
 /**
  * Uninstall the IRQ handler.
@@ -164,17 +272,18 @@
 	if (!irq_enabled)
 		return -EINVAL;
 
-	DRM_DEBUG("irq=%d\n", dev->irq);
+	DRM_DEBUG("irq=%d\n", dev->pdev->irq);
 
 	dev->driver->irq_uninstall(dev);
 
-	free_irq(dev->irq, dev);
+	free_irq(dev->pdev->irq, dev);
+
+	drm_vblank_cleanup(dev);
 
 	dev->locked_tasklet_func = NULL;
 
 	return 0;
 }
-
 EXPORT_SYMBOL(drm_irq_uninstall);
 
 /**
@@ -201,7 +310,7 @@
 		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 			return 0;
 		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
-		    ctl->irq != dev->irq)
+		    ctl->irq != dev->pdev->irq)
 			return -EINVAL;
 		return drm_irq_install(dev);
 	case DRM_UNINST_HANDLER:
@@ -214,6 +323,174 @@
 }
 
 /**
+ * drm_vblank_count - retrieve "cooked" vblank counter value
+ * @dev: DRM device
+ * @crtc: which counter to retrieve
+ *
+ * Fetches the "cooked" vblank count value that represents the number of
+ * vblank events since the system was booted, including lost events due to
+ * modesetting activity.
+ */
+u32 drm_vblank_count(struct drm_device *dev, int crtc)
+{
+	return atomic_read(&dev->_vblank_count[crtc]);
+}
+EXPORT_SYMBOL(drm_vblank_count);
+
+/**
+ * drm_update_vblank_count - update the master vblank counter
+ * @dev: DRM device
+ * @crtc: counter to update
+ *
+ * Call back into the driver to update the appropriate vblank counter
+ * (specified by @crtc).  Deal with wraparound, if it occurred, and
+ * update the last read value so we can deal with wraparound on the next
+ * call if necessary.
+ *
+ * Only necessary when going from off->on, to account for frames we
+ * didn't get an interrupt for.
+ *
+ * Note: caller must hold dev->vbl_lock since this reads & writes
+ * device vblank fields.
+ */
+static void drm_update_vblank_count(struct drm_device *dev, int crtc)
+{
+	u32 cur_vblank, diff;
+
+	/*
+	 * Interrupts were disabled prior to this call, so deal with counter
+	 * wrap if needed.
+	 * NOTE!  It's possible we lost a full dev->max_vblank_count events
+	 * here if the register is small or we had vblank interrupts off for
+	 * a long time.
+	 */
+	cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+	diff = cur_vblank - dev->last_vblank[crtc];
+	if (cur_vblank < dev->last_vblank[crtc]) {
+		diff += dev->max_vblank_count;
+
+		DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
+			  crtc, dev->last_vblank[crtc], cur_vblank, diff);
+	}
+
+	DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
+		  crtc, diff);
+
+	atomic_add(diff, &dev->_vblank_count[crtc]);
+}
+
+/**
+ * drm_vblank_get - get a reference count on vblank events
+ * @dev: DRM device
+ * @crtc: which CRTC to own
+ *
+ * Acquire a reference count on vblank events to avoid having them disabled
+ * while in use.
+ *
+ * RETURNS
+ * Zero on success, nonzero on failure.
+ */
+int drm_vblank_get(struct drm_device *dev, int crtc)
+{
+	unsigned long irqflags;
+	int ret = 0;
+
+	spin_lock_irqsave(&dev->vbl_lock, irqflags);
+	/* Going from 0->1 means we have to enable interrupts again */
+	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
+	    !dev->vblank_enabled[crtc]) {
+		ret = dev->driver->enable_vblank(dev, crtc);
+		DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
+		if (ret)
+			atomic_dec(&dev->vblank_refcount[crtc]);
+		else {
+			dev->vblank_enabled[crtc] = 1;
+			drm_update_vblank_count(dev, crtc);
+		}
+	}
+	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_vblank_get);
+
+/**
+ * drm_vblank_put - give up ownership of vblank events
+ * @dev: DRM device
+ * @crtc: which counter to give up
+ *
+ * Release ownership of a given vblank counter, turning off interrupts
+ * if possible.
+ */
+void drm_vblank_put(struct drm_device *dev, int crtc)
+{
+	/* Last user schedules interrupt disable */
+	if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
+		mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
+}
+EXPORT_SYMBOL(drm_vblank_put);
+
+/**
+ * drm_modeset_ctl - handle vblank event counter changes across mode switch
+ * @DRM_IOCTL_ARGS: standard ioctl arguments
+ *
+ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
+ * ioctls around modesetting so that any lost vblank events are accounted for.
+ *
+ * Generally the counter will reset across mode sets.  If interrupts are
+ * enabled around this call, we don't have to do anything since the counter
+ * will have already been incremented.
+ */
+int drm_modeset_ctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	struct drm_modeset_ctl *modeset = data;
+	unsigned long irqflags;
+	int crtc, ret = 0;
+
+	/* If drm_vblank_init() hasn't been called yet, just no-op */
+	if (!dev->num_crtcs)
+		goto out;
+
+	crtc = modeset->crtc;
+	if (crtc >= dev->num_crtcs) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * To avoid all the problems that might happen if interrupts
+	 * were enabled/disabled around or between these calls, we just
+	 * have the kernel take a reference on the CRTC (just once though
+	 * to avoid corrupting the count if multiple, mismatch calls occur),
+	 * so that interrupts remain enabled in the interim.
+	 */
+	switch (modeset->cmd) {
+	case _DRM_PRE_MODESET:
+		if (!dev->vblank_inmodeset[crtc]) {
+			dev->vblank_inmodeset[crtc] = 1;
+			drm_vblank_get(dev, crtc);
+		}
+		break;
+	case _DRM_POST_MODESET:
+		if (dev->vblank_inmodeset[crtc]) {
+			spin_lock_irqsave(&dev->vbl_lock, irqflags);
+			dev->vblank_disable_allowed = 1;
+			dev->vblank_inmodeset[crtc] = 0;
+			spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+			drm_vblank_put(dev, crtc);
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	return ret;
+}
+
+/**
  * Wait for VBLANK.
  *
  * \param inode device inode.
@@ -232,14 +509,14 @@
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_wait_vblank(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
 {
 	union drm_wait_vblank *vblwait = data;
-	struct timeval now;
 	int ret = 0;
-	unsigned int flags, seq;
+	unsigned int flags, seq, crtc;
 
-	if ((!dev->irq) || (!dev->irq_enabled))
+	if ((!dev->pdev->irq) || (!dev->irq_enabled))
 		return -EINVAL;
 
 	if (vblwait->request.type &
@@ -251,13 +528,17 @@
 	}
 
 	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
+	crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
 
-	if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
-				    DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
+	if (crtc >= dev->num_crtcs)
 		return -EINVAL;
 
-	seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
-			  : &dev->vbl_received);
+	ret = drm_vblank_get(dev, crtc);
+	if (ret) {
+		DRM_ERROR("failed to acquire vblank counter, %d\n", ret);
+		return ret;
+	}
+	seq = drm_vblank_count(dev, crtc);
 
 	switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
 	case _DRM_VBLANK_RELATIVE:
@@ -266,7 +547,8 @@
 	case _DRM_VBLANK_ABSOLUTE:
 		break;
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
+		goto done;
 	}
 
 	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
@@ -276,8 +558,7 @@
 
 	if (flags & _DRM_VBLANK_SIGNAL) {
 		unsigned long irqflags;
-		struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
-				      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+		struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
 		struct drm_vbl_sig *vbl_sig;
 
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -298,22 +579,29 @@
 			}
 		}
 
-		if (dev->vbl_pending >= 100) {
+		if (atomic_read(&dev->vbl_signal_pending) >= 100) {
 			spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-			return -EBUSY;
+			ret = -EBUSY;
+			goto done;
 		}
 
-		dev->vbl_pending++;
-
 		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
-		if (!
-		    (vbl_sig =
-		     drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
-			return -ENOMEM;
+		vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
+				     DRM_MEM_DRIVER);
+		if (!vbl_sig) {
+			ret = -ENOMEM;
+			goto done;
 		}
 
-		memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
+		ret = drm_vblank_get(dev, crtc);
+		if (ret) {
+			drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
+				 DRM_MEM_DRIVER);
+			return ret;
+		}
+
+		atomic_inc(&dev->vbl_signal_pending);
 
 		vbl_sig->sequence = vblwait->request.sequence;
 		vbl_sig->info.si_signo = vblwait->request.signal;
@@ -327,20 +615,29 @@
 
 		vblwait->reply.sequence = seq;
 	} else {
-		if (flags & _DRM_VBLANK_SECONDARY) {
-			if (dev->driver->vblank_wait2)
-				ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
-		} else if (dev->driver->vblank_wait)
-			ret =
-			    dev->driver->vblank_wait(dev,
-						     &vblwait->request.sequence);
+		DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
+			  vblwait->request.sequence, crtc);
+		DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
+			    ((drm_vblank_count(dev, crtc)
+			      - vblwait->request.sequence) <= (1 << 23)));
 
-		do_gettimeofday(&now);
-		vblwait->reply.tval_sec = now.tv_sec;
-		vblwait->reply.tval_usec = now.tv_usec;
+		if (ret != -EINTR) {
+			struct timeval now;
+
+			do_gettimeofday(&now);
+
+			vblwait->reply.tval_sec = now.tv_sec;
+			vblwait->reply.tval_usec = now.tv_usec;
+			vblwait->reply.sequence = drm_vblank_count(dev, crtc);
+			DRM_DEBUG("returning %d to client\n",
+				  vblwait->reply.sequence);
+		} else {
+			DRM_DEBUG("vblank wait interrupted by signal\n");
+		}
 	}
 
-      done:
+done:
+	drm_vblank_put(dev, crtc);
 	return ret;
 }
 
@@ -348,44 +645,57 @@
  * Send the VBLANK signals.
  *
  * \param dev DRM device.
+ * \param crtc CRTC where the vblank event occurred
  *
  * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-void drm_vbl_send_signals(struct drm_device * dev)
+static void drm_vbl_send_signals(struct drm_device *dev, int crtc)
 {
+	struct drm_vbl_sig *vbl_sig, *tmp;
+	struct list_head *vbl_sigs;
+	unsigned int vbl_seq;
 	unsigned long flags;
-	int i;
 
 	spin_lock_irqsave(&dev->vbl_lock, flags);
 
-	for (i = 0; i < 2; i++) {
-		struct drm_vbl_sig *vbl_sig, *tmp;
-		struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-		unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
-						   &dev->vbl_received);
+	vbl_sigs = &dev->vbl_sigs[crtc];
+	vbl_seq = drm_vblank_count(dev, crtc);
 
-		list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
-			if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
-				vbl_sig->info.si_code = vbl_seq;
-				send_sig_info(vbl_sig->info.si_signo,
-					      &vbl_sig->info, vbl_sig->task);
+	list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
+	    if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+		vbl_sig->info.si_code = vbl_seq;
+		send_sig_info(vbl_sig->info.si_signo,
+			      &vbl_sig->info, vbl_sig->task);
 
-				list_del(&vbl_sig->head);
+		list_del(&vbl_sig->head);
 
-				drm_free(vbl_sig, sizeof(*vbl_sig),
-					 DRM_MEM_DRIVER);
-
-				dev->vbl_pending--;
-			}
-		}
+		drm_free(vbl_sig, sizeof(*vbl_sig),
+			 DRM_MEM_DRIVER);
+		atomic_dec(&dev->vbl_signal_pending);
+		drm_vblank_put(dev, crtc);
+	    }
 	}
 
 	spin_unlock_irqrestore(&dev->vbl_lock, flags);
 }
 
-EXPORT_SYMBOL(drm_vbl_send_signals);
+/**
+ * drm_handle_vblank - handle a vblank event
+ * @dev: DRM device
+ * @crtc: where this event occurred
+ *
+ * Drivers should call this routine in their vblank interrupt handlers to
+ * update the vblank counter and send any signals that may be pending.
+ */
+void drm_handle_vblank(struct drm_device *dev, int crtc)
+{
+	atomic_inc(&dev->_vblank_count[crtc]);
+	DRM_WAKEUP(&dev->vbl_queue[crtc]);
+	drm_vbl_send_signals(dev, crtc);
+}
+EXPORT_SYMBOL(drm_handle_vblank);
 
 /**
  * Tasklet wrapper function.
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index 0177012..803bc9e 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -133,6 +133,7 @@
 {
 	return drm_agp_free_memory(handle) ? 0 : -EINVAL;
 }
+EXPORT_SYMBOL(drm_free_agp);
 
 /** Wrapper around agp_bind_memory() */
 int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
@@ -145,6 +146,7 @@
 {
 	return drm_agp_unbind_memory(handle);
 }
+EXPORT_SYMBOL(drm_unbind_agp);
 
 #else  /*  __OS_HAS_AGP  */
 static inline void *agp_remap(unsigned long offset, unsigned long size,
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index dcff9e9..217ad7d 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -169,6 +169,7 @@
 
 	return child;
 }
+EXPORT_SYMBOL(drm_mm_get_block);
 
 /*
  * Put a block. Merge with the previous and / or next block if they are free.
@@ -217,6 +218,7 @@
 		drm_free(cur, sizeof(*cur), DRM_MEM_MM);
 	}
 }
+EXPORT_SYMBOL(drm_mm_put_block);
 
 struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
 				  unsigned long size,
@@ -265,6 +267,7 @@
 
 	return (head->next->next == head);
 }
+EXPORT_SYMBOL(drm_mm_search_free);
 
 int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
@@ -273,7 +276,7 @@
 
 	return drm_mm_create_tail_node(mm, start, size);
 }
-
+EXPORT_SYMBOL(drm_mm_init);
 
 void drm_mm_takedown(struct drm_mm * mm)
 {
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index 93b1e04..d490db4 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -49,6 +49,10 @@
 			   int request, int *eof, void *data);
 static int drm_bufs_info(char *buf, char **start, off_t offset,
 			 int request, int *eof, void *data);
+static int drm_gem_name_info(char *buf, char **start, off_t offset,
+			     int request, int *eof, void *data);
+static int drm_gem_object_info(char *buf, char **start, off_t offset,
+			       int request, int *eof, void *data);
 #if DRM_DEBUG_CODE
 static int drm_vma_info(char *buf, char **start, off_t offset,
 			int request, int *eof, void *data);
@@ -60,13 +64,16 @@
 static struct drm_proc_list {
 	const char *name;	/**< file name */
 	int (*f) (char *, char **, off_t, int, int *, void *);		/**< proc callback*/
+	u32 driver_features; /**< Required driver features for this entry */
 } drm_proc_list[] = {
-	{"name", drm_name_info},
-	{"mem", drm_mem_info},
-	{"vm", drm_vm_info},
-	{"clients", drm_clients_info},
-	{"queues", drm_queues_info},
-	{"bufs", drm_bufs_info},
+	{"name", drm_name_info, 0},
+	{"mem", drm_mem_info, 0},
+	{"vm", drm_vm_info, 0},
+	{"clients", drm_clients_info, 0},
+	{"queues", drm_queues_info, 0},
+	{"bufs", drm_bufs_info, 0},
+	{"gem_names", drm_gem_name_info, DRIVER_GEM},
+	{"gem_objects", drm_gem_object_info, DRIVER_GEM},
 #if DRM_DEBUG_CODE
 	{"vma", drm_vma_info},
 #endif
@@ -90,8 +97,9 @@
 int drm_proc_init(struct drm_minor *minor, int minor_id,
 		  struct proc_dir_entry *root)
 {
+	struct drm_device *dev = minor->dev;
 	struct proc_dir_entry *ent;
-	int i, j;
+	int i, j, ret;
 	char name[64];
 
 	sprintf(name, "%d", minor_id);
@@ -102,23 +110,42 @@
 	}
 
 	for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+		u32 features = drm_proc_list[i].driver_features;
+
+		if (features != 0 &&
+		    (dev->driver->driver_features & features) != features)
+			continue;
+
 		ent = create_proc_entry(drm_proc_list[i].name,
 					S_IFREG | S_IRUGO, minor->dev_root);
 		if (!ent) {
 			DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
 				  name, drm_proc_list[i].name);
-			for (j = 0; j < i; j++)
-				remove_proc_entry(drm_proc_list[i].name,
-						  minor->dev_root);
-			remove_proc_entry(name, root);
-			minor->dev_root = NULL;
-			return -1;
+			ret = -1;
+			goto fail;
 		}
 		ent->read_proc = drm_proc_list[i].f;
 		ent->data = minor;
 	}
 
+	if (dev->driver->proc_init) {
+		ret = dev->driver->proc_init(minor);
+		if (ret) {
+			DRM_ERROR("DRM: Driver failed to initialize "
+				  "/proc/dri.\n");
+			goto fail;
+		}
+	}
+
 	return 0;
+ fail:
+
+	for (j = 0; j < i; j++)
+		remove_proc_entry(drm_proc_list[i].name,
+				  minor->dev_root);
+	remove_proc_entry(name, root);
+	minor->dev_root = NULL;
+	return ret;
 }
 
 /**
@@ -133,12 +160,16 @@
  */
 int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
 {
+	struct drm_device *dev = minor->dev;
 	int i;
 	char name[64];
 
 	if (!root || !minor->dev_root)
 		return 0;
 
+	if (dev->driver->proc_cleanup)
+		dev->driver->proc_cleanup(minor);
+
 	for (i = 0; i < DRM_PROC_ENTRIES; i++)
 		remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
 	sprintf(name, "%d", minor->index);
@@ -480,6 +511,84 @@
 	return ret;
 }
 
+struct drm_gem_name_info_data {
+       int                     len;
+       char                    *buf;
+       int                     eof;
+};
+
+static int drm_gem_one_name_info(int id, void *ptr, void *data)
+{
+	struct drm_gem_object *obj = ptr;
+	struct drm_gem_name_info_data   *nid = data;
+
+	DRM_INFO("name %d size %d\n", obj->name, obj->size);
+	if (nid->eof)
+		return 0;
+
+	nid->len += sprintf(&nid->buf[nid->len],
+			    "%6d%9d%8d%9d\n",
+			    obj->name, obj->size,
+			    atomic_read(&obj->handlecount.refcount),
+			    atomic_read(&obj->refcount.refcount));
+	if (nid->len > DRM_PROC_LIMIT) {
+		nid->eof = 1;
+		return 0;
+	}
+	return 0;
+}
+
+static int drm_gem_name_info(char *buf, char **start, off_t offset,
+			     int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	struct drm_gem_name_info_data nid;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	nid.len = sprintf(buf, "  name     size handles refcount\n");
+	nid.buf = buf;
+	nid.eof = 0;
+	idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid);
+
+	*start = &buf[offset];
+	*eof = 0;
+	if (nid.len > request + offset)
+		return request;
+	*eof = 1;
+	return nid.len - offset;
+}
+
+static int drm_gem_object_info(char *buf, char **start, off_t offset,
+			       int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	int len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof = 0;
+	DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count));
+	DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory));
+	DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count));
+	DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory));
+	DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory));
+	DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total);
+	if (len > request + offset)
+		return request;
+	*eof = 1;
+	return len - offset;
+}
+
 #if DRM_DEBUG_CODE
 
 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index c2f584f..141e330 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -107,7 +107,6 @@
 #ifdef __alpha__
 	dev->hose = pdev->sysdata;
 #endif
-	dev->irq = pdev->irq;
 
 	if (drm_ht_create(&dev->map_hash, 12)) {
 		return -ENOMEM;
@@ -152,6 +151,15 @@
 		goto error_out_unreg;
 	}
 
+	if (driver->driver_features & DRIVER_GEM) {
+		retcode = drm_gem_init(dev);
+		if (retcode) {
+			DRM_ERROR("Cannot initialize graphics execution "
+				  "manager (GEM)\n");
+			goto error_out_unreg;
+		}
+	}
+
 	return 0;
 
       error_out_unreg:
@@ -317,6 +325,7 @@
 int drm_put_minor(struct drm_minor **minor_p)
 {
 	struct drm_minor *minor = *minor_p;
+
 	DRM_DEBUG("release secondary minor %d\n", minor->index);
 
 	if (minor->type == DRM_MINOR_LEGACY)
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index af211a0..1611b9b 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -184,7 +184,7 @@
 err_out_files:
 	if (i > 0)
 		for (j = 0; j < i; j++)
-			device_remove_file(&minor->kdev, &device_attrs[i]);
+			device_remove_file(&minor->kdev, &device_attrs[j]);
 	device_unregister(&minor->kdev);
 err_out:
 
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index a9e6046..5ba78e4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -3,7 +3,12 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 ccflags-y := -Iinclude/drm
-i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
+i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o \
+          i915_suspend.o \
+	  i915_gem.o \
+	  i915_gem_debug.o \
+	  i915_gem_proc.o \
+	  i915_gem_tiling.o
 
 i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 9ac4720..db34780 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -40,40 +40,96 @@
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-	u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
+	u32 last_acthd = I915_READ(acthd_reg);
+	u32 acthd;
+	u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
 	int i;
 
-	for (i = 0; i < 10000; i++) {
-		ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	for (i = 0; i < 100000; i++) {
+		ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+		acthd = I915_READ(acthd_reg);
 		ring->space = ring->head - (ring->tail + 8);
 		if (ring->space < 0)
 			ring->space += ring->Size;
 		if (ring->space >= n)
 			return 0;
 
-		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+		if (dev_priv->sarea_priv)
+			dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
 
 		if (ring->head != last_head)
 			i = 0;
+		if (acthd != last_acthd)
+			i = 0;
 
 		last_head = ring->head;
+		last_acthd = acthd;
+		msleep_interruptible(10);
+
 	}
 
 	return -EBUSY;
 }
 
+/**
+ * Sets up the hardware status page for devices that need a physical address
+ * in the register.
+ */
+static int i915_init_phys_hws(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	/* Program Hardware Status Page */
+	dev_priv->status_page_dmah =
+		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+	if (!dev_priv->status_page_dmah) {
+		DRM_ERROR("Can not allocate hardware status page\n");
+		return -ENOMEM;
+	}
+	dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
+	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+
+	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
+	DRM_DEBUG("Enabled hardware status page\n");
+	return 0;
+}
+
+/**
+ * Frees the hardware status page, whether it's a physical address or a virtual
+ * address set up by the X Server.
+ */
+static void i915_free_hws(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	if (dev_priv->status_page_dmah) {
+		drm_pci_free(dev, dev_priv->status_page_dmah);
+		dev_priv->status_page_dmah = NULL;
+	}
+
+	if (dev_priv->status_gfx_addr) {
+		dev_priv->status_gfx_addr = 0;
+		drm_core_ioremapfree(&dev_priv->hws_map, dev);
+	}
+
+	/* Need to rewrite hardware status page */
+	I915_WRITE(HWS_PGA, 0x1ffff000);
+}
+
 void i915_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
 
-	ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-	ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+	ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+	ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
 	ring->space = ring->head - (ring->tail + 8);
 	if (ring->space < 0)
 		ring->space += ring->Size;
 
-	if (ring->head == ring->tail)
+	if (ring->head == ring->tail && dev_priv->sarea_priv)
 		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
 }
 
@@ -84,28 +140,19 @@
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if (dev->irq)
+	if (dev->irq_enabled)
 		drm_irq_uninstall(dev);
 
 	if (dev_priv->ring.virtual_start) {
 		drm_core_ioremapfree(&dev_priv->ring.map, dev);
-		dev_priv->ring.virtual_start = 0;
-		dev_priv->ring.map.handle = 0;
+		dev_priv->ring.virtual_start = NULL;
+		dev_priv->ring.map.handle = NULL;
 		dev_priv->ring.map.size = 0;
 	}
 
-	if (dev_priv->status_page_dmah) {
-		drm_pci_free(dev, dev_priv->status_page_dmah);
-		dev_priv->status_page_dmah = NULL;
-		/* Need to rewrite hardware status page */
-		I915_WRITE(0x02080, 0x1ffff000);
-	}
-
-	if (dev_priv->status_gfx_addr) {
-		dev_priv->status_gfx_addr = 0;
-		drm_core_ioremapfree(&dev_priv->hws_map, dev);
-		I915_WRITE(0x2080, 0x1ffff000);
-	}
+	/* Clear the HWS virtual address at teardown */
+	if (I915_NEED_GFX_HWS(dev))
+		i915_free_hws(dev);
 
 	return 0;
 }
@@ -121,34 +168,34 @@
 		return -EINVAL;
 	}
 
-	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
-	if (!dev_priv->mmio_map) {
-		i915_dma_cleanup(dev);
-		DRM_ERROR("can not find mmio map!\n");
-		return -EINVAL;
-	}
-
 	dev_priv->sarea_priv = (drm_i915_sarea_t *)
 	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
 
-	dev_priv->ring.Start = init->ring_start;
-	dev_priv->ring.End = init->ring_end;
-	dev_priv->ring.Size = init->ring_size;
-	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+	if (init->ring_size != 0) {
+		if (dev_priv->ring.ring_obj != NULL) {
+			i915_dma_cleanup(dev);
+			DRM_ERROR("Client tried to initialize ringbuffer in "
+				  "GEM mode\n");
+			return -EINVAL;
+		}
 
-	dev_priv->ring.map.offset = init->ring_start;
-	dev_priv->ring.map.size = init->ring_size;
-	dev_priv->ring.map.type = 0;
-	dev_priv->ring.map.flags = 0;
-	dev_priv->ring.map.mtrr = 0;
+		dev_priv->ring.Size = init->ring_size;
+		dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 
-	drm_core_ioremap(&dev_priv->ring.map, dev);
+		dev_priv->ring.map.offset = init->ring_start;
+		dev_priv->ring.map.size = init->ring_size;
+		dev_priv->ring.map.type = 0;
+		dev_priv->ring.map.flags = 0;
+		dev_priv->ring.map.mtrr = 0;
 
-	if (dev_priv->ring.map.handle == NULL) {
-		i915_dma_cleanup(dev);
-		DRM_ERROR("can not ioremap virtual address for"
-			  " ring buffer\n");
-		return -ENOMEM;
+		drm_core_ioremap(&dev_priv->ring.map, dev);
+
+		if (dev_priv->ring.map.handle == NULL) {
+			i915_dma_cleanup(dev);
+			DRM_ERROR("can not ioremap virtual address for"
+				  " ring buffer\n");
+			return -ENOMEM;
+		}
 	}
 
 	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
@@ -159,34 +206,10 @@
 	dev_priv->current_page = 0;
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 
-	/* We are using separate values as placeholders for mechanisms for
-	 * private backbuffer/depthbuffer usage.
-	 */
-	dev_priv->use_mi_batchbuffer_start = 0;
-	if (IS_I965G(dev)) /* 965 doesn't support older method */
-		dev_priv->use_mi_batchbuffer_start = 1;
-
 	/* Allow hardware batchbuffers unless told otherwise.
 	 */
 	dev_priv->allow_batchbuffer = 1;
 
-	/* Program Hardware Status Page */
-	if (!I915_NEED_GFX_HWS(dev)) {
-		dev_priv->status_page_dmah =
-			drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
-
-		if (!dev_priv->status_page_dmah) {
-			i915_dma_cleanup(dev);
-			DRM_ERROR("Can not allocate hardware status page\n");
-			return -ENOMEM;
-		}
-		dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-		dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
-		memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-		I915_WRITE(0x02080, dev_priv->dma_status_page);
-	}
-	DRM_DEBUG("Enabled hardware status page\n");
 	return 0;
 }
 
@@ -201,11 +224,6 @@
 		return -EINVAL;
 	}
 
-	if (!dev_priv->mmio_map) {
-		DRM_ERROR("can not find mmio map!\n");
-		return -EINVAL;
-	}
-
 	if (dev_priv->ring.map.handle == NULL) {
 		DRM_ERROR("can not ioremap virtual address for"
 			  " ring buffer\n");
@@ -220,9 +238,9 @@
 	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
 
 	if (dev_priv->status_gfx_addr != 0)
-		I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+		I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
 	else
-		I915_WRITE(0x02080, dev_priv->dma_status_page);
+		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
 	DRM_DEBUG("Enabled hardware status page\n");
 
 	return 0;
@@ -367,9 +385,10 @@
 	return 0;
 }
 
-static int i915_emit_box(struct drm_device * dev,
-			 struct drm_clip_rect __user * boxes,
-			 int i, int DR1, int DR4)
+int
+i915_emit_box(struct drm_device *dev,
+	      struct drm_clip_rect __user *boxes,
+	      int i, int DR1, int DR4)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_clip_rect box;
@@ -415,14 +434,15 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
 
-	dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
-
+	dev_priv->counter++;
 	if (dev_priv->counter > 0x7FFFFFFFUL)
-		dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+		dev_priv->counter = 0;
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
 	BEGIN_LP_RING(4);
-	OUT_RING(CMD_STORE_DWORD_IDX);
-	OUT_RING(20);
+	OUT_RING(MI_STORE_DWORD_INDEX);
+	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
 	OUT_RING(dev_priv->counter);
 	OUT_RING(0);
 	ADVANCE_LP_RING();
@@ -486,7 +506,7 @@
 				return ret;
 		}
 
-		if (dev_priv->use_mi_batchbuffer_start) {
+		if (!IS_I830(dev) && !IS_845G(dev)) {
 			BEGIN_LP_RING(2);
 			if (IS_I965G(dev)) {
 				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
@@ -516,6 +536,9 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
 
+	if (!dev_priv->sarea_priv)
+		return -EINVAL;
+
 	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
 		  __func__,
 		  dev_priv->current_page,
@@ -524,7 +547,7 @@
 	i915_kernel_lost_context(dev);
 
 	BEGIN_LP_RING(2);
-	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+	OUT_RING(MI_FLUSH | MI_READ_FLUSH);
 	OUT_RING(0);
 	ADVANCE_LP_RING();
 
@@ -549,8 +572,8 @@
 	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
 
 	BEGIN_LP_RING(4);
-	OUT_RING(CMD_STORE_DWORD_IDX);
-	OUT_RING(20);
+	OUT_RING(MI_STORE_DWORD_INDEX);
+	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
 	OUT_RING(dev_priv->counter);
 	OUT_RING(0);
 	ADVANCE_LP_RING();
@@ -570,9 +593,15 @@
 static int i915_flush_ioctl(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv)
 {
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
+	int ret;
 
-	return i915_quiescent(dev);
+	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+	mutex_lock(&dev->struct_mutex);
+	ret = i915_quiescent(dev);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
 }
 
 static int i915_batchbuffer(struct drm_device *dev, void *data,
@@ -593,16 +622,19 @@
 	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
 		  batch->start, batch->used, batch->num_cliprects);
 
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
+	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 	if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
 						       batch->num_cliprects *
 						       sizeof(struct drm_clip_rect)))
 		return -EFAULT;
 
+	mutex_lock(&dev->struct_mutex);
 	ret = i915_dispatch_batchbuffer(dev, batch);
+	mutex_unlock(&dev->struct_mutex);
 
-	sarea_priv->last_dispatch = (int)hw_status[5];
+	if (sarea_priv)
+		sarea_priv->last_dispatch = (int)hw_status[5];
 	return ret;
 }
 
@@ -619,7 +651,7 @@
 	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
 		  cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
 
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
+	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 	if (cmdbuf->num_cliprects &&
 	    DRM_VERIFYAREA_READ(cmdbuf->cliprects,
@@ -629,24 +661,33 @@
 		return -EFAULT;
 	}
 
+	mutex_lock(&dev->struct_mutex);
 	ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
+	mutex_unlock(&dev->struct_mutex);
 	if (ret) {
 		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
 		return ret;
 	}
 
-	sarea_priv->last_dispatch = (int)hw_status[5];
+	if (sarea_priv)
+		sarea_priv->last_dispatch = (int)hw_status[5];
 	return 0;
 }
 
 static int i915_flip_bufs(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv)
 {
+	int ret;
+
 	DRM_DEBUG("%s\n", __func__);
 
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
+	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-	return i915_dispatch_flip(dev);
+	mutex_lock(&dev->struct_mutex);
+	ret = i915_dispatch_flip(dev);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
 }
 
 static int i915_getparam(struct drm_device *dev, void *data,
@@ -663,7 +704,7 @@
 
 	switch (param->param) {
 	case I915_PARAM_IRQ_ACTIVE:
-		value = dev->irq ? 1 : 0;
+		value = dev->pdev->irq ? 1 : 0;
 		break;
 	case I915_PARAM_ALLOW_BATCHBUFFER:
 		value = dev_priv->allow_batchbuffer ? 1 : 0;
@@ -671,6 +712,12 @@
 	case I915_PARAM_LAST_DISPATCH:
 		value = READ_BREADCRUMB(dev_priv);
 		break;
+	case I915_PARAM_CHIPSET_ID:
+		value = dev->pci_device;
+		break;
+	case I915_PARAM_HAS_GEM:
+		value = 1;
+		break;
 	default:
 		DRM_ERROR("Unknown parameter %d\n", param->param);
 		return -EINVAL;
@@ -697,8 +744,6 @@
 
 	switch (param->param) {
 	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
-		if (!IS_I965G(dev))
-			dev_priv->use_mi_batchbuffer_start = param->value;
 		break;
 	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
 		dev_priv->tex_lru_log_granularity = param->value;
@@ -749,8 +794,8 @@
 	dev_priv->hw_status_page = dev_priv->hws_map.handle;
 
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-	I915_WRITE(0x02080, dev_priv->status_gfx_addr);
-	DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
+	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+	DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
 			dev_priv->status_gfx_addr);
 	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
 	return 0;
@@ -776,14 +821,38 @@
 	memset(dev_priv, 0, sizeof(drm_i915_private_t));
 
 	dev->dev_private = (void *)dev_priv;
+	dev_priv->dev = dev;
 
 	/* Add register map (needed for suspend/resume) */
 	base = drm_get_resource_start(dev, mmio_bar);
 	size = drm_get_resource_len(dev, mmio_bar);
 
-	ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
-			 _DRM_KERNEL | _DRM_DRIVER,
-			 &dev_priv->mmio_map);
+	dev_priv->regs = ioremap(base, size);
+
+	i915_gem_load(dev);
+
+	/* Init HWS */
+	if (!I915_NEED_GFX_HWS(dev)) {
+		ret = i915_init_phys_hws(dev);
+		if (ret != 0)
+			return ret;
+	}
+
+	/* On the 945G/GM, the chipset reports the MSI capability on the
+	 * integrated graphics even though the support isn't actually there
+	 * according to the published specs.  It doesn't appear to function
+	 * correctly in testing on 945G.
+	 * This may be a side effect of MSI having been made available for PEG
+	 * and the registers being closely associated.
+	 */
+	if (!IS_I945G(dev) && !IS_I945GM(dev))
+		if (pci_enable_msi(dev->pdev))
+			DRM_ERROR("failed to enable MSI\n");
+
+	intel_opregion_init(dev);
+
+	spin_lock_init(&dev_priv->user_irq_lock);
+
 	return ret;
 }
 
@@ -791,8 +860,15 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->mmio_map)
-		drm_rmmap(dev, dev_priv->mmio_map);
+	if (dev->pdev->msi_enabled)
+		pci_disable_msi(dev->pdev);
+
+	i915_free_hws(dev);
+
+	if (dev_priv->regs != NULL)
+		iounmap(dev_priv->regs);
+
+	intel_opregion_free(dev);
 
 	drm_free(dev->dev_private, sizeof(drm_i915_private_t),
 		 DRM_MEM_DRIVER);
@@ -800,6 +876,25 @@
 	return 0;
 }
 
+int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_i915_file_private *i915_file_priv;
+
+	DRM_DEBUG("\n");
+	i915_file_priv = (struct drm_i915_file_private *)
+	    drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
+
+	if (!i915_file_priv)
+		return -ENOMEM;
+
+	file_priv->driver_priv = i915_file_priv;
+
+	i915_file_priv->mm.last_gem_seqno = 0;
+	i915_file_priv->mm.last_gem_throttle_seqno = 0;
+
+	return 0;
+}
+
 void i915_driver_lastclose(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -807,6 +902,8 @@
 	if (!dev_priv)
 		return;
 
+	i915_gem_lastclose(dev);
+
 	if (dev_priv->agp_heap)
 		i915_mem_takedown(&(dev_priv->agp_heap));
 
@@ -819,6 +916,13 @@
 	i915_mem_release(dev, file_priv, dev_priv->agp_heap);
 }
 
+void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+
+	drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
+}
+
 struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
@@ -836,7 +940,23 @@
 	DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
 	DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
 	DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 93aed1c..a80ead2 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -38,211 +38,9 @@
 	i915_PCI_IDS
 };
 
-enum pipe {
-    PIPE_A = 0,
-    PIPE_B,
-};
-
-static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (pipe == PIPE_A)
-		return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
-	else
-		return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
-}
-
-static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
-	u32 *array;
-	int i;
-
-	if (!i915_pipe_enabled(dev, pipe))
-		return;
-
-	if (pipe == PIPE_A)
-		array = dev_priv->save_palette_a;
-	else
-		array = dev_priv->save_palette_b;
-
-	for(i = 0; i < 256; i++)
-		array[i] = I915_READ(reg + (i << 2));
-}
-
-static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
-	u32 *array;
-	int i;
-
-	if (!i915_pipe_enabled(dev, pipe))
-		return;
-
-	if (pipe == PIPE_A)
-		array = dev_priv->save_palette_a;
-	else
-		array = dev_priv->save_palette_b;
-
-	for(i = 0; i < 256; i++)
-		I915_WRITE(reg + (i << 2), array[i]);
-}
-
-static u8 i915_read_indexed(u16 index_port, u16 data_port, u8 reg)
-{
-	outb(reg, index_port);
-	return inb(data_port);
-}
-
-static u8 i915_read_ar(u16 st01, u8 reg, u16 palette_enable)
-{
-	inb(st01);
-	outb(palette_enable | reg, VGA_AR_INDEX);
-	return inb(VGA_AR_DATA_READ);
-}
-
-static void i915_write_ar(u8 st01, u8 reg, u8 val, u16 palette_enable)
-{
-	inb(st01);
-	outb(palette_enable | reg, VGA_AR_INDEX);
-	outb(val, VGA_AR_DATA_WRITE);
-}
-
-static void i915_write_indexed(u16 index_port, u16 data_port, u8 reg, u8 val)
-{
-	outb(reg, index_port);
-	outb(val, data_port);
-}
-
-static void i915_save_vga(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
-	u16 cr_index, cr_data, st01;
-
-	/* VGA color palette registers */
-	dev_priv->saveDACMASK = inb(VGA_DACMASK);
-	/* DACCRX automatically increments during read */
-	outb(0, VGA_DACRX);
-	/* Read 3 bytes of color data from each index */
-	for (i = 0; i < 256 * 3; i++)
-		dev_priv->saveDACDATA[i] = inb(VGA_DACDATA);
-
-	/* MSR bits */
-	dev_priv->saveMSR = inb(VGA_MSR_READ);
-	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
-		cr_index = VGA_CR_INDEX_CGA;
-		cr_data = VGA_CR_DATA_CGA;
-		st01 = VGA_ST01_CGA;
-	} else {
-		cr_index = VGA_CR_INDEX_MDA;
-		cr_data = VGA_CR_DATA_MDA;
-		st01 = VGA_ST01_MDA;
-	}
-
-	/* CRT controller regs */
-	i915_write_indexed(cr_index, cr_data, 0x11,
-			   i915_read_indexed(cr_index, cr_data, 0x11) &
-			   (~0x80));
-	for (i = 0; i <= 0x24; i++)
-		dev_priv->saveCR[i] =
-			i915_read_indexed(cr_index, cr_data, i);
-	/* Make sure we don't turn off CR group 0 writes */
-	dev_priv->saveCR[0x11] &= ~0x80;
-
-	/* Attribute controller registers */
-	inb(st01);
-	dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX);
-	for (i = 0; i <= 0x14; i++)
-		dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);
-	inb(st01);
-	outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX);
-	inb(st01);
-
-	/* Graphics controller registers */
-	for (i = 0; i < 9; i++)
-		dev_priv->saveGR[i] =
-			i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, i);
-
-	dev_priv->saveGR[0x10] =
-		i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10);
-	dev_priv->saveGR[0x11] =
-		i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11);
-	dev_priv->saveGR[0x18] =
-		i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18);
-
-	/* Sequencer registers */
-	for (i = 0; i < 8; i++)
-		dev_priv->saveSR[i] =
-			i915_read_indexed(VGA_SR_INDEX, VGA_SR_DATA, i);
-}
-
-static void i915_restore_vga(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
-	u16 cr_index, cr_data, st01;
-
-	/* MSR bits */
-	outb(dev_priv->saveMSR, VGA_MSR_WRITE);
-	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
-		cr_index = VGA_CR_INDEX_CGA;
-		cr_data = VGA_CR_DATA_CGA;
-		st01 = VGA_ST01_CGA;
-	} else {
-		cr_index = VGA_CR_INDEX_MDA;
-		cr_data = VGA_CR_DATA_MDA;
-		st01 = VGA_ST01_MDA;
-	}
-
-	/* Sequencer registers, don't write SR07 */
-	for (i = 0; i < 7; i++)
-		i915_write_indexed(VGA_SR_INDEX, VGA_SR_DATA, i,
-				   dev_priv->saveSR[i]);
-
-	/* CRT controller regs */
-	/* Enable CR group 0 writes */
-	i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
-	for (i = 0; i <= 0x24; i++)
-		i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);
-
-	/* Graphics controller regs */
-	for (i = 0; i < 9; i++)
-		i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, i,
-				   dev_priv->saveGR[i]);
-
-	i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10,
-			   dev_priv->saveGR[0x10]);
-	i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11,
-			   dev_priv->saveGR[0x11]);
-	i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18,
-			   dev_priv->saveGR[0x18]);
-
-	/* Attribute controller registers */
-	inb(st01);
-	for (i = 0; i <= 0x14; i++)
-		i915_write_ar(st01, i, dev_priv->saveAR[i], 0);
-	inb(st01); /* switch back to index mode */
-	outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX);
-	inb(st01);
-
-	/* VGA color palette registers */
-	outb(dev_priv->saveDACMASK, VGA_DACMASK);
-	/* DACCRX automatically increments during read */
-	outb(0, VGA_DACWX);
-	/* Read 3 bytes of color data from each index */
-	for (i = 0; i < 256 * 3; i++)
-		outb(dev_priv->saveDACDATA[i], VGA_DACDATA);
-
-}
-
 static int i915_suspend(struct drm_device *dev, pm_message_t state)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
 
 	if (!dev || !dev_priv) {
 		printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
@@ -254,122 +52,10 @@
 		return 0;
 
 	pci_save_state(dev->pdev);
-	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
 
-	/* Display arbitration control */
-	dev_priv->saveDSPARB = I915_READ(DSPARB);
+	i915_save_state(dev);
 
-	/* Pipe & plane A info */
-	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
-	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
-	dev_priv->saveFPA0 = I915_READ(FPA0);
-	dev_priv->saveFPA1 = I915_READ(FPA1);
-	dev_priv->saveDPLL_A = I915_READ(DPLL_A);
-	if (IS_I965G(dev))
-		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
-	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
-	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
-	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
-	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
-	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
-	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
-	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-
-	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
-	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
-	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
-	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
-	dev_priv->saveDSPABASE = I915_READ(DSPABASE);
-	if (IS_I965G(dev)) {
-		dev_priv->saveDSPASURF = I915_READ(DSPASURF);
-		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
-	}
-	i915_save_palette(dev, PIPE_A);
-	dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT);
-
-	/* Pipe & plane B info */
-	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
-	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
-	dev_priv->saveFPB0 = I915_READ(FPB0);
-	dev_priv->saveFPB1 = I915_READ(FPB1);
-	dev_priv->saveDPLL_B = I915_READ(DPLL_B);
-	if (IS_I965G(dev))
-		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
-	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
-	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
-	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
-	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
-	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
-	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
-	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-
-	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
-	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
-	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
-	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
-	dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
-	if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
-		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
-		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
-	}
-	i915_save_palette(dev, PIPE_B);
-	dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT);
-
-	/* CRT state */
-	dev_priv->saveADPA = I915_READ(ADPA);
-
-	/* LVDS state */
-	dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
-	dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
-	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
-	if (IS_I965G(dev))
-		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
-	if (IS_MOBILE(dev) && !IS_I830(dev))
-		dev_priv->saveLVDS = I915_READ(LVDS);
-	if (!IS_I830(dev) && !IS_845G(dev))
-		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
-	dev_priv->saveLVDSPP_ON = I915_READ(LVDSPP_ON);
-	dev_priv->saveLVDSPP_OFF = I915_READ(LVDSPP_OFF);
-	dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
-
-	/* FIXME: save TV & SDVO state */
-
-	/* FBC state */
-	dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
-	dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
-	dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
-	dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
-
-	/* Interrupt state */
-	dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R);
-	dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R);
-	dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R);
-
-	/* VGA state */
-	dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
-	dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
-	dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
-	dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
-
-	/* Clock gating state */
-	dev_priv->saveD_STATE = I915_READ(D_STATE);
-	dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
-
-	/* Cache mode state */
-	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
-
-	/* Memory Arbitration state */
-	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
-
-	/* Scratch space */
-	for (i = 0; i < 16; i++) {
-		dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2));
-		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
-	}
-	for (i = 0; i < 3; i++)
-		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
-
-	i915_save_vga(dev);
+	intel_opregion_free(dev);
 
 	if (state.event == PM_EVENT_SUSPEND) {
 		/* Shut down the device */
@@ -382,155 +68,15 @@
 
 static int i915_resume(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
-
 	pci_set_power_state(dev->pdev, PCI_D0);
 	pci_restore_state(dev->pdev);
 	if (pci_enable_device(dev->pdev))
 		return -1;
 	pci_set_master(dev->pdev);
 
-	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+	i915_restore_state(dev);
 
-	I915_WRITE(DSPARB, dev_priv->saveDSPARB);
-
-	/* Pipe & plane A info */
-	/* Prime the clock */
-	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
-		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
-			   ~DPLL_VCO_ENABLE);
-		udelay(150);
-	}
-	I915_WRITE(FPA0, dev_priv->saveFPA0);
-	I915_WRITE(FPA1, dev_priv->saveFPA1);
-	/* Actually enable it */
-	I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
-	udelay(150);
-	if (IS_I965G(dev))
-		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
-	udelay(150);
-
-	/* Restore mode */
-	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
-	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
-	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
-	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
-	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
-	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
-	I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
-
-	/* Restore plane info */
-	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
-	I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
-	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
-	if (IS_I965G(dev)) {
-		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
-	}
-
-	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
-
-	i915_restore_palette(dev, PIPE_A);
-	/* Enable the plane */
-	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
-	I915_WRITE(DSPABASE, I915_READ(DSPABASE));
-
-	/* Pipe & plane B info */
-	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
-			   ~DPLL_VCO_ENABLE);
-		udelay(150);
-	}
-	I915_WRITE(FPB0, dev_priv->saveFPB0);
-	I915_WRITE(FPB1, dev_priv->saveFPB1);
-	/* Actually enable it */
-	I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
-	udelay(150);
-	if (IS_I965G(dev))
-		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
-	udelay(150);
-
-	/* Restore mode */
-	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
-	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
-	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
-	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
-	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
-	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
-	I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
-
-	/* Restore plane info */
-	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
-	I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
-	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
-	if (IS_I965G(dev)) {
-		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
-	}
-
-	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
-
-	i915_restore_palette(dev, PIPE_B);
-	/* Enable the plane */
-	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
-	I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
-
-	/* CRT state */
-	I915_WRITE(ADPA, dev_priv->saveADPA);
-
-	/* LVDS state */
-	if (IS_I965G(dev))
-		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
-	if (IS_MOBILE(dev) && !IS_I830(dev))
-		I915_WRITE(LVDS, dev_priv->saveLVDS);
-	if (!IS_I830(dev) && !IS_845G(dev))
-		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
-
-	I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
-	I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
-	I915_WRITE(LVDSPP_ON, dev_priv->saveLVDSPP_ON);
-	I915_WRITE(LVDSPP_OFF, dev_priv->saveLVDSPP_OFF);
-	I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
-	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
-
-	/* FIXME: restore TV & SDVO state */
-
-	/* FBC info */
-	I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
-	I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
-	I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
-	I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
-
-	/* VGA state */
-	I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
-	I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
-	I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
-	I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
-	udelay(150);
-
-	/* Clock gating state */
-	I915_WRITE (D_STATE, dev_priv->saveD_STATE);
-	I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
-
-	/* Cache mode state */
-	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
-
-	/* Memory arbitration state */
-	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
-
-	for (i = 0; i < 16; i++) {
-		I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]);
-		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
-	}
-	for (i = 0; i < 3; i++)
-		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
-
-	i915_restore_vga(dev);
+	intel_opregion_init(dev);
 
 	return 0;
 }
@@ -541,17 +87,19 @@
 	 */
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
-	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
-	    DRIVER_IRQ_VBL2,
+	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
 	.load = i915_driver_load,
 	.unload = i915_driver_unload,
+	.open = i915_driver_open,
 	.lastclose = i915_driver_lastclose,
 	.preclose = i915_driver_preclose,
+	.postclose = i915_driver_postclose,
 	.suspend = i915_suspend,
 	.resume = i915_resume,
 	.device_is_agp = i915_driver_device_is_agp,
-	.vblank_wait = i915_driver_vblank_wait,
-	.vblank_wait2 = i915_driver_vblank_wait2,
+	.get_vblank_counter = i915_get_vblank_counter,
+	.enable_vblank = i915_enable_vblank,
+	.disable_vblank = i915_disable_vblank,
 	.irq_preinstall = i915_driver_irq_preinstall,
 	.irq_postinstall = i915_driver_irq_postinstall,
 	.irq_uninstall = i915_driver_irq_uninstall,
@@ -559,6 +107,10 @@
 	.reclaim_buffers = drm_core_reclaim_buffers,
 	.get_map_ofs = drm_core_get_map_ofs,
 	.get_reg_ofs = drm_core_get_reg_ofs,
+	.proc_init = i915_gem_proc_init,
+	.proc_cleanup = i915_gem_proc_cleanup,
+	.gem_init_object = i915_gem_init_object,
+	.gem_free_object = i915_gem_free_object,
 	.ioctls = i915_ioctls,
 	.fops = {
 		 .owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d7326d9..eae4ed3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -30,6 +30,8 @@
 #ifndef _I915_DRV_H_
 #define _I915_DRV_H_
 
+#include "i915_reg.h"
+
 /* General customization:
  */
 
@@ -37,7 +39,12 @@
 
 #define DRIVER_NAME		"i915"
 #define DRIVER_DESC		"Intel Graphics"
-#define DRIVER_DATE		"20060119"
+#define DRIVER_DATE		"20080730"
+
+enum pipe {
+	PIPE_A = 0,
+	PIPE_B,
+};
 
 /* Interface history:
  *
@@ -53,16 +60,23 @@
 #define DRIVER_MINOR		6
 #define DRIVER_PATCHLEVEL	0
 
+#define WATCH_COHERENCY	0
+#define WATCH_BUF	0
+#define WATCH_EXEC	0
+#define WATCH_LRU	0
+#define WATCH_RELOC	0
+#define WATCH_INACTIVE	0
+#define WATCH_PWRITE	0
+
 typedef struct _drm_i915_ring_buffer {
 	int tail_mask;
-	unsigned long Start;
-	unsigned long End;
 	unsigned long Size;
 	u8 *virtual_start;
 	int head;
 	int tail;
 	int space;
 	drm_local_map_t map;
+	struct drm_gem_object *ring_obj;
 } drm_i915_ring_buffer_t;
 
 struct mem_block {
@@ -76,13 +90,28 @@
 typedef struct _drm_i915_vbl_swap {
 	struct list_head head;
 	drm_drawable_t drw_id;
-	unsigned int pipe;
+	unsigned int plane;
 	unsigned int sequence;
 } drm_i915_vbl_swap_t;
 
+struct opregion_header;
+struct opregion_acpi;
+struct opregion_swsci;
+struct opregion_asle;
+
+struct intel_opregion {
+	struct opregion_header *header;
+	struct opregion_acpi *acpi;
+	struct opregion_swsci *swsci;
+	struct opregion_asle *asle;
+	int enabled;
+};
+
 typedef struct drm_i915_private {
+	struct drm_device *dev;
+
+	void __iomem *regs;
 	drm_local_map_t *sarea;
-	drm_local_map_t *mmio_map;
 
 	drm_i915_sarea_t *sarea_priv;
 	drm_i915_ring_buffer_t ring;
@@ -90,20 +119,25 @@
 	drm_dma_handle_t *status_page_dmah;
 	void *hw_status_page;
 	dma_addr_t dma_status_page;
-	unsigned long counter;
+	uint32_t counter;
 	unsigned int status_gfx_addr;
 	drm_local_map_t hws_map;
+	struct drm_gem_object *hws_obj;
 
 	unsigned int cpp;
 	int back_offset;
 	int front_offset;
 	int current_page;
 	int page_flipping;
-	int use_mi_batchbuffer_start;
 
 	wait_queue_head_t irq_queue;
 	atomic_t irq_received;
-	atomic_t irq_emitted;
+	/** Protects user_irq_refcount and irq_mask_reg */
+	spinlock_t user_irq_lock;
+	/** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
+	int user_irq_refcount;
+	/** Cached value of IMR to avoid reads in updating the bitfield */
+	u32 irq_mask_reg;
 
 	int tex_lru_log_granularity;
 	int allow_batchbuffer;
@@ -115,6 +149,8 @@
 	drm_i915_vbl_swap_t vbl_swaps;
 	unsigned int swaps_pending;
 
+	struct intel_opregion opregion;
+
 	/* Register state */
 	u8 saveLBB;
 	u32 saveDSPACNTR;
@@ -139,7 +175,7 @@
 	u32 saveDSPASTRIDE;
 	u32 saveDSPASIZE;
 	u32 saveDSPAPOS;
-	u32 saveDSPABASE;
+	u32 saveDSPAADDR;
 	u32 saveDSPASURF;
 	u32 saveDSPATILEOFF;
 	u32 savePFIT_PGM_RATIOS;
@@ -160,24 +196,24 @@
 	u32 saveDSPBSTRIDE;
 	u32 saveDSPBSIZE;
 	u32 saveDSPBPOS;
-	u32 saveDSPBBASE;
+	u32 saveDSPBADDR;
 	u32 saveDSPBSURF;
 	u32 saveDSPBTILEOFF;
-	u32 saveVCLK_DIVISOR_VGA0;
-	u32 saveVCLK_DIVISOR_VGA1;
-	u32 saveVCLK_POST_DIV;
+	u32 saveVGA0;
+	u32 saveVGA1;
+	u32 saveVGA_PD;
 	u32 saveVGACNTRL;
 	u32 saveADPA;
 	u32 saveLVDS;
-	u32 saveLVDSPP_ON;
-	u32 saveLVDSPP_OFF;
+	u32 savePP_ON_DELAYS;
+	u32 savePP_OFF_DELAYS;
 	u32 saveDVOA;
 	u32 saveDVOB;
 	u32 saveDVOC;
 	u32 savePP_ON;
 	u32 savePP_OFF;
 	u32 savePP_CONTROL;
-	u32 savePP_CYCLE;
+	u32 savePP_DIVISOR;
 	u32 savePFIT_CONTROL;
 	u32 save_palette_a[256];
 	u32 save_palette_b[256];
@@ -190,7 +226,7 @@
 	u32 saveIMR;
 	u32 saveCACHE_MODE_0;
 	u32 saveD_STATE;
-	u32 saveDSPCLK_GATE_D;
+	u32 saveCG_2D_DIS;
 	u32 saveMI_ARB_STATE;
 	u32 saveSWF0[16];
 	u32 saveSWF1[16];
@@ -203,8 +239,180 @@
 	u8 saveDACMASK;
 	u8 saveDACDATA[256*3]; /* 256 3-byte colors */
 	u8 saveCR[37];
+
+	struct {
+		struct drm_mm gtt_space;
+
+		/**
+		 * List of objects currently involved in rendering from the
+		 * ringbuffer.
+		 *
+		 * A reference is held on the buffer while on this list.
+		 */
+		struct list_head active_list;
+
+		/**
+		 * List of objects which are not in the ringbuffer but which
+		 * still have a write_domain which needs to be flushed before
+		 * unbinding.
+		 *
+		 * A reference is held on the buffer while on this list.
+		 */
+		struct list_head flushing_list;
+
+		/**
+		 * LRU list of objects which are not in the ringbuffer and
+		 * are ready to unbind, but are still in the GTT.
+		 *
+		 * A reference is not held on the buffer while on this list,
+		 * as merely being GTT-bound shouldn't prevent its being
+		 * freed, and we'll pull it off the list in the free path.
+		 */
+		struct list_head inactive_list;
+
+		/**
+		 * List of breadcrumbs associated with GPU requests currently
+		 * outstanding.
+		 */
+		struct list_head request_list;
+
+		/**
+		 * We leave the user IRQ off as much as possible,
+		 * but this means that requests will finish and never
+		 * be retired once the system goes idle. Set a timer to
+		 * fire periodically while the ring is running. When it
+		 * fires, go retire requests.
+		 */
+		struct delayed_work retire_work;
+
+		/** Work task for vblank-related ring access */
+		struct work_struct vblank_work;
+
+		uint32_t next_gem_seqno;
+
+		/**
+		 * Waiting sequence number, if any
+		 */
+		uint32_t waiting_gem_seqno;
+
+		/**
+		 * Last seq seen at irq time
+		 */
+		uint32_t irq_gem_seqno;
+
+		/**
+		 * Flag if the X Server, and thus DRM, is not currently in
+		 * control of the device.
+		 *
+		 * This is set between LeaveVT and EnterVT.  It needs to be
+		 * replaced with a semaphore.  It also needs to be
+		 * transitioned away from for kernel modesetting.
+		 */
+		int suspended;
+
+		/**
+		 * Flag if the hardware appears to be wedged.
+		 *
+		 * This is set when attempts to idle the device timeout.
+		 * It prevents command submission from occuring and makes
+		 * every pending request fail
+		 */
+		int wedged;
+
+		/** Bit 6 swizzling required for X tiling */
+		uint32_t bit_6_swizzle_x;
+		/** Bit 6 swizzling required for Y tiling */
+		uint32_t bit_6_swizzle_y;
+	} mm;
 } drm_i915_private_t;
 
+/** driver private structure attached to each drm_gem_object */
+struct drm_i915_gem_object {
+	struct drm_gem_object *obj;
+
+	/** Current space allocated to this object in the GTT, if any. */
+	struct drm_mm_node *gtt_space;
+
+	/** This object's place on the active/flushing/inactive lists */
+	struct list_head list;
+
+	/**
+	 * This is set if the object is on the active or flushing lists
+	 * (has pending rendering), and is not set if it's on inactive (ready
+	 * to be unbound).
+	 */
+	int active;
+
+	/**
+	 * This is set if the object has been written to since last bound
+	 * to the GTT
+	 */
+	int dirty;
+
+	/** AGP memory structure for our GTT binding. */
+	DRM_AGP_MEM *agp_mem;
+
+	struct page **page_list;
+
+	/**
+	 * Current offset of the object in GTT space.
+	 *
+	 * This is the same as gtt_space->start
+	 */
+	uint32_t gtt_offset;
+
+	/** Boolean whether this object has a valid gtt offset. */
+	int gtt_bound;
+
+	/** How many users have pinned this object in GTT space */
+	int pin_count;
+
+	/** Breadcrumb of last rendering to the buffer. */
+	uint32_t last_rendering_seqno;
+
+	/** Current tiling mode for the object. */
+	uint32_t tiling_mode;
+
+	/** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */
+	uint32_t agp_type;
+
+	/**
+	 * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when
+	 * GEM_DOMAIN_CPU is not in the object's read domain.
+	 */
+	uint8_t *page_cpu_valid;
+};
+
+/**
+ * Request queue structure.
+ *
+ * The request queue allows us to note sequence numbers that have been emitted
+ * and may be associated with active buffers to be retired.
+ *
+ * By keeping this list, we can avoid having to do questionable
+ * sequence-number comparisons on buffer last_rendering_seqnos, and associate
+ * an emission time with seqnos for tracking how far ahead of the GPU we are.
+ */
+struct drm_i915_gem_request {
+	/** GEM sequence number associated with this request. */
+	uint32_t seqno;
+
+	/** Time at which this request was emitted, in jiffies. */
+	unsigned long emitted_jiffies;
+
+	/** Cache domains that were flushed at the start of the request. */
+	uint32_t flush_domains;
+
+	struct list_head list;
+};
+
+struct drm_i915_file_private {
+	struct {
+		uint32_t last_gem_seqno;
+		uint32_t last_gem_throttle_seqno;
+	} mm;
+};
+
 extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 
@@ -212,31 +420,42 @@
 extern void i915_kernel_lost_context(struct drm_device * dev);
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
 extern int i915_driver_unload(struct drm_device *);
+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
 extern void i915_driver_lastclose(struct drm_device * dev);
 extern void i915_driver_preclose(struct drm_device *dev,
 				 struct drm_file *file_priv);
+extern void i915_driver_postclose(struct drm_device *dev,
+				  struct drm_file *file_priv);
 extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
+extern int i915_emit_box(struct drm_device *dev,
+			 struct drm_clip_rect __user *boxes,
+			 int i, int DR1, int DR4);
 
 /* i915_irq.c */
 extern int i915_irq_emit(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 extern int i915_irq_wait(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
+void i915_user_irq_get(struct drm_device *dev);
+void i915_user_irq_put(struct drm_device *dev);
 
-extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
+extern void i915_gem_vblank_work_handler(struct work_struct *work);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(struct drm_device * dev);
-extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern int i915_driver_irq_postinstall(struct drm_device *dev);
 extern void i915_driver_irq_uninstall(struct drm_device * dev);
 extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
 extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+extern int i915_enable_vblank(struct drm_device *dev, int crtc);
+extern void i915_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv);
+extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
 
 /* i915_mem.c */
 extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -250,11 +469,99 @@
 extern void i915_mem_takedown(struct mem_block **heap);
 extern void i915_mem_release(struct drm_device * dev,
 			     struct drm_file *file_priv, struct mem_block *heap);
+/* i915_gem.c */
+int i915_gem_init_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_create_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+int i915_gem_pread_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+int i915_gem_execbuffer(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+int i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int i915_gem_set_tiling(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_get_tiling(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+void i915_gem_load(struct drm_device *dev);
+int i915_gem_proc_init(struct drm_minor *minor);
+void i915_gem_proc_cleanup(struct drm_minor *minor);
+int i915_gem_init_object(struct drm_gem_object *obj);
+void i915_gem_free_object(struct drm_gem_object *obj);
+int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
+void i915_gem_object_unpin(struct drm_gem_object *obj);
+void i915_gem_lastclose(struct drm_device *dev);
+uint32_t i915_get_gem_seqno(struct drm_device *dev);
+void i915_gem_retire_requests(struct drm_device *dev);
+void i915_gem_retire_work_handler(struct work_struct *work);
+void i915_gem_clflush_object(struct drm_gem_object *obj);
 
-#define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
-#define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
-#define I915_READ16(reg)	DRM_READ16(dev_priv->mmio_map, (reg))
-#define I915_WRITE16(reg,val)	DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
+/* i915_gem_tiling.c */
+void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
+
+/* i915_gem_debug.c */
+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
+			  const char *where, uint32_t mark);
+#if WATCH_INACTIVE
+void i915_verify_inactive(struct drm_device *dev, char *file, int line);
+#else
+#define i915_verify_inactive(dev, file, line)
+#endif
+void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle);
+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
+			  const char *where, uint32_t mark);
+void i915_dump_lru(struct drm_device *dev, const char *where);
+
+/* i915_suspend.c */
+extern int i915_save_state(struct drm_device *dev);
+extern int i915_restore_state(struct drm_device *dev);
+
+/* i915_suspend.c */
+extern int i915_save_state(struct drm_device *dev);
+extern int i915_restore_state(struct drm_device *dev);
+
+/* i915_opregion.c */
+extern int intel_opregion_init(struct drm_device *dev);
+extern void intel_opregion_free(struct drm_device *dev);
+extern void opregion_asle_intr(struct drm_device *dev);
+extern void opregion_enable_asle(struct drm_device *dev);
+
+/**
+ * Lock test for when it's just for synchronization of ring access.
+ *
+ * In that case, we don't need to do it when GEM is initialized as nobody else
+ * has access to the ring.
+ */
+#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do {			\
+	if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \
+		LOCK_TEST_WITH_RETURN(dev, file_priv);			\
+} while (0)
+
+#define I915_READ(reg)          readl(dev_priv->regs + (reg))
+#define I915_WRITE(reg, val)     writel(val, dev_priv->regs + (reg))
+#define I915_READ16(reg)	readw(dev_priv->regs + (reg))
+#define I915_WRITE16(reg, val)	writel(val, dev_priv->regs + (reg))
+#define I915_READ8(reg)		readb(dev_priv->regs + (reg))
+#define I915_WRITE8(reg, val)	writeb(val, dev_priv->regs + (reg))
 
 #define I915_VERBOSE 0
 
@@ -284,816 +591,29 @@
 	if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);	\
 	dev_priv->ring.tail = outring;					\
 	dev_priv->ring.space -= outcount * 4;				\
-	I915_WRITE(LP_RING + RING_TAIL, outring);			\
+	I915_WRITE(PRB0_TAIL, outring);			\
 } while(0)
 
-extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
-
-/* Extended config space */
-#define LBB 0xf4
-
-/* VGA stuff */
-
-#define VGA_ST01_MDA 0x3ba
-#define VGA_ST01_CGA 0x3da
-
-#define VGA_MSR_WRITE 0x3c2
-#define VGA_MSR_READ 0x3cc
-#define   VGA_MSR_MEM_EN (1<<1)
-#define   VGA_MSR_CGA_MODE (1<<0)
-
-#define VGA_SR_INDEX 0x3c4
-#define VGA_SR_DATA 0x3c5
-
-#define VGA_AR_INDEX 0x3c0
-#define   VGA_AR_VID_EN (1<<5)
-#define VGA_AR_DATA_WRITE 0x3c0
-#define VGA_AR_DATA_READ 0x3c1
-
-#define VGA_GR_INDEX 0x3ce
-#define VGA_GR_DATA 0x3cf
-/* GR05 */
-#define   VGA_GR_MEM_READ_MODE_SHIFT 3
-#define     VGA_GR_MEM_READ_MODE_PLANE 1
-/* GR06 */
-#define   VGA_GR_MEM_MODE_MASK 0xc
-#define   VGA_GR_MEM_MODE_SHIFT 2
-#define   VGA_GR_MEM_A0000_AFFFF 0
-#define   VGA_GR_MEM_A0000_BFFFF 1
-#define   VGA_GR_MEM_B0000_B7FFF 2
-#define   VGA_GR_MEM_B0000_BFFFF 3
-
-#define VGA_DACMASK 0x3c6
-#define VGA_DACRX 0x3c7
-#define VGA_DACWX 0x3c8
-#define VGA_DACDATA 0x3c9
-
-#define VGA_CR_INDEX_MDA 0x3b4
-#define VGA_CR_DATA_MDA 0x3b5
-#define VGA_CR_INDEX_CGA 0x3d4
-#define VGA_CR_DATA_CGA 0x3d5
-
-#define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD			(7<<23)
-#define CMD_STORE_DWORD_IDX		((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
-
-#define INST_PARSER_CLIENT   0x00000000
-#define INST_OP_FLUSH        0x02000000
-#define INST_FLUSH_MAP_CACHE 0x00000001
-
-#define BB1_START_ADDR_MASK   (~0x7)
-#define BB1_PROTECTED         (1<<0)
-#define BB1_UNPROTECTED       (0<<0)
-#define BB2_END_ADDR_MASK     (~0x7)
-
-/* Framebuffer compression */
-#define FBC_CFB_BASE		0x03200 /* 4k page aligned */
-#define FBC_LL_BASE		0x03204 /* 4k page aligned */
-#define FBC_CONTROL		0x03208
-#define   FBC_CTL_EN		(1<<31)
-#define   FBC_CTL_PERIODIC	(1<<30)
-#define   FBC_CTL_INTERVAL_SHIFT (16)
-#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
-#define   FBC_CTL_STRIDE_SHIFT	(5)
-#define   FBC_CTL_FENCENO	(1<<0)
-#define FBC_COMMAND		0x0320c
-#define   FBC_CMD_COMPRESS	(1<<0)
-#define FBC_STATUS		0x03210
-#define   FBC_STAT_COMPRESSING	(1<<31)
-#define   FBC_STAT_COMPRESSED	(1<<30)
-#define   FBC_STAT_MODIFIED	(1<<29)
-#define   FBC_STAT_CURRENT_LINE	(1<<0)
-#define FBC_CONTROL2		0x03214
-#define   FBC_CTL_FENCE_DBL	(0<<4)
-#define   FBC_CTL_IDLE_IMM	(0<<2)
-#define   FBC_CTL_IDLE_FULL	(1<<2)
-#define   FBC_CTL_IDLE_LINE	(2<<2)
-#define   FBC_CTL_IDLE_DEBUG	(3<<2)
-#define   FBC_CTL_CPU_FENCE	(1<<1)
-#define   FBC_CTL_PLANEA	(0<<0)
-#define   FBC_CTL_PLANEB	(1<<0)
-#define FBC_FENCE_OFF		0x0321b
-
-#define FBC_LL_SIZE		(1536)
-#define FBC_LL_PAD		(32)
-
-/* Interrupt bits:
- */
-#define USER_INT_FLAG    (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
-
-#define I915REG_HWSTAM		0x02098
-#define I915REG_INT_IDENTITY_R	0x020a4
-#define I915REG_INT_MASK_R	0x020a8
-#define I915REG_INT_ENABLE_R	0x020a0
-
-#define I915REG_PIPEASTAT	0x70024
-#define I915REG_PIPEBSTAT	0x71024
-
-#define I915_VBLANK_INTERRUPT_ENABLE	(1UL<<17)
-#define I915_VBLANK_CLEAR		(1UL<<1)
-
-#define SRX_INDEX		0x3c4
-#define SRX_DATA		0x3c5
-#define SR01			1
-#define SR01_SCREEN_OFF		(1<<5)
-
-#define PPCR			0x61204
-#define PPCR_ON			(1<<0)
-
-#define DVOB			0x61140
-#define DVOB_ON			(1<<31)
-#define DVOC			0x61160
-#define DVOC_ON			(1<<31)
-#define LVDS			0x61180
-#define LVDS_ON			(1<<31)
-
-#define ADPA			0x61100
-#define ADPA_DPMS_MASK		(~(3<<10))
-#define ADPA_DPMS_ON		(0<<10)
-#define ADPA_DPMS_SUSPEND	(1<<10)
-#define ADPA_DPMS_STANDBY	(2<<10)
-#define ADPA_DPMS_OFF		(3<<10)
-
-#define NOPID                   0x2094
-#define LP_RING			0x2030
-#define HP_RING			0x2040
-/* The binner has its own ring buffer:
- */
-#define HWB_RING		0x2400
-
-#define RING_TAIL		0x00
-#define TAIL_ADDR		0x001FFFF8
-#define RING_HEAD		0x04
-#define HEAD_WRAP_COUNT		0xFFE00000
-#define HEAD_WRAP_ONE		0x00200000
-#define HEAD_ADDR		0x001FFFFC
-#define RING_START		0x08
-#define START_ADDR		0x0xFFFFF000
-#define RING_LEN		0x0C
-#define RING_NR_PAGES		0x001FF000
-#define RING_REPORT_MASK	0x00000006
-#define RING_REPORT_64K		0x00000002
-#define RING_REPORT_128K	0x00000004
-#define RING_NO_REPORT		0x00000000
-#define RING_VALID_MASK		0x00000001
-#define RING_VALID		0x00000001
-#define RING_INVALID		0x00000000
-
-/* Instruction parser error reg:
- */
-#define IPEIR			0x2088
-
-/* Scratch pad debug 0 reg:
- */
-#define SCPD0			0x209c
-
-/* Error status reg:
- */
-#define ESR			0x20b8
-
-/* Secondary DMA fetch address debug reg:
- */
-#define DMA_FADD_S		0x20d4
-
-/* Memory Interface Arbitration State
- */
-#define MI_ARB_STATE		0x20e4
-
-/* Cache mode 0 reg.
- *  - Manipulating render cache behaviour is central
- *    to the concept of zone rendering, tuning this reg can help avoid
- *    unnecessary render cache reads and even writes (for z/stencil)
- *    at beginning and end of scene.
+/**
+ * Reads a dword out of the status page, which is written to from the command
+ * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
+ * MI_STORE_DATA_IMM.
  *
- * - To change a bit, write to this reg with a mask bit set and the
- * bit of interest either set or cleared.  EG: (BIT<<16) | BIT to set.
+ * The following dwords have a reserved meaning:
+ * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
+ * 0x04: ring 0 head pointer
+ * 0x05: ring 1 head pointer (915-class)
+ * 0x06: ring 2 head pointer (915-class)
+ * 0x10-0x1b: Context status DWords (GM45)
+ * 0x1f: Last written status offset. (GM45)
+ *
+ * The area from dword 0x20 to 0x3ff is available for driver usage.
  */
-#define Cache_Mode_0		0x2120
-#define CACHE_MODE_0		0x2120
-#define CM0_MASK_SHIFT          16
-#define CM0_IZ_OPT_DISABLE      (1<<6)
-#define CM0_ZR_OPT_DISABLE      (1<<5)
-#define CM0_DEPTH_EVICT_DISABLE (1<<4)
-#define CM0_COLOR_EVICT_DISABLE (1<<3)
-#define CM0_DEPTH_WRITE_DISABLE (1<<1)
-#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
-
-
-/* Graphics flush control.  A CPU write flushes the GWB of all writes.
- * The data is discarded.
- */
-#define GFX_FLSH_CNTL		0x2170
-
-/* Binner control.  Defines the location of the bin pointer list:
- */
-#define BINCTL			0x2420
-#define BC_MASK			(1 << 9)
-
-/* Binned scene info.
- */
-#define BINSCENE		0x2428
-#define BS_OP_LOAD		(1 << 8)
-#define BS_MASK			(1 << 22)
-
-/* Bin command parser debug reg:
- */
-#define BCPD			0x2480
-
-/* Bin memory control debug reg:
- */
-#define BMCD			0x2484
-
-/* Bin data cache debug reg:
- */
-#define BDCD			0x2488
-
-/* Binner pointer cache debug reg:
- */
-#define BPCD			0x248c
-
-/* Binner scratch pad debug reg:
- */
-#define BINSKPD			0x24f0
-
-/* HWB scratch pad debug reg:
- */
-#define HWBSKPD			0x24f4
-
-/* Binner memory pool reg:
- */
-#define BMP_BUFFER		0x2430
-#define BMP_PAGE_SIZE_4K	(0 << 10)
-#define BMP_BUFFER_SIZE_SHIFT	1
-#define BMP_ENABLE		(1 << 0)
-
-/* Get/put memory from the binner memory pool:
- */
-#define BMP_GET			0x2438
-#define BMP_PUT			0x2440
-#define BMP_OFFSET_SHIFT	5
-
-/* 3D state packets:
- */
-#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
-
-#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR       (0x1<<1)
-#define SC_ENABLE_MASK          (0x1<<0)
-#define SC_ENABLE               (0x1<<0)
-
-#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
-
-#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK      (0xffff<<16)
-#define SCI_XMIN_MASK      (0xffff<<0)
-#define SCI_YMAX_MASK      (0xffff<<16)
-#define SCI_XMAX_MASK      (0xffff<<0)
-
-#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-
-#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
-
-#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
-#define XY_SRC_COPY_BLT_CMD		((2<<29)|(0x53<<22)|6)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB	(1<<20)
-#define XY_SRC_COPY_BLT_SRC_TILED	(1<<15)
-#define XY_SRC_COPY_BLT_DST_TILED	(1<<11)
-
-#define MI_BATCH_BUFFER		((0x30<<23)|1)
-#define MI_BATCH_BUFFER_START	(0x31<<23)
-#define MI_BATCH_BUFFER_END	(0xA<<23)
-#define MI_BATCH_NON_SECURE	(1)
-#define MI_BATCH_NON_SECURE_I965 (1<<8)
-
-#define MI_WAIT_FOR_EVENT       ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
-#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-
-#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
-
-#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-#define ASYNC_FLIP                (1<<22)
-#define DISPLAY_PLANE_A           (0<<20)
-#define DISPLAY_PLANE_B           (1<<20)
-
-/* Display regs */
-#define DSPACNTR                0x70180
-#define DSPBCNTR                0x71180
-#define DISPPLANE_SEL_PIPE_MASK                 (1<<24)
-
-/* Define the region of interest for the binner:
- */
-#define CMD_OP_BIN_CONTROL	 ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
-
-#define CMD_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-
-#define CMD_MI_FLUSH         (0x04 << 23)
-#define MI_NO_WRITE_FLUSH    (1 << 2)
-#define MI_READ_FLUSH        (1 << 0)
-#define MI_EXE_FLUSH         (1 << 1)
-#define MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
-#define MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
-
-#define BREADCRUMB_BITS 31
-#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
-
-#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
 #define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
+#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5)
+#define I915_GEM_HWS_INDEX		0x20
 
-#define BLC_PWM_CTL		0x61254
-#define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
-
-#define BLC_PWM_CTL2		0x61250
-/**
- * This is the most significant 15 bits of the number of backlight cycles in a
- * complete cycle of the modulated backlight control.
- *
- * The actual value is this field multiplied by two.
- */
-#define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
-#define BLM_LEGACY_MODE				(1 << 16)
-/**
- * This is the number of cycles out of the backlight modulation cycle for which
- * the backlight is on.
- *
- * This field must be no greater than the number of cycles in the complete
- * backlight modulation cycle.
- */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
-#define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
-
-#define I915_GCFGC			0xf0
-#define I915_LOW_FREQUENCY_ENABLE		(1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ		(0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ		(4 << 4)
-#define I915_DISPLAY_CLOCK_MASK			(7 << 4)
-
-#define I855_HPLLCC			0xc0
-#define I855_CLOCK_CONTROL_MASK			(3 << 0)
-#define I855_CLOCK_133_200			(0 << 0)
-#define I855_CLOCK_100_200			(1 << 0)
-#define I855_CLOCK_100_133			(2 << 0)
-#define I855_CLOCK_166_250			(3 << 0)
-
-/* p317, 319
- */
-#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
-#define VCLK2_VCO_N        0x600a
-#define VCLK2_VCO_DIV_SEL  0x6012
-
-#define VCLK_DIVISOR_VGA0   0x6000
-#define VCLK_DIVISOR_VGA1   0x6004
-#define VCLK_POST_DIV	    0x6010
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA1_PD_P2_DIV_4	(1 << 15)
-/** Overrides the p2 post divisor field */
-# define VGA1_PD_P1_DIV_2	(1 << 13)
-# define VGA1_PD_P1_SHIFT	8
-/** P1 value is 2 greater than this field */
-# define VGA1_PD_P1_MASK	(0x1f << 8)
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA0_PD_P2_DIV_4	(1 << 7)
-/** Overrides the p2 post divisor field */
-# define VGA0_PD_P1_DIV_2	(1 << 5)
-# define VGA0_PD_P1_SHIFT	0
-/** P1 value is 2 greater than this field */
-# define VGA0_PD_P1_MASK	(0x1f << 0)
-
-/* PCI D state control register */
-#define D_STATE		0x6104
-#define DSPCLK_GATE_D	0x6200
-
-/* I830 CRTC registers */
-#define HTOTAL_A	0x60000
-#define HBLANK_A	0x60004
-#define HSYNC_A		0x60008
-#define VTOTAL_A	0x6000c
-#define VBLANK_A	0x60010
-#define VSYNC_A		0x60014
-#define PIPEASRC	0x6001c
-#define BCLRPAT_A	0x60020
-#define VSYNCSHIFT_A	0x60028
-
-#define HTOTAL_B	0x61000
-#define HBLANK_B	0x61004
-#define HSYNC_B		0x61008
-#define VTOTAL_B	0x6100c
-#define VBLANK_B	0x61010
-#define VSYNC_B		0x61014
-#define PIPEBSRC	0x6101c
-#define BCLRPAT_B	0x61020
-#define VSYNCSHIFT_B	0x61028
-
-#define PP_STATUS	0x61200
-# define PP_ON					(1 << 31)
-/**
- * Indicates that all dependencies of the panel are on:
- *
- * - PLL enabled
- * - pipe enabled
- * - LVDS/DVOB/DVOC on
- */
-# define PP_READY				(1 << 30)
-# define PP_SEQUENCE_NONE			(0 << 28)
-# define PP_SEQUENCE_ON				(1 << 28)
-# define PP_SEQUENCE_OFF			(2 << 28)
-# define PP_SEQUENCE_MASK			0x30000000
-#define PP_CONTROL	0x61204
-# define POWER_TARGET_ON			(1 << 0)
-
-#define LVDSPP_ON       0x61208
-#define LVDSPP_OFF      0x6120c
-#define PP_CYCLE        0x61210
-
-#define PFIT_CONTROL	0x61230
-# define PFIT_ENABLE				(1 << 31)
-# define PFIT_PIPE_MASK				(3 << 29)
-# define PFIT_PIPE_SHIFT			29
-# define VERT_INTERP_DISABLE			(0 << 10)
-# define VERT_INTERP_BILINEAR			(1 << 10)
-# define VERT_INTERP_MASK			(3 << 10)
-# define VERT_AUTO_SCALE			(1 << 9)
-# define HORIZ_INTERP_DISABLE			(0 << 6)
-# define HORIZ_INTERP_BILINEAR			(1 << 6)
-# define HORIZ_INTERP_MASK			(3 << 6)
-# define HORIZ_AUTO_SCALE			(1 << 5)
-# define PANEL_8TO6_DITHER_ENABLE		(1 << 3)
-
-#define PFIT_PGM_RATIOS	0x61234
-# define PFIT_VERT_SCALE_MASK			0xfff00000
-# define PFIT_HORIZ_SCALE_MASK			0x0000fff0
-
-#define PFIT_AUTO_RATIOS	0x61238
-
-
-#define DPLL_A		0x06014
-#define DPLL_B		0x06018
-# define DPLL_VCO_ENABLE			(1 << 31)
-# define DPLL_DVO_HIGH_SPEED			(1 << 30)
-# define DPLL_SYNCLOCK_ENABLE			(1 << 29)
-# define DPLL_VGA_MODE_DIS			(1 << 28)
-# define DPLLB_MODE_DAC_SERIAL			(1 << 26) /* i915 */
-# define DPLLB_MODE_LVDS			(2 << 26) /* i915 */
-# define DPLL_MODE_MASK				(3 << 26)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24) /* i915 */
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24) /* i915 */
-# define DPLL_P2_CLOCK_DIV_MASK			0x03000000 /* i915 */
-# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000 /* i915 */
-/**
- *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
-/**
- * The i830 generation, in LVDS mode, defines P1 as the bit number set within
- * this field (only one bit may be set).
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
-# define DPLL_FPA01_P1_POST_DIV_SHIFT		16
-# define PLL_P2_DIVIDE_BY_4			(1 << 23) /* i830, required in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO			(1 << 21) /* i830 */
-# define PLL_REF_INPUT_DREFCLK			(0 << 13)
-# define PLL_REF_INPUT_TVCLKINA			(1 << 13) /* i830 */
-# define PLL_REF_INPUT_TVCLKINBC		(2 << 13) /* SDVO TVCLKIN */
-# define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
-# define PLL_REF_INPUT_MASK			(3 << 13)
-# define PLL_LOAD_PULSE_PHASE_SHIFT		9
-/*
- * Parallel to Serial Load Pulse phase selection.
- * Selects the phase for the 10X DPLL clock for the PCIe
- * digital display port. The range is 4 to 13; 10 or more
- * is just a flip delay. The default is 6
- */
-# define PLL_LOAD_PULSE_PHASE_MASK		(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-# define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
-
-/**
- * SDVO multiplier for 945G/GM. Not used on 965.
- *
- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
- */
-# define SDVO_MULTIPLIER_MASK			0x000000ff
-# define SDVO_MULTIPLIER_SHIFT_HIRES		4
-# define SDVO_MULTIPLIER_SHIFT_VGA		0
-
-/** @defgroup DPLL_MD
- * @{
- */
-/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_A_MD		0x0601c
-/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_B_MD		0x06020
-/**
- * UDI pixel divider, controlling how many pixels are stuffed into a packet.
- *
- * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
- */
-# define DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
-# define DPLL_MD_UDI_DIVIDER_SHIFT		24
-/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-# define DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
-# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
-/**
- * SDVO/UDI pixel multiplier.
- *
- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
- * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
- * modes, the bus rate would be below the limits, so SDVO allows for stuffing
- * dummy bytes in the datastream at an increased clock rate, with both sides of
- * the link knowing how many bytes are fill.
- *
- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
- * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
- * through an SDVO command.
- *
- * This register field has values of multiplication factor minus 1, with
- * a maximum multiplier of 5 for SDVO.
- */
-# define DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
-# define DPLL_MD_UDI_MULTIPLIER_SHIFT		8
-/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
- * This best be set to the default value (3) or the CRT won't work. No,
- * I don't entirely understand what this does...
- */
-# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
-# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
-/** @} */
-
-#define DPLL_TEST		0x606c
-# define DPLLB_TEST_SDVO_DIV_1			(0 << 22)
-# define DPLLB_TEST_SDVO_DIV_2			(1 << 22)
-# define DPLLB_TEST_SDVO_DIV_4			(2 << 22)
-# define DPLLB_TEST_SDVO_DIV_MASK		(3 << 22)
-# define DPLLB_TEST_N_BYPASS			(1 << 19)
-# define DPLLB_TEST_M_BYPASS			(1 << 18)
-# define DPLLB_INPUT_BUFFER_ENABLE		(1 << 16)
-# define DPLLA_TEST_N_BYPASS			(1 << 3)
-# define DPLLA_TEST_M_BYPASS			(1 << 2)
-# define DPLLA_INPUT_BUFFER_ENABLE		(1 << 0)
-
-#define ADPA			0x61100
-#define ADPA_DAC_ENABLE		(1<<31)
-#define ADPA_DAC_DISABLE	0
-#define ADPA_PIPE_SELECT_MASK	(1<<30)
-#define ADPA_PIPE_A_SELECT	0
-#define ADPA_PIPE_B_SELECT	(1<<30)
-#define ADPA_USE_VGA_HVPOLARITY (1<<15)
-#define ADPA_SETS_HVPOLARITY	0
-#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
-#define ADPA_VSYNC_CNTL_ENABLE	0
-#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
-#define ADPA_HSYNC_CNTL_ENABLE	0
-#define ADPA_VSYNC_ACTIVE_HIGH	(1<<4)
-#define ADPA_VSYNC_ACTIVE_LOW	0
-#define ADPA_HSYNC_ACTIVE_HIGH	(1<<3)
-#define ADPA_HSYNC_ACTIVE_LOW	0
-
-#define FPA0		0x06040
-#define FPA1		0x06044
-#define FPB0		0x06048
-#define FPB1		0x0604c
-# define FP_N_DIV_MASK				0x003f0000
-# define FP_N_DIV_SHIFT				16
-# define FP_M1_DIV_MASK				0x00003f00
-# define FP_M1_DIV_SHIFT			8
-# define FP_M2_DIV_MASK				0x0000003f
-# define FP_M2_DIV_SHIFT			0
-
-
-#define PORT_HOTPLUG_EN		0x61110
-# define SDVOB_HOTPLUG_INT_EN			(1 << 26)
-# define SDVOC_HOTPLUG_INT_EN			(1 << 25)
-# define TV_HOTPLUG_INT_EN			(1 << 18)
-# define CRT_HOTPLUG_INT_EN			(1 << 9)
-# define CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
-
-#define PORT_HOTPLUG_STAT	0x61114
-# define CRT_HOTPLUG_INT_STATUS			(1 << 11)
-# define TV_HOTPLUG_INT_STATUS			(1 << 10)
-# define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
-# define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
-# define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
-# define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
-
-#define SDVOB			0x61140
-#define SDVOC			0x61160
-#define SDVO_ENABLE				(1 << 31)
-#define SDVO_PIPE_B_SELECT			(1 << 30)
-#define SDVO_STALL_SELECT			(1 << 29)
-#define SDVO_INTERRUPT_ENABLE			(1 << 26)
-/**
- * 915G/GM SDVO pixel multiplier.
- *
- * Programmed value is multiplier - 1, up to 5x.
- *
- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
- */
-#define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT		23
-#define SDVO_PHASE_SELECT_MASK			(15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
-#define SDVOC_GANG_MODE				(1 << 16)
-#define SDVO_BORDER_ENABLE			(1 << 7)
-#define SDVOB_PCIE_CONCURRENCY			(1 << 3)
-#define SDVO_DETECTED				(1 << 2)
-/* Bits to be preserved when writing */
-#define SDVOB_PRESERVE_MASK			((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK			(1 << 17)
-
-/** @defgroup LVDS
- * @{
- */
-/**
- * This register controls the LVDS output enable, pipe selection, and data
- * format selection.
- *
- * All of the clock/data pairs are force powered down by power sequencing.
- */
-#define LVDS			0x61180
-/**
- * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
- * the DPLL semantics change when the LVDS is assigned to that pipe.
- */
-# define LVDS_PORT_EN			(1 << 31)
-/** Selects pipe B for LVDS data.  Must be set on pre-965. */
-# define LVDS_PIPEB_SELECT		(1 << 30)
-
-/**
- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
- * pixel.
- */
-# define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
-# define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
-# define LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
-/**
- * Controls the A3 data pair, which contains the additional LSBs for 24 bit
- * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
- * on.
- */
-# define LVDS_A3_POWER_MASK		(3 << 6)
-# define LVDS_A3_POWER_DOWN		(0 << 6)
-# define LVDS_A3_POWER_UP		(3 << 6)
-/**
- * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
- * is set.
- */
-# define LVDS_CLKB_POWER_MASK		(3 << 4)
-# define LVDS_CLKB_POWER_DOWN		(0 << 4)
-# define LVDS_CLKB_POWER_UP		(3 << 4)
-
-/**
- * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
- * setting for whether we are in dual-channel mode.  The B3 pair will
- * additionally only be powered up when LVDS_A3_POWER_UP is set.
- */
-# define LVDS_B0B3_POWER_MASK		(3 << 2)
-# define LVDS_B0B3_POWER_DOWN		(0 << 2)
-# define LVDS_B0B3_POWER_UP		(3 << 2)
-
-#define PIPEACONF 0x70008
-#define PIPEACONF_ENABLE	(1<<31)
-#define PIPEACONF_DISABLE	0
-#define PIPEACONF_DOUBLE_WIDE	(1<<30)
-#define I965_PIPECONF_ACTIVE	(1<<30)
-#define PIPEACONF_SINGLE_WIDE	0
-#define PIPEACONF_PIPE_UNLOCKED 0
-#define PIPEACONF_PIPE_LOCKED	(1<<25)
-#define PIPEACONF_PALETTE	0
-#define PIPEACONF_GAMMA		(1<<24)
-#define PIPECONF_FORCE_BORDER	(1<<25)
-#define PIPECONF_PROGRESSIVE	(0 << 21)
-#define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
-#define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
-
-#define DSPARB	  0x70030
-#define DSPARB_CSTART_MASK	(0x7f << 7)
-#define DSPARB_CSTART_SHIFT	7
-#define DSPARB_BSTART_MASK	(0x7f)		 
-#define DSPARB_BSTART_SHIFT	0
-
-#define PIPEBCONF 0x71008
-#define PIPEBCONF_ENABLE	(1<<31)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_DOUBLE_WIDE	(1<<30)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_GAMMA		(1<<24)
-#define PIPEBCONF_PALETTE	0
-
-#define PIPEBGCMAXRED		0x71010
-#define PIPEBGCMAXGREEN		0x71014
-#define PIPEBGCMAXBLUE		0x71018
-#define PIPEBSTAT		0x71024
-#define PIPEBFRAMEHIGH		0x71040
-#define PIPEBFRAMEPIXEL		0x71044
-
-#define DSPACNTR		0x70180
-#define DSPBCNTR		0x71180
-#define DISPLAY_PLANE_ENABLE			(1<<31)
-#define DISPLAY_PLANE_DISABLE			0
-#define DISPPLANE_GAMMA_ENABLE			(1<<30)
-#define DISPPLANE_GAMMA_DISABLE			0
-#define DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
-#define DISPPLANE_8BPP				(0x2<<26)
-#define DISPPLANE_15_16BPP			(0x4<<26)
-#define DISPPLANE_16BPP				(0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA		(0x6<<26)
-#define DISPPLANE_32BPP				(0x7<<26)
-#define DISPPLANE_STEREO_ENABLE			(1<<25)
-#define DISPPLANE_STEREO_DISABLE		0
-#define DISPPLANE_SEL_PIPE_MASK			(1<<24)
-#define DISPPLANE_SEL_PIPE_A			0
-#define DISPPLANE_SEL_PIPE_B			(1<<24)
-#define DISPPLANE_SRC_KEY_ENABLE		(1<<22)
-#define DISPPLANE_SRC_KEY_DISABLE		0
-#define DISPPLANE_LINE_DOUBLE			(1<<20)
-#define DISPPLANE_NO_LINE_DOUBLE		0
-#define DISPPLANE_STEREO_POLARITY_FIRST		0
-#define DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
-/* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
-#define DISPPLANE_ALPHA_TRANS_DISABLE		0
-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA		0
-#define DISPPLANE_SPRITE_ABOVE_OVERLAY		(1)
-
-#define DSPABASE		0x70184
-#define DSPASTRIDE		0x70188
-
-#define DSPBBASE		0x71184
-#define DSPBADDR		DSPBBASE
-#define DSPBSTRIDE		0x71188
-
-#define DSPAKEYVAL		0x70194
-#define DSPAKEYMASK		0x70198
-
-#define DSPAPOS			0x7018C /* reserved */
-#define DSPASIZE		0x70190
-#define DSPBPOS			0x7118C
-#define DSPBSIZE		0x71190
-
-#define DSPASURF		0x7019C
-#define DSPATILEOFF		0x701A4
-
-#define DSPBSURF		0x7119C
-#define DSPBTILEOFF		0x711A4
-
-#define VGACNTRL		0x71400
-# define VGA_DISP_DISABLE			(1 << 31)
-# define VGA_2X_MODE				(1 << 30)
-# define VGA_PIPE_B_SELECT			(1 << 29)
-
-/*
- * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
- * of video memory available to the BIOS in SWF1.
- */
-
-#define SWF0			0x71410
-
-/*
- * 855 scratch registers.
- */
-#define SWF10			0x70410
-
-#define SWF30			0x72414
-
-/*
- * Overlay registers.  These are overlay registers accessed via MMIO.
- * Those loaded via the overlay register page are defined in i830_video.c.
- */
-#define OVADD			0x30000
-
-#define DOVSTA			0x30008
-#define OC_BUF			(0x3<<20)
-
-#define OGAMC5			0x30010
-#define OGAMC4			0x30014
-#define OGAMC3			0x30018
-#define OGAMC2			0x3001c
-#define OGAMC1			0x30020
-#define OGAMC0			0x30024
-/*
- * Palette registers
- */
-#define PALETTE_A		0x0a000
-#define PALETTE_B		0x0a800
+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 #define IS_I830(dev) ((dev)->pci_device == 0x3577)
 #define IS_845G(dev) ((dev)->pci_device == 0x2562)
@@ -1119,7 +639,7 @@
 
 #define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
 
-#define IS_IGD_GM(dev) ((dev)->pci_device == 0x2A42)
+#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
 
 #define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
 		     (dev)->pci_device == 0x2E12 || \
@@ -1133,9 +653,9 @@
 		      IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
 
 #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
-			IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev))
+			IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))
 
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_IGD_GM(dev) || IS_G4X(dev))
+#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
 
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
new file mode 100644
index 0000000..9ac73dd
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -0,0 +1,2558 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include <linux/swap.h>
+
+static int
+i915_gem_object_set_domain(struct drm_gem_object *obj,
+			    uint32_t read_domains,
+			    uint32_t write_domain);
+static int
+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
+				 uint64_t offset,
+				 uint64_t size,
+				 uint32_t read_domains,
+				 uint32_t write_domain);
+static int
+i915_gem_set_domain(struct drm_gem_object *obj,
+		    struct drm_file *file_priv,
+		    uint32_t read_domains,
+		    uint32_t write_domain);
+static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
+static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
+static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
+
+static void
+i915_gem_cleanup_ringbuffer(struct drm_device *dev);
+
+int
+i915_gem_init_ioctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_init *args = data;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (args->gtt_start >= args->gtt_end ||
+	    (args->gtt_start & (PAGE_SIZE - 1)) != 0 ||
+	    (args->gtt_end & (PAGE_SIZE - 1)) != 0) {
+		mutex_unlock(&dev->struct_mutex);
+		return -EINVAL;
+	}
+
+	drm_mm_init(&dev_priv->mm.gtt_space, args->gtt_start,
+	    args->gtt_end - args->gtt_start);
+
+	dev->gtt_total = (uint32_t) (args->gtt_end - args->gtt_start);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+
+/**
+ * Creates a new mm object and returns a handle to it.
+ */
+int
+i915_gem_create_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct drm_i915_gem_create *args = data;
+	struct drm_gem_object *obj;
+	int handle, ret;
+
+	args->size = roundup(args->size, PAGE_SIZE);
+
+	/* Allocate the new object */
+	obj = drm_gem_object_alloc(dev, args->size);
+	if (obj == NULL)
+		return -ENOMEM;
+
+	ret = drm_gem_handle_create(file_priv, obj, &handle);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	if (ret)
+		return ret;
+
+	args->handle = handle;
+
+	return 0;
+}
+
+/**
+ * Reads data from the object referenced by handle.
+ *
+ * On error, the contents of *data are undefined.
+ */
+int
+i915_gem_pread_ioctl(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv)
+{
+	struct drm_i915_gem_pread *args = data;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	ssize_t read;
+	loff_t offset;
+	int ret;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EBADF;
+	obj_priv = obj->driver_private;
+
+	/* Bounds check source.
+	 *
+	 * XXX: This could use review for overflow issues...
+	 */
+	if (args->offset > obj->size || args->size > obj->size ||
+	    args->offset + args->size > obj->size) {
+		drm_gem_object_unreference(obj);
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+
+	ret = i915_gem_object_set_domain_range(obj, args->offset, args->size,
+					       I915_GEM_DOMAIN_CPU, 0);
+	if (ret != 0) {
+		drm_gem_object_unreference(obj);
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+
+	offset = args->offset;
+
+	read = vfs_read(obj->filp, (char __user *)(uintptr_t)args->data_ptr,
+			args->size, &offset);
+	if (read != args->size) {
+		drm_gem_object_unreference(obj);
+		mutex_unlock(&dev->struct_mutex);
+		if (read < 0)
+			return read;
+		else
+			return -EINVAL;
+	}
+
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+static int
+i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+		    struct drm_i915_gem_pwrite *args,
+		    struct drm_file *file_priv)
+{
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	ssize_t remain;
+	loff_t offset;
+	char __user *user_data;
+	char __iomem *vaddr;
+	char *vaddr_atomic;
+	int i, o, l;
+	int ret = 0;
+	unsigned long pfn;
+	unsigned long unwritten;
+
+	user_data = (char __user *) (uintptr_t) args->data_ptr;
+	remain = args->size;
+	if (!access_ok(VERIFY_READ, user_data, remain))
+		return -EFAULT;
+
+
+	mutex_lock(&dev->struct_mutex);
+	ret = i915_gem_object_pin(obj, 0);
+	if (ret) {
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+	ret = i915_gem_set_domain(obj, file_priv,
+				  I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+	if (ret)
+		goto fail;
+
+	obj_priv = obj->driver_private;
+	offset = obj_priv->gtt_offset + args->offset;
+	obj_priv->dirty = 1;
+
+	while (remain > 0) {
+		/* Operation in this page
+		 *
+		 * i = page number
+		 * o = offset within page
+		 * l = bytes to copy
+		 */
+		i = offset >> PAGE_SHIFT;
+		o = offset & (PAGE_SIZE-1);
+		l = remain;
+		if ((o + l) > PAGE_SIZE)
+			l = PAGE_SIZE - o;
+
+		pfn = (dev->agp->base >> PAGE_SHIFT) + i;
+
+#ifdef CONFIG_HIGHMEM
+		/* This is a workaround for the low performance of iounmap
+		 * (approximate 10% cpu cost on normal 3D workloads).
+		 * kmap_atomic on HIGHMEM kernels happens to let us map card
+		 * memory without taking IPIs.  When the vmap rework lands
+		 * we should be able to dump this hack.
+		 */
+		vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0);
+#if WATCH_PWRITE
+		DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
+			 i, o, l, pfn, vaddr_atomic);
+#endif
+		unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o,
+							      user_data, l);
+		kunmap_atomic(vaddr_atomic, KM_USER0);
+
+		if (unwritten)
+#endif /* CONFIG_HIGHMEM */
+		{
+			vaddr = ioremap_wc(pfn << PAGE_SHIFT, PAGE_SIZE);
+#if WATCH_PWRITE
+			DRM_INFO("pwrite slow i %d o %d l %d "
+				 "pfn %ld vaddr %p\n",
+				 i, o, l, pfn, vaddr);
+#endif
+			if (vaddr == NULL) {
+				ret = -EFAULT;
+				goto fail;
+			}
+			unwritten = __copy_from_user(vaddr + o, user_data, l);
+#if WATCH_PWRITE
+			DRM_INFO("unwritten %ld\n", unwritten);
+#endif
+			iounmap(vaddr);
+			if (unwritten) {
+				ret = -EFAULT;
+				goto fail;
+			}
+		}
+
+		remain -= l;
+		user_data += l;
+		offset += l;
+	}
+#if WATCH_PWRITE && 1
+	i915_gem_clflush_object(obj);
+	i915_gem_dump_object(obj, args->offset + args->size, __func__, ~0);
+	i915_gem_clflush_object(obj);
+#endif
+
+fail:
+	i915_gem_object_unpin(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static int
+i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+		      struct drm_i915_gem_pwrite *args,
+		      struct drm_file *file_priv)
+{
+	int ret;
+	loff_t offset;
+	ssize_t written;
+
+	mutex_lock(&dev->struct_mutex);
+
+	ret = i915_gem_set_domain(obj, file_priv,
+				  I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+	if (ret) {
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+
+	offset = args->offset;
+
+	written = vfs_write(obj->filp,
+			    (char __user *)(uintptr_t) args->data_ptr,
+			    args->size, &offset);
+	if (written != args->size) {
+		mutex_unlock(&dev->struct_mutex);
+		if (written < 0)
+			return written;
+		else
+			return -EINVAL;
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+/**
+ * Writes data to the object referenced by handle.
+ *
+ * On error, the contents of the buffer that were to be modified are undefined.
+ */
+int
+i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct drm_i915_gem_pwrite *args = data;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret = 0;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EBADF;
+	obj_priv = obj->driver_private;
+
+	/* Bounds check destination.
+	 *
+	 * XXX: This could use review for overflow issues...
+	 */
+	if (args->offset > obj->size || args->size > obj->size ||
+	    args->offset + args->size > obj->size) {
+		drm_gem_object_unreference(obj);
+		return -EINVAL;
+	}
+
+	/* We can only do the GTT pwrite on untiled buffers, as otherwise
+	 * it would end up going through the fenced access, and we'll get
+	 * different detiling behavior between reading and writing.
+	 * pread/pwrite currently are reading and writing from the CPU
+	 * perspective, requiring manual detiling by the client.
+	 */
+	if (obj_priv->tiling_mode == I915_TILING_NONE &&
+	    dev->gtt_total != 0)
+		ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
+	else
+		ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
+
+#if WATCH_PWRITE
+	if (ret)
+		DRM_INFO("pwrite failed %d\n", ret);
+#endif
+
+	drm_gem_object_unreference(obj);
+
+	return ret;
+}
+
+/**
+ * Called when user space prepares to use an object
+ */
+int
+i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	struct drm_i915_gem_set_domain *args = data;
+	struct drm_gem_object *obj;
+	int ret;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EBADF;
+
+	mutex_lock(&dev->struct_mutex);
+#if WATCH_BUF
+	DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
+		 obj, obj->size, args->read_domains, args->write_domain);
+#endif
+	ret = i915_gem_set_domain(obj, file_priv,
+				  args->read_domains, args->write_domain);
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+/**
+ * Called when user space has done writes to this buffer
+ */
+int
+i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct drm_i915_gem_sw_finish *args = data;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret = 0;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	mutex_lock(&dev->struct_mutex);
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL) {
+		mutex_unlock(&dev->struct_mutex);
+		return -EBADF;
+	}
+
+#if WATCH_BUF
+	DRM_INFO("%s: sw_finish %d (%p %d)\n",
+		 __func__, args->handle, obj, obj->size);
+#endif
+	obj_priv = obj->driver_private;
+
+	/* Pinned buffers may be scanout, so flush the cache */
+	if ((obj->write_domain & I915_GEM_DOMAIN_CPU) && obj_priv->pin_count) {
+		i915_gem_clflush_object(obj);
+		drm_agp_chipset_flush(dev);
+	}
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+/**
+ * Maps the contents of an object, returning the address it is mapped
+ * into.
+ *
+ * While the mapping holds a reference on the contents of the object, it doesn't
+ * imply a ref on the object itself.
+ */
+int
+i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv)
+{
+	struct drm_i915_gem_mmap *args = data;
+	struct drm_gem_object *obj;
+	loff_t offset;
+	unsigned long addr;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EBADF;
+
+	offset = args->offset;
+
+	down_write(&current->mm->mmap_sem);
+	addr = do_mmap(obj->filp, 0, args->size,
+		       PROT_READ | PROT_WRITE, MAP_SHARED,
+		       args->offset);
+	up_write(&current->mm->mmap_sem);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+	if (IS_ERR((void *)addr))
+		return addr;
+
+	args->addr_ptr = (uint64_t) addr;
+
+	return 0;
+}
+
+static void
+i915_gem_object_free_page_list(struct drm_gem_object *obj)
+{
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int page_count = obj->size / PAGE_SIZE;
+	int i;
+
+	if (obj_priv->page_list == NULL)
+		return;
+
+
+	for (i = 0; i < page_count; i++)
+		if (obj_priv->page_list[i] != NULL) {
+			if (obj_priv->dirty)
+				set_page_dirty(obj_priv->page_list[i]);
+			mark_page_accessed(obj_priv->page_list[i]);
+			page_cache_release(obj_priv->page_list[i]);
+		}
+	obj_priv->dirty = 0;
+
+	drm_free(obj_priv->page_list,
+		 page_count * sizeof(struct page *),
+		 DRM_MEM_DRIVER);
+	obj_priv->page_list = NULL;
+}
+
+static void
+i915_gem_object_move_to_active(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+	/* Add a reference if we're newly entering the active list. */
+	if (!obj_priv->active) {
+		drm_gem_object_reference(obj);
+		obj_priv->active = 1;
+	}
+	/* Move from whatever list we were on to the tail of execution. */
+	list_move_tail(&obj_priv->list,
+		       &dev_priv->mm.active_list);
+}
+
+
+static void
+i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+	if (obj_priv->pin_count != 0)
+		list_del_init(&obj_priv->list);
+	else
+		list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
+
+	if (obj_priv->active) {
+		obj_priv->active = 0;
+		drm_gem_object_unreference(obj);
+	}
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+}
+
+/**
+ * Creates a new sequence number, emitting a write of it to the status page
+ * plus an interrupt, which will trigger i915_user_interrupt_handler.
+ *
+ * Must be called with struct_lock held.
+ *
+ * Returned sequence numbers are nonzero on success.
+ */
+static uint32_t
+i915_add_request(struct drm_device *dev, uint32_t flush_domains)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_request *request;
+	uint32_t seqno;
+	int was_empty;
+	RING_LOCALS;
+
+	request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
+	if (request == NULL)
+		return 0;
+
+	/* Grab the seqno we're going to make this request be, and bump the
+	 * next (skipping 0 so it can be the reserved no-seqno value).
+	 */
+	seqno = dev_priv->mm.next_gem_seqno;
+	dev_priv->mm.next_gem_seqno++;
+	if (dev_priv->mm.next_gem_seqno == 0)
+		dev_priv->mm.next_gem_seqno++;
+
+	BEGIN_LP_RING(4);
+	OUT_RING(MI_STORE_DWORD_INDEX);
+	OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+	OUT_RING(seqno);
+
+	OUT_RING(MI_USER_INTERRUPT);
+	ADVANCE_LP_RING();
+
+	DRM_DEBUG("%d\n", seqno);
+
+	request->seqno = seqno;
+	request->emitted_jiffies = jiffies;
+	request->flush_domains = flush_domains;
+	was_empty = list_empty(&dev_priv->mm.request_list);
+	list_add_tail(&request->list, &dev_priv->mm.request_list);
+
+	if (was_empty && !dev_priv->mm.suspended)
+		schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+	return seqno;
+}
+
+/**
+ * Command execution barrier
+ *
+ * Ensures that all commands in the ring are finished
+ * before signalling the CPU
+ */
+static uint32_t
+i915_retire_commands(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+	uint32_t flush_domains = 0;
+	RING_LOCALS;
+
+	/* The sampler always gets flushed on i965 (sigh) */
+	if (IS_I965G(dev))
+		flush_domains |= I915_GEM_DOMAIN_SAMPLER;
+	BEGIN_LP_RING(2);
+	OUT_RING(cmd);
+	OUT_RING(0); /* noop */
+	ADVANCE_LP_RING();
+	return flush_domains;
+}
+
+/**
+ * Moves buffers associated only with the given active seqno from the active
+ * to inactive list, potentially freeing them.
+ */
+static void
+i915_gem_retire_request(struct drm_device *dev,
+			struct drm_i915_gem_request *request)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	/* Move any buffers on the active list that are no longer referenced
+	 * by the ringbuffer to the flushing/inactive lists as appropriate.
+	 */
+	while (!list_empty(&dev_priv->mm.active_list)) {
+		struct drm_gem_object *obj;
+		struct drm_i915_gem_object *obj_priv;
+
+		obj_priv = list_first_entry(&dev_priv->mm.active_list,
+					    struct drm_i915_gem_object,
+					    list);
+		obj = obj_priv->obj;
+
+		/* If the seqno being retired doesn't match the oldest in the
+		 * list, then the oldest in the list must still be newer than
+		 * this seqno.
+		 */
+		if (obj_priv->last_rendering_seqno != request->seqno)
+			return;
+#if WATCH_LRU
+		DRM_INFO("%s: retire %d moves to inactive list %p\n",
+			 __func__, request->seqno, obj);
+#endif
+
+		if (obj->write_domain != 0) {
+			list_move_tail(&obj_priv->list,
+				       &dev_priv->mm.flushing_list);
+		} else {
+			i915_gem_object_move_to_inactive(obj);
+		}
+	}
+
+	if (request->flush_domains != 0) {
+		struct drm_i915_gem_object *obj_priv, *next;
+
+		/* Clear the write domain and activity from any buffers
+		 * that are just waiting for a flush matching the one retired.
+		 */
+		list_for_each_entry_safe(obj_priv, next,
+					 &dev_priv->mm.flushing_list, list) {
+			struct drm_gem_object *obj = obj_priv->obj;
+
+			if (obj->write_domain & request->flush_domains) {
+				obj->write_domain = 0;
+				i915_gem_object_move_to_inactive(obj);
+			}
+		}
+
+	}
+}
+
+/**
+ * Returns true if seq1 is later than seq2.
+ */
+static int
+i915_seqno_passed(uint32_t seq1, uint32_t seq2)
+{
+	return (int32_t)(seq1 - seq2) >= 0;
+}
+
+uint32_t
+i915_get_gem_seqno(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
+}
+
+/**
+ * This function clears the request list as sequence numbers are passed.
+ */
+void
+i915_gem_retire_requests(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t seqno;
+
+	seqno = i915_get_gem_seqno(dev);
+
+	while (!list_empty(&dev_priv->mm.request_list)) {
+		struct drm_i915_gem_request *request;
+		uint32_t retiring_seqno;
+
+		request = list_first_entry(&dev_priv->mm.request_list,
+					   struct drm_i915_gem_request,
+					   list);
+		retiring_seqno = request->seqno;
+
+		if (i915_seqno_passed(seqno, retiring_seqno) ||
+		    dev_priv->mm.wedged) {
+			i915_gem_retire_request(dev, request);
+
+			list_del(&request->list);
+			drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
+		} else
+			break;
+	}
+}
+
+void
+i915_gem_retire_work_handler(struct work_struct *work)
+{
+	drm_i915_private_t *dev_priv;
+	struct drm_device *dev;
+
+	dev_priv = container_of(work, drm_i915_private_t,
+				mm.retire_work.work);
+	dev = dev_priv->dev;
+
+	mutex_lock(&dev->struct_mutex);
+	i915_gem_retire_requests(dev);
+	if (!dev_priv->mm.suspended &&
+	    !list_empty(&dev_priv->mm.request_list))
+		schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+	mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
+static int
+i915_wait_request(struct drm_device *dev, uint32_t seqno)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret = 0;
+
+	BUG_ON(seqno == 0);
+
+	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
+		dev_priv->mm.waiting_gem_seqno = seqno;
+		i915_user_irq_get(dev);
+		ret = wait_event_interruptible(dev_priv->irq_queue,
+					       i915_seqno_passed(i915_get_gem_seqno(dev),
+								 seqno) ||
+					       dev_priv->mm.wedged);
+		i915_user_irq_put(dev);
+		dev_priv->mm.waiting_gem_seqno = 0;
+	}
+	if (dev_priv->mm.wedged)
+		ret = -EIO;
+
+	if (ret && ret != -ERESTARTSYS)
+		DRM_ERROR("%s returns %d (awaiting %d at %d)\n",
+			  __func__, ret, seqno, i915_get_gem_seqno(dev));
+
+	/* Directly dispatch request retiring.  While we have the work queue
+	 * to handle this, the waiter on a request often wants an associated
+	 * buffer to have made it to the inactive list, and we would need
+	 * a separate wait queue to handle that.
+	 */
+	if (ret == 0)
+		i915_gem_retire_requests(dev);
+
+	return ret;
+}
+
+static void
+i915_gem_flush(struct drm_device *dev,
+	       uint32_t invalidate_domains,
+	       uint32_t flush_domains)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t cmd;
+	RING_LOCALS;
+
+#if WATCH_EXEC
+	DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
+		  invalidate_domains, flush_domains);
+#endif
+
+	if (flush_domains & I915_GEM_DOMAIN_CPU)
+		drm_agp_chipset_flush(dev);
+
+	if ((invalidate_domains | flush_domains) & ~(I915_GEM_DOMAIN_CPU |
+						     I915_GEM_DOMAIN_GTT)) {
+		/*
+		 * read/write caches:
+		 *
+		 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
+		 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
+		 * also flushed at 2d versus 3d pipeline switches.
+		 *
+		 * read-only caches:
+		 *
+		 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
+		 * MI_READ_FLUSH is set, and is always flushed on 965.
+		 *
+		 * I915_GEM_DOMAIN_COMMAND may not exist?
+		 *
+		 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
+		 * invalidated when MI_EXE_FLUSH is set.
+		 *
+		 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
+		 * invalidated with every MI_FLUSH.
+		 *
+		 * TLBs:
+		 *
+		 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
+		 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
+		 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
+		 * are flushed at any MI_FLUSH.
+		 */
+
+		cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+		if ((invalidate_domains|flush_domains) &
+		    I915_GEM_DOMAIN_RENDER)
+			cmd &= ~MI_NO_WRITE_FLUSH;
+		if (!IS_I965G(dev)) {
+			/*
+			 * On the 965, the sampler cache always gets flushed
+			 * and this bit is reserved.
+			 */
+			if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
+				cmd |= MI_READ_FLUSH;
+		}
+		if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
+			cmd |= MI_EXE_FLUSH;
+
+#if WATCH_EXEC
+		DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
+#endif
+		BEGIN_LP_RING(2);
+		OUT_RING(cmd);
+		OUT_RING(0); /* noop */
+		ADVANCE_LP_RING();
+	}
+}
+
+/**
+ * Ensures that all rendering to the object has completed and the object is
+ * safe to unbind from the GTT or access from the CPU.
+ */
+static int
+i915_gem_object_wait_rendering(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int ret;
+
+	/* If there are writes queued to the buffer, flush and
+	 * create a new seqno to wait for.
+	 */
+	if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) {
+		uint32_t write_domain = obj->write_domain;
+#if WATCH_BUF
+		DRM_INFO("%s: flushing object %p from write domain %08x\n",
+			  __func__, obj, write_domain);
+#endif
+		i915_gem_flush(dev, 0, write_domain);
+
+		i915_gem_object_move_to_active(obj);
+		obj_priv->last_rendering_seqno = i915_add_request(dev,
+								  write_domain);
+		BUG_ON(obj_priv->last_rendering_seqno == 0);
+#if WATCH_LRU
+		DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj);
+#endif
+	}
+
+	/* If there is rendering queued on the buffer being evicted, wait for
+	 * it.
+	 */
+	if (obj_priv->active) {
+#if WATCH_BUF
+		DRM_INFO("%s: object %p wait for seqno %08x\n",
+			  __func__, obj, obj_priv->last_rendering_seqno);
+#endif
+		ret = i915_wait_request(dev, obj_priv->last_rendering_seqno);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * Unbinds an object from the GTT aperture.
+ */
+static int
+i915_gem_object_unbind(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int ret = 0;
+
+#if WATCH_BUF
+	DRM_INFO("%s:%d %p\n", __func__, __LINE__, obj);
+	DRM_INFO("gtt_space %p\n", obj_priv->gtt_space);
+#endif
+	if (obj_priv->gtt_space == NULL)
+		return 0;
+
+	if (obj_priv->pin_count != 0) {
+		DRM_ERROR("Attempting to unbind pinned buffer\n");
+		return -EINVAL;
+	}
+
+	/* Wait for any rendering to complete
+	 */
+	ret = i915_gem_object_wait_rendering(obj);
+	if (ret) {
+		DRM_ERROR("wait_rendering failed: %d\n", ret);
+		return ret;
+	}
+
+	/* Move the object to the CPU domain to ensure that
+	 * any possible CPU writes while it's not in the GTT
+	 * are flushed when we go to remap it. This will
+	 * also ensure that all pending GPU writes are finished
+	 * before we unbind.
+	 */
+	ret = i915_gem_object_set_domain(obj, I915_GEM_DOMAIN_CPU,
+					 I915_GEM_DOMAIN_CPU);
+	if (ret) {
+		DRM_ERROR("set_domain failed: %d\n", ret);
+		return ret;
+	}
+
+	if (obj_priv->agp_mem != NULL) {
+		drm_unbind_agp(obj_priv->agp_mem);
+		drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
+		obj_priv->agp_mem = NULL;
+	}
+
+	BUG_ON(obj_priv->active);
+
+	i915_gem_object_free_page_list(obj);
+
+	if (obj_priv->gtt_space) {
+		atomic_dec(&dev->gtt_count);
+		atomic_sub(obj->size, &dev->gtt_memory);
+
+		drm_mm_put_block(obj_priv->gtt_space);
+		obj_priv->gtt_space = NULL;
+	}
+
+	/* Remove ourselves from the LRU list if present. */
+	if (!list_empty(&obj_priv->list))
+		list_del_init(&obj_priv->list);
+
+	return 0;
+}
+
+static int
+i915_gem_evict_something(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret = 0;
+
+	for (;;) {
+		/* If there's an inactive buffer available now, grab it
+		 * and be done.
+		 */
+		if (!list_empty(&dev_priv->mm.inactive_list)) {
+			obj_priv = list_first_entry(&dev_priv->mm.inactive_list,
+						    struct drm_i915_gem_object,
+						    list);
+			obj = obj_priv->obj;
+			BUG_ON(obj_priv->pin_count != 0);
+#if WATCH_LRU
+			DRM_INFO("%s: evicting %p\n", __func__, obj);
+#endif
+			BUG_ON(obj_priv->active);
+
+			/* Wait on the rendering and unbind the buffer. */
+			ret = i915_gem_object_unbind(obj);
+			break;
+		}
+
+		/* If we didn't get anything, but the ring is still processing
+		 * things, wait for one of those things to finish and hopefully
+		 * leave us a buffer to evict.
+		 */
+		if (!list_empty(&dev_priv->mm.request_list)) {
+			struct drm_i915_gem_request *request;
+
+			request = list_first_entry(&dev_priv->mm.request_list,
+						   struct drm_i915_gem_request,
+						   list);
+
+			ret = i915_wait_request(dev, request->seqno);
+			if (ret)
+				break;
+
+			/* if waiting caused an object to become inactive,
+			 * then loop around and wait for it. Otherwise, we
+			 * assume that waiting freed and unbound something,
+			 * so there should now be some space in the GTT
+			 */
+			if (!list_empty(&dev_priv->mm.inactive_list))
+				continue;
+			break;
+		}
+
+		/* If we didn't have anything on the request list but there
+		 * are buffers awaiting a flush, emit one and try again.
+		 * When we wait on it, those buffers waiting for that flush
+		 * will get moved to inactive.
+		 */
+		if (!list_empty(&dev_priv->mm.flushing_list)) {
+			obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
+						    struct drm_i915_gem_object,
+						    list);
+			obj = obj_priv->obj;
+
+			i915_gem_flush(dev,
+				       obj->write_domain,
+				       obj->write_domain);
+			i915_add_request(dev, obj->write_domain);
+
+			obj = NULL;
+			continue;
+		}
+
+		DRM_ERROR("inactive empty %d request empty %d "
+			  "flushing empty %d\n",
+			  list_empty(&dev_priv->mm.inactive_list),
+			  list_empty(&dev_priv->mm.request_list),
+			  list_empty(&dev_priv->mm.flushing_list));
+		/* If we didn't do any of the above, there's nothing to be done
+		 * and we just can't fit it in.
+		 */
+		return -ENOMEM;
+	}
+	return ret;
+}
+
+static int
+i915_gem_object_get_page_list(struct drm_gem_object *obj)
+{
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int page_count, i;
+	struct address_space *mapping;
+	struct inode *inode;
+	struct page *page;
+	int ret;
+
+	if (obj_priv->page_list)
+		return 0;
+
+	/* Get the list of pages out of our struct file.  They'll be pinned
+	 * at this point until we release them.
+	 */
+	page_count = obj->size / PAGE_SIZE;
+	BUG_ON(obj_priv->page_list != NULL);
+	obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *),
+					 DRM_MEM_DRIVER);
+	if (obj_priv->page_list == NULL) {
+		DRM_ERROR("Faled to allocate page list\n");
+		return -ENOMEM;
+	}
+
+	inode = obj->filp->f_path.dentry->d_inode;
+	mapping = inode->i_mapping;
+	for (i = 0; i < page_count; i++) {
+		page = read_mapping_page(mapping, i, NULL);
+		if (IS_ERR(page)) {
+			ret = PTR_ERR(page);
+			DRM_ERROR("read_mapping_page failed: %d\n", ret);
+			i915_gem_object_free_page_list(obj);
+			return ret;
+		}
+		obj_priv->page_list[i] = page;
+	}
+	return 0;
+}
+
+/**
+ * Finds free space in the GTT aperture and binds the object there.
+ */
+static int
+i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
+{
+	struct drm_device *dev = obj->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	struct drm_mm_node *free_space;
+	int page_count, ret;
+
+	if (alignment == 0)
+		alignment = PAGE_SIZE;
+	if (alignment & (PAGE_SIZE - 1)) {
+		DRM_ERROR("Invalid object alignment requested %u\n", alignment);
+		return -EINVAL;
+	}
+
+ search_free:
+	free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
+					obj->size, alignment, 0);
+	if (free_space != NULL) {
+		obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
+						       alignment);
+		if (obj_priv->gtt_space != NULL) {
+			obj_priv->gtt_space->private = obj;
+			obj_priv->gtt_offset = obj_priv->gtt_space->start;
+		}
+	}
+	if (obj_priv->gtt_space == NULL) {
+		/* If the gtt is empty and we're still having trouble
+		 * fitting our object in, we're out of memory.
+		 */
+#if WATCH_LRU
+		DRM_INFO("%s: GTT full, evicting something\n", __func__);
+#endif
+		if (list_empty(&dev_priv->mm.inactive_list) &&
+		    list_empty(&dev_priv->mm.flushing_list) &&
+		    list_empty(&dev_priv->mm.active_list)) {
+			DRM_ERROR("GTT full, but LRU list empty\n");
+			return -ENOMEM;
+		}
+
+		ret = i915_gem_evict_something(dev);
+		if (ret != 0) {
+			DRM_ERROR("Failed to evict a buffer %d\n", ret);
+			return ret;
+		}
+		goto search_free;
+	}
+
+#if WATCH_BUF
+	DRM_INFO("Binding object of size %d at 0x%08x\n",
+		 obj->size, obj_priv->gtt_offset);
+#endif
+	ret = i915_gem_object_get_page_list(obj);
+	if (ret) {
+		drm_mm_put_block(obj_priv->gtt_space);
+		obj_priv->gtt_space = NULL;
+		return ret;
+	}
+
+	page_count = obj->size / PAGE_SIZE;
+	/* Create an AGP memory structure pointing at our pages, and bind it
+	 * into the GTT.
+	 */
+	obj_priv->agp_mem = drm_agp_bind_pages(dev,
+					       obj_priv->page_list,
+					       page_count,
+					       obj_priv->gtt_offset,
+					       obj_priv->agp_type);
+	if (obj_priv->agp_mem == NULL) {
+		i915_gem_object_free_page_list(obj);
+		drm_mm_put_block(obj_priv->gtt_space);
+		obj_priv->gtt_space = NULL;
+		return -ENOMEM;
+	}
+	atomic_inc(&dev->gtt_count);
+	atomic_add(obj->size, &dev->gtt_memory);
+
+	/* Assert that the object is not currently in any GPU domain. As it
+	 * wasn't in the GTT, there shouldn't be any way it could have been in
+	 * a GPU cache
+	 */
+	BUG_ON(obj->read_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
+	BUG_ON(obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
+
+	return 0;
+}
+
+void
+i915_gem_clflush_object(struct drm_gem_object *obj)
+{
+	struct drm_i915_gem_object	*obj_priv = obj->driver_private;
+
+	/* If we don't have a page list set up, then we're not pinned
+	 * to GPU, and we can ignore the cache flush because it'll happen
+	 * again at bind time.
+	 */
+	if (obj_priv->page_list == NULL)
+		return;
+
+	drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE);
+}
+
+/*
+ * Set the next domain for the specified object. This
+ * may not actually perform the necessary flushing/invaliding though,
+ * as that may want to be batched with other set_domain operations
+ *
+ * This is (we hope) the only really tricky part of gem. The goal
+ * is fairly simple -- track which caches hold bits of the object
+ * and make sure they remain coherent. A few concrete examples may
+ * help to explain how it works. For shorthand, we use the notation
+ * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
+ * a pair of read and write domain masks.
+ *
+ * Case 1: the batch buffer
+ *
+ *	1. Allocated
+ *	2. Written by CPU
+ *	3. Mapped to GTT
+ *	4. Read by GPU
+ *	5. Unmapped from GTT
+ *	6. Freed
+ *
+ *	Let's take these a step at a time
+ *
+ *	1. Allocated
+ *		Pages allocated from the kernel may still have
+ *		cache contents, so we set them to (CPU, CPU) always.
+ *	2. Written by CPU (using pwrite)
+ *		The pwrite function calls set_domain (CPU, CPU) and
+ *		this function does nothing (as nothing changes)
+ *	3. Mapped by GTT
+ *		This function asserts that the object is not
+ *		currently in any GPU-based read or write domains
+ *	4. Read by GPU
+ *		i915_gem_execbuffer calls set_domain (COMMAND, 0).
+ *		As write_domain is zero, this function adds in the
+ *		current read domains (CPU+COMMAND, 0).
+ *		flush_domains is set to CPU.
+ *		invalidate_domains is set to COMMAND
+ *		clflush is run to get data out of the CPU caches
+ *		then i915_dev_set_domain calls i915_gem_flush to
+ *		emit an MI_FLUSH and drm_agp_chipset_flush
+ *	5. Unmapped from GTT
+ *		i915_gem_object_unbind calls set_domain (CPU, CPU)
+ *		flush_domains and invalidate_domains end up both zero
+ *		so no flushing/invalidating happens
+ *	6. Freed
+ *		yay, done
+ *
+ * Case 2: The shared render buffer
+ *
+ *	1. Allocated
+ *	2. Mapped to GTT
+ *	3. Read/written by GPU
+ *	4. set_domain to (CPU,CPU)
+ *	5. Read/written by CPU
+ *	6. Read/written by GPU
+ *
+ *	1. Allocated
+ *		Same as last example, (CPU, CPU)
+ *	2. Mapped to GTT
+ *		Nothing changes (assertions find that it is not in the GPU)
+ *	3. Read/written by GPU
+ *		execbuffer calls set_domain (RENDER, RENDER)
+ *		flush_domains gets CPU
+ *		invalidate_domains gets GPU
+ *		clflush (obj)
+ *		MI_FLUSH and drm_agp_chipset_flush
+ *	4. set_domain (CPU, CPU)
+ *		flush_domains gets GPU
+ *		invalidate_domains gets CPU
+ *		wait_rendering (obj) to make sure all drawing is complete.
+ *		This will include an MI_FLUSH to get the data from GPU
+ *		to memory
+ *		clflush (obj) to invalidate the CPU cache
+ *		Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
+ *	5. Read/written by CPU
+ *		cache lines are loaded and dirtied
+ *	6. Read written by GPU
+ *		Same as last GPU access
+ *
+ * Case 3: The constant buffer
+ *
+ *	1. Allocated
+ *	2. Written by CPU
+ *	3. Read by GPU
+ *	4. Updated (written) by CPU again
+ *	5. Read by GPU
+ *
+ *	1. Allocated
+ *		(CPU, CPU)
+ *	2. Written by CPU
+ *		(CPU, CPU)
+ *	3. Read by GPU
+ *		(CPU+RENDER, 0)
+ *		flush_domains = CPU
+ *		invalidate_domains = RENDER
+ *		clflush (obj)
+ *		MI_FLUSH
+ *		drm_agp_chipset_flush
+ *	4. Updated (written) by CPU again
+ *		(CPU, CPU)
+ *		flush_domains = 0 (no previous write domain)
+ *		invalidate_domains = 0 (no new read domains)
+ *	5. Read by GPU
+ *		(CPU+RENDER, 0)
+ *		flush_domains = CPU
+ *		invalidate_domains = RENDER
+ *		clflush (obj)
+ *		MI_FLUSH
+ *		drm_agp_chipset_flush
+ */
+static int
+i915_gem_object_set_domain(struct drm_gem_object *obj,
+			    uint32_t read_domains,
+			    uint32_t write_domain)
+{
+	struct drm_device		*dev = obj->dev;
+	struct drm_i915_gem_object	*obj_priv = obj->driver_private;
+	uint32_t			invalidate_domains = 0;
+	uint32_t			flush_domains = 0;
+	int				ret;
+
+#if WATCH_BUF
+	DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
+		 __func__, obj,
+		 obj->read_domains, read_domains,
+		 obj->write_domain, write_domain);
+#endif
+	/*
+	 * If the object isn't moving to a new write domain,
+	 * let the object stay in multiple read domains
+	 */
+	if (write_domain == 0)
+		read_domains |= obj->read_domains;
+	else
+		obj_priv->dirty = 1;
+
+	/*
+	 * Flush the current write domain if
+	 * the new read domains don't match. Invalidate
+	 * any read domains which differ from the old
+	 * write domain
+	 */
+	if (obj->write_domain && obj->write_domain != read_domains) {
+		flush_domains |= obj->write_domain;
+		invalidate_domains |= read_domains & ~obj->write_domain;
+	}
+	/*
+	 * Invalidate any read caches which may have
+	 * stale data. That is, any new read domains.
+	 */
+	invalidate_domains |= read_domains & ~obj->read_domains;
+	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
+#if WATCH_BUF
+		DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
+			 __func__, flush_domains, invalidate_domains);
+#endif
+		/*
+		 * If we're invaliding the CPU cache and flushing a GPU cache,
+		 * then pause for rendering so that the GPU caches will be
+		 * flushed before the cpu cache is invalidated
+		 */
+		if ((invalidate_domains & I915_GEM_DOMAIN_CPU) &&
+		    (flush_domains & ~(I915_GEM_DOMAIN_CPU |
+				       I915_GEM_DOMAIN_GTT))) {
+			ret = i915_gem_object_wait_rendering(obj);
+			if (ret)
+				return ret;
+		}
+		i915_gem_clflush_object(obj);
+	}
+
+	if ((write_domain | flush_domains) != 0)
+		obj->write_domain = write_domain;
+
+	/* If we're invalidating the CPU domain, clear the per-page CPU
+	 * domain list as well.
+	 */
+	if (obj_priv->page_cpu_valid != NULL &&
+	    (write_domain != 0 ||
+	     read_domains & I915_GEM_DOMAIN_CPU)) {
+		drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
+			 DRM_MEM_DRIVER);
+		obj_priv->page_cpu_valid = NULL;
+	}
+	obj->read_domains = read_domains;
+
+	dev->invalidate_domains |= invalidate_domains;
+	dev->flush_domains |= flush_domains;
+#if WATCH_BUF
+	DRM_INFO("%s: read %08x write %08x invalidate %08x flush %08x\n",
+		 __func__,
+		 obj->read_domains, obj->write_domain,
+		 dev->invalidate_domains, dev->flush_domains);
+#endif
+	return 0;
+}
+
+/**
+ * Set the read/write domain on a range of the object.
+ *
+ * Currently only implemented for CPU reads, otherwise drops to normal
+ * i915_gem_object_set_domain().
+ */
+static int
+i915_gem_object_set_domain_range(struct drm_gem_object *obj,
+				 uint64_t offset,
+				 uint64_t size,
+				 uint32_t read_domains,
+				 uint32_t write_domain)
+{
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int ret, i;
+
+	if (obj->read_domains & I915_GEM_DOMAIN_CPU)
+		return 0;
+
+	if (read_domains != I915_GEM_DOMAIN_CPU ||
+	    write_domain != 0)
+		return i915_gem_object_set_domain(obj,
+						  read_domains, write_domain);
+
+	/* Wait on any GPU rendering to the object to be flushed. */
+	if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) {
+		ret = i915_gem_object_wait_rendering(obj);
+		if (ret)
+			return ret;
+	}
+
+	if (obj_priv->page_cpu_valid == NULL) {
+		obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
+						      DRM_MEM_DRIVER);
+	}
+
+	/* Flush the cache on any pages that are still invalid from the CPU's
+	 * perspective.
+	 */
+	for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; i++) {
+		if (obj_priv->page_cpu_valid[i])
+			continue;
+
+		drm_clflush_pages(obj_priv->page_list + i, 1);
+
+		obj_priv->page_cpu_valid[i] = 1;
+	}
+
+	return 0;
+}
+
+/**
+ * Once all of the objects have been set in the proper domain,
+ * perform the necessary flush and invalidate operations.
+ *
+ * Returns the write domains flushed, for use in flush tracking.
+ */
+static uint32_t
+i915_gem_dev_set_domain(struct drm_device *dev)
+{
+	uint32_t flush_domains = dev->flush_domains;
+
+	/*
+	 * Now that all the buffers are synced to the proper domains,
+	 * flush and invalidate the collected domains
+	 */
+	if (dev->invalidate_domains | dev->flush_domains) {
+#if WATCH_EXEC
+		DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
+			  __func__,
+			 dev->invalidate_domains,
+			 dev->flush_domains);
+#endif
+		i915_gem_flush(dev,
+			       dev->invalidate_domains,
+			       dev->flush_domains);
+		dev->invalidate_domains = 0;
+		dev->flush_domains = 0;
+	}
+
+	return flush_domains;
+}
+
+/**
+ * Pin an object to the GTT and evaluate the relocations landing in it.
+ */
+static int
+i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
+				 struct drm_file *file_priv,
+				 struct drm_i915_gem_exec_object *entry)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_relocation_entry reloc;
+	struct drm_i915_gem_relocation_entry __user *relocs;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int i, ret;
+	uint32_t last_reloc_offset = -1;
+	void __iomem *reloc_page = NULL;
+
+	/* Choose the GTT offset for our buffer and put it there. */
+	ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
+	if (ret)
+		return ret;
+
+	entry->offset = obj_priv->gtt_offset;
+
+	relocs = (struct drm_i915_gem_relocation_entry __user *)
+		 (uintptr_t) entry->relocs_ptr;
+	/* Apply the relocations, using the GTT aperture to avoid cache
+	 * flushing requirements.
+	 */
+	for (i = 0; i < entry->relocation_count; i++) {
+		struct drm_gem_object *target_obj;
+		struct drm_i915_gem_object *target_obj_priv;
+		uint32_t reloc_val, reloc_offset;
+		uint32_t __iomem *reloc_entry;
+
+		ret = copy_from_user(&reloc, relocs + i, sizeof(reloc));
+		if (ret != 0) {
+			i915_gem_object_unpin(obj);
+			return ret;
+		}
+
+		target_obj = drm_gem_object_lookup(obj->dev, file_priv,
+						   reloc.target_handle);
+		if (target_obj == NULL) {
+			i915_gem_object_unpin(obj);
+			return -EBADF;
+		}
+		target_obj_priv = target_obj->driver_private;
+
+		/* The target buffer should have appeared before us in the
+		 * exec_object list, so it should have a GTT space bound by now.
+		 */
+		if (target_obj_priv->gtt_space == NULL) {
+			DRM_ERROR("No GTT space found for object %d\n",
+				  reloc.target_handle);
+			drm_gem_object_unreference(target_obj);
+			i915_gem_object_unpin(obj);
+			return -EINVAL;
+		}
+
+		if (reloc.offset > obj->size - 4) {
+			DRM_ERROR("Relocation beyond object bounds: "
+				  "obj %p target %d offset %d size %d.\n",
+				  obj, reloc.target_handle,
+				  (int) reloc.offset, (int) obj->size);
+			drm_gem_object_unreference(target_obj);
+			i915_gem_object_unpin(obj);
+			return -EINVAL;
+		}
+		if (reloc.offset & 3) {
+			DRM_ERROR("Relocation not 4-byte aligned: "
+				  "obj %p target %d offset %d.\n",
+				  obj, reloc.target_handle,
+				  (int) reloc.offset);
+			drm_gem_object_unreference(target_obj);
+			i915_gem_object_unpin(obj);
+			return -EINVAL;
+		}
+
+		if (reloc.write_domain && target_obj->pending_write_domain &&
+		    reloc.write_domain != target_obj->pending_write_domain) {
+			DRM_ERROR("Write domain conflict: "
+				  "obj %p target %d offset %d "
+				  "new %08x old %08x\n",
+				  obj, reloc.target_handle,
+				  (int) reloc.offset,
+				  reloc.write_domain,
+				  target_obj->pending_write_domain);
+			drm_gem_object_unreference(target_obj);
+			i915_gem_object_unpin(obj);
+			return -EINVAL;
+		}
+
+#if WATCH_RELOC
+		DRM_INFO("%s: obj %p offset %08x target %d "
+			 "read %08x write %08x gtt %08x "
+			 "presumed %08x delta %08x\n",
+			 __func__,
+			 obj,
+			 (int) reloc.offset,
+			 (int) reloc.target_handle,
+			 (int) reloc.read_domains,
+			 (int) reloc.write_domain,
+			 (int) target_obj_priv->gtt_offset,
+			 (int) reloc.presumed_offset,
+			 reloc.delta);
+#endif
+
+		target_obj->pending_read_domains |= reloc.read_domains;
+		target_obj->pending_write_domain |= reloc.write_domain;
+
+		/* If the relocation already has the right value in it, no
+		 * more work needs to be done.
+		 */
+		if (target_obj_priv->gtt_offset == reloc.presumed_offset) {
+			drm_gem_object_unreference(target_obj);
+			continue;
+		}
+
+		/* Now that we're going to actually write some data in,
+		 * make sure that any rendering using this buffer's contents
+		 * is completed.
+		 */
+		i915_gem_object_wait_rendering(obj);
+
+		/* As we're writing through the gtt, flush
+		 * any CPU writes before we write the relocations
+		 */
+		if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
+			i915_gem_clflush_object(obj);
+			drm_agp_chipset_flush(dev);
+			obj->write_domain = 0;
+		}
+
+		/* Map the page containing the relocation we're going to
+		 * perform.
+		 */
+		reloc_offset = obj_priv->gtt_offset + reloc.offset;
+		if (reloc_page == NULL ||
+		    (last_reloc_offset & ~(PAGE_SIZE - 1)) !=
+		    (reloc_offset & ~(PAGE_SIZE - 1))) {
+			if (reloc_page != NULL)
+				iounmap(reloc_page);
+
+			reloc_page = ioremap_wc(dev->agp->base +
+						(reloc_offset &
+						 ~(PAGE_SIZE - 1)),
+						PAGE_SIZE);
+			last_reloc_offset = reloc_offset;
+			if (reloc_page == NULL) {
+				drm_gem_object_unreference(target_obj);
+				i915_gem_object_unpin(obj);
+				return -ENOMEM;
+			}
+		}
+
+		reloc_entry = (uint32_t __iomem *)(reloc_page +
+					   (reloc_offset & (PAGE_SIZE - 1)));
+		reloc_val = target_obj_priv->gtt_offset + reloc.delta;
+
+#if WATCH_BUF
+		DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n",
+			  obj, (unsigned int) reloc.offset,
+			  readl(reloc_entry), reloc_val);
+#endif
+		writel(reloc_val, reloc_entry);
+
+		/* Write the updated presumed offset for this entry back out
+		 * to the user.
+		 */
+		reloc.presumed_offset = target_obj_priv->gtt_offset;
+		ret = copy_to_user(relocs + i, &reloc, sizeof(reloc));
+		if (ret != 0) {
+			drm_gem_object_unreference(target_obj);
+			i915_gem_object_unpin(obj);
+			return ret;
+		}
+
+		drm_gem_object_unreference(target_obj);
+	}
+
+	if (reloc_page != NULL)
+		iounmap(reloc_page);
+
+#if WATCH_BUF
+	if (0)
+		i915_gem_dump_object(obj, 128, __func__, ~0);
+#endif
+	return 0;
+}
+
+/** Dispatch a batchbuffer to the ring
+ */
+static int
+i915_dispatch_gem_execbuffer(struct drm_device *dev,
+			      struct drm_i915_gem_execbuffer *exec,
+			      uint64_t exec_offset)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *)
+					     (uintptr_t) exec->cliprects_ptr;
+	int nbox = exec->num_cliprects;
+	int i = 0, count;
+	uint32_t	exec_start, exec_len;
+	RING_LOCALS;
+
+	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+	exec_len = (uint32_t) exec->batch_len;
+
+	if ((exec_start | exec_len) & 0x7) {
+		DRM_ERROR("alignment\n");
+		return -EINVAL;
+	}
+
+	if (!exec_start)
+		return -EINVAL;
+
+	count = nbox ? nbox : 1;
+
+	for (i = 0; i < count; i++) {
+		if (i < nbox) {
+			int ret = i915_emit_box(dev, boxes, i,
+						exec->DR1, exec->DR4);
+			if (ret)
+				return ret;
+		}
+
+		if (IS_I830(dev) || IS_845G(dev)) {
+			BEGIN_LP_RING(4);
+			OUT_RING(MI_BATCH_BUFFER);
+			OUT_RING(exec_start | MI_BATCH_NON_SECURE);
+			OUT_RING(exec_start + exec_len - 4);
+			OUT_RING(0);
+			ADVANCE_LP_RING();
+		} else {
+			BEGIN_LP_RING(2);
+			if (IS_I965G(dev)) {
+				OUT_RING(MI_BATCH_BUFFER_START |
+					 (2 << 6) |
+					 MI_BATCH_NON_SECURE_I965);
+				OUT_RING(exec_start);
+			} else {
+				OUT_RING(MI_BATCH_BUFFER_START |
+					 (2 << 6));
+				OUT_RING(exec_start | MI_BATCH_NON_SECURE);
+			}
+			ADVANCE_LP_RING();
+		}
+	}
+
+	/* XXX breadcrumb */
+	return 0;
+}
+
+/* Throttle our rendering by waiting until the ring has completed our requests
+ * emitted over 20 msec ago.
+ *
+ * This should get us reasonable parallelism between CPU and GPU but also
+ * relatively low latency when blocking on a particular request to finish.
+ */
+static int
+i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+	int ret = 0;
+	uint32_t seqno;
+
+	mutex_lock(&dev->struct_mutex);
+	seqno = i915_file_priv->mm.last_gem_throttle_seqno;
+	i915_file_priv->mm.last_gem_throttle_seqno =
+		i915_file_priv->mm.last_gem_seqno;
+	if (seqno)
+		ret = i915_wait_request(dev, seqno);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+int
+i915_gem_execbuffer(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+	struct drm_i915_gem_execbuffer *args = data;
+	struct drm_i915_gem_exec_object *exec_list = NULL;
+	struct drm_gem_object **object_list = NULL;
+	struct drm_gem_object *batch_obj;
+	int ret, i, pinned = 0;
+	uint64_t exec_offset;
+	uint32_t seqno, flush_domains;
+
+#if WATCH_EXEC
+	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+	if (args->buffer_count < 1) {
+		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
+		return -EINVAL;
+	}
+	/* Copy in the exec list from userland */
+	exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count,
+			       DRM_MEM_DRIVER);
+	object_list = drm_calloc(sizeof(*object_list), args->buffer_count,
+				 DRM_MEM_DRIVER);
+	if (exec_list == NULL || object_list == NULL) {
+		DRM_ERROR("Failed to allocate exec or object list "
+			  "for %d buffers\n",
+			  args->buffer_count);
+		ret = -ENOMEM;
+		goto pre_mutex_err;
+	}
+	ret = copy_from_user(exec_list,
+			     (struct drm_i915_relocation_entry __user *)
+			     (uintptr_t) args->buffers_ptr,
+			     sizeof(*exec_list) * args->buffer_count);
+	if (ret != 0) {
+		DRM_ERROR("copy %d exec entries failed %d\n",
+			  args->buffer_count, ret);
+		goto pre_mutex_err;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+	if (dev_priv->mm.wedged) {
+		DRM_ERROR("Execbuf while wedged\n");
+		mutex_unlock(&dev->struct_mutex);
+		return -EIO;
+	}
+
+	if (dev_priv->mm.suspended) {
+		DRM_ERROR("Execbuf while VT-switched.\n");
+		mutex_unlock(&dev->struct_mutex);
+		return -EBUSY;
+	}
+
+	/* Zero the gloabl flush/invalidate flags. These
+	 * will be modified as each object is bound to the
+	 * gtt
+	 */
+	dev->invalidate_domains = 0;
+	dev->flush_domains = 0;
+
+	/* Look up object handles and perform the relocations */
+	for (i = 0; i < args->buffer_count; i++) {
+		object_list[i] = drm_gem_object_lookup(dev, file_priv,
+						       exec_list[i].handle);
+		if (object_list[i] == NULL) {
+			DRM_ERROR("Invalid object handle %d at index %d\n",
+				   exec_list[i].handle, i);
+			ret = -EBADF;
+			goto err;
+		}
+
+		object_list[i]->pending_read_domains = 0;
+		object_list[i]->pending_write_domain = 0;
+		ret = i915_gem_object_pin_and_relocate(object_list[i],
+						       file_priv,
+						       &exec_list[i]);
+		if (ret) {
+			DRM_ERROR("object bind and relocate failed %d\n", ret);
+			goto err;
+		}
+		pinned = i + 1;
+	}
+
+	/* Set the pending read domains for the batch buffer to COMMAND */
+	batch_obj = object_list[args->buffer_count-1];
+	batch_obj->pending_read_domains = I915_GEM_DOMAIN_COMMAND;
+	batch_obj->pending_write_domain = 0;
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+	for (i = 0; i < args->buffer_count; i++) {
+		struct drm_gem_object *obj = object_list[i];
+		struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+		if (obj_priv->gtt_space == NULL) {
+			/* We evicted the buffer in the process of validating
+			 * our set of buffers in.  We could try to recover by
+			 * kicking them everything out and trying again from
+			 * the start.
+			 */
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		/* make sure all previous memory operations have passed */
+		ret = i915_gem_object_set_domain(obj,
+						 obj->pending_read_domains,
+						 obj->pending_write_domain);
+		if (ret)
+			goto err;
+	}
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+	/* Flush/invalidate caches and chipset buffer */
+	flush_domains = i915_gem_dev_set_domain(dev);
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+#if WATCH_COHERENCY
+	for (i = 0; i < args->buffer_count; i++) {
+		i915_gem_object_check_coherency(object_list[i],
+						exec_list[i].handle);
+	}
+#endif
+
+	exec_offset = exec_list[args->buffer_count - 1].offset;
+
+#if WATCH_EXEC
+	i915_gem_dump_object(object_list[args->buffer_count - 1],
+			      args->batch_len,
+			      __func__,
+			      ~0);
+#endif
+
+	(void)i915_add_request(dev, flush_domains);
+
+	/* Exec the batchbuffer */
+	ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset);
+	if (ret) {
+		DRM_ERROR("dispatch failed %d\n", ret);
+		goto err;
+	}
+
+	/*
+	 * Ensure that the commands in the batch buffer are
+	 * finished before the interrupt fires
+	 */
+	flush_domains = i915_retire_commands(dev);
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+	/*
+	 * Get a seqno representing the execution of the current buffer,
+	 * which we can wait on.  We would like to mitigate these interrupts,
+	 * likely by only creating seqnos occasionally (so that we have
+	 * *some* interrupts representing completion of buffers that we can
+	 * wait on when trying to clear up gtt space).
+	 */
+	seqno = i915_add_request(dev, flush_domains);
+	BUG_ON(seqno == 0);
+	i915_file_priv->mm.last_gem_seqno = seqno;
+	for (i = 0; i < args->buffer_count; i++) {
+		struct drm_gem_object *obj = object_list[i];
+		struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+		i915_gem_object_move_to_active(obj);
+		obj_priv->last_rendering_seqno = seqno;
+#if WATCH_LRU
+		DRM_INFO("%s: move to exec list %p\n", __func__, obj);
+#endif
+	}
+#if WATCH_LRU
+	i915_dump_lru(dev, __func__);
+#endif
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+	/* Copy the new buffer offsets back to the user's exec list. */
+	ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+			   (uintptr_t) args->buffers_ptr,
+			   exec_list,
+			   sizeof(*exec_list) * args->buffer_count);
+	if (ret)
+		DRM_ERROR("failed to copy %d exec entries "
+			  "back to user (%d)\n",
+			   args->buffer_count, ret);
+err:
+	if (object_list != NULL) {
+		for (i = 0; i < pinned; i++)
+			i915_gem_object_unpin(object_list[i]);
+
+		for (i = 0; i < args->buffer_count; i++)
+			drm_gem_object_unreference(object_list[i]);
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+pre_mutex_err:
+	drm_free(object_list, sizeof(*object_list) * args->buffer_count,
+		 DRM_MEM_DRIVER);
+	drm_free(exec_list, sizeof(*exec_list) * args->buffer_count,
+		 DRM_MEM_DRIVER);
+
+	return ret;
+}
+
+int
+i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int ret;
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+	if (obj_priv->gtt_space == NULL) {
+		ret = i915_gem_object_bind_to_gtt(obj, alignment);
+		if (ret != 0) {
+			DRM_ERROR("Failure to bind: %d", ret);
+			return ret;
+		}
+	}
+	obj_priv->pin_count++;
+
+	/* If the object is not active and not pending a flush,
+	 * remove it from the inactive list
+	 */
+	if (obj_priv->pin_count == 1) {
+		atomic_inc(&dev->pin_count);
+		atomic_add(obj->size, &dev->pin_memory);
+		if (!obj_priv->active &&
+		    (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
+					   I915_GEM_DOMAIN_GTT)) == 0 &&
+		    !list_empty(&obj_priv->list))
+			list_del_init(&obj_priv->list);
+	}
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+	return 0;
+}
+
+void
+i915_gem_object_unpin(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+	obj_priv->pin_count--;
+	BUG_ON(obj_priv->pin_count < 0);
+	BUG_ON(obj_priv->gtt_space == NULL);
+
+	/* If the object is no longer pinned, and is
+	 * neither active nor being flushed, then stick it on
+	 * the inactive list
+	 */
+	if (obj_priv->pin_count == 0) {
+		if (!obj_priv->active &&
+		    (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
+					   I915_GEM_DOMAIN_GTT)) == 0)
+			list_move_tail(&obj_priv->list,
+				       &dev_priv->mm.inactive_list);
+		atomic_dec(&dev->pin_count);
+		atomic_sub(obj->size, &dev->pin_memory);
+	}
+	i915_verify_inactive(dev, __FILE__, __LINE__);
+}
+
+int
+i915_gem_pin_ioctl(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv)
+{
+	struct drm_i915_gem_pin *args = data;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret;
+
+	mutex_lock(&dev->struct_mutex);
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL) {
+		DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n",
+			  args->handle);
+		mutex_unlock(&dev->struct_mutex);
+		return -EBADF;
+	}
+	obj_priv = obj->driver_private;
+
+	ret = i915_gem_object_pin(obj, args->alignment);
+	if (ret != 0) {
+		drm_gem_object_unreference(obj);
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+
+	/* XXX - flush the CPU caches for pinned objects
+	 * as the X server doesn't manage domains yet
+	 */
+	if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
+		i915_gem_clflush_object(obj);
+		drm_agp_chipset_flush(dev);
+		obj->write_domain = 0;
+	}
+	args->offset = obj_priv->gtt_offset;
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+int
+i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv)
+{
+	struct drm_i915_gem_pin *args = data;
+	struct drm_gem_object *obj;
+
+	mutex_lock(&dev->struct_mutex);
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL) {
+		DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n",
+			  args->handle);
+		mutex_unlock(&dev->struct_mutex);
+		return -EBADF;
+	}
+
+	i915_gem_object_unpin(obj);
+
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+}
+
+int
+i915_gem_busy_ioctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	struct drm_i915_gem_busy *args = data;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+
+	mutex_lock(&dev->struct_mutex);
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL) {
+		DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
+			  args->handle);
+		mutex_unlock(&dev->struct_mutex);
+		return -EBADF;
+	}
+
+	obj_priv = obj->driver_private;
+	args->busy = obj_priv->active;
+
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+}
+
+int
+i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+    return i915_gem_ring_throttle(dev, file_priv);
+}
+
+int i915_gem_init_object(struct drm_gem_object *obj)
+{
+	struct drm_i915_gem_object *obj_priv;
+
+	obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
+	if (obj_priv == NULL)
+		return -ENOMEM;
+
+	/*
+	 * We've just allocated pages from the kernel,
+	 * so they've just been written by the CPU with
+	 * zeros. They'll need to be clflushed before we
+	 * use them with the GPU.
+	 */
+	obj->write_domain = I915_GEM_DOMAIN_CPU;
+	obj->read_domains = I915_GEM_DOMAIN_CPU;
+
+	obj_priv->agp_type = AGP_USER_MEMORY;
+
+	obj->driver_private = obj_priv;
+	obj_priv->obj = obj;
+	INIT_LIST_HEAD(&obj_priv->list);
+	return 0;
+}
+
+void i915_gem_free_object(struct drm_gem_object *obj)
+{
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+	while (obj_priv->pin_count > 0)
+		i915_gem_object_unpin(obj);
+
+	i915_gem_object_unbind(obj);
+
+	drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
+	drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
+}
+
+static int
+i915_gem_set_domain(struct drm_gem_object *obj,
+		    struct drm_file *file_priv,
+		    uint32_t read_domains,
+		    uint32_t write_domain)
+{
+	struct drm_device *dev = obj->dev;
+	int ret;
+	uint32_t flush_domains;
+
+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	ret = i915_gem_object_set_domain(obj, read_domains, write_domain);
+	if (ret)
+		return ret;
+	flush_domains = i915_gem_dev_set_domain(obj->dev);
+
+	if (flush_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT))
+		(void) i915_add_request(dev, flush_domains);
+
+	return 0;
+}
+
+/** Unbinds all objects that are on the given buffer list. */
+static int
+i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
+{
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret;
+
+	while (!list_empty(head)) {
+		obj_priv = list_first_entry(head,
+					    struct drm_i915_gem_object,
+					    list);
+		obj = obj_priv->obj;
+
+		if (obj_priv->pin_count != 0) {
+			DRM_ERROR("Pinned object in unbind list\n");
+			mutex_unlock(&dev->struct_mutex);
+			return -EINVAL;
+		}
+
+		ret = i915_gem_object_unbind(obj);
+		if (ret != 0) {
+			DRM_ERROR("Error unbinding object in LeaveVT: %d\n",
+				  ret);
+			mutex_unlock(&dev->struct_mutex);
+			return ret;
+		}
+	}
+
+
+	return 0;
+}
+
+static int
+i915_gem_idle(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t seqno, cur_seqno, last_seqno;
+	int stuck, ret;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) {
+		mutex_unlock(&dev->struct_mutex);
+		return 0;
+	}
+
+	/* Hack!  Don't let anybody do execbuf while we don't control the chip.
+	 * We need to replace this with a semaphore, or something.
+	 */
+	dev_priv->mm.suspended = 1;
+
+	/* Cancel the retire work handler, wait for it to finish if running
+	 */
+	mutex_unlock(&dev->struct_mutex);
+	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
+	mutex_lock(&dev->struct_mutex);
+
+	i915_kernel_lost_context(dev);
+
+	/* Flush the GPU along with all non-CPU write domains
+	 */
+	i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT),
+		       ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
+	seqno = i915_add_request(dev, ~(I915_GEM_DOMAIN_CPU |
+					I915_GEM_DOMAIN_GTT));
+
+	if (seqno == 0) {
+		mutex_unlock(&dev->struct_mutex);
+		return -ENOMEM;
+	}
+
+	dev_priv->mm.waiting_gem_seqno = seqno;
+	last_seqno = 0;
+	stuck = 0;
+	for (;;) {
+		cur_seqno = i915_get_gem_seqno(dev);
+		if (i915_seqno_passed(cur_seqno, seqno))
+			break;
+		if (last_seqno == cur_seqno) {
+			if (stuck++ > 100) {
+				DRM_ERROR("hardware wedged\n");
+				dev_priv->mm.wedged = 1;
+				DRM_WAKEUP(&dev_priv->irq_queue);
+				break;
+			}
+		}
+		msleep(10);
+		last_seqno = cur_seqno;
+	}
+	dev_priv->mm.waiting_gem_seqno = 0;
+
+	i915_gem_retire_requests(dev);
+
+	/* Active and flushing should now be empty as we've
+	 * waited for a sequence higher than any pending execbuffer
+	 */
+	BUG_ON(!list_empty(&dev_priv->mm.active_list));
+	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+
+	/* Request should now be empty as we've also waited
+	 * for the last request in the list
+	 */
+	BUG_ON(!list_empty(&dev_priv->mm.request_list));
+
+	/* Move all buffers out of the GTT. */
+	ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
+	if (ret) {
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+
+	BUG_ON(!list_empty(&dev_priv->mm.active_list));
+	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
+	BUG_ON(!list_empty(&dev_priv->mm.request_list));
+
+	i915_gem_cleanup_ringbuffer(dev);
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
+static int
+i915_gem_init_hws(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret;
+
+	/* If we need a physical address for the status page, it's already
+	 * initialized at driver load time.
+	 */
+	if (!I915_NEED_GFX_HWS(dev))
+		return 0;
+
+	obj = drm_gem_object_alloc(dev, 4096);
+	if (obj == NULL) {
+		DRM_ERROR("Failed to allocate status page\n");
+		return -ENOMEM;
+	}
+	obj_priv = obj->driver_private;
+	obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
+
+	ret = i915_gem_object_pin(obj, 4096);
+	if (ret != 0) {
+		drm_gem_object_unreference(obj);
+		return ret;
+	}
+
+	dev_priv->status_gfx_addr = obj_priv->gtt_offset;
+
+	dev_priv->hw_status_page = kmap(obj_priv->page_list[0]);
+	if (dev_priv->hw_status_page == NULL) {
+		DRM_ERROR("Failed to map status page.\n");
+		memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+		drm_gem_object_unreference(obj);
+		return -EINVAL;
+	}
+	dev_priv->hws_obj = obj;
+	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+	I915_READ(HWS_PGA); /* posting read */
+	DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
+
+	return 0;
+}
+
+static int
+i915_gem_init_ringbuffer(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret;
+	u32 head;
+
+	ret = i915_gem_init_hws(dev);
+	if (ret != 0)
+		return ret;
+
+	obj = drm_gem_object_alloc(dev, 128 * 1024);
+	if (obj == NULL) {
+		DRM_ERROR("Failed to allocate ringbuffer\n");
+		return -ENOMEM;
+	}
+	obj_priv = obj->driver_private;
+
+	ret = i915_gem_object_pin(obj, 4096);
+	if (ret != 0) {
+		drm_gem_object_unreference(obj);
+		return ret;
+	}
+
+	/* Set up the kernel mapping for the ring. */
+	dev_priv->ring.Size = obj->size;
+	dev_priv->ring.tail_mask = obj->size - 1;
+
+	dev_priv->ring.map.offset = dev->agp->base + obj_priv->gtt_offset;
+	dev_priv->ring.map.size = obj->size;
+	dev_priv->ring.map.type = 0;
+	dev_priv->ring.map.flags = 0;
+	dev_priv->ring.map.mtrr = 0;
+
+	drm_core_ioremap_wc(&dev_priv->ring.map, dev);
+	if (dev_priv->ring.map.handle == NULL) {
+		DRM_ERROR("Failed to map ringbuffer.\n");
+		memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
+		drm_gem_object_unreference(obj);
+		return -EINVAL;
+	}
+	dev_priv->ring.ring_obj = obj;
+	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+	/* Stop the ring if it's running. */
+	I915_WRITE(PRB0_CTL, 0);
+	I915_WRITE(PRB0_TAIL, 0);
+	I915_WRITE(PRB0_HEAD, 0);
+
+	/* Initialize the ring. */
+	I915_WRITE(PRB0_START, obj_priv->gtt_offset);
+	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+
+	/* G45 ring initialization fails to reset head to zero */
+	if (head != 0) {
+		DRM_ERROR("Ring head not reset to zero "
+			  "ctl %08x head %08x tail %08x start %08x\n",
+			  I915_READ(PRB0_CTL),
+			  I915_READ(PRB0_HEAD),
+			  I915_READ(PRB0_TAIL),
+			  I915_READ(PRB0_START));
+		I915_WRITE(PRB0_HEAD, 0);
+
+		DRM_ERROR("Ring head forced to zero "
+			  "ctl %08x head %08x tail %08x start %08x\n",
+			  I915_READ(PRB0_CTL),
+			  I915_READ(PRB0_HEAD),
+			  I915_READ(PRB0_TAIL),
+			  I915_READ(PRB0_START));
+	}
+
+	I915_WRITE(PRB0_CTL,
+		   ((obj->size - 4096) & RING_NR_PAGES) |
+		   RING_NO_REPORT |
+		   RING_VALID);
+
+	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+
+	/* If the head is still not zero, the ring is dead */
+	if (head != 0) {
+		DRM_ERROR("Ring initialization failed "
+			  "ctl %08x head %08x tail %08x start %08x\n",
+			  I915_READ(PRB0_CTL),
+			  I915_READ(PRB0_HEAD),
+			  I915_READ(PRB0_TAIL),
+			  I915_READ(PRB0_START));
+		return -EIO;
+	}
+
+	/* Update our cache of the ring state */
+	i915_kernel_lost_context(dev);
+
+	return 0;
+}
+
+static void
+i915_gem_cleanup_ringbuffer(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (dev_priv->ring.ring_obj == NULL)
+		return;
+
+	drm_core_ioremapfree(&dev_priv->ring.map, dev);
+
+	i915_gem_object_unpin(dev_priv->ring.ring_obj);
+	drm_gem_object_unreference(dev_priv->ring.ring_obj);
+	dev_priv->ring.ring_obj = NULL;
+	memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
+
+	if (dev_priv->hws_obj != NULL) {
+		struct drm_gem_object *obj = dev_priv->hws_obj;
+		struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+		kunmap(obj_priv->page_list[0]);
+		i915_gem_object_unpin(obj);
+		drm_gem_object_unreference(obj);
+		dev_priv->hws_obj = NULL;
+		memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+		dev_priv->hw_status_page = NULL;
+
+		/* Write high address into HWS_PGA when disabling. */
+		I915_WRITE(HWS_PGA, 0x1ffff000);
+	}
+}
+
+int
+i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
+
+	if (dev_priv->mm.wedged) {
+		DRM_ERROR("Reenabling wedged hardware, good luck\n");
+		dev_priv->mm.wedged = 0;
+	}
+
+	ret = i915_gem_init_ringbuffer(dev);
+	if (ret != 0)
+		return ret;
+
+	mutex_lock(&dev->struct_mutex);
+	BUG_ON(!list_empty(&dev_priv->mm.active_list));
+	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
+	BUG_ON(!list_empty(&dev_priv->mm.request_list));
+	dev_priv->mm.suspended = 0;
+	mutex_unlock(&dev->struct_mutex);
+
+	drm_irq_install(dev);
+
+	return 0;
+}
+
+int
+i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	int ret;
+
+	ret = i915_gem_idle(dev);
+	drm_irq_uninstall(dev);
+
+	return ret;
+}
+
+void
+i915_gem_lastclose(struct drm_device *dev)
+{
+	int ret;
+
+	ret = i915_gem_idle(dev);
+	if (ret)
+		DRM_ERROR("failed to idle hardware: %d\n", ret);
+}
+
+void
+i915_gem_load(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	INIT_LIST_HEAD(&dev_priv->mm.active_list);
+	INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
+	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
+	INIT_LIST_HEAD(&dev_priv->mm.request_list);
+	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
+			  i915_gem_retire_work_handler);
+	INIT_WORK(&dev_priv->mm.vblank_work,
+		  i915_gem_vblank_work_handler);
+	dev_priv->mm.next_gem_seqno = 1;
+
+	i915_gem_detect_bit_6_swizzle(dev);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
new file mode 100644
index 0000000..131c088
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#if WATCH_INACTIVE
+void
+i915_verify_inactive(struct drm_device *dev, char *file, int line)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+
+	list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
+		obj = obj_priv->obj;
+		if (obj_priv->pin_count || obj_priv->active ||
+		    (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
+					   I915_GEM_DOMAIN_GTT)))
+			DRM_ERROR("inactive %p (p %d a %d w %x)  %s:%d\n",
+				  obj,
+				  obj_priv->pin_count, obj_priv->active,
+				  obj->write_domain, file, line);
+	}
+}
+#endif /* WATCH_INACTIVE */
+
+
+#if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE
+static void
+i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
+		   uint32_t bias, uint32_t mark)
+{
+	uint32_t *mem = kmap_atomic(page, KM_USER0);
+	int i;
+	for (i = start; i < end; i += 4)
+		DRM_INFO("%08x: %08x%s\n",
+			  (int) (bias + i), mem[i / 4],
+			  (bias + i == mark) ? " ********" : "");
+	kunmap_atomic(mem, KM_USER0);
+	/* give syslog time to catch up */
+	msleep(1);
+}
+
+void
+i915_gem_dump_object(struct drm_gem_object *obj, int len,
+		     const char *where, uint32_t mark)
+{
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int page;
+
+	DRM_INFO("%s: object at offset %08x\n", where, obj_priv->gtt_offset);
+	for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) {
+		int page_len, chunk, chunk_len;
+
+		page_len = len - page * PAGE_SIZE;
+		if (page_len > PAGE_SIZE)
+			page_len = PAGE_SIZE;
+
+		for (chunk = 0; chunk < page_len; chunk += 128) {
+			chunk_len = page_len - chunk;
+			if (chunk_len > 128)
+				chunk_len = 128;
+			i915_gem_dump_page(obj_priv->page_list[page],
+					   chunk, chunk + chunk_len,
+					   obj_priv->gtt_offset +
+					   page * PAGE_SIZE,
+					   mark);
+		}
+	}
+}
+#endif
+
+#if WATCH_LRU
+void
+i915_dump_lru(struct drm_device *dev, const char *where)
+{
+	drm_i915_private_t		*dev_priv = dev->dev_private;
+	struct drm_i915_gem_object	*obj_priv;
+
+	DRM_INFO("active list %s {\n", where);
+	list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
+			    list)
+	{
+		DRM_INFO("    %p: %08x\n", obj_priv,
+			 obj_priv->last_rendering_seqno);
+	}
+	DRM_INFO("}\n");
+	DRM_INFO("flushing list %s {\n", where);
+	list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
+			    list)
+	{
+		DRM_INFO("    %p: %08x\n", obj_priv,
+			 obj_priv->last_rendering_seqno);
+	}
+	DRM_INFO("}\n");
+	DRM_INFO("inactive %s {\n", where);
+	list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
+		DRM_INFO("    %p: %08x\n", obj_priv,
+			 obj_priv->last_rendering_seqno);
+	}
+	DRM_INFO("}\n");
+}
+#endif
+
+
+#if WATCH_COHERENCY
+void
+i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int page;
+	uint32_t *gtt_mapping;
+	uint32_t *backing_map = NULL;
+	int bad_count = 0;
+
+	DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n",
+		 __func__, obj, obj_priv->gtt_offset, handle,
+		 obj->size / 1024);
+
+	gtt_mapping = ioremap(dev->agp->base + obj_priv->gtt_offset,
+			      obj->size);
+	if (gtt_mapping == NULL) {
+		DRM_ERROR("failed to map GTT space\n");
+		return;
+	}
+
+	for (page = 0; page < obj->size / PAGE_SIZE; page++) {
+		int i;
+
+		backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0);
+
+		if (backing_map == NULL) {
+			DRM_ERROR("failed to map backing page\n");
+			goto out;
+		}
+
+		for (i = 0; i < PAGE_SIZE / 4; i++) {
+			uint32_t cpuval = backing_map[i];
+			uint32_t gttval = readl(gtt_mapping +
+						page * 1024 + i);
+
+			if (cpuval != gttval) {
+				DRM_INFO("incoherent CPU vs GPU at 0x%08x: "
+					 "0x%08x vs 0x%08x\n",
+					 (int)(obj_priv->gtt_offset +
+					       page * PAGE_SIZE + i * 4),
+					 cpuval, gttval);
+				if (bad_count++ >= 8) {
+					DRM_INFO("...\n");
+					goto out;
+				}
+			}
+		}
+		kunmap_atomic(backing_map, KM_USER0);
+		backing_map = NULL;
+	}
+
+ out:
+	if (backing_map != NULL)
+		kunmap_atomic(backing_map, KM_USER0);
+	iounmap(gtt_mapping);
+
+	/* give syslog time to catch up */
+	msleep(1);
+
+	/* Directly flush the object, since we just loaded values with the CPU
+	 * from the backing pages and we don't want to disturb the cache
+	 * management that we're trying to observe.
+	 */
+
+	i915_gem_clflush_object(obj);
+}
+#endif
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
new file mode 100644
index 0000000..15d4160
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *    Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static int i915_gem_active_info(char *buf, char **start, off_t offset,
+				int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv;
+	int len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof = 0;
+	DRM_PROC_PRINT("Active:\n");
+	list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
+			    list)
+	{
+		struct drm_gem_object *obj = obj_priv->obj;
+		if (obj->name) {
+			DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
+				       obj, obj->name,
+				       obj->read_domains, obj->write_domain,
+				       obj_priv->last_rendering_seqno);
+		} else {
+			DRM_PROC_PRINT("       %p: %08x %08x %d\n",
+				       obj,
+				       obj->read_domains, obj->write_domain,
+				       obj_priv->last_rendering_seqno);
+		}
+	}
+	if (len > request + offset)
+		return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int i915_gem_flushing_info(char *buf, char **start, off_t offset,
+				  int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv;
+	int len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof = 0;
+	DRM_PROC_PRINT("Flushing:\n");
+	list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
+			    list)
+	{
+		struct drm_gem_object *obj = obj_priv->obj;
+		if (obj->name) {
+			DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
+				       obj, obj->name,
+				       obj->read_domains, obj->write_domain,
+				       obj_priv->last_rendering_seqno);
+		} else {
+			DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
+				       obj->read_domains, obj->write_domain,
+				       obj_priv->last_rendering_seqno);
+		}
+	}
+	if (len > request + offset)
+		return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int i915_gem_inactive_info(char *buf, char **start, off_t offset,
+				  int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv;
+	int len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof = 0;
+	DRM_PROC_PRINT("Inactive:\n");
+	list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
+			    list)
+	{
+		struct drm_gem_object *obj = obj_priv->obj;
+		if (obj->name) {
+			DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
+				       obj, obj->name,
+				       obj->read_domains, obj->write_domain,
+				       obj_priv->last_rendering_seqno);
+		} else {
+			DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
+				       obj->read_domains, obj->write_domain,
+				       obj_priv->last_rendering_seqno);
+		}
+	}
+	if (len > request + offset)
+		return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int i915_gem_request_info(char *buf, char **start, off_t offset,
+				 int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_request *gem_request;
+	int len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof = 0;
+	DRM_PROC_PRINT("Request:\n");
+	list_for_each_entry(gem_request, &dev_priv->mm.request_list,
+			    list)
+	{
+		DRM_PROC_PRINT("    %d @ %d %08x\n",
+			       gem_request->seqno,
+			       (int) (jiffies - gem_request->emitted_jiffies),
+			       gem_request->flush_domains);
+	}
+	if (len > request + offset)
+		return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
+			       int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof = 0;
+	DRM_PROC_PRINT("Current sequence: %d\n", i915_get_gem_seqno(dev));
+	DRM_PROC_PRINT("Waiter sequence:  %d\n",
+		       dev_priv->mm.waiting_gem_seqno);
+	DRM_PROC_PRINT("IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
+	if (len > request + offset)
+		return request;
+	*eof = 1;
+	return len - offset;
+}
+
+
+static int i915_interrupt_info(char *buf, char **start, off_t offset,
+			       int request, int *eof, void *data)
+{
+	struct drm_minor *minor = (struct drm_minor *) data;
+	struct drm_device *dev = minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof = 0;
+	DRM_PROC_PRINT("Interrupt enable:    %08x\n",
+		       I915_READ(IER));
+	DRM_PROC_PRINT("Interrupt identity:  %08x\n",
+		       I915_READ(IIR));
+	DRM_PROC_PRINT("Interrupt mask:      %08x\n",
+		       I915_READ(IMR));
+	DRM_PROC_PRINT("Pipe A stat:         %08x\n",
+		       I915_READ(PIPEASTAT));
+	DRM_PROC_PRINT("Pipe B stat:         %08x\n",
+		       I915_READ(PIPEBSTAT));
+	DRM_PROC_PRINT("Interrupts received: %d\n",
+		       atomic_read(&dev_priv->irq_received));
+	DRM_PROC_PRINT("Current sequence:    %d\n",
+		       i915_get_gem_seqno(dev));
+	DRM_PROC_PRINT("Waiter sequence:     %d\n",
+		       dev_priv->mm.waiting_gem_seqno);
+	DRM_PROC_PRINT("IRQ sequence:        %d\n",
+		       dev_priv->mm.irq_gem_seqno);
+	if (len > request + offset)
+		return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static struct drm_proc_list {
+	/** file name */
+	const char *name;
+	/** proc callback*/
+	int (*f) (char *, char **, off_t, int, int *, void *);
+} i915_gem_proc_list[] = {
+	{"i915_gem_active", i915_gem_active_info},
+	{"i915_gem_flushing", i915_gem_flushing_info},
+	{"i915_gem_inactive", i915_gem_inactive_info},
+	{"i915_gem_request", i915_gem_request_info},
+	{"i915_gem_seqno", i915_gem_seqno_info},
+	{"i915_gem_interrupt", i915_interrupt_info},
+};
+
+#define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
+
+int i915_gem_proc_init(struct drm_minor *minor)
+{
+	struct proc_dir_entry *ent;
+	int i, j;
+
+	for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) {
+		ent = create_proc_entry(i915_gem_proc_list[i].name,
+					S_IFREG | S_IRUGO, minor->dev_root);
+		if (!ent) {
+			DRM_ERROR("Cannot create /proc/dri/.../%s\n",
+				  i915_gem_proc_list[i].name);
+			for (j = 0; j < i; j++)
+				remove_proc_entry(i915_gem_proc_list[i].name,
+						  minor->dev_root);
+			return -1;
+		}
+		ent->read_proc = i915_gem_proc_list[i].f;
+		ent->data = minor;
+	}
+	return 0;
+}
+
+void i915_gem_proc_cleanup(struct drm_minor *minor)
+{
+	int i;
+
+	if (!minor->dev_root)
+		return;
+
+	for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
+		remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
new file mode 100644
index 0000000..e8b85ac
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/** @file i915_gem_tiling.c
+ *
+ * Support for managing tiling state of buffer objects.
+ *
+ * The idea behind tiling is to increase cache hit rates by rearranging
+ * pixel data so that a group of pixel accesses are in the same cacheline.
+ * Performance improvement from doing this on the back/depth buffer are on
+ * the order of 30%.
+ *
+ * Intel architectures make this somewhat more complicated, though, by
+ * adjustments made to addressing of data when the memory is in interleaved
+ * mode (matched pairs of DIMMS) to improve memory bandwidth.
+ * For interleaved memory, the CPU sends every sequential 64 bytes
+ * to an alternate memory channel so it can get the bandwidth from both.
+ *
+ * The GPU also rearranges its accesses for increased bandwidth to interleaved
+ * memory, and it matches what the CPU does for non-tiled.  However, when tiled
+ * it does it a little differently, since one walks addresses not just in the
+ * X direction but also Y.  So, along with alternating channels when bit
+ * 6 of the address flips, it also alternates when other bits flip --  Bits 9
+ * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
+ * are common to both the 915 and 965-class hardware.
+ *
+ * The CPU also sometimes XORs in higher bits as well, to improve
+ * bandwidth doing strided access like we do so frequently in graphics.  This
+ * is called "Channel XOR Randomization" in the MCH documentation.  The result
+ * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
+ * decode.
+ *
+ * All of this bit 6 XORing has an effect on our memory management,
+ * as we need to make sure that the 3d driver can correctly address object
+ * contents.
+ *
+ * If we don't have interleaved memory, all tiling is safe and no swizzling is
+ * required.
+ *
+ * When bit 17 is XORed in, we simply refuse to tile at all.  Bit
+ * 17 is not just a page offset, so as we page an objet out and back in,
+ * individual pages in it will have different bit 17 addresses, resulting in
+ * each 64 bytes being swapped with its neighbor!
+ *
+ * Otherwise, if interleaved, we have to tell the 3d driver what the address
+ * swizzling it needs to do is, since it's writing with the CPU to the pages
+ * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
+ * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
+ * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
+ * to match what the GPU expects.
+ */
+
+/**
+ * Detects bit 6 swizzling of address lookup between IGD access and CPU
+ * access through main memory.
+ */
+void
+i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+
+	if (!IS_I9XX(dev)) {
+		/* As far as we know, the 865 doesn't have these bit 6
+		 * swizzling issues.
+		 */
+		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+	} else if ((!IS_I965G(dev) && !IS_G33(dev)) || IS_I965GM(dev) ||
+		   IS_GM45(dev)) {
+		uint32_t dcc;
+
+		/* On 915-945 and GM965, channel interleave by the CPU is
+		 * determined by DCC.  The CPU will alternate based on bit 6
+		 * in interleaved mode, and the GPU will then also alternate
+		 * on bit 6, 9, and 10 for X, but the CPU may also optionally
+		 * alternate based on bit 17 (XOR not disabled and XOR
+		 * bit == 17).
+		 */
+		dcc = I915_READ(DCC);
+		switch (dcc & DCC_ADDRESSING_MODE_MASK) {
+		case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
+		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
+			swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+			swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+			break;
+		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
+			if (IS_I915G(dev) || IS_I915GM(dev) ||
+			    dcc & DCC_CHANNEL_XOR_DISABLE) {
+				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+				swizzle_y = I915_BIT_6_SWIZZLE_9;
+			} else if (IS_I965GM(dev) || IS_GM45(dev)) {
+				/* GM965 only does bit 11-based channel
+				 * randomization
+				 */
+				swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
+				swizzle_y = I915_BIT_6_SWIZZLE_9_11;
+			} else {
+				/* Bit 17 or perhaps other swizzling */
+				swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+				swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+			}
+			break;
+		}
+		if (dcc == 0xffffffff) {
+			DRM_ERROR("Couldn't read from MCHBAR.  "
+				  "Disabling tiling.\n");
+			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+		}
+	} else {
+		/* The 965, G33, and newer, have a very flexible memory
+		 * configuration.  It will enable dual-channel mode
+		 * (interleaving) on as much memory as it can, and the GPU
+		 * will additionally sometimes enable different bit 6
+		 * swizzling for tiled objects from the CPU.
+		 *
+		 * Here's what I found on the G965:
+		 *    slot fill         memory size  swizzling
+		 * 0A   0B   1A   1B    1-ch   2-ch
+		 * 512  0    0    0     512    0     O
+		 * 512  0    512  0     16     1008  X
+		 * 512  0    0    512   16     1008  X
+		 * 0    512  0    512   16     1008  X
+		 * 1024 1024 1024 0     2048   1024  O
+		 *
+		 * We could probably detect this based on either the DRB
+		 * matching, which was the case for the swizzling required in
+		 * the table above, or from the 1-ch value being less than
+		 * the minimum size of a rank.
+		 */
+		if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
+			swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+			swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+		} else {
+			swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+			swizzle_y = I915_BIT_6_SWIZZLE_9;
+		}
+	}
+
+	dev_priv->mm.bit_6_swizzle_x = swizzle_x;
+	dev_priv->mm.bit_6_swizzle_y = swizzle_y;
+}
+
+/**
+ * Sets the tiling mode of an object, returning the required swizzling of
+ * bit 6 of addresses in the object.
+ */
+int
+i915_gem_set_tiling(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv)
+{
+	struct drm_i915_gem_set_tiling *args = data;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EINVAL;
+	obj_priv = obj->driver_private;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (args->tiling_mode == I915_TILING_NONE) {
+		obj_priv->tiling_mode = I915_TILING_NONE;
+		args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+	} else {
+		if (args->tiling_mode == I915_TILING_X)
+			args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
+		else
+			args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
+		/* If we can't handle the swizzling, make it untiled. */
+		if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
+			args->tiling_mode = I915_TILING_NONE;
+			args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+		}
+	}
+	obj_priv->tiling_mode = args->tiling_mode;
+
+	mutex_unlock(&dev->struct_mutex);
+
+	drm_gem_object_unreference(obj);
+
+	return 0;
+}
+
+/**
+ * Returns the current tiling mode and required bit 6 swizzling for the object.
+ */
+int
+i915_gem_get_tiling(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv)
+{
+	struct drm_i915_gem_get_tiling *args = data;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	if (obj == NULL)
+		return -EINVAL;
+	obj_priv = obj->driver_private;
+
+	mutex_lock(&dev->struct_mutex);
+
+	args->tiling_mode = obj_priv->tiling_mode;
+	switch (obj_priv->tiling_mode) {
+	case I915_TILING_X:
+		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
+		break;
+	case I915_TILING_Y:
+		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
+		break;
+	case I915_TILING_NONE:
+		args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+		break;
+	default:
+		DRM_ERROR("unknown tiling mode\n");
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+	drm_gem_object_unreference(obj);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index df03611..baae511 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -31,12 +31,92 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#define USER_INT_FLAG (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-
 #define MAX_NOPID ((u32)~0)
 
+/** These are the interrupts used by the driver */
+#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT |		\
+				    I915_ASLE_INTERRUPT |		\
+				    I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+				    I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+
+void
+i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	if ((dev_priv->irq_mask_reg & mask) != 0) {
+		dev_priv->irq_mask_reg &= ~mask;
+		I915_WRITE(IMR, dev_priv->irq_mask_reg);
+		(void) I915_READ(IMR);
+	}
+}
+
+static inline void
+i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	if ((dev_priv->irq_mask_reg & mask) != mask) {
+		dev_priv->irq_mask_reg |= mask;
+		I915_WRITE(IMR, dev_priv->irq_mask_reg);
+		(void) I915_READ(IMR);
+	}
+}
+
+/**
+ * i915_get_pipe - return the the pipe associated with a given plane
+ * @dev: DRM device
+ * @plane: plane to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a pipe number, since they may not always be equal.  This routine
+ * maps the given @plane back to a pipe number.
+ */
+static int
+i915_get_pipe(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 dspcntr;
+
+	dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
+
+	return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
+}
+
+/**
+ * i915_get_plane - return the the plane associated with a given pipe
+ * @dev: DRM device
+ * @pipe: pipe to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a plane number, since they may not always be equal.  This routine
+ * maps the given @pipe back to a plane number.
+ */
+static int
+i915_get_plane(struct drm_device *dev, int pipe)
+{
+	if (i915_get_pipe(dev, 0) == pipe)
+		return 0;
+	return 1;
+}
+
+/**
+ * i915_pipe_enabled - check if a pipe is enabled
+ * @dev: DRM device
+ * @pipe: pipe to check
+ *
+ * Reading certain registers when the pipe is disabled can hang the chip.
+ * Use this routine to make sure the PLL is running and the pipe is active
+ * before reading such registers if unsure.
+ */
+static int
+i915_pipe_enabled(struct drm_device *dev, int pipe)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
+
+	if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
+		return 1;
+
+	return 0;
+}
+
 /**
  * Emit blits for scheduled buffer swaps.
  *
@@ -48,8 +128,7 @@
 	unsigned long irqflags;
 	struct list_head *list, *tmp, hits, *hit;
 	int nhits, nrects, slice[2], upper[2], lower[2], i;
-	unsigned counter[2] = { atomic_read(&dev->vbl_received),
-				atomic_read(&dev->vbl_received2) };
+	unsigned counter[2];
 	struct drm_drawable_info *drw;
 	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	u32 cpp = dev_priv->cpp;
@@ -71,6 +150,9 @@
 		src_pitch >>= 2;
 	}
 
+	counter[0] = drm_vblank_count(dev, 0);
+	counter[1] = drm_vblank_count(dev, 1);
+
 	DRM_DEBUG("\n");
 
 	INIT_LIST_HEAD(&hits);
@@ -83,12 +165,14 @@
 	list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
 		drm_i915_vbl_swap_t *vbl_swap =
 			list_entry(list, drm_i915_vbl_swap_t, head);
+		int pipe = i915_get_pipe(dev, vbl_swap->plane);
 
-		if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
+		if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
 			continue;
 
 		list_del(list);
 		dev_priv->swaps_pending--;
+		drm_vblank_put(dev, pipe);
 
 		spin_unlock(&dev_priv->swaps_lock);
 		spin_lock(&dev->drw_lock);
@@ -181,7 +265,7 @@
 			drm_i915_vbl_swap_t *swap_hit =
 				list_entry(hit, drm_i915_vbl_swap_t, head);
 			struct drm_clip_rect *rect;
-			int num_rects, pipe;
+			int num_rects, plane;
 			unsigned short top, bottom;
 
 			drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -190,9 +274,9 @@
 				continue;
 
 			rect = drw->rects;
-			pipe = swap_hit->pipe;
-			top = upper[pipe];
-			bottom = lower[pipe];
+			plane = swap_hit->plane;
+			top = upper[plane];
+			bottom = lower[plane];
 
 			for (num_rects = drw->num_rects; num_rects--; rect++) {
 				int y1 = max(rect->y1, top);
@@ -229,61 +313,139 @@
 	}
 }
 
+u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	unsigned long high_frame;
+	unsigned long low_frame;
+	u32 high1, high2, low, count;
+	int pipe;
+
+	pipe = i915_get_pipe(dev, plane);
+	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
+	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+
+	if (!i915_pipe_enabled(dev, pipe)) {
+		DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+		return 0;
+	}
+
+	/*
+	 * High & low register fields aren't synchronized, so make sure
+	 * we get a low value that's stable across two reads of the high
+	 * register.
+	 */
+	do {
+		high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+			 PIPE_FRAME_HIGH_SHIFT);
+		low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+			PIPE_FRAME_LOW_SHIFT);
+		high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+			 PIPE_FRAME_HIGH_SHIFT);
+	} while (high1 != high2);
+
+	count = (high1 << 8) | low;
+
+	return count;
+}
+
+void
+i915_gem_vblank_work_handler(struct work_struct *work)
+{
+	drm_i915_private_t *dev_priv;
+	struct drm_device *dev;
+
+	dev_priv = container_of(work, drm_i915_private_t,
+				mm.vblank_work);
+	dev = dev_priv->dev;
+
+	mutex_lock(&dev->struct_mutex);
+	i915_vblank_tasklet(dev);
+	mutex_unlock(&dev->struct_mutex);
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 temp;
+	u32 iir;
 	u32 pipea_stats, pipeb_stats;
+	int vblank = 0;
 
-	pipea_stats = I915_READ(I915REG_PIPEASTAT);
-	pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+	atomic_inc(&dev_priv->irq_received);
 
-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
+	if (dev->pdev->msi_enabled)
+		I915_WRITE(IMR, ~0);
+	iir = I915_READ(IIR);
 
-	temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
-
-	DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
-
-	if (temp == 0)
+	if (iir == 0) {
+		if (dev->pdev->msi_enabled) {
+			I915_WRITE(IMR, dev_priv->irq_mask_reg);
+			(void) I915_READ(IMR);
+		}
 		return IRQ_NONE;
+	}
 
-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-	(void) I915_READ16(I915REG_INT_IDENTITY_R);
-	DRM_READMEMORYBARRIER();
+	/*
+	 * Clear the PIPE(A|B)STAT regs before the IIR otherwise
+	 * we may get extra interrupts.
+	 */
+	if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+		pipea_stats = I915_READ(PIPEASTAT);
+		if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
+			pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+					 PIPE_VBLANK_INTERRUPT_ENABLE);
+		else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
+					PIPE_VBLANK_INTERRUPT_STATUS)) {
+			vblank++;
+			drm_handle_vblank(dev, i915_get_plane(dev, 0));
+		}
 
-	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+		I915_WRITE(PIPEASTAT, pipea_stats);
+	}
+	if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
+		pipeb_stats = I915_READ(PIPEBSTAT);
+		/* Ack the event */
+		I915_WRITE(PIPEBSTAT, pipeb_stats);
 
-	if (temp & USER_INT_FLAG)
+		/* The vblank interrupt gets enabled even if we didn't ask for
+		   it, so make sure it's shut down again */
+		if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
+			pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+					 PIPE_VBLANK_INTERRUPT_ENABLE);
+		else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
+					PIPE_VBLANK_INTERRUPT_STATUS)) {
+			vblank++;
+			drm_handle_vblank(dev, i915_get_plane(dev, 1));
+		}
+
+		if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
+			opregion_asle_intr(dev);
+		I915_WRITE(PIPEBSTAT, pipeb_stats);
+	}
+
+	I915_WRITE(IIR, iir);
+	if (dev->pdev->msi_enabled)
+		I915_WRITE(IMR, dev_priv->irq_mask_reg);
+	(void) I915_READ(IIR); /* Flush posted writes */
+
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->last_dispatch =
+			READ_BREADCRUMB(dev_priv);
+
+	if (iir & I915_USER_INTERRUPT) {
+		dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
 		DRM_WAKEUP(&dev_priv->irq_queue);
+	}
 
-	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-		int vblank_pipe = dev_priv->vblank_pipe;
+	if (iir & I915_ASLE_INTERRUPT)
+		opregion_asle_intr(dev);
 
-		if ((vblank_pipe &
-		     (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-		    == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
-			if (temp & VSYNC_PIPEA_FLAG)
-				atomic_inc(&dev->vbl_received);
-			if (temp & VSYNC_PIPEB_FLAG)
-				atomic_inc(&dev->vbl_received2);
-		} else if (((temp & VSYNC_PIPEA_FLAG) &&
-			    (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
-			   ((temp & VSYNC_PIPEB_FLAG) &&
-			    (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-			atomic_inc(&dev->vbl_received);
-
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
-
-		if (dev_priv->swaps_pending > 0)
+	if (vblank && dev_priv->swaps_pending > 0) {
+		if (dev_priv->ring.ring_obj == NULL)
 			drm_locked_tasklet(dev, i915_vblank_tasklet);
-		I915_WRITE(I915REG_PIPEASTAT,
-			pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
-			I915_VBLANK_CLEAR);
-		I915_WRITE(I915REG_PIPEBSTAT,
-			pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
-			I915_VBLANK_CLEAR);
+		else
+			schedule_work(&dev_priv->mm.vblank_work);
 	}
 
 	return IRQ_HANDLED;
@@ -298,23 +460,45 @@
 
 	DRM_DEBUG("\n");
 
-	dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
-
+	dev_priv->counter++;
 	if (dev_priv->counter > 0x7FFFFFFFUL)
-		dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+		dev_priv->counter = 1;
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
 	BEGIN_LP_RING(6);
-	OUT_RING(CMD_STORE_DWORD_IDX);
-	OUT_RING(20);
+	OUT_RING(MI_STORE_DWORD_INDEX);
+	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
 	OUT_RING(dev_priv->counter);
 	OUT_RING(0);
 	OUT_RING(0);
-	OUT_RING(GFX_OP_USER_INTERRUPT);
+	OUT_RING(MI_USER_INTERRUPT);
 	ADVANCE_LP_RING();
 
 	return dev_priv->counter;
 }
 
+void i915_user_irq_get(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	spin_lock(&dev_priv->user_irq_lock);
+	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
+		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+	spin_unlock(&dev_priv->user_irq_lock);
+}
+
+void i915_user_irq_put(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	spin_lock(&dev_priv->user_irq_lock);
+	BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
+	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
+		i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+	spin_unlock(&dev_priv->user_irq_lock);
+}
+
 static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -323,55 +507,34 @@
 	DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
 		  READ_BREADCRUMB(dev_priv));
 
-	if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+	if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
+		if (dev_priv->sarea_priv) {
+			dev_priv->sarea_priv->last_dispatch =
+				READ_BREADCRUMB(dev_priv);
+		}
 		return 0;
+	}
 
-	dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
 
+	i915_user_irq_get(dev);
 	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
 		    READ_BREADCRUMB(dev_priv) >= irq_nr);
+	i915_user_irq_put(dev);
 
 	if (ret == -EBUSY) {
 		DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
 			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
 	}
 
-	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-	return ret;
-}
-
-static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
-				      atomic_t *counter)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	unsigned int cur_vblank;
-	int ret = 0;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(counter))
-			- *sequence) <= (1<<23)));
-
-	*sequence = cur_vblank;
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->last_dispatch =
+			READ_BREADCRUMB(dev_priv);
 
 	return ret;
 }
 
-
-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
-}
-
-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
-}
-
 /* Needs the lock as it touches the ring.
  */
 int i915_irq_emit(struct drm_device *dev, void *data,
@@ -381,14 +544,15 @@
 	drm_i915_irq_emit_t *emit = data;
 	int result;
 
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
+	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 	if (!dev_priv) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
-
+	mutex_lock(&dev->struct_mutex);
 	result = i915_emit_irq(dev);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
 		DRM_ERROR("copy_to_user\n");
@@ -414,18 +578,74 @@
 	return i915_wait_irq(dev, irqwait->irq_seq);
 }
 
-static void i915_enable_interrupt (struct drm_device *dev)
+int i915_enable_vblank(struct drm_device *dev, int plane)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 flag;
+	int pipe = i915_get_pipe(dev, plane);
+	u32	pipestat_reg = 0;
+	u32	pipestat;
 
-	flag = 0;
-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-		flag |= VSYNC_PIPEA_FLAG;
-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-		flag |= VSYNC_PIPEB_FLAG;
+	switch (pipe) {
+	case 0:
+		pipestat_reg = PIPEASTAT;
+		i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
+		break;
+	case 1:
+		pipestat_reg = PIPEBSTAT;
+		i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+		break;
+	default:
+		DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
+			  pipe);
+		break;
+	}
 
-	I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
+	if (pipestat_reg) {
+		pipestat = I915_READ(pipestat_reg);
+		if (IS_I965G(dev))
+			pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
+		else
+			pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
+		/* Clear any stale interrupt status */
+		pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+			     PIPE_VBLANK_INTERRUPT_STATUS);
+		I915_WRITE(pipestat_reg, pipestat);
+	}
+
+	return 0;
+}
+
+void i915_disable_vblank(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe = i915_get_pipe(dev, plane);
+	u32	pipestat_reg = 0;
+	u32	pipestat;
+
+	switch (pipe) {
+	case 0:
+		pipestat_reg = PIPEASTAT;
+		i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
+		break;
+	case 1:
+		pipestat_reg = PIPEBSTAT;
+		i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+		break;
+	default:
+		DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
+			  pipe);
+		break;
+	}
+
+	if (pipestat_reg) {
+		pipestat = I915_READ(pipestat_reg);
+		pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+			      PIPE_VBLANK_INTERRUPT_ENABLE);
+		/* Clear any stale interrupt status */
+		pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+			     PIPE_VBLANK_INTERRUPT_STATUS);
+		I915_WRITE(pipestat_reg, pipestat);
+	}
 }
 
 /* Set the vblank monitor pipe
@@ -434,22 +654,12 @@
 			 struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	drm_i915_vblank_pipe_t *pipe = data;
 
 	if (!dev_priv) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
 
-	if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
-		DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
-		return -EINVAL;
-	}
-
-	dev_priv->vblank_pipe = pipe->pipe;
-
-	i915_enable_interrupt (dev);
-
 	return 0;
 }
 
@@ -458,19 +668,13 @@
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_vblank_pipe_t *pipe = data;
-	u16 flag;
 
 	if (!dev_priv) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
 
-	flag = I915_READ(I915REG_INT_ENABLE_R);
-	pipe->pipe = 0;
-	if (flag & VSYNC_PIPEA_FLAG)
-		pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-	if (flag & VSYNC_PIPEB_FLAG)
-		pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
+	pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
 	return 0;
 }
@@ -484,11 +688,12 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_vblank_swap_t *swap = data;
 	drm_i915_vbl_swap_t *vbl_swap;
-	unsigned int pipe, seqtype, curseq;
+	unsigned int pipe, seqtype, curseq, plane;
 	unsigned long irqflags;
 	struct list_head *list;
+	int ret;
 
-	if (!dev_priv) {
+	if (!dev_priv || !dev_priv->sarea_priv) {
 		DRM_ERROR("%s called with no initialization\n", __func__);
 		return -EINVAL;
 	}
@@ -504,7 +709,8 @@
 		return -EINVAL;
 	}
 
-	pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+	plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+	pipe = i915_get_pipe(dev, plane);
 
 	seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
 
@@ -523,7 +729,14 @@
 
 	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
-	curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+	/*
+	 * We take the ref here and put it when the swap actually completes
+	 * in the tasklet.
+	 */
+	ret = drm_vblank_get(dev, pipe);
+	if (ret)
+		return ret;
+	curseq = drm_vblank_count(dev, pipe);
 
 	if (seqtype == _DRM_VBLANK_RELATIVE)
 		swap->sequence += curseq;
@@ -533,6 +746,7 @@
 			swap->sequence = curseq + 1;
 		} else {
 			DRM_DEBUG("Missed target sequence\n");
+			drm_vblank_put(dev, pipe);
 			return -EINVAL;
 		}
 	}
@@ -543,7 +757,7 @@
 		vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
 
 		if (vbl_swap->drw_id == swap->drawable &&
-		    vbl_swap->pipe == pipe &&
+		    vbl_swap->plane == plane &&
 		    vbl_swap->sequence == swap->sequence) {
 			spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
 			DRM_DEBUG("Already scheduled\n");
@@ -555,6 +769,7 @@
 
 	if (dev_priv->swaps_pending >= 100) {
 		DRM_DEBUG("Too many swaps queued\n");
+		drm_vblank_put(dev, pipe);
 		return -EBUSY;
 	}
 
@@ -562,13 +777,14 @@
 
 	if (!vbl_swap) {
 		DRM_ERROR("Failed to allocate memory to queue swap\n");
+		drm_vblank_put(dev, pipe);
 		return -ENOMEM;
 	}
 
 	DRM_DEBUG("\n");
 
 	vbl_swap->drw_id = swap->drawable;
-	vbl_swap->pipe = pipe;
+	vbl_swap->plane = plane;
 	vbl_swap->sequence = swap->sequence;
 
 	spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
@@ -587,37 +803,63 @@
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	I915_WRITE16(I915REG_HWSTAM, 0xfffe);
-	I915_WRITE16(I915REG_INT_MASK_R, 0x0);
-	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+	I915_WRITE(HWSTAM, 0xeffe);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
 }
 
-void i915_driver_irq_postinstall(struct drm_device * dev)
+int i915_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int ret, num_pipes = 2;
 
 	spin_lock_init(&dev_priv->swaps_lock);
 	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
 	dev_priv->swaps_pending = 0;
 
-	if (!dev_priv->vblank_pipe)
-		dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
-	i915_enable_interrupt(dev);
+	/* Set initial unmasked IRQs to just the selected vblank pipes. */
+	dev_priv->irq_mask_reg = ~0;
+
+	ret = drm_vblank_init(dev, num_pipes);
+	if (ret)
+		return ret;
+
+	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+	dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
+	dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
+
+	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
+	dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
+
+	I915_WRITE(IMR, dev_priv->irq_mask_reg);
+	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
+	(void) I915_READ(IER);
+
+	opregion_enable_asle(dev);
 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+
+	return 0;
 }
 
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 temp;
+	u32 temp;
 
 	if (!dev_priv)
 		return;
 
-	I915_WRITE16(I915REG_HWSTAM, 0xffff);
-	I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
-	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+	dev_priv->vblank_pipe = 0;
 
-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+	I915_WRITE(HWSTAM, 0xffffffff);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
+
+	temp = I915_READ(PIPEASTAT);
+	I915_WRITE(PIPEASTAT, temp);
+	temp = I915_READ(PIPEBSTAT);
+	I915_WRITE(PIPEBSTAT, temp);
+	temp = I915_READ(IIR);
+	I915_WRITE(IIR, temp);
 }
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
new file mode 100644
index 0000000..1787a0c
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_opregion.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2008 Intel Corporation <hong.liu@intel.com>
+ * Copyright 2008 Red Hat <mjg@redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/acpi.h>
+
+#include "drmP.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define PCI_ASLE 0xe4
+#define PCI_LBPC 0xf4
+#define PCI_ASLS 0xfc
+
+#define OPREGION_SZ            (8*1024)
+#define OPREGION_HEADER_OFFSET 0
+#define OPREGION_ACPI_OFFSET   0x100
+#define OPREGION_SWSCI_OFFSET  0x200
+#define OPREGION_ASLE_OFFSET   0x300
+#define OPREGION_VBT_OFFSET    0x1000
+
+#define OPREGION_SIGNATURE "IntelGraphicsMem"
+#define MBOX_ACPI      (1<<0)
+#define MBOX_SWSCI     (1<<1)
+#define MBOX_ASLE      (1<<2)
+
+struct opregion_header {
+       u8 signature[16];
+       u32 size;
+       u32 opregion_ver;
+       u8 bios_ver[32];
+       u8 vbios_ver[16];
+       u8 driver_ver[16];
+       u32 mboxes;
+       u8 reserved[164];
+} __attribute__((packed));
+
+/* OpRegion mailbox #1: public ACPI methods */
+struct opregion_acpi {
+       u32 drdy;       /* driver readiness */
+       u32 csts;       /* notification status */
+       u32 cevt;       /* current event */
+       u8 rsvd1[20];
+       u32 didl[8];    /* supported display devices ID list */
+       u32 cpdl[8];    /* currently presented display list */
+       u32 cadl[8];    /* currently active display list */
+       u32 nadl[8];    /* next active devices list */
+       u32 aslp;       /* ASL sleep time-out */
+       u32 tidx;       /* toggle table index */
+       u32 chpd;       /* current hotplug enable indicator */
+       u32 clid;       /* current lid state*/
+       u32 cdck;       /* current docking state */
+       u32 sxsw;       /* Sx state resume */
+       u32 evts;       /* ASL supported events */
+       u32 cnot;       /* current OS notification */
+       u32 nrdy;       /* driver status */
+       u8 rsvd2[60];
+} __attribute__((packed));
+
+/* OpRegion mailbox #2: SWSCI */
+struct opregion_swsci {
+       u32 scic;       /* SWSCI command|status|data */
+       u32 parm;       /* command parameters */
+       u32 dslp;       /* driver sleep time-out */
+       u8 rsvd[244];
+} __attribute__((packed));
+
+/* OpRegion mailbox #3: ASLE */
+struct opregion_asle {
+       u32 ardy;       /* driver readiness */
+       u32 aslc;       /* ASLE interrupt command */
+       u32 tche;       /* technology enabled indicator */
+       u32 alsi;       /* current ALS illuminance reading */
+       u32 bclp;       /* backlight brightness to set */
+       u32 pfit;       /* panel fitting state */
+       u32 cblv;       /* current brightness level */
+       u16 bclm[20];   /* backlight level duty cycle mapping table */
+       u32 cpfm;       /* current panel fitting mode */
+       u32 epfm;       /* enabled panel fitting modes */
+       u8 plut[74];    /* panel LUT and identifier */
+       u32 pfmb;       /* PWM freq and min brightness */
+       u8 rsvd[102];
+} __attribute__((packed));
+
+/* ASLE irq request bits */
+#define ASLE_SET_ALS_ILLUM     (1 << 0)
+#define ASLE_SET_BACKLIGHT     (1 << 1)
+#define ASLE_SET_PFIT          (1 << 2)
+#define ASLE_SET_PWM_FREQ      (1 << 3)
+#define ASLE_REQ_MSK           0xf
+
+/* response bits of ASLE irq request */
+#define ASLE_ALS_ILLUM_FAIL    (2<<10)
+#define ASLE_BACKLIGHT_FAIL    (2<<12)
+#define ASLE_PFIT_FAIL         (2<<14)
+#define ASLE_PWM_FREQ_FAIL     (2<<16)
+
+/* ASLE backlight brightness to set */
+#define ASLE_BCLP_VALID                (1<<31)
+#define ASLE_BCLP_MSK          (~(1<<31))
+
+/* ASLE panel fitting request */
+#define ASLE_PFIT_VALID         (1<<31)
+#define ASLE_PFIT_CENTER (1<<0)
+#define ASLE_PFIT_STRETCH_TEXT (1<<1)
+#define ASLE_PFIT_STRETCH_GFX (1<<2)
+
+/* PWM frequency and minimum brightness */
+#define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
+#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
+#define ASLE_PFMB_PWM_MASK (0x7ffffe00)
+#define ASLE_PFMB_PWM_VALID (1<<31)
+
+#define ASLE_CBLV_VALID         (1<<31)
+
+static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct opregion_asle *asle = dev_priv->opregion.asle;
+	u32 blc_pwm_ctl, blc_pwm_ctl2;
+
+	if (!(bclp & ASLE_BCLP_VALID))
+		return ASLE_BACKLIGHT_FAIL;
+
+	bclp &= ASLE_BCLP_MSK;
+	if (bclp < 0 || bclp > 255)
+		return ASLE_BACKLIGHT_FAIL;
+
+	blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
+	blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+	blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
+
+	if (blc_pwm_ctl2 & BLM_COMBINATION_MODE)
+		pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
+	else
+		I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | ((bclp * 0x101)-1));
+
+	asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
+
+	return 0;
+}
+
+static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
+{
+	/* alsi is the current ALS reading in lux. 0 indicates below sensor
+	   range, 0xffff indicates above sensor range. 1-0xfffe are valid */
+	return 0;
+}
+
+static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (pfmb & ASLE_PFMB_PWM_VALID) {
+		u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
+		u32 pwm = pfmb & ASLE_PFMB_PWM_MASK;
+		blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
+		pwm = pwm >> 9;
+		/* FIXME - what do we do with the PWM? */
+	}
+	return 0;
+}
+
+static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
+{
+	/* Panel fitting is currently controlled by the X code, so this is a
+	   noop until modesetting support works fully */
+	if (!(pfit & ASLE_PFIT_VALID))
+		return ASLE_PFIT_FAIL;
+	return 0;
+}
+
+void opregion_asle_intr(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct opregion_asle *asle = dev_priv->opregion.asle;
+	u32 asle_stat = 0;
+	u32 asle_req;
+
+	if (!asle)
+		return;
+
+	asle_req = asle->aslc & ASLE_REQ_MSK;
+
+	if (!asle_req) {
+		DRM_DEBUG("non asle set request??\n");
+		return;
+	}
+
+	if (asle_req & ASLE_SET_ALS_ILLUM)
+		asle_stat |= asle_set_als_illum(dev, asle->alsi);
+
+	if (asle_req & ASLE_SET_BACKLIGHT)
+		asle_stat |= asle_set_backlight(dev, asle->bclp);
+
+	if (asle_req & ASLE_SET_PFIT)
+		asle_stat |= asle_set_pfit(dev, asle->pfit);
+
+	if (asle_req & ASLE_SET_PWM_FREQ)
+		asle_stat |= asle_set_pwm_freq(dev, asle->pfmb);
+
+	asle->aslc = asle_stat;
+}
+
+#define ASLE_ALS_EN    (1<<0)
+#define ASLE_BLC_EN    (1<<1)
+#define ASLE_PFIT_EN   (1<<2)
+#define ASLE_PFMB_EN   (1<<3)
+
+void opregion_enable_asle(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct opregion_asle *asle = dev_priv->opregion.asle;
+
+	if (asle) {
+		u32 pipeb_stats = I915_READ(PIPEBSTAT);
+		if (IS_MOBILE(dev)) {
+			/* Many devices trigger events with a write to the
+			   legacy backlight controller, so we need to ensure
+			   that it's able to generate interrupts */
+			I915_WRITE(PIPEBSTAT, pipeb_stats |=
+				   I915_LEGACY_BLC_EVENT_ENABLE);
+			i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT |
+					I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
+		} else
+			i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT);
+
+		asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
+			ASLE_PFMB_EN;
+		asle->ardy = 1;
+	}
+}
+
+#define ACPI_EV_DISPLAY_SWITCH (1<<0)
+#define ACPI_EV_LID            (1<<1)
+#define ACPI_EV_DOCK           (1<<2)
+
+static struct intel_opregion *system_opregion;
+
+int intel_opregion_video_event(struct notifier_block *nb, unsigned long val,
+			       void *data)
+{
+	/* The only video events relevant to opregion are 0x80. These indicate
+	   either a docking event, lid switch or display switch request. In
+	   Linux, these are handled by the dock, button and video drivers.
+	   We might want to fix the video driver to be opregion-aware in
+	   future, but right now we just indicate to the firmware that the
+	   request has been handled */
+
+	struct opregion_acpi *acpi;
+
+	if (!system_opregion)
+		return NOTIFY_DONE;
+
+	acpi = system_opregion->acpi;
+	acpi->csts = 0;
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block intel_opregion_notifier = {
+	.notifier_call = intel_opregion_video_event,
+};
+
+int intel_opregion_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_opregion *opregion = &dev_priv->opregion;
+	void *base;
+	u32 asls, mboxes;
+	int err = 0;
+
+	pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
+	DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls);
+	if (asls == 0) {
+		DRM_DEBUG("ACPI OpRegion not supported!\n");
+		return -ENOTSUPP;
+	}
+
+	base = ioremap(asls, OPREGION_SZ);
+	if (!base)
+		return -ENOMEM;
+
+	opregion->header = base;
+	if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
+		DRM_DEBUG("opregion signature mismatch\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	mboxes = opregion->header->mboxes;
+	if (mboxes & MBOX_ACPI) {
+		DRM_DEBUG("Public ACPI methods supported\n");
+		opregion->acpi = base + OPREGION_ACPI_OFFSET;
+	} else {
+		DRM_DEBUG("Public ACPI methods not supported\n");
+		err = -ENOTSUPP;
+		goto err_out;
+	}
+	opregion->enabled = 1;
+
+	if (mboxes & MBOX_SWSCI) {
+		DRM_DEBUG("SWSCI supported\n");
+		opregion->swsci = base + OPREGION_SWSCI_OFFSET;
+	}
+	if (mboxes & MBOX_ASLE) {
+		DRM_DEBUG("ASLE supported\n");
+		opregion->asle = base + OPREGION_ASLE_OFFSET;
+	}
+
+	/* Notify BIOS we are ready to handle ACPI video ext notifs.
+	 * Right now, all the events are handled by the ACPI video module.
+	 * We don't actually need to do anything with them. */
+	opregion->acpi->csts = 0;
+	opregion->acpi->drdy = 1;
+
+	system_opregion = opregion;
+	register_acpi_notifier(&intel_opregion_notifier);
+
+	return 0;
+
+err_out:
+	iounmap(opregion->header);
+	opregion->header = NULL;
+	return err;
+}
+
+void intel_opregion_free(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_opregion *opregion = &dev_priv->opregion;
+
+	if (!opregion->enabled)
+		return;
+
+	opregion->acpi->drdy = 0;
+
+	system_opregion = NULL;
+	unregister_acpi_notifier(&intel_opregion_notifier);
+
+	/* just clear all opregion memory pointers now */
+	iounmap(opregion->header);
+	opregion->header = NULL;
+	opregion->acpi = NULL;
+	opregion->swsci = NULL;
+	opregion->asle = NULL;
+
+	opregion->enabled = 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
new file mode 100644
index 0000000..5c2d9f2
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -0,0 +1,1417 @@
+/* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _I915_REG_H_
+#define _I915_REG_H_
+
+/*
+ * The Bridge device's PCI config space has information about the
+ * fb aperture size and the amount of pre-reserved memory.
+ */
+#define INTEL_GMCH_CTRL		0x52
+#define INTEL_GMCH_ENABLED	0x4
+#define INTEL_GMCH_MEM_MASK	0x1
+#define INTEL_GMCH_MEM_64M	0x1
+#define INTEL_GMCH_MEM_128M	0
+
+#define INTEL_855_GMCH_GMS_MASK		(0x7 << 4)
+#define INTEL_855_GMCH_GMS_DISABLED	(0x0 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_1M	(0x1 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_4M	(0x2 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_8M	(0x3 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_16M	(0x4 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_32M	(0x5 << 4)
+
+#define INTEL_915G_GMCH_GMS_STOLEN_48M	(0x6 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_64M	(0x7 << 4)
+
+/* PCI config space */
+
+#define HPLLCC	0xc0 /* 855 only */
+#define   GC_CLOCK_CONTROL_MASK		(3 << 0)
+#define   GC_CLOCK_133_200		(0 << 0)
+#define   GC_CLOCK_100_200		(1 << 0)
+#define   GC_CLOCK_100_133		(2 << 0)
+#define   GC_CLOCK_166_250		(3 << 0)
+#define GCFGC	0xf0 /* 915+ only */
+#define   GC_LOW_FREQUENCY_ENABLE	(1 << 7)
+#define   GC_DISPLAY_CLOCK_190_200_MHZ	(0 << 4)
+#define   GC_DISPLAY_CLOCK_333_MHZ	(4 << 4)
+#define   GC_DISPLAY_CLOCK_MASK		(7 << 4)
+#define LBB	0xf4
+
+/* VGA stuff */
+
+#define VGA_ST01_MDA 0x3ba
+#define VGA_ST01_CGA 0x3da
+
+#define VGA_MSR_WRITE 0x3c2
+#define VGA_MSR_READ 0x3cc
+#define   VGA_MSR_MEM_EN (1<<1)
+#define   VGA_MSR_CGA_MODE (1<<0)
+
+#define VGA_SR_INDEX 0x3c4
+#define VGA_SR_DATA 0x3c5
+
+#define VGA_AR_INDEX 0x3c0
+#define   VGA_AR_VID_EN (1<<5)
+#define VGA_AR_DATA_WRITE 0x3c0
+#define VGA_AR_DATA_READ 0x3c1
+
+#define VGA_GR_INDEX 0x3ce
+#define VGA_GR_DATA 0x3cf
+/* GR05 */
+#define   VGA_GR_MEM_READ_MODE_SHIFT 3
+#define     VGA_GR_MEM_READ_MODE_PLANE 1
+/* GR06 */
+#define   VGA_GR_MEM_MODE_MASK 0xc
+#define   VGA_GR_MEM_MODE_SHIFT 2
+#define   VGA_GR_MEM_A0000_AFFFF 0
+#define   VGA_GR_MEM_A0000_BFFFF 1
+#define   VGA_GR_MEM_B0000_B7FFF 2
+#define   VGA_GR_MEM_B0000_BFFFF 3
+
+#define VGA_DACMASK 0x3c6
+#define VGA_DACRX 0x3c7
+#define VGA_DACWX 0x3c8
+#define VGA_DACDATA 0x3c9
+
+#define VGA_CR_INDEX_MDA 0x3b4
+#define VGA_CR_DATA_MDA 0x3b5
+#define VGA_CR_INDEX_CGA 0x3d4
+#define VGA_CR_DATA_CGA 0x3d5
+
+/*
+ * Memory interface instructions used by the kernel
+ */
+#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
+
+#define MI_NOOP			MI_INSTR(0, 0)
+#define MI_USER_INTERRUPT	MI_INSTR(0x02, 0)
+#define MI_WAIT_FOR_EVENT       MI_INSTR(0x03, 0)
+#define   MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
+#define   MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define   MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+#define MI_FLUSH		MI_INSTR(0x04, 0)
+#define   MI_READ_FLUSH		(1 << 0)
+#define   MI_EXE_FLUSH		(1 << 1)
+#define   MI_NO_WRITE_FLUSH	(1 << 2)
+#define   MI_SCENE_COUNT	(1 << 3) /* just increment scene count */
+#define   MI_END_SCENE		(1 << 4) /* flush binner and incr scene count */
+#define MI_BATCH_BUFFER_END	MI_INSTR(0x0a, 0)
+#define MI_REPORT_HEAD		MI_INSTR(0x07, 0)
+#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
+#define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
+#define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
+#define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
+#define   MI_STORE_DWORD_INDEX_SHIFT 2
+#define MI_LOAD_REGISTER_IMM	MI_INSTR(0x22, 1)
+#define MI_BATCH_BUFFER		MI_INSTR(0x30, 1)
+#define   MI_BATCH_NON_SECURE	(1)
+#define   MI_BATCH_NON_SECURE_I965 (1<<8)
+#define MI_BATCH_BUFFER_START	MI_INSTR(0x31, 0)
+
+/*
+ * 3D instructions used by the kernel
+ */
+#define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags))
+
+#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define   SC_UPDATE_SCISSOR       (0x1<<1)
+#define   SC_ENABLE_MASK          (0x1<<0)
+#define   SC_ENABLE               (0x1<<0)
+#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define   SCI_YMIN_MASK      (0xffff<<16)
+#define   SCI_XMIN_MASK      (0xffff<<0)
+#define   SCI_YMAX_MASK      (0xffff<<16)
+#define   SCI_XMAX_MASK      (0xffff<<0)
+#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
+#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
+#define XY_SRC_COPY_BLT_CMD		((2<<29)|(0x53<<22)|6)
+#define XY_MONO_SRC_COPY_IMM_BLT	((2<<29)|(0x71<<22)|5)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB	(1<<20)
+#define   BLT_DEPTH_8			(0<<24)
+#define   BLT_DEPTH_16_565		(1<<24)
+#define   BLT_DEPTH_16_1555		(2<<24)
+#define   BLT_DEPTH_32			(3<<24)
+#define   BLT_ROP_GXCOPY		(0xcc<<16)
+#define XY_SRC_COPY_BLT_SRC_TILED	(1<<15) /* 965+ only */
+#define XY_SRC_COPY_BLT_DST_TILED	(1<<11) /* 965+ only */
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define   ASYNC_FLIP                (1<<22)
+#define   DISPLAY_PLANE_A           (0<<20)
+#define   DISPLAY_PLANE_B           (1<<20)
+
+/*
+ * Instruction and interrupt control regs
+ */
+
+#define PRB0_TAIL	0x02030
+#define PRB0_HEAD	0x02034
+#define PRB0_START	0x02038
+#define PRB0_CTL	0x0203c
+#define   TAIL_ADDR		0x001FFFF8
+#define   HEAD_WRAP_COUNT	0xFFE00000
+#define   HEAD_WRAP_ONE		0x00200000
+#define   HEAD_ADDR		0x001FFFFC
+#define   RING_NR_PAGES		0x001FF000
+#define   RING_REPORT_MASK	0x00000006
+#define   RING_REPORT_64K	0x00000002
+#define   RING_REPORT_128K	0x00000004
+#define   RING_NO_REPORT	0x00000000
+#define   RING_VALID_MASK	0x00000001
+#define   RING_VALID		0x00000001
+#define   RING_INVALID		0x00000000
+#define PRB1_TAIL	0x02040 /* 915+ only */
+#define PRB1_HEAD	0x02044 /* 915+ only */
+#define PRB1_START	0x02048 /* 915+ only */
+#define PRB1_CTL	0x0204c /* 915+ only */
+#define ACTHD_I965	0x02074
+#define HWS_PGA		0x02080
+#define HWS_ADDRESS_MASK	0xfffff000
+#define HWS_START_ADDRESS_SHIFT	4
+#define IPEIR		0x02088
+#define NOPID		0x02094
+#define HWSTAM		0x02098
+#define SCPD0		0x0209c /* 915+ only */
+#define IER		0x020a0
+#define IIR		0x020a4
+#define IMR		0x020a8
+#define ISR		0x020ac
+#define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT		(1<<18)
+#define   I915_DISPLAY_PORT_INTERRUPT			(1<<17)
+#define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT	(1<<15)
+#define   I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT	(1<<14)
+#define   I915_HWB_OOM_INTERRUPT			(1<<13)
+#define   I915_SYNC_STATUS_INTERRUPT			(1<<12)
+#define   I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT	(1<<11)
+#define   I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT	(1<<10)
+#define   I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT	(1<<9)
+#define   I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT	(1<<8)
+#define   I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT		(1<<7)
+#define   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT		(1<<6)
+#define   I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT		(1<<5)
+#define   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT		(1<<4)
+#define   I915_DEBUG_INTERRUPT				(1<<2)
+#define   I915_USER_INTERRUPT				(1<<1)
+#define   I915_ASLE_INTERRUPT				(1<<0)
+#define EIR		0x020b0
+#define EMR		0x020b4
+#define ESR		0x020b8
+#define INSTPM	        0x020c0
+#define ACTHD	        0x020c8
+#define FW_BLC		0x020d8
+#define FW_BLC_SELF	0x020e0 /* 915+ only */
+#define MI_ARB_STATE	0x020e4 /* 915+ only */
+#define CACHE_MODE_0	0x02120 /* 915+ only */
+#define   CM0_MASK_SHIFT          16
+#define   CM0_IZ_OPT_DISABLE      (1<<6)
+#define   CM0_ZR_OPT_DISABLE      (1<<5)
+#define   CM0_DEPTH_EVICT_DISABLE (1<<4)
+#define   CM0_COLOR_EVICT_DISABLE (1<<3)
+#define   CM0_DEPTH_WRITE_DISABLE (1<<1)
+#define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
+#define GFX_FLSH_CNTL	0x02170 /* 915+ only */
+
+/*
+ * Framebuffer compression (915+ only)
+ */
+
+#define FBC_CFB_BASE		0x03200 /* 4k page aligned */
+#define FBC_LL_BASE		0x03204 /* 4k page aligned */
+#define FBC_CONTROL		0x03208
+#define   FBC_CTL_EN		(1<<31)
+#define   FBC_CTL_PERIODIC	(1<<30)
+#define   FBC_CTL_INTERVAL_SHIFT (16)
+#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define   FBC_CTL_STRIDE_SHIFT	(5)
+#define   FBC_CTL_FENCENO	(1<<0)
+#define FBC_COMMAND		0x0320c
+#define   FBC_CMD_COMPRESS	(1<<0)
+#define FBC_STATUS		0x03210
+#define   FBC_STAT_COMPRESSING	(1<<31)
+#define   FBC_STAT_COMPRESSED	(1<<30)
+#define   FBC_STAT_MODIFIED	(1<<29)
+#define   FBC_STAT_CURRENT_LINE	(1<<0)
+#define FBC_CONTROL2		0x03214
+#define   FBC_CTL_FENCE_DBL	(0<<4)
+#define   FBC_CTL_IDLE_IMM	(0<<2)
+#define   FBC_CTL_IDLE_FULL	(1<<2)
+#define   FBC_CTL_IDLE_LINE	(2<<2)
+#define   FBC_CTL_IDLE_DEBUG	(3<<2)
+#define   FBC_CTL_CPU_FENCE	(1<<1)
+#define   FBC_CTL_PLANEA	(0<<0)
+#define   FBC_CTL_PLANEB	(1<<0)
+#define FBC_FENCE_OFF		0x0321b
+
+#define FBC_LL_SIZE		(1536)
+
+/*
+ * GPIO regs
+ */
+#define GPIOA			0x5010
+#define GPIOB			0x5014
+#define GPIOC			0x5018
+#define GPIOD			0x501c
+#define GPIOE			0x5020
+#define GPIOF			0x5024
+#define GPIOG			0x5028
+#define GPIOH			0x502c
+# define GPIO_CLOCK_DIR_MASK		(1 << 0)
+# define GPIO_CLOCK_DIR_IN		(0 << 1)
+# define GPIO_CLOCK_DIR_OUT		(1 << 1)
+# define GPIO_CLOCK_VAL_MASK		(1 << 2)
+# define GPIO_CLOCK_VAL_OUT		(1 << 3)
+# define GPIO_CLOCK_VAL_IN		(1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE	(1 << 5)
+# define GPIO_DATA_DIR_MASK		(1 << 8)
+# define GPIO_DATA_DIR_IN		(0 << 9)
+# define GPIO_DATA_DIR_OUT		(1 << 9)
+# define GPIO_DATA_VAL_MASK		(1 << 10)
+# define GPIO_DATA_VAL_OUT		(1 << 11)
+# define GPIO_DATA_VAL_IN		(1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
+
+/*
+ * Clock control & power management
+ */
+
+#define VGA0	0x6000
+#define VGA1	0x6004
+#define VGA_PD	0x6010
+#define   VGA0_PD_P2_DIV_4	(1 << 7)
+#define   VGA0_PD_P1_DIV_2	(1 << 5)
+#define   VGA0_PD_P1_SHIFT	0
+#define   VGA0_PD_P1_MASK	(0x1f << 0)
+#define   VGA1_PD_P2_DIV_4	(1 << 15)
+#define   VGA1_PD_P1_DIV_2	(1 << 13)
+#define   VGA1_PD_P1_SHIFT	8
+#define   VGA1_PD_P1_MASK	(0x1f << 8)
+#define DPLL_A	0x06014
+#define DPLL_B	0x06018
+#define   DPLL_VCO_ENABLE		(1 << 31)
+#define   DPLL_DVO_HIGH_SPEED		(1 << 30)
+#define   DPLL_SYNCLOCK_ENABLE		(1 << 29)
+#define   DPLL_VGA_MODE_DIS		(1 << 28)
+#define   DPLLB_MODE_DAC_SERIAL		(1 << 26) /* i915 */
+#define   DPLLB_MODE_LVDS		(2 << 26) /* i915 */
+#define   DPLL_MODE_MASK		(3 << 26)
+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
+#define   DPLLB_LVDS_P2_CLOCK_DIV_14	(0 << 24) /* i915 */
+#define   DPLLB_LVDS_P2_CLOCK_DIV_7	(1 << 24) /* i915 */
+#define   DPLL_P2_CLOCK_DIV_MASK	0x03000000 /* i915 */
+#define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
+
+#define I915_FIFO_UNDERRUN_STATUS		(1UL<<31)
+#define I915_CRC_ERROR_ENABLE			(1UL<<29)
+#define I915_CRC_DONE_ENABLE			(1UL<<28)
+#define I915_GMBUS_EVENT_ENABLE			(1UL<<27)
+#define I915_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
+#define I915_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
+#define I915_DPST_EVENT_ENABLE			(1UL<<23)
+#define I915_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
+#define I915_ODD_FIELD_INTERRUPT_ENABLE		(1UL<<21)
+#define I915_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
+#define I915_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18)	/* 965 or later */
+#define I915_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
+#define I915_OVERLAY_UPDATED_ENABLE		(1UL<<16)
+#define I915_CRC_ERROR_INTERRUPT_STATUS		(1UL<<13)
+#define I915_CRC_DONE_INTERRUPT_STATUS		(1UL<<12)
+#define I915_GMBUS_INTERRUPT_STATUS		(1UL<<11)
+#define I915_VSYNC_INTERRUPT_STATUS		(1UL<<9)
+#define I915_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
+#define I915_DPST_EVENT_STATUS			(1UL<<7)
+#define I915_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
+#define I915_ODD_FIELD_INTERRUPT_STATUS		(1UL<<5)
+#define I915_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
+#define I915_START_VBLANK_INTERRUPT_STATUS	(1UL<<2)	/* 965 or later */
+#define I915_VBLANK_INTERRUPT_STATUS		(1UL<<1)
+#define I915_OVERLAY_UPDATED_STATUS		(1UL<<0)
+
+#define SRX_INDEX		0x3c4
+#define SRX_DATA		0x3c5
+#define SR01			1
+#define SR01_SCREEN_OFF		(1<<5)
+
+#define PPCR			0x61204
+#define PPCR_ON			(1<<0)
+
+#define DVOB			0x61140
+#define DVOB_ON			(1<<31)
+#define DVOC			0x61160
+#define DVOC_ON			(1<<31)
+#define LVDS			0x61180
+#define LVDS_ON			(1<<31)
+
+#define ADPA			0x61100
+#define ADPA_DPMS_MASK		(~(3<<10))
+#define ADPA_DPMS_ON		(0<<10)
+#define ADPA_DPMS_SUSPEND	(1<<10)
+#define ADPA_DPMS_STANDBY	(2<<10)
+#define ADPA_DPMS_OFF		(3<<10)
+
+#define RING_TAIL		0x00
+#define TAIL_ADDR		0x001FFFF8
+#define RING_HEAD		0x04
+#define HEAD_WRAP_COUNT		0xFFE00000
+#define HEAD_WRAP_ONE		0x00200000
+#define HEAD_ADDR		0x001FFFFC
+#define RING_START		0x08
+#define START_ADDR		0xFFFFF000
+#define RING_LEN		0x0C
+#define RING_NR_PAGES		0x001FF000
+#define RING_REPORT_MASK	0x00000006
+#define RING_REPORT_64K		0x00000002
+#define RING_REPORT_128K	0x00000004
+#define RING_NO_REPORT		0x00000000
+#define RING_VALID_MASK		0x00000001
+#define RING_VALID		0x00000001
+#define RING_INVALID		0x00000000
+
+/* Scratch pad debug 0 reg:
+ */
+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
+/*
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
+#define   DPLL_FPA01_P1_POST_DIV_SHIFT	16
+/* i830, required in DVO non-gang */
+#define   PLL_P2_DIVIDE_BY_4		(1 << 23)
+#define   PLL_P1_DIVIDE_BY_TWO		(1 << 21) /* i830 */
+#define   PLL_REF_INPUT_DREFCLK		(0 << 13)
+#define   PLL_REF_INPUT_TVCLKINA	(1 << 13) /* i830 */
+#define   PLL_REF_INPUT_TVCLKINBC	(2 << 13) /* SDVO TVCLKIN */
+#define   PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
+#define   PLL_REF_INPUT_MASK		(3 << 13)
+#define   PLL_LOAD_PULSE_PHASE_SHIFT		9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+#define   PLL_LOAD_PULSE_PHASE_MASK		(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+#define   DISPLAY_RATE_SELECT_FPA1		(1 << 8)
+/*
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ */
+#define   SDVO_MULTIPLIER_MASK			0x000000ff
+#define   SDVO_MULTIPLIER_SHIFT_HIRES		4
+#define   SDVO_MULTIPLIER_SHIFT_VGA		0
+#define DPLL_A_MD 0x0601c /* 965+ only */
+/*
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
+ */
+#define   DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
+#define   DPLL_MD_UDI_DIVIDER_SHIFT		24
+/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+#define   DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
+#define   DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
+/*
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+#define   DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
+#define   DPLL_MD_UDI_MULTIPLIER_SHIFT		8
+/*
+ * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+#define   DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
+#define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
+#define DPLL_B_MD 0x06020 /* 965+ only */
+#define FPA0	0x06040
+#define FPA1	0x06044
+#define FPB0	0x06048
+#define FPB1	0x0604c
+#define   FP_N_DIV_MASK		0x003f0000
+#define   FP_N_DIV_SHIFT		16
+#define   FP_M1_DIV_MASK	0x00003f00
+#define   FP_M1_DIV_SHIFT		 8
+#define   FP_M2_DIV_MASK	0x0000003f
+#define   FP_M2_DIV_SHIFT		 0
+#define DPLL_TEST	0x606c
+#define   DPLLB_TEST_SDVO_DIV_1		(0 << 22)
+#define   DPLLB_TEST_SDVO_DIV_2		(1 << 22)
+#define   DPLLB_TEST_SDVO_DIV_4		(2 << 22)
+#define   DPLLB_TEST_SDVO_DIV_MASK	(3 << 22)
+#define   DPLLB_TEST_N_BYPASS		(1 << 19)
+#define   DPLLB_TEST_M_BYPASS		(1 << 18)
+#define   DPLLB_INPUT_BUFFER_ENABLE	(1 << 16)
+#define   DPLLA_TEST_N_BYPASS		(1 << 3)
+#define   DPLLA_TEST_M_BYPASS		(1 << 2)
+#define   DPLLA_INPUT_BUFFER_ENABLE	(1 << 0)
+#define D_STATE		0x6104
+#define CG_2D_DIS	0x6200
+#define CG_3D_DIS	0x6204
+
+/*
+ * Palette regs
+ */
+
+#define PALETTE_A		0x0a000
+#define PALETTE_B		0x0a800
+
+/* MCH MMIO space */
+
+/*
+ * MCHBAR mirror.
+ *
+ * This mirrors the MCHBAR MMIO space whose location is determined by
+ * device 0 function 0's pci config register 0x44 or 0x48 and matches it in
+ * every way.  It is not accessible from the CP register read instructions.
+ *
+ */
+#define MCHBAR_MIRROR_BASE	0x10000
+
+/** 915-945 and GM965 MCH register controlling DRAM channel access */
+#define DCC			0x10200
+#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL		(0 << 0)
+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC	(1 << 0)
+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED	(2 << 0)
+#define DCC_ADDRESSING_MODE_MASK			(3 << 0)
+#define DCC_CHANNEL_XOR_DISABLE				(1 << 10)
+
+/** 965 MCH register controlling DRAM channel configuration */
+#define C0DRB3			0x10206
+#define C1DRB3			0x10606
+
+/*
+ * Overlay regs
+ */
+
+#define OVADD			0x30000
+#define DOVSTA			0x30008
+#define OC_BUF			(0x3<<20)
+#define OGAMC5			0x30010
+#define OGAMC4			0x30014
+#define OGAMC3			0x30018
+#define OGAMC2			0x3001c
+#define OGAMC1			0x30020
+#define OGAMC0			0x30024
+
+/*
+ * Display engine regs
+ */
+
+/* Pipe A timing regs */
+#define HTOTAL_A	0x60000
+#define HBLANK_A	0x60004
+#define HSYNC_A		0x60008
+#define VTOTAL_A	0x6000c
+#define VBLANK_A	0x60010
+#define VSYNC_A		0x60014
+#define PIPEASRC	0x6001c
+#define BCLRPAT_A	0x60020
+
+/* Pipe B timing regs */
+#define HTOTAL_B	0x61000
+#define HBLANK_B	0x61004
+#define HSYNC_B		0x61008
+#define VTOTAL_B	0x6100c
+#define VBLANK_B	0x61010
+#define VSYNC_B		0x61014
+#define PIPEBSRC	0x6101c
+#define BCLRPAT_B	0x61020
+
+/* VGA port control */
+#define ADPA			0x61100
+#define   ADPA_DAC_ENABLE	(1<<31)
+#define   ADPA_DAC_DISABLE	0
+#define   ADPA_PIPE_SELECT_MASK	(1<<30)
+#define   ADPA_PIPE_A_SELECT	0
+#define   ADPA_PIPE_B_SELECT	(1<<30)
+#define   ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define   ADPA_SETS_HVPOLARITY	0
+#define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define   ADPA_VSYNC_CNTL_ENABLE 0
+#define   ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define   ADPA_HSYNC_CNTL_ENABLE 0
+#define   ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define   ADPA_VSYNC_ACTIVE_LOW	0
+#define   ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define   ADPA_HSYNC_ACTIVE_LOW	0
+#define   ADPA_DPMS_MASK	(~(3<<10))
+#define   ADPA_DPMS_ON		(0<<10)
+#define   ADPA_DPMS_SUSPEND	(1<<10)
+#define   ADPA_DPMS_STANDBY	(2<<10)
+#define   ADPA_DPMS_OFF		(3<<10)
+
+/* Hotplug control (945+ only) */
+#define PORT_HOTPLUG_EN		0x61110
+#define   SDVOB_HOTPLUG_INT_EN			(1 << 26)
+#define   SDVOC_HOTPLUG_INT_EN			(1 << 25)
+#define   TV_HOTPLUG_INT_EN			(1 << 18)
+#define   CRT_HOTPLUG_INT_EN			(1 << 9)
+#define   CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
+
+#define PORT_HOTPLUG_STAT	0x61114
+#define   CRT_HOTPLUG_INT_STATUS		(1 << 11)
+#define   TV_HOTPLUG_INT_STATUS			(1 << 10)
+#define   CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
+#define   CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
+#define   CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
+#define   CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
+#define   SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
+#define   SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+
+/* SDVO port control */
+#define SDVOB			0x61140
+#define SDVOC			0x61160
+#define   SDVO_ENABLE		(1 << 31)
+#define   SDVO_PIPE_B_SELECT	(1 << 30)
+#define   SDVO_STALL_SELECT	(1 << 29)
+#define   SDVO_INTERRUPT_ENABLE	(1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define   SDVO_PORT_MULTIPLY_MASK	(7 << 23)
+#define   SDVO_PORT_MULTIPLY_SHIFT		23
+#define   SDVO_PHASE_SELECT_MASK	(15 << 19)
+#define   SDVO_PHASE_SELECT_DEFAULT	(6 << 19)
+#define   SDVO_CLOCK_OUTPUT_INVERT	(1 << 18)
+#define   SDVOC_GANG_MODE		(1 << 16)
+#define   SDVO_BORDER_ENABLE		(1 << 7)
+#define   SDVOB_PCIE_CONCURRENCY	(1 << 3)
+#define   SDVO_DETECTED			(1 << 2)
+/* Bits to be preserved when writing */
+#define   SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
+#define   SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26))
+
+/* DVO port control */
+#define DVOA			0x61120
+#define DVOB			0x61140
+#define DVOC			0x61160
+#define   DVO_ENABLE			(1 << 31)
+#define   DVO_PIPE_B_SELECT		(1 << 30)
+#define   DVO_PIPE_STALL_UNUSED		(0 << 28)
+#define   DVO_PIPE_STALL		(1 << 28)
+#define   DVO_PIPE_STALL_TV		(2 << 28)
+#define   DVO_PIPE_STALL_MASK		(3 << 28)
+#define   DVO_USE_VGA_SYNC		(1 << 15)
+#define   DVO_DATA_ORDER_I740		(0 << 14)
+#define   DVO_DATA_ORDER_FP		(1 << 14)
+#define   DVO_VSYNC_DISABLE		(1 << 11)
+#define   DVO_HSYNC_DISABLE		(1 << 10)
+#define   DVO_VSYNC_TRISTATE		(1 << 9)
+#define   DVO_HSYNC_TRISTATE		(1 << 8)
+#define   DVO_BORDER_ENABLE		(1 << 7)
+#define   DVO_DATA_ORDER_GBRG		(1 << 6)
+#define   DVO_DATA_ORDER_RGGB		(0 << 6)
+#define   DVO_DATA_ORDER_GBRG_ERRATA	(0 << 6)
+#define   DVO_DATA_ORDER_RGGB_ERRATA	(1 << 6)
+#define   DVO_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define   DVO_HSYNC_ACTIVE_HIGH		(1 << 3)
+#define   DVO_BLANK_ACTIVE_HIGH		(1 << 2)
+#define   DVO_OUTPUT_CSTATE_PIXELS	(1 << 1)	/* SDG only */
+#define   DVO_OUTPUT_SOURCE_SIZE_PIXELS	(1 << 0)	/* SDG only */
+#define   DVO_PRESERVE_MASK		(0x7<<24)
+#define DVOA_SRCDIM		0x61124
+#define DVOB_SRCDIM		0x61144
+#define DVOC_SRCDIM		0x61164
+#define   DVO_SRCDIM_HORIZONTAL_SHIFT	12
+#define   DVO_SRCDIM_VERTICAL_SHIFT	0
+
+/* LVDS port control */
+#define LVDS			0x61180
+/*
+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+#define   LVDS_PORT_EN			(1 << 31)
+/* Selects pipe B for LVDS data.  Must be set on pre-965. */
+#define   LVDS_PIPEB_SELECT		(1 << 30)
+/*
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+#define   LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
+#define   LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
+#define   LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
+/*
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+#define   LVDS_A3_POWER_MASK		(3 << 6)
+#define   LVDS_A3_POWER_DOWN		(0 << 6)
+#define   LVDS_A3_POWER_UP		(3 << 6)
+/*
+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+#define   LVDS_CLKB_POWER_MASK		(3 << 4)
+#define   LVDS_CLKB_POWER_DOWN		(0 << 4)
+#define   LVDS_CLKB_POWER_UP		(3 << 4)
+/*
+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode.  The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+#define   LVDS_B0B3_POWER_MASK		(3 << 2)
+#define   LVDS_B0B3_POWER_DOWN		(0 << 2)
+#define   LVDS_B0B3_POWER_UP		(3 << 2)
+
+/* Panel power sequencing */
+#define PP_STATUS	0x61200
+#define   PP_ON		(1 << 31)
+/*
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+#define   PP_READY		(1 << 30)
+#define   PP_SEQUENCE_NONE	(0 << 28)
+#define   PP_SEQUENCE_ON	(1 << 28)
+#define   PP_SEQUENCE_OFF	(2 << 28)
+#define   PP_SEQUENCE_MASK	0x30000000
+#define PP_CONTROL	0x61204
+#define   POWER_TARGET_ON	(1 << 0)
+#define PP_ON_DELAYS	0x61208
+#define PP_OFF_DELAYS	0x6120c
+#define PP_DIVISOR	0x61210
+
+/* Panel fitting */
+#define PFIT_CONTROL	0x61230
+#define   PFIT_ENABLE		(1 << 31)
+#define   PFIT_PIPE_MASK	(3 << 29)
+#define   PFIT_PIPE_SHIFT	29
+#define   VERT_INTERP_DISABLE	(0 << 10)
+#define   VERT_INTERP_BILINEAR	(1 << 10)
+#define   VERT_INTERP_MASK	(3 << 10)
+#define   VERT_AUTO_SCALE	(1 << 9)
+#define   HORIZ_INTERP_DISABLE	(0 << 6)
+#define   HORIZ_INTERP_BILINEAR	(1 << 6)
+#define   HORIZ_INTERP_MASK	(3 << 6)
+#define   HORIZ_AUTO_SCALE	(1 << 5)
+#define   PANEL_8TO6_DITHER_ENABLE (1 << 3)
+#define PFIT_PGM_RATIOS	0x61234
+#define   PFIT_VERT_SCALE_MASK			0xfff00000
+#define   PFIT_HORIZ_SCALE_MASK			0x0000fff0
+#define PFIT_AUTO_RATIOS 0x61238
+
+/* Backlight control */
+#define BLC_PWM_CTL		0x61254
+#define   BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
+#define BLC_PWM_CTL2		0x61250 /* 965+ only */
+#define   BLM_COMBINATION_MODE (1 << 30)
+/*
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define   BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
+#define   BLM_LEGACY_MODE				(1 << 16)
+/*
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define   BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
+#define   BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
+
+/* TV port control */
+#define TV_CTL			0x68000
+/** Enables the TV encoder */
+# define TV_ENC_ENABLE			(1 << 31)
+/** Sources the TV encoder input from pipe B instead of A. */
+# define TV_ENC_PIPEB_SELECT		(1 << 30)
+/** Outputs composite video (DAC A only) */
+# define TV_ENC_OUTPUT_COMPOSITE	(0 << 28)
+/** Outputs SVideo video (DAC B/C) */
+# define TV_ENC_OUTPUT_SVIDEO		(1 << 28)
+/** Outputs Component video (DAC A/B/C) */
+# define TV_ENC_OUTPUT_COMPONENT	(2 << 28)
+/** Outputs Composite and SVideo (DAC A/B/C) */
+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE	(3 << 28)
+# define TV_TRILEVEL_SYNC		(1 << 21)
+/** Enables slow sync generation (945GM only) */
+# define TV_SLOW_SYNC			(1 << 20)
+/** Selects 4x oversampling for 480i and 576p */
+# define TV_OVERSAMPLE_4X		(0 << 18)
+/** Selects 2x oversampling for 720p and 1080i */
+# define TV_OVERSAMPLE_2X		(1 << 18)
+/** Selects no oversampling for 1080p */
+# define TV_OVERSAMPLE_NONE		(2 << 18)
+/** Selects 8x oversampling */
+# define TV_OVERSAMPLE_8X		(3 << 18)
+/** Selects progressive mode rather than interlaced */
+# define TV_PROGRESSIVE			(1 << 17)
+/** Sets the colorburst to PAL mode.  Required for non-M PAL modes. */
+# define TV_PAL_BURST			(1 << 16)
+/** Field for setting delay of Y compared to C */
+# define TV_YC_SKEW_MASK		(7 << 12)
+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
+# define TV_ENC_SDP_FIX			(1 << 11)
+/**
+ * Enables a fix for the 915GM only.
+ *
+ * Not sure what it does.
+ */
+# define TV_ENC_C0_FIX			(1 << 10)
+/** Bits that must be preserved by software */
+# define TV_CTL_SAVE			((3 << 8) | (3 << 6))
+# define TV_FUSE_STATE_MASK		(3 << 4)
+/** Read-only state that reports all features enabled */
+# define TV_FUSE_STATE_ENABLED		(0 << 4)
+/** Read-only state that reports that Macrovision is disabled in hardware*/
+# define TV_FUSE_STATE_NO_MACROVISION	(1 << 4)
+/** Read-only state that reports that TV-out is disabled in hardware. */
+# define TV_FUSE_STATE_DISABLED		(2 << 4)
+/** Normal operation */
+# define TV_TEST_MODE_NORMAL		(0 << 0)
+/** Encoder test pattern 1 - combo pattern */
+# define TV_TEST_MODE_PATTERN_1		(1 << 0)
+/** Encoder test pattern 2 - full screen vertical 75% color bars */
+# define TV_TEST_MODE_PATTERN_2		(2 << 0)
+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
+# define TV_TEST_MODE_PATTERN_3		(3 << 0)
+/** Encoder test pattern 4 - random noise */
+# define TV_TEST_MODE_PATTERN_4		(4 << 0)
+/** Encoder test pattern 5 - linear color ramps */
+# define TV_TEST_MODE_PATTERN_5		(5 << 0)
+/**
+ * This test mode forces the DACs to 50% of full output.
+ *
+ * This is used for load detection in combination with TVDAC_SENSE_MASK
+ */
+# define TV_TEST_MODE_MONITOR_DETECT	(7 << 0)
+# define TV_TEST_MODE_MASK		(7 << 0)
+
+#define TV_DAC			0x68004
+/**
+ * Reports that DAC state change logic has reported change (RO).
+ *
+ * This gets cleared when TV_DAC_STATE_EN is cleared
+*/
+# define TVDAC_STATE_CHG		(1 << 31)
+# define TVDAC_SENSE_MASK		(7 << 28)
+/** Reports that DAC A voltage is above the detect threshold */
+# define TVDAC_A_SENSE			(1 << 30)
+/** Reports that DAC B voltage is above the detect threshold */
+# define TVDAC_B_SENSE			(1 << 29)
+/** Reports that DAC C voltage is above the detect threshold */
+# define TVDAC_C_SENSE			(1 << 28)
+/**
+ * Enables DAC state detection logic, for load-based TV detection.
+ *
+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
+ * to off, for load detection to work.
+ */
+# define TVDAC_STATE_CHG_EN		(1 << 27)
+/** Sets the DAC A sense value to high */
+# define TVDAC_A_SENSE_CTL		(1 << 26)
+/** Sets the DAC B sense value to high */
+# define TVDAC_B_SENSE_CTL		(1 << 25)
+/** Sets the DAC C sense value to high */
+# define TVDAC_C_SENSE_CTL		(1 << 24)
+/** Overrides the ENC_ENABLE and DAC voltage levels */
+# define DAC_CTL_OVERRIDE		(1 << 7)
+/** Sets the slew rate.  Must be preserved in software */
+# define ENC_TVDAC_SLEW_FAST		(1 << 6)
+# define DAC_A_1_3_V			(0 << 4)
+# define DAC_A_1_1_V			(1 << 4)
+# define DAC_A_0_7_V			(2 << 4)
+# define DAC_A_OFF			(3 << 4)
+# define DAC_B_1_3_V			(0 << 2)
+# define DAC_B_1_1_V			(1 << 2)
+# define DAC_B_0_7_V			(2 << 2)
+# define DAC_B_OFF			(3 << 2)
+# define DAC_C_1_3_V			(0 << 0)
+# define DAC_C_1_1_V			(1 << 0)
+# define DAC_C_0_7_V			(2 << 0)
+# define DAC_C_OFF			(3 << 0)
+
+/**
+ * CSC coefficients are stored in a floating point format with 9 bits of
+ * mantissa and 2 or 3 bits of exponent.  The exponent is represented as 2**-n,
+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
+ * -1 (0x3) being the only legal negative value.
+ */
+#define TV_CSC_Y		0x68010
+# define TV_RY_MASK			0x07ff0000
+# define TV_RY_SHIFT			16
+# define TV_GY_MASK			0x00000fff
+# define TV_GY_SHIFT			0
+
+#define TV_CSC_Y2		0x68014
+# define TV_BY_MASK			0x07ff0000
+# define TV_BY_SHIFT			16
+/**
+ * Y attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AY_MASK			0x000003ff
+# define TV_AY_SHIFT			0
+
+#define TV_CSC_U		0x68018
+# define TV_RU_MASK			0x07ff0000
+# define TV_RU_SHIFT			16
+# define TV_GU_MASK			0x000007ff
+# define TV_GU_SHIFT			0
+
+#define TV_CSC_U2		0x6801c
+# define TV_BU_MASK			0x07ff0000
+# define TV_BU_SHIFT			16
+/**
+ * U attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AU_MASK			0x000003ff
+# define TV_AU_SHIFT			0
+
+#define TV_CSC_V		0x68020
+# define TV_RV_MASK			0x0fff0000
+# define TV_RV_SHIFT			16
+# define TV_GV_MASK			0x000007ff
+# define TV_GV_SHIFT			0
+
+#define TV_CSC_V2		0x68024
+# define TV_BV_MASK			0x07ff0000
+# define TV_BV_SHIFT			16
+/**
+ * V attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AV_MASK			0x000007ff
+# define TV_AV_SHIFT			0
+
+#define TV_CLR_KNOBS		0x68028
+/** 2s-complement brightness adjustment */
+# define TV_BRIGHTNESS_MASK		0xff000000
+# define TV_BRIGHTNESS_SHIFT		24
+/** Contrast adjustment, as a 2.6 unsigned floating point number */
+# define TV_CONTRAST_MASK		0x00ff0000
+# define TV_CONTRAST_SHIFT		16
+/** Saturation adjustment, as a 2.6 unsigned floating point number */
+# define TV_SATURATION_MASK		0x0000ff00
+# define TV_SATURATION_SHIFT		8
+/** Hue adjustment, as an integer phase angle in degrees */
+# define TV_HUE_MASK			0x000000ff
+# define TV_HUE_SHIFT			0
+
+#define TV_CLR_LEVEL		0x6802c
+/** Controls the DAC level for black */
+# define TV_BLACK_LEVEL_MASK		0x01ff0000
+# define TV_BLACK_LEVEL_SHIFT		16
+/** Controls the DAC level for blanking */
+# define TV_BLANK_LEVEL_MASK		0x000001ff
+# define TV_BLANK_LEVEL_SHIFT		0
+
+#define TV_H_CTL_1		0x68030
+/** Number of pixels in the hsync. */
+# define TV_HSYNC_END_MASK		0x1fff0000
+# define TV_HSYNC_END_SHIFT		16
+/** Total number of pixels minus one in the line (display and blanking). */
+# define TV_HTOTAL_MASK			0x00001fff
+# define TV_HTOTAL_SHIFT		0
+
+#define TV_H_CTL_2		0x68034
+/** Enables the colorburst (needed for non-component color) */
+# define TV_BURST_ENA			(1 << 31)
+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
+# define TV_HBURST_START_SHIFT		16
+# define TV_HBURST_START_MASK		0x1fff0000
+/** Length of the colorburst */
+# define TV_HBURST_LEN_SHIFT		0
+# define TV_HBURST_LEN_MASK		0x0001fff
+
+#define TV_H_CTL_3		0x68038
+/** End of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_END_SHIFT		16
+# define TV_HBLANK_END_MASK		0x1fff0000
+/** Start of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_START_SHIFT		0
+# define TV_HBLANK_START_MASK		0x0001fff
+
+#define TV_V_CTL_1		0x6803c
+/** XXX */
+# define TV_NBR_END_SHIFT		16
+# define TV_NBR_END_MASK		0x07ff0000
+/** XXX */
+# define TV_VI_END_F1_SHIFT		8
+# define TV_VI_END_F1_MASK		0x00003f00
+/** XXX */
+# define TV_VI_END_F2_SHIFT		0
+# define TV_VI_END_F2_MASK		0x0000003f
+
+#define TV_V_CTL_2		0x68040
+/** Length of vsync, in half lines */
+# define TV_VSYNC_LEN_MASK		0x07ff0000
+# define TV_VSYNC_LEN_SHIFT		16
+/** Offset of the start of vsync in field 1, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F1_MASK		0x00007f00
+# define TV_VSYNC_START_F1_SHIFT	8
+/**
+ * Offset of the start of vsync in field 2, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F2_MASK		0x0000007f
+# define TV_VSYNC_START_F2_SHIFT	0
+
+#define TV_V_CTL_3		0x68044
+/** Enables generation of the equalization signal */
+# define TV_EQUAL_ENA			(1 << 31)
+/** Length of vsync, in half lines */
+# define TV_VEQ_LEN_MASK		0x007f0000
+# define TV_VEQ_LEN_SHIFT		16
+/** Offset of the start of equalization in field 1, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F1_MASK		0x0007f00
+# define TV_VEQ_START_F1_SHIFT		8
+/**
+ * Offset of the start of equalization in field 2, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F2_MASK		0x000007f
+# define TV_VEQ_START_F2_SHIFT		0
+
+#define TV_V_CTL_4		0x68048
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F1_MASK	0x003f0000
+# define TV_VBURST_START_F1_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F1_MASK		0x000000ff
+# define TV_VBURST_END_F1_SHIFT		0
+
+#define TV_V_CTL_5		0x6804c
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F2_MASK	0x003f0000
+# define TV_VBURST_START_F2_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F2_MASK		0x000000ff
+# define TV_VBURST_END_F2_SHIFT		0
+
+#define TV_V_CTL_6		0x68050
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F3_MASK	0x003f0000
+# define TV_VBURST_START_F3_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F3_MASK		0x000000ff
+# define TV_VBURST_END_F3_SHIFT		0
+
+#define TV_V_CTL_7		0x68054
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F4_MASK	0x003f0000
+# define TV_VBURST_START_F4_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F4_MASK		0x000000ff
+# define TV_VBURST_END_F4_SHIFT		0
+
+#define TV_SC_CTL_1		0x68060
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA1_EN			(1 << 31)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA2_EN			(1 << 30)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA3_EN			(1 << 29)
+/** Sets the subcarrier DDA to reset frequency every other field */
+# define TV_SC_RESET_EVERY_2		(0 << 24)
+/** Sets the subcarrier DDA to reset frequency every fourth field */
+# define TV_SC_RESET_EVERY_4		(1 << 24)
+/** Sets the subcarrier DDA to reset frequency every eighth field */
+# define TV_SC_RESET_EVERY_8		(2 << 24)
+/** Sets the subcarrier DDA to never reset the frequency */
+# define TV_SC_RESET_NEVER		(3 << 24)
+/** Sets the peak amplitude of the colorburst.*/
+# define TV_BURST_LEVEL_MASK		0x00ff0000
+# define TV_BURST_LEVEL_SHIFT		16
+/** Sets the increment of the first subcarrier phase generation DDA */
+# define TV_SCDDA1_INC_MASK		0x00000fff
+# define TV_SCDDA1_INC_SHIFT		0
+
+#define TV_SC_CTL_2		0x68064
+/** Sets the rollover for the second subcarrier phase generation DDA */
+# define TV_SCDDA2_SIZE_MASK		0x7fff0000
+# define TV_SCDDA2_SIZE_SHIFT		16
+/** Sets the increent of the second subcarrier phase generation DDA */
+# define TV_SCDDA2_INC_MASK		0x00007fff
+# define TV_SCDDA2_INC_SHIFT		0
+
+#define TV_SC_CTL_3		0x68068
+/** Sets the rollover for the third subcarrier phase generation DDA */
+# define TV_SCDDA3_SIZE_MASK		0x7fff0000
+# define TV_SCDDA3_SIZE_SHIFT		16
+/** Sets the increent of the third subcarrier phase generation DDA */
+# define TV_SCDDA3_INC_MASK		0x00007fff
+# define TV_SCDDA3_INC_SHIFT		0
+
+#define TV_WIN_POS		0x68070
+/** X coordinate of the display from the start of horizontal active */
+# define TV_XPOS_MASK			0x1fff0000
+# define TV_XPOS_SHIFT			16
+/** Y coordinate of the display from the start of vertical active (NBR) */
+# define TV_YPOS_MASK			0x00000fff
+# define TV_YPOS_SHIFT			0
+
+#define TV_WIN_SIZE		0x68074
+/** Horizontal size of the display window, measured in pixels*/
+# define TV_XSIZE_MASK			0x1fff0000
+# define TV_XSIZE_SHIFT			16
+/**
+ * Vertical size of the display window, measured in pixels.
+ *
+ * Must be even for interlaced modes.
+ */
+# define TV_YSIZE_MASK			0x00000fff
+# define TV_YSIZE_SHIFT			0
+
+#define TV_FILTER_CTL_1		0x68080
+/**
+ * Enables automatic scaling calculation.
+ *
+ * If set, the rest of the registers are ignored, and the calculated values can
+ * be read back from the register.
+ */
+# define TV_AUTO_SCALE			(1 << 31)
+/**
+ * Disables the vertical filter.
+ *
+ * This is required on modes more than 1024 pixels wide */
+# define TV_V_FILTER_BYPASS		(1 << 29)
+/** Enables adaptive vertical filtering */
+# define TV_VADAPT			(1 << 28)
+# define TV_VADAPT_MODE_MASK		(3 << 26)
+/** Selects the least adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_LEAST		(0 << 26)
+/** Selects the moderately adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MODERATE	(1 << 26)
+/** Selects the most adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MOST		(3 << 26)
+/**
+ * Sets the horizontal scaling factor.
+ *
+ * This should be the fractional part of the horizontal scaling factor divided
+ * by the oversampling rate.  TV_HSCALE should be less than 1, and set to:
+ *
+ * (src width - 1) / ((oversample * dest width) - 1)
+ */
+# define TV_HSCALE_FRAC_MASK		0x00003fff
+# define TV_HSCALE_FRAC_SHIFT		0
+
+#define TV_FILTER_CTL_2		0x68084
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
+ */
+# define TV_VSCALE_INT_MASK		0x00038000
+# define TV_VSCALE_INT_SHIFT		15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * \sa TV_VSCALE_INT_MASK
+ */
+# define TV_VSCALE_FRAC_MASK		0x00007fff
+# define TV_VSCALE_FRAC_SHIFT		0
+
+#define TV_FILTER_CTL_3		0x68088
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ */
+# define TV_VSCALE_IP_INT_MASK		0x00038000
+# define TV_VSCALE_IP_INT_SHIFT		15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ *
+ * \sa TV_VSCALE_IP_INT_MASK
+ */
+# define TV_VSCALE_IP_FRAC_MASK		0x00007fff
+# define TV_VSCALE_IP_FRAC_SHIFT		0
+
+#define TV_CC_CONTROL		0x68090
+# define TV_CC_ENABLE			(1 << 31)
+/**
+ * Specifies which field to send the CC data in.
+ *
+ * CC data is usually sent in field 0.
+ */
+# define TV_CC_FID_MASK			(1 << 27)
+# define TV_CC_FID_SHIFT		27
+/** Sets the horizontal position of the CC data.  Usually 135. */
+# define TV_CC_HOFF_MASK		0x03ff0000
+# define TV_CC_HOFF_SHIFT		16
+/** Sets the vertical position of the CC data.  Usually 21 */
+# define TV_CC_LINE_MASK		0x0000003f
+# define TV_CC_LINE_SHIFT		0
+
+#define TV_CC_DATA		0x68094
+# define TV_CC_RDY			(1 << 31)
+/** Second word of CC data to be transmitted. */
+# define TV_CC_DATA_2_MASK		0x007f0000
+# define TV_CC_DATA_2_SHIFT		16
+/** First word of CC data to be transmitted. */
+# define TV_CC_DATA_1_MASK		0x0000007f
+# define TV_CC_DATA_1_SHIFT		0
+
+#define TV_H_LUMA_0		0x68100
+#define TV_H_LUMA_59		0x681ec
+#define TV_H_CHROMA_0		0x68200
+#define TV_H_CHROMA_59		0x682ec
+#define TV_V_LUMA_0		0x68300
+#define TV_V_LUMA_42		0x683a8
+#define TV_V_CHROMA_0		0x68400
+#define TV_V_CHROMA_42		0x684a8
+
+/* Display & cursor control */
+
+/* Pipe A */
+#define PIPEADSL		0x70000
+#define PIPEACONF		0x70008
+#define   PIPEACONF_ENABLE	(1<<31)
+#define   PIPEACONF_DISABLE	0
+#define   PIPEACONF_DOUBLE_WIDE	(1<<30)
+#define   I965_PIPECONF_ACTIVE	(1<<30)
+#define   PIPEACONF_SINGLE_WIDE	0
+#define   PIPEACONF_PIPE_UNLOCKED 0
+#define   PIPEACONF_PIPE_LOCKED	(1<<25)
+#define   PIPEACONF_PALETTE	0
+#define   PIPEACONF_GAMMA		(1<<24)
+#define   PIPECONF_FORCE_BORDER	(1<<25)
+#define   PIPECONF_PROGRESSIVE	(0 << 21)
+#define   PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
+#define   PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
+#define PIPEASTAT		0x70024
+#define   PIPE_FIFO_UNDERRUN_STATUS		(1UL<<31)
+#define   PIPE_CRC_ERROR_ENABLE			(1UL<<29)
+#define   PIPE_CRC_DONE_ENABLE			(1UL<<28)
+#define   PIPE_GMBUS_EVENT_ENABLE		(1UL<<27)
+#define   PIPE_HOTPLUG_INTERRUPT_ENABLE		(1UL<<26)
+#define   PIPE_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
+#define   PIPE_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
+#define   PIPE_DPST_EVENT_ENABLE		(1UL<<23)
+#define   PIPE_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
+#define   PIPE_ODD_FIELD_INTERRUPT_ENABLE	(1UL<<21)
+#define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
+#define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE	(1UL<<18) /* pre-965 */
+#define   PIPE_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18) /* 965 or later */
+#define   PIPE_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
+#define   PIPE_OVERLAY_UPDATED_ENABLE		(1UL<<16)
+#define   PIPE_CRC_ERROR_INTERRUPT_STATUS	(1UL<<13)
+#define   PIPE_CRC_DONE_INTERRUPT_STATUS	(1UL<<12)
+#define   PIPE_GMBUS_INTERRUPT_STATUS		(1UL<<11)
+#define   PIPE_HOTPLUG_INTERRUPT_STATUS		(1UL<<10)
+#define   PIPE_VSYNC_INTERRUPT_STATUS		(1UL<<9)
+#define   PIPE_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
+#define   PIPE_DPST_EVENT_STATUS		(1UL<<7)
+#define   PIPE_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
+#define   PIPE_ODD_FIELD_INTERRUPT_STATUS	(1UL<<5)
+#define   PIPE_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
+#define   PIPE_HOTPLUG_TV_INTERRUPT_STATUS	(1UL<<2) /* pre-965 */
+#define   PIPE_START_VBLANK_INTERRUPT_STATUS	(1UL<<2) /* 965 or later */
+#define   PIPE_VBLANK_INTERRUPT_STATUS		(1UL<<1)
+#define   PIPE_OVERLAY_UPDATED_STATUS		(1UL<<0)
+
+#define DSPARB			0x70030
+#define   DSPARB_CSTART_MASK	(0x7f << 7)
+#define   DSPARB_CSTART_SHIFT	7
+#define   DSPARB_BSTART_MASK	(0x7f)
+#define   DSPARB_BSTART_SHIFT	0
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code
+ * should work:
+ *
+ *  do {
+ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT;
+ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
+ *             PIPE_FRAME_LOW_SHIFT);
+ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT);
+ *  } while (high1 != high2);
+ *  frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH          0x70040
+#define   PIPE_FRAME_HIGH_MASK    0x0000ffff
+#define   PIPE_FRAME_HIGH_SHIFT   0
+#define PIPEAFRAMEPIXEL         0x70044
+#define   PIPE_FRAME_LOW_MASK     0xff000000
+#define   PIPE_FRAME_LOW_SHIFT    24
+#define   PIPE_PIXEL_MASK         0x00ffffff
+#define   PIPE_PIXEL_SHIFT        0
+
+/* Cursor A & B regs */
+#define CURACNTR		0x70080
+#define   CURSOR_MODE_DISABLE   0x00
+#define   CURSOR_MODE_64_32B_AX 0x07
+#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
+#define CURABASE		0x70084
+#define CURAPOS			0x70088
+#define   CURSOR_POS_MASK       0x007FF
+#define   CURSOR_POS_SIGN       0x8000
+#define   CURSOR_X_SHIFT        0
+#define   CURSOR_Y_SHIFT        16
+#define CURBCNTR		0x700c0
+#define CURBBASE		0x700c4
+#define CURBPOS			0x700c8
+
+/* Display A control */
+#define DSPACNTR                0x70180
+#define   DISPLAY_PLANE_ENABLE			(1<<31)
+#define   DISPLAY_PLANE_DISABLE			0
+#define   DISPPLANE_GAMMA_ENABLE		(1<<30)
+#define   DISPPLANE_GAMMA_DISABLE		0
+#define   DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
+#define   DISPPLANE_8BPP			(0x2<<26)
+#define   DISPPLANE_15_16BPP			(0x4<<26)
+#define   DISPPLANE_16BPP			(0x5<<26)
+#define   DISPPLANE_32BPP_NO_ALPHA		(0x6<<26)
+#define   DISPPLANE_32BPP			(0x7<<26)
+#define   DISPPLANE_STEREO_ENABLE		(1<<25)
+#define   DISPPLANE_STEREO_DISABLE		0
+#define   DISPPLANE_SEL_PIPE_MASK		(1<<24)
+#define   DISPPLANE_SEL_PIPE_A			0
+#define   DISPPLANE_SEL_PIPE_B			(1<<24)
+#define   DISPPLANE_SRC_KEY_ENABLE		(1<<22)
+#define   DISPPLANE_SRC_KEY_DISABLE		0
+#define   DISPPLANE_LINE_DOUBLE			(1<<20)
+#define   DISPPLANE_NO_LINE_DOUBLE		0
+#define   DISPPLANE_STEREO_POLARITY_FIRST	0
+#define   DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
+#define DSPAADDR		0x70184
+#define DSPASTRIDE		0x70188
+#define DSPAPOS			0x7018C /* reserved */
+#define DSPASIZE		0x70190
+#define DSPASURF		0x7019C /* 965+ only */
+#define DSPATILEOFF		0x701A4 /* 965+ only */
+
+/* VBIOS flags */
+#define SWF00			0x71410
+#define SWF01			0x71414
+#define SWF02			0x71418
+#define SWF03			0x7141c
+#define SWF04			0x71420
+#define SWF05			0x71424
+#define SWF06			0x71428
+#define SWF10			0x70410
+#define SWF11			0x70414
+#define SWF14			0x71420
+#define SWF30			0x72414
+#define SWF31			0x72418
+#define SWF32			0x7241c
+
+/* Pipe B */
+#define PIPEBDSL		0x71000
+#define PIPEBCONF		0x71008
+#define PIPEBSTAT		0x71024
+#define PIPEBFRAMEHIGH		0x71040
+#define PIPEBFRAMEPIXEL		0x71044
+
+/* Display B control */
+#define DSPBCNTR		0x71180
+#define   DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
+#define   DISPPLANE_ALPHA_TRANS_DISABLE		0
+#define   DISPPLANE_SPRITE_ABOVE_DISPLAY	0
+#define   DISPPLANE_SPRITE_ABOVE_OVERLAY	(1)
+#define DSPBADDR		0x71184
+#define DSPBSTRIDE		0x71188
+#define DSPBPOS			0x7118C
+#define DSPBSIZE		0x71190
+#define DSPBSURF		0x7119C
+#define DSPBTILEOFF		0x711A4
+
+/* VBIOS regs */
+#define VGACNTRL		0x71400
+# define VGA_DISP_DISABLE			(1 << 31)
+# define VGA_2X_MODE				(1 << 30)
+# define VGA_PIPE_B_SELECT			(1 << 29)
+
+#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
new file mode 100644
index 0000000..603fe74
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -0,0 +1,509 @@
+/*
+ *
+ * Copyright 2008 (c) Intel Corporation
+ *   Jesse Barnes <jbarnes@virtuousgeek.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (pipe == PIPE_A)
+		return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
+	else
+		return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
+}
+
+static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	u32 *array;
+	int i;
+
+	if (!i915_pipe_enabled(dev, pipe))
+		return;
+
+	if (pipe == PIPE_A)
+		array = dev_priv->save_palette_a;
+	else
+		array = dev_priv->save_palette_b;
+
+	for(i = 0; i < 256; i++)
+		array[i] = I915_READ(reg + (i << 2));
+}
+
+static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	u32 *array;
+	int i;
+
+	if (!i915_pipe_enabled(dev, pipe))
+		return;
+
+	if (pipe == PIPE_A)
+		array = dev_priv->save_palette_a;
+	else
+		array = dev_priv->save_palette_b;
+
+	for(i = 0; i < 256; i++)
+		I915_WRITE(reg + (i << 2), array[i]);
+}
+
+static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE8(index_port, reg);
+	return I915_READ8(data_port);
+}
+
+static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_READ8(st01);
+	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+	return I915_READ8(VGA_AR_DATA_READ);
+}
+
+static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_READ8(st01);
+	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+	I915_WRITE8(VGA_AR_DATA_WRITE, val);
+}
+
+static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE8(index_port, reg);
+	I915_WRITE8(data_port, val);
+}
+
+static void i915_save_vga(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+	u16 cr_index, cr_data, st01;
+
+	/* VGA color palette registers */
+	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
+	/* DACCRX automatically increments during read */
+	I915_WRITE8(VGA_DACRX, 0);
+	/* Read 3 bytes of color data from each index */
+	for (i = 0; i < 256 * 3; i++)
+		dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
+
+	/* MSR bits */
+	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
+	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+		cr_index = VGA_CR_INDEX_CGA;
+		cr_data = VGA_CR_DATA_CGA;
+		st01 = VGA_ST01_CGA;
+	} else {
+		cr_index = VGA_CR_INDEX_MDA;
+		cr_data = VGA_CR_DATA_MDA;
+		st01 = VGA_ST01_MDA;
+	}
+
+	/* CRT controller regs */
+	i915_write_indexed(dev, cr_index, cr_data, 0x11,
+			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
+			   (~0x80));
+	for (i = 0; i <= 0x24; i++)
+		dev_priv->saveCR[i] =
+			i915_read_indexed(dev, cr_index, cr_data, i);
+	/* Make sure we don't turn off CR group 0 writes */
+	dev_priv->saveCR[0x11] &= ~0x80;
+
+	/* Attribute controller registers */
+	I915_READ8(st01);
+	dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
+	for (i = 0; i <= 0x14; i++)
+		dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
+	I915_READ8(st01);
+	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
+	I915_READ8(st01);
+
+	/* Graphics controller registers */
+	for (i = 0; i < 9; i++)
+		dev_priv->saveGR[i] =
+			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
+
+	dev_priv->saveGR[0x10] =
+		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
+	dev_priv->saveGR[0x11] =
+		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
+	dev_priv->saveGR[0x18] =
+		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
+
+	/* Sequencer registers */
+	for (i = 0; i < 8; i++)
+		dev_priv->saveSR[i] =
+			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
+}
+
+static void i915_restore_vga(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+	u16 cr_index, cr_data, st01;
+
+	/* MSR bits */
+	I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
+	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+		cr_index = VGA_CR_INDEX_CGA;
+		cr_data = VGA_CR_DATA_CGA;
+		st01 = VGA_ST01_CGA;
+	} else {
+		cr_index = VGA_CR_INDEX_MDA;
+		cr_data = VGA_CR_DATA_MDA;
+		st01 = VGA_ST01_MDA;
+	}
+
+	/* Sequencer registers, don't write SR07 */
+	for (i = 0; i < 7; i++)
+		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
+				   dev_priv->saveSR[i]);
+
+	/* CRT controller regs */
+	/* Enable CR group 0 writes */
+	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
+	for (i = 0; i <= 0x24; i++)
+		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
+
+	/* Graphics controller regs */
+	for (i = 0; i < 9; i++)
+		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
+				   dev_priv->saveGR[i]);
+
+	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
+			   dev_priv->saveGR[0x10]);
+	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
+			   dev_priv->saveGR[0x11]);
+	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
+			   dev_priv->saveGR[0x18]);
+
+	/* Attribute controller registers */
+	I915_READ8(st01); /* switch back to index mode */
+	for (i = 0; i <= 0x14; i++)
+		i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
+	I915_READ8(st01); /* switch back to index mode */
+	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
+	I915_READ8(st01);
+
+	/* VGA color palette registers */
+	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
+	/* DACCRX automatically increments during read */
+	I915_WRITE8(VGA_DACWX, 0);
+	/* Read 3 bytes of color data from each index */
+	for (i = 0; i < 256 * 3; i++)
+		I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
+
+}
+
+int i915_save_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+
+	/* Display arbitration control */
+	dev_priv->saveDSPARB = I915_READ(DSPARB);
+
+	/* Pipe & plane A info */
+	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
+	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+	dev_priv->saveFPA0 = I915_READ(FPA0);
+	dev_priv->saveFPA1 = I915_READ(FPA1);
+	dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+	if (IS_I965G(dev))
+		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
+	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
+	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
+	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
+	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
+	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
+	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
+	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
+	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
+	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
+	dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
+	if (IS_I965G(dev)) {
+		dev_priv->saveDSPASURF = I915_READ(DSPASURF);
+		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
+	}
+	i915_save_palette(dev, PIPE_A);
+	dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
+
+	/* Pipe & plane B info */
+	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
+	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+	dev_priv->saveFPB0 = I915_READ(FPB0);
+	dev_priv->saveFPB1 = I915_READ(FPB1);
+	dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+	if (IS_I965G(dev))
+		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
+	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
+	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
+	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
+	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
+	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
+	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
+	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
+	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
+	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
+	dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
+	if (IS_I965GM(dev) || IS_GM45(dev)) {
+		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
+		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
+	}
+	i915_save_palette(dev, PIPE_B);
+	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+
+	/* CRT state */
+	dev_priv->saveADPA = I915_READ(ADPA);
+
+	/* LVDS state */
+	dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
+	dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
+	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+	if (IS_I965G(dev))
+		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+	if (IS_MOBILE(dev) && !IS_I830(dev))
+		dev_priv->saveLVDS = I915_READ(LVDS);
+	if (!IS_I830(dev) && !IS_845G(dev))
+		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
+	dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
+	dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
+	dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
+
+	/* FIXME: save TV & SDVO state */
+
+	/* FBC state */
+	dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
+	dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
+	dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
+	dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+
+	/* Interrupt state */
+	dev_priv->saveIIR = I915_READ(IIR);
+	dev_priv->saveIER = I915_READ(IER);
+	dev_priv->saveIMR = I915_READ(IMR);
+
+	/* VGA state */
+	dev_priv->saveVGA0 = I915_READ(VGA0);
+	dev_priv->saveVGA1 = I915_READ(VGA1);
+	dev_priv->saveVGA_PD = I915_READ(VGA_PD);
+	dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+
+	/* Clock gating state */
+	dev_priv->saveD_STATE = I915_READ(D_STATE);
+	dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
+
+	/* Cache mode state */
+	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
+
+	/* Memory Arbitration state */
+	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
+
+	/* Scratch space */
+	for (i = 0; i < 16; i++) {
+		dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
+		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+	}
+	for (i = 0; i < 3; i++)
+		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
+
+	i915_save_vga(dev);
+
+	return 0;
+}
+
+int i915_restore_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+
+	I915_WRITE(DSPARB, dev_priv->saveDSPARB);
+
+	/* Pipe & plane A info */
+	/* Prime the clock */
+	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+			   ~DPLL_VCO_ENABLE);
+		DRM_UDELAY(150);
+	}
+	I915_WRITE(FPA0, dev_priv->saveFPA0);
+	I915_WRITE(FPA1, dev_priv->saveFPA1);
+	/* Actually enable it */
+	I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+	DRM_UDELAY(150);
+	if (IS_I965G(dev))
+		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+	DRM_UDELAY(150);
+
+	/* Restore mode */
+	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+	I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+	/* Restore plane info */
+	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+	I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
+	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+	if (IS_I965G(dev)) {
+		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+	}
+
+	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+	i915_restore_palette(dev, PIPE_A);
+	/* Enable the plane */
+	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+	I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
+
+	/* Pipe & plane B info */
+	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+			   ~DPLL_VCO_ENABLE);
+		DRM_UDELAY(150);
+	}
+	I915_WRITE(FPB0, dev_priv->saveFPB0);
+	I915_WRITE(FPB1, dev_priv->saveFPB1);
+	/* Actually enable it */
+	I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+	DRM_UDELAY(150);
+	if (IS_I965G(dev))
+		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+	DRM_UDELAY(150);
+
+	/* Restore mode */
+	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+	I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+	/* Restore plane info */
+	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+	I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
+	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+	if (IS_I965G(dev)) {
+		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+	}
+
+	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+	i915_restore_palette(dev, PIPE_B);
+	/* Enable the plane */
+	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+	I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
+
+	/* CRT state */
+	I915_WRITE(ADPA, dev_priv->saveADPA);
+
+	/* LVDS state */
+	if (IS_I965G(dev))
+		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
+	if (IS_MOBILE(dev) && !IS_I830(dev))
+		I915_WRITE(LVDS, dev_priv->saveLVDS);
+	if (!IS_I830(dev) && !IS_845G(dev))
+		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
+
+	I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
+	I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+	I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
+	I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
+	I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
+	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+
+	/* FIXME: restore TV & SDVO state */
+
+	/* FBC info */
+	I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
+	I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
+	I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
+	I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+
+	/* VGA state */
+	I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+	I915_WRITE(VGA0, dev_priv->saveVGA0);
+	I915_WRITE(VGA1, dev_priv->saveVGA1);
+	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
+	DRM_UDELAY(150);
+
+	/* Clock gating state */
+	I915_WRITE (D_STATE, dev_priv->saveD_STATE);
+	I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
+
+	/* Cache mode state */
+	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+
+	/* Memory arbitration state */
+	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+
+	for (i = 0; i < 16; i++) {
+		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
+		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+	}
+	for (i = 0; i < 3; i++)
+		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+
+	i915_restore_vga(dev);
+
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
index 5572939..97ee566 100644
--- a/drivers/gpu/drm/mga/mga_drv.c
+++ b/drivers/gpu/drm/mga/mga_drv.c
@@ -45,15 +45,16 @@
 static struct drm_driver driver = {
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
-	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-	    DRIVER_IRQ_VBL,
+	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
 	.dev_priv_size = sizeof(drm_mga_buf_priv_t),
 	.load = mga_driver_load,
 	.unload = mga_driver_unload,
 	.lastclose = mga_driver_lastclose,
 	.dma_quiescent = mga_driver_dma_quiescent,
 	.device_is_agp = mga_driver_device_is_agp,
-	.vblank_wait = mga_driver_vblank_wait,
+	.get_vblank_counter = mga_get_vblank_counter,
+	.enable_vblank = mga_enable_vblank,
+	.disable_vblank = mga_disable_vblank,
 	.irq_preinstall = mga_driver_irq_preinstall,
 	.irq_postinstall = mga_driver_irq_postinstall,
 	.irq_uninstall = mga_driver_irq_uninstall,
@@ -64,20 +65,20 @@
 	.ioctls = mga_ioctls,
 	.dma_ioctl = mga_dma_buffers,
 	.fops = {
-		 .owner = THIS_MODULE,
-		 .open = drm_open,
-		 .release = drm_release,
-		 .ioctl = drm_ioctl,
-		 .mmap = drm_mmap,
-		 .poll = drm_poll,
-		 .fasync = drm_fasync,
+		.owner = THIS_MODULE,
+		.open = drm_open,
+		.release = drm_release,
+		.ioctl = drm_ioctl,
+		.mmap = drm_mmap,
+		.poll = drm_poll,
+		.fasync = drm_fasync,
 #ifdef CONFIG_COMPAT
-		 .compat_ioctl = mga_compat_ioctl,
+		.compat_ioctl = mga_compat_ioctl,
 #endif
-		 },
+	},
 	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
+		.name = DRIVER_NAME,
+		.id_table = pciidlist,
 	},
 
 	.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
index f6ebd24..88257c2 100644
--- a/drivers/gpu/drm/mga/mga_drv.h
+++ b/drivers/gpu/drm/mga/mga_drv.h
@@ -120,6 +120,7 @@
 	u32 clear_cmd;
 	u32 maccess;
 
+	atomic_t vbl_received;          /**< Number of vblanks received. */
 	wait_queue_head_t fence_queue;
 	atomic_t last_fence_retired;
 	u32 next_fence_to_post;
@@ -181,11 +182,14 @@
 extern int mga_warp_init(drm_mga_private_t * dev_priv);
 
 				/* mga_irq.c */
+extern int mga_enable_vblank(struct drm_device *dev, int crtc);
+extern void mga_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
 extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
 extern void mga_driver_irq_preinstall(struct drm_device * dev);
-extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern int mga_driver_irq_postinstall(struct drm_device *dev);
 extern void mga_driver_irq_uninstall(struct drm_device * dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 			     unsigned long arg);
diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c
index 9302cb8..bab42f4 100644
--- a/drivers/gpu/drm/mga/mga_irq.c
+++ b/drivers/gpu/drm/mga/mga_irq.c
@@ -1,5 +1,6 @@
 /* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
- *
+ */
+/*
  * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
  *
  * The Weather Channel (TM) funded Tungsten Graphics to develop the
@@ -35,6 +36,18 @@
 #include "mga_drm.h"
 #include "mga_drv.h"
 
+u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	const drm_mga_private_t *const dev_priv =
+		(drm_mga_private_t *) dev->dev_private;
+
+	if (crtc != 0)
+		return 0;
+
+	return atomic_read(&dev_priv->vbl_received);
+}
+
+
 irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -47,9 +60,8 @@
 	/* VBLANK interrupt */
 	if (status & MGA_VLINEPEN) {
 		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
-		atomic_inc(&dev->vbl_received);
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+		atomic_inc(&dev_priv->vbl_received);
+		drm_handle_vblank(dev, 0);
 		handled = 1;
 	}
 
@@ -58,6 +70,7 @@
 		const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
 		const u32 prim_end = MGA_READ(MGA_PRIMEND);
 
+
 		MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
 
 		/* In addition to clearing the interrupt-pending bit, we
@@ -72,28 +85,39 @@
 		handled = 1;
 	}
 
-	if (handled) {
+	if (handled)
 		return IRQ_HANDLED;
-	}
 	return IRQ_NONE;
 }
 
-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int mga_enable_vblank(struct drm_device *dev, int crtc)
 {
-	unsigned int cur_vblank;
-	int ret = 0;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
+	if (crtc != 0) {
+		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+			  crtc);
+		return 0;
+	}
+
+	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+	return 0;
+}
+
+
+void mga_disable_vblank(struct drm_device *dev, int crtc)
+{
+	if (crtc != 0) {
+		DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+			  crtc);
+	}
+
+	/* Do *NOT* disable the vertical refresh interrupt.  MGA doesn't have
+	 * a nice hardware counter that tracks the number of refreshes when
+	 * the interrupt is disabled, and the kernel doesn't know the refresh
+	 * rate to calculate an estimate.
 	 */
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received))
-		      - *sequence) <= (1 << 23)));
-
-	*sequence = cur_vblank;
-
-	return ret;
+	/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
 }
 
 int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
@@ -125,14 +149,22 @@
 	MGA_WRITE(MGA_ICLEAR, ~0);
 }
 
-void mga_driver_irq_postinstall(struct drm_device * dev)
+int mga_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+	int ret;
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret)
+		return ret;
 
 	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
 
-	/* Turn on vertical blank interrupt and soft trap interrupt. */
-	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+	/* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
+	 * in mga_enable_vblank.
+	 */
+	MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
+	return 0;
 }
 
 void mga_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c
index d3f8aad..b710fab 100644
--- a/drivers/gpu/drm/mga/mga_state.c
+++ b/drivers/gpu/drm/mga/mga_state.c
@@ -1022,7 +1022,7 @@
 
 	switch (param->param) {
 	case MGA_PARAM_IRQ_NR:
-		value = dev->irq;
+		value = drm_dev_to_irq(dev);
 		break;
 	case MGA_PARAM_CARD_TYPE:
 		value = dev_priv->chipset;
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 6108e75..3265d53 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -43,12 +43,13 @@
 static struct drm_driver driver = {
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-	    DRIVER_IRQ_VBL,
+	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
 	.dev_priv_size = sizeof(drm_r128_buf_priv_t),
 	.preclose = r128_driver_preclose,
 	.lastclose = r128_driver_lastclose,
-	.vblank_wait = r128_driver_vblank_wait,
+	.get_vblank_counter = r128_get_vblank_counter,
+	.enable_vblank = r128_enable_vblank,
+	.disable_vblank = r128_disable_vblank,
 	.irq_preinstall = r128_driver_irq_preinstall,
 	.irq_postinstall = r128_driver_irq_postinstall,
 	.irq_uninstall = r128_driver_irq_uninstall,
@@ -59,21 +60,20 @@
 	.ioctls = r128_ioctls,
 	.dma_ioctl = r128_cce_buffers,
 	.fops = {
-		 .owner = THIS_MODULE,
-		 .open = drm_open,
-		 .release = drm_release,
-		 .ioctl = drm_ioctl,
-		 .mmap = drm_mmap,
-		 .poll = drm_poll,
-		 .fasync = drm_fasync,
+		.owner = THIS_MODULE,
+		.open = drm_open,
+		.release = drm_release,
+		.ioctl = drm_ioctl,
+		.mmap = drm_mmap,
+		.poll = drm_poll,
+		.fasync = drm_fasync,
 #ifdef CONFIG_COMPAT
-		 .compat_ioctl = r128_compat_ioctl,
+		.compat_ioctl = r128_compat_ioctl,
 #endif
 	},
-
 	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
+		.name = DRIVER_NAME,
+		.id_table = pciidlist,
 	},
 
 	.name = DRIVER_NAME,
@@ -87,6 +87,7 @@
 static int __init r128_init(void)
 {
 	driver.num_ioctls = r128_max_ioctl;
+
 	return drm_init(&driver);
 }
 
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 011105e..5898b27 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -29,7 +29,7 @@
  *    Rickard E. (Rik) Faith <faith@valinux.com>
  *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *    Michel Dänzer <daenzerm@student.ethz.ch>
+ *    Michel D�zer <daenzerm@student.ethz.ch>
  */
 
 #ifndef __R128_DRV_H__
@@ -97,6 +97,8 @@
 	u32 crtc_offset;
 	u32 crtc_offset_cntl;
 
+	atomic_t vbl_received;
+
 	u32 color_fmt;
 	unsigned int front_offset;
 	unsigned int front_pitch;
@@ -149,11 +151,12 @@
 extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
 extern int r128_do_cleanup_cce(struct drm_device * dev);
 
-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-
+extern int r128_enable_vblank(struct drm_device *dev, int crtc);
+extern void r128_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
 extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
 extern void r128_driver_irq_preinstall(struct drm_device * dev);
-extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern int r128_driver_irq_postinstall(struct drm_device *dev);
 extern void r128_driver_irq_uninstall(struct drm_device * dev);
 extern void r128_driver_lastclose(struct drm_device * dev);
 extern void r128_driver_preclose(struct drm_device * dev,
diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c
index c76fdca..d734901 100644
--- a/drivers/gpu/drm/r128/r128_irq.c
+++ b/drivers/gpu/drm/r128/r128_irq.c
@@ -35,6 +35,16 @@
 #include "r128_drm.h"
 #include "r128_drv.h"
 
+u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	const drm_r128_private_t *dev_priv = dev->dev_private;
+
+	if (crtc != 0)
+		return 0;
+
+	return atomic_read(&dev_priv->vbl_received);
+}
+
 irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -46,30 +56,38 @@
 	/* VBLANK interrupt */
 	if (status & R128_CRTC_VBLANK_INT) {
 		R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
-		atomic_inc(&dev->vbl_received);
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+		atomic_inc(&dev_priv->vbl_received);
+		drm_handle_vblank(dev, 0);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
 }
 
-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int r128_enable_vblank(struct drm_device *dev, int crtc)
 {
-	unsigned int cur_vblank;
-	int ret = 0;
+	drm_r128_private_t *dev_priv = dev->dev_private;
 
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
+	if (crtc != 0) {
+		DRM_ERROR("%s:  bad crtc %d\n", __func__, crtc);
+		return -EINVAL;
+	}
+
+	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+	return 0;
+}
+
+void r128_disable_vblank(struct drm_device *dev, int crtc)
+{
+	if (crtc != 0)
+		DRM_ERROR("%s:  bad crtc %d\n", __func__, crtc);
+
+	/*
+	 * FIXME: implement proper interrupt disable by using the vblank
+	 * counter register (if available)
+	 *
+	 * R128_WRITE(R128_GEN_INT_CNTL,
+	 *            R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
 	 */
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received))
-		      - *sequence) <= (1 << 23)));
-
-	*sequence = cur_vblank;
-
-	return ret;
 }
 
 void r128_driver_irq_preinstall(struct drm_device * dev)
@@ -82,12 +100,9 @@
 	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
 }
 
-void r128_driver_irq_postinstall(struct drm_device * dev)
+int r128_driver_irq_postinstall(struct drm_device *dev)
 {
-	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-	/* Turn on VBL interrupt */
-	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+	return drm_vblank_init(dev, 1);
 }
 
 void r128_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index 51a9afc..f7a5b57 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -1629,7 +1629,7 @@
 
 	switch (param->param) {
 	case R128_PARAM_IRQ_NR:
-		value = dev->irq;
+		value = drm_dev_to_irq(dev);
 		break;
 	default:
 		return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 248ab4a..59a2132 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -71,7 +71,8 @@
 
 static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
 {
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
 		return RS690_READ_MCIND(dev_priv, addr);
 	else
 		return RS480_READ_MCIND(dev_priv, addr);
@@ -82,7 +83,8 @@
 
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
 		return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
 		return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
 	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
 		return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
@@ -94,7 +96,8 @@
 {
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
 		R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
 		RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
 	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
 		R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
@@ -106,7 +109,8 @@
 {
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
 		R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
 		RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
 	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
 		R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
@@ -122,15 +126,17 @@
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
 		R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
 		R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
 		RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
 		RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
 	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
 		R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
 		R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480) {
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
 		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
-		RADEON_WRITE(RS480_AGP_BASE_2, 0);
+		RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi);
 	} else {
 		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
 		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
@@ -347,6 +353,7 @@
 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
 		DRM_INFO("Loading R300 Microcode\n");
 		for (i = 0; i < 256; i++) {
@@ -356,6 +363,7 @@
 				     R300_cp_microcode[i][0]);
 		}
 	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
 		DRM_INFO("Loading R400 Microcode\n");
 		for (i = 0; i < 256; i++) {
@@ -364,8 +372,9 @@
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
 				     R420_cp_microcode[i][0]);
 		}
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
-		DRM_INFO("Loading RS690 Microcode\n");
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+		DRM_INFO("Loading RS690/RS740 Microcode\n");
 		for (i = 0; i < 256; i++) {
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
 				     RS690_cp_microcode[i][1]);
@@ -626,8 +635,6 @@
 		     dev_priv->ring.size_l2qw);
 #endif
 
-	/* Start with assuming that writeback doesn't work */
-	dev_priv->writeback_works = 0;
 
 	/* Initialize the scratch register pointer.  This will cause
 	 * the scratch register values to be written out to memory
@@ -646,8 +653,18 @@
 	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
 
 	/* Turn on bus mastering */
-	tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
-	RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+		/* rs400, rs690/rs740 */
+		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS400_BUS_MASTER_DIS;
+		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+	} else if (!(((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+		    ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R423))) {
+		/* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */
+		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+	} /* PCIE cards appears to not need this */
 
 	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
 	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
@@ -674,6 +691,9 @@
 {
 	u32 tmp;
 
+	/* Start with assuming that writeback doesn't work */
+	dev_priv->writeback_works = 0;
+
 	/* Writeback doesn't seem to work everywhere, test it here and possibly
 	 * enable it if it appears to work
 	 */
@@ -719,7 +739,8 @@
 			  dev_priv->gart_size);
 
 		temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
 			IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
 							     RS690_BLOCK_GFX_D3_EN));
 		else
@@ -812,6 +833,7 @@
 	u32 tmp;
 
 	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740) ||
 	    (dev_priv->flags & RADEON_IS_IGPGART)) {
 		radeon_set_igpgart(dev_priv, on);
 		return;
@@ -1286,7 +1308,7 @@
 	radeon_cp_init_ring_buffer(dev, dev_priv);
 
 	radeon_do_engine_reset(dev);
-	radeon_enable_interrupt(dev);
+	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
 
 	DRM_DEBUG("radeon_do_resume_cp() complete\n");
 
@@ -1708,6 +1730,7 @@
 	case CHIP_R300:
 	case CHIP_R350:
 	case CHIP_R420:
+	case CHIP_R423:
 	case CHIP_RV410:
 	case CHIP_RV515:
 	case CHIP_R520:
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 637bd7f..71af746 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -52,6 +52,28 @@
 		        "r300"));
 }
 
+static int radeon_suspend(struct drm_device *dev, pm_message_t state)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	/* Disable *all* interrupts */
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+	return 0;
+}
+
+static int radeon_resume(struct drm_device *dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	/* Restore interrupt registers */
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+		RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+	return 0;
+}
+
 static struct pci_device_id pciidlist[] = {
 	radeon_PCI_IDS
 };
@@ -59,8 +81,7 @@
 static struct drm_driver driver = {
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
-	    DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
+	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
 	.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
 	.load = radeon_driver_load,
 	.firstopen = radeon_driver_firstopen,
@@ -69,8 +90,11 @@
 	.postclose = radeon_driver_postclose,
 	.lastclose = radeon_driver_lastclose,
 	.unload = radeon_driver_unload,
-	.vblank_wait = radeon_driver_vblank_wait,
-	.vblank_wait2 = radeon_driver_vblank_wait2,
+	.suspend = radeon_suspend,
+	.resume = radeon_resume,
+	.get_vblank_counter = radeon_get_vblank_counter,
+	.enable_vblank = radeon_enable_vblank,
+	.disable_vblank = radeon_disable_vblank,
 	.dri_library_name = dri_library_name,
 	.irq_preinstall = radeon_driver_irq_preinstall,
 	.irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 0993816..4dbb813 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -122,9 +122,12 @@
 	CHIP_RV350,
 	CHIP_RV380,
 	CHIP_R420,
+	CHIP_R423,
 	CHIP_RV410,
+	CHIP_RS400,
 	CHIP_RS480,
 	CHIP_RS690,
+	CHIP_RS740,
 	CHIP_RV515,
 	CHIP_R520,
 	CHIP_RV530,
@@ -378,17 +381,17 @@
 			       struct mem_block *heap);
 
 				/* radeon_irq.c */
+extern void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state);
 extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
 extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
 extern void radeon_do_release(struct drm_device * dev);
-extern int radeon_driver_vblank_wait(struct drm_device * dev,
-				     unsigned int *sequence);
-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
-				      unsigned int *sequence);
+extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
+extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
 extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
 extern void radeon_driver_irq_preinstall(struct drm_device * dev);
-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern int radeon_driver_irq_postinstall(struct drm_device *dev);
 extern void radeon_driver_irq_uninstall(struct drm_device * dev);
 extern void radeon_enable_interrupt(struct drm_device *dev);
 extern int radeon_vblank_crtc_get(struct drm_device *dev);
@@ -397,19 +400,22 @@
 extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
 extern int radeon_driver_unload(struct drm_device *dev);
 extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(struct drm_device * dev, struct drm_file *file_priv);
-extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp);
+extern void radeon_driver_preclose(struct drm_device *dev,
+				   struct drm_file *file_priv);
+extern void radeon_driver_postclose(struct drm_device *dev,
+				    struct drm_file *file_priv);
 extern void radeon_driver_lastclose(struct drm_device * dev);
-extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv);
+extern int radeon_driver_open(struct drm_device *dev,
+			      struct drm_file *file_priv);
 extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
 				unsigned long arg);
 
 /* r300_cmdbuf.c */
 extern void r300_init_reg_flags(struct drm_device *dev);
 
-extern int r300_do_cp_cmdbuf(struct drm_device * dev,
+extern int r300_do_cp_cmdbuf(struct drm_device *dev,
 			     struct drm_file *file_priv,
-			     drm_radeon_kcmd_buffer_t * cmdbuf);
+			     drm_radeon_kcmd_buffer_t *cmdbuf);
 
 /* Flags for stats.boxes
  */
@@ -434,8 +440,31 @@
 #	define RADEON_SCISSOR_1_ENABLE		(1 << 29)
 #	define RADEON_SCISSOR_2_ENABLE		(1 << 30)
 
+/*
+ * PCIE radeons (rv370/rv380, rv410, r423/r430/r480, r5xx)
+ * don't have an explicit bus mastering disable bit.  It's handled
+ * by the PCI D-states.  PMI_BM_DIS disables D-state bus master
+ * handling, not bus mastering itself.
+ */
 #define RADEON_BUS_CNTL			0x0030
+/* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */
 #	define RADEON_BUS_MASTER_DIS		(1 << 6)
+/* rs400, rs690/rs740 */
+#	define RS400_BUS_MASTER_DIS		(1 << 14)
+#	define RS400_MSI_REARM		        (1 << 20)
+/* see RS480_MSI_REARM in AIC_CNTL for rs480 */
+
+#define RADEON_BUS_CNTL1		0x0034
+#	define RADEON_PMI_BM_DIS		(1 << 2)
+#	define RADEON_PMI_INT_DIS		(1 << 3)
+
+#define RV370_BUS_CNTL			0x004c
+#	define RV370_PMI_BM_DIS		        (1 << 5)
+#	define RV370_PMI_INT_DIS		(1 << 6)
+
+#define RADEON_MSI_REARM_EN		0x0160
+/* rv370/rv380, rv410, r423/r430/r480, r5xx */
+#	define RV370_MSI_REARM_EN		(1 << 0)
 
 #define RADEON_CLOCK_CNTL_DATA		0x000c
 #	define RADEON_PLL_WR_EN			(1 << 7)
@@ -623,6 +652,7 @@
 #	define RADEON_SW_INT_TEST		(1 << 25)
 #	define RADEON_SW_INT_TEST_ACK		(1 << 25)
 #	define RADEON_SW_INT_FIRE		(1 << 26)
+#       define R500_DISPLAY_INT_STATUS          (1 << 0)
 
 #define RADEON_HOST_PATH_CNTL		0x0130
 #	define RADEON_HDP_SOFT_RESET		(1 << 26)
@@ -907,6 +937,7 @@
 
 #define RADEON_AIC_CNTL			0x01d0
 #	define RADEON_PCIGART_TRANSLATE_EN	(1 << 0)
+#	define RS480_MSI_REARM	                (1 << 3)
 #define RADEON_AIC_STAT			0x01d4
 #define RADEON_AIC_PT_BASE		0x01d8
 #define RADEON_AIC_LO_ADDR		0x01dc
@@ -1116,6 +1147,9 @@
 
 #define R200_VAP_PVS_CNTL_1               0x22D0
 
+#define RADEON_CRTC_CRNT_FRAME 0x0214
+#define RADEON_CRTC2_CRNT_FRAME 0x0314
+
 #define R500_D1CRTC_STATUS 0x609c
 #define R500_D2CRTC_STATUS 0x689c
 #define R500_CRTC_V_BLANK (1<<0)
@@ -1200,7 +1234,8 @@
 
 #define IGP_WRITE_MCIND(addr, val)				\
 do {									\
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)       \
+	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||   \
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))      \
 		RS690_WRITE_MCIND(addr, val);				\
 	else								\
 		RS480_WRITE_MCIND(addr, val);				\
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
index ee40d19..5079f70 100644
--- a/drivers/gpu/drm/radeon/radeon_irq.c
+++ b/drivers/gpu/drm/radeon/radeon_irq.c
@@ -27,7 +27,7 @@
  *
  * Authors:
  *    Keith Whitwell <keith@tungstengraphics.com>
- *    Michel Dänzer <michel@daenzer.net>
+ *    Michel D�zer <michel@daenzer.net>
  */
 
 #include "drmP.h"
@@ -35,12 +35,128 @@
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
-					      u32 mask)
+void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
 {
-	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if (state)
+		dev_priv->irq_enable_reg |= mask;
+	else
+		dev_priv->irq_enable_reg &= ~mask;
+
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+}
+
+static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if (state)
+		dev_priv->r500_disp_irq_reg |= mask;
+	else
+		dev_priv->r500_disp_irq_reg &= ~mask;
+
+	RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
+}
+
+int radeon_enable_vblank(struct drm_device *dev, int crtc)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		switch (crtc) {
+		case 0:
+			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
+			break;
+		case 1:
+			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			return EINVAL;
+		}
+	} else {
+		switch (crtc) {
+		case 0:
+			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
+			break;
+		case 1:
+			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			return EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+void radeon_disable_vblank(struct drm_device *dev, int crtc)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		switch (crtc) {
+		case 0:
+			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
+			break;
+		case 1:
+			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			break;
+		}
+	} else {
+		switch (crtc) {
+		case 0:
+			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
+			break;
+		case 1:
+			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			break;
+		}
+	}
+}
+
+static inline u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
+{
+	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
+	u32 irq_mask = RADEON_SW_INT_TEST;
+
+	*r500_disp_int = 0;
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		/* vbl interrupts in a different place */
+
+		if (irqs & R500_DISPLAY_INT_STATUS) {
+			/* if a display interrupt */
+			u32 disp_irq;
+
+			disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS);
+
+			*r500_disp_int = disp_irq;
+			if (disp_irq & R500_D1_VBLANK_INTERRUPT)
+				RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK);
+			if (disp_irq & R500_D2_VBLANK_INTERRUPT)
+				RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK);
+		}
+		irq_mask |= R500_DISPLAY_INT_STATUS;
+	} else
+		irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT;
+
+	irqs &=	irq_mask;
+
 	if (irqs)
 		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+
 	return irqs;
 }
 
@@ -68,44 +184,33 @@
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	u32 stat;
+	u32 r500_disp_int;
 
 	/* Only consider the bits we're interested in - others could be used
 	 * outside the DRM
 	 */
-	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-						  RADEON_CRTC_VBLANK_STAT |
-						  RADEON_CRTC2_VBLANK_STAT));
+	stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int);
 	if (!stat)
 		return IRQ_NONE;
 
 	stat &= dev_priv->irq_enable_reg;
 
 	/* SW interrupt */
-	if (stat & RADEON_SW_INT_TEST) {
+	if (stat & RADEON_SW_INT_TEST)
 		DRM_WAKEUP(&dev_priv->swi_queue);
-	}
 
 	/* VBLANK interrupt */
-	if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
-		int vblank_crtc = dev_priv->vblank_crtc;
-
-		if ((vblank_crtc &
-		     (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
-		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
-			if (stat & RADEON_CRTC_VBLANK_STAT)
-				atomic_inc(&dev->vbl_received);
-			if (stat & RADEON_CRTC2_VBLANK_STAT)
-				atomic_inc(&dev->vbl_received2);
-		} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
-			   (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
-			   ((stat & RADEON_CRTC2_VBLANK_STAT) &&
-			    (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
-			atomic_inc(&dev->vbl_received);
-
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
+			drm_handle_vblank(dev, 0);
+		if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
+			drm_handle_vblank(dev, 1);
+	} else {
+		if (stat & RADEON_CRTC_VBLANK_STAT)
+			drm_handle_vblank(dev, 0);
+		if (stat & RADEON_CRTC2_VBLANK_STAT)
+			drm_handle_vblank(dev, 1);
 	}
-
 	return IRQ_HANDLED;
 }
 
@@ -144,54 +249,31 @@
 	return ret;
 }
 
-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
-					unsigned int *sequence, int crtc)
+u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
 {
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-	unsigned int cur_vblank;
-	int ret = 0;
-	int ack = 0;
-	atomic_t *counter;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
 	if (!dev_priv) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
 
-	if (crtc == DRM_RADEON_VBLANK_CRTC1) {
-		counter = &dev->vbl_received;
-		ack |= RADEON_CRTC_VBLANK_STAT;
-	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
-		counter = &dev->vbl_received2;
-		ack |= RADEON_CRTC2_VBLANK_STAT;
-	} else
+	if (crtc < 0 || crtc > 1) {
+		DRM_ERROR("Invalid crtc %d\n", crtc);
 		return -EINVAL;
+	}
 
-	radeon_acknowledge_irqs(dev_priv, ack);
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
-	 */
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(counter))
-		      - *sequence) <= (1 << 23)));
-
-	*sequence = cur_vblank;
-
-	return ret;
-}
-
-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
-}
-
-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		if (crtc == 0)
+			return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
+		else
+			return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
+	} else {
+		if (crtc == 0)
+			return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
+		else
+			return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
+	}
 }
 
 /* Needs the lock as it touches the ring.
@@ -234,46 +316,41 @@
 	return radeon_wait_irq(dev, irqwait->irq_seq);
 }
 
-void radeon_enable_interrupt(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
-	dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
-	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
-		dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
-
-	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
-		dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
-
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
-	dev_priv->irq_enabled = 1;
-}
-
 /* drm_dma.h hooks
 */
 void radeon_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
+	u32 dummy;
 
 	/* Disable *all* interrupts */
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 
 	/* Clear bits if they're already high */
-	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-					   RADEON_CRTC_VBLANK_STAT |
-					   RADEON_CRTC2_VBLANK_STAT));
+	radeon_acknowledge_irqs(dev_priv, &dummy);
 }
 
-void radeon_driver_irq_postinstall(struct drm_device * dev)
+int radeon_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
+	int ret;
 
 	atomic_set(&dev_priv->swi_emitted, 0);
 	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
 
-	radeon_enable_interrupt(dev);
+	ret = drm_vblank_init(dev, 2);
+	if (ret)
+		return ret;
+
+	dev->max_vblank_count = 0x001fffff;
+
+	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
+
+	return 0;
 }
 
 void radeon_driver_irq_uninstall(struct drm_device * dev)
@@ -285,6 +362,8 @@
 
 	dev_priv->irq_enabled = 0;
 
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
 	/* Disable *all* interrupts */
 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 }
@@ -293,18 +372,8 @@
 int radeon_vblank_crtc_get(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-	u32 flag;
-	u32 value;
 
-	flag = RADEON_READ(RADEON_GEN_INT_CNTL);
-	value = 0;
-
-	if (flag & RADEON_CRTC_VBLANK_MASK)
-		value |= DRM_RADEON_VBLANK_CRTC1;
-
-	if (flag & RADEON_CRTC2_VBLANK_MASK)
-		value |= DRM_RADEON_VBLANK_CRTC2;
-	return value;
+	return dev_priv->vblank_crtc;
 }
 
 int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
@@ -315,6 +384,5 @@
 		return -EINVAL;
 	}
 	dev_priv->vblank_crtc = (unsigned int)value;
-	radeon_enable_interrupt(dev);
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 11c146b..5d7153f 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -2997,7 +2997,7 @@
 		value = GET_SCRATCH(2);
 		break;
 	case RADEON_PARAM_IRQ_NR:
-		value = dev->irq;
+		value = drm_dev_to_irq(dev);
 		break;
 	case RADEON_PARAM_GART_BASE:
 		value = dev_priv->gart_vm_start;
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
index b387877..af22111 100644
--- a/drivers/gpu/drm/sis/sis_mm.c
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -41,7 +41,7 @@
 #define AGP_TYPE 1
 
 
-#if defined(CONFIG_FB_SIS)
+#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
 /* fb management via fb device */
 
 #define SIS_MM_ALIGN_SHIFT 0
@@ -57,7 +57,7 @@
 	if (req.size == 0)
 		return NULL;
 	else
-		return (void *)~req.offset;
+		return (void *)(unsigned long)~req.offset;
 }
 
 static void sis_sman_mm_free(void *private, void *ref)
@@ -75,12 +75,12 @@
 	return ~((unsigned long)ref);
 }
 
-#else /* CONFIG_FB_SIS */
+#else /* CONFIG_FB_SIS[_MODULE] */
 
 #define SIS_MM_ALIGN_SHIFT 4
 #define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
 
-#endif /* CONFIG_FB_SIS */
+#endif /* CONFIG_FB_SIS[_MODULE] */
 
 static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
@@ -89,7 +89,7 @@
 	int ret;
 
 	mutex_lock(&dev->struct_mutex);
-#if defined(CONFIG_FB_SIS)
+#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
 	{
 		struct drm_sman_mm sman_mm;
 		sman_mm.private = (void *)0xFFFFFFFF;
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index 80c01cd..0993b44 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -40,11 +40,13 @@
 static struct drm_driver driver = {
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
-	    DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+	    DRIVER_IRQ_SHARED,
 	.load = via_driver_load,
 	.unload = via_driver_unload,
 	.context_dtor = via_final_context,
-	.vblank_wait = via_driver_vblank_wait,
+	.get_vblank_counter = via_get_vblank_counter,
+	.enable_vblank = via_enable_vblank,
+	.disable_vblank = via_disable_vblank,
 	.irq_preinstall = via_driver_irq_preinstall,
 	.irq_postinstall = via_driver_irq_postinstall,
 	.irq_uninstall = via_driver_irq_uninstall,
@@ -59,17 +61,17 @@
 	.get_reg_ofs = drm_core_get_reg_ofs,
 	.ioctls = via_ioctls,
 	.fops = {
-		 .owner = THIS_MODULE,
-		 .open = drm_open,
-		 .release = drm_release,
-		 .ioctl = drm_ioctl,
-		 .mmap = drm_mmap,
-		 .poll = drm_poll,
-		 .fasync = drm_fasync,
-	},
+		.owner = THIS_MODULE,
+		.open = drm_open,
+		.release = drm_release,
+		.ioctl = drm_ioctl,
+		.mmap = drm_mmap,
+		.poll = drm_poll,
+		.fasync = drm_fasync,
+		},
 	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
+		.name = DRIVER_NAME,
+		.id_table = pciidlist,
 	},
 
 	.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 2daae81..cafcb84 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -75,6 +75,7 @@
 	struct timeval last_vblank;
 	int last_vblank_valid;
 	unsigned usec_per_vblank;
+	atomic_t vbl_received;
 	drm_via_state_t hc_state;
 	char pci_buf[VIA_PCI_BUF_SIZE];
 	const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
@@ -130,21 +131,24 @@
 extern int via_final_context(struct drm_device * dev, int context);
 
 extern int via_do_cleanup_map(struct drm_device * dev);
-extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int via_enable_vblank(struct drm_device *dev, int crtc);
+extern void via_disable_vblank(struct drm_device *dev, int crtc);
 
 extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
 extern void via_driver_irq_preinstall(struct drm_device * dev);
-extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern int via_driver_irq_postinstall(struct drm_device *dev);
 extern void via_driver_irq_uninstall(struct drm_device * dev);
 
 extern int via_dma_cleanup(struct drm_device * dev);
 extern void via_init_command_verifier(void);
 extern int via_driver_dma_quiescent(struct drm_device * dev);
-extern void via_init_futex(drm_via_private_t * dev_priv);
-extern void via_cleanup_futex(drm_via_private_t * dev_priv);
-extern void via_release_futex(drm_via_private_t * dev_priv, int context);
+extern void via_init_futex(drm_via_private_t *dev_priv);
+extern void via_cleanup_futex(drm_via_private_t *dev_priv);
+extern void via_release_futex(drm_via_private_t *dev_priv, int context);
 
-extern void via_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv);
+extern void via_reclaim_buffers_locked(struct drm_device *dev,
+				       struct drm_file *file_priv);
 extern void via_lastclose(struct drm_device *dev);
 
 extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
index c6bb978..665d319 100644
--- a/drivers/gpu/drm/via/via_irq.c
+++ b/drivers/gpu/drm/via/via_irq.c
@@ -43,7 +43,7 @@
 #define VIA_REG_INTERRUPT       0x200
 
 /* VIA_REG_INTERRUPT */
-#define VIA_IRQ_GLOBAL          (1 << 31)
+#define VIA_IRQ_GLOBAL	  (1 << 31)
 #define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
 #define VIA_IRQ_VBLANK_PENDING  (1 << 3)
 #define VIA_IRQ_HQV0_ENABLE     (1 << 11)
@@ -68,16 +68,15 @@
 
 static maskarray_t via_pro_group_a_irqs[] = {
 	{VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
-	 0x00000000},
+	 0x00000000 },
 	{VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
-	 0x00000000},
+	 0x00000000 },
 	{VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
 	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
 	{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
 	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
 };
-static int via_num_pro_group_a =
-    sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
+static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs);
 static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
 
 static maskarray_t via_unichrome_irqs[] = {
@@ -86,14 +85,24 @@
 	{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
 	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
 };
-static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
 static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
 
+
 static unsigned time_diff(struct timeval *now, struct timeval *then)
 {
 	return (now->tv_usec >= then->tv_usec) ?
-	    now->tv_usec - then->tv_usec :
-	    1000000 - (then->tv_usec - now->tv_usec);
+		now->tv_usec - then->tv_usec :
+		1000000 - (then->tv_usec - now->tv_usec);
+}
+
+u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	drm_via_private_t *dev_priv = dev->dev_private;
+	if (crtc != 0)
+		return 0;
+
+	return atomic_read(&dev_priv->vbl_received);
 }
 
 irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
@@ -108,23 +117,22 @@
 
 	status = VIA_READ(VIA_REG_INTERRUPT);
 	if (status & VIA_IRQ_VBLANK_PENDING) {
-		atomic_inc(&dev->vbl_received);
-		if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+		atomic_inc(&dev_priv->vbl_received);
+		if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
 			do_gettimeofday(&cur_vblank);
 			if (dev_priv->last_vblank_valid) {
 				dev_priv->usec_per_vblank =
-				    time_diff(&cur_vblank,
-					      &dev_priv->last_vblank) >> 4;
+					time_diff(&cur_vblank,
+						  &dev_priv->last_vblank) >> 4;
 			}
 			dev_priv->last_vblank = cur_vblank;
 			dev_priv->last_vblank_valid = 1;
 		}
-		if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+		if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
 			DRM_DEBUG("US per vblank is: %u\n",
 				  dev_priv->usec_per_vblank);
 		}
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+		drm_handle_vblank(dev, 0);
 		handled = 1;
 	}
 
@@ -145,6 +153,7 @@
 	/* Acknowlege interrupts */
 	VIA_WRITE(VIA_REG_INTERRUPT, status);
 
+
 	if (handled)
 		return IRQ_HANDLED;
 	else
@@ -163,31 +172,34 @@
 	}
 }
 
-int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int via_enable_vblank(struct drm_device *dev, int crtc)
 {
-	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-	unsigned int cur_vblank;
-	int ret = 0;
+	drm_via_private_t *dev_priv = dev->dev_private;
+	u32 status;
 
-	DRM_DEBUG("\n");
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
+	if (crtc != 0) {
+		DRM_ERROR("%s:  bad crtc %d\n", __func__, crtc);
 		return -EINVAL;
 	}
 
-	viadrv_acknowledge_irqs(dev_priv);
+	status = VIA_READ(VIA_REG_INTERRUPT);
+	VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
 
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
-	 */
+	VIA_WRITE8(0x83d4, 0x11);
+	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received)) -
-		      *sequence) <= (1 << 23)));
+	return 0;
+}
 
-	*sequence = cur_vblank;
-	return ret;
+void via_disable_vblank(struct drm_device *dev, int crtc)
+{
+	drm_via_private_t *dev_priv = dev->dev_private;
+
+	VIA_WRITE8(0x83d4, 0x11);
+	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+	if (crtc != 0)
+		DRM_ERROR("%s:  bad crtc %d\n", __func__, crtc);
 }
 
 static int
@@ -239,6 +251,7 @@
 	return ret;
 }
 
+
 /*
  * drm_dma.h hooks
  */
@@ -292,23 +305,25 @@
 	}
 }
 
-void via_driver_irq_postinstall(struct drm_device * dev)
+int via_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
 
-	DRM_DEBUG("\n");
-	if (dev_priv) {
-		status = VIA_READ(VIA_REG_INTERRUPT);
-		VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-			  | dev_priv->irq_enable_mask);
+	DRM_DEBUG("via_driver_irq_postinstall\n");
+	if (!dev_priv)
+		return -EINVAL;
 
-		/* Some magic, oh for some data sheets ! */
+	drm_vblank_init(dev, 1);
+	status = VIA_READ(VIA_REG_INTERRUPT);
+	VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+		  | dev_priv->irq_enable_mask);
 
-		VIA_WRITE8(0x83d4, 0x11);
-		VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+	/* Some magic, oh for some data sheets ! */
+	VIA_WRITE8(0x83d4, 0x11);
+	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
 
-	}
+	return 0;
 }
 
 void via_driver_irq_uninstall(struct drm_device * dev)
@@ -339,9 +354,6 @@
 	drm_via_irq_t *cur_irq = dev_priv->via_irqs;
 	int force_sequence;
 
-	if (!dev->irq)
-		return -EINVAL;
-
 	if (irqwait->request.irq >= dev_priv->num_irqs) {
 		DRM_ERROR("Trying to wait on unknown irq %d\n",
 			  irqwait->request.irq);
@@ -352,7 +364,8 @@
 
 	switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
 	case VIA_IRQ_RELATIVE:
-		irqwait->request.sequence += atomic_read(&cur_irq->irq_received);
+		irqwait->request.sequence +=
+			atomic_read(&cur_irq->irq_received);
 		irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
 	case VIA_IRQ_ABSOLUTE:
 		break;
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
index e640949..f694cb5 100644
--- a/drivers/gpu/drm/via/via_mm.c
+++ b/drivers/gpu/drm/via/via_mm.c
@@ -93,8 +93,7 @@
 	/* Last context, perform cleanup */
 	if (dev->ctx_count == 1 && dev->dev_private) {
 		DRM_DEBUG("Last Context\n");
-		if (dev->irq)
-			drm_irq_uninstall(dev);
+		drm_irq_uninstall(dev);
 		via_cleanup_futex(dev_priv);
 		via_do_cleanup_map(dev);
 	}
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 227642b..a887824 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -3481,7 +3481,9 @@
 					}
 					ctrlVal = 0;
 					for (k = 0; k < state->MXL_Ctrl[i].size; k++)
-						ctrlVal += state->MXL_Ctrl[i].val[k] * (1 << k);
+						ctrlVal += state->
+							MXL_Ctrl[i].val[k] *
+							(1 << k);
 				} else
 					return -1;
 			}
@@ -3581,7 +3583,7 @@
 
 static u32 MXL_Ceiling(u32 value, u32 resolution)
 {
-	return (value/resolution + (value % resolution > 0 ? 1 : 0));
+	return value / resolution + (value % resolution > 0 ? 1 : 0);
 }
 
 /* Retrieve the Initialzation Registers */
@@ -3910,7 +3912,10 @@
 
 static int mxl5005s_init(struct dvb_frontend *fe)
 {
+	struct mxl5005s_state *state = fe->tuner_priv;
+
 	dprintk(1, "%s()\n", __func__);
+	state->current_mode = MXL_QAM;
 	return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ);
 }
 
@@ -4092,7 +4097,6 @@
 	state->frontend = fe;
 	state->config = config;
 	state->i2c = i2c;
-	state->current_mode = MXL_QAM;
 
 	printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n",
 		config->i2c_address);
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index 2a1aac1..fb3f3b3 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -493,6 +493,7 @@
 	case TUNER_PHILIPS_FM1216ME_MK3:
 	case TUNER_PHILIPS_FM1236_MK3:
 	case TUNER_PHILIPS_FMD1216ME_MK3:
+	case TUNER_PHILIPS_FMD1216MEX_MK3:
 	case TUNER_LG_NTSC_TAPE:
 	case TUNER_PHILIPS_FM1256_IH3:
 	case TUNER_TCL_MF02GIP_5N:
@@ -767,6 +768,7 @@
 
 	switch (priv->type) {
 	case TUNER_PHILIPS_FMD1216ME_MK3:
+	case TUNER_PHILIPS_FMD1216MEX_MK3:
 		if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
 		    params->frequency >= 158870000)
 			buf[3] |= 0x08;
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c
index 04961a1..7c0bc06 100644
--- a/drivers/media/common/tuners/tuner-types.c
+++ b/drivers/media/common/tuners/tuner-types.c
@@ -946,7 +946,7 @@
 	},
 };
 
-/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
+/* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */
 
 static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
 	{ 16 * 160.00 /*MHz*/, 0x86, 0x51, },
@@ -984,6 +984,27 @@
 	},
 };
 
+static struct tuner_params tuner_philips_fmd1216mex_mk3_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_PAL,
+		.ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
+		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
+		.has_tda9887 = 1,
+		.port1_active = 1,
+		.port2_active = 1,
+		.port2_fm_high_sensitivity = 1,
+		.port2_invert_for_secam_lc = 1,
+		.port1_set_for_fm_mono = 1,
+		.radio_if = 1,
+		.fm_gain_normal = 1,
+	},
+	{
+		.type   = TUNER_PARAM_TYPE_DIGITAL,
+		.ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
+		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
+		.iffreq = 16 * 36.125, /*MHz*/
+	},
+};
 
 /* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
 
@@ -1663,6 +1684,16 @@
 		.params = tuner_tcl_mf02gip_5n_params,
 		.count  = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params),
 	},
+	[TUNER_PHILIPS_FMD1216MEX_MK3] = { /* Philips PAL */
+		.name   = "Philips FMD1216MEX MK3 Hybrid Tuner",
+		.params = tuner_philips_fmd1216mex_mk3_params,
+		.count  = ARRAY_SIZE(tuner_philips_fmd1216mex_mk3_params),
+		.min = 16 *  50.87,
+		.max = 16 * 858.00,
+		.stepsize = 166667,
+		.initdata = tua603x_agc112,
+		.sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
+	},
 };
 EXPORT_SYMBOL(tuners);
 
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index f9c2bb9..e12d13e 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -43,7 +43,7 @@
 static DEFINE_MUTEX(xc5000_list_mutex);
 static LIST_HEAD(hybrid_tuner_instance_list);
 
-#define dprintk(level,fmt, arg...) if (debug >= level) \
+#define dprintk(level, fmt, arg...) if (debug >= level) \
 	printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
 
 #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
@@ -138,11 +138,11 @@
    immediately the length of the following transaction.
 
 */
-typedef struct {
+struct XC_TV_STANDARD {
 	char *Name;
 	u16 AudioMode;
 	u16 VideoMode;
-} XC_TV_STANDARD;
+};
 
 /* Tuner standards */
 #define MN_NTSC_PAL_BTSC	0
@@ -169,7 +169,7 @@
 #define FM_Radio_INPUT2 	21
 #define FM_Radio_INPUT1 	22
 
-static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
+static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
 	{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
 	{"M/N-NTSC/PAL-A2",   0x0600, 0x8020},
 	{"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
@@ -183,7 +183,7 @@
 	{"D/K-PAL-NICAM",     0x0E80, 0x8009},
 	{"D/K-PAL-MONO",      0x1478, 0x8009},
 	{"D/K-SECAM-A2 DK1",  0x1200, 0x8009},
-	{"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009},
+	{"D/K-SECAM-A2 L/DK3", 0x0E00, 0x8009},
 	{"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
 	{"L-SECAM-NICAM",     0x8E82, 0x0009},
 	{"L'-SECAM-NICAM",    0x8E82, 0x4009},
@@ -307,9 +307,10 @@
 	unsigned int len, pos, index;
 	u8 buf[XC_MAX_I2C_WRITE_LENGTH];
 
-	index=0;
-	while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) {
-		len = i2c_sequence[index]* 256 + i2c_sequence[index+1];
+	index = 0;
+	while ((i2c_sequence[index] != 0xFF) ||
+		(i2c_sequence[index + 1] != 0xFF)) {
+		len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
 		if (len == 0x0000) {
 			/* RESET command */
 			result = xc_reset(fe);
@@ -329,15 +330,17 @@
 			buf[1] = i2c_sequence[index + 1];
 			pos = 2;
 			while (pos < len) {
-				if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) {
-					nbytes_to_send = XC_MAX_I2C_WRITE_LENGTH;
-				} else {
+				if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
+					nbytes_to_send =
+						XC_MAX_I2C_WRITE_LENGTH;
+				else
 					nbytes_to_send = (len - pos + 2);
+				for (i = 2; i < nbytes_to_send; i++) {
+					buf[i] = i2c_sequence[index + pos +
+						i - 2];
 				}
-				for (i=2; i<nbytes_to_send; i++) {
-					buf[i] = i2c_sequence[index + pos + i - 2];
-				}
-				result = xc_send_i2c_data(priv, buf, nbytes_to_send);
+				result = xc_send_i2c_data(priv, buf,
+					nbytes_to_send);
 
 				if (result != XC_RESULT_SUCCESS)
 					return result;
@@ -386,8 +389,7 @@
 	dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
 		rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
 
-	if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
-	{
+	if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
 		rf_mode = XC_RF_MODE_CABLE;
 		printk(KERN_ERR
 			"%s(), Invalid mode, defaulting to CABLE",
@@ -560,13 +562,13 @@
 		.flags = I2C_M_RD, .buf = buf, .len = len };
 
 	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
-		printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
+		printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", (int)len);
 		return -EREMOTEIO;
 	}
 	return 0;
 }
 
-static int xc5000_fwupload(struct dvb_frontend* fe)
+static int xc5000_fwupload(struct dvb_frontend *fe)
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
 	const struct firmware *fw;
@@ -576,7 +578,8 @@
 	printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
 		XC5000_DEFAULT_FIRMWARE);
 
-	ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c_props.adap->dev);
+	ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE,
+		&priv->i2c_props.adap->dev);
 	if (ret) {
 		printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
 		ret = XC_RESULT_RESET_FAILURE;
@@ -592,7 +595,7 @@
 		ret = XC_RESULT_RESET_FAILURE;
 	} else {
 		printk(KERN_INFO "xc5000: firmware upload\n");
-		ret = xc_load_i2c_sequence(fe,  fw->data );
+		ret = xc_load_i2c_sequence(fe,  fw->data);
 	}
 
 out:
@@ -651,7 +654,7 @@
 
 	dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
 
-	switch(params->u.vsb.modulation) {
+	switch (params->u.vsb.modulation) {
 	case VSB_8:
 	case VSB_16:
 		dprintk(1, "%s() VSB modulation\n", __func__);
@@ -748,42 +751,42 @@
 	/* FIX ME: Some video standards may have several possible audio
 		   standards. We simply default to one of them here.
 	 */
-	if(params->std & V4L2_STD_MN) {
+	if (params->std & V4L2_STD_MN) {
 		/* default to BTSC audio standard */
 		priv->video_standard = MN_NTSC_PAL_BTSC;
 		goto tune_channel;
 	}
 
-	if(params->std & V4L2_STD_PAL_BG) {
+	if (params->std & V4L2_STD_PAL_BG) {
 		/* default to NICAM audio standard */
 		priv->video_standard = BG_PAL_NICAM;
 		goto tune_channel;
 	}
 
-	if(params->std & V4L2_STD_PAL_I) {
+	if (params->std & V4L2_STD_PAL_I) {
 		/* default to NICAM audio standard */
 		priv->video_standard = I_PAL_NICAM;
 		goto tune_channel;
 	}
 
-	if(params->std & V4L2_STD_PAL_DK) {
+	if (params->std & V4L2_STD_PAL_DK) {
 		/* default to NICAM audio standard */
 		priv->video_standard = DK_PAL_NICAM;
 		goto tune_channel;
 	}
 
-	if(params->std & V4L2_STD_SECAM_DK) {
+	if (params->std & V4L2_STD_SECAM_DK) {
 		/* default to A2 DK1 audio standard */
 		priv->video_standard = DK_SECAM_A2DK1;
 		goto tune_channel;
 	}
 
-	if(params->std & V4L2_STD_SECAM_L) {
+	if (params->std & V4L2_STD_SECAM_L) {
 		priv->video_standard = L_SECAM_NICAM;
 		goto tune_channel;
 	}
 
-	if(params->std & V4L2_STD_SECAM_LC) {
+	if (params->std & V4L2_STD_SECAM_LC) {
 		priv->video_standard = LC_SECAM_NICAM;
 		goto tune_channel;
 	}
@@ -791,7 +794,7 @@
 tune_channel:
 	ret = xc_SetSignalSource(priv, priv->rf_mode);
 	if (ret != XC_RESULT_SUCCESS) {
-	printk(KERN_ERR
+		printk(KERN_ERR
 			"xc5000: xc_SetSignalSource(%d) failed\n",
 			priv->rf_mode);
 		return -EREMOTEIO;
@@ -863,7 +866,7 @@
 	 * I2C transactions until calibration is complete.  This way we
 	 * don't have to rely on clock stretching working.
 	 */
-	xc_wait( 100 );
+	xc_wait(100);
 
 	/* Default to "CABLE" mode */
 	ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
@@ -885,15 +888,13 @@
 	 */
 
 	ret = xc_shutdown(priv);
-	if(ret != XC_RESULT_SUCCESS) {
+	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR
 			"xc5000: %s() unable to shutdown tuner\n",
 			__func__);
 		return -EREMOTEIO;
-	}
-	else {
+	} else
 		return XC_RESULT_SUCCESS;
-	}
 }
 
 static int xc5000_init(struct dvb_frontend *fe)
@@ -989,7 +990,7 @@
 	if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
 		goto fail;
 
-	switch(id) {
+	switch (id) {
 	case XC_PRODUCT_ID_FW_LOADED:
 		printk(KERN_INFO
 			"xc5000: Successfully identified at address 0x%02x\n",
diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h
index cf1a558..f4c1466 100644
--- a/drivers/media/common/tuners/xc5000.h
+++ b/drivers/media/common/tuners/xc5000.h
@@ -45,17 +45,17 @@
 
 #if defined(CONFIG_MEDIA_TUNER_XC5000) || \
     (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
-extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 					  struct i2c_adapter *i2c,
 					  struct xc5000_config *cfg);
 #else
-static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 						 struct i2c_adapter *i2c,
 						 struct xc5000_config *cfg)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-#endif // CONFIG_MEDIA_TUNER_XC5000
+#endif
 
-#endif // __XC5000_H__
+#endif
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index f732144..14e627e 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -595,6 +595,18 @@
 	dm1105dvb_dma_unmap(dm1105dvb);
 }
 
+static struct stv0299_config sharp_z0194a_config = {
+	.demod_address = 0x68,
+	.inittab = sharp_z0194a_inittab,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.lock_output = STV0299_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
 static struct stv0288_config earda_config = {
 	.demod_address = 0x68,
 	.min_delay_ms = 100,
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index f170e82..5689d1f 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -47,6 +47,7 @@
 static int dvb_force_auto_inversion;
 static int dvb_override_tune_delay;
 static int dvb_powerdown_on_sleep = 1;
+static int dvb_mfe_wait_time = 5;
 
 module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
 MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
@@ -58,6 +59,8 @@
 MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
 module_param(dvb_powerdown_on_sleep, int, 0644);
 MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
+module_param(dvb_mfe_wait_time, int, 0644);
+MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
 
 #define dprintk if (dvb_frontend_debug) printk
 
@@ -212,8 +215,9 @@
 
 static void dvb_frontend_init(struct dvb_frontend *fe)
 {
-	dprintk ("DVB: initialising frontend %i (%s)...\n",
+	dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
 		 fe->dvb->num,
+		 fe->id,
 		 fe->ops.info.name);
 
 	if (fe->ops.init)
@@ -686,7 +690,7 @@
 	mb();
 
 	fe_thread = kthread_run(dvb_frontend_thread, fe,
-		"kdvb-fe-%i", fe->dvb->num);
+		"kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id);
 	if (IS_ERR(fe_thread)) {
 		ret = PTR_ERR(fe_thread);
 		printk("dvb_frontend_start: failed to start kthread (%d)\n", ret);
@@ -710,8 +714,8 @@
 		*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
 
 	if (*freq_min == 0 || *freq_max == 0)
-		printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n",
-		       fe->dvb->num);
+		printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
+		       fe->dvb->num,fe->id);
 }
 
 static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
@@ -724,8 +728,8 @@
 	dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max);
 	if ((freq_min && parms->frequency < freq_min) ||
 	    (freq_max && parms->frequency > freq_max)) {
-		printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n",
-		       fe->dvb->num, parms->frequency, freq_min, freq_max);
+		printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
+		       fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max);
 		return -EINVAL;
 	}
 
@@ -735,8 +739,8 @@
 		     parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) ||
 		    (fe->ops.info.symbol_rate_max &&
 		     parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) {
-			printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
-			       fe->dvb->num, parms->u.qpsk.symbol_rate,
+			printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
+			       fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate,
 			       fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
 			return -EINVAL;
 		}
@@ -746,8 +750,8 @@
 		     parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) ||
 		    (fe->ops.info.symbol_rate_max &&
 		     parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) {
-			printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
-			       fe->dvb->num, parms->u.qam.symbol_rate,
+			printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
+			       fe->dvb->num, fe->id, parms->u.qam.symbol_rate,
 			       fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
 			return -EINVAL;
 		}
@@ -899,30 +903,30 @@
 	int i;
 
 	if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
-		printk("%s: tvp.cmd = 0x%08x (undefined/unknown/invalid)\n",
+		printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n",
 			__func__, tvp->cmd);
 		return;
 	}
 
-	printk("%s() tvp.cmd    = 0x%08x (%s)\n"
-		,__FUNCTION__
+	dprintk("%s() tvp.cmd    = 0x%08x (%s)\n"
+		,__func__
 		,tvp->cmd
 		,dtv_cmds[ tvp->cmd ].name);
 
 	if(dtv_cmds[ tvp->cmd ].buffer) {
 
-		printk("%s() tvp.u.buffer.len = 0x%02x\n"
-			,__FUNCTION__
+		dprintk("%s() tvp.u.buffer.len = 0x%02x\n"
+			,__func__
 			,tvp->u.buffer.len);
 
 		for(i = 0; i < tvp->u.buffer.len; i++)
-			printk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
-				,__FUNCTION__
+			dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
+				,__func__
 				,i
 				,tvp->u.buffer.data[i]);
 
 	} else
-		printk("%s() tvp.u.data = 0x%08x\n", __FUNCTION__, tvp->u.data);
+		dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
 }
 
 int is_legacy_delivery_system(fe_delivery_system_t s)
@@ -942,8 +946,6 @@
 {
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	printk("%s()\n", __FUNCTION__);
-
 	c->frequency = p->frequency;
 	c->inversion = p->inversion;
 
@@ -998,27 +1000,25 @@
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	struct dvb_frontend_parameters *p = &fepriv->parameters;
 
-	printk("%s()\n", __FUNCTION__);
-
 	p->frequency = c->frequency;
 	p->inversion = c->inversion;
 
 	switch (fe->ops.info.type) {
 	case FE_QPSK:
-		printk("%s() Preparing QPSK req\n", __FUNCTION__);
+		dprintk("%s() Preparing QPSK req\n", __func__);
 		p->u.qpsk.symbol_rate = c->symbol_rate;
 		p->u.qpsk.fec_inner = c->fec_inner;
 		c->delivery_system = SYS_DVBS;
 		break;
 	case FE_QAM:
-		printk("%s() Preparing QAM req\n", __FUNCTION__);
+		dprintk("%s() Preparing QAM req\n", __func__);
 		p->u.qam.symbol_rate = c->symbol_rate;
 		p->u.qam.fec_inner = c->fec_inner;
 		p->u.qam.modulation = c->modulation;
 		c->delivery_system = SYS_DVBC_ANNEX_AC;
 		break;
 	case FE_OFDM:
-		printk("%s() Preparing OFDM req\n", __FUNCTION__);
+		dprintk("%s() Preparing OFDM req\n", __func__);
 		if (c->bandwidth_hz == 6000000)
 			p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
 		else if (c->bandwidth_hz == 7000000)
@@ -1036,7 +1036,7 @@
 		c->delivery_system = SYS_DVBT;
 		break;
 	case FE_ATSC:
-		printk("%s() Preparing VSB req\n", __FUNCTION__);
+		dprintk("%s() Preparing VSB req\n", __func__);
 		p->u.vsb.modulation = c->modulation;
 		if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
 			c->delivery_system = SYS_ATSC;
@@ -1055,14 +1055,13 @@
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	struct dvb_frontend_parameters *p = &fepriv->parameters;
 
-	printk("%s()\n", __FUNCTION__);
-
 	p->frequency = c->frequency;
 	p->inversion = c->inversion;
 
 	switch(c->modulation) {
 	case PSK_8:
 	case APSK_16:
+	case APSK_32:
 	case QPSK:
 		p->u.qpsk.symbol_rate = c->symbol_rate;
 		p->u.qpsk.fec_inner = c->fec_inner;
@@ -1089,19 +1088,17 @@
 {
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	printk("%s()\n", __FUNCTION__);
-
 	/* For legacy delivery systems we don't need the delivery_system to
 	 * be specified, but we populate the older structures from the cache
 	 * so we can call set_frontend on older drivers.
 	 */
 	if(is_legacy_delivery_system(c->delivery_system)) {
 
-		printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation);
+		dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation);
 		dtv_property_legacy_params_sync(fe);
 
 	} else {
-		printk("%s() adv, modulation = %d\n", __FUNCTION__, c->modulation);
+		dprintk("%s() adv, modulation = %d\n", __func__, c->modulation);
 
 		/* For advanced delivery systems / modulation types ...
 		 * we seed the lecacy dvb_frontend_parameters structure
@@ -1123,8 +1120,6 @@
 {
 	int r = 0;
 
-	printk("%s()\n", __FUNCTION__);
-
 	dtv_property_dump(tvp);
 
 	/* Allow the frontend to validate incoming properties */
@@ -1198,7 +1193,6 @@
 {
 	int r = 0;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	printk("%s()\n", __FUNCTION__);
 	dtv_property_dump(tvp);
 
 	/* Allow the frontend to validate incoming properties */
@@ -1213,7 +1207,7 @@
 		/* Reset a cache of data specific to the frontend here. This does
 		 * not effect hardware.
 		 */
-		printk("%s() Flushing property cache\n", __FUNCTION__);
+		dprintk("%s() Flushing property cache\n", __func__);
 		memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties));
 		fe->dtv_property_cache.state = tvp->cmd;
 		fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
@@ -1224,7 +1218,7 @@
 		 * ioctl.
 		 */
 		fe->dtv_property_cache.state = tvp->cmd;
-		printk("%s() Finalised property cache\n", __FUNCTION__);
+		dprintk("%s() Finalised property cache\n", __func__);
 		dtv_property_cache_submit(fe);
 
 		r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
@@ -1335,12 +1329,10 @@
 	dprintk("%s\n", __func__);
 
 	if(cmd == FE_SET_PROPERTY) {
-		printk("%s() FE_SET_PROPERTY\n", __FUNCTION__);
-
 		tvps = (struct dtv_properties __user *)parg;
 
-		printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
-		printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
+		dprintk("%s() properties.num = %d\n", __func__, tvps->num);
+		dprintk("%s() properties.props = %p\n", __func__, tvps->props);
 
 		/* Put an arbitrary limit on the number of messages that can
 		 * be sent at once */
@@ -1364,18 +1356,16 @@
 			err |= (tvp + i)->result;
 		}
 
-		if(fe->dtv_property_cache.state == DTV_TUNE) {
-			printk("%s() Property cache is full, tuning\n", __FUNCTION__);
-		}
+		if(fe->dtv_property_cache.state == DTV_TUNE)
+			dprintk("%s() Property cache is full, tuning\n", __func__);
 
 	} else
 	if(cmd == FE_GET_PROPERTY) {
-		printk("%s() FE_GET_PROPERTY\n", __FUNCTION__);
 
 		tvps = (struct dtv_properties __user *)parg;
 
-		printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
-		printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
+		dprintk("%s() properties.num = %d\n", __func__, tvps->num);
+		dprintk("%s() properties.props = %p\n", __func__, tvps->props);
 
 		/* Put an arbitrary limit on the number of messages that can
 		 * be sent at once */
@@ -1704,13 +1694,53 @@
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend *fe = dvbdev->priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_adapter *adapter = fe->dvb;
 	int ret;
 
 	dprintk ("%s\n", __func__);
 
+	if (adapter->mfe_shared) {
+		mutex_lock (&adapter->mfe_lock);
+
+		if (adapter->mfe_dvbdev == NULL)
+			adapter->mfe_dvbdev = dvbdev;
+
+		else if (adapter->mfe_dvbdev != dvbdev) {
+			struct dvb_device
+				*mfedev = adapter->mfe_dvbdev;
+			struct dvb_frontend
+				*mfe = mfedev->priv;
+			struct dvb_frontend_private
+				*mfepriv = mfe->frontend_priv;
+			int mferetry = (dvb_mfe_wait_time << 1);
+
+			mutex_unlock (&adapter->mfe_lock);
+			while (mferetry-- && (mfedev->users != -1 ||
+					mfepriv->thread != NULL)) {
+				if(msleep_interruptible(500)) {
+					if(signal_pending(current))
+						return -EINTR;
+				}
+			}
+
+			mutex_lock (&adapter->mfe_lock);
+			if(adapter->mfe_dvbdev != dvbdev) {
+				mfedev = adapter->mfe_dvbdev;
+				mfe = mfedev->priv;
+				mfepriv = mfe->frontend_priv;
+				if (mfedev->users != -1 ||
+						mfepriv->thread != NULL) {
+					mutex_unlock (&adapter->mfe_lock);
+					return -EBUSY;
+				}
+				adapter->mfe_dvbdev = dvbdev;
+			}
+		}
+	}
+
 	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
 		if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
-			return ret;
+			goto err0;
 	}
 
 	if ((ret = dvb_generic_open (inode, file)) < 0)
@@ -1730,6 +1760,8 @@
 		fepriv->events.eventr = fepriv->events.eventw = 0;
 	}
 
+	if (adapter->mfe_shared)
+		mutex_unlock (&adapter->mfe_lock);
 	return ret;
 
 err2:
@@ -1737,6 +1769,9 @@
 err1:
 	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
 		fe->ops.ts_bus_ctrl(fe, 0);
+err0:
+	if (adapter->mfe_shared)
+		mutex_unlock (&adapter->mfe_lock);
 	return ret;
 }
 
@@ -1806,8 +1841,9 @@
 	fe->dvb = dvb;
 	fepriv->inversion = INVERSION_OFF;
 
-	printk ("DVB: registering frontend %i (%s)...\n",
+	printk ("DVB: registering adapter %i frontend %i (%s)...\n",
 		fe->dvb->num,
+		fe->id,
 		fe->ops.info.name);
 
 	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 3055301..db4a63b 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -222,6 +222,7 @@
 	struct dtv_frontend_properties dtv_property_cache;
 #define DVB_FRONTEND_COMPONENT_TUNER 0
 	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
+	int id;
 };
 
 extern int dvb_register_frontend(struct dvb_adapter *dvb,
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 665776d..a113744 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -326,6 +326,9 @@
 	adap->name = name;
 	adap->module = module;
 	adap->device = device;
+	adap->mfe_shared = 0;
+	adap->mfe_dvbdev = NULL;
+	mutex_init (&adap->mfe_lock);
 
 	list_add_tail (&adap->list_head, &dvb_adapter_list);
 
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 89d12dc..574e336 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -62,6 +62,10 @@
 	struct device *device;
 
 	struct module *module;
+
+	int mfe_shared;			/* indicates mutually exclusive frontends */
+	struct dvb_device *mfe_dvbdev;	/* frontend device in use */
+	struct mutex mfe_lock;		/* access lock for thread creation */
 };
 
 
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index ca53df6..6286fbb 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -422,6 +422,18 @@
 	return 0;
 }
 
+static struct stv0299_config sharp_z0194a_config = {
+	.demod_address = 0x68,
+	.inittab = sharp_z0194a_inittab,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.lock_output = STV0299_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
 static struct cx24116_config dw2104_config = {
 	.demod_address = 0x55,
 	.mpg_clk_pos_pol = 0x01,
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 9430e03..5d1abe3 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -34,13 +34,12 @@
 #include "dvb_frontend.h"
 #include "cx22702.h"
 
-
 struct cx22702_state {
 
-	struct i2c_adapter* i2c;
+	struct i2c_adapter *i2c;
 
 	/* configuration settings */
-	const struct cx22702_config* config;
+	const struct cx22702_config *config;
 
 	struct dvb_frontend frontend;
 
@@ -49,10 +48,13 @@
 };
 
 static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
 #define dprintk	if (debug) printk
 
 /* Register values to initialise the demod */
-static u8 init_tab [] = {
+static u8 init_tab[] = {
 	0x00, 0x00, /* Stop aquisition */
 	0x0B, 0x06,
 	0x09, 0x01,
@@ -80,65 +82,67 @@
 	0xfd, 0x00,
 };
 
-static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
+static int cx22702_writereg(struct cx22702_state *state, u8 reg, u8 data)
 {
 	int ret;
-	u8 buf [] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address, .flags = 0,
+			.buf = buf, .len = 2 };
 
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+		printk(KERN_ERR
+			"%s: error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
 			__func__, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
 }
 
-static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
+static u8 cx22702_readreg(struct cx22702_state *state, u8 reg)
 {
 	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
 
-	struct i2c_msg msg [] = {
-		{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0,
+			.buf = b0, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
+			.buf = b1, .len = 1 } };
 
 	ret = i2c_transfer(state->i2c, msg, 2);
 
 	if (ret != 2)
-		printk("%s: readreg error (ret == %i)\n", __func__, ret);
+		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+			__func__, ret);
 
 	return b1[0];
 }
 
-static int cx22702_set_inversion (struct cx22702_state *state, int inversion)
+static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
 {
 	u8 val;
 
 	switch (inversion) {
-
-		case INVERSION_AUTO:
-			return -EOPNOTSUPP;
-
-		case INVERSION_ON:
-			val = cx22702_readreg (state, 0x0C);
-			return cx22702_writereg (state, 0x0C, val | 0x01);
-
-		case INVERSION_OFF:
-			val = cx22702_readreg (state, 0x0C);
-			return cx22702_writereg (state, 0x0C, val & 0xfe);
-
-		default:
-			return -EINVAL;
-
+	case INVERSION_AUTO:
+		return -EOPNOTSUPP;
+	case INVERSION_ON:
+		val = cx22702_readreg(state, 0x0C);
+		return cx22702_writereg(state, 0x0C, val | 0x01);
+	case INVERSION_OFF:
+		val = cx22702_readreg(state, 0x0C);
+		return cx22702_writereg(state, 0x0C, val & 0xfe);
+	default:
+		return -EINVAL;
 	}
 
 }
 
 /* Retrieve the demod settings */
-static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_parameters *p)
+static int cx22702_get_tps(struct cx22702_state *state,
+	struct dvb_ofdm_parameters *p)
 {
 	u8 val;
 
@@ -146,180 +150,281 @@
 	if (!(cx22702_readreg(state, 0x0A) & 0x20))
 		return -EAGAIN;
 
-	val = cx22702_readreg (state, 0x01);
-	switch( (val&0x18)>>3) {
-		case 0: p->constellation =   QPSK; break;
-		case 1: p->constellation = QAM_16; break;
-		case 2: p->constellation = QAM_64; break;
+	val = cx22702_readreg(state, 0x01);
+	switch ((val & 0x18) >> 3) {
+	case 0:
+		p->constellation = QPSK;
+		break;
+	case 1:
+		p->constellation = QAM_16;
+		break;
+	case 2:
+		p->constellation = QAM_64;
+		break;
 	}
-	switch( val&0x07 ) {
-		case 0: p->hierarchy_information = HIERARCHY_NONE; break;
-		case 1: p->hierarchy_information =    HIERARCHY_1; break;
-		case 2: p->hierarchy_information =    HIERARCHY_2; break;
-		case 3: p->hierarchy_information =    HIERARCHY_4; break;
+	switch (val & 0x07) {
+	case 0:
+		p->hierarchy_information = HIERARCHY_NONE;
+		break;
+	case 1:
+		p->hierarchy_information = HIERARCHY_1;
+		break;
+	case 2:
+		p->hierarchy_information = HIERARCHY_2;
+		break;
+	case 3:
+		p->hierarchy_information = HIERARCHY_4;
+		break;
 	}
 
 
-	val = cx22702_readreg (state, 0x02);
-	switch( (val&0x38)>>3 ) {
-		case 0: p->code_rate_HP = FEC_1_2; break;
-		case 1: p->code_rate_HP = FEC_2_3; break;
-		case 2: p->code_rate_HP = FEC_3_4; break;
-		case 3: p->code_rate_HP = FEC_5_6; break;
-		case 4: p->code_rate_HP = FEC_7_8; break;
+	val = cx22702_readreg(state, 0x02);
+	switch ((val & 0x38) >> 3) {
+	case 0:
+		p->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_HP = FEC_7_8;
+		break;
 	}
-	switch( val&0x07 ) {
-		case 0: p->code_rate_LP = FEC_1_2; break;
-		case 1: p->code_rate_LP = FEC_2_3; break;
-		case 2: p->code_rate_LP = FEC_3_4; break;
-		case 3: p->code_rate_LP = FEC_5_6; break;
-		case 4: p->code_rate_LP = FEC_7_8; break;
+	switch (val & 0x07) {
+	case 0:
+		p->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_LP = FEC_7_8;
+		break;
 	}
 
-
-	val = cx22702_readreg (state, 0x03);
-	switch( (val&0x0c)>>2 ) {
-		case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
-		case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
-		case 2: p->guard_interval =  GUARD_INTERVAL_1_8; break;
-		case 3: p->guard_interval =  GUARD_INTERVAL_1_4; break;
+	val = cx22702_readreg(state, 0x03);
+	switch ((val & 0x0c) >> 2) {
+	case 0:
+		p->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		p->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		p->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		p->guard_interval = GUARD_INTERVAL_1_4;
+		break;
 	}
-	switch( val&0x03 ) {
-		case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
-		case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+	switch (val & 0x03) {
+	case 0:
+		p->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		p->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
 	}
 
 	return 0;
 }
 
-static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
-	dprintk ("%s(%d)\n", __func__, enable);
+	struct cx22702_state *state = fe->demodulator_priv;
+	dprintk("%s(%d)\n", __func__, enable);
 	if (enable)
-		return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+		return cx22702_writereg(state, 0x0D,
+			cx22702_readreg(state, 0x0D) & 0xfe);
 	else
-		return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1);
+		return cx22702_writereg(state, 0x0D,
+			cx22702_readreg(state, 0x0D) | 1);
 }
 
 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_set_tps(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
 {
 	u8 val;
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 
 	if (fe->ops.tuner_ops.set_params) {
 		fe->ops.tuner_ops.set_params(fe, p);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
 	}
 
 	/* set inversion */
-	cx22702_set_inversion (state, p->inversion);
+	cx22702_set_inversion(state, p->inversion);
 
 	/* set bandwidth */
-	switch(p->u.ofdm.bandwidth) {
+	switch (p->u.ofdm.bandwidth) {
 	case BANDWIDTH_6_MHZ:
-		cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20 );
+		cx22702_writereg(state, 0x0C,
+			(cx22702_readreg(state, 0x0C) & 0xcf) | 0x20);
 		break;
 	case BANDWIDTH_7_MHZ:
-		cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10 );
+		cx22702_writereg(state, 0x0C,
+			(cx22702_readreg(state, 0x0C) & 0xcf) | 0x10);
 		break;
 	case BANDWIDTH_8_MHZ:
-		cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
+		cx22702_writereg(state, 0x0C,
+			cx22702_readreg(state, 0x0C) & 0xcf);
 		break;
 	default:
-		dprintk ("%s: invalid bandwidth\n",__func__);
+		dprintk("%s: invalid bandwidth\n", __func__);
 		return -EINVAL;
 	}
 
-
-	p->u.ofdm.code_rate_LP = FEC_AUTO; //temp hack as manual not working
+	p->u.ofdm.code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
 
 	/* use auto configuration? */
-	if((p->u.ofdm.hierarchy_information==HIERARCHY_AUTO) ||
-	   (p->u.ofdm.constellation==QAM_AUTO) ||
-	   (p->u.ofdm.code_rate_HP==FEC_AUTO) ||
-	   (p->u.ofdm.code_rate_LP==FEC_AUTO) ||
-	   (p->u.ofdm.guard_interval==GUARD_INTERVAL_AUTO) ||
-	   (p->u.ofdm.transmission_mode==TRANSMISSION_MODE_AUTO) ) {
+	if ((p->u.ofdm.hierarchy_information == HIERARCHY_AUTO) ||
+	   (p->u.ofdm.constellation == QAM_AUTO) ||
+	   (p->u.ofdm.code_rate_HP == FEC_AUTO) ||
+	   (p->u.ofdm.code_rate_LP == FEC_AUTO) ||
+	   (p->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO) ||
+	   (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO)) {
 
 		/* TPS Source - use hardware driven values */
 		cx22702_writereg(state, 0x06, 0x10);
 		cx22702_writereg(state, 0x07, 0x9);
 		cx22702_writereg(state, 0x08, 0xC1);
-		cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
-		cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+		cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B)
+			& 0xfc);
+		cx22702_writereg(state, 0x0C,
+			(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
 		cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
-		dprintk("%s: Autodetecting\n",__func__);
+		dprintk("%s: Autodetecting\n", __func__);
 		return 0;
 	}
 
 	/* manually programmed values */
-	val=0;
-	switch(p->u.ofdm.constellation) {
-		case   QPSK: val = (val&0xe7); break;
-		case QAM_16: val = (val&0xe7)|0x08; break;
-		case QAM_64: val = (val&0xe7)|0x10; break;
-		default:
-			dprintk ("%s: invalid constellation\n",__func__);
-			return -EINVAL;
+	val = 0;
+	switch (p->u.ofdm.constellation) {
+	case QPSK:
+		val = (val & 0xe7);
+		break;
+	case QAM_16:
+		val = (val & 0xe7) | 0x08;
+		break;
+	case QAM_64:
+		val = (val & 0xe7) | 0x10;
+		break;
+	default:
+		dprintk("%s: invalid constellation\n", __func__);
+		return -EINVAL;
 	}
-	switch(p->u.ofdm.hierarchy_information) {
-		case HIERARCHY_NONE: val = (val&0xf8); break;
-		case    HIERARCHY_1: val = (val&0xf8)|1; break;
-		case    HIERARCHY_2: val = (val&0xf8)|2; break;
-		case    HIERARCHY_4: val = (val&0xf8)|3; break;
-		default:
-			dprintk ("%s: invalid hierarchy\n",__func__);
-			return -EINVAL;
+	switch (p->u.ofdm.hierarchy_information) {
+	case HIERARCHY_NONE:
+		val = (val & 0xf8);
+		break;
+	case HIERARCHY_1:
+		val = (val & 0xf8) | 1;
+		break;
+	case HIERARCHY_2:
+		val = (val & 0xf8) | 2;
+		break;
+	case HIERARCHY_4:
+		val = (val & 0xf8) | 3;
+		break;
+	default:
+		dprintk("%s: invalid hierarchy\n", __func__);
+		return -EINVAL;
 	}
-	cx22702_writereg (state, 0x06, val);
+	cx22702_writereg(state, 0x06, val);
 
-	val=0;
-	switch(p->u.ofdm.code_rate_HP) {
-		case FEC_NONE:
-		case FEC_1_2: val = (val&0xc7); break;
-		case FEC_2_3: val = (val&0xc7)|0x08; break;
-		case FEC_3_4: val = (val&0xc7)|0x10; break;
-		case FEC_5_6: val = (val&0xc7)|0x18; break;
-		case FEC_7_8: val = (val&0xc7)|0x20; break;
-		default:
-			dprintk ("%s: invalid code_rate_HP\n",__func__);
-			return -EINVAL;
+	val = 0;
+	switch (p->u.ofdm.code_rate_HP) {
+	case FEC_NONE:
+	case FEC_1_2:
+		val = (val & 0xc7);
+		break;
+	case FEC_2_3:
+		val = (val & 0xc7) | 0x08;
+		break;
+	case FEC_3_4:
+		val = (val & 0xc7) | 0x10;
+		break;
+	case FEC_5_6:
+		val = (val & 0xc7) | 0x18;
+		break;
+	case FEC_7_8:
+		val = (val & 0xc7) | 0x20;
+		break;
+	default:
+		dprintk("%s: invalid code_rate_HP\n", __func__);
+		return -EINVAL;
 	}
-	switch(p->u.ofdm.code_rate_LP) {
-		case FEC_NONE:
-		case FEC_1_2: val = (val&0xf8); break;
-		case FEC_2_3: val = (val&0xf8)|1; break;
-		case FEC_3_4: val = (val&0xf8)|2; break;
-		case FEC_5_6: val = (val&0xf8)|3; break;
-		case FEC_7_8: val = (val&0xf8)|4; break;
-		default:
-			dprintk ("%s: invalid code_rate_LP\n",__func__);
-			return -EINVAL;
+	switch (p->u.ofdm.code_rate_LP) {
+	case FEC_NONE:
+	case FEC_1_2:
+		val = (val & 0xf8);
+		break;
+	case FEC_2_3:
+		val = (val & 0xf8) | 1;
+		break;
+	case FEC_3_4:
+		val = (val & 0xf8) | 2;
+		break;
+	case FEC_5_6:
+		val = (val & 0xf8) | 3;
+		break;
+	case FEC_7_8:
+		val = (val & 0xf8) | 4;
+		break;
+	default:
+		dprintk("%s: invalid code_rate_LP\n", __func__);
+		return -EINVAL;
 	}
-	cx22702_writereg (state, 0x07, val);
+	cx22702_writereg(state, 0x07, val);
 
-	val=0;
-	switch(p->u.ofdm.guard_interval) {
-		case GUARD_INTERVAL_1_32: val = (val&0xf3); break;
-		case GUARD_INTERVAL_1_16: val = (val&0xf3)|0x04; break;
-		case  GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
-		case  GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
-		default:
-			dprintk ("%s: invalid guard_interval\n",__func__);
-			return -EINVAL;
+	val = 0;
+	switch (p->u.ofdm.guard_interval) {
+	case GUARD_INTERVAL_1_32:
+		val = (val & 0xf3);
+		break;
+	case GUARD_INTERVAL_1_16:
+		val = (val & 0xf3) | 0x04;
+		break;
+	case GUARD_INTERVAL_1_8:
+		val = (val & 0xf3) | 0x08;
+		break;
+	case GUARD_INTERVAL_1_4:
+		val = (val & 0xf3) | 0x0c;
+		break;
+	default:
+		dprintk("%s: invalid guard_interval\n", __func__);
+		return -EINVAL;
 	}
-	switch(p->u.ofdm.transmission_mode) {
-		case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
-		case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
-		default:
-			dprintk ("%s: invalid transmission_mode\n",__func__);
-			return -EINVAL;
+	switch (p->u.ofdm.transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		val = (val & 0xfc);
+		break;
+	case TRANSMISSION_MODE_8K:
+		val = (val & 0xfc) | 1;
+		break;
+	default:
+		dprintk("%s: invalid transmission_mode\n", __func__);
+		return -EINVAL;
 	}
 	cx22702_writereg(state, 0x08, val);
-	cx22702_writereg(state, 0x0B, (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02 );
-	cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+	cx22702_writereg(state, 0x0B,
+		(cx22702_readreg(state, 0x0B) & 0xfc) | 0x02);
+	cx22702_writereg(state, 0x0C,
+		(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
 
 	/* Begin channel aquisition */
 	cx22702_writereg(state, 0x00, 0x01);
@@ -329,109 +434,111 @@
 
 /* Reset the demod hardware and reset all of the configuration registers
    to a default state. */
-static int cx22702_init (struct dvb_frontend* fe)
+static int cx22702_init(struct dvb_frontend *fe)
 {
 	int i;
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 
-	cx22702_writereg (state, 0x00, 0x02);
+	cx22702_writereg(state, 0x00, 0x02);
 
 	msleep(10);
 
-	for (i=0; i<sizeof(init_tab); i+=2)
-		cx22702_writereg (state, init_tab[i], init_tab[i+1]);
+	for (i = 0; i < ARRAY_SIZE(init_tab); i += 2)
+		cx22702_writereg(state, init_tab[i], init_tab[i + 1]);
 
-	cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
+	cx22702_writereg(state, 0xf8, (state->config->output_mode << 1)
+		& 0x02);
 
 	cx22702_i2c_gate_ctrl(fe, 0);
 
 	return 0;
 }
 
-static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx22702_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 	u8 reg0A;
 	u8 reg23;
 
 	*status = 0;
 
-	reg0A = cx22702_readreg (state, 0x0A);
-	reg23 = cx22702_readreg (state, 0x23);
+	reg0A = cx22702_readreg(state, 0x0A);
+	reg23 = cx22702_readreg(state, 0x23);
 
-	dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
-		,__func__,reg0A,reg23);
+	dprintk("%s: status demod=0x%02x agc=0x%02x\n"
+		, __func__, reg0A, reg23);
 
-	if(reg0A & 0x10) {
+	if (reg0A & 0x10) {
 		*status |= FE_HAS_LOCK;
 		*status |= FE_HAS_VITERBI;
 		*status |= FE_HAS_SYNC;
 	}
 
-	if(reg0A & 0x20)
+	if (reg0A & 0x20)
 		*status |= FE_HAS_CARRIER;
 
-	if(reg23 < 0xf0)
+	if (reg23 < 0xf0)
 		*status |= FE_HAS_SIGNAL;
 
 	return 0;
 }
 
-static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
+static int cx22702_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 
-	if(cx22702_readreg (state, 0xE4) & 0x02) {
+	if (cx22702_readreg(state, 0xE4) & 0x02) {
 		/* Realtime statistics */
-		*ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
-			| (cx22702_readreg (state, 0xDF)&0x7F);
+		*ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+			| (cx22702_readreg(state, 0xDF) & 0x7F);
 	} else {
 		/* Averagtine statistics */
-		*ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
-			| cx22702_readreg (state, 0xDF);
+		*ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+			| cx22702_readreg(state, 0xDF);
 	}
 
 	return 0;
 }
 
-static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx22702_read_signal_strength(struct dvb_frontend *fe,
+	u16 *signal_strength)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 
 	u16 rs_ber = 0;
-	rs_ber = cx22702_readreg (state, 0x23);
+	rs_ber = cx22702_readreg(state, 0x23);
 	*signal_strength = (rs_ber << 8) | rs_ber;
 
 	return 0;
 }
 
-static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr)
+static int cx22702_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 
-	u16 rs_ber=0;
-	if(cx22702_readreg (state, 0xE4) & 0x02) {
+	u16 rs_ber = 0;
+	if (cx22702_readreg(state, 0xE4) & 0x02) {
 		/* Realtime statistics */
-		rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
-			| (cx22702_readreg (state, 0xDF)& 0x7F);
+		rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+			| (cx22702_readreg(state, 0xDF) & 0x7F);
 	} else {
 		/* Averagine statistics */
-		rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 8
-			| cx22702_readreg (state, 0xDF);
+		rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 8
+			| cx22702_readreg(state, 0xDF);
 	}
 	*snr = ~rs_ber;
 
 	return 0;
 }
 
-static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 
 	u8 _ucblocks;
 
 	/* RS Uncorrectable Packet Count then reset */
-	_ucblocks = cx22702_readreg (state, 0xE3);
+	_ucblocks = cx22702_readreg(state, 0xE3);
 	if (state->prevUCBlocks < _ucblocks)
 		*ucblocks = (_ucblocks - state->prevUCBlocks);
 	else
@@ -441,34 +548,36 @@
 	return 0;
 }
 
-static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_get_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 
-	u8 reg0C = cx22702_readreg (state, 0x0C);
+	u8 reg0C = cx22702_readreg(state, 0x0C);
 
 	p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
-	return cx22702_get_tps (state, &p->u.ofdm);
+	return cx22702_get_tps(state, &p->u.ofdm);
 }
 
-static int cx22702_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+static int cx22702_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *tune)
 {
 	tune->min_delay_ms = 1000;
 	return 0;
 }
 
-static void cx22702_release(struct dvb_frontend* fe)
+static void cx22702_release(struct dvb_frontend *fe)
 {
-	struct cx22702_state* state = fe->demodulator_priv;
+	struct cx22702_state *state = fe->demodulator_priv;
 	kfree(state);
 }
 
 static struct dvb_frontend_ops cx22702_ops;
 
-struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
-				    struct i2c_adapter* i2c)
+struct dvb_frontend *cx22702_attach(const struct cx22702_config *config,
+	struct i2c_adapter *i2c)
 {
-	struct cx22702_state* state = NULL;
+	struct cx22702_state *state = NULL;
 
 	/* allocate memory for the internal state */
 	state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
@@ -485,7 +594,8 @@
 		goto error;
 
 	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
+	memcpy(&state->frontend.ops, &cx22702_ops,
+		sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -493,6 +603,7 @@
 	kfree(state);
 	return NULL;
 }
+EXPORT_SYMBOL(cx22702_attach);
 
 static struct dvb_frontend_ops cx22702_ops = {
 
@@ -525,11 +636,6 @@
 	.read_ucblocks = cx22702_read_ucblocks,
 };
 
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
 MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(cx22702_attach);
diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
index b1e465c..f154e1f 100644
--- a/drivers/media/dvb/frontends/cx22702.h
+++ b/drivers/media/dvb/frontends/cx22702.h
@@ -30,8 +30,7 @@
 
 #include <linux/dvb/frontend.h>
 
-struct cx22702_config
-{
+struct cx22702_config {
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
@@ -41,16 +40,19 @@
 	u8 output_mode;
 };
 
-#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) && defined(MODULE))
-extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
-					   struct i2c_adapter* i2c);
+#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *cx22702_attach(
+	const struct cx22702_config *config,
+	struct i2c_adapter *i2c);
 #else
-static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
-					   struct i2c_adapter* i2c)
+static inline struct dvb_frontend *cx22702_attach(
+	const struct cx22702_config *config,
+	struct i2c_adapter *i2c)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-#endif // CONFIG_DVB_CX22702
+#endif
 
-#endif // CX22702_H
+#endif
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
index deb36f4..b144b30 100644
--- a/drivers/media/dvb/frontends/cx24116.c
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -41,10 +41,14 @@
 #include "dvb_frontend.h"
 #include "cx24116.h"
 
-static int debug = 0;
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
 #define dprintk(args...) \
 	do { \
-		if (debug) printk ("cx24116: " args); \
+		if (debug) \
+			printk(KERN_INFO "cx24116: " args); \
 	} while (0)
 
 #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
@@ -68,13 +72,20 @@
 #define CX24116_REG_UCB8    (0xca)
 #define CX24116_REG_CLKDIV  (0xf3)
 #define CX24116_REG_RATEDIV (0xf9)
-#define CX24116_REG_FECSTATUS (0x9c)    /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
+
+/* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
+#define CX24116_REG_FECSTATUS (0x9c)
 
 /* FECSTATUS bits */
-#define CX24116_FEC_FECMASK   (0x1f)    /* mask to determine configured fec (not tuned) or actual fec (tuned) */
-#define CX24116_FEC_DVBS      (0x20)    /* Select DVB-S demodulator, else DVB-S2 */
+/* mask to determine configured fec (not tuned) or actual fec (tuned) */
+#define CX24116_FEC_FECMASK   (0x1f)
+
+/* Select DVB-S demodulator, else DVB-S2 */
+#define CX24116_FEC_DVBS      (0x20)
 #define CX24116_FEC_UNKNOWN   (0x40)    /* Unknown/unused */
-#define CX24116_FEC_PILOT     (0x80)    /* Pilot mode requested when tuning else always reset when tuned */
+
+/* Pilot mode requested when tuning else always reset when tuned */
+#define CX24116_FEC_PILOT     (0x80)
 
 /* arg buffer size */
 #define CX24116_ARGLEN (0x1e)
@@ -116,12 +127,17 @@
 
 /* DiSEqC tone burst */
 static int toneburst = 1;
+module_param(toneburst, int, 0644);
+MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
+	"2=MESSAGE CACHE (default:1)");
 
 /* SNR measurements */
-static int esno_snr = 0;
+static int esno_snr;
+module_param(esno_snr, int, 0644);
+MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\
+	"1=ESNO(db * 10) (default:0)");
 
-enum cmds
-{
+enum cmds {
 	CMD_SET_VCO     = 0x10,
 	CMD_TUNEREQUEST = 0x11,
 	CMD_MPEGCONFIG  = 0x13,
@@ -138,8 +154,7 @@
 };
 
 /* The Demod/Tuner can't easily provide these, we cache them */
-struct cx24116_tuning
-{
+struct cx24116_tuning {
 	u32 frequency;
 	u32 symbol_rate;
 	fe_spectral_inversion_t inversion;
@@ -158,16 +173,14 @@
 };
 
 /* Basic commands that are sent to the firmware */
-struct cx24116_cmd
-{
+struct cx24116_cmd {
 	u8 len;
 	u8 args[CX24116_ARGLEN];
 };
 
-struct cx24116_state
-{
-	struct i2c_adapter* i2c;
-	const struct cx24116_config* config;
+struct cx24116_state {
+	struct i2c_adapter *i2c;
+	const struct cx24116_config *config;
 
 	struct dvb_frontend frontend;
 
@@ -179,19 +192,20 @@
 	struct cx24116_cmd dsec_cmd;
 };
 
-static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
+static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
 {
 	u8 buf[] = { reg, data };
 	struct i2c_msg msg = { .addr = state->config->demod_address,
 		.flags = 0, .buf = buf, .len = 2 };
 	int err;
 
-	if (debug>1)
+	if (debug > 1)
 		printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
-						__func__,reg, data);
+			__func__, reg, data);
 
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		printk("%s: writereg error(err == %i, reg == 0x%02x,"
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
 			 " value == 0x%02x)\n", __func__, err, reg, data);
 		return -EREMOTEIO;
 	}
@@ -200,7 +214,8 @@
 }
 
 /* Bulk byte writes to a single I2C address, for 32k firmware load */
-static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len)
+static int cx24116_writeregN(struct cx24116_state *state, int reg,
+			     const u8 *data, u16 len)
 {
 	int ret = -EREMOTEIO;
 	struct i2c_msg msg;
@@ -221,12 +236,13 @@
 	msg.buf = buf;
 	msg.len = len + 1;
 
-	if (debug>1)
-		printk("cx24116: %s:  write regN 0x%02x, len = %d\n",
-						__func__,reg, len);
+	if (debug > 1)
+		printk(KERN_INFO "cx24116: %s:  write regN 0x%02x, len = %d\n",
+			__func__, reg, len);
 
-	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		printk("%s: writereg error(err == %i, reg == 0x%02x\n",
+	ret = i2c_transfer(state->i2c, &msg, 1);
+	if (ret != 1) {
+		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
 			 __func__, ret, reg);
 		ret = -EREMOTEIO;
 	}
@@ -237,30 +253,35 @@
 	return ret;
 }
 
-static int cx24116_readreg(struct cx24116_state* state, u8 reg)
+static int cx24116_readreg(struct cx24116_state *state, u8 reg)
 {
 	int ret;
 	u8 b0[] = { reg };
 	u8 b1[] = { 0 };
 	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+		{ .addr = state->config->demod_address, .flags = 0,
+			.buf = b0, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
+			.buf = b1, .len = 1 }
 	};
 
 	ret = i2c_transfer(state->i2c, msg, 2);
 
 	if (ret != 2) {
-		printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
+		printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
+			__func__, reg, ret);
 		return ret;
 	}
 
-	if (debug>1)
-		printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]);
+	if (debug > 1)
+		printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
+			reg, b1[0]);
 
 	return b1[0];
 }
 
-static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion)
+static int cx24116_set_inversion(struct cx24116_state *state,
+	fe_spectral_inversion_t inversion)
 {
 	dprintk("%s(%d)\n", __func__, inversion);
 
@@ -308,10 +329,10 @@
  * Eg.(2/3) szap "Zone Horror"
  *
  * mask/val = 0x04, 0x20
- * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK
+ * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 0 | FE_HAS_LOCK
  *
  * mask/val = 0x04, 0x30
- * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+ * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 0 | FE_HAS_LOCK
  *
  * After tuning FECSTATUS contains actual FEC
  * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
@@ -389,18 +410,16 @@
   */
 };
 
-static int cx24116_lookup_fecmod(struct cx24116_state* state,
+static int cx24116_lookup_fecmod(struct cx24116_state *state,
 	fe_modulation_t m, fe_code_rate_t f)
 {
 	int i, ret = -EOPNOTSUPP;
 
 	dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
 
-	for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
-	{
-		if( (m == CX24116_MODFEC_MODES[i].modulation) &&
-			(f == CX24116_MODFEC_MODES[i].fec) )
-			{
+	for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
+		if ((m == CX24116_MODFEC_MODES[i].modulation) &&
+			(f == CX24116_MODFEC_MODES[i].fec)) {
 				ret = i;
 				break;
 			}
@@ -409,7 +428,8 @@
 	return ret;
 }
 
-static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
+static int cx24116_set_fec(struct cx24116_state *state,
+	fe_modulation_t mod, fe_code_rate_t fec)
 {
 	int ret = 0;
 
@@ -417,7 +437,7 @@
 
 	ret = cx24116_lookup_fecmod(state, mod, fec);
 
-	if(ret < 0)
+	if (ret < 0)
 		return ret;
 
 	state->dnxt.fec = fec;
@@ -429,7 +449,7 @@
 	return 0;
 }
 
-static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
+static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
 {
 	dprintk("%s(%d)\n", __func__, rate);
 
@@ -446,42 +466,49 @@
 	return 0;
 }
 
-static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+	const struct firmware *fw);
 
-static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
+static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	const struct firmware *fw;
 	int ret = 0;
 
-	dprintk("%s()\n",__func__);
+	dprintk("%s()\n", __func__);
 
-	if (cx24116_readreg(state, 0x20) > 0)
-	{
+	if (cx24116_readreg(state, 0x20) > 0) {
 
 		if (state->skip_fw_load)
 			return 0;
 
 		/* Load firmware */
-		/* request the firmware, this will block until someone uploads it */
-		printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE);
-		ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev);
-		printk("%s: Waiting for firmware upload(2)...\n", __func__);
+		/* request the firmware, this will block until loaded */
+		printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
+			__func__, CX24116_DEFAULT_FIRMWARE);
+		ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
+			&state->i2c->dev);
+		printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
+			__func__);
 		if (ret) {
-			printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__);
+			printk(KERN_ERR "%s: No firmware uploaded "
+				"(timeout or file not found?)\n", __func__);
 			return ret;
 		}
 
-		/* Make sure we don't recurse back through here during loading */
+		/* Make sure we don't recurse back through here
+		 * during loading */
 		state->skip_fw_load = 1;
 
 		ret = cx24116_load_firmware(fe, fw);
 		if (ret)
-			printk("%s: Writing firmware to device failed\n", __func__);
+			printk(KERN_ERR "%s: Writing firmware to device failed\n",
+				__func__);
 
 		release_firmware(fw);
 
-		printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed");
+		printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
+			ret == 0 ? "complete" : "failed");
 
 		/* Ensure firmware is always loaded if required */
 		state->skip_fw_load = 0;
@@ -490,8 +517,10 @@
 	return ret;
 }
 
-/* Take a basic firmware command structure, format it and forward it for processing */
-static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
+/* Take a basic firmware command structure, format it
+ * and forward it for processing
+ */
+static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	int i, ret;
@@ -499,49 +528,49 @@
 	dprintk("%s()\n", __func__);
 
 	/* Load the firmware if required */
-	if ( (ret = cx24116_firmware_ondemand(fe)) != 0)
-	{
-		printk("%s(): Unable initialise the firmware\n", __func__);
+	ret = cx24116_firmware_ondemand(fe);
+	if (ret != 0) {
+		printk(KERN_ERR "%s(): Unable initialise the firmware\n",
+			__func__);
 		return ret;
 	}
 
 	/* Write the command */
-	for(i = 0; i < cmd->len ; i++)
-	{
+	for (i = 0; i < cmd->len ; i++) {
 		dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
 		cx24116_writereg(state, i, cmd->args[i]);
 	}
 
 	/* Start execution and wait for cmd to terminate */
 	cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
-	while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
-	{
+	while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
 		msleep(10);
-		if(i++ > 64)
-		{
-			/* Avoid looping forever if the firmware does no respond */
-			printk("%s() Firmware not responding\n", __func__);
+		if (i++ > 64) {
+			/* Avoid looping forever if the firmware does
+				not respond */
+			printk(KERN_WARNING "%s() Firmware not responding\n",
+				__func__);
 			return -EREMOTEIO;
 		}
 	}
 	return 0;
 }
 
-static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+	const struct firmware *fw)
 {
-	struct cx24116_state* state = fe->demodulator_priv;
+	struct cx24116_state *state = fe->demodulator_priv;
 	struct cx24116_cmd cmd;
 	int i, ret;
 	unsigned char vers[4];
 
 	dprintk("%s\n", __func__);
-	dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
-			,fw->size
-			,fw->data[0]
-			,fw->data[1]
-			,fw->data[ fw->size-2 ]
-			,fw->data[ fw->size-1 ]
-			);
+	dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
+			fw->size,
+			fw->data[0],
+			fw->data[1],
+			fw->data[fw->size-2],
+			fw->data[fw->size-1]);
 
 	/* Toggle 88x SRST pin to reset demod */
 	if (state->config->reset_device)
@@ -587,7 +616,7 @@
 	cmd.args[0x07] = 0x9d;
 	cmd.args[0x08] = 0xfc;
 	cmd.args[0x09] = 0x06;
-	cmd.len= 0x0a;
+	cmd.len = 0x0a;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
@@ -598,7 +627,7 @@
 	cmd.args[0x00] = CMD_TUNERINIT;
 	cmd.args[0x01] = 0x00;
 	cmd.args[0x02] = 0x00;
-	cmd.len= 0x03;
+	cmd.len = 0x03;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
@@ -615,36 +644,38 @@
 	else
 		cmd.args[0x04] = 0x02;
 	cmd.args[0x05] = 0x00;
-	cmd.len= 0x06;
+	cmd.len = 0x06;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
 
 	/* Firmware CMD 35: Get firmware version */
 	cmd.args[0x00] = CMD_UPDFWVERS;
-	cmd.len= 0x02;
-	for(i=0; i<4; i++) {
+	cmd.len = 0x02;
+	for (i = 0; i < 4; i++) {
 		cmd.args[0x01] = i;
 		ret = cx24116_cmd_execute(fe, &cmd);
 		if (ret != 0)
 			return ret;
-		vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
+		vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
 	}
-	printk("%s: FW version %i.%i.%i.%i\n", __func__,
+	printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
 		vers[0], vers[1], vers[2], vers[3]);
 
 	return 0;
 }
 
-static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int cx24116_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t voltage)
 {
 	/* The isl6421 module will override this function in the fops. */
-	dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__);
+	dprintk("%s() This should never appear if the isl6421 module "
+		"is loaded correctly\n", __func__);
 
 	return -EOPNOTSUPP;
 }
 
-static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 
@@ -666,22 +697,23 @@
 	return 0;
 }
 
-static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
+static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 
 	dprintk("%s()\n", __func__);
 
-	*ber =  ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
-		( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
-		( cx24116_readreg(state, CX24116_REG_BER8 ) << 8  ) |
-		  cx24116_readreg(state, CX24116_REG_BER0 );
+	*ber =  (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
+		(cx24116_readreg(state, CX24116_REG_BER16) << 16) |
+		(cx24116_readreg(state, CX24116_REG_BER8)  << 8)  |
+		 cx24116_readreg(state, CX24116_REG_BER0);
 
 	return 0;
 }
 
 /* TODO Determine function and scale appropriately */
-static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx24116_read_signal_strength(struct dvb_frontend *fe,
+	u16 *signal_strength)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	struct cx24116_cmd cmd;
@@ -692,39 +724,43 @@
 
 	/* Firmware CMD 19: Get AGC */
 	cmd.args[0x00] = CMD_GETAGC;
-	cmd.len= 0x01;
+	cmd.len = 0x01;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
 
-	sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
-		( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
-	*signal_strength= 0 - sig_reading;
+	sig_reading =
+		(cx24116_readreg(state,
+			CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
+		(cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
+	*signal_strength = 0 - sig_reading;
 
-	dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
+	dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
+		__func__, sig_reading, *signal_strength);
 
 	return 0;
 }
 
 /* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
-static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr)
+static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	u8 snr_reading;
 	static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
-		0x00000,0x0199A,0x03333,0x04ccD,0x06667,
-			0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
-		0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
+		0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
+		0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
+		0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
+		0x18000 };
 
 	dprintk("%s()\n", __func__);
 
 	snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
 
-	if(snr_reading >= 0xa0 /* 100% */)
+	if (snr_reading >= 0xa0 /* 100% */)
 		*snr = 0xffff;
 	else
-		*snr = snr_tab [ ( snr_reading & 0xf0 )   >> 4 ] +
-			( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
+		*snr = snr_tab[(snr_reading & 0xf0) >> 4] +
+			(snr_tab[(snr_reading & 0x0f)] >> 4);
 
 	dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
 		snr_reading, *snr);
@@ -736,7 +772,7 @@
  * ESNO, from 0->30db (values 0->300). We provide this value by
  * default.
  */
-static int cx24116_read_snr_esno(struct dvb_frontend* fe, u16* snr)
+static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 
@@ -750,7 +786,7 @@
 	return 0;
 }
 
-static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
+static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
 	if (esno_snr == 1)
 		return cx24116_read_snr_esno(fe, snr);
@@ -758,27 +794,27 @@
 		return cx24116_read_snr_pct(fe, snr);
 }
 
-static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 
 	dprintk("%s()\n", __func__);
 
-	*ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
+	*ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
 		cx24116_readreg(state, CX24116_REG_UCB0);
 
 	return 0;
 }
 
 /* Overwrite the current tuning params, we are about to tune */
-static void cx24116_clone_params(struct dvb_frontend* fe)
+static void cx24116_clone_params(struct dvb_frontend *fe)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
 }
 
 /* Wait for LNB */
-static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
+static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	int i;
@@ -787,7 +823,7 @@
 		cx24116_readreg(state, CX24116_REG_QSTATUS));
 
 	/* Wait for up to 300 ms */
-	for(i = 0; i < 30 ; i++) {
+	for (i = 0; i < 30 ; i++) {
 		if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
 			return 0;
 		msleep(10);
@@ -798,20 +834,21 @@
 	return -ETIMEDOUT; /* -EBUSY ? */
 }
 
-static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int cx24116_set_tone(struct dvb_frontend *fe,
+	fe_sec_tone_mode_t tone)
 {
 	struct cx24116_cmd cmd;
 	int ret;
 
 	dprintk("%s(%d)\n", __func__, tone);
-	if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) {
-		printk("%s: Invalid, tone=%d\n", __func__, tone);
+	if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
+		printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
 		return -EINVAL;
 	}
 
 	/* Wait for LNB ready */
 	ret = cx24116_wait_for_lnb(fe);
-	if(ret != 0)
+	if (ret != 0)
 		return ret;
 
 	/* Min delay time after DiSEqC send */
@@ -820,7 +857,7 @@
 	/* This is always done before the tone is set */
 	cmd.args[0x00] = CMD_SET_TONEPRE;
 	cmd.args[0x01] = 0x00;
-	cmd.len= 0x02;
+	cmd.len = 0x02;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
@@ -836,11 +873,11 @@
 		cmd.args[0x03] = 0x01;
 		break;
 	case SEC_TONE_OFF:
-		dprintk("%s: setting tone off\n",__func__);
+		dprintk("%s: setting tone off\n", __func__);
 		cmd.args[0x03] = 0x00;
 		break;
 	}
-	cmd.len= 0x04;
+	cmd.len = 0x04;
 
 	/* Min delay time before DiSEqC send */
 	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
@@ -849,7 +886,7 @@
 }
 
 /* Initialise DiSEqC */
-static int cx24116_diseqc_init(struct dvb_frontend* fe)
+static int cx24116_diseqc_init(struct dvb_frontend *fe)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	struct cx24116_cmd cmd;
@@ -864,7 +901,7 @@
 	cmd.args[0x05] = 0x28;
 	cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
 	cmd.args[0x07] = 0x01;
-	cmd.len= 0x08;
+	cmd.len = 0x08;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
@@ -878,36 +915,38 @@
 	/* Unknown */
 	state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
 	state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
-	state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
+	/* Continuation flag? */
+	state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
 
 	/* DiSEqC message length */
 	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
 
 	/* Command length */
-	state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
+	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
 
 	return 0;
 }
 
 /* Send DiSEqC message with derived burst (hack) || previous burst */
-static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
+static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *d)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	int i, ret;
 
 	/* Dump DiSEqC message */
 	if (debug) {
-		printk("cx24116: %s(", __func__);
-		for(i = 0 ; i < d->msg_len ;) {
-			printk("0x%02x", d->msg[i]);
-			if(++i < d->msg_len)
-				printk(", ");
-			}
+		printk(KERN_INFO "cx24116: %s(", __func__);
+		for (i = 0 ; i < d->msg_len ;) {
+			printk(KERN_INFO "0x%02x", d->msg[i]);
+			if (++i < d->msg_len)
+				printk(KERN_INFO ", ");
+		}
 		printk(") toneburst=%d\n", toneburst);
 	}
 
 	/* Validate length */
-	if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
+	if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
 		return -EINVAL;
 
 	/* DiSEqC message */
@@ -918,18 +957,19 @@
 	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
 
 	/* Command length */
-	state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
+	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
+		state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
 
 	/* DiSEqC toneburst */
-	if(toneburst == CX24116_DISEQC_MESGCACHE)
+	if (toneburst == CX24116_DISEQC_MESGCACHE)
 		/* Message is cached */
 		return 0;
 
-	else if(toneburst == CX24116_DISEQC_TONEOFF)
+	else if (toneburst == CX24116_DISEQC_TONEOFF)
 		/* Message is sent without burst */
 		state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
 
-	else if(toneburst == CX24116_DISEQC_TONECACHE) {
+	else if (toneburst == CX24116_DISEQC_TONECACHE) {
 		/*
 		 * Message is sent with derived else cached burst
 		 *
@@ -948,15 +988,17 @@
 		 *              Y = VOLTAGE             (0=13V, 1=18V)
 		 *              Z = BAND                (0=LOW, 1=HIGH(22K))
 		 */
-		if(d->msg_len >= 4 && d->msg[2] == 0x38)
-			state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
-		if(debug)
-			dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
+		if (d->msg_len >= 4 && d->msg[2] == 0x38)
+			state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+				((d->msg[3] & 4) >> 2);
+		if (debug)
+			dprintk("%s burst=%d\n", __func__,
+				state->dsec_cmd.args[CX24116_DISEQC_BURST]);
 	}
 
 	/* Wait for LNB ready */
 	ret = cx24116_wait_for_lnb(fe);
-	if(ret != 0)
+	if (ret != 0)
 		return ret;
 
 	/* Wait for voltage/min repeat delay */
@@ -964,7 +1006,7 @@
 
 	/* Command */
 	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
-	if(ret != 0)
+	if (ret != 0)
 		return ret;
 	/*
 	 * Wait for send
@@ -976,29 +1018,33 @@
 	 *  12.5ms burst        +
 	 * >15ms delay            (XXX determine if FW does this, see set_tone)
 	 */
-	msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
+	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
+		((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
 
 	return 0;
 }
 
 /* Send DiSEqC burst */
-static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t burst)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	int ret;
 
-	dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
+	dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
 
 	/* DiSEqC burst */
 	if (burst == SEC_MINI_A)
-		state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
-	else if(burst == SEC_MINI_B)
-		state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
+		state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+			CX24116_DISEQC_MINI_A;
+	else if (burst == SEC_MINI_B)
+		state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+			CX24116_DISEQC_MINI_B;
 	else
 		return -EINVAL;
 
 	/* DiSEqC toneburst */
-	if(toneburst != CX24116_DISEQC_MESGCACHE)
+	if (toneburst != CX24116_DISEQC_MESGCACHE)
 		/* Burst is cached */
 		return 0;
 
@@ -1006,7 +1052,7 @@
 
 	/* Wait for LNB ready */
 	ret = cx24116_wait_for_lnb(fe);
-	if(ret != 0)
+	if (ret != 0)
 		return ret;
 
 	/* Wait for voltage/min repeat delay */
@@ -1014,7 +1060,7 @@
 
 	/* Command */
 	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
-	if(ret != 0)
+	if (ret != 0)
 		return ret;
 
 	/*
@@ -1027,34 +1073,32 @@
 	 *  12.5ms burst        +
 	 * >15ms delay            (XXX determine if FW does this, see set_tone)
 	 */
-	msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
+	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
 
 	return 0;
 }
 
-static void cx24116_release(struct dvb_frontend* fe)
+static void cx24116_release(struct dvb_frontend *fe)
 {
-	struct cx24116_state* state = fe->demodulator_priv;
-	dprintk("%s\n",__func__);
+	struct cx24116_state *state = fe->demodulator_priv;
+	dprintk("%s\n", __func__);
 	kfree(state);
 }
 
 static struct dvb_frontend_ops cx24116_ops;
 
-struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
-				    struct i2c_adapter* i2c)
+struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
+	struct i2c_adapter *i2c)
 {
-	struct cx24116_state* state = NULL;
+	struct cx24116_state *state = NULL;
 	int ret;
 
-	dprintk("%s\n",__func__);
+	dprintk("%s\n", __func__);
 
 	/* allocate memory for the internal state */
 	state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
-	if (state == NULL) {
-		printk("Unable to kmalloc\n");
+	if (state == NULL)
 		goto error1;
-	}
 
 	/* setup the state */
 	memset(state, 0, sizeof(struct cx24116_state));
@@ -1063,32 +1107,36 @@
 	state->i2c = i2c;
 
 	/* check if the demod is present */
-	ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
+	ret = (cx24116_readreg(state, 0xFF) << 8) |
+		cx24116_readreg(state, 0xFE);
 	if (ret != 0x0501) {
-		printk("Invalid probe, probably not a CX24116 device\n");
+		printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
 		goto error2;
 	}
 
 	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops));
+	memcpy(&state->frontend.ops, &cx24116_ops,
+		sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
 error2: kfree(state);
 error1: return NULL;
 }
+EXPORT_SYMBOL(cx24116_attach);
+
 /*
  * Initialise or wake up device
  *
  * Power config will reset and load initial firmware if required
  */
-static int cx24116_initfe(struct dvb_frontend* fe)
+static int cx24116_initfe(struct dvb_frontend *fe)
 {
-	struct cx24116_state* state = fe->demodulator_priv;
+	struct cx24116_state *state = fe->demodulator_priv;
 	struct cx24116_cmd cmd;
 	int ret;
 
-	dprintk("%s()\n",__func__);
+	dprintk("%s()\n", __func__);
 
 	/* Power on */
 	cx24116_writereg(state, 0xe0, 0);
@@ -1098,9 +1146,9 @@
 	/* Firmware CMD 36: Power config */
 	cmd.args[0x00] = CMD_TUNERSLEEP;
 	cmd.args[0x01] = 0;
-	cmd.len= 0x02;
+	cmd.len = 0x02;
 	ret = cx24116_cmd_execute(fe, &cmd);
-	if(ret != 0)
+	if (ret != 0)
 		return ret;
 
 	return cx24116_diseqc_init(fe);
@@ -1109,20 +1157,20 @@
 /*
  * Put device to sleep
  */
-static int cx24116_sleep(struct dvb_frontend* fe)
+static int cx24116_sleep(struct dvb_frontend *fe)
 {
-	struct cx24116_state* state = fe->demodulator_priv;
+	struct cx24116_state *state = fe->demodulator_priv;
 	struct cx24116_cmd cmd;
 	int ret;
 
-	dprintk("%s()\n",__func__);
+	dprintk("%s()\n", __func__);
 
 	/* Firmware CMD 36: Power config */
 	cmd.args[0x00] = CMD_TUNERSLEEP;
 	cmd.args[0x01] = 1;
-	cmd.len= 0x02;
+	cmd.len = 0x02;
 	ret = cx24116_cmd_execute(fe, &cmd);
-	if(ret != 0)
+	if (ret != 0)
 		return ret;
 
 	/* Power off (Shutdown clocks) */
@@ -1133,13 +1181,15 @@
 	return 0;
 }
 
-static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
+static int cx24116_set_property(struct dvb_frontend *fe,
+	struct dtv_property *tvp)
 {
 	dprintk("%s(..)\n", __func__);
 	return 0;
 }
 
-static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp)
+static int cx24116_get_property(struct dvb_frontend *fe,
+	struct dtv_property *tvp)
 {
 	dprintk("%s(..)\n", __func__);
 	return 0;
@@ -1148,7 +1198,8 @@
 /* dvb-core told us to tune, the tv property cache will be complete,
  * it's safe for is to pull values and use them for tuning purposes.
  */
-static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24116_set_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1156,96 +1207,102 @@
 	fe_status_t tunerstat;
 	int i, status, ret, retune;
 
-	dprintk("%s()\n",__func__);
+	dprintk("%s()\n", __func__);
 
-	switch(c->delivery_system) {
-		case SYS_DVBS:
-			dprintk("%s: DVB-S delivery system selected\n",__func__);
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		dprintk("%s: DVB-S delivery system selected\n", __func__);
 
-			/* Only QPSK is supported for DVB-S */
-			if(c->modulation != QPSK) {
-				dprintk("%s: unsupported modulation selected (%d)\n",
-					__func__, c->modulation);
-				return -EOPNOTSUPP;
-			}
+		/* Only QPSK is supported for DVB-S */
+		if (c->modulation != QPSK) {
+			dprintk("%s: unsupported modulation selected (%d)\n",
+				__func__, c->modulation);
+			return -EOPNOTSUPP;
+		}
 
-			/* Pilot doesn't exist in DVB-S, turn bit off */
+		/* Pilot doesn't exist in DVB-S, turn bit off */
+		state->dnxt.pilot_val = CX24116_PILOT_OFF;
+		retune = 1;
+
+		/* DVB-S only supports 0.35 */
+		if (c->rolloff != ROLLOFF_35) {
+			dprintk("%s: unsupported rolloff selected (%d)\n",
+				__func__, c->rolloff);
+			return -EOPNOTSUPP;
+		}
+		state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+		break;
+
+	case SYS_DVBS2:
+		dprintk("%s: DVB-S2 delivery system selected\n", __func__);
+
+		/*
+		 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
+		 * but not hardware auto detection
+		 */
+		if (c->modulation != PSK_8 && c->modulation != QPSK) {
+			dprintk("%s: unsupported modulation selected (%d)\n",
+				__func__, c->modulation);
+			return -EOPNOTSUPP;
+		}
+
+		switch (c->pilot) {
+		case PILOT_AUTO:	/* Not supported but emulated */
+			state->dnxt.pilot_val = (c->modulation == QPSK)
+				? CX24116_PILOT_OFF : CX24116_PILOT_ON;
+			retune = 2;
+			break;
+		case PILOT_OFF:
 			state->dnxt.pilot_val = CX24116_PILOT_OFF;
-			retune = 1;
+			break;
+		case PILOT_ON:
+			state->dnxt.pilot_val = CX24116_PILOT_ON;
+			break;
+		default:
+			dprintk("%s: unsupported pilot mode selected (%d)\n",
+				__func__, c->pilot);
+			return -EOPNOTSUPP;
+		}
 
-			/* DVB-S only supports 0.35 */
-			if(c->rolloff != ROLLOFF_35) {
-				dprintk("%s: unsupported rolloff selected (%d)\n",
-					__func__, c->rolloff);
-				return -EOPNOTSUPP;
-			}
+		switch (c->rolloff) {
+		case ROLLOFF_20:
+			state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
+			break;
+		case ROLLOFF_25:
+			state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
+			break;
+		case ROLLOFF_35:
 			state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
 			break;
-
-		case SYS_DVBS2:
-			dprintk("%s: DVB-S2 delivery system selected\n",__func__);
-
-			/*
-			 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
-			 * but not hardware auto detection
-			 */
-			if(c->modulation != PSK_8 && c->modulation != QPSK) {
-				dprintk("%s: unsupported modulation selected (%d)\n",
-					__func__, c->modulation);
-				return -EOPNOTSUPP;
-			}
-
-			switch(c->pilot) {
-				case PILOT_AUTO:	/* Not supported but emulated */
-					retune = 2;	/* Fall-through */
-				case PILOT_OFF:
-					state->dnxt.pilot_val = CX24116_PILOT_OFF;
-					break;
-				case PILOT_ON:
-					state->dnxt.pilot_val = CX24116_PILOT_ON;
-					break;
-				default:
-					dprintk("%s: unsupported pilot mode selected (%d)\n",
-						__func__, c->pilot);
-					return -EOPNOTSUPP;
-			}
-
-			switch(c->rolloff) {
-				case ROLLOFF_20:
-					state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
-					break;
-				case ROLLOFF_25:
-					state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
-					break;
-				case ROLLOFF_35:
-					state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
-					break;
-				case ROLLOFF_AUTO:	/* Rolloff must be explicit */
-				default:
-					dprintk("%s: unsupported rolloff selected (%d)\n",
-						__func__, c->rolloff);
-					return -EOPNOTSUPP;
-			}
-			break;
-
+		case ROLLOFF_AUTO:	/* Rolloff must be explicit */
 		default:
-			dprintk("%s: unsupported delivery system selected (%d)\n",
-				__func__, c->delivery_system);
+			dprintk("%s: unsupported rolloff selected (%d)\n",
+				__func__, c->rolloff);
 			return -EOPNOTSUPP;
+		}
+		break;
+
+	default:
+		dprintk("%s: unsupported delivery system selected (%d)\n",
+			__func__, c->delivery_system);
+		return -EOPNOTSUPP;
 	}
 	state->dnxt.modulation = c->modulation;
 	state->dnxt.frequency = c->frequency;
 	state->dnxt.pilot = c->pilot;
 	state->dnxt.rolloff = c->rolloff;
 
-	if ((ret = cx24116_set_inversion(state, c->inversion)) !=  0)
+	ret = cx24116_set_inversion(state, c->inversion);
+	if (ret !=  0)
 		return ret;
 
 	/* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
-	if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) !=  0)
+	ret = cx24116_set_fec(state, c->modulation, c->fec_inner);
+	if (ret !=  0)
 		return ret;
 
-	if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) !=  0)
+	ret = cx24116_set_symbolrate(state, c->symbol_rate);
+	if (ret !=  0)
 		return ret;
 
 	/* discard the 'current' tuning parameters and prepare to tune */
@@ -1271,7 +1328,7 @@
 	/* Set/Reset B/W */
 	cmd.args[0x00] = CMD_BANDWIDTH;
 	cmd.args[0x01] = 0x01;
-	cmd.len= 0x02;
+	cmd.len = 0x02;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
@@ -1319,7 +1376,7 @@
 		cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
 	}
 
-	cmd.len= 0x13;
+	cmd.len = 0x13;
 
 	/* We need to support pilot and non-pilot tuning in the
 	 * driver automatically. This is a workaround for because
@@ -1327,12 +1384,13 @@
 	 */
 	do {
 		/* Reset status register */
-		status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
+		status = cx24116_readreg(state, CX24116_REG_SSTATUS)
+			& CX24116_SIGNAL_MASK;
 		cx24116_writereg(state, CX24116_REG_SSTATUS, status);
 
 		/* Tune */
 		ret = cx24116_cmd_execute(fe, &cmd);
-		if( ret != 0 )
+		if (ret != 0)
 			break;
 
 		/*
@@ -1341,28 +1399,27 @@
 		 * If we are able to tune then generally it occurs within 100ms.
 		 * If it takes longer, try a different toneburst setting.
 		 */
-		for(i = 0; i < 50 ; i++) {
+		for (i = 0; i < 50 ; i++) {
 			cx24116_read_status(fe, &tunerstat);
 			status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
-			if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
-				dprintk("%s: Tuned\n",__func__);
+			if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
+				dprintk("%s: Tuned\n", __func__);
 				goto tuned;
 			}
 			msleep(10);
 		}
 
-		dprintk("%s: Not tuned\n",__func__);
+		dprintk("%s: Not tuned\n", __func__);
 
 		/* Toggle pilot bit when in auto-pilot */
-		if(state->dcur.pilot == PILOT_AUTO)
+		if (state->dcur.pilot == PILOT_AUTO)
 			cmd.args[0x07] ^= CX24116_PILOT_ON;
-	}
-	while(--retune);
+	} while (--retune);
 
 tuned:  /* Set/Reset B/W */
 	cmd.args[0x00] = CMD_BANDWIDTH;
 	cmd.args[0x01] = 0x00;
-	cmd.len= 0x02;
+	cmd.len = 0x02;
 	ret = cx24116_cmd_execute(fe, &cmd);
 	if (ret != 0)
 		return ret;
@@ -1407,17 +1464,7 @@
 	.set_frontend = cx24116_set_frontend,
 };
 
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-module_param(toneburst, int, 0644);
-MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
-
-module_param(esno_snr, int, 0644);
-MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)");
-
 MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(cx24116_attach);
diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h
index 8dbcec2..4cb3ddd 100644
--- a/drivers/media/dvb/frontends/cx24116.h
+++ b/drivers/media/dvb/frontends/cx24116.h
@@ -23,31 +23,32 @@
 
 #include <linux/dvb/frontend.h>
 
-struct cx24116_config
-{
+struct cx24116_config {
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
 	/* Need to set device param for start_dma */
-	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
 
 	/* Need to reset device during firmware loading */
-	int (*reset_device)(struct dvb_frontend* fe);
+	int (*reset_device)(struct dvb_frontend *fe);
 
 	/* Need to set MPEG parameters */
 	u8 mpg_clk_pos_pol:0x02;
 };
 
 #if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE)
-extern struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
-					   struct i2c_adapter* i2c);
+extern struct dvb_frontend *cx24116_attach(
+	const struct cx24116_config *config,
+	struct i2c_adapter *i2c);
 #else
-static inline struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
-						  struct i2c_adapter* i2c)
+static inline struct dvb_frontend *cx24116_attach(
+	const struct cx24116_config *config,
+	struct i2c_adapter *i2c)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-#endif // CONFIG_DVB_CX24116
+#endif
 
 #endif /* CX24116_H */
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index 7156157..1a8c36f 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -33,7 +33,13 @@
 #define XTAL 10111000
 
 static int force_band;
+module_param(force_band, int, 0644);
+MODULE_PARM_DESC(force_band, "Force a specific band select "\
+	"(1-9, default:off).");
+
 static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 
 #define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
 #define err(args...)  do { printk(KERN_ERR  "CX24123: " args); } while (0)
@@ -46,10 +52,9 @@
 		} \
 	} while (0)
 
-struct cx24123_state
-{
-	struct i2c_adapter* i2c;
-	const struct cx24123_config* config;
+struct cx24123_state {
+	struct i2c_adapter *i2c;
+	const struct cx24123_config *config;
 
 	struct dvb_frontend frontend;
 
@@ -70,8 +75,7 @@
 };
 
 /* Various tuner defaults need to be established for a given symbol rate Sps */
-static struct
-{
+static struct cx24123_AGC_val {
 	u32 symbolrate_low;
 	u32 symbolrate_high;
 	u32 VCAprogdata;
@@ -109,8 +113,7 @@
  * fixme: The bounds on the bands do not match the doc in real life.
  * fixme: Some of them have been moved, other might need adjustment.
  */
-static struct
-{
+static struct cx24123_bandselect_val {
 	u32 freq_low;
 	u32 freq_high;
 	u32 VCOdivider;
@@ -249,7 +252,8 @@
 
 	/* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
 
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
 		printk("%s: writereg error(err == %i, reg == 0x%02x,"
 			 " data == 0x%02x)\n", __func__, err, reg, data);
 		return err;
@@ -284,7 +288,8 @@
 #define cx24123_writereg(state, reg, val) \
 	cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
 
-static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+static int cx24123_set_inversion(struct cx24123_state *state,
+	fe_spectral_inversion_t inversion)
 {
 	u8 nom_reg = cx24123_readreg(state, 0x0e);
 	u8 auto_reg = cx24123_readreg(state, 0x10);
@@ -311,7 +316,8 @@
 	return 0;
 }
 
-static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion)
+static int cx24123_get_inversion(struct cx24123_state *state,
+	fe_spectral_inversion_t *inversion)
 {
 	u8 val;
 
@@ -328,18 +334,20 @@
 	return 0;
 }
 
-static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
 {
 	u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
 
-	if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
+	if ((fec < FEC_NONE) || (fec > FEC_AUTO))
 		fec = FEC_AUTO;
 
 	/* Set the soft decision threshold */
-	if(fec == FEC_1_2)
-		cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) | 0x01);
+	if (fec == FEC_1_2)
+		cx24123_writereg(state, 0x43,
+			cx24123_readreg(state, 0x43) | 0x01);
 	else
-		cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) & ~0x01);
+		cx24123_writereg(state, 0x43,
+			cx24123_readreg(state, 0x43) & ~0x01);
 
 	switch (fec) {
 	case FEC_1_2:
@@ -388,11 +396,11 @@
 	return 0;
 }
 
-static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
+static int cx24123_get_fec(struct cx24123_state *state, fe_code_rate_t *fec)
 {
 	int ret;
 
-	ret = cx24123_readreg (state, 0x1b);
+	ret = cx24123_readreg(state, 0x1b);
 	if (ret < 0)
 		return ret;
 	ret = ret & 0x07;
@@ -433,16 +441,16 @@
 {
 	u32 exp, nearest = 0;
 	u32 div = a / b;
-	if(a % b >= b / 2) ++div;
-	if(div < (1 << 31))
-	{
-		for(exp = 1; div > exp; nearest++)
+	if (a % b >= b / 2)
+		++div;
+	if (div < (1 << 31)) {
+		for (exp = 1; div > exp; nearest++)
 			exp += exp;
 	}
 	return nearest;
 }
 
-static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
 {
 	u32 tmp, sample_rate, ratio, sample_gain;
 	u8 pll_mult;
@@ -498,9 +506,9 @@
 
 	cx24123_writereg(state, 0x01, pll_mult * 6);
 
-	cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f );
-	cx24123_writereg(state, 0x09, (ratio >>  8) & 0xff );
-	cx24123_writereg(state, 0x0a, (ratio      ) & 0xff );
+	cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f);
+	cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff);
+	cx24123_writereg(state, 0x0a, ratio & 0xff);
 
 	/* also set the demodulator sample gain */
 	sample_gain = cx24123_int_log2(sample_rate, srate);
@@ -514,10 +522,12 @@
 }
 
 /*
- * Based on the required frequency and symbolrate, the tuner AGC has to be configured
- * and the correct band selected. Calculate those values
+ * Based on the required frequency and symbolrate, the tuner AGC has
+ * to be configured and the correct band selected.
+ * Calculate those values.
  */
-static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_calculate(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	u32 ndiv = 0, adiv = 0, vco_div = 0;
@@ -525,6 +535,8 @@
 	int pump = 2;
 	int band = 0;
 	int num_bands = ARRAY_SIZE(cx24123_bandselect_vals);
+	struct cx24123_bandselect_val *bsv = NULL;
+	struct cx24123_AGC_val *agcv = NULL;
 
 	/* Defaults for low freq, low rate */
 	state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
@@ -532,58 +544,65 @@
 	state->bandselectarg = cx24123_bandselect_vals[0].progdata;
 	vco_div = cx24123_bandselect_vals[0].VCOdivider;
 
-	/* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
-	for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++)
-	{
-		if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
-		    (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
-			state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
-			state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
-			state->FILTune = cx24123_AGC_vals[i].FILTune;
+	/* For the given symbol rate, determine the VCA, VGA and
+	 * FILTUNE programming bits */
+	for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) {
+		agcv = &cx24123_AGC_vals[i];
+		if ((agcv->symbolrate_low <= p->u.qpsk.symbol_rate) &&
+		    (agcv->symbolrate_high >= p->u.qpsk.symbol_rate)) {
+			state->VCAarg = agcv->VCAprogdata;
+			state->VGAarg = agcv->VGAprogdata;
+			state->FILTune = agcv->FILTune;
 		}
 	}
 
 	/* determine the band to use */
-	if(force_band < 1 || force_band > num_bands)
-	{
-		for (i = 0; i < num_bands; i++)
-		{
-			if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
-			    (cx24123_bandselect_vals[i].freq_high >= p->frequency) )
+	if (force_band < 1 || force_band > num_bands) {
+		for (i = 0; i < num_bands; i++) {
+			bsv = &cx24123_bandselect_vals[i];
+			if ((bsv->freq_low <= p->frequency) &&
+				(bsv->freq_high >= p->frequency))
 				band = i;
 		}
-	}
-	else
+	} else
 		band = force_band - 1;
 
 	state->bandselectarg = cx24123_bandselect_vals[band].progdata;
 	vco_div = cx24123_bandselect_vals[band].VCOdivider;
 
 	/* determine the charge pump current */
-	if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 )
+	if (p->frequency < (cx24123_bandselect_vals[band].freq_low +
+		cx24123_bandselect_vals[band].freq_high) / 2)
 		pump = 0x01;
 	else
 		pump = 0x02;
 
 	/* Determine the N/A dividers for the requested lband freq (in kHz). */
-	/* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */
-	ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
-	adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
+	/* Note: the reference divider R=10, frequency is in KHz,
+	 * XTAL is in Hz */
+	ndiv = (((p->frequency * vco_div * 10) /
+		(2 * XTAL / 1000)) / 32) & 0x1ff;
+	adiv = (((p->frequency * vco_div * 10) /
+		(2 * XTAL / 1000)) % 32) & 0x1f;
 
 	if (adiv == 0 && ndiv > 0)
 		ndiv--;
 
-	/* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
-	state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
+	/* control bits 11, refdiv 11, charge pump polarity 1,
+	 * charge pump current, ndiv, adiv */
+	state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) |
+		(pump << 14) | (ndiv << 5) | adiv;
 
 	return 0;
 }
 
 /*
  * Tuner data is 21 bits long, must be left-aligned in data.
- * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
+ * Tuner cx24109 is written through a dedicated 3wire interface
+ * on the demod chip.
  */
-static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+static int cx24123_pll_writereg(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p, u32 data)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	unsigned long timeout;
@@ -610,7 +629,7 @@
 
 	/* send another 8 bytes, wait for the send to be completed */
 	timeout = jiffies + msecs_to_jiffies(40);
-	cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+	cx24123_writereg(state, 0x22, (data >> 8) & 0xff);
 	while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
 		if (time_after(jiffies, timeout)) {
 			err("%s:  demodulator is not responding, "\
@@ -620,9 +639,10 @@
 		msleep(10);
 	}
 
-	/* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */
+	/* send the lower 5 bits of this byte, padded with 3 LBB,
+	 * wait for the send to be completed */
 	timeout = jiffies + msecs_to_jiffies(40);
-	cx24123_writereg(state, 0x22, (data) & 0xff );
+	cx24123_writereg(state, 0x22, (data) & 0xff);
 	while ((cx24123_readreg(state, 0x20) & 0x80)) {
 		if (time_after(jiffies, timeout)) {
 			err("%s:  demodulator is not responding," \
@@ -639,7 +659,8 @@
 	return 0;
 }
 
-static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_tune(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
@@ -690,7 +711,7 @@
 	return cx24123_writereg(state, 0x23, r);
 }
 
-static int cx24123_initfe(struct dvb_frontend* fe)
+static int cx24123_initfe(struct dvb_frontend *fe)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	int i;
@@ -699,19 +720,22 @@
 
 	/* Configure the demod to a good set of defaults */
 	for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
-		cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
+		cx24123_writereg(state, cx24123_regdata[i].reg,
+			cx24123_regdata[i].data);
 
 	/* Set the LNB polarity */
-	if(state->config->lnb_polarity)
-		cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
+	if (state->config->lnb_polarity)
+		cx24123_writereg(state, 0x32,
+			cx24123_readreg(state, 0x32) | 0x02);
 
 	if (state->config->dont_use_pll)
-	cx24123_repeater_mode(state, 1, 0);
+		cx24123_repeater_mode(state, 1, 0);
 
 	return 0;
 }
 
-static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int cx24123_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t voltage)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
@@ -740,7 +764,7 @@
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(200);
 	while (!(cx24123_readreg(state, 0x29) & 0x40)) {
-		if(time_after(jiffies, timeout)) {
+		if (time_after(jiffies, timeout)) {
 			err("%s: diseqc queue not ready, " \
 				"command may be lost.\n", __func__);
 			break;
@@ -749,7 +773,8 @@
 	}
 }
 
-static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
+static int cx24123_send_diseqc_msg(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *cmd)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	int i, val, tone;
@@ -771,20 +796,21 @@
 		cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
 
 	val = cx24123_readreg(state, 0x29);
-	cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
+	cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) |
+		((cmd->msg_len-3) & 3));
 
 	/* wait for diseqc message to finish sending */
 	cx24123_wait_for_diseqc(state);
 
 	/* restart continuous tone if enabled */
-	if (tone & 0x10) {
+	if (tone & 0x10)
 		cx24123_writereg(state, 0x29, tone & ~0x40);
-	}
 
 	return 0;
 }
 
-static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int cx24123_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t burst)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	int val, tone;
@@ -814,13 +840,13 @@
 	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
 	/* restart continuous tone if enabled */
-	if (tone & 0x10) {
+	if (tone & 0x10)
 		cx24123_writereg(state, 0x29, tone & ~0x40);
-	}
+
 	return 0;
 }
 
-static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx24123_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	int sync = cx24123_readreg(state, 0x14);
@@ -853,8 +879,9 @@
 }
 
 /*
- * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
- * is available, so this value doubles up to satisfy both measurements
+ * Configured to return the measurement of errors in blocks,
+ * because no UCBLOCKS value is available, so this value doubles up
+ * to satisfy both measurements.
  */
 static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
@@ -876,7 +903,8 @@
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 
-	*signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+	/* larger = better */
+	*signal_strength = cx24123_readreg(state, 0x3b) << 8;
 
 	dprintk("Signal strength = %d\n", *signal_strength);
 
@@ -907,7 +935,7 @@
 	if (state->config->set_ts_params)
 		state->config->set_ts_params(fe, 0);
 
-	state->currentfreq=p->frequency;
+	state->currentfreq = p->frequency;
 	state->currentsymbolrate = p->u.qpsk.symbol_rate;
 
 	cx24123_set_inversion(state, p->inversion);
@@ -932,7 +960,8 @@
 	return 0;
 }
 
-static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_get_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 
@@ -952,7 +981,7 @@
 	return 0;
 }
 
-static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
@@ -977,8 +1006,8 @@
 	return 0;
 }
 
-static int cx24123_tune(struct dvb_frontend* fe,
-			struct dvb_frontend_parameters* params,
+static int cx24123_tune(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *params,
 			unsigned int mode_flags,
 			unsigned int *delay,
 			fe_status_t *status)
@@ -997,12 +1026,12 @@
 
 static int cx24123_get_algo(struct dvb_frontend *fe)
 {
-	return 1; //FE_ALGO_HW
+	return 1; /* FE_ALGO_HW */
 }
 
-static void cx24123_release(struct dvb_frontend* fe)
+static void cx24123_release(struct dvb_frontend *fe)
 {
-	struct cx24123_state* state = fe->demodulator_priv;
+	struct cx24123_state *state = fe->demodulator_priv;
 	dprintk("\n");
 	i2c_del_adapter(&state->tuner_i2c_adapter);
 	kfree(state);
@@ -1013,7 +1042,7 @@
 {
 	struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
 	/* this repeater closes after the first stop */
-    cx24123_repeater_mode(state, 1, 1);
+	cx24123_repeater_mode(state, 1, 1);
 	return i2c_transfer(state->i2c, msg, num);
 }
 
@@ -1037,8 +1066,8 @@
 
 static struct dvb_frontend_ops cx24123_ops;
 
-struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
-				    struct i2c_adapter* i2c)
+struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
+				    struct i2c_adapter *i2c)
 {
 	struct cx24123_state *state =
 		kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
@@ -1057,20 +1086,25 @@
 	/* check if the demod is there */
 	state->demod_rev = cx24123_readreg(state, 0x00);
 	switch (state->demod_rev) {
-	case 0xe1: info("detected CX24123C\n"); break;
-	case 0xd1: info("detected CX24123\n"); break;
+	case 0xe1:
+		info("detected CX24123C\n");
+		break;
+	case 0xd1:
+		info("detected CX24123\n");
+		break;
 	default:
 		err("wrong demod revision: %x\n", state->demod_rev);
 		goto error;
 	}
 
 	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+	memcpy(&state->frontend.ops, &cx24123_ops,
+		sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
-    /* create tuner i2c adapter */
-    if (config->dont_use_pll)
-	cx24123_repeater_mode(state, 1, 0);
+	/* create tuner i2c adapter */
+	if (config->dont_use_pll)
+		cx24123_repeater_mode(state, 1, 0);
 
 	strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
 		sizeof(state->tuner_i2c_adapter.name));
@@ -1079,7 +1113,7 @@
 	state->tuner_i2c_adapter.algo_data = NULL;
 	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
 	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
-	err("tuner i2c bus could not be initialized\n");
+		err("tuner i2c bus could not be initialized\n");
 		goto error;
 	}
 
@@ -1090,6 +1124,7 @@
 
 	return NULL;
 }
+EXPORT_SYMBOL(cx24123_attach);
 
 static struct dvb_frontend_ops cx24123_ops = {
 
@@ -1126,15 +1161,8 @@
 	.get_frontend_algo = cx24123_get_algo,
 };
 
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-module_param(force_band, int, 0644);
-MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
-
 MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
 	"CX24123/CX24109/CX24113 hardware");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(cx24123_attach);
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
index cc6b411..51ae866 100644
--- a/drivers/media/dvb/frontends/cx24123.h
+++ b/drivers/media/dvb/frontends/cx24123.h
@@ -23,13 +23,12 @@
 
 #include <linux/dvb/frontend.h>
 
-struct cx24123_config
-{
+struct cx24123_config {
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
 	/* Need to set device param for start_dma */
-	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
 
 	/* 0 = LNB voltage normal, 1 = LNB voltage inverted */
 	int lnb_polarity;
@@ -39,7 +38,8 @@
 	void (*agc_callback) (struct dvb_frontend *);
 };
 
-#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE))
+#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
+	&& defined(MODULE))
 extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
 					   struct i2c_adapter *i2c);
 extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
@@ -56,6 +56,6 @@
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-#endif // CONFIG_DVB_CX24123
+#endif
 
 #endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index 7500a1c..cf4d893 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -30,10 +30,10 @@
 
 struct s5h1409_state {
 
-	struct i2c_adapter* i2c;
+	struct i2c_adapter *i2c;
 
 	/* configuration settings */
-	const struct s5h1409_config* config;
+	const struct s5h1409_config *config;
 
 	struct dvb_frontend frontend;
 
@@ -48,6 +48,9 @@
 };
 
 static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
 #define dprintk	if (debug) printk
 
 /* Register values to initialise the demod, this will set VSB by default */
@@ -299,10 +302,10 @@
 };
 
 /* 8 bit registers, 16 bit values */
-static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
+static int s5h1409_writereg(struct s5h1409_state *state, u8 reg, u16 data)
 {
 	int ret;
-	u8 buf [] = { reg, data >> 8,  data & 0xff };
+	u8 buf[] = { reg, data >> 8,  data & 0xff };
 
 	struct i2c_msg msg = { .addr = state->config->demod_address,
 			       .flags = 0, .buf = buf, .len = 3 };
@@ -310,19 +313,19 @@
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+		printk(KERN_ERR "%s: error (reg == 0x%02x, val == 0x%04x, "
 		       "ret == %i)\n", __func__, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
 }
 
-static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
+static u16 s5h1409_readreg(struct s5h1409_state *state, u8 reg)
 {
 	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0, 0 };
+	u8 b0[] = { reg };
+	u8 b1[] = { 0, 0 };
 
-	struct i2c_msg msg [] = {
+	struct i2c_msg msg[] = {
 		{ .addr = state->config->demod_address, .flags = 0,
 		  .buf = b0, .len = 1 },
 		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
@@ -335,9 +338,9 @@
 	return (b1[0] << 8) | b1[1];
 }
 
-static int s5h1409_softreset(struct dvb_frontend* fe)
+static int s5h1409_softreset(struct dvb_frontend *fe)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s()\n", __func__);
 
@@ -349,11 +352,11 @@
 }
 
 #define S5H1409_VSB_IF_FREQ 5380
-#define S5H1409_QAM_IF_FREQ state->config->qam_if
+#define S5H1409_QAM_IF_FREQ (state->config->qam_if)
 
-static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
+static int s5h1409_set_if_freq(struct dvb_frontend *fe, int KHz)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s(%d KHz)\n", __func__, KHz);
 
@@ -376,26 +379,26 @@
 	return 0;
 }
 
-static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
+static int s5h1409_set_spectralinversion(struct dvb_frontend *fe, int inverted)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s(%d)\n", __func__, inverted);
 
-	if(inverted == 1)
+	if (inverted == 1)
 		return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
 	else
 		return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */
 }
 
-static int s5h1409_enable_modulation(struct dvb_frontend* fe,
+static int s5h1409_enable_modulation(struct dvb_frontend *fe,
 				     fe_modulation_t m)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s(0x%08x)\n", __func__, m);
 
-	switch(m) {
+	switch (m) {
 	case VSB_8:
 		dprintk("%s() VSB_8\n", __func__);
 		if (state->if_freq != S5H1409_VSB_IF_FREQ)
@@ -422,9 +425,9 @@
 	return 0;
 }
 
-static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+static int s5h1409_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s(%d)\n", __func__, enable);
 
@@ -434,9 +437,9 @@
 		return s5h1409_writereg(state, 0xf3, 0);
 }
 
-static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
+static int s5h1409_set_gpio(struct dvb_frontend *fe, int enable)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s(%d)\n", __func__, enable);
 
@@ -448,18 +451,18 @@
 			s5h1409_readreg(state, 0xe3) & 0xfeff);
 }
 
-static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
+static int s5h1409_sleep(struct dvb_frontend *fe, int enable)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s(%d)\n", __func__, enable);
 
 	return s5h1409_writereg(state, 0xf2, enable);
 }
 
-static int s5h1409_register_reset(struct dvb_frontend* fe)
+static int s5h1409_register_reset(struct dvb_frontend *fe)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s()\n", __func__);
 
@@ -483,7 +486,7 @@
 		reg &= 0xff;
 
 		s5h1409_writereg(state, 0x96, 0x00c);
-		if ((reg < 0x38) || (reg > 0x68) ) {
+		if ((reg < 0x38) || (reg > 0x68)) {
 			s5h1409_writereg(state, 0x93, 0x3332);
 			s5h1409_writereg(state, 0x9e, 0x2c37);
 		} else {
@@ -514,7 +517,7 @@
 
 			s5h1409_writereg(state, 0x96, 0x20);
 			s5h1409_writereg(state, 0xad,
-				( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) );
+				(((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
 			s5h1409_writereg(state, 0xab,
 				s5h1409_readreg(state, 0xab) & 0xeffe);
 		}
@@ -529,10 +532,10 @@
 }
 
 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1409_set_frontend (struct dvb_frontend* fe,
+static int s5h1409_set_frontend(struct dvb_frontend *fe,
 				 struct dvb_frontend_parameters *p)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
 
@@ -546,9 +549,11 @@
 	msleep(100);
 
 	if (fe->ops.tuner_ops.set_params) {
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
 		fe->ops.tuner_ops.set_params(fe, p);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
 	}
 
 	/* Optimize the demod for QAM */
@@ -592,17 +597,17 @@
 
 /* Reset the demod hardware and reset all of the configuration registers
    to a default state. */
-static int s5h1409_init (struct dvb_frontend* fe)
+static int s5h1409_init(struct dvb_frontend *fe)
 {
 	int i;
 
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 	dprintk("%s()\n", __func__);
 
 	s5h1409_sleep(fe, 0);
 	s5h1409_register_reset(fe);
 
-	for (i=0; i < ARRAY_SIZE(init_tab); i++)
+	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
 		s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data);
 
 	/* The datasheet says that after initialisation, VSB is default */
@@ -627,9 +632,9 @@
 	return 0;
 }
 
-static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 	u16 reg;
 	u32 tuner_status = 0;
 
@@ -637,12 +642,12 @@
 
 	/* Get the demodulator status */
 	reg = s5h1409_readreg(state, 0xf1);
-	if(reg & 0x1000)
+	if (reg & 0x1000)
 		*status |= FE_HAS_VITERBI;
-	if(reg & 0x8000)
+	if (reg & 0x8000)
 		*status |= FE_HAS_LOCK | FE_HAS_SYNC;
 
-	switch(state->config->status_mode) {
+	switch (state->config->status_mode) {
 	case S5H1409_DEMODLOCKING:
 		if (*status & FE_HAS_VITERBI)
 			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
@@ -668,12 +673,12 @@
 	return 0;
 }
 
-static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
 {
 	int i, ret = -EINVAL;
 	dprintk("%s()\n", __func__);
 
-	for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+	for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
 		if (v < qam256_snr_tab[i].val) {
 			*snr = qam256_snr_tab[i].data;
 			ret = 0;
@@ -683,12 +688,12 @@
 	return ret;
 }
 
-static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
 {
 	int i, ret = -EINVAL;
 	dprintk("%s()\n", __func__);
 
-	for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+	for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
 		if (v < qam64_snr_tab[i].val) {
 			*snr = qam64_snr_tab[i].data;
 			ret = 0;
@@ -698,12 +703,12 @@
 	return ret;
 }
 
-static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
 {
 	int i, ret = -EINVAL;
 	dprintk("%s()\n", __func__);
 
-	for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+	for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
 		if (v > vsb_snr_tab[i].val) {
 			*snr = vsb_snr_tab[i].data;
 			ret = 0;
@@ -714,13 +719,13 @@
 	return ret;
 }
 
-static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
+static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 	u16 reg;
 	dprintk("%s()\n", __func__);
 
-	switch(state->current_modulation) {
+	switch (state->current_modulation) {
 	case QAM_64:
 		reg = s5h1409_readreg(state, 0xf0) & 0xff;
 		return s5h1409_qam64_lookup_snr(fe, snr, reg);
@@ -737,30 +742,30 @@
 	return -EINVAL;
 }
 
-static int s5h1409_read_signal_strength(struct dvb_frontend* fe,
-					u16* signal_strength)
+static int s5h1409_read_signal_strength(struct dvb_frontend *fe,
+					u16 *signal_strength)
 {
 	return s5h1409_read_snr(fe, signal_strength);
 }
 
-static int s5h1409_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	*ucblocks = s5h1409_readreg(state, 0xb5);
 
 	return 0;
 }
 
-static int s5h1409_read_ber(struct dvb_frontend* fe, u32* ber)
+static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
 	return s5h1409_read_ucblocks(fe, ber);
 }
 
-static int s5h1409_get_frontend(struct dvb_frontend* fe,
+static int s5h1409_get_frontend(struct dvb_frontend *fe,
 				struct dvb_frontend_parameters *p)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 
 	p->frequency = state->current_frequency;
 	p->u.vsb.modulation = state->current_modulation;
@@ -768,25 +773,25 @@
 	return 0;
 }
 
-static int s5h1409_get_tune_settings(struct dvb_frontend* fe,
+static int s5h1409_get_tune_settings(struct dvb_frontend *fe,
 				     struct dvb_frontend_tune_settings *tune)
 {
 	tune->min_delay_ms = 1000;
 	return 0;
 }
 
-static void s5h1409_release(struct dvb_frontend* fe)
+static void s5h1409_release(struct dvb_frontend *fe)
 {
-	struct s5h1409_state* state = fe->demodulator_priv;
+	struct s5h1409_state *state = fe->demodulator_priv;
 	kfree(state);
 }
 
 static struct dvb_frontend_ops s5h1409_ops;
 
-struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
-				    struct i2c_adapter* i2c)
+struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+				    struct i2c_adapter *i2c)
 {
-	struct s5h1409_state* state = NULL;
+	struct s5h1409_state *state = NULL;
 	u16 reg;
 
 	/* allocate memory for the internal state */
@@ -825,6 +830,7 @@
 	kfree(state);
 	return NULL;
 }
+EXPORT_SYMBOL(s5h1409_attach);
 
 static struct dvb_frontend_ops s5h1409_ops = {
 
@@ -850,14 +856,10 @@
 	.release              = s5h1409_release,
 };
 
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
 MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(s5h1409_attach);
 
 /*
  * Local variables:
diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h
index d1a1d2e..070d974 100644
--- a/drivers/media/dvb/frontends/s5h1409.h
+++ b/drivers/media/dvb/frontends/s5h1409.h
@@ -24,8 +24,7 @@
 
 #include <linux/dvb/frontend.h>
 
-struct s5h1409_config
-{
+struct s5h1409_config {
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
@@ -60,12 +59,14 @@
 	u16 mpeg_timing;
 };
 
-#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE))
-extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
-					   struct i2c_adapter* i2c);
+#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+					   struct i2c_adapter *i2c);
 #else
-static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
-						  struct i2c_adapter* i2c)
+static inline struct dvb_frontend *s5h1409_attach(
+	const struct s5h1409_config *config,
+	struct i2c_adapter *i2c)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
index 2da1a37..2febfb5 100644
--- a/drivers/media/dvb/frontends/s5h1411.c
+++ b/drivers/media/dvb/frontends/s5h1411.c
@@ -343,7 +343,7 @@
 	u8 addr, u8 reg, u16 data)
 {
 	int ret;
-	u8 buf [] = { reg, data >> 8,  data & 0xff };
+	u8 buf[] = { reg, data >> 8,  data & 0xff };
 
 	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
 
@@ -359,10 +359,10 @@
 static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
 {
 	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0, 0 };
+	u8 b0[] = { reg };
+	u8 b1[] = { 0, 0 };
 
-	struct i2c_msg msg [] = {
+	struct i2c_msg msg[] = {
 		{ .addr = addr, .flags = 0, .buf = b0, .len = 1 },
 		{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
 
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 04e7f1c..2a8bbcd 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -195,7 +195,7 @@
 static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
 {
 	int ret;
-	u8 buf [] = { reg, data };
+	u8 buf[] = { reg, data };
 	struct i2c_msg msg = {
 		.addr = state->config->demod_address,
 		.flags = 0, .buf = buf, .len = 2 };
@@ -213,9 +213,9 @@
 static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
 {
 	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = {
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
 		{ .addr = state->config->demod_address,
 			.flags = 0, .buf = b0, .len = 1 },
 		{ .addr = state->config->demod_address,
@@ -393,43 +393,89 @@
 
 	val = tda10048_readreg(state, TDA10048_OUT_CONF2);
 	switch ((val & 0x60) >> 5) {
-	case 0: p->constellation =   QPSK; break;
-	case 1: p->constellation = QAM_16; break;
-	case 2: p->constellation = QAM_64; break;
+	case 0:
+		p->constellation = QPSK;
+		break;
+	case 1:
+		p->constellation = QAM_16;
+		break;
+	case 2:
+		p->constellation = QAM_64;
+		break;
 	}
 	switch ((val & 0x18) >> 3) {
-	case 0: p->hierarchy_information = HIERARCHY_NONE; break;
-	case 1: p->hierarchy_information =    HIERARCHY_1; break;
-	case 2: p->hierarchy_information =    HIERARCHY_2; break;
-	case 3: p->hierarchy_information =    HIERARCHY_4; break;
+	case 0:
+		p->hierarchy_information = HIERARCHY_NONE;
+		break;
+	case 1:
+		p->hierarchy_information = HIERARCHY_1;
+		break;
+	case 2:
+		p->hierarchy_information = HIERARCHY_2;
+		break;
+	case 3:
+		p->hierarchy_information = HIERARCHY_4;
+		break;
 	}
 	switch (val & 0x07) {
-	case 0: p->code_rate_HP = FEC_1_2; break;
-	case 1: p->code_rate_HP = FEC_2_3; break;
-	case 2: p->code_rate_HP = FEC_3_4; break;
-	case 3: p->code_rate_HP = FEC_5_6; break;
-	case 4: p->code_rate_HP = FEC_7_8; break;
+	case 0:
+		p->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_HP = FEC_7_8;
+		break;
 	}
 
 	val = tda10048_readreg(state, TDA10048_OUT_CONF3);
 	switch (val & 0x07) {
-	case 0: p->code_rate_LP = FEC_1_2; break;
-	case 1: p->code_rate_LP = FEC_2_3; break;
-	case 2: p->code_rate_LP = FEC_3_4; break;
-	case 3: p->code_rate_LP = FEC_5_6; break;
-	case 4: p->code_rate_LP = FEC_7_8; break;
+	case 0:
+		p->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_LP = FEC_7_8;
+		break;
 	}
 
 	val = tda10048_readreg(state, TDA10048_OUT_CONF1);
 	switch ((val & 0x0c) >> 2) {
-	case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
-	case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
-	case 2: p->guard_interval =  GUARD_INTERVAL_1_8; break;
-	case 3: p->guard_interval =  GUARD_INTERVAL_1_4; break;
+	case 0:
+		p->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		p->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		p->guard_interval =  GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		p->guard_interval =  GUARD_INTERVAL_1_4;
+		break;
 	}
 	switch (val & 0x02) {
-	case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
-	case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+	case 0:
+		p->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		p->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
 	}
 
 	return 0;
diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb/frontends/z0194a.h
index d2876d2..07f3fc0 100644
--- a/drivers/media/dvb/frontends/z0194a.h
+++ b/drivers/media/dvb/frontends/z0194a.h
@@ -12,7 +12,7 @@
 #ifndef Z0194A
 #define Z0194A
 
-static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
+static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe,
 					 u32 srate, u32 ratio)
 {
 	u8 aclk = 0;
@@ -40,7 +40,7 @@
 	return 0;
 }
 
-static u8 sharp_z0194a__inittab[] = {
+static u8 sharp_z0194a_inittab[] = {
 	0x01, 0x15,
 	0x02, 0x00,
 	0x03, 0x00,
@@ -82,16 +82,4 @@
 	0xff, 0xff
 };
 
-static struct stv0299_config sharp_z0194a_config = {
-	.demod_address = 0x68,
-	.inittab = sharp_z0194a__inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = sharp_z0194a__set_symbol_rate,
-};
-
 #endif
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index 9da260f..6f9b773 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -42,6 +42,10 @@
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0x5510),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5520),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5530),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0x5580),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0x5590),
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index e51d707..04cd7c0 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -359,7 +359,7 @@
 	  computer's USB port.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called radio-silabs.
+	  module will be called radio-si470x.
 
 config USB_MR800
 	tristate "AverMedia MR 800 USB FM radio support"
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index f6cedcd..5920cd30 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -104,6 +104,7 @@
  *		- hardware frequency seek support
  *		- afc indication
  *		- more safety checks, let si470x_get_freq return errno
+ *		- vidioc behavior corrected according to v4l2 spec
  *
  * ToDo:
  * - add firmware download/update support
@@ -141,9 +142,9 @@
 /* USB Device ID List */
 static struct usb_device_id si470x_usb_driver_id_table[] = {
 	/* Silicon Labs USB FM Radio Reference Design */
-	{ USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a,	USB_CLASS_HID, 0, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
 	/* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
-	{ USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155,	USB_CLASS_HID, 0, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
 	/* Terminating entry */
 	{ }
 };
@@ -157,7 +158,7 @@
 
 /* Radio Nr */
 static int radio_nr = -1;
-module_param(radio_nr, int, 0);
+module_param(radio_nr, int, 0444);
 MODULE_PARM_DESC(radio_nr, "Radio Nr");
 
 /* Spacing (kHz) */
@@ -165,42 +166,42 @@
 /* 1: 100 kHz (Europe, Japan) */
 /* 2:  50 kHz */
 static unsigned short space = 2;
-module_param(space, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
+module_param(space, ushort, 0444);
+MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
 
 /* Bottom of Band (MHz) */
 /* 0: 87.5 - 108 MHz (USA, Europe)*/
 /* 1: 76   - 108 MHz (Japan wide band) */
 /* 2: 76   -  90 MHz (Japan) */
 static unsigned short band = 1;
-module_param(band, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
+module_param(band, ushort, 0444);
+MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
 
 /* De-emphasis */
 /* 0: 75 us (USA) */
 /* 1: 50 us (Europe, Australia, Japan) */
 static unsigned short de = 1;
-module_param(de, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*");
+module_param(de, ushort, 0444);
+MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");
 
 /* USB timeout */
 static unsigned int usb_timeout = 500;
-module_param(usb_timeout, uint, 0);
+module_param(usb_timeout, uint, 0644);
 MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");
 
 /* Tune timeout */
 static unsigned int tune_timeout = 3000;
-module_param(tune_timeout, uint, 0);
+module_param(tune_timeout, uint, 0644);
 MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
 
 /* Seek timeout */
 static unsigned int seek_timeout = 5000;
-module_param(seek_timeout, uint, 0);
+module_param(seek_timeout, uint, 0644);
 MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
 
 /* RDS buffer blocks */
 static unsigned int rds_buf = 100;
-module_param(rds_buf, uint, 0);
+module_param(rds_buf, uint, 0444);
 MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
 
 /* RDS maximum block errors */
@@ -209,7 +210,7 @@
 /* 1 means 1-2  errors requiring correction (used by original USBRadio.exe) */
 /* 2 means 3-5  errors requiring correction */
 /* 3 means   6+ errors or errors in checkword, correction not possible */
-module_param(max_rds_errors, ushort, 0);
+module_param(max_rds_errors, ushort, 0644);
 MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
 
 /* RDS poll frequency */
@@ -218,7 +219,7 @@
 /* 50 is used by radio-cadet */
 /* 75 should be okay */
 /* 80 is the usual RDS receive interval */
-module_param(rds_poll_time, uint, 0);
+module_param(rds_poll_time, uint, 0644);
 MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
 
 
@@ -667,23 +668,29 @@
 	int retval;
 
 	/* Spacing (kHz) */
-	switch (space) {
+	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
 	/* 0: 200 kHz (USA, Australia) */
-	case 0 : spacing = 0.200 * FREQ_MUL; break;
+	case 0:
+		spacing = 0.200 * FREQ_MUL; break;
 	/* 1: 100 kHz (Europe, Japan) */
-	case 1 : spacing = 0.100 * FREQ_MUL; break;
+	case 1:
+		spacing = 0.100 * FREQ_MUL; break;
 	/* 2:  50 kHz */
-	default: spacing = 0.050 * FREQ_MUL; break;
+	default:
+		spacing = 0.050 * FREQ_MUL; break;
 	};
 
 	/* Bottom of Band (MHz) */
-	switch (band) {
+	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
 	/* 0: 87.5 - 108 MHz (USA, Europe) */
-	case 0 : band_bottom = 87.5 * FREQ_MUL; break;
+	case 0:
+		band_bottom = 87.5 * FREQ_MUL; break;
 	/* 1: 76   - 108 MHz (Japan wide band) */
-	default: band_bottom = 76   * FREQ_MUL; break;
+	default:
+		band_bottom = 76   * FREQ_MUL; break;
 	/* 2: 76   -  90 MHz (Japan) */
-	case 2 : band_bottom = 76   * FREQ_MUL; break;
+	case 2:
+		band_bottom = 76   * FREQ_MUL; break;
 	};
 
 	/* read channel */
@@ -706,23 +713,29 @@
 	unsigned short chan;
 
 	/* Spacing (kHz) */
-	switch (space) {
+	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
 	/* 0: 200 kHz (USA, Australia) */
-	case 0 : spacing = 0.200 * FREQ_MUL; break;
+	case 0:
+		spacing = 0.200 * FREQ_MUL; break;
 	/* 1: 100 kHz (Europe, Japan) */
-	case 1 : spacing = 0.100 * FREQ_MUL; break;
+	case 1:
+		spacing = 0.100 * FREQ_MUL; break;
 	/* 2:  50 kHz */
-	default: spacing = 0.050 * FREQ_MUL; break;
+	default:
+		spacing = 0.050 * FREQ_MUL; break;
 	};
 
 	/* Bottom of Band (MHz) */
-	switch (band) {
+	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
 	/* 0: 87.5 - 108 MHz (USA, Europe) */
-	case 0 : band_bottom = 87.5 * FREQ_MUL; break;
+	case 0:
+		band_bottom = 87.5 * FREQ_MUL; break;
 	/* 1: 76   - 108 MHz (Japan wide band) */
-	default: band_bottom = 76   * FREQ_MUL; break;
+	default:
+		band_bottom = 76   * FREQ_MUL; break;
 	/* 2: 76   -  90 MHz (Japan) */
-	case 2 : band_bottom = 76   * FREQ_MUL; break;
+	case 2:
+		band_bottom = 76   * FREQ_MUL; break;
 	};
 
 	/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
@@ -1164,7 +1177,6 @@
  * si470x_v4l2_queryctrl - query control
  */
 static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
-/* HINT: the disabled controls are only here to satify kradio and such apps */
 	{
 		.id		= V4L2_CID_AUDIO_VOLUME,
 		.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -1175,18 +1187,6 @@
 		.default_value	= 15,
 	},
 	{
-		.id		= V4L2_CID_AUDIO_BALANCE,
-		.flags		= V4L2_CTRL_FLAG_DISABLED,
-	},
-	{
-		.id		= V4L2_CID_AUDIO_BASS,
-		.flags		= V4L2_CTRL_FLAG_DISABLED,
-	},
-	{
-		.id		= V4L2_CID_AUDIO_TREBLE,
-		.flags		= V4L2_CTRL_FLAG_DISABLED,
-	},
-	{
 		.id		= V4L2_CID_AUDIO_MUTE,
 		.type		= V4L2_CTRL_TYPE_BOOLEAN,
 		.name		= "Mute",
@@ -1195,10 +1195,6 @@
 		.step		= 1,
 		.default_value	= 1,
 	},
-	{
-		.id		= V4L2_CID_AUDIO_LOUDNESS,
-		.flags		= V4L2_CTRL_FLAG_DISABLED,
-	},
 };
 
 
@@ -1220,56 +1216,34 @@
 
 
 /*
- * si470x_vidioc_g_input - get input
- */
-static int si470x_vidioc_g_input(struct file *file, void *priv,
-		unsigned int *i)
-{
-	*i = 0;
-
-	return 0;
-}
-
-
-/*
- * si470x_vidioc_s_input - set input
- */
-static int si470x_vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-	int retval = 0;
-
-	/* safety checks */
-	if (i != 0)
-		retval = -EINVAL;
-
-	if (retval < 0)
-		printk(KERN_WARNING DRIVER_NAME
-			": set input failed with %d\n", retval);
-	return retval;
-}
-
-
-/*
  * si470x_vidioc_queryctrl - enumerate control items
  */
 static int si470x_vidioc_queryctrl(struct file *file, void *priv,
 		struct v4l2_queryctrl *qc)
 {
-	unsigned char i;
+	unsigned char i = 0;
 	int retval = -EINVAL;
 
-	/* safety checks */
-	if (!qc->id)
+	/* abort if qc->id is below V4L2_CID_BASE */
+	if (qc->id < V4L2_CID_BASE)
 		goto done;
 
+	/* search video control */
 	for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
 		if (qc->id == si470x_v4l2_queryctrl[i].id) {
 			memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
-			retval = 0;
+			retval = 0; /* found */
 			break;
 		}
 	}
 
+	/* disable unsupported base controls */
+	/* to satisfy kradio and such apps */
+	if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
+		qc->flags = V4L2_CTRL_FLAG_DISABLED;
+		retval = 0;
+	}
+
 done:
 	if (retval < 0)
 		printk(KERN_WARNING DRIVER_NAME
@@ -1360,44 +1334,13 @@
 static int si470x_vidioc_g_audio(struct file *file, void *priv,
 		struct v4l2_audio *audio)
 {
-	int retval = 0;
-
-	/* safety checks */
-	if (audio->index != 0) {
-		retval = -EINVAL;
-		goto done;
-	}
-
+	/* driver constants */
+	audio->index = 0;
 	strcpy(audio->name, "Radio");
 	audio->capability = V4L2_AUDCAP_STEREO;
+	audio->mode = 0;
 
-done:
-	if (retval < 0)
-		printk(KERN_WARNING DRIVER_NAME
-			": get audio failed with %d\n", retval);
-	return retval;
-}
-
-
-/*
- * si470x_vidioc_s_audio - set audio attributes
- */
-static int si470x_vidioc_s_audio(struct file *file, void *priv,
-		struct v4l2_audio *audio)
-{
-	int retval = 0;
-
-	/* safety checks */
-	if (audio->index != 0) {
-		retval = -EINVAL;
-		goto done;
-	}
-
-done:
-	if (retval < 0)
-		printk(KERN_WARNING DRIVER_NAME
-			": set audio failed with %d\n", retval);
-	return retval;
+	return 0;
 }
 
 
@@ -1415,7 +1358,7 @@
 		retval = -EIO;
 		goto done;
 	}
-	if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
+	if (tuner->index != 0) {
 		retval = -EINVAL;
 		goto done;
 	}
@@ -1424,8 +1367,13 @@
 	if (retval < 0)
 		goto done;
 
+	/* driver constants */
 	strcpy(tuner->name, "FM");
-	switch (band) {
+	tuner->type = V4L2_TUNER_RADIO;
+	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+
+	/* range limits */
+	switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
 	/* 0: 87.5 - 108 MHz (USA, Europe, default) */
 	default:
 		tuner->rangelow  =  87.5 * FREQ_MUL;
@@ -1442,14 +1390,18 @@
 		tuner->rangehigh =  90   * FREQ_MUL;
 		break;
 	};
-	tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-	tuner->capability = V4L2_TUNER_CAP_LOW;
 
-	/* Stereo indicator == Stereo (instead of Mono) */
+	/* stereo indicator == stereo (instead of mono) */
 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1)
-		tuner->audmode = V4L2_TUNER_MODE_STEREO;
+		tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 	else
+		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+	/* mono/stereo selector */
+	if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1)
 		tuner->audmode = V4L2_TUNER_MODE_MONO;
+	else
+		tuner->audmode = V4L2_TUNER_MODE_STEREO;
 
 	/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
 	tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI)
@@ -1474,23 +1426,28 @@
 		struct v4l2_tuner *tuner)
 {
 	struct si470x_device *radio = video_drvdata(file);
-	int retval = 0;
+	int retval = -EINVAL;
 
 	/* safety checks */
 	if (radio->disconnected) {
 		retval = -EIO;
 		goto done;
 	}
-	if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
-		retval = -EINVAL;
+	if (tuner->index != 0)
+		goto done;
+
+	/* mono/stereo selector */
+	switch (tuner->audmode) {
+	case V4L2_TUNER_MODE_MONO:
+		radio->registers[POWERCFG] |= POWERCFG_MONO;  /* force mono */
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+		radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
+		break;
+	default:
 		goto done;
 	}
 
-	if (tuner->audmode == V4L2_TUNER_MODE_MONO)
-		radio->registers[POWERCFG] |= POWERCFG_MONO;  /* force mono */
-	else
-		radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
-
 	retval = si470x_set_register(radio, POWERCFG);
 
 done:
@@ -1515,11 +1472,12 @@
 		retval = -EIO;
 		goto done;
 	}
-	if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+	if (freq->tuner != 0) {
 		retval = -EINVAL;
 		goto done;
 	}
 
+	freq->type = V4L2_TUNER_RADIO;
 	retval = si470x_get_freq(radio, &freq->frequency);
 
 done:
@@ -1544,7 +1502,7 @@
 		retval = -EIO;
 		goto done;
 	}
-	if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+	if (freq->tuner != 0) {
 		retval = -EINVAL;
 		goto done;
 	}
@@ -1573,7 +1531,7 @@
 		retval = -EIO;
 		goto done;
 	}
-	if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) {
+	if (seek->tuner != 0) {
 		retval = -EINVAL;
 		goto done;
 	}
@@ -1588,15 +1546,16 @@
 	return retval;
 }
 
+
+/*
+ * si470x_ioctl_ops - video device ioctl operations
+ */
 static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
 	.vidioc_querycap	= si470x_vidioc_querycap,
-	.vidioc_g_input		= si470x_vidioc_g_input,
-	.vidioc_s_input		= si470x_vidioc_s_input,
 	.vidioc_queryctrl	= si470x_vidioc_queryctrl,
 	.vidioc_g_ctrl		= si470x_vidioc_g_ctrl,
 	.vidioc_s_ctrl		= si470x_vidioc_s_ctrl,
 	.vidioc_g_audio		= si470x_vidioc_g_audio,
-	.vidioc_s_audio		= si470x_vidioc_s_audio,
 	.vidioc_g_tuner		= si470x_vidioc_g_tuner,
 	.vidioc_s_tuner		= si470x_vidioc_s_tuner,
 	.vidioc_g_frequency	= si470x_vidioc_g_frequency,
@@ -1604,14 +1563,15 @@
 	.vidioc_s_hw_freq_seek	= si470x_vidioc_s_hw_freq_seek,
 };
 
+
 /*
- * si470x_viddev_tamples - video device interface
+ * si470x_viddev_template - video device interface
  */
 static struct video_device si470x_viddev_template = {
 	.fops			= &si470x_fops,
-	.ioctl_ops 		= &si470x_ioctl_ops,
 	.name			= DRIVER_NAME,
 	.release		= video_device_release,
+	.ioctl_ops		= &si470x_ioctl_ops,
 };
 
 
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index f794f2d..e0eb4f3 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -29,43 +29,24 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
 #include <linux/videodev.h>
 #include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
 MODULE_AUTHOR("Maxim Yevtyushkin");
 MODULE_LICENSE("GPL");
 
-
-#define I2C_NAME(x) (x)->name
-
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 /* ----------------------------------------------------------------------- */
 
 struct adv7170 {
@@ -80,21 +61,12 @@
 	int sat;
 };
 
-#define   I2C_ADV7170        0xd4
-#define   I2C_ADV7171        0x54
-
-static char adv7170_name[] = "adv7170";
-static char adv7171_name[] = "adv7171";
-
 static char *inputs[] = { "pass_through", "play_back" };
 static char *norms[] = { "PAL", "NTSC" };
 
 /* ----------------------------------------------------------------------- */
 
-static inline int
-adv7170_write (struct i2c_client *client,
-	       u8                 reg,
-	       u8                 value)
+static inline int adv7170_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct adv7170 *encoder = i2c_get_clientdata(client);
 
@@ -102,17 +74,13 @@
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int
-adv7170_read (struct i2c_client *client,
-	      u8                 reg)
+static inline int adv7170_read(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int
-adv7170_write_block (struct i2c_client *client,
-		     const u8          *data,
-		     unsigned int       len)
+static int adv7170_write_block(struct i2c_client *client,
+		     const u8 *data, unsigned int len)
 {
 	int ret = -1;
 	u8 reg;
@@ -133,33 +101,25 @@
 				    encoder->reg[reg++] = data[1];
 				len -= 2;
 				data += 2;
-			} while (len >= 2 && data[0] == reg &&
-				 block_len < 32);
-			if ((ret = i2c_master_send(client, block_data,
-						   block_len)) < 0)
+			} while (len >= 2 && data[0] == reg && block_len < 32);
+			ret = i2c_master_send(client, block_data, block_len);
+			if (ret < 0)
 				break;
 		}
 	} else {
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			if ((ret = adv7170_write(client, reg,
-						 *data++)) < 0)
+			ret = adv7170_write(client, reg, *data++);
+			if (ret < 0)
 				break;
 			len -= 2;
 		}
 	}
-
 	return ret;
 }
 
 /* ----------------------------------------------------------------------- */
-// Output filter:  S-Video  Composite
-
-#define MR050       0x11	//0x09
-#define MR060       0x14	//0x0c
-
-//---------------------------------------------------------------------------
 
 #define TR0MODE     0x4c
 #define TR0RST	    0x80
@@ -167,7 +127,6 @@
 #define TR1CAPT	    0x00
 #define TR1PLAY	    0x00
 
-
 static const unsigned char init_NTSC[] = {
 	0x00, 0x10,		// MR0
 	0x01, 0x20,		// MR1
@@ -227,15 +186,11 @@
 };
 
 
-static int
-adv7170_command (struct i2c_client *client,
-		 unsigned int       cmd,
-		 void *             arg)
+static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	struct adv7170 *encoder = i2c_get_clientdata(client);
 
 	switch (cmd) {
-
 	case 0:
 #if 0
 		/* This is just for testing!!! */
@@ -254,18 +209,16 @@
 			     VIDEO_ENCODER_NTSC;
 		cap->inputs = 2;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case ENCODER_SET_NORM:
 	{
 		int iarg = *(int *) arg;
 
-		dprintk(1, KERN_DEBUG "%s_command: set norm %d",
-			I2C_NAME(client), iarg);
+		v4l_dbg(1, debug, client, "set norm %d\n", iarg);
 
 		switch (iarg) {
-
 		case VIDEO_MODE_NTSC:
 			adv7170_write_block(client, init_NTSC,
 					    sizeof(init_NTSC));
@@ -285,16 +238,13 @@
 			break;
 
 		default:
-			dprintk(1, KERN_ERR "%s: illegal norm: %d\n",
-			       I2C_NAME(client), iarg);
+			v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
 			return -EINVAL;
-
 		}
-		dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client),
-			norms[iarg]);
+		v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
 		encoder->norm = iarg;
-	}
 		break;
+	}
 
 	case ENCODER_SET_INPUT:
 	{
@@ -304,19 +254,17 @@
 		 *iarg = 1: input is from ZR36060
 		 *iarg = 2: color bar */
 
-		dprintk(1, KERN_DEBUG "%s_command: set input from %s\n",
-			I2C_NAME(client),
+		v4l_dbg(1, debug, client, "set input from %s\n",
 			iarg == 0 ? "decoder" : "ZR36060");
 
 		switch (iarg) {
-
 		case 0:
 			adv7170_write(client, 0x01, 0x20);
 			adv7170_write(client, 0x08, TR1CAPT);	/* TR1 */
 			adv7170_write(client, 0x02, 0x0e);	// Enable genlock
 			adv7170_write(client, 0x07, TR0MODE | TR0RST);
 			adv7170_write(client, 0x07, TR0MODE);
-			//udelay(10);
+			/* udelay(10); */
 			break;
 
 		case 1:
@@ -325,20 +273,17 @@
 			adv7170_write(client, 0x02, 0x08);
 			adv7170_write(client, 0x07, TR0MODE | TR0RST);
 			adv7170_write(client, 0x07, TR0MODE);
-			//udelay(10);
+			/* udelay(10); */
 			break;
 
 		default:
-			dprintk(1, KERN_ERR "%s: illegal input: %d\n",
-				I2C_NAME(client), iarg);
+			v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
 			return -EINVAL;
-
 		}
-		dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client),
-			inputs[iarg]);
+		v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
 		encoder->input = iarg;
-	}
 		break;
+	}
 
 	case ENCODER_SET_OUTPUT:
 	{
@@ -348,16 +293,16 @@
 		if (*iarg != 0) {
 			return -EINVAL;
 		}
-	}
 		break;
+	}
 
 	case ENCODER_ENABLE_OUTPUT:
 	{
 		int *iarg = arg;
 
 		encoder->enable = !!*iarg;
-	}
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -368,149 +313,67 @@
 
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] =
-    { I2C_ADV7170 >> 1, (I2C_ADV7170 >> 1) + 1,
-	I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1,
+static unsigned short normal_i2c[] = {
+	0xd4 >> 1, 0xd6 >> 1,	/* adv7170 IDs */
+	0x54 >> 1, 0x56 >> 1,	/* adv7171 IDs */
 	I2C_CLIENT_END
 };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver i2c_driver_adv7170;
-
-static int
-adv7170_detect_client (struct i2c_adapter *adapter,
-		       int                 address,
-		       int                 kind)
+static int adv7170_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-	int i;
-	struct i2c_client *client;
 	struct adv7170 *encoder;
-	char *dname;
-
-	dprintk(1,
-		KERN_INFO
-		"adv7170.c: detecting adv7170 client on address 0x%x\n",
-		address << 1);
+	int i;
 
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_adv7170;
-	if ((client->addr == I2C_ADV7170 >> 1) ||
-	    (client->addr == (I2C_ADV7170 >> 1) + 1)) {
-		dname = adv7170_name;
-	} else if ((client->addr == I2C_ADV7171 >> 1) ||
-		   (client->addr == (I2C_ADV7171 >> 1) + 1)) {
-		dname = adv7171_name;
-	} else {
-		/* We should never get here!!! */
-		kfree(client);
-		return 0;
-	}
-	strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
-	if (encoder == NULL) {
-		kfree(client);
+	if (encoder == NULL)
 		return -ENOMEM;
-	}
 	encoder->norm = VIDEO_MODE_NTSC;
 	encoder->input = 0;
 	encoder->enable = 1;
 	i2c_set_clientdata(client, encoder);
 
-	i = i2c_attach_client(client);
-	if (i) {
-		kfree(client);
-		kfree(encoder);
-		return i;
-	}
-
 	i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC));
 	if (i >= 0) {
 		i = adv7170_write(client, 0x07, TR0MODE | TR0RST);
 		i = adv7170_write(client, 0x07, TR0MODE);
 		i = adv7170_read(client, 0x12);
-		dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%02x\n",
-			I2C_NAME(client), i & 1, client->addr << 1);
+		v4l_dbg(1, debug, client, "revision %d\n", i & 1);
 	}
-	if (i < 0) {
-		dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n",
-		       I2C_NAME(client), i);
-	}
-
+	if (i < 0)
+		v4l_dbg(1, debug, client, "init error 0x%x\n", i);
 	return 0;
 }
 
-static int
-adv7170_attach_adapter (struct i2c_adapter *adapter)
+static int adv7170_remove(struct i2c_client *client)
 {
-	dprintk(1,
-		KERN_INFO
-		"adv7170.c: starting probe for adapter %s (0x%x)\n",
-		I2C_NAME(adapter), adapter->id);
-	return i2c_probe(adapter, &addr_data, &adv7170_detect_client);
-}
-
-static int
-adv7170_detach_client (struct i2c_client *client)
-{
-	struct adv7170 *encoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(encoder);
-	kfree(client);
-
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_adv7170 = {
-	.driver = {
-		.name = "adv7170",	/* name */
-	},
-
-	.id = I2C_DRIVERID_ADV7170,
-
-	.attach_adapter = adv7170_attach_adapter,
-	.detach_client = adv7170_detach_client,
-	.command = adv7170_command,
+static const struct i2c_device_id adv7170_id[] = {
+	{ "adv7170", 0 },
+	{ "adv7171", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, adv7170_id);
 
-static int __init
-adv7170_init (void)
-{
-	return i2c_add_driver(&i2c_driver_adv7170);
-}
-
-static void __exit
-adv7170_exit (void)
-{
-	i2c_del_driver(&i2c_driver_adv7170);
-}
-
-module_init(adv7170_init);
-module_exit(adv7170_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "adv7170",
+	.driverid = I2C_DRIVERID_ADV7170,
+	.command = adv7170_command,
+	.probe = adv7170_probe,
+	.remove = adv7170_remove,
+	.id_table = adv7170_id,
+};
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 8ee07a6..6008e84 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -25,43 +25,24 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
 #include <linux/videodev.h>
 #include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
 MODULE_AUTHOR("Dave Perks");
 MODULE_LICENSE("GPL");
 
-
-#define I2C_NAME(s) (s)->name
-
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 /* ----------------------------------------------------------------------- */
 
 struct adv7175 {
@@ -77,33 +58,23 @@
 #define   I2C_ADV7175        0xd4
 #define   I2C_ADV7176        0x54
 
-static char adv7175_name[] = "adv7175";
-static char adv7176_name[] = "adv7176";
-
 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
 static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
 
 /* ----------------------------------------------------------------------- */
 
-static inline int
-adv7175_write (struct i2c_client *client,
-	       u8                 reg,
-	       u8                 value)
+static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int
-adv7175_read (struct i2c_client *client,
-	      u8                 reg)
+static inline int adv7175_read(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int
-adv7175_write_block (struct i2c_client *client,
-		     const u8          *data,
-		     unsigned int       len)
+static int adv7175_write_block(struct i2c_client *client,
+		     const u8 *data, unsigned int len)
 {
 	int ret = -1;
 	u8 reg;
@@ -123,18 +94,17 @@
 				reg++;
 				len -= 2;
 				data += 2;
-			} while (len >= 2 && data[0] == reg &&
-				 block_len < 32);
-			if ((ret = i2c_master_send(client, block_data,
-						   block_len)) < 0)
+			} while (len >= 2 && data[0] == reg && block_len < 32);
+			ret = i2c_master_send(client, block_data, block_len);
+			if (ret < 0)
 				break;
 		}
 	} else {
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			if ((ret = adv7175_write(client, reg,
-						 *data++)) < 0)
+			ret = adv7175_write(client, reg, *data++);
+			if (ret < 0)
 				break;
 			len -= 2;
 		}
@@ -143,13 +113,11 @@
 	return ret;
 }
 
-static void
-set_subcarrier_freq (struct i2c_client *client,
-		     int                pass_through)
+static void set_subcarrier_freq(struct i2c_client *client, int pass_through)
 {
 	/* for some reason pass_through NTSC needs
 	 * a different sub-carrier freq to remain stable. */
-	if(pass_through)
+	if (pass_through)
 		adv7175_write(client, 0x02, 0x00);
 	else
 		adv7175_write(client, 0x02, 0x55);
@@ -160,12 +128,12 @@
 }
 
 /* ----------------------------------------------------------------------- */
-// Output filter:  S-Video  Composite
+/* Output filter:  S-Video  Composite */
 
-#define MR050       0x11	//0x09
-#define MR060       0x14	//0x0c
+#define MR050       0x11	/* 0x09 */
+#define MR060       0x14	/* 0x0c */
 
-//---------------------------------------------------------------------------
+/* ----------------------------------------------------------------------- */
 
 #define TR0MODE     0x46
 #define TR0RST	    0x80
@@ -216,15 +184,11 @@
 	0x06, 0x1a,		/* subc. phase */
 };
 
-static int
-adv7175_command (struct i2c_client *client,
-		 unsigned int       cmd,
-		 void              *arg)
+static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	struct adv7175 *encoder = i2c_get_clientdata(client);
 
 	switch (cmd) {
-
 	case 0:
 		/* This is just for testing!!! */
 		adv7175_write_block(client, init_common,
@@ -242,15 +206,14 @@
 			     VIDEO_ENCODER_SECAM; /* well, hacky */
 		cap->inputs = 2;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case ENCODER_SET_NORM:
 	{
 		int iarg = *(int *) arg;
 
 		switch (iarg) {
-
 		case VIDEO_MODE_NTSC:
 			adv7175_write_block(client, init_ntsc,
 					    sizeof(init_ntsc));
@@ -284,16 +247,13 @@
 			adv7175_write(client, 0x07, TR0MODE);
 			break;
 		default:
-			dprintk(1, KERN_ERR "%s: illegal norm: %d\n",
-				I2C_NAME(client), iarg);
+			v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
 			return -EINVAL;
-
 		}
-		dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client),
-			norms[iarg]);
+		v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
 		encoder->norm = iarg;
-	}
 		break;
+	}
 
 	case ENCODER_SET_INPUT:
 	{
@@ -304,7 +264,6 @@
 		 *iarg = 2: color bar */
 
 		switch (iarg) {
-
 		case 0:
 			adv7175_write(client, 0x01, 0x00);
 
@@ -331,7 +290,7 @@
 			adv7175_write(client, 0x0d, 0x49);
 			adv7175_write(client, 0x07, TR0MODE | TR0RST);
 			adv7175_write(client, 0x07, TR0MODE);
-			//udelay(10);
+			/* udelay(10); */
 			break;
 
 		case 2:
@@ -343,39 +302,35 @@
 			adv7175_write(client, 0x0d, 0x49);
 			adv7175_write(client, 0x07, TR0MODE | TR0RST);
 			adv7175_write(client, 0x07, TR0MODE);
-			//udelay(10);
+			/* udelay(10); */
 			break;
 
 		default:
-			dprintk(1, KERN_ERR "%s: illegal input: %d\n",
-				I2C_NAME(client), iarg);
+			v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
 			return -EINVAL;
-
 		}
-		dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client),
-			inputs[iarg]);
+		v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
 		encoder->input = iarg;
-	}
 		break;
+	}
 
 	case ENCODER_SET_OUTPUT:
 	{
 		int *iarg = arg;
 
 		/* not much choice of outputs */
-		if (*iarg != 0) {
+		if (*iarg != 0)
 			return -EINVAL;
-		}
-	}
 		break;
+	}
 
 	case ENCODER_ENABLE_OUTPUT:
 	{
 		int *iarg = arg;
 
 		encoder->enable = !!*iarg;
-	}
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -390,145 +345,67 @@
  * Generic i2c probe
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
-static unsigned short normal_i2c[] =
-    { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
+static unsigned short normal_i2c[] = {
+	I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
 	I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
 	I2C_CLIENT_END
 };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver i2c_driver_adv7175;
-
-static int
-adv7175_detect_client (struct i2c_adapter *adapter,
-		       int                 address,
-		       int                 kind)
+static int adv7175_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	int i;
-	struct i2c_client *client;
 	struct adv7175 *encoder;
-	char *dname;
-
-	dprintk(1,
-		KERN_INFO
-		"adv7175.c: detecting adv7175 client on address 0x%x\n",
-		address << 1);
 
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_adv7175;
-	if ((client->addr == I2C_ADV7175 >> 1) ||
-	    (client->addr == (I2C_ADV7175 >> 1) + 1)) {
-		dname = adv7175_name;
-	} else if ((client->addr == I2C_ADV7176 >> 1) ||
-		   (client->addr == (I2C_ADV7176 >> 1) + 1)) {
-		dname = adv7176_name;
-	} else {
-		/* We should never get here!!! */
-		kfree(client);
-		return 0;
-	}
-	strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
-	if (encoder == NULL) {
-		kfree(client);
+	if (encoder == NULL)
 		return -ENOMEM;
-	}
 	encoder->norm = VIDEO_MODE_PAL;
 	encoder->input = 0;
 	encoder->enable = 1;
 	i2c_set_clientdata(client, encoder);
 
-	i = i2c_attach_client(client);
-	if (i) {
-		kfree(client);
-		kfree(encoder);
-		return i;
-	}
-
 	i = adv7175_write_block(client, init_common, sizeof(init_common));
 	if (i >= 0) {
 		i = adv7175_write(client, 0x07, TR0MODE | TR0RST);
 		i = adv7175_write(client, 0x07, TR0MODE);
 		i = adv7175_read(client, 0x12);
-		dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%x\n",
-			I2C_NAME(client), i & 1, client->addr << 1);
+		v4l_dbg(1, debug, client, "revision %d\n", i & 1);
 	}
-	if (i < 0) {
-		dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n",
-			I2C_NAME(client), i);
-	}
-
+	if (i < 0)
+		v4l_dbg(1, debug, client, "init error 0x%x\n", i);
 	return 0;
 }
 
-static int
-adv7175_attach_adapter (struct i2c_adapter *adapter)
+static int adv7175_remove(struct i2c_client *client)
 {
-	dprintk(1,
-		KERN_INFO
-		"adv7175.c: starting probe for adapter %s (0x%x)\n",
-		I2C_NAME(adapter), adapter->id);
-	return i2c_probe(adapter, &addr_data, &adv7175_detect_client);
-}
-
-static int
-adv7175_detach_client (struct i2c_client *client)
-{
-	struct adv7175 *encoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(encoder);
-	kfree(client);
-
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_adv7175 = {
-	.driver = {
-		.name = "adv7175",	/* name */
-	},
-
-	.id = I2C_DRIVERID_ADV7175,
-
-	.attach_adapter = adv7175_attach_adapter,
-	.detach_client = adv7175_detach_client,
-	.command = adv7175_command,
+static const struct i2c_device_id adv7175_id[] = {
+	{ "adv7175", 0 },
+	{ "adv7176", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, adv7175_id);
 
-static int __init
-adv7175_init (void)
-{
-	return i2c_add_driver(&i2c_driver_adv7175);
-}
-
-static void __exit
-adv7175_exit (void)
-{
-	i2c_del_driver(&i2c_driver_adv7175);
-}
-
-module_init(adv7175_init);
-module_exit(adv7175_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "adv7175",
+	.driverid = I2C_DRIVERID_ADV7175,
+	.command = adv7175_command,
+	.probe = adv7175_probe,
+	.remove = adv7175_remove,
+	.id_table = adv7175_id,
+};
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
index 5f07a8a..d60123b 100644
--- a/drivers/media/video/au0828/au0828-cards.c
+++ b/drivers/media/video/au0828/au0828-cards.c
@@ -90,6 +90,7 @@
 	case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
 	case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
 	case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */
+	case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
 	case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
 	case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
 		break;
@@ -185,7 +186,7 @@
 }
 
 /* table of devices that work with this driver */
-struct usb_device_id au0828_usb_id_table [] = {
+struct usb_device_id au0828_usb_id_table[] = {
 	{ USB_DEVICE(0x2040, 0x7200),
 		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 	{ USB_DEVICE(0x2040, 0x7240),
@@ -198,6 +199,8 @@
 		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 	{ USB_DEVICE(0x2040, 0x721b),
 		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+	{ USB_DEVICE(0x2040, 0x721e),
+		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 	{ USB_DEVICE(0x2040, 0x721f),
 		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 	{ USB_DEVICE(0x2040, 0x7280),
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
index d856de9..5765e86 100644
--- a/drivers/media/video/au0828/au0828-core.c
+++ b/drivers/media/video/au0828/au0828-core.c
@@ -91,7 +91,8 @@
 		status = usb_control_msg(dev->usbdev,
 				usb_sndctrlpipe(dev->usbdev, 0),
 				request,
-				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				USB_DIR_OUT | USB_TYPE_VENDOR |
+					USB_RECIP_DEVICE,
 				value, index,
 				cp, size, 1000);
 
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
index f0fcdb4..a882cf5 100644
--- a/drivers/media/video/au0828/au0828-dvb.c
+++ b/drivers/media/video/au0828/au0828-dvb.c
@@ -173,7 +173,8 @@
 		purb->status = -EINPROGRESS;
 		usb_fill_bulk_urb(purb,
 				  dev->usbdev,
-				  usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
+				  usb_rcvbulkpipe(dev->usbdev,
+					_AU0828_BULKPIPE),
 				  purb->transfer_buffer,
 				  URB_BUFSIZE,
 				  urb_completion,
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index ddd2a79..a07b7b8 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -29,44 +29,25 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
 #include <linux/videodev.h>
 #include <linux/video_decoder.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
 MODULE_AUTHOR("Mike Bernson & Dave Perks");
 MODULE_LICENSE("GPL");
 
-
-#define I2C_NAME(s) (s)->name
-
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 /* ----------------------------------------------------------------------- */
 
 struct bt819 {
@@ -97,14 +78,9 @@
 	{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
 };
 
-#define   I2C_BT819        0x8a
-
 /* ----------------------------------------------------------------------- */
 
-static inline int
-bt819_write (struct i2c_client *client,
-	     u8                 reg,
-	     u8                 value)
+static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct bt819 *decoder = i2c_get_clientdata(client);
 
@@ -112,24 +88,15 @@
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int
-bt819_setbit (struct i2c_client *client,
-	      u8                 reg,
-	      u8                 bit,
-	      u8                 value)
+static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
 {
 	struct bt819 *decoder = i2c_get_clientdata(client);
 
 	return bt819_write(client, reg,
-			   (decoder->
-			    reg[reg] & ~(1 << bit)) |
-			    (value ? (1 << bit) : 0));
+		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
 }
 
-static int
-bt819_write_block (struct i2c_client *client,
-		   const u8          *data,
-		   unsigned int       len)
+static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
 {
 	int ret = -1;
 	u8 reg;
@@ -150,10 +117,9 @@
 				    decoder->reg[reg++] = data[1];
 				len -= 2;
 				data += 2;
-			} while (len >= 2 && data[0] == reg &&
-				 block_len < 32);
-			if ((ret = i2c_master_send(client, block_data,
-						   block_len)) < 0)
+			} while (len >= 2 && data[0] == reg && block_len < 32);
+			ret = i2c_master_send(client, block_data, block_len);
+			if (ret < 0)
 				break;
 		}
 	} else {
@@ -169,20 +135,17 @@
 	return ret;
 }
 
-static inline int
-bt819_read (struct i2c_client *client,
-	    u8                 reg)
+static inline int bt819_read(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int
-bt819_init (struct i2c_client *client)
+static int bt819_init(struct i2c_client *client)
 {
 	struct bt819 *decoder = i2c_get_clientdata(client);
 
 	static unsigned char init[] = {
-		//0x1f, 0x00,     /* Reset */
+		/*0x1f, 0x00,*/     /* Reset */
 		0x01, 0x59,	/* 0x01 input format */
 		0x02, 0x00,	/* 0x02 temporal decimation */
 		0x03, 0x12,	/* 0x03 Cropping msb */
@@ -218,12 +181,10 @@
 	struct timing *timing = &timing_data[decoder->norm];
 
 	init[0x03 * 2 - 1] =
-	    (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
-						       vactive >> 8) &
-						      0x03) << 4) |
-	    (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
-						      hactive >> 8) &
-						     0x03);
+	    (((timing->vdelay >> 8) & 0x03) << 6) |
+	    (((timing->vactive >> 8) & 0x03) << 4) |
+	    (((timing->hdelay >> 8) & 0x03) << 2) |
+	    ((timing->hactive >> 8) & 0x03);
 	init[0x04 * 2 - 1] = timing->vdelay & 0xff;
 	init[0x05 * 2 - 1] = timing->vactive & 0xff;
 	init[0x06 * 2 - 1] = timing->hdelay & 0xff;
@@ -238,27 +199,22 @@
 
 	/* init */
 	return bt819_write_block(client, init, sizeof(init));
-
 }
 
 /* ----------------------------------------------------------------------- */
 
-static int
-bt819_command (struct i2c_client *client,
-	       unsigned int       cmd,
-	       void              *arg)
+static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	int temp;
 
 	struct bt819 *decoder = i2c_get_clientdata(client);
 
-	if (!decoder->initialized) {	// First call to bt819_init could be
-		bt819_init(client);	// without #FRST = 0
+	if (!decoder->initialized) {	/* First call to bt819_init could be */
+		bt819_init(client);	/* without #FRST = 0 */
 		decoder->initialized = 1;
 	}
 
 	switch (cmd) {
-
 	case 0:
 		/* This is just for testing!!! */
 		bt819_init(client);
@@ -274,8 +230,8 @@
 			     VIDEO_DECODER_CCIR;
 		cap->inputs = 8;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case DECODER_GET_STATUS:
 	{
@@ -285,9 +241,9 @@
 
 		status = bt819_read(client, 0x00);
 		res = 0;
-		if ((status & 0x80)) {
+		if ((status & 0x80))
 			res |= DECODER_STATUS_GOOD;
-		}
+
 		switch (decoder->norm) {
 		case VIDEO_MODE_NTSC:
 			res |= DECODER_STATUS_NTSC;
@@ -297,28 +253,25 @@
 			break;
 		default:
 		case VIDEO_MODE_AUTO:
-			if ((status & 0x10)) {
+			if ((status & 0x10))
 				res |= DECODER_STATUS_PAL;
-			} else {
+			else
 				res |= DECODER_STATUS_NTSC;
-			}
 			break;
 		}
 		res |= DECODER_STATUS_COLOR;
 		*iarg = res;
 
-		dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client),
-			*iarg);
-	}
+		v4l_dbg(1, debug, client, "get status %x\n", *iarg);
 		break;
+	}
 
 	case DECODER_SET_NORM:
 	{
 		int *iarg = arg;
 		struct timing *timing = NULL;
 
-		dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client),
-			*iarg);
+		v4l_dbg(1, debug, client, "set norm %x\n", *iarg);
 
 		switch (*iarg) {
 		case VIDEO_MODE_NTSC:
@@ -327,7 +280,7 @@
 			bt819_setbit(client, 0x01, 5, 0);
 			bt819_write(client, 0x18, 0x68);
 			bt819_write(client, 0x19, 0x5d);
-			//bt819_setbit(client, 0x1a,  5, 1);
+			/* bt819_setbit(client, 0x1a,  5, 1); */
 			timing = &timing_data[VIDEO_MODE_NTSC];
 			break;
 		case VIDEO_MODE_PAL:
@@ -336,7 +289,7 @@
 			bt819_setbit(client, 0x01, 5, 1);
 			bt819_write(client, 0x18, 0x7f);
 			bt819_write(client, 0x19, 0x72);
-			//bt819_setbit(client, 0x1a,  5, 0);
+			/* bt819_setbit(client, 0x1a,  5, 0); */
 			timing = &timing_data[VIDEO_MODE_PAL];
 			break;
 		case VIDEO_MODE_AUTO:
@@ -344,10 +297,7 @@
 			bt819_setbit(client, 0x01, 1, 0);
 			break;
 		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: unsupported norm %d\n",
-				I2C_NAME(client), *iarg);
+			v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg);
 			return -EINVAL;
 		}
 
@@ -366,19 +316,17 @@
 		}
 
 		decoder->norm = *iarg;
-	}
 		break;
+	}
 
 	case DECODER_SET_INPUT:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client),
-			*iarg);
+		v4l_dbg(1, debug, client, "set input %x\n", *iarg);
 
-		if (*iarg < 0 || *iarg > 7) {
+		if (*iarg < 0 || *iarg > 7)
 			return -EINVAL;
-		}
 
 		if (decoder->input != *iarg) {
 			decoder->input = *iarg;
@@ -391,52 +339,42 @@
 				bt819_setbit(client, 0x1a, 1, 0);
 			}
 		}
-	}
 		break;
+	}
 
 	case DECODER_SET_OUTPUT:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client),
-			*iarg);
+		v4l_dbg(1, debug, client, "set output %x\n", *iarg);
 
 		/* not much choice of outputs */
-		if (*iarg != 0) {
+		if (*iarg != 0)
 			return -EINVAL;
-		}
-	}
 		break;
+	}
 
 	case DECODER_ENABLE_OUTPUT:
 	{
 		int *iarg = arg;
 		int enable = (*iarg != 0);
 
-		dprintk(1, KERN_INFO "%s: enable output %x\n",
-			I2C_NAME(client), *iarg);
+		v4l_dbg(1, debug, client, "enable output %x\n", *iarg);
 
 		if (decoder->enable != enable) {
 			decoder->enable = enable;
-
-			if (decoder->enable) {
-				bt819_setbit(client, 0x16, 7, 0);
-			} else {
-				bt819_setbit(client, 0x16, 7, 1);
-			}
+			bt819_setbit(client, 0x16, 7, !enable);
 		}
-	}
 		break;
+	}
 
 	case DECODER_SET_PICTURE:
 	{
 		struct video_picture *pic = arg;
 
-		dprintk(1,
-			KERN_INFO
-			"%s: set picture brightness %d contrast %d colour %d\n",
-			I2C_NAME(client), pic->brightness, pic->contrast,
-			pic->colour);
+		v4l_dbg(1, debug, client,
+			"set picture brightness %d contrast %d colour %d\n",
+			pic->brightness, pic->contrast, pic->colour);
 
 
 		if (decoder->bright != pic->brightness) {
@@ -474,8 +412,8 @@
 			bt819_write(client, 0x0f,
 				    128 - (decoder->hue >> 8));
 		}
-	}
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -486,55 +424,44 @@
 
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = {
-	I2C_BT819 >> 1,
-	I2C_CLIENT_END,
-};
+static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver i2c_driver_bt819;
-
-static int
-bt819_detect_client (struct i2c_adapter *adapter,
-		     int                 address,
-		     int                 kind)
+static int bt819_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-	int i, id;
+	int i, ver;
 	struct bt819 *decoder;
-	struct i2c_client *client;
-
-	dprintk(1,
-		KERN_INFO
-		"bt819: detecting bt819 client on address 0x%x\n",
-		address << 1);
+	const char *name;
 
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_bt819;
+	ver = bt819_read(client, 0x17);
+	switch (ver & 0xf0) {
+	case 0x70:
+		name = "bt819a";
+		break;
+	case 0x60:
+		name = "bt817a";
+		break;
+	case 0x20:
+		name = "bt815a";
+		break;
+	default:
+		v4l_dbg(1, debug, client,
+			"unknown chip version 0x%02x\n", ver);
+		return -ENODEV;
+	}
+
+	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
+			client->addr << 1, client->adapter->name);
 
 	decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
-	if (decoder == NULL) {
-		kfree(client);
+	if (decoder == NULL)
 		return -ENOMEM;
-	}
 	decoder->norm = VIDEO_MODE_NTSC;
 	decoder->input = 0;
 	decoder->enable = 1;
@@ -545,97 +472,33 @@
 	decoder->initialized = 0;
 	i2c_set_clientdata(client, decoder);
 
-	id = bt819_read(client, 0x17);
-	switch (id & 0xf0) {
-	case 0x70:
-		strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
-		break;
-	case 0x60:
-		strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
-		break;
-	case 0x20:
-		strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
-		break;
-	default:
-		dprintk(1,
-			KERN_ERR
-			"bt819: unknown chip version 0x%x (ver 0x%x)\n",
-			id & 0xf0, id & 0x0f);
-		kfree(decoder);
-		kfree(client);
-		return 0;
-	}
-
-	i = i2c_attach_client(client);
-	if (i) {
-		kfree(client);
-		kfree(decoder);
-		return i;
-	}
-
 	i = bt819_init(client);
-	if (i < 0) {
-		dprintk(1, KERN_ERR "%s_attach: init status %d\n",
-			I2C_NAME(client), i);
-	} else {
-		dprintk(1,
-			KERN_INFO
-			"%s_attach: chip version 0x%x at address 0x%x\n",
-			I2C_NAME(client), id & 0x0f,
-			client->addr << 1);
-	}
-
+	if (i < 0)
+		v4l_dbg(1, debug, client, "init status %d\n", i);
 	return 0;
 }
 
-static int
-bt819_attach_adapter (struct i2c_adapter *adapter)
+static int bt819_remove(struct i2c_client *client)
 {
-	return i2c_probe(adapter, &addr_data, &bt819_detect_client);
-}
-
-static int
-bt819_detach_client (struct i2c_client *client)
-{
-	struct bt819 *decoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(decoder);
-	kfree(client);
-
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_bt819 = {
-	.driver = {
-		.name = "bt819",
-	},
-
-	.id = I2C_DRIVERID_BT819,
-
-	.attach_adapter = bt819_attach_adapter,
-	.detach_client = bt819_detach_client,
-	.command = bt819_command,
+static const struct i2c_device_id bt819_id[] = {
+	{ "bt819a", 0 },
+	{ "bt817a", 0 },
+	{ "bt815a", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, bt819_id);
 
-static int __init
-bt819_init_module (void)
-{
-	return i2c_add_driver(&i2c_driver_bt819);
-}
-
-static void __exit
-bt819_exit (void)
-{
-	i2c_del_driver(&i2c_driver_bt819);
-}
-
-module_init(bt819_init_module);
-module_exit(bt819_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "bt819",
+	.driverid = I2C_DRIVERID_BT819,
+	.command = bt819_command,
+	.probe = bt819_probe,
+	.remove = bt819_remove,
+	.id_table = bt819_id,
+};
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index ab2ce4d..4213867 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -29,43 +29,24 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/video_encoder.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
 #include <linux/videodev.h>
+#include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
 MODULE_AUTHOR("Mike Bernson & Dave Perks");
 MODULE_LICENSE("GPL");
 
-
-#define I2C_NAME(s) (s)->name
-
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 /* ----------------------------------------------------------------------- */
 
 #define BT856_REG_OFFSET	0xDA
@@ -78,14 +59,9 @@
 	int enable;
 };
 
-#define   I2C_BT856        0x88
-
 /* ----------------------------------------------------------------------- */
 
-static inline int
-bt856_write (struct i2c_client *client,
-	     u8                 reg,
-	     u8                 value)
+static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct bt856 *encoder = i2c_get_clientdata(client);
 
@@ -93,46 +69,36 @@
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int
-bt856_setbit (struct i2c_client *client,
-	      u8                 reg,
-	      u8                 bit,
-	      u8                 value)
+static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
 {
 	struct bt856 *encoder = i2c_get_clientdata(client);
 
 	return bt856_write(client, reg,
-			   (encoder->
-			    reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
-			    (value ? (1 << bit) : 0));
+		(encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
+				(value ? (1 << bit) : 0));
 }
 
-static void
-bt856_dump (struct i2c_client *client)
+static void bt856_dump(struct i2c_client *client)
 {
 	int i;
 	struct bt856 *encoder = i2c_get_clientdata(client);
 
-	printk(KERN_INFO "%s: register dump:", I2C_NAME(client));
+	v4l_info(client, "register dump:\n");
 	for (i = 0; i < BT856_NR_REG; i += 2)
-		printk(" %02x", encoder->reg[i]);
-	printk("\n");
+		printk(KERN_CONT " %02x", encoder->reg[i]);
+	printk(KERN_CONT "\n");
 }
 
 /* ----------------------------------------------------------------------- */
 
-static int
-bt856_command (struct i2c_client *client,
-	       unsigned int       cmd,
-	       void              *arg)
+static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	struct bt856 *encoder = i2c_get_clientdata(client);
 
 	switch (cmd) {
-
 	case 0:
 		/* This is just for testing!!! */
-		dprintk(1, KERN_INFO "bt856: init\n");
+		v4l_dbg(1, debug, client, "init\n");
 		bt856_write(client, 0xdc, 0x18);
 		bt856_write(client, 0xda, 0);
 		bt856_write(client, 0xde, 0);
@@ -142,7 +108,6 @@
 		bt856_setbit(client, 0xdc, 4, 1);
 
 		switch (encoder->norm) {
-
 		case VIDEO_MODE_NTSC:
 			bt856_setbit(client, 0xdc, 2, 0);
 			break;
@@ -163,26 +128,23 @@
 	{
 		struct video_encoder_capability *cap = arg;
 
-		dprintk(1, KERN_INFO "%s: get capabilities\n",
-			I2C_NAME(client));
+		v4l_dbg(1, debug, client, "get capabilities\n");
 
 		cap->flags = VIDEO_ENCODER_PAL |
 			     VIDEO_ENCODER_NTSC |
 			     VIDEO_ENCODER_CCIR;
 		cap->inputs = 2;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case ENCODER_SET_NORM:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_INFO "%s: set norm %d\n", I2C_NAME(client),
-			*iarg);
+		v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
 
 		switch (*iarg) {
-
 		case VIDEO_MODE_NTSC:
 			bt856_setbit(client, 0xdc, 2, 0);
 			break;
@@ -195,27 +157,23 @@
 
 		default:
 			return -EINVAL;
-
 		}
 		encoder->norm = *iarg;
 		if (debug != 0)
 			bt856_dump(client);
-	}
 		break;
+	}
 
 	case ENCODER_SET_INPUT:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_INFO "%s: set input %d\n", I2C_NAME(client),
-			*iarg);
+		v4l_dbg(1, debug, client, "set input %d\n", *iarg);
 
 		/* We only have video bus.
 		 * iarg = 0: input is from bt819
 		 * iarg = 1: input is from ZR36060 */
-
 		switch (*iarg) {
-
 		case 0:
 			bt856_setbit(client, 0xde, 4, 0);
 			bt856_setbit(client, 0xde, 3, 1);
@@ -234,27 +192,24 @@
 			break;
 		default:
 			return -EINVAL;
-
 		}
 
 		if (debug != 0)
 			bt856_dump(client);
-	}
 		break;
+	}
 
 	case ENCODER_SET_OUTPUT:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_INFO "%s: set output %d\n", I2C_NAME(client),
-			*iarg);
+		v4l_dbg(1, debug, client, "set output %d\n", *iarg);
 
 		/* not much choice of outputs */
-		if (*iarg != 0) {
+		if (*iarg != 0)
 			return -EINVAL;
-		}
-	}
 		break;
+	}
 
 	case ENCODER_ENABLE_OUTPUT:
 	{
@@ -262,10 +217,9 @@
 
 		encoder->enable = !!*iarg;
 
-		dprintk(1, KERN_INFO "%s: enable output %d\n",
-			I2C_NAME(client), encoder->enable);
-	}
+		v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -276,64 +230,29 @@
 
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver i2c_driver_bt856;
-
-static int
-bt856_detect_client (struct i2c_adapter *adapter,
-		     int                 address,
-		     int                 kind)
+static int bt856_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-	int i;
-	struct i2c_client *client;
 	struct bt856 *encoder;
 
-	dprintk(1,
-		KERN_INFO
-		"bt856.c: detecting bt856 client on address 0x%x\n",
-		address << 1);
-
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_bt856;
-	strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
-	if (encoder == NULL) {
-		kfree(client);
+	if (encoder == NULL)
 		return -ENOMEM;
-	}
 	encoder->norm = VIDEO_MODE_NTSC;
 	encoder->enable = 1;
 	i2c_set_clientdata(client, encoder);
 
-	i = i2c_attach_client(client);
-	if (i) {
-		kfree(client);
-		kfree(encoder);
-		return i;
-	}
-
 	bt856_write(client, 0xdc, 0x18);
 	bt856_write(client, 0xda, 0);
 	bt856_write(client, 0xde, 0);
@@ -359,65 +278,26 @@
 
 	if (debug != 0)
 		bt856_dump(client);
-
-	dprintk(1, KERN_INFO "%s_attach: at address 0x%x\n", I2C_NAME(client),
-		client->addr << 1);
-
 	return 0;
 }
 
-static int
-bt856_attach_adapter (struct i2c_adapter *adapter)
+static int bt856_remove(struct i2c_client *client)
 {
-	dprintk(1,
-		KERN_INFO
-		"bt856.c: starting probe for adapter %s (0x%x)\n",
-		I2C_NAME(adapter), adapter->id);
-	return i2c_probe(adapter, &addr_data, &bt856_detect_client);
-}
-
-static int
-bt856_detach_client (struct i2c_client *client)
-{
-	struct bt856 *encoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(encoder);
-	kfree(client);
-
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver i2c_driver_bt856 = {
-	.driver = {
-		.name = "bt856",
-	},
-
-	.id = I2C_DRIVERID_BT856,
-
-	.attach_adapter = bt856_attach_adapter,
-	.detach_client = bt856_detach_client,
-	.command = bt856_command,
+static const struct i2c_device_id bt856_id[] = {
+	{ "bt856", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, bt856_id);
 
-static int __init
-bt856_init (void)
-{
-	return i2c_add_driver(&i2c_driver_bt856);
-}
-
-static void __exit
-bt856_exit (void)
-{
-	i2c_del_driver(&i2c_driver_bt856);
-}
-
-module_init(bt856_init);
-module_exit(bt856_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "bt856",
+	.driverid = I2C_DRIVERID_BT856,
+	.command = bt856_command,
+	.probe = bt856_probe,
+	.remove = bt856_remove,
+	.id_table = bt856_id,
+};
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
index 96b4155..596f9e2 100644
--- a/drivers/media/video/bt866.c
+++ b/drivers/media/video/bt866.c
@@ -29,42 +29,28 @@
 */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/sched.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-
-#include <linux/videodev.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
 #include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
+MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
+MODULE_AUTHOR("Mike Bernson & Dave Perks");
 MODULE_LICENSE("GPL");
 
-#define	BT866_DEVNAME	"bt866"
-#define I2C_BT866	0x88
-
-MODULE_LICENSE("GPL");
-
-#define DEBUG(x)		/* Debug driver */
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 /* ----------------------------------------------------------------------- */
 
 struct bt866 {
-	struct i2c_client *i2c;
-	int addr;
-	unsigned char reg[256];
+	u8 reg[256];
 
 	int norm;
 	int enable;
@@ -74,20 +60,45 @@
 	int sat;
 };
 
-static int bt866_write(struct bt866 *dev,
-			unsigned char subaddr, unsigned char data);
-
-static int bt866_do_command(struct bt866 *encoder,
-			unsigned int cmd, void *arg)
+static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data)
 {
+	struct bt866 *encoder = i2c_get_clientdata(client);
+	u8 buffer[2];
+	int err;
+
+	buffer[0] = subaddr;
+	buffer[1] = data;
+
+	encoder->reg[subaddr] = data;
+
+	v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data);
+
+	for (err = 0; err < 3;) {
+		if (i2c_master_send(client, buffer, 2) == 2)
+			break;
+		err++;
+		v4l_warn(client, "error #%d writing to 0x%02x\n",
+				err, subaddr);
+		schedule_timeout_interruptible(msecs_to_jiffies(100));
+	}
+	if (err == 3) {
+		v4l_warn(client, "giving up\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+	struct bt866 *encoder = i2c_get_clientdata(client);
+
 	switch (cmd) {
 	case ENCODER_GET_CAPABILITIES:
 	{
 		struct video_encoder_capability *cap = arg;
 
-		DEBUG(printk
-		      (KERN_INFO "%s: get capabilities\n",
-		       encoder->i2c->name));
+		v4l_dbg(1, debug, client, "get capabilities\n");
 
 		cap->flags
 			= VIDEO_ENCODER_PAL
@@ -95,18 +106,16 @@
 			| VIDEO_ENCODER_CCIR;
 		cap->inputs = 2;
 		cap->outputs = 1;
+		break;
 	}
-	break;
 
 	case ENCODER_SET_NORM:
 	{
 		int *iarg = arg;
 
-		DEBUG(printk(KERN_INFO "%s: set norm %d\n",
-			     encoder->i2c->name, *iarg));
+		v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
 
 		switch (*iarg) {
-
 		case VIDEO_MODE_NTSC:
 			break;
 
@@ -115,11 +124,10 @@
 
 		default:
 			return -EINVAL;
-
 		}
 		encoder->norm = *iarg;
+		break;
 	}
-	break;
 
 	case ENCODER_SET_INPUT:
 	{
@@ -155,7 +163,7 @@
 		u8 val;
 
 		for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
-			bt866_write(encoder, init[i], init[i+1]);
+			bt866_write(client, init[i], init[i+1]);
 
 		val = encoder->reg[0xdc];
 
@@ -164,17 +172,16 @@
 		else
 			val &= ~0x40; /* !CBSWAP */
 
-		bt866_write(encoder, 0xdc, val);
+		bt866_write(client, 0xdc, val);
 
 		val = encoder->reg[0xcc];
 		if (*iarg == 2)
 			val |= 0x01; /* OSDBAR */
 		else
 			val &= ~0x01; /* !OSDBAR */
-		bt866_write(encoder, 0xcc, val);
+		bt866_write(client, 0xcc, val);
 
-		DEBUG(printk(KERN_INFO "%s: set input %d\n",
-			     encoder->i2c->name, *iarg));
+		v4l_dbg(1, debug, client, "set input %d\n", *iarg);
 
 		switch (*iarg) {
 		case 0:
@@ -183,48 +190,44 @@
 			break;
 		default:
 			return -EINVAL;
-
 		}
+		break;
 	}
-	break;
 
 	case ENCODER_SET_OUTPUT:
 	{
 		int *iarg = arg;
 
-		DEBUG(printk(KERN_INFO "%s: set output %d\n",
-			     encoder->i2c->name, *iarg));
+		v4l_dbg(1, debug, client, "set output %d\n", *iarg);
 
 		/* not much choice of outputs */
 		if (*iarg != 0)
 			return -EINVAL;
+		break;
 	}
-	break;
 
 	case ENCODER_ENABLE_OUTPUT:
 	{
 		int *iarg = arg;
 		encoder->enable = !!*iarg;
 
-		DEBUG(printk
-		      (KERN_INFO "%s: enable output %d\n",
-		       encoder->i2c->name, encoder->enable));
+		v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
+		break;
 	}
-	break;
 
 	case 4711:
 	{
 		int *iarg = arg;
 		__u8 val;
 
-		printk("bt866: square = %d\n", *iarg);
+		v4l_dbg(1, debug, client, "square %d\n", *iarg);
 
 		val = encoder->reg[0xdc];
 		if (*iarg)
 			val |= 1; /* SQUARE */
 		else
 			val &= ~1; /* !SQUARE */
-		bt866_write(encoder, 0xdc, val);
+		bt866_write(client, 0xdc, val);
 		break;
 	}
 
@@ -235,141 +238,49 @@
 	return 0;
 }
 
-static int bt866_write(struct bt866 *encoder,
-			unsigned char subaddr, unsigned char data)
-{
-	unsigned char buffer[2];
-	int err;
+static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
-	buffer[0] = subaddr;
-	buffer[1] = data;
+I2C_CLIENT_INSMOD;
 
-	encoder->reg[subaddr] = data;
-
-	DEBUG(printk
-	      ("%s: write 0x%02X = 0x%02X\n",
-	       encoder->i2c->name, subaddr, data));
-
-	for (err = 0; err < 3;) {
-		if (i2c_master_send(encoder->i2c, buffer, 2) == 2)
-			break;
-		err++;
-		printk(KERN_WARNING "%s: I/O error #%d "
-		       "(write 0x%02x/0x%02x)\n",
-		       encoder->i2c->name, err, encoder->addr, subaddr);
-		schedule_timeout_interruptible(msecs_to_jiffies(100));
-	}
-	if (err == 3) {
-		printk(KERN_WARNING "%s: giving up\n",
-		       encoder->i2c->name);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int bt866_attach(struct i2c_adapter *adapter);
-static int bt866_detach(struct i2c_client *client);
-static int bt866_command(struct i2c_client *client,
-			 unsigned int cmd, void *arg);
-
-
-/* Addresses to scan */
-static unsigned short normal_i2c[]	= {I2C_BT866>>1, I2C_CLIENT_END};
-static unsigned short probe[2]		= {I2C_CLIENT_END, I2C_CLIENT_END};
-static unsigned short ignore[2]		= {I2C_CLIENT_END, I2C_CLIENT_END};
-
-static struct i2c_client_address_data addr_data = {
-	normal_i2c,
-	probe,
-	ignore,
-};
-
-static struct i2c_driver i2c_driver_bt866 = {
-	.driver.name = BT866_DEVNAME,
-	.id = I2C_DRIVERID_BT866,
-	.attach_adapter = bt866_attach,
-	.detach_client = bt866_detach,
-	.command = bt866_command
-};
-
-
-static struct i2c_client bt866_client_tmpl =
-{
-	.name = "(nil)",
-	.addr = 0,
-	.adapter = NULL,
-	.driver = &i2c_driver_bt866,
-};
-
-static int bt866_found_proc(struct i2c_adapter *adapter,
-			    int addr, int kind)
+static int bt866_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	struct bt866 *encoder;
-	struct i2c_client *client;
 
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (client == NULL)
-		return -ENOMEM;
-	memcpy(client, &bt866_client_tmpl, sizeof(*client));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
-	if (encoder == NULL) {
-		kfree(client);
+	if (encoder == NULL)
 		return -ENOMEM;
-	}
 
 	i2c_set_clientdata(client, encoder);
-	client->adapter = adapter;
-	client->addr = addr;
-	sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
-
-	encoder->i2c = client;
-	encoder->addr = addr;
-	//encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
-
-	/* initialize */
-
-	i2c_attach_client(client);
-
 	return 0;
 }
 
-static int bt866_attach(struct i2c_adapter *adapter)
+static int bt866_remove(struct i2c_client *client)
 {
-	if (adapter->id == I2C_HW_B_ZR36067)
-		return i2c_probe(adapter, &addr_data, bt866_found_proc);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
-static int bt866_detach(struct i2c_client *client)
+static int bt866_legacy_probe(struct i2c_adapter *adapter)
 {
-	struct bt866 *encoder = i2c_get_clientdata(client);
-
-	i2c_detach_client(client);
-	kfree(encoder);
-	kfree(client);
-
-	return 0;
+	return adapter->id == I2C_HW_B_ZR36067;
 }
 
-static int bt866_command(struct i2c_client *client,
-			 unsigned int cmd, void *arg)
-{
-	struct bt866 *encoder = i2c_get_clientdata(client);
-	return bt866_do_command(encoder, cmd, arg);
-}
+static const struct i2c_device_id bt866_id[] = {
+	{ "bt866", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bt866_id);
 
-static int __devinit bt866_init(void)
-{
-	i2c_add_driver(&i2c_driver_bt866);
-	return 0;
-}
-
-static void __devexit bt866_exit(void)
-{
-	i2c_del_driver(&i2c_driver_bt866);
-}
-
-module_init(bt866_init);
-module_exit(bt866_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "bt866",
+	.driverid = I2C_DRIVERID_BT866,
+	.command = bt866_command,
+	.probe = bt866_probe,
+	.remove = bt866_remove,
+	.legacy_probe = bt866_legacy_probe,
+	.id_table = bt866_id,
+};
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 2cda15f..dac5ccc 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -39,16 +39,16 @@
 		.input          = {{
 			.type   = CX23885_VMUX_COMPOSITE1,
 			.vmux   = 0,
-		},{
+		}, {
 			.type   = CX23885_VMUX_COMPOSITE2,
 			.vmux   = 1,
-		},{
+		}, {
 			.type   = CX23885_VMUX_COMPOSITE3,
 			.vmux   = 2,
-		},{
+		}, {
 			.type   = CX23885_VMUX_COMPOSITE4,
 			.vmux   = 3,
-		}},
+		} },
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR1800lp] = {
 		.name		= "Hauppauge WinTV-HVR1800lp",
@@ -57,19 +57,19 @@
 			.type   = CX23885_VMUX_TELEVISION,
 			.vmux   = 0,
 			.gpio0  = 0xff00,
-		},{
+		}, {
 			.type   = CX23885_VMUX_DEBUG,
 			.vmux   = 0,
 			.gpio0  = 0xff01,
-		},{
+		}, {
 			.type   = CX23885_VMUX_COMPOSITE1,
 			.vmux   = 1,
 			.gpio0  = 0xff02,
-		},{
+		}, {
 			.type   = CX23885_VMUX_SVIDEO,
 			.vmux   = 2,
 			.gpio0  = 0xff02,
-		}},
+		} },
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR1800] = {
 		.name		= "Hauppauge WinTV-HVR1800",
@@ -84,20 +84,20 @@
 					CX25840_VIN5_CH2 |
 					CX25840_VIN2_CH1,
 			.gpio0  = 0,
-		},{
+		}, {
 			.type   = CX23885_VMUX_COMPOSITE1,
 			.vmux   =	CX25840_VIN7_CH3 |
 					CX25840_VIN4_CH2 |
 					CX25840_VIN6_CH1,
 			.gpio0  = 0,
-		},{
+		}, {
 			.type   = CX23885_VMUX_SVIDEO,
 			.vmux   =	CX25840_VIN7_CH3 |
 					CX25840_VIN4_CH2 |
 					CX25840_VIN8_CH1 |
 					CX25840_SVIDEO_ON,
 			.gpio0  = 0,
-		}},
+		} },
 	},
 	[CX23885_BOARD_HAUPPAUGE_HVR1250] = {
 		.name		= "Hauppauge WinTV-HVR1250",
@@ -106,19 +106,19 @@
 			.type   = CX23885_VMUX_TELEVISION,
 			.vmux   = 0,
 			.gpio0  = 0xff00,
-		},{
+		}, {
 			.type   = CX23885_VMUX_DEBUG,
 			.vmux   = 0,
 			.gpio0  = 0xff01,
-		},{
+		}, {
 			.type   = CX23885_VMUX_COMPOSITE1,
 			.vmux   = 1,
 			.gpio0  = 0xff02,
-		},{
+		}, {
 			.type   = CX23885_VMUX_SVIDEO,
 			.vmux   = 2,
 			.gpio0  = 0xff02,
-		}},
+		} },
 	},
 	[CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP] = {
 		.name		= "DViCO FusionHDTV5 Express",
@@ -169,43 +169,43 @@
 		.subvendor = 0x0070,
 		.subdevice = 0x3400,
 		.card      = CX23885_BOARD_UNKNOWN,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7600,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800lp,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7800,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7801,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7809,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7911,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1250,
-	},{
+	}, {
 		.subvendor = 0x18ac,
 		.subdevice = 0xd500,
 		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7790,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7797,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7710,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
-	},{
+	}, {
 		.subvendor = 0x0070,
 		.subdevice = 0x7717,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
@@ -225,11 +225,11 @@
 		.subvendor = 0x0070,
 		.subdevice = 0x8010,
 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1400,
-	},{
+	}, {
 		.subvendor = 0x18ac,
 		.subdevice = 0xd618,
 		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
-	},{
+	}, {
 		.subvendor = 0x18ac,
 		.subdevice = 0xdb78,
 		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP,
@@ -247,23 +247,25 @@
 
 	if (0 == dev->pci->subsystem_vendor &&
 	    0 == dev->pci->subsystem_device) {
-		printk("%s: Your board has no valid PCIe Subsystem ID and thus can't\n"
-		       "%s: be autodetected.  Please pass card=<n> insmod option to\n"
-		       "%s: workaround that.  Redirect complaints to the vendor of\n"
-		       "%s: the TV card.  Best regards,\n"
+		printk(KERN_INFO
+			"%s: Board has no valid PCIe Subsystem ID and can't\n"
+		       "%s: be autodetected. Pass card=<n> insmod option\n"
+		       "%s: to workaround that. Redirect complaints to the\n"
+		       "%s: vendor of the TV card.  Best regards,\n"
 		       "%s:         -- tux\n",
 		       dev->name, dev->name, dev->name, dev->name, dev->name);
 	} else {
-		printk("%s: Your board isn't known (yet) to the driver.  You can\n"
-		       "%s: try to pick one of the existing card configs via\n"
+		printk(KERN_INFO
+			"%s: Your board isn't known (yet) to the driver.\n"
+		       "%s: Try to pick one of the existing card configs via\n"
 		       "%s: card=<n> insmod option.  Updating to the latest\n"
 		       "%s: version might help as well.\n",
 		       dev->name, dev->name, dev->name, dev->name);
 	}
-	printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+	printk(KERN_INFO "%s: Here is a list of valid choices for the card=<n> insmod option:\n",
 	       dev->name);
 	for (i = 0; i < cx23885_bcount; i++)
-		printk("%s:    card=%d -> %s\n",
+		printk(KERN_INFO "%s:    card=%d -> %s\n",
 		       dev->name, i, cx23885_boards[i].name);
 }
 
@@ -271,11 +273,11 @@
 {
 	struct tveeprom tv;
 
-	tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv, eeprom_data);
+	tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
+		eeprom_data);
 
 	/* Make sure we support the board model */
-	switch (tv.model)
-	{
+	switch (tv.model) {
 	case 71009:
 		/* WinTV-HVR1200 (PCIe, Retail, full height)
 		 * DVB-T and basic analog */
@@ -303,21 +305,51 @@
 	case 71999:
 		/* WinTV-HVR1200 (PCIe, OEM, full height)
 		 * DVB-T and basic analog */
-	case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */
-	case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */
-	case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */
-	case 77041: /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM and Basic analog */
-	case 77051: /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM and Basic analog */
-	case 78011: /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
-	case 78501: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
-	case 78521: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
-	case 78531: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
-	case 78631: /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
-	case 79001: /* WinTV-HVR1250 (PCIe, Retail, IR, full height, ATSC and Basic analog */
-	case 79101: /* WinTV-HVR1250 (PCIe, Retail, IR, half height, ATSC and Basic analog */
-	case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
-	case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
-	case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+	case 76601:
+		/* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual
+			channel ATSC and MPEG2 HW Encoder */
+	case 77001:
+		/* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC
+			and Basic analog */
+	case 77011:
+		/* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC
+			and Basic analog */
+	case 77041:
+		/* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM
+			and Basic analog */
+	case 77051:
+		/* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM
+			and Basic analog */
+	case 78011:
+		/* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78501:
+		/* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78521:
+		/* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78531:
+		/* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78631:
+		/* WinTV-HVR1800 (PCIe, OEM, No IR, No FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 79001:
+		/* WinTV-HVR1250 (PCIe, Retail, IR, full height,
+			ATSC and Basic analog */
+	case 79101:
+		/* WinTV-HVR1250 (PCIe, Retail, IR, half height,
+			ATSC and Basic analog */
+	case 79561:
+		/* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+			ATSC and Basic analog */
+	case 79571:
+		/* WinTV-HVR1250 (PCIe, OEM, No IR, full height,
+		 ATSC and Basic analog */
+	case 79671:
+		/* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+			ATSC and Basic analog */
 	case 80019:
 		/* WinTV-HVR1400 (Express Card, Retail, IR,
 		 * DVB-T and Basic analog */
@@ -329,7 +361,8 @@
 		 * DVB-T and MPEG2 HW Encoder */
 		break;
 	default:
-		printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
+		printk(KERN_WARNING "%s: warning: unknown hauppauge model #%d\n",
+			dev->name, tv.model);
 		break;
 	}
 
@@ -352,7 +385,7 @@
 		return -EINVAL;
 	}
 
-	switch(dev->board) {
+	switch (dev->board) {
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -383,7 +416,7 @@
 
 void cx23885_gpio_setup(struct cx23885_dev *dev)
 {
-	switch(dev->board) {
+	switch (dev->board) {
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 		/* GPIO-0 cx24227 demodulator reset */
 		cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
@@ -617,10 +650,3 @@
 }
 
 /* ------------------------------------------------------------------ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index beb3e61..8f6fb2a 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -37,12 +37,12 @@
 MODULE_LICENSE("GPL");
 
 static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
 
 static unsigned int card[]  = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
 module_param_array(card,  int, NULL, 0444);
-MODULE_PARM_DESC(card,"card type");
+MODULE_PARM_DESC(card, "card type");
 
 #define dprintk(level, fmt, arg...)\
 	do { if (debug >= level)\
@@ -364,13 +364,12 @@
 		list_del(&buf->vb.queue);
 		wake_up(&buf->vb.done);
 	}
-	if (list_empty(&q->active)) {
+	if (list_empty(&q->active))
 		del_timer(&q->timeout);
-	} else {
+	else
 		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-	}
 	if (bc != 1)
-		printk("%s: %d buffers handled (should be 1)\n",
+		printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
 		       __func__, bc);
 }
 
@@ -381,8 +380,7 @@
 	unsigned int i, lines;
 	u32 cdt;
 
-	if (ch->cmds_start == 0)
-	{
+	if (ch->cmds_start == 0) {
 		dprintk(1, "%s() Erasing channel [%s]\n", __func__,
 			ch->name);
 		cx_write(ch->ptr1_reg, 0);
@@ -418,15 +416,15 @@
 
 	/* write CMDS */
 	if (ch->jumponly)
-		cx_write(ch->cmds_start +  0, 8);
+		cx_write(ch->cmds_start + 0, 8);
 	else
-		cx_write(ch->cmds_start +  0, risc);
+		cx_write(ch->cmds_start + 0, risc);
 	cx_write(ch->cmds_start +  4, 0); /* 64 bits 63-32 */
 	cx_write(ch->cmds_start +  8, cdt);
 	cx_write(ch->cmds_start + 12, (lines*16) >> 3);
 	cx_write(ch->cmds_start + 16, ch->ctrl_start);
 	if (ch->jumponly)
-		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2) );
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
 	else
 		cx_write(ch->cmds_start + 20, 64 >> 2);
 	for (i = 24; i < 80; i += 4)
@@ -436,9 +434,9 @@
 	cx_write(ch->ptr1_reg, ch->fifo_start);
 	cx_write(ch->ptr2_reg, cdt);
 	cx_write(ch->cnt2_reg, (lines*16) >> 3);
-	cx_write(ch->cnt1_reg, (bpl >> 3) -1);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
 
-	dprintk(2,"[bridge %d] sram setup %s: bpl=%d lines=%d\n",
+	dprintk(2, "[bridge %d] sram setup %s: bpl=%d lines=%d\n",
 		dev->bridge,
 		ch->name,
 		bpl,
@@ -469,43 +467,43 @@
 	u32 risc;
 	unsigned int i, j, n;
 
-	printk("%s: %s - dma channel status dump\n",
+	printk(KERN_WARNING "%s: %s - dma channel status dump\n",
 	       dev->name, ch->name);
 	for (i = 0; i < ARRAY_SIZE(name); i++)
-		printk("%s:   cmds: %-15s: 0x%08x\n",
+		printk(KERN_WARNING "%s:   cmds: %-15s: 0x%08x\n",
 		       dev->name, name[i],
 		       cx_read(ch->cmds_start + 4*i));
 
 	for (i = 0; i < 4; i++) {
 		risc = cx_read(ch->cmds_start + 4 * (i + 14));
-		printk("%s:   risc%d: ", dev->name, i);
+		printk(KERN_WARNING "%s:   risc%d: ", dev->name, i);
 		cx23885_risc_decode(risc);
 	}
 	for (i = 0; i < (64 >> 2); i += n) {
 		risc = cx_read(ch->ctrl_start + 4 * i);
 		/* No consideration for bits 63-32 */
 
-		printk("%s:   (0x%08x) iq %x: ", dev->name,
+		printk(KERN_WARNING "%s:   (0x%08x) iq %x: ", dev->name,
 		       ch->ctrl_start + 4 * i, i);
 		n = cx23885_risc_decode(risc);
 		for (j = 1; j < n; j++) {
 			risc = cx_read(ch->ctrl_start + 4 * (i + j));
-			printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
+			printk(KERN_WARNING "%s:   iq %x: 0x%08x [ arg #%d ]\n",
 			       dev->name, i+j, risc, j);
 		}
 	}
 
-	printk("%s: fifo: 0x%08x -> 0x%x\n",
+	printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
 	       dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
-	printk("%s: ctrl: 0x%08x -> 0x%x\n",
+	printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
 	       dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
-	printk("%s:   ptr1_reg: 0x%08x\n",
+	printk(KERN_WARNING "%s:   ptr1_reg: 0x%08x\n",
 	       dev->name, cx_read(ch->ptr1_reg));
-	printk("%s:   ptr2_reg: 0x%08x\n",
+	printk(KERN_WARNING "%s:   ptr2_reg: 0x%08x\n",
 	       dev->name, cx_read(ch->ptr2_reg));
-	printk("%s:   cnt1_reg: 0x%08x\n",
+	printk(KERN_WARNING "%s:   cnt1_reg: 0x%08x\n",
 	       dev->name, cx_read(ch->cnt1_reg));
-	printk("%s:   cnt2_reg: 0x%08x\n",
+	printk(KERN_WARNING "%s:   cnt2_reg: 0x%08x\n",
 	       dev->name, cx_read(ch->cnt2_reg));
 }
 
@@ -515,13 +513,13 @@
 	struct cx23885_dev *dev = port->dev;
 	unsigned int i, j, n;
 
-	printk("%s: risc disasm: %p [dma=0x%08lx]\n",
+	printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
 	       dev->name, risc->cpu, (unsigned long)risc->dma);
 	for (i = 0; i < (risc->size >> 2); i += n) {
-		printk("%s:   %04d: ", dev->name, i);
+		printk(KERN_INFO "%s:   %04d: ", dev->name, i);
 		n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
 		for (j = 1; j < n; j++)
-			printk("%s:   %04d: 0x%08x [ arg #%d ]\n",
+			printk(KERN_INFO "%s:   %04d: 0x%08x [ arg #%d ]\n",
 			       dev->name, i + j, risc->cpu[i + j], j);
 		if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
 			break;
@@ -600,7 +598,7 @@
 	 * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
 	 * occur on the cx23887 bridge.
 	 */
-	if(dev->bridge == CX23885_BRIDGE_885)
+	if (dev->bridge == CX23885_BRIDGE_885)
 		cx_clear(RDR_TLCTL0, 1 << 4);
 
 	return 0;
@@ -608,13 +606,13 @@
 
 static int get_resources(struct cx23885_dev *dev)
 {
-	if (request_mem_region(pci_resource_start(dev->pci,0),
-			       pci_resource_len(dev->pci,0),
+	if (request_mem_region(pci_resource_start(dev->pci, 0),
+			       pci_resource_len(dev->pci, 0),
 			       dev->name))
 		return 0;
 
 	printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
-		dev->name, (unsigned long long)pci_resource_start(dev->pci,0));
+		dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
 
 	return -EBUSY;
 }
@@ -623,7 +621,8 @@
 int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
 				u32 reg, u32 mask, u32 value);
 
-static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
+static int cx23885_init_tsport(struct cx23885_dev *dev,
+	struct cx23885_tsport *port, int portno)
 {
 	dprintk(1, "%s(portno=%d)\n", __func__, portno);
 
@@ -643,7 +642,18 @@
 	port->mpegq.timeout.data = (unsigned long)port;
 	init_timer(&port->mpegq.timeout);
 
-	switch(portno) {
+	mutex_init(&port->frontends.lock);
+	INIT_LIST_HEAD(&port->frontends.felist);
+	port->frontends.active_fe_id = 0;
+
+	/* This should be hardcoded allow a single frontend
+	 * attachment to this tsport, keeping the -dvb.c
+	 * code clean and safe.
+	 */
+	if (!port->num_frontends)
+		port->num_frontends = 1;
+
+	switch (portno) {
 	case 1:
 		port->reg_gpcnt          = VID_B_GPCNT;
 		port->reg_gpcnt_ctl      = VID_B_GPCNT_CTL;
@@ -744,13 +754,13 @@
 	mutex_unlock(&devlist);
 
 	/* Configure the internal memory */
-	if(dev->pci->device == 0x8880) {
+	if (dev->pci->device == 0x8880) {
 		dev->bridge = CX23885_BRIDGE_887;
 		/* Apply a sensible clock frequency for the PCIe bridge */
 		dev->clk_freq = 25000000;
 		dev->sram_channels = cx23887_sram_channels;
 	} else
-	if(dev->pci->device == 0x8852) {
+	if (dev->pci->device == 0x8852) {
 		dev->bridge = CX23885_BRIDGE_885;
 		/* Apply a sensible clock frequency for the PCIe bridge */
 		dev->clk_freq = 28000000;
@@ -831,8 +841,8 @@
 	}
 
 	/* PCIe stuff */
-	dev->lmmio = ioremap(pci_resource_start(dev->pci,0),
-			     pci_resource_len(dev->pci,0));
+	dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
+			     pci_resource_len(dev->pci, 0));
 
 	dev->bmmio = (u8 __iomem *)dev->lmmio;
 
@@ -862,7 +872,7 @@
 	cx23885_i2c_register(&dev->i2c_bus[1]);
 	cx23885_i2c_register(&dev->i2c_bus[2]);
 	cx23885_card_setup(dev);
-	cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+	cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
 	cx23885_ir_init(dev);
 
 	if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
@@ -908,8 +918,8 @@
 
 static void cx23885_dev_unregister(struct cx23885_dev *dev)
 {
-	release_mem_region(pci_resource_start(dev->pci,0),
-			   pci_resource_len(dev->pci,0));
+	release_mem_region(pci_resource_start(dev->pci, 0),
+			   pci_resource_len(dev->pci, 0));
 
 	if (!atomic_dec_and_test(&dev->refcount))
 		return;
@@ -936,7 +946,7 @@
 	iounmap(dev->lmmio);
 }
 
-static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
+static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
 			       unsigned int offset, u32 sync_line,
 			       unsigned int bpl, unsigned int padding,
 			       unsigned int lines)
@@ -957,31 +967,31 @@
 		}
 		if (bpl <= sg_dma_len(sg)-offset) {
 			/* fits into current chunk */
-			*(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
-			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-			*(rp++)=cpu_to_le32(0); /* bits 63-32 */
-			offset+=bpl;
+			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
+			offset += bpl;
 		} else {
 			/* scanline needs to be split */
 			todo = bpl;
-			*(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
+			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
 					    (sg_dma_len(sg)-offset));
-			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-			*(rp++)=cpu_to_le32(0); /* bits 63-32 */
+			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
 			todo -= (sg_dma_len(sg)-offset);
 			offset = 0;
 			sg++;
 			while (todo > sg_dma_len(sg)) {
-				*(rp++)=cpu_to_le32(RISC_WRITE|
+				*(rp++) = cpu_to_le32(RISC_WRITE|
 						    sg_dma_len(sg));
-				*(rp++)=cpu_to_le32(sg_dma_address(sg));
-				*(rp++)=cpu_to_le32(0); /* bits 63-32 */
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0); /* bits 63-32 */
 				todo -= sg_dma_len(sg);
 				sg++;
 			}
-			*(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
-			*(rp++)=cpu_to_le32(sg_dma_address(sg));
-			*(rp++)=cpu_to_le32(0); /* bits 63-32 */
+			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
 			offset += todo;
 		}
 		offset += padding;
@@ -1010,9 +1020,11 @@
 	   can cause next bpl to start close to a page border.  First DMA
 	   region may be smaller than PAGE_SIZE */
 	/* write and jump need and extra dword */
-	instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+	instructions  = fields * (1 + ((bpl + padding) * lines)
+		/ PAGE_SIZE + lines);
 	instructions += 2;
-	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+	rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+	if (rc < 0)
 		return rc;
 
 	/* write risc instructions */
@@ -1026,7 +1038,7 @@
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
-	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
 	return 0;
 }
 
@@ -1048,7 +1060,8 @@
 	instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
 	instructions += 1;
 
-	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+	rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+	if (rc < 0)
 		return rc;
 
 	/* write risc instructions */
@@ -1057,7 +1070,7 @@
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
-	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
 	return 0;
 }
 
@@ -1067,7 +1080,8 @@
 	__le32 *rp;
 	int rc;
 
-	if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
+	rc = btcx_riscmem_alloc(pci, risc, 4*16);
+	if (rc < 0)
 		return rc;
 
 	/* write risc instructions */
@@ -1161,22 +1175,23 @@
 
 	/* setup fifo + format */
 	cx23885_sram_channel_setup(dev,
-				   &dev->sram_channels[ port->sram_chno ],
+				   &dev->sram_channels[port->sram_chno],
 				   port->ts_packet_size, buf->risc.dma);
-	if(debug > 5) {
-		cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ] );
+	if (debug > 5) {
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[port->sram_chno]);
 		cx23885_risc_disasm(port, &buf->risc);
 	}
 
 	/* write TS length to chip */
 	cx_write(port->reg_lngth, buf->vb.width);
 
-	if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
-		(!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
-		printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
+	if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
+		(!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
+		printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
 			__func__,
 			cx23885_boards[dev->board].portb,
-			cx23885_boards[dev->board].portc );
+			cx23885_boards[dev->board].portc);
 		return -EINVAL;
 	}
 
@@ -1186,7 +1201,7 @@
 	udelay(100);
 
 	/* If the port supports SRC SELECT, configure it */
-	if(port->reg_src_sel)
+	if (port->reg_src_sel)
 		cx_write(port->reg_src_sel, port->src_sel_val);
 
 	cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
@@ -1195,7 +1210,7 @@
 	cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
 	udelay(100);
 
-	// NOTE: this is 2 (reserved) for portb, does it matter?
+	/* NOTE: this is 2 (reserved) for portb, does it matter? */
 	/* reset counter to zero */
 	cx_write(port->reg_gpcnt_ctl, 3);
 	q->count = 1;
@@ -1229,11 +1244,11 @@
 		cx_write(ALT_PIN_OUT_SEL, 0x10100045);
 	}
 
-	switch(dev->bridge) {
+	switch (dev->bridge) {
 	case CX23885_BRIDGE_885:
 	case CX23885_BRIDGE_887:
 		/* enable irqs */
-		dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
+		dprintk(1, "%s() enabling TS int's and DMA\n", __func__);
 		cx_set(port->reg_ts_int_msk,  port->ts_int_msk_val);
 		cx_set(port->reg_dma_ctl, port->dma_ctl_val);
 		cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
@@ -1292,8 +1307,7 @@
 	struct cx23885_buffer *buf;
 
 	dprintk(5, "%s()\n", __func__);
-	if (list_empty(&q->active))
-	{
+	if (list_empty(&q->active)) {
 		struct cx23885_buffer *prev;
 		prev = NULL;
 
@@ -1311,7 +1325,7 @@
 				buf->vb.state = VIDEOBUF_ACTIVE;
 				buf->count    = q->count++;
 				mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-				dprintk(5, "[%p/%d] restart_queue - first active\n",
+				dprintk(5, "[%p/%d] restart_queue - f/active\n",
 					buf, buf->vb.i);
 
 			} else if (prev->vb.width  == buf->vb.width  &&
@@ -1322,8 +1336,9 @@
 				buf->vb.state = VIDEOBUF_ACTIVE;
 				buf->count    = q->count++;
 				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-				prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
-				dprintk(5,"[%p/%d] restart_queue - move to active\n",
+				/* 64 bit bits 63-32 */
+				prev->risc.jmp[2] = cpu_to_le32(0);
+				dprintk(5, "[%p/%d] restart_queue - m/active\n",
 					buf, buf->vb.i);
 			} else {
 				return 0;
@@ -1362,7 +1377,8 @@
 		buf->vb.size   = size;
 		buf->vb.field  = field /*V4L2_FIELD_TOP*/;
 
-		if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (0 != rc)
 			goto fail;
 		cx23885_risc_databuffer(dev->pci, &buf->risc,
 					videobuf_to_dma(&buf->vb)->sglist,
@@ -1388,7 +1404,7 @@
 	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
 
 	if (list_empty(&cx88q->active)) {
-		dprintk( 1, "queue is empty - first active\n" );
+		dprintk(1, "queue is empty - first active\n");
 		list_add_tail(&buf->vb.queue, &cx88q->active);
 		cx23885_start_dma(port, cx88q, buf);
 		buf->vb.state = VIDEOBUF_ACTIVE;
@@ -1397,7 +1413,7 @@
 		dprintk(1, "[%p/%d] %s - first active\n",
 			buf, buf->vb.i, __func__);
 	} else {
-		dprintk( 1, "queue is not empty - append to active\n" );
+		dprintk(1, "queue is not empty - append to active\n");
 		prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
 				  vb.queue);
 		list_add_tail(&buf->vb.queue, &cx88q->active);
@@ -1405,7 +1421,7 @@
 		buf->count    = cx88q->count++;
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
-		dprintk( 1, "[%p/%d] %s - append to active\n",
+		dprintk(1, "[%p/%d] %s - append to active\n",
 			 buf, buf->vb.i, __func__);
 	}
 }
@@ -1431,7 +1447,7 @@
 			buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
 	}
 	if (restart) {
-		dprintk(1, "restarting queue\n" );
+		dprintk(1, "restarting queue\n");
 		cx23885_restart_queue(port, q);
 	}
 	spin_unlock_irqrestore(&port->slock, flags);
@@ -1453,10 +1469,11 @@
 	struct cx23885_tsport *port = (struct cx23885_tsport *)data;
 	struct cx23885_dev *dev = port->dev;
 
-	dprintk(1, "%s()\n",__func__);
+	dprintk(1, "%s()\n", __func__);
 
 	if (debug > 5)
-		cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[port->sram_chno]);
 
 	cx23885_stop_dma(port);
 	do_cancel_buffers(port, "timeout", 1);
@@ -1532,16 +1549,23 @@
 	if ((status & VID_BC_MSK_OPC_ERR) ||
 		(status & VID_BC_MSK_BAD_PKT) ||
 		(status & VID_BC_MSK_SYNC) ||
-		(status & VID_BC_MSK_OF))
-	{
+		(status & VID_BC_MSK_OF)) {
+
 		if (status & VID_BC_MSK_OPC_ERR)
-			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
+			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+				VID_BC_MSK_OPC_ERR);
+
 		if (status & VID_BC_MSK_BAD_PKT)
-			dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n", VID_BC_MSK_BAD_PKT);
+			dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n",
+				VID_BC_MSK_BAD_PKT);
+
 		if (status & VID_BC_MSK_SYNC)
-			dprintk(7, " (VID_BC_MSK_SYNC    0x%08x)\n", VID_BC_MSK_SYNC);
+			dprintk(7, " (VID_BC_MSK_SYNC    0x%08x)\n",
+				VID_BC_MSK_SYNC);
+
 		if (status & VID_BC_MSK_OF)
-			dprintk(7, " (VID_BC_MSK_OF      0x%08x)\n", VID_BC_MSK_OF);
+			dprintk(7, " (VID_BC_MSK_OF      0x%08x)\n",
+				VID_BC_MSK_OF);
 
 		printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
 
@@ -1595,7 +1619,7 @@
 	ts2_status = cx_read(VID_C_INT_STAT);
 	ts2_mask = cx_read(VID_C_INT_MSK);
 
-	if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) )
+	if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0))
 		goto out;
 
 	vida_count = cx_read(VID_A_GPCNT);
@@ -1610,38 +1634,56 @@
 	dprintk(7, "ts2_status: 0x%08x  ts2_mask: 0x%08x count: 0x%x\n",
 		ts2_status, ts2_mask, ts2_count);
 
-	if ( (pci_status & PCI_MSK_RISC_RD) ||
-	     (pci_status & PCI_MSK_RISC_WR) ||
-	     (pci_status & PCI_MSK_AL_RD) ||
-	     (pci_status & PCI_MSK_AL_WR) ||
-	     (pci_status & PCI_MSK_APB_DMA) ||
-	     (pci_status & PCI_MSK_VID_C) ||
-	     (pci_status & PCI_MSK_VID_B) ||
-	     (pci_status & PCI_MSK_VID_A) ||
-	     (pci_status & PCI_MSK_AUD_INT) ||
-	     (pci_status & PCI_MSK_AUD_EXT) )
-	{
+	if ((pci_status & PCI_MSK_RISC_RD) ||
+	    (pci_status & PCI_MSK_RISC_WR) ||
+	    (pci_status & PCI_MSK_AL_RD) ||
+	    (pci_status & PCI_MSK_AL_WR) ||
+	    (pci_status & PCI_MSK_APB_DMA) ||
+	    (pci_status & PCI_MSK_VID_C) ||
+	    (pci_status & PCI_MSK_VID_B) ||
+	    (pci_status & PCI_MSK_VID_A) ||
+	    (pci_status & PCI_MSK_AUD_INT) ||
+	    (pci_status & PCI_MSK_AUD_EXT)) {
 
 		if (pci_status & PCI_MSK_RISC_RD)
-			dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n", PCI_MSK_RISC_RD);
+			dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n",
+				PCI_MSK_RISC_RD);
+
 		if (pci_status & PCI_MSK_RISC_WR)
-			dprintk(7, " (PCI_MSK_RISC_WR   0x%08x)\n", PCI_MSK_RISC_WR);
+			dprintk(7, " (PCI_MSK_RISC_WR   0x%08x)\n",
+				PCI_MSK_RISC_WR);
+
 		if (pci_status & PCI_MSK_AL_RD)
-			dprintk(7, " (PCI_MSK_AL_RD     0x%08x)\n", PCI_MSK_AL_RD);
+			dprintk(7, " (PCI_MSK_AL_RD     0x%08x)\n",
+				PCI_MSK_AL_RD);
+
 		if (pci_status & PCI_MSK_AL_WR)
-			dprintk(7, " (PCI_MSK_AL_WR     0x%08x)\n", PCI_MSK_AL_WR);
+			dprintk(7, " (PCI_MSK_AL_WR     0x%08x)\n",
+				PCI_MSK_AL_WR);
+
 		if (pci_status & PCI_MSK_APB_DMA)
-			dprintk(7, " (PCI_MSK_APB_DMA   0x%08x)\n", PCI_MSK_APB_DMA);
+			dprintk(7, " (PCI_MSK_APB_DMA   0x%08x)\n",
+				PCI_MSK_APB_DMA);
+
 		if (pci_status & PCI_MSK_VID_C)
-			dprintk(7, " (PCI_MSK_VID_C     0x%08x)\n", PCI_MSK_VID_C);
+			dprintk(7, " (PCI_MSK_VID_C     0x%08x)\n",
+				PCI_MSK_VID_C);
+
 		if (pci_status & PCI_MSK_VID_B)
-			dprintk(7, " (PCI_MSK_VID_B     0x%08x)\n", PCI_MSK_VID_B);
+			dprintk(7, " (PCI_MSK_VID_B     0x%08x)\n",
+				PCI_MSK_VID_B);
+
 		if (pci_status & PCI_MSK_VID_A)
-			dprintk(7, " (PCI_MSK_VID_A     0x%08x)\n", PCI_MSK_VID_A);
+			dprintk(7, " (PCI_MSK_VID_A     0x%08x)\n",
+				PCI_MSK_VID_A);
+
 		if (pci_status & PCI_MSK_AUD_INT)
-			dprintk(7, " (PCI_MSK_AUD_INT   0x%08x)\n", PCI_MSK_AUD_INT);
+			dprintk(7, " (PCI_MSK_AUD_INT   0x%08x)\n",
+				PCI_MSK_AUD_INT);
+
 		if (pci_status & PCI_MSK_AUD_EXT)
-			dprintk(7, " (PCI_MSK_AUD_EXT   0x%08x)\n", PCI_MSK_AUD_EXT);
+			dprintk(7, " (PCI_MSK_AUD_EXT   0x%08x)\n",
+				PCI_MSK_AUD_EXT);
 
 	}
 
@@ -1753,13 +1795,13 @@
 		.device       = 0x8852,
 		.subvendor    = PCI_ANY_ID,
 		.subdevice    = PCI_ANY_ID,
-	},{
+	}, {
 		/* CX23887 Rev 2 */
 		.vendor       = 0x14f1,
 		.device       = 0x8880,
 		.subvendor    = PCI_ANY_ID,
 		.subdevice    = PCI_ANY_ID,
-	},{
+	}, {
 		/* --- end of list --- */
 	}
 };
@@ -1797,9 +1839,3 @@
 module_exit(cx23885_fini);
 
 /* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 24bd183..e1aac07 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -78,19 +78,19 @@
 			   struct videobuf_buffer *vb, enum v4l2_field field)
 {
 	struct cx23885_tsport *port = q->priv_data;
-	return cx23885_buf_prepare(q, port, (struct cx23885_buffer*)vb, field);
+	return cx23885_buf_prepare(q, port, (struct cx23885_buffer *)vb, field);
 }
 
 static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
 	struct cx23885_tsport *port = q->priv_data;
-	cx23885_buf_queue(port, (struct cx23885_buffer*)vb);
+	cx23885_buf_queue(port, (struct cx23885_buffer *)vb);
 }
 
 static void dvb_buf_release(struct videobuf_queue *q,
 			    struct videobuf_buffer *vb)
 {
-	cx23885_free_buffer(q, (struct cx23885_buffer*)vb);
+	cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
 }
 
 static struct videobuf_queue_ops dvb_qops = {
@@ -312,19 +312,25 @@
 {
 	struct cx23885_dev *dev = port->dev;
 	struct cx23885_i2c *i2c_bus = NULL;
+	struct videobuf_dvb_frontend *fe0;
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
 
 	/* init struct videobuf_dvb */
-	port->dvb.name = dev->name;
+	fe0->dvb.name = dev->name;
 
 	/* init frontend */
 	switch (dev->board) {
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 		i2c_bus = &dev->i2c_bus[0];
-		port->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&hauppauge_generic_config,
 						&i2c_bus->i2c_adap);
-		if (port->dvb.frontend != NULL) {
-			dvb_attach(mt2131_attach, port->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(mt2131_attach, fe0->dvb.frontend,
 				   &i2c_bus->i2c_adap,
 				   &hauppauge_generic_tunerconfig, 0);
 		}
@@ -333,27 +339,27 @@
 		i2c_bus = &dev->i2c_bus[0];
 		switch (alt_tuner) {
 		case 1:
-			port->dvb.frontend =
+			fe0->dvb.frontend =
 				dvb_attach(s5h1409_attach,
 					   &hauppauge_ezqam_config,
 					   &i2c_bus->i2c_adap);
-			if (port->dvb.frontend != NULL) {
-				dvb_attach(tda829x_attach, port->dvb.frontend,
+			if (fe0->dvb.frontend != NULL) {
+				dvb_attach(tda829x_attach, fe0->dvb.frontend,
 					   &dev->i2c_bus[1].i2c_adap, 0x42,
 					   &tda829x_no_probe);
-				dvb_attach(tda18271_attach, port->dvb.frontend,
+				dvb_attach(tda18271_attach, fe0->dvb.frontend,
 					   0x60, &dev->i2c_bus[1].i2c_adap,
 					   &hauppauge_tda18271_config);
 			}
 			break;
 		case 0:
 		default:
-			port->dvb.frontend =
+			fe0->dvb.frontend =
 				dvb_attach(s5h1409_attach,
 					   &hauppauge_generic_config,
 					   &i2c_bus->i2c_adap);
-			if (port->dvb.frontend != NULL)
-				dvb_attach(mt2131_attach, port->dvb.frontend,
+			if (fe0->dvb.frontend != NULL)
+				dvb_attach(mt2131_attach, fe0->dvb.frontend,
 					   &i2c_bus->i2c_adap,
 					   &hauppauge_generic_tunerconfig, 0);
 			break;
@@ -361,42 +367,42 @@
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
 		i2c_bus = &dev->i2c_bus[0];
-		port->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&hauppauge_hvr1800lp_config,
 						&i2c_bus->i2c_adap);
-		if (port->dvb.frontend != NULL) {
-			dvb_attach(mt2131_attach, port->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(mt2131_attach, fe0->dvb.frontend,
 				   &i2c_bus->i2c_adap,
 				   &hauppauge_generic_tunerconfig, 0);
 		}
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
 		i2c_bus = &dev->i2c_bus[0];
-		port->dvb.frontend = dvb_attach(lgdt330x_attach,
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 						&fusionhdtv_5_express,
 						&i2c_bus->i2c_adap);
-		if (port->dvb.frontend != NULL) {
-			dvb_attach(simple_tuner_attach, port->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 				   &i2c_bus->i2c_adap, 0x61,
 				   TUNER_LG_TDVS_H06XF);
 		}
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
 		i2c_bus = &dev->i2c_bus[1];
-		port->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&hauppauge_hvr1500q_config,
 						&dev->i2c_bus[0].i2c_adap);
-		if (port->dvb.frontend != NULL)
-			dvb_attach(xc5000_attach, port->dvb.frontend,
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(xc5000_attach, fe0->dvb.frontend,
 				   &i2c_bus->i2c_adap,
 				   &hauppauge_hvr1500q_tunerconfig);
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 		i2c_bus = &dev->i2c_bus[1];
-		port->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&hauppauge_hvr1500_config,
 						&dev->i2c_bus[0].i2c_adap);
-		if (port->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend != NULL) {
 			struct dvb_frontend *fe;
 			struct xc2028_config cfg = {
 				.i2c_adap  = &i2c_bus->i2c_adap,
@@ -409,7 +415,7 @@
 			};
 
 			fe = dvb_attach(xc2028_attach,
-					port->dvb.frontend, &cfg);
+					fe0->dvb.frontend, &cfg);
 			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
 				fe->ops.tuner_ops.set_config(fe, &ctl);
 		}
@@ -417,24 +423,24 @@
 	case CX23885_BOARD_HAUPPAUGE_HVR1200:
 	case CX23885_BOARD_HAUPPAUGE_HVR1700:
 		i2c_bus = &dev->i2c_bus[0];
-		port->dvb.frontend = dvb_attach(tda10048_attach,
+		fe0->dvb.frontend = dvb_attach(tda10048_attach,
 			&hauppauge_hvr1200_config,
 			&i2c_bus->i2c_adap);
-		if (port->dvb.frontend != NULL) {
-			dvb_attach(tda829x_attach, port->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda829x_attach, fe0->dvb.frontend,
 				&dev->i2c_bus[1].i2c_adap, 0x42,
 				&tda829x_no_probe);
-			dvb_attach(tda18271_attach, port->dvb.frontend,
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
 				0x60, &dev->i2c_bus[1].i2c_adap,
 				&hauppauge_hvr1200_tuner_config);
 		}
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
 		i2c_bus = &dev->i2c_bus[0];
-		port->dvb.frontend = dvb_attach(dib7000p_attach,
+		fe0->dvb.frontend = dvb_attach(dib7000p_attach,
 			&i2c_bus->i2c_adap,
 			0x12, &hauppauge_hvr1400_dib7000_config);
-		if (port->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend != NULL) {
 			struct dvb_frontend *fe;
 			struct xc2028_config cfg = {
 				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
@@ -444,12 +450,13 @@
 				.fname   = XC3028L_DEFAULT_FIRMWARE,
 				.max_len = 64,
 				.demod   = 5000,
-				/* This is true for all demods with v36 firmware? */
+				/* This is true for all demods with
+					v36 firmware? */
 				.type    = XC2028_D2633,
 			};
 
 			fe = dvb_attach(xc2028_attach,
-					port->dvb.frontend, &cfg);
+					fe0->dvb.frontend, &cfg);
 			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
 				fe->ops.tuner_ops.set_config(fe, &ctl);
 		}
@@ -457,25 +464,25 @@
 	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
 		i2c_bus = &dev->i2c_bus[port->nr - 1];
 
-		port->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&dvico_s5h1409_config,
 						&i2c_bus->i2c_adap);
-		if (port->dvb.frontend == NULL)
-			port->dvb.frontend = dvb_attach(s5h1411_attach,
+		if (fe0->dvb.frontend == NULL)
+			fe0->dvb.frontend = dvb_attach(s5h1411_attach,
 							&dvico_s5h1411_config,
 							&i2c_bus->i2c_adap);
-		if (port->dvb.frontend != NULL)
-			dvb_attach(xc5000_attach, port->dvb.frontend,
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(xc5000_attach, fe0->dvb.frontend,
 				   &i2c_bus->i2c_adap,
 				   &dvico_xc5000_tunerconfig);
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
 		i2c_bus = &dev->i2c_bus[port->nr - 1];
 
-		port->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_xc3028,
 					       &i2c_bus->i2c_adap);
-		if (port->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend != NULL) {
 			struct dvb_frontend      *fe;
 			struct xc2028_config	  cfg = {
 				.i2c_adap  = &i2c_bus->i2c_adap,
@@ -487,7 +494,7 @@
 				.demod       = XC3028_FE_ZARLINK456,
 			};
 
-			fe = dvb_attach(xc2028_attach, port->dvb.frontend,
+			fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
 					&cfg);
 			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
 				fe->ops.tuner_ops.set_config(fe, &ctl);
@@ -497,10 +504,10 @@
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
 		i2c_bus = &dev->i2c_bus[0];
 
-		port->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 			&dvico_fusionhdtv_xc3028,
 			&i2c_bus->i2c_adap);
-		if (port->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend != NULL) {
 			struct dvb_frontend      *fe;
 			struct xc2028_config	  cfg = {
 				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
@@ -512,73 +519,108 @@
 				.demod       = XC3028_FE_ZARLINK456,
 			};
 
-			fe = dvb_attach(xc2028_attach, port->dvb.frontend,
+			fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
 				&cfg);
 			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
 				fe->ops.tuner_ops.set_config(fe, &ctl);
 		}
 		break;
 	default:
-		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
+		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
+			" isn't supported yet\n",
 		       dev->name);
 		break;
 	}
-	if (NULL == port->dvb.frontend) {
-		printk("%s: frontend initialization failed\n", dev->name);
+	if (NULL == fe0->dvb.frontend) {
+		printk(KERN_ERR "%s: frontend initialization failed\n",
+			dev->name);
 		return -1;
 	}
 	/* define general-purpose callback pointer */
-	port->dvb.frontend->callback = cx23885_tuner_callback;
+	fe0->dvb.frontend->callback = cx23885_tuner_callback;
 
 	/* Put the analog decoder in standby to keep it quiet */
 	cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
 
-	if (port->dvb.frontend->ops.analog_ops.standby)
-		port->dvb.frontend->ops.analog_ops.standby(port->dvb.frontend);
+	if (fe0->dvb.frontend->ops.analog_ops.standby)
+		fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
 
 	/* register everything */
-	return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
-				     &dev->pci->dev, adapter_nr);
+	return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
+		&dev->pci->dev, adapter_nr, 0);
+
 }
 
 int cx23885_dvb_register(struct cx23885_tsport *port)
 {
+
+	struct videobuf_dvb_frontend *fe0;
 	struct cx23885_dev *dev = port->dev;
-	int err;
+	int err, i;
 
-	dprintk(1, "%s\n", __func__);
-	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
-		dev->board,
-		dev->name,
-		dev->pci_bus,
-		dev->pci_slot);
+	/* Here we need to allocate the correct number of frontends,
+	 * as reflected in the cards struct. The reality is that currrently
+	 * no cx23885 boards support this - yet. But, if we don't modify this
+	 * code then the second frontend would never be allocated (later)
+	 * and fail with error before the attach in dvb_register().
+	 * Without these changes we risk an OOPS later. The changes here
+	 * are for safety, and should provide a good foundation for the
+	 * future addition of any multi-frontend cx23885 based boards.
+	 */
+	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+		port->num_frontends);
 
-	err = -ENODEV;
+	for (i = 1; i <= port->num_frontends; i++) {
+		if (videobuf_dvb_alloc_frontend(
+			&port->frontends, i) == NULL) {
+			printk(KERN_ERR "%s() failed to alloc\n", __func__);
+			return -ENOMEM;
+		}
 
-	/* dvb stuff */
-	printk("%s: cx23885 based dvb card\n", dev->name);
-	videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
+		fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
+		if (!fe0)
+			err = -EINVAL;
+
+		dprintk(1, "%s\n", __func__);
+		dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
+			dev->board,
+			dev->name,
+			dev->pci_bus,
+			dev->pci_slot);
+
+		err = -ENODEV;
+
+		/* dvb stuff */
+		/* We have to init the queue for each frontend on a port. */
+		printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
+		videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
+			    &dev->pci->dev, &port->slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
 			    sizeof(struct cx23885_buffer), port);
+	}
 	err = dvb_register(port);
 	if (err != 0)
-		printk("%s() dvb_register failed err = %d\n", __func__, err);
+		printk(KERN_ERR "%s() dvb_register failed err = %d\n",
+			__func__, err);
 
 	return err;
 }
 
 int cx23885_dvb_unregister(struct cx23885_tsport *port)
 {
-	/* dvb */
-	if(port->dvb.frontend)
-		videobuf_dvb_unregister(&port->dvb);
+	struct videobuf_dvb_frontend *fe0;
+
+	/* FIXME: in an error condition where the we have
+	 * an expected number of frontends (attach problem)
+	 * then this might not clean up correctly, if 1
+	 * is invalid.
+	 * This comment only applies to future boards IF they
+	 * implement MFE support.
+	 */
+	fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+	if (fe0->dvb.frontend)
+		videobuf_dvb_unregister_bus(&port->frontends);
 
 	return 0;
 }
 
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
-*/
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index f98e476..bb7f71a 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -131,7 +131,7 @@
 			printk(" >\n");
 	}
 
-	for (cnt = 1; cnt < msg->len; cnt++ ) {
+	for (cnt = 1; cnt < msg->len; cnt++) {
 		/* following bytes */
 		wdata = msg->buf[cnt];
 		ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
@@ -151,9 +151,9 @@
 		if (retval == 0)
 			goto eio;
 		if (i2c_debug) {
-			printk(" %02x", msg->buf[cnt]);
+			dprintk(1, " %02x", msg->buf[cnt]);
 			if (!(ctrl & I2C_NOSTOP))
-				printk(" >\n");
+				dprintk(1, " >\n");
 		}
 	}
 	return msg->len;
@@ -162,7 +162,7 @@
 	retval = -EIO;
  err:
 	if (i2c_debug)
-		printk(" ERR: %d\n", retval);
+		printk(KERN_ERR " ERR: %d\n", retval);
 	return retval;
 }
 
@@ -194,12 +194,12 @@
 
 	if (i2c_debug) {
 		if (joined)
-			printk(" R");
+			dprintk(1, " R");
 		else
-			printk(" <R %02x", (msg->addr << 1) + 1);
+			dprintk(1, " <R %02x", (msg->addr << 1) + 1);
 	}
 
-	for(cnt = 0; cnt < msg->len; cnt++) {
+	for (cnt = 0; cnt < msg->len; cnt++) {
 
 		ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
 
@@ -216,9 +216,9 @@
 			goto eio;
 		msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
 		if (i2c_debug) {
-			printk(" %02x", msg->buf[cnt]);
+			dprintk(1, " %02x", msg->buf[cnt]);
 			if (!(ctrl & I2C_NOSTOP))
-				printk(" >\n");
+				dprintk(1, " >\n");
 		}
 	}
 	return msg->len;
@@ -227,7 +227,7 @@
 	retval = -EIO;
  err:
 	if (i2c_debug)
-		printk(" ERR: %d\n", retval);
+		printk(KERN_ERR " ERR: %d\n", retval);
 	return retval;
 }
 
@@ -353,17 +353,17 @@
 };
 
 static char *i2c_devs[128] = {
-	[0x10 >> 1]   = "tda10048",
-	[0x12 >> 1]   = "dib7000pc",
-	[ 0x1c >> 1 ] = "lgdt3303",
-	[ 0x86 >> 1 ] = "tda9887",
-	[ 0x32 >> 1 ] = "cx24227",
-	[ 0x88 >> 1 ] = "cx25837",
-	[ 0x84 >> 1 ] = "tda8295",
-	[ 0xa0 >> 1 ] = "eeprom",
-	[ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
+	[0x10 >> 1] = "tda10048",
+	[0x12 >> 1] = "dib7000pc",
+	[0x1c >> 1] = "lgdt3303",
+	[0x86 >> 1] = "tda9887",
+	[0x32 >> 1] = "cx24227",
+	[0x88 >> 1] = "cx25837",
+	[0x84 >> 1] = "tda8295",
+	[0xa0 >> 1] = "eeprom",
+	[0xc0 >> 1] = "tuner/mt2131/tda8275",
 	[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
-	[0xc8 >> 1]   = "tuner/xc3028L",
+	[0xc8 >> 1] = "tuner/xc3028L",
 };
 
 static void do_i2c_scan(char *name, struct i2c_client *c)
@@ -376,7 +376,7 @@
 		rc = i2c_master_recv(c, &buf, 0);
 		if (rc < 0)
 			continue;
-		printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
+		printk(KERN_INFO "%s: i2c scan: found device @ 0x%x  [%s]\n",
 		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 }
@@ -408,11 +408,12 @@
 	bus->i2c_client.adapter = &bus->i2c_adap;
 
 	if (0 == bus->i2c_rc) {
-		printk("%s: i2c bus %d registered\n", dev->name, bus->nr);
+		dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
 		if (i2c_scan)
 			do_i2c_scan(dev->name, &bus->i2c_client);
 	} else
-		printk("%s: i2c bus %d register FAILED\n", dev->name, bus->nr);
+		printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
+			dev->name, bus->nr);
 
 	return bus->i2c_rc;
 }
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index f75ed1c..ab3110d 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -285,11 +285,10 @@
 		list_del(&buf->vb.queue);
 		wake_up(&buf->vb.done);
 	}
-	if (list_empty(&q->active)) {
+	if (list_empty(&q->active))
 		del_timer(&q->timeout);
-	} else {
+	else
 		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-	}
 	if (bc != 1)
 		printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
 			__func__, bc);
@@ -379,12 +378,12 @@
 
 static int res_check(struct cx23885_fh *fh, unsigned int bit)
 {
-	return (fh->resources & bit);
+	return fh->resources & bit;
 }
 
 static int res_locked(struct cx23885_dev *dev, unsigned int bit)
 {
-	return (dev->resources & bit);
+	return dev->resources & bit;
 }
 
 static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
@@ -887,14 +886,16 @@
 /* ------------------------------------------------------------------ */
 /* VIDEO CTRL IOCTLS                                                  */
 
-static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_get_control(struct cx23885_dev *dev,
+	struct v4l2_control *ctl)
 {
 	dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
 	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
 	return 0;
 }
 
-static int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_set_control(struct cx23885_dev *dev,
+	struct v4l2_control *ctl)
 {
 	dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
 		" (disabled - no action)\n", __func__);
@@ -1073,29 +1074,29 @@
 	struct v4l2_requestbuffers *p)
 {
 	struct cx23885_fh *fh = priv;
-	return (videobuf_reqbufs(get_queue(fh), p));
+	return videobuf_reqbufs(get_queue(fh), p);
 }
 
 static int vidioc_querybuf(struct file *file, void *priv,
 	struct v4l2_buffer *p)
 {
 	struct cx23885_fh *fh = priv;
-	return (videobuf_querybuf(get_queue(fh), p));
+	return videobuf_querybuf(get_queue(fh), p);
 }
 
 static int vidioc_qbuf(struct file *file, void *priv,
 	struct v4l2_buffer *p)
 {
 	struct cx23885_fh *fh = priv;
-	return (videobuf_qbuf(get_queue(fh), p));
+	return videobuf_qbuf(get_queue(fh), p);
 }
 
 static int vidioc_dqbuf(struct file *file, void *priv,
 	struct v4l2_buffer *p)
 {
 	struct cx23885_fh *fh = priv;
-	return (videobuf_dqbuf(get_queue(fh), p,
-				file->f_flags & O_NONBLOCK));
+	return videobuf_dqbuf(get_queue(fh), p,
+				file->f_flags & O_NONBLOCK);
 }
 
 static int vidioc_streamon(struct file *file, void *priv,
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index ba4e0aa..1d53f54 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -37,7 +37,7 @@
 #include <linux/version.h>
 #include <linux/mutex.h>
 
-#define CX23885_VERSION_CODE KERNEL_VERSION(0,0,1)
+#define CX23885_VERSION_CODE KERNEL_VERSION(0, 0, 1)
 
 #define UNSET (-1U)
 
@@ -225,7 +225,7 @@
 	int                        nr;
 	int                        sram_chno;
 
-	struct videobuf_dvb        dvb;
+	struct videobuf_dvb_frontends frontends;
 
 	/* dma queues */
 	struct cx23885_dmaqueue    mpegq;
@@ -262,6 +262,9 @@
 	u32                        src_sel_val;
 	u32                        vld_misc_val;
 	u32                        hw_sop_ctrl_val;
+
+	/* Allow a single tsport to have multiple frontends */
+	u32                        num_frontends;
 };
 
 struct cx23885_dev {
@@ -367,14 +370,14 @@
 /* ----------------------------------------------------------- */
 
 #define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
-#define cx_write(reg,value)      writel((value), dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
 
-#define cx_andor(reg,mask,value) \
+#define cx_andor(reg, mask, value) \
   writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
   ((value) & (mask)), dev->lmmio+((reg)>>2))
 
-#define cx_set(reg,bit)          cx_andor((reg),(bit),(bit))
-#define cx_clear(reg,bit)        cx_andor((reg),(bit),0)
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
 
 /* ----------------------------------------------------------- */
 /* cx23885-core.c                                              */
@@ -411,7 +414,8 @@
 extern struct cx23885_subid cx23885_subids[];
 extern const unsigned int cx23885_idcount;
 
-extern int cx23885_tuner_callback(void *priv, int component, int command, int arg);
+extern int cx23885_tuner_callback(void *priv, int component,
+	int command, int arg);
 extern void cx23885_card_list(struct cx23885_dev *dev);
 extern int  cx23885_ir_init(struct cx23885_dev *dev);
 extern void cx23885_gpio_setup(struct cx23885_dev *dev);
@@ -479,11 +483,3 @@
 {
 	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 }
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 5da04e8..fbc224f 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1270,27 +1270,40 @@
 		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_HAUPPAUGE_HVR3000] = {
-		/* FIXME: Add dvb & radio support */
 		.name           = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T",
 		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
+		.audio_chip     = V4L2_IDENT_WM8775,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
 			.gpio0  = 0x84bf,
+			/* 1: TV Audio / FM Mono */
+			.audioroute = 1,
 		},{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
 			.gpio0  = 0x84bf,
+			/* 2: Line-In */
+			.audioroute = 2,
 		},{
 			.type   = CX88_VMUX_SVIDEO,
 			.vmux   = 2,
 			.gpio0  = 0x84bf,
+			/* 2: Line-In */
+			.audioroute = 2,
 		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0	= 0x84bf,
+			/* 4: FM Stereo (untested) */
+			.audioroute = 8,
+		},
 		.mpeg           = CX88_MPEG_DVB,
+		.num_frontends	= 2,
 	},
 	[CX88_BOARD_NORWOOD_MICRO] = {
 		.name           = "Norwood Micro TV Tuner",
@@ -1356,23 +1369,27 @@
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
 			.gpio0	= 0xef88,
+			/* 1: TV Audio / FM Mono */
 			.audioroute = 1,
 		},{
 			.type	= CX88_VMUX_COMPOSITE1,
 			.vmux	= 1,
 			.gpio0	= 0xef88,
+			/* 2: Line-In */
 			.audioroute = 2,
 		},{
 			.type	= CX88_VMUX_SVIDEO,
 			.vmux	= 2,
 			.gpio0	= 0xef88,
+			/* 2: Line-In */
 			.audioroute = 2,
 		}},
-		/* fixme: Add radio support */
 		.mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
 		.radio = {
 			.type   = CX88_RADIO,
 			.gpio0	= 0xef88,
+			/* 4: FM Stereo (untested) */
+			.audioroute = 8,
 		},
 	},
 	[CX88_BOARD_ADSTECH_PTV_390] = {
@@ -1716,6 +1733,7 @@
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
+		.audio_chip     = V4L2_IDENT_WM8775,
 		/*
 		 * GPIO0 (WINTV2000)
 		 *
@@ -1729,7 +1747,7 @@
 		 * BIT  VALUE   FUNCTION GP{x}_IO
 		 * 0    1       I:?
 		 * 1    1       I:?
-		 * 2    1       O:DVB-T DEMOD ENABLE LOW/ANALOG DEMOD ENABLE HIGH
+		 * 2    1       O:MPEG PORT 0=DVB-T 1=DVB-S
 		 * 3    1       I:?
 		 * 4    1       I:?
 		 * 5    1       I:?
@@ -1745,22 +1763,41 @@
 		 * d    0       I
 		 * e    1       O
 		 * f    1       O
+		 *
+		 * WM8775 ADC
+		 *
+		 * 1: TV Audio / FM Mono
+		 * 2: Line-In
+		 * 3: Line-In Expansion
+		 * 4: FM Stereo
 		 */
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
 			.gpio0  = 0xc4bf,
+			/* 1: TV Audio / FM Mono */
+			.audioroute = 1,
 		}, {
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
 			.gpio0  = 0xc4bf,
+			/* 2: Line-In */
+			.audioroute = 2,
 		}, {
 			.type   = CX88_VMUX_SVIDEO,
 			.vmux   = 2,
 			.gpio0  = 0xc4bf,
+			/* 2: Line-In */
+			.audioroute = 2,
 		} },
-		/* fixme: Add radio support */
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0	= 0xc4bf,
+			/* 4: FM Stereo */
+			.audioroute = 8,
+		},
 		.mpeg           = CX88_MPEG_DVB,
+		.num_frontends	= 2,
 	},
 	[CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
 		.name           = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
@@ -2662,10 +2699,13 @@
 
 	case CX88_BOARD_HAUPPAUGE_HVR3000:
 	case CX88_BOARD_HAUPPAUGE_HVR4000:
-	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
 		/* Init GPIO */
 		cx_write(MO_GP0_IO, core->board.input[0].gpio0);
 		udelay(1000);
+		cx_clear(MO_GP0_IO, 0x00000080);
+		udelay(50);
+		cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+		udelay(1000);
 		break;
 	}
 }
@@ -3004,10 +3044,14 @@
 
 	memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
 
-	info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+	if (!core->board.num_frontends)
+		core->board.num_frontends=1;
+
+	info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
 		pci->subsystem_vendor, pci->subsystem_device, core->board.name,
 		core->boardnr, card[core->nr] == core->boardnr ?
-		"insmod option" : "autodetected");
+		"insmod option" : "autodetected",
+		core->board.num_frontends);
 
 	if (tuner[core->nr] != UNSET)
 		core->board.tuner_type = tuner[core->nr];
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index d656fec..60705b0 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -549,7 +549,8 @@
 		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 	}
 	if (bc != 1)
-		printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
+		dprintk(2, "%s: %d buffers handled (should be 1)\n",
+			__func__, bc);
 }
 
 void cx88_shutdown(struct cx88_core *core)
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 344ed26..6968ab0 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -116,13 +116,23 @@
 	struct cx8802_dev *dev= fe->dvb->priv;
 	struct cx8802_driver *drv = NULL;
 	int ret = 0;
+	int fe_id;
+
+	fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
+	if (!fe_id) {
+		printk(KERN_ERR "%s() No frontend found\n", __func__);
+		return -EINVAL;
+	}
 
 	drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
 	if (drv) {
-		if (acquire)
+		if (acquire){
+			dev->frontends.active_fe_id = fe_id;
 			ret = drv->request_acquire(drv);
-		else
+		} else {
 			ret = drv->request_release(drv);
+			dev->frontends.active_fe_id = 0;
+		}
 	}
 
 	return ret;
@@ -396,7 +406,7 @@
 			cx_write(MO_GP0_IO, 0x00006060);
 			break;
 		case SEC_VOLTAGE_OFF:
-			printk("LNB Voltage SEC_VOLTAGE_off\n");
+		   	printk("LNB Voltage SEC_VOLTAGE_off\n");
 			break;
 	}
 
@@ -483,6 +493,7 @@
 static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
 {
 	struct dvb_frontend *fe;
+	struct videobuf_dvb_frontend *fe0 = NULL;
 	struct xc2028_ctrl ctl;
 	struct xc2028_config cfg = {
 		.i2c_adap  = &dev->core->i2c_adap,
@@ -490,7 +501,12 @@
 		.ctrl      = &ctl,
 	};
 
-	if (!dev->dvb.frontend) {
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
+
+	if (!fe0->dvb.frontend) {
 		printk(KERN_ERR "%s/2: dvb frontend not attached. "
 				"Can't attach xc3028\n",
 		       dev->core->name);
@@ -504,10 +520,13 @@
 	 */
 	cx88_setup_xc3028(dev->core, &ctl);
 
-	fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+	fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
 	if (!fe) {
 		printk(KERN_ERR "%s/2: xc3028 attach failed\n",
 		       dev->core->name);
+		dvb_frontend_detach(fe0->dvb.frontend);
+		dvb_unregister_frontend(fe0->dvb.frontend);
+		fe0->dvb.frontend = NULL;
 		return -EINVAL;
 	}
 
@@ -532,8 +551,10 @@
 	struct cx88_core *core = dev->core;
 
 	/* Reset the part */
+	/* Put the cx24116 into reset */
 	cx_write(MO_SRST_IO, 0);
 	msleep(10);
+	/* Take the cx24116 out of reset */
 	cx_write(MO_SRST_IO, 1);
 	msleep(10);
 
@@ -554,14 +575,14 @@
 
 static struct stv0299_config tevii_tuner_sharp_config = {
 	.demod_address = 0x68,
-	.inittab = sharp_z0194a__inittab,
+	.inittab = sharp_z0194a_inittab,
 	.mclk = 88000000UL,
 	.invert = 1,
 	.skip_reinit = 0,
 	.lock_output = 1,
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.min_delay_ms = 100,
-	.set_symbol_rate = sharp_z0194a__set_symbol_rate,
+	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
 	.set_ts_params = cx24116_set_ts_param,
 };
 
@@ -574,19 +595,25 @@
 static int dvb_register(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
+	struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+	int mfe_shared = 0; /* bus not shared by default */
 
-	/* init struct videobuf_dvb */
-	dev->dvb.name = core->name;
-	dev->ts_gen_cntrl = 0x0c;
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
 
-	/* init frontend */
+	/* multi-frontend gate control is undefined or defaults to fe0 */
+	dev->frontends.gate = 0;
+
+	/* init frontend(s) */
 	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
-		dev->dvb.frontend = dvb_attach(cx22702_attach,
+		fe0->dvb.frontend = dvb_attach(cx22702_attach,
 					       &connexant_refboard_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, &core->i2c_adap,
 					DVB_PLL_THOMSON_DTT759X))
 				goto frontend_detach;
@@ -596,11 +623,11 @@
 	case CX88_BOARD_CONEXANT_DVB_T1:
 	case CX88_BOARD_KWORLD_DVB_T_CX22702:
 	case CX88_BOARD_WINFAST_DTV1000:
-		dev->dvb.frontend = dvb_attach(cx22702_attach,
+		fe0->dvb.frontend = dvb_attach(cx22702_attach,
 					       &connexant_refboard_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x60, &core->i2c_adap,
 					DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
@@ -610,33 +637,67 @@
 	case CX88_BOARD_HAUPPAUGE_HVR1100:
 	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
-	case CX88_BOARD_HAUPPAUGE_HVR3000:
-		dev->dvb.frontend = dvb_attach(cx22702_attach,
+		fe0->dvb.frontend = dvb_attach(cx22702_attach,
 					       &hauppauge_hvr_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 				   &core->i2c_adap, 0x61,
 				   TUNER_PHILIPS_FMD1216ME_MK3))
 				goto frontend_detach;
 		}
 		break;
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+		/* DVB-S init */
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
+			       &hauppauge_novas_config,
+			       &dev->core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+			&dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
+				dprintk( 1, "%s(): HVR3000 - DVB-S LNB Init: failed\n", __func__);
+			}
+		} else {
+			dprintk( 1, "%s(): HVR3000 - DVB-S Init: failed\n", __func__);
+		}
+		/* DVB-T init */
+		fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+		if (fe1) {
+			dev->frontends.gate = 2;
+			mfe_shared = 1;
+			fe1->dvb.frontend = dvb_attach(cx22702_attach,
+				&hauppauge_hvr_config,
+				&dev->core->i2c_adap);
+			if (fe1->dvb.frontend) {
+				fe1->dvb.frontend->id = 1;
+				if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
+						&dev->core->i2c_adap, 0x61,
+						TUNER_PHILIPS_FMD1216ME_MK3)) {
+					dprintk( 1, "%s(): HVR3000 - DVB-T misc Init: failed\n", __func__);
+				}
+			} else {
+				dprintk( 1, "%s(): HVR3000 - DVB-T Init: failed\n", __func__);
+			}
+		} else {
+			dprintk( 1, "%s(): HVR3000 - DVB-T Init: can't find frontend 2.\n", __func__);
+		}
+		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-		dev->dvb.frontend = dvb_attach(mt352_attach,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dvico_fusionhdtv,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
 			break;
 		}
 		/* ZL10353 replaces MT352 on later cards */
-		dev->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_plus_v1_1,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
 		}
@@ -644,31 +705,31 @@
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
 		/* The tin box says DEE1601, but it seems to be DTT7579
 		 * compatible, with a slightly different MT352 AGC gain. */
-		dev->dvb.frontend = dvb_attach(mt352_attach,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dvico_fusionhdtv_dual,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
 			break;
 		}
 		/* ZL10353 replaces MT352 on later cards */
-		dev->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_plus_v1_1,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
 		}
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-		dev->dvb.frontend = dvb_attach(mt352_attach,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dvico_fusionhdtv,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_LG_Z201))
 				goto frontend_detach;
 		}
@@ -676,11 +737,11 @@
 	case CX88_BOARD_KWORLD_DVB_T:
 	case CX88_BOARD_DNTV_LIVE_DVB_T:
 	case CX88_BOARD_ADSTECH_DVB_T_PCI:
-		dev->dvb.frontend = dvb_attach(mt352_attach,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dntv_live_dvbt_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_UNKNOWN_1))
 				goto frontend_detach;
 		}
@@ -688,10 +749,10 @@
 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
 		/* MT352 is on a secondary I2C bus made from some GPIO lines */
-		dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+		fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
 					       &dev->vp3054->adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_PHILIPS_FMD1216ME_MK3))
 				goto frontend_detach;
@@ -702,22 +763,22 @@
 #endif
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
-		dev->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_hybrid,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 				   &core->i2c_adap, 0x61,
 				   TUNER_THOMSON_FE6600))
 				goto frontend_detach;
 		}
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
-		dev->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_xc3028,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend == NULL)
-			dev->dvb.frontend = dvb_attach(mt352_attach,
+		if (fe0->dvb.frontend == NULL)
+			fe0->dvb.frontend = dvb_attach(mt352_attach,
 						&dvico_fusionhdtv_mt352_xc3028,
 						&core->i2c_adap);
 		/*
@@ -725,16 +786,16 @@
 		 * We must not permit gate_ctrl to be performed, or
 		 * the xc3028 cannot communicate on the bus.
 		 */
-		if (dev->dvb.frontend)
-			dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+		if (fe0->dvb.frontend)
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
 		if (attach_xc3028(0x61, dev) < 0)
 			return -EINVAL;
 		break;
 	case CX88_BOARD_PCHDTV_HD3000:
-		dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+		fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_THOMSON_DTT761X))
 				goto frontend_detach;
@@ -751,11 +812,11 @@
 
 		/* Select RF connector callback */
 		fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
-		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &fusionhdtv_3_gold,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_MICROTUNE_4042FI5))
 				goto frontend_detach;
@@ -769,11 +830,11 @@
 		mdelay(100);
 		cx_set(MO_GP0_IO, 9);
 		mdelay(200);
-		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &fusionhdtv_3_gold,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_THOMSON_DTT761X))
 				goto frontend_detach;
@@ -787,15 +848,15 @@
 		mdelay(100);
 		cx_set(MO_GP0_IO, 1);
 		mdelay(200);
-		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &fusionhdtv_5_gold,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_LG_TDVS_H06XF))
 				goto frontend_detach;
-			if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
 				   &core->i2c_adap, 0x43))
 				goto frontend_detach;
 		}
@@ -808,25 +869,25 @@
 		mdelay(100);
 		cx_set(MO_GP0_IO, 1);
 		mdelay(200);
-		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &pchdtv_hd5500,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_LG_TDVS_H06XF))
 				goto frontend_detach;
-			if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
 				   &core->i2c_adap, 0x43))
 				goto frontend_detach;
 		}
 		break;
 	case CX88_BOARD_ATI_HDTVWONDER:
-		dev->dvb.frontend = dvb_attach(nxt200x_attach,
+		fe0->dvb.frontend = dvb_attach(nxt200x_attach,
 					       &ati_hdtvwonder,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_PHILIPS_TUV1236D))
 				goto frontend_detach;
@@ -834,49 +895,49 @@
 		break;
 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
 	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-		dev->dvb.frontend = dvb_attach(cx24123_attach,
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
 					       &hauppauge_novas_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend) {
-			if (!dvb_attach(isl6421_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend) {
+			if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
 				goto frontend_detach;
 		}
 		break;
 	case CX88_BOARD_KWORLD_DVBS_100:
-		dev->dvb.frontend = dvb_attach(cx24123_attach,
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
 					       &kworld_dvbs_100_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend) {
-			core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
-			dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
+		if (fe0->dvb.frontend) {
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
 		}
 		break;
 	case CX88_BOARD_GENIATECH_DVBS:
-		dev->dvb.frontend = dvb_attach(cx24123_attach,
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
 					       &geniatech_dvbs_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend) {
-			core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
-			dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
+		if (fe0->dvb.frontend) {
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
 		}
 		break;
 	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-		dev->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 					       &pinnacle_pctv_hd_800i_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
 					&core->i2c_adap,
 					&pinnacle_pctv_hd_800i_tuner_config))
 				goto frontend_detach;
 		}
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
-		dev->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&dvico_hdtv5_pci_nano_config,
 						&core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend != NULL) {
 			struct dvb_frontend *fe;
 			struct xc2028_config cfg = {
 				.i2c_adap  = &core->i2c_adap,
@@ -889,17 +950,17 @@
 			};
 
 			fe = dvb_attach(xc2028_attach,
-					dev->dvb.frontend, &cfg);
+					fe0->dvb.frontend, &cfg);
 			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
 				fe->ops.tuner_ops.set_config(fe, &ctl);
 		}
 		break;
 	 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
-		dev->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &cx88_pinnacle_hybrid_pctv,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend) {
-			dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
 			if (attach_xc3028(0x61, dev) < 0)
 				goto frontend_detach;
 		}
@@ -907,85 +968,118 @@
 	 case CX88_BOARD_GENIATECH_X8000_MT:
 		dev->ts_gen_cntrl = 0x00;
 
-		dev->dvb.frontend = dvb_attach(zl10353_attach,
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &cx88_geniatech_x8000_mt,
 					       &core->i2c_adap);
 		if (attach_xc3028(0x61, dev) < 0)
 			goto frontend_detach;
 		break;
 	 case CX88_BOARD_KWORLD_ATSC_120:
-		dev->dvb.frontend = dvb_attach(s5h1409_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 					       &kworld_atsc_120_config,
 					       &core->i2c_adap);
 		if (attach_xc3028(0x61, dev) < 0)
 			goto frontend_detach;
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
-		dev->dvb.frontend = dvb_attach(s5h1411_attach,
+		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
 					       &dvico_fusionhdtv7_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
 					&core->i2c_adap,
 					&dvico_fusionhdtv7_tuner_config))
 				goto frontend_detach;
 		}
 		break;
 	case CX88_BOARD_HAUPPAUGE_HVR4000:
-	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
-		/* Support for DVB-S only, not DVB-T support */
-		dev->dvb.frontend = dvb_attach(cx24116_attach,
+		/* DVB-S/S2 Init */
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
 			&hauppauge_hvr4000_config,
 			&dev->core->i2c_adap);
-		if (dev->dvb.frontend) {
-			dvb_attach(isl6421_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend) {
+			if(!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+				&dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
+				dprintk( 1, "%s(): HVR4000 - DVB-S LNB Init: failed\n", __func__);
+			}
+		} else {
+			dprintk( 1, "%s(): HVR4000 - DVB-S Init: failed\n", __func__);
+		}
+		/* DVB-T Init */
+		fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+		if (fe1) {
+			dev->frontends.gate = 2;
+			mfe_shared = 1;
+			fe1->dvb.frontend = dvb_attach(cx22702_attach,
+				&hauppauge_hvr_config,
+				&dev->core->i2c_adap);
+			if (fe1->dvb.frontend) {
+				fe1->dvb.frontend->id = 1;
+				if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
+					&dev->core->i2c_adap, 0x61,
+					TUNER_PHILIPS_FMD1216ME_MK3)) {
+					dprintk( 1, "%s(): HVR4000 - DVB-T misc Init: failed\n", __func__);
+				}
+			} else {
+				dprintk( 1, "%s(): HVR4000 - DVB-T Init: failed\n", __func__);
+			}
+		} else {
+			dprintk( 1, "%s(): HVR4000 - DVB-T Init: can't find frontend 2.\n", __func__);
+		}
+		break;
+	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+			&hauppauge_hvr4000_config,
+			&dev->core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			dvb_attach(isl6421_attach, fe0->dvb.frontend,
 				&dev->core->i2c_adap,
 				0x08, ISL6421_DCL, 0x00);
 		}
 		break;
 	case CX88_BOARD_TEVII_S420:
-		dev->dvb.frontend = dvb_attach(stv0299_attach,
+		fe0->dvb.frontend = dvb_attach(stv0299_attach,
 						&tevii_tuner_sharp_config,
 						&core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
 					&core->i2c_adap, DVB_PLL_OPERA1))
 				goto frontend_detach;
-			core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
-			dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 
 		} else {
-			dev->dvb.frontend = dvb_attach(stv0288_attach,
+			fe0->dvb.frontend = dvb_attach(stv0288_attach,
 							    &tevii_tuner_earda_config,
 							    &core->i2c_adap);
-				if (dev->dvb.frontend != NULL) {
-					if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61,
+				if (fe0->dvb.frontend != NULL) {
+					if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
 						&core->i2c_adap))
 					goto frontend_detach;
-				core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
-				dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+				core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+				fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 
 			}
 		}
 		break;
 	case CX88_BOARD_TEVII_S460:
-		dev->dvb.frontend = dvb_attach(cx24116_attach,
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
 					       &tevii_s460_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
-			dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+		if (fe0->dvb.frontend != NULL) {
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 		}
 		break;
 	case CX88_BOARD_OMICOM_SS4_PCI:
 	case CX88_BOARD_TBS_8920:
 	case CX88_BOARD_PROF_7300:
-		dev->dvb.frontend = dvb_attach(cx24116_attach,
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
 					       &hauppauge_hvr4000_config,
 					       &core->i2c_adap);
-		if (dev->dvb.frontend != NULL) {
-			core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
-			dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+		if (fe0->dvb.frontend != NULL) {
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 		}
 		break;
 	default:
@@ -993,29 +1087,32 @@
 		       core->name);
 		break;
 	}
-	if (NULL == dev->dvb.frontend) {
+
+        if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
 		printk(KERN_ERR
 		       "%s/2: frontend initialization failed\n",
 		       core->name);
 		return -EINVAL;
 	}
 	/* define general-purpose callback pointer */
-	dev->dvb.frontend->callback = cx88_tuner_callback;
+	fe0->dvb.frontend->callback = cx88_tuner_callback;
 
 	/* Ensure all frontends negotiate bus access */
-	dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+	fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+	if (fe1)
+		fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
 
 	/* Put the analog decoder in standby to keep it quiet */
 	cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL);
 
 	/* register everything */
-	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
-				     &dev->pci->dev, adapter_nr);
+	return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+		&dev->pci->dev, adapter_nr, mfe_shared);
 
 frontend_detach:
-	if (dev->dvb.frontend) {
-		dvb_frontend_detach(dev->dvb.frontend);
-		dev->dvb.frontend = NULL;
+	if (fe0->dvb.frontend) {
+		dvb_frontend_detach(fe0->dvb.frontend);
+		fe0->dvb.frontend = NULL;
 	}
 	return -EINVAL;
 }
@@ -1039,6 +1136,38 @@
 		cx_clear(MO_GP0_IO, 0x00000004);
 		udelay(1000);
 		break;
+
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+	case CX88_BOARD_HAUPPAUGE_HVR4000:
+		if(core->dvbdev->frontends.active_fe_id == 1) {
+			/* DVB-S/S2 Enabled */
+
+			/* Toggle reset on cx22702 leaving i2c active */
+			cx_write(MO_GP0_IO, (core->board.input[0].gpio0 & 0x0000ff00) | 0x00000080);
+			udelay(1000);
+			cx_clear(MO_GP0_IO, 0x00000080);
+			udelay(50);
+			cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset */
+			cx_set(MO_GP0_IO, 0x00000004); /* tri-state the cx22702 pins */
+			udelay(1000);
+
+			cx_write(MO_SRST_IO, 1); /* Take the cx24116/cx24123 out of reset */
+			core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
+		} else
+		if (core->dvbdev->frontends.active_fe_id == 2) {
+			/* DVB-T Enabled */
+
+			/* Put the cx24116/cx24123 into reset */
+			cx_write(MO_SRST_IO, 0);
+
+			/* cx22702 out of reset and enable it */
+			cx_set(MO_GP0_IO,   0x00000080);
+			cx_clear(MO_GP0_IO, 0x00000004);
+			core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
+			udelay(1000);
+		}
+		break;
+
 	default:
 		err = -ENODEV;
 	}
@@ -1056,6 +1185,9 @@
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 		/* Do Nothing, leave the cx22702 on the bus. */
 		break;
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+	case CX88_BOARD_HAUPPAUGE_HVR4000:
+		break;
 	default:
 		err = -ENODEV;
 	}
@@ -1066,7 +1198,8 @@
 {
 	struct cx88_core *core = drv->core;
 	struct cx8802_dev *dev = drv->core->dvbdev;
-	int err;
+	int err, i;
+	struct videobuf_dvb_frontend *fe;
 
 	dprintk( 1, "%s\n", __func__);
 	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
@@ -1086,18 +1219,28 @@
 
 	/* dvb stuff */
 	printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
-	videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
+	dev->ts_gen_cntrl = 0x0c;
+
+	for (i = 1; i <= core->board.num_frontends; i++) {
+		fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+		if (!fe) {
+			printk(KERN_ERR "%s() failed to get frontend(%d)\n", __func__, i);
+			continue;
+		}
+		videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
 			    &dev->pci->dev, &dev->slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_TOP,
 			    sizeof(struct cx88_buffer),
 			    dev);
+		/* init struct videobuf_dvb */
+		fe->dvb.name = dev->core->name;
+	}
 	err = dvb_register(dev);
 	if (err != 0)
 		printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
 		       core->name, err);
-
- fail_core:
+fail_core:
 	return err;
 }
 
@@ -1105,9 +1248,7 @@
 {
 	struct cx8802_dev *dev = drv->core->dvbdev;
 
-	/* dvb */
-	if (dev->dvb.frontend)
-		videobuf_dvb_unregister(&dev->dvb);
+	videobuf_dvb_unregister_bus(&dev->frontends);
 
 	vp3054_i2c_remove(dev);
 
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 8e74d64..01de230 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -116,18 +116,25 @@
 
 void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
 {
+	struct videobuf_dvb_frontends *f = &core->dvbdev->frontends;
+	struct videobuf_dvb_frontend *fe = NULL;
 	if (0 != core->i2c_rc)
 		return;
 
 #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
-	if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) {
-		if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
-			core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
+	if (core->dvbdev && f) {
+		if(f->gate <= 1) /* undefined or fe0 */
+			fe = videobuf_dvb_get_frontend(f, 1);
+		else
+			fe = videobuf_dvb_get_frontend(f, f->gate);
+
+		if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+			fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 1);
 
 		i2c_clients_command(&core->i2c_adap, cmd, arg);
 
-		if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
-			core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
+		if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+			fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 0);
 	} else
 #endif
 		i2c_clients_command(&core->i2c_adap, cmd, arg);
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index a6b061c..6df5cf3 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -768,7 +768,8 @@
 {
 	struct cx8802_dev *dev;
 	struct cx88_core  *core;
-	int err;
+	struct videobuf_dvb_frontend *demod;
+	int err,i;
 
 	/* general setup */
 	core = cx88_core_get(pci_dev);
@@ -781,6 +782,11 @@
 	if (!core->board.mpeg)
 		goto fail_core;
 
+	if (!core->board.num_frontends) {
+		printk(KERN_ERR "%s() .num_frontends should be non-zero, err = %d\n", __func__, err);
+		goto fail_core;
+	}
+
 	err = -ENOMEM;
 	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
 	if (NULL == dev)
@@ -795,6 +801,20 @@
 	INIT_LIST_HEAD(&dev->drvlist);
 	list_add_tail(&dev->devlist,&cx8802_devlist);
 
+	mutex_init(&dev->frontends.lock);
+	INIT_LIST_HEAD(&dev->frontends.felist);
+
+	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends);
+
+	for (i = 1; i <= core->board.num_frontends; i++) {
+		demod = videobuf_dvb_alloc_frontend(&dev->frontends, i);
+		if(demod == NULL) {
+			printk(KERN_ERR "%s() failed to alloc\n", __func__);
+			err = -ENOMEM;
+			goto fail_free;
+		}
+	}
+
 	/* Maintain a reference so cx88-video can query the 8802 device. */
 	core->dvbdev = dev;
 
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 3a1977f..7dd506b 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -767,6 +767,14 @@
 	case WW_FM:
 		set_audio_standard_FM(core, radio_deemphasis);
 		break;
+	case WW_I2SADC:
+		set_audio_start(core, 0x01);
+		/* Slave/Philips/Autobaud */
+		cx_write(AUD_I2SINPUTCNTL, 0);
+		/* Switch to "I2S ADC mode" */
+		cx_write(AUD_I2SCNTL, 0x1);
+		set_audio_finish(core, EN_I2SIN_ENABLE);
+		break;
 	case WW_NONE:
 	default:
 		printk("%s/0: unknown tv audio mode [%d]\n",
@@ -895,6 +903,9 @@
 			break;
 		}
 		break;
+	case WW_I2SADC:
+		/* DO NOTHING */
+		break;
 	}
 
 	if (UNSET != ctl) {
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index be45955..3904b73 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -426,24 +426,7 @@
 
 	/* if there are audioroutes defined, we have an external
 	   ADC to deal with audio */
-
 	if (INPUT(input).audioroute) {
-
-		/* cx2388's C-ADC is connected to the tuner only.
-		   When used with S-Video, that ADC is busy dealing with
-		   chroma, so an external must be used for baseband audio */
-
-		if (INPUT(input).type != CX88_VMUX_TELEVISION &&
-			INPUT(input).type != CX88_RADIO) {
-			/* "ADC mode" */
-			cx_write(AUD_I2SCNTL, 0x1);
-			cx_set(AUD_CTL, EN_I2SIN_ENABLE);
-		} else {
-			/* Normal mode */
-			cx_write(AUD_I2SCNTL, 0x0);
-			cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
-		}
-
 		/* The wm8775 module has the "2" route hardwired into
 		   the initialization. Some boards may use different
 		   routes for different inputs. HVR-1300 surely does */
@@ -454,9 +437,19 @@
 			route.input = INPUT(input).audioroute;
 			cx88_call_i2c_clients(core,
 				VIDIOC_INT_S_AUDIO_ROUTING, &route);
-
 		}
-
+		/* cx2388's C-ADC is connected to the tuner only.
+		   When used with S-Video, that ADC is busy dealing with
+		   chroma, so an external must be used for baseband audio */
+		if (INPUT(input).type != CX88_VMUX_TELEVISION ) {
+			/* "I2S ADC mode" */
+			core->tvaudio = WW_I2SADC;
+			cx88_set_tvaudio(core);
+		} else {
+			/* Normal mode */
+			cx_write(AUD_I2SCNTL, 0x0);
+			cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+		}
 	}
 
 	return 0;
@@ -832,9 +825,24 @@
 		cx_write(MO_GP0_IO, core->board.radio.gpio0);
 		cx_write(MO_GP1_IO, core->board.radio.gpio1);
 		cx_write(MO_GP2_IO, core->board.radio.gpio2);
-		core->tvaudio = WW_FM;
-		cx88_set_tvaudio(core);
-		cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+		if (core->board.radio.audioroute) {
+			if(core->board.audio_chip &&
+				core->board.audio_chip == V4L2_IDENT_WM8775) {
+				struct v4l2_routing route;
+
+				route.input = core->board.radio.audioroute;
+				cx88_call_i2c_clients(core,
+					VIDIOC_INT_S_AUDIO_ROUTING, &route);
+			}
+			/* "I2S ADC mode" */
+			core->tvaudio = WW_I2SADC;
+			cx88_set_tvaudio(core);
+		} else {
+			/* FM Mode */
+			core->tvaudio = WW_FM;
+			cx88_set_tvaudio(core);
+			cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+		}
 		cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
 	}
 	unlock_kernel();
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index dbf01b8..76207c2 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -247,7 +247,7 @@
 	enum cx88_itype type;
 	u32             gpio0, gpio1, gpio2, gpio3;
 	unsigned int    vmux:2;
-	unsigned int    audioroute:2;
+	unsigned int    audioroute:4;
 };
 
 struct cx88_board {
@@ -261,6 +261,7 @@
 	struct cx88_input       radio;
 	enum cx88_board_type    mpeg;
 	unsigned int            audio_chip;
+	int			num_frontends;
 };
 
 struct cx88_subid {
@@ -356,6 +357,7 @@
 	struct cx8802_dev          *dvbdev;
 	enum cx88_board_type       active_type_id;
 	int			   active_ref;
+	int			   active_fe_id;
 };
 
 struct cx8800_dev;
@@ -490,7 +492,7 @@
 
 #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
 	/* for dvb only */
-	struct videobuf_dvb        dvb;
+	struct videobuf_dvb_frontends frontends;
 #endif
 
 #if defined(CONFIG_VIDEO_CX88_VP3054) || \
@@ -628,6 +630,7 @@
 #define WW_EIAJ		 7
 #define WW_I2SPT	 8
 #define WW_FM		 9
+#define WW_I2SADC	 10
 
 void cx88_set_tvaudio(struct cx88_core *core);
 void cx88_newstation(struct cx88_core *core);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index c21af31..e48fbfc 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -21,6 +21,7 @@
 #define MODULE_NAME "gspca"
 
 #include <linux/init.h>
+#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
@@ -403,7 +404,7 @@
 	unsigned int i;
 
 	PDEBUG(D_STREAM, "kill transfer");
-	for (i = 0; i < MAX_NURBS; ++i) {
+	for (i = 0; i < MAX_NURBS; i++) {
 		urb = gspca_dev->urb[i];
 		if (urb == NULL)
 			break;
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 4779dd0..1d9dc90 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -2,7 +2,6 @@
 #define GSPCAV2_H
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/videodev2.h>
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h
index c786d7d..1a37ae4 100644
--- a/drivers/media/video/gspca/m5602/m5602_bridge.h
+++ b/drivers/media/video/gspca/m5602/m5602_bridge.h
@@ -1,7 +1,7 @@
 /*
  * USB Driver for ALi m5602 based webcams
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -25,33 +25,6 @@
 
 /*****************************************************************************/
 
-#undef PDEBUG
-#undef info
-#undef err
-
-#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
-	format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
-	format "\n" , ## arg)
-
-/* Debug parameters */
-#define DBG_INIT 0x1
-#define DBG_PROBE 0x2
-#define DBG_V4L2 0x4
-#define DBG_TRACE 0x8
-#define DBG_DATA 0x10
-#define DBG_V4L2_CID 0x20
-#define DBG_GSPCA 0x40
-
-#define PDEBUG(level, fmt, args...) \
-	do { \
-		if (m5602_debug & level)     \
-			info("[%s:%d] " fmt, __func__, __LINE__ , \
-			## args); \
-	} while (0)
-
-/*****************************************************************************/
-
 #define M5602_XB_SENSOR_TYPE 0x00
 #define M5602_XB_SENSOR_CTRL 0x01
 #define M5602_XB_LINE_OF_FRAME_H 0x02
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index 19d5e35..fd6ce38 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -1,7 +1,7 @@
-/*
+ /*
  * USB Driver for ALi m5602 based webcams
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -26,7 +26,6 @@
 int force_sensor;
 int dump_bridge;
 int dump_sensor;
-unsigned int m5602_debug;
 
 static const __devinitdata struct usb_device_id m5602_table[] = {
 	{USB_DEVICE(0x0402, 0x5602)},
@@ -48,7 +47,7 @@
 			      1, M5602_URB_MSG_TIMEOUT);
 	*i2c_data = buf[0];
 
-	PDEBUG(DBG_TRACE, "Reading bridge register 0x%x containing 0x%x",
+	PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x",
 	       address, *i2c_data);
 
 	/* usb_control_msg(...) returns the number of bytes sent upon success,
@@ -63,7 +62,7 @@
 	struct usb_device *udev = sd->gspca_dev.dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
 
-	PDEBUG(DBG_TRACE, "Writing bridge register 0x%x with 0x%x",
+	PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x",
 	       address, i2c_data);
 
 	memcpy(buf, bridge_urb_skeleton,
@@ -91,7 +90,8 @@
 		m5602_read_bridge(sd, i, &val);
 		info("ALi m5602 address 0x%x contains 0x%x", i, val);
 	}
-	info("Warning: The camera probably won't work until it's power cycled");
+	info("Warning: The ALi m5602 webcam probably won't work "
+		"until it's power cycled");
 }
 
 static int m5602_probe_sensor(struct sd *sd)
@@ -135,7 +135,7 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	int err;
 
-	PDEBUG(DBG_TRACE, "Initializing ALi m5602 webcam");
+	PDEBUG(D_CONF, "Initializing ALi m5602 webcam");
 	/* Run the init sequence */
 	err = sd->sensor->init(sd);
 
@@ -146,16 +146,18 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	__u8 *buf = sd->gspca_dev.usb_buf;
+	int err;
 
 	/* Send start command to the camera */
 	const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
 	memcpy(buf, buffer, sizeof(buffer));
-	usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0),
-			0x04, 0x40, 0x19, 0x0000, buf,
-			4, M5602_URB_MSG_TIMEOUT);
+	err = usb_control_msg(gspca_dev->dev,
+			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      0x04, 0x40, 0x19, 0x0000, buf,
+			      4, M5602_URB_MSG_TIMEOUT);
 
-	PDEBUG(DBG_V4L2, "Transfer started");
-	return 0;
+	PDEBUG(D_STREAM, "Transfer started");
+	return (err < 0) ? err : 0;
 }
 
 static void m5602_urb_complete(struct gspca_dev *gspca_dev,
@@ -165,14 +167,14 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	if (len < 6) {
-		PDEBUG(DBG_DATA, "Packet is less than 6 bytes");
+		PDEBUG(D_PACK, "Packet is less than 6 bytes");
 		return;
 	}
 
 	/* Frame delimiter: ff xx xx xx ff ff */
 	if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
 	    data[2] != sd->frame_id) {
-		PDEBUG(DBG_DATA, "Frame delimiter detected");
+		PDEBUG(D_FRAM, "Frame delimiter detected");
 		sd->frame_id = data[2];
 
 		/* Remove the extra fluff appended on each header */
@@ -187,7 +189,7 @@
 		/* Create a new frame */
 		gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
 
-		PDEBUG(DBG_V4L2, "Starting new frame %d",
+		PDEBUG(D_FRAM, "Starting new frame %d",
 		       sd->frame_count);
 
 	} else {
@@ -198,7 +200,7 @@
 		len -= 4;
 
 		if (cur_frame_len + len <= frame->v4l2_buf.length) {
-			PDEBUG(DBG_DATA, "Continuing frame %d copying %d bytes",
+			PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes",
 			       sd->frame_count, len);
 
 			gspca_frame_add(gspca_dev, INTER_PACKET, frame,
@@ -234,8 +236,6 @@
 	struct cam *cam;
 	int err;
 
-	PDEBUG(DBG_GSPCA, "m5602_configure start");
-
 	cam = &gspca_dev->cam;
 	cam->epaddr = M5602_ISOC_ENDPOINT_ADDR;
 	sd->desc = &sd_desc;
@@ -248,11 +248,10 @@
 	if (err)
 		goto fail;
 
-	PDEBUG(DBG_GSPCA, "m5602_configure end");
 	return 0;
 
 fail:
-	PDEBUG(DBG_GSPCA, "m5602_configure failed");
+	PDEBUG(D_ERR, "ALi m5602 webcam failed");
 	cam->cam_mode = NULL;
 	cam->nmodes = 0;
 
@@ -282,13 +281,13 @@
 {
 	if (usb_register(&sd_driver) < 0)
 		return -1;
-	PDEBUG(D_PROBE, "m5602 module registered");
+	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
 static void __exit mod_m5602_exit(void)
 {
 	usb_deregister(&sd_driver);
-	PDEBUG(D_PROBE, "m5602 module deregistered");
+	PDEBUG(D_PROBE, "deregistered");
 }
 
 module_init(mod_m5602_init);
@@ -297,9 +296,6 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "toggles debug on/off");
-
 module_param(force_sensor, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(force_sensor,
 		"force detection of sensor, "
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
index 566d492..fb700c2 100644
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -1,7 +1,7 @@
 /*
  * Driver for the mt9m111 sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -107,7 +107,7 @@
 	err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
 				  data, 2);
 	*val = data[0] & MT9M111_RMB_MIRROR_ROWS;
-	PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
+	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -118,7 +118,7 @@
 	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
+	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 
 	/* Set the correct page map */
 	err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
@@ -145,7 +145,7 @@
 	err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
 				  data, 2);
 	*val = data[0] & MT9M111_RMB_MIRROR_COLS;
-	PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
+	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -156,7 +156,7 @@
 	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val);
+	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
 
 	/* Set the correct page map */
 	err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
@@ -188,7 +188,7 @@
 	      ((tmp & (1 <<  8)) * 2) |
 	       (tmp & 0x7f);
 
-	PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+	PDEBUG(D_V4L2, "Read gain %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -222,7 +222,7 @@
 
 	data[1] = (tmp & 0xff00) >> 8;
 	data[0] = (tmp & 0xff);
-	PDEBUG(DBG_V4L2_CID, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
+	PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
 	       data[1], data[0]);
 
 	err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
@@ -257,7 +257,7 @@
 	for (i = 0; i < len && !err; i++) {
 		err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
 
-		PDEBUG(DBG_TRACE, "Reading sensor register "
+		PDEBUG(D_CONF, "Reading sensor register "
 		       "0x%x contains 0x%x ", address, *i2c_data);
 	}
 out:
@@ -290,7 +290,7 @@
 		memcpy(p, sensor_urb_skeleton + 16, 4);
 		p[3] = i2c_data[i];
 		p += 4;
-		PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+		PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
 		       address, i2c_data[i]);
 	}
 
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
index 79a5d88..315209d5 100644
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.h
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
@@ -1,7 +1,7 @@
 /*
  * Driver for the mt9m111 sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -82,7 +82,6 @@
 /* Kernel module parameters */
 extern int force_sensor;
 extern int dump_sensor;
-extern unsigned int m5602_debug;
 
 int mt9m111_probe(struct sd *sd);
 int mt9m111_init(struct sd *sd);
@@ -152,8 +151,8 @@
 			.default_value  = DEFAULT_GAIN,
 			.flags          = V4L2_CTRL_FLAG_SLIDER
 		},
-		.set = mt9m111_set_hflip,
-		.get = mt9m111_get_hflip
+		.set = mt9m111_set_gain,
+		.get = mt9m111_get_gain
 	}
 	},
 
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
index 31c5896..837c7e47 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -1,7 +1,7 @@
 /*
  * Driver for the ov9650 sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -40,7 +40,7 @@
 	for (i = 0; i < len; i++) {
 		err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
 
-		PDEBUG(DBG_TRACE, "Reading sensor register "
+		PDEBUG(D_CONF, "Reading sensor register "
 				"0x%x containing 0x%x ", address, *i2c_data);
 	}
 	return (err < 0) ? err : 0;
@@ -72,7 +72,7 @@
 		memcpy(p, sensor_urb_skeleton + 16, 4);
 		p[3] = i2c_data[i];
 		p += 4;
-		PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+		PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
 		       address, i2c_data[i]);
 	}
 
@@ -199,7 +199,7 @@
 		goto out;
 	*val |= (i2c_data & 0x3f) << 10;
 
-	PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val);
+	PDEBUG(D_V4L2, "Read exposure %d", *val);
 out:
 	return (err < 0) ? err : 0;
 }
@@ -210,7 +210,7 @@
 	u8 i2c_data;
 	int err;
 
-	PDEBUG(DBG_V4L2_CID, "Set exposure to %d",
+	PDEBUG(D_V4L2, "Set exposure to %d",
 	       val & 0xffff);
 
 	/* The 6 MSBs */
@@ -246,7 +246,7 @@
 
 	err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
 	*val |= i2c_data;
-	PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+	PDEBUG(D_V4L2, "Read gain %d", *val);
 	return (err < 0) ? err : 0;
 }
 
@@ -280,7 +280,7 @@
 	err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1);
 	*val = i2c_data;
 
-	PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val);
+	PDEBUG(D_V4L2, "Read red gain %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -291,7 +291,7 @@
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set red gain to %d",
+	PDEBUG(D_V4L2, "Set red gain to %d",
 			     val & 0xff);
 
 	i2c_data = val & 0xff;
@@ -309,7 +309,7 @@
 	err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
 	*val = i2c_data;
 
-	PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val);
+	PDEBUG(D_V4L2, "Read blue gain %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -320,7 +320,7 @@
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set blue gain to %d",
+	PDEBUG(D_V4L2, "Set blue gain to %d",
 	       val & 0xff);
 
 	i2c_data = val & 0xff;
@@ -340,7 +340,7 @@
 		*val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
 	else
 		*val = (i2c_data & OV9650_HFLIP) >> 5;
-	PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
+	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -351,7 +351,7 @@
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val);
+	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
 	err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 	if (err < 0)
 		goto out;
@@ -379,7 +379,7 @@
 		*val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
 	else
 		*val = (i2c_data & 0x10) >> 4;
-	PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
+	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -390,7 +390,7 @@
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
+	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 	err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 	if (err < 0)
 		goto out;
@@ -420,7 +420,7 @@
 
 	err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
 	*val |= i2c_data;
-	PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+	PDEBUG(D_V4L2, "Read gain %d", *val);
 out:
 	return (err < 0) ? err : 0;
 }
@@ -431,7 +431,7 @@
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set gain to %d", val & 0x3ff);
+	PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff);
 
 	/* Read the OV9650_VREF register first to avoid
 		corrupting the VREF high and low bits */
@@ -461,7 +461,7 @@
 
 	err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	*val = (i2c_data & OV9650_AWB_EN) >> 1;
-	PDEBUG(DBG_V4L2_CID, "Read auto white balance %d", *val);
+	PDEBUG(D_V4L2, "Read auto white balance %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -472,7 +472,7 @@
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set auto white balance to %d", val);
+	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
 	err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	if (err < 0)
 		goto out;
@@ -491,7 +491,7 @@
 
 	err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	*val = (i2c_data & OV9650_AGC_EN) >> 2;
-	PDEBUG(DBG_V4L2_CID, "Read auto gain control %d", *val);
+	PDEBUG(D_V4L2, "Read auto gain control %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -502,7 +502,7 @@
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	PDEBUG(DBG_V4L2_CID, "Set auto gain control to %d", val);
+	PDEBUG(D_V4L2, "Set auto gain control to %d", val);
 	err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	if (err < 0)
 		goto out;
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
index 2f29cb0..065632f 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.h
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h
@@ -1,7 +1,7 @@
 /*
  * Driver for the ov9650 sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -121,7 +121,6 @@
 /* Kernel module parameters */
 extern int force_sensor;
 extern int dump_sensor;
-extern unsigned int m5602_debug;
 
 int ov9650_probe(struct sd *sd);
 int ov9650_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
index 08c015b..d17ac52 100644
--- a/drivers/media/video/gspca/m5602/m5602_po1030.c
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -1,7 +1,7 @@
 /*
  * Driver for the po1030 sensor
  *
- * Copyright (c) 2008 Erik Andren
+ * Copyright (c) 2008 Erik Andrén
  * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -82,7 +82,7 @@
 	for (i = 0; i < len; i++) {
 		err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
 
-		PDEBUG(DBG_TRACE, "Reading sensor register "
+		PDEBUG(D_CONF, "Reading sensor register "
 				"0x%x containing 0x%x ", address, *i2c_data);
 	}
 	return (err < 0) ? err : 0;
@@ -112,7 +112,7 @@
 		memcpy(p, sensor_urb_skeleton + 16, 4);
 		p[3] = i2c_data[i];
 		p += 4;
-		PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+		PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
 		       address, i2c_data[i]);
 	}
 
@@ -185,7 +185,7 @@
 				 &i2c_data, 1);
 	*val |= i2c_data;
 
-	PDEBUG(DBG_V4L2_CID, "Exposure read as %d", *val);
+	PDEBUG(D_V4L2, "Exposure read as %d", *val);
 out:
 	return (err < 0) ? err : 0;
 }
@@ -196,10 +196,10 @@
 	u8 i2c_data;
 	int err;
 
-	PDEBUG(DBG_V4L2, "Set exposure to %d", val & 0xffff);
+	PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
 
 	i2c_data = ((val & 0xff00) >> 8);
-	PDEBUG(DBG_V4L2, "Set exposure to high byte to 0x%x",
+	PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
 	       i2c_data);
 
 	err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H,
@@ -208,7 +208,7 @@
 		goto out;
 
 	i2c_data = (val & 0xff);
-	PDEBUG(DBG_V4L2, "Set exposure to low byte to 0x%x",
+	PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
 	       i2c_data);
 	err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M,
 				  &i2c_data, 1);
@@ -226,7 +226,71 @@
 	err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
 				 &i2c_data, 1);
 	*val = i2c_data;
-	PDEBUG(DBG_V4L2_CID, "Read global gain %d", *val);
+	PDEBUG(D_V4L2, "Read global gain %d", *val);
+
+	return (err < 0) ? err : 0;
+}
+
+int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 i2c_data;
+	int err;
+
+	err = po1030_read_sensor(sd, PO1030_REG_CONTROL2,
+				 &i2c_data, 1);
+
+	*val = (i2c_data >> 7) & 0x01 ;
+
+	PDEBUG(D_V4L2, "Read hflip %d", *val);
+
+	return (err < 0) ? err : 0;
+}
+
+int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 i2c_data;
+	int err;
+
+	PDEBUG(D_V4L2, "Set hflip %d", val);
+
+	i2c_data = (val & 0x01) << 7;
+
+	err = po1030_write_sensor(sd, PO1030_REG_CONTROL2,
+				  &i2c_data, 1);
+
+	return (err < 0) ? err : 0;
+}
+
+int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 i2c_data;
+	int err;
+
+	err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
+				 &i2c_data, 1);
+
+	*val = (i2c_data >> 6) & 0x01;
+
+	PDEBUG(D_V4L2, "Read vflip %d", *val);
+
+	return (err < 0) ? err : 0;
+}
+
+int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 i2c_data;
+	int err;
+
+	PDEBUG(D_V4L2, "Set vflip %d", val);
+
+	i2c_data = (val & 0x01) << 6;
+
+	err = po1030_write_sensor(sd, PO1030_REG_CONTROL2,
+				  &i2c_data, 1);
 
 	return (err < 0) ? err : 0;
 }
@@ -238,7 +302,7 @@
 	int err;
 
 	i2c_data = val & 0xff;
-	PDEBUG(DBG_V4L2, "Set global gain to %d", i2c_data);
+	PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
 	err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN,
 				  &i2c_data, 1);
 	return (err < 0) ? err : 0;
@@ -253,7 +317,7 @@
 	err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN,
 				 &i2c_data, 1);
 	*val = i2c_data;
-	PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val);
+	PDEBUG(D_V4L2, "Read red gain %d", *val);
 	return (err < 0) ? err : 0;
 }
 
@@ -264,7 +328,7 @@
 	int err;
 
 	i2c_data = val & 0xff;
-	PDEBUG(DBG_V4L2, "Set red gain to %d", i2c_data);
+	PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
 	err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN,
 				  &i2c_data, 1);
 	return (err < 0) ? err : 0;
@@ -279,7 +343,7 @@
 	err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN,
 				 &i2c_data, 1);
 	*val = i2c_data;
-	PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val);
+	PDEBUG(D_V4L2, "Read blue gain %d", *val);
 
 	return (err < 0) ? err : 0;
 }
@@ -290,7 +354,7 @@
 	u8 i2c_data;
 	int err;
 	i2c_data = val & 0xff;
-	PDEBUG(DBG_V4L2, "Set blue gain to %d", i2c_data);
+	PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
 	err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN,
 				  &i2c_data, 1);
 
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
index 68f34c9..a0b75ff 100644
--- a/drivers/media/video/gspca/m5602/m5602_po1030.h
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.h
@@ -1,8 +1,7 @@
 /*
  * Driver for the po1030 sensor.
- * This is probably a pixel plus sensor but we haven't identified it yet
  *
- * Copyright (c) 2008 Erik Andren
+ * Copyright (c) 2008 Erik Andrén
  * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -109,10 +108,13 @@
 #define PO1030_REG_YCONTRAST		0x74
 #define PO1030_REG_YSATURATION		0x75
 
+#define PO1030_HFLIP			(1 << 7)
+#define PO1030_VFLIP			(1 << 6)
+
 /*****************************************************************************/
 
 #define PO1030_GLOBAL_GAIN_DEFAULT	0x12
-#define PO1030_EXPOSURE_DEFAULT		0xf0ff
+#define PO1030_EXPOSURE_DEFAULT		0x0085
 #define PO1030_BLUE_GAIN_DEFAULT 	0x40
 #define PO1030_RED_GAIN_DEFAULT 	0x40
 
@@ -121,7 +123,6 @@
 /* Kernel module parameters */
 extern int force_sensor;
 extern int dump_sensor;
-extern unsigned int m5602_debug;
 
 int po1030_probe(struct sd *sd);
 int po1030_init(struct sd *sd);
@@ -142,6 +143,10 @@
 int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
 int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
 int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
 
 static struct m5602_sensor po1030 = {
 	.name = "PO1030",
@@ -152,7 +157,7 @@
 	.init = po1030_init,
 	.power_down = po1030_power_down,
 
-	.nctrls = 4,
+	.nctrls = 6,
 	.ctrls = {
 	{
 		{
@@ -160,7 +165,7 @@
 			.type 		= V4L2_CTRL_TYPE_INTEGER,
 			.name 		= "gain",
 			.minimum 	= 0x00,
-			.maximum 	= 0xff,
+			.maximum 	= 0x4f,
 			.step 		= 0x1,
 			.default_value 	= PO1030_GLOBAL_GAIN_DEFAULT,
 			.flags         	= V4L2_CTRL_FLAG_SLIDER
@@ -173,7 +178,7 @@
 			.type 		= V4L2_CTRL_TYPE_INTEGER,
 			.name 		= "exposure",
 			.minimum 	= 0x00,
-			.maximum 	= 0xffff,
+			.maximum 	= 0x02ff,
 			.step 		= 0x1,
 			.default_value 	= PO1030_EXPOSURE_DEFAULT,
 			.flags         	= V4L2_CTRL_FLAG_SLIDER
@@ -206,8 +211,33 @@
 		},
 		.set = po1030_set_blue_balance,
 		.get = po1030_get_blue_balance
+	}, {
+		{
+			.id 		= V4L2_CID_HFLIP,
+			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name 		= "horizontal flip",
+			.minimum 	= 0,
+			.maximum 	= 1,
+			.step 		= 1,
+			.default_value 	= 0,
+		},
+		.set = po1030_set_hflip,
+		.get = po1030_get_hflip
+	}, {
+		{
+			.id 		= V4L2_CID_VFLIP,
+			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name 		= "vertical flip",
+			.minimum 	= 0,
+			.maximum 	= 1,
+			.step 		= 1,
+			.default_value 	= 0,
+		},
+		.set = po1030_set_vflip,
+		.get = po1030_get_vflip
 	}
 	},
+
 	.nmodes = 1,
 	.modes = {
 	{
@@ -381,7 +411,7 @@
 
 	/* Set the y window to 1 */
 	{SENSOR, PO1030_REG_WINDOWY_H, 0x00},
-	{SENSOR, PO1030_REG_WINDOWX_L, 0x01},
+	{SENSOR, PO1030_REG_WINDOWY_L, 0x01},
 
 	{SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02},
 	{SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87},
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index 6820256..14b1eac 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -1,7 +1,7 @@
 /*
  * Driver for the s5k4aa sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -117,7 +117,7 @@
 	for (i = 0; (i < len) & !err; i++) {
 		err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
 
-		PDEBUG(DBG_TRACE, "Reading sensor register "
+		PDEBUG(D_CONF, "Reading sensor register "
 				  "0x%x containing 0x%x ", address, *i2c_data);
 	}
 out:
@@ -150,7 +150,7 @@
 		memcpy(p, sensor_urb_skeleton + 16, 4);
 		p[3] = i2c_data[i];
 		p += 4;
-		PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+		PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
 		       address, i2c_data[i]);
 	}
 
@@ -248,7 +248,7 @@
 	*val = data << 8;
 	err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
 	*val |= data;
-	PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val);
+	PDEBUG(D_V4L2, "Read exposure %d", *val);
 out:
 	return (err < 0) ? err : 0;
 }
@@ -259,7 +259,7 @@
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val);
+	PDEBUG(D_V4L2, "Set exposure to %d", val);
 	err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		goto out;
@@ -285,7 +285,7 @@
 
 	err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	*val = (data & S5K4AA_RM_V_FLIP) >> 7;
-	PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
+	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
 out:
 	return (err < 0) ? err : 0;
@@ -297,7 +297,7 @@
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
+	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 	err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		goto out;
@@ -341,7 +341,7 @@
 
 	err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	*val = (data & S5K4AA_RM_H_FLIP) >> 6;
-	PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
+	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 out:
 	return (err < 0) ? err : 0;
 }
@@ -352,7 +352,7 @@
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d",
+	PDEBUG(D_V4L2, "Set horizontal flip to %d",
 	       val);
 	err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
@@ -397,7 +397,7 @@
 
 	err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
 	*val = data;
-	PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+	PDEBUG(D_V4L2, "Read gain %d", *val);
 
 out:
 	return (err < 0) ? err : 0;
@@ -409,7 +409,7 @@
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	PDEBUG(DBG_V4L2_CID, "Set gain to %d", val);
+	PDEBUG(D_V4L2, "Set gain to %d", val);
 	err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		goto out;
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
index bb7f7e3..eaef676 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
@@ -1,7 +1,7 @@
 /*
  * Driver for the s5k4aa sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -63,7 +63,6 @@
 /* Kernel module parameters */
 extern int force_sensor;
 extern int dump_sensor;
-extern unsigned int m5602_debug;
 
 int s5k4aa_probe(struct sd *sd);
 int s5k4aa_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
index b4b33c2..8988a72 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -1,7 +1,7 @@
 /*
  * Driver for the s5k83a sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -101,7 +101,7 @@
 	for (i = 0; i < len && !len; i++) {
 		err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
 
-		PDEBUG(DBG_TRACE, "Reading sensor register "
+		PDEBUG(D_CONF, "Reading sensor register "
 				  "0x%x containing 0x%x ", address, *i2c_data);
 	}
 
@@ -135,7 +135,7 @@
 		memcpy(p, sensor_urb_skeleton + 16, 4);
 		p[3] = i2c_data[i];
 		p += 4;
-		PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+		PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
 		       address, i2c_data[i]);
 	}
 
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
index 833708e..ee3ee9c 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.h
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
@@ -1,7 +1,7 @@
 /*
  * Driver for the s5k83a sensor
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
@@ -41,8 +41,6 @@
 /* Kernel module parameters */
 extern int force_sensor;
 extern int dump_sensor;
-extern unsigned int m5602_debug;
-
 
 int s5k83a_probe(struct sd *sd);
 int s5k83a_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h
index 930fcaa..60c9a48 100644
--- a/drivers/media/video/gspca/m5602/m5602_sensor.h
+++ b/drivers/media/video/gspca/m5602/m5602_sensor.h
@@ -1,7 +1,7 @@
 /*
  * USB Driver for ALi m5602 based webcams
  *
- * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2008 Erik Andrén
  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  *
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index b561f7c..eac245d 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -50,7 +50,7 @@
 
 	__u8 sensor;
 #define SENSOR_TAS5130A 0
-#define SENSOR_OTHER 1
+#define SENSOR_OM6802 1
 };
 
 /* V4L2 controls supported by the driver */
@@ -188,7 +188,7 @@
 	  .minimum = 0,
 	  .maximum = 1,
 	  .step = 1,
-	  .default_value = 1,
+	  .default_value = 0,
 	  },
 	 .set = sd_setwhitebalance,
 	 .get = sd_getwhitebalance
@@ -261,6 +261,59 @@
 		.priv = 0},
 };
 
+/* sensor specific data */
+struct additional_sensor_data {
+	const __u8 data1[20];
+	const __u8 data2[18];
+	const __u8 data3[18];
+	const __u8 data4[4];
+	const __u8 data5[6];
+	const __u8 stream[4];
+};
+
+const static struct additional_sensor_data sensor_data[] = {
+    {				/* TAS5130A */
+	.data1 =
+		{0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10,
+		 0xd4, 0xbb, 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
+		 0xd8, 0xc8, 0xd9, 0xfc},
+	.data2 =
+		{0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60,
+		 0xe4, 0xa8, 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
+		 0xe8, 0xe0},
+	.data3 =
+		{0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60,
+		 0xcb, 0xa8, 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
+		 0xcf, 0xe0},
+	.data4 =	/* Freq (50/60Hz). Splitted for test purpose */
+		{0x66, 0x00, 0xa8, 0xe8},
+	.data5 =
+		{0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
+	.stream =
+		{0x0b, 0x04, 0x0a, 0x40},
+    },
+    {				/* OM6802 */
+	.data1 =
+		{0xd0, 0xc2, 0xd1, 0x28, 0xd2, 0x0f, 0xd3, 0x22,
+		 0xd4, 0xcd, 0xd5, 0x27, 0xd6, 0x2c, 0xd7, 0x06,
+		 0xd8, 0xb3, 0xd9, 0xfc},
+	.data2 =
+		{0xe0, 0x80, 0xe1, 0xff, 0xe2, 0xff, 0xe3, 0x80,
+		 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0x80, 0xe7, 0xff,
+		 0xe8, 0xff},
+	.data3 =
+		{0xc7, 0x80, 0xc8, 0xff, 0xc9, 0xff, 0xca, 0x80,
+		 0xcb, 0xff, 0xcc, 0xff, 0xcd, 0x80, 0xce, 0xff,
+		 0xcf, 0xff},
+	.data4 =	/*Freq (50/60Hz). Splitted for test purpose */
+		{0x66, 0xca, 0xa8, 0xf0 },
+	.data5 =	/* this could be removed later */
+		{0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
+	.stream =
+		{0x0b, 0x04, 0x0a, 0x78},
+    }
+};
+
 #define MAX_EFFECTS 7
 /* easily done by soft, this table could be removed,
  * i keep it here just in case */
@@ -365,6 +418,8 @@
 	{},
 };
 
+static __u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
+
 /* read 1 byte */
 static int reg_r(struct gspca_dev *gspca_dev,
 		   __u16 index)
@@ -385,12 +440,12 @@
 	usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
 			0,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0, index,
 			NULL, 0, 500);
 }
 
-static void i2c_w(struct gspca_dev *gspca_dev,
+static void reg_w_buf(struct gspca_dev *gspca_dev,
 		  const __u8 *buffer, __u16 len)
 {
 	if (len <= USB_BUF_SZ) {
@@ -398,7 +453,7 @@
 		usb_control_msg(gspca_dev->dev,
 				usb_sndctrlpipe(gspca_dev->dev, 0),
 				0,
-			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				0x01, 0,
 				gspca_dev->usb_buf, len, 500);
 	} else {
@@ -409,14 +464,15 @@
 		usb_control_msg(gspca_dev->dev,
 				usb_sndctrlpipe(gspca_dev->dev, 0),
 				0,
-			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				0x01, 0,
 				tmpbuf, len, 500);
 		kfree(tmpbuf);
 	}
 }
 
-static void other_sensor_init(struct gspca_dev *gspca_dev)
+/* Reported as OM6802*/
+static void om6802_sensor_init(struct gspca_dev *gspca_dev)
 {
 	int i;
 	const __u8 *p;
@@ -436,19 +492,32 @@
 		0x90, 0x24,
 		0x91, 0xb2,
 		0x82, 0x32,
-		0xfd, 0x00,
-		0xfd, 0x01,
 		0xfd, 0x41,
 		0x00			/* table end */
 	};
 
+	reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
+	msleep(5);
+	i = 4;
+	while (--i < 0) {
+		byte = reg_r(gspca_dev, 0x0060);
+		if (!(byte & 0x01))
+			break;
+		msleep(100);
+	}
+	byte = reg_r(gspca_dev, 0x0063);
+	if (byte != 0x17) {
+		err("Bad sensor reset %02x", byte);
+		/* continue? */
+	}
+
 	p = sensor_init;
 	while (*p != 0) {
 		val[1] = *p++;
 		val[3] = *p++;
 		if (*p == 0)
 			reg_w(gspca_dev, 0x3c80);
-		i2c_w(gspca_dev, val, sizeof val);
+		reg_w_buf(gspca_dev, val, sizeof val);
 		i = 4;
 		while (--i >= 0) {
 			msleep(15);
@@ -457,7 +526,8 @@
 				break;
 		}
 	}
-			reg_w(gspca_dev, 0x3c80);
+	msleep(15);
+	reg_w(gspca_dev, 0x3c80);
 }
 
 /* this function is called at probe time */
@@ -485,12 +555,75 @@
 	return 0;
 }
 
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	unsigned int brightness;
+	__u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
+
+	brightness = sd->brightness;
+	if (brightness < 7) {
+		set6[1] = 0x26;
+		set6[3] = 0x70 - brightness * 0x10;
+	} else {
+		set6[3] = 0x00 + ((brightness - 7) * 0x10);
+	}
+
+	reg_w_buf(gspca_dev, set6, sizeof set6);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	unsigned int contrast = sd->contrast;
+	__u16 reg_to_write;
+
+	if (contrast < 7)
+		reg_to_write = 0x8ea9 - contrast * 0x200;
+	else
+		reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
+
+	reg_w(gspca_dev, reg_to_write);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	__u16 reg_to_write;
+
+	reg_to_write = 0x80bb + sd->colors * 0x100;	/* was 0xc0 */
+	reg_w(gspca_dev, reg_to_write);
+}
+
 static void setgamma(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
-	i2c_w(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
+	reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
+}
+
+static void setwhitebalance(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	__u8 white_balance[8] =
+		{0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
+
+	if (sd->whitebalance)
+		white_balance[7] = 0x3c;
+
+	reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	__u16 reg_to_write;
+
+	reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
+
+	reg_w(gspca_dev, reg_to_write);
 }
 
 /* this function is called at probe and resume time */
@@ -511,8 +644,6 @@
 			{0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
 	static const __u8 n2[] =
 			{0x08, 0x00};
-	static const __u8 nset[] =
-			{ 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
 	static const __u8 n3[] =
 			{0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
 	static const __u8 n4[] =
@@ -525,51 +656,29 @@
 		 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
 		 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
 		 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
-	static const __u8 nset4[] = {
-		0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
-		0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
-		0xe8, 0xe0
-	};
-	/* ojo puede ser 0xe6 en vez de 0xe9 */
-	static const __u8 nset2[] = {
-		0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
-		0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
-		0xd8, 0xc8, 0xd9, 0xfc
-	};
-	static const __u8 missing[] =
-		{ 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
-	static const __u8 nset3[] = {
-		0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
-		0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
-		0xcf, 0xe0
-	};
-	static const __u8 nset5[] =
-			{ 0x8f, 0x24, 0xc3, 0x00 };	/* bright */
-	static const __u8 nset7[4] =
-			{ 0x66, 0xca, 0xa8, 0xf8 };	/* 50/60 Hz */
 	static const __u8 nset9[4] =
 			{ 0x0b, 0x04, 0x0a, 0x78 };
 	static const __u8 nset8[6] =
 			{ 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
-	static const __u8 nset10[6] =
-			{ 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
 
 	byte = reg_r(gspca_dev, 0x06);
 	test_byte = reg_r(gspca_dev, 0x07);
 	if (byte == 0x08 && test_byte == 0x07) {
-		PDEBUG(D_CONF, "other sensor");
-		sd->sensor = SENSOR_OTHER;
+		PDEBUG(D_CONF, "sensor om6802");
+		sd->sensor = SENSOR_OM6802;
+	} else if (byte == 0x08 && test_byte == 0x01) {
+		PDEBUG(D_CONF, "sensor tas5130a");
+		sd->sensor = SENSOR_TAS5130A;
 	} else {
-		PDEBUG(D_CONF, "sensor %02x %02x", byte, test_byte);
+		PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
 		sd->sensor = SENSOR_TAS5130A;
 	}
 
-	i2c_w(gspca_dev, n1, sizeof n1);
+	reg_w_buf(gspca_dev, n1, sizeof n1);
 	test_byte = 0;
 	i = 5;
 	while (--i >= 0) {
-		i2c_w(gspca_dev, nset, sizeof nset);
-		msleep(5);
+		reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
 		test_byte = reg_r(gspca_dev, 0x0063);
 		msleep(100);
 		if (test_byte == 0x17)
@@ -580,7 +689,7 @@
 /*		return -EIO; */
 /*fixme: test - continue */
 	}
-	i2c_w(gspca_dev, n2, sizeof n2);
+	reg_w_buf(gspca_dev, n2, sizeof n2);
 
 	i = 0;
 	while (read_indexs[i] != 0x00) {
@@ -590,58 +699,52 @@
 		i++;
 	}
 
-	i2c_w(gspca_dev, n3, sizeof n3);
-	i2c_w(gspca_dev, n4, sizeof n4);
+	reg_w_buf(gspca_dev, n3, sizeof n3);
+	reg_w_buf(gspca_dev, n4, sizeof n4);
 	reg_r(gspca_dev, 0x0080);
 	reg_w(gspca_dev, 0x2c80);
-	i2c_w(gspca_dev, nset2, sizeof nset2);
-	i2c_w(gspca_dev, nset3, sizeof nset3);
-	i2c_w(gspca_dev, nset4, sizeof nset4);
+
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
+			sizeof sensor_data[sd->sensor].data1);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
+			sizeof sensor_data[sd->sensor].data3);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
+			sizeof sensor_data[sd->sensor].data2);
+
 	reg_w(gspca_dev, 0x3880);
 	reg_w(gspca_dev, 0x3880);
 	reg_w(gspca_dev, 0x338e);
-	i2c_w(gspca_dev, nset5, sizeof nset5);
-	reg_w(gspca_dev, 0x00a9);
+
+	setbrightness(gspca_dev);
+	setcontrast(gspca_dev);
 	setgamma(gspca_dev);
-	reg_w(gspca_dev, 0x86bb);
-	reg_w(gspca_dev, 0x4aa6);
+	setcolors(gspca_dev);
+	setsharpness(gspca_dev);
+	setwhitebalance(gspca_dev);
 
-	i2c_w(gspca_dev, missing, sizeof missing);
-
-	reg_w(gspca_dev, 0x2087);
+	reg_w(gspca_dev, 0x2087);	/* tied to white balance? */
 	reg_w(gspca_dev, 0x2088);
 	reg_w(gspca_dev, 0x2089);
 
-	i2c_w(gspca_dev, nset7, sizeof nset7);
-	i2c_w(gspca_dev, nset10, sizeof nset10);
-	i2c_w(gspca_dev, nset8, sizeof nset8);
-	i2c_w(gspca_dev, nset9, sizeof nset9);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
+			sizeof sensor_data[sd->sensor].data4);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5,
+			sizeof sensor_data[sd->sensor].data5);
+	reg_w_buf(gspca_dev, nset8, sizeof nset8);
+	reg_w_buf(gspca_dev, nset9, sizeof nset9);
 
 	reg_w(gspca_dev, 0x2880);
-	i2c_w(gspca_dev, nset2, sizeof nset2);
-	i2c_w(gspca_dev, nset3, sizeof nset3);
-	i2c_w(gspca_dev, nset4, sizeof nset4);
+
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
+			sizeof sensor_data[sd->sensor].data1);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
+			sizeof sensor_data[sd->sensor].data3);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
+			sizeof sensor_data[sd->sensor].data2);
 
 	return 0;
 }
 
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	unsigned int brightness;
-	__u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x00 };
-
-	brightness = sd->brightness;
-	if (brightness < 7) {
-		set6[3] = 0x70 - brightness * 0x10;
-	} else {
-		set6[1] = 0x24;
-		set6[3] = 0x00 + ((brightness - 7) * 0x10);
-	}
-
-	i2c_w(gspca_dev, set6, sizeof set6);
-}
-
 static void setflip(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -651,14 +754,15 @@
 	if (sd->mirror)
 		flipcmd[3] = 0x01;
 
-	i2c_w(gspca_dev, flipcmd, sizeof flipcmd);
+	reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
 }
 
 static void seteffect(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	i2c_w(gspca_dev, effects_table[sd->effect], sizeof effects_table[0]);
+	reg_w_buf(gspca_dev, effects_table[sd->effect],
+				sizeof effects_table[0]);
 	if (sd->effect == 1 || sd->effect == 5) {
 		PDEBUG(D_CONF,
 		       "This effect have been disabled for webcam \"safety\"");
@@ -671,19 +775,6 @@
 		reg_w(gspca_dev, 0xfaa6);
 }
 
-static void setwhitebalance(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	__u8 white_balance[8] =
-	    { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
-
-	if (sd->whitebalance == 1)
-		white_balance[7] = 0x3c;
-
-	i2c_w(gspca_dev, white_balance, sizeof white_balance);
-}
-
 static void setlightfreq(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -692,52 +783,46 @@
 	if (sd->freq == 2)	/* 60hz */
 		freq[1] = 0x00;
 
-	i2c_w(gspca_dev, freq, sizeof freq);
+	reg_w_buf(gspca_dev, freq, sizeof freq);
 }
 
-static void setcontrast(struct gspca_dev *gspca_dev)
+/* Is this really needed?
+ * i added some module parameters for test with some users */
+static void poll_sensor(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	unsigned int contrast = sd->contrast;
-	__u16 reg_to_write;
+	static const __u8 poll1[] =
+		{0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
+		 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
+		 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
+		 0x60, 0x14};
+	static const __u8 poll2[] =
+		{0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
+		 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
+	static const __u8 poll3[] =
+		{0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
+	static const __u8 poll4[] =
+		{0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
+		 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
+		 0xc2, 0x80, 0xc3, 0x10};
 
-	if (contrast < 7)
-		reg_to_write = 0x8ea9 - (0x200 * contrast);
-	else
-		reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
-
-	reg_w(gspca_dev, reg_to_write);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	__u16 reg_to_write;
-
-	reg_to_write = 0xc0bb + sd->colors * 0x100;
-	reg_w(gspca_dev, reg_to_write);
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	__u16 reg_to_write;
-
-	reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
-
-	reg_w(gspca_dev, reg_to_write);
+	if (sd->sensor != SENSOR_TAS5130A) {
+		PDEBUG(D_STREAM, "[Sensor requires polling]");
+		reg_w_buf(gspca_dev, poll1, sizeof poll1);
+		reg_w_buf(gspca_dev, poll2, sizeof poll2);
+		reg_w_buf(gspca_dev, poll3, sizeof poll3);
+		reg_w_buf(gspca_dev, poll4, sizeof poll4);
+	}
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i, mode;
-	static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
 	__u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
 	static const __u8 t3[] =
 		{ 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
 		  0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
-	static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
 
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
 	switch (mode) {
@@ -760,25 +845,29 @@
 	if (sd->sensor == SENSOR_TAS5130A) {
 		i = 0;
 		while (tas5130a_sensor_init[i][0] != 0) {
-			i2c_w(gspca_dev, tas5130a_sensor_init[i],
+			reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
 					 sizeof tas5130a_sensor_init[0]);
 			i++;
 		}
 		reg_w(gspca_dev, 0x3c80);
 		/* just in case and to keep sync with logs (for mine) */
-		i2c_w(gspca_dev, tas5130a_sensor_init[3],
+		reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
 				 sizeof tas5130a_sensor_init[0]);
 		reg_w(gspca_dev, 0x3c80);
 	} else {
-		other_sensor_init(gspca_dev);
+		om6802_sensor_init(gspca_dev);
 	}
-	/* just in case and to keep sync with logs  (for mine) */
-	i2c_w(gspca_dev, t1, sizeof t1);
-	i2c_w(gspca_dev, t2, sizeof t2);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
+			sizeof sensor_data[sd->sensor].data4);
 	reg_r(gspca_dev, 0x0012);
-	i2c_w(gspca_dev, t3, sizeof t3);
+	reg_w_buf(gspca_dev, t2, sizeof t2);
+	reg_w_buf(gspca_dev, t3, sizeof t3);
 	reg_w(gspca_dev, 0x0013);
-	i2c_w(gspca_dev, t4, sizeof t4);
+	msleep(15);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+			sizeof sensor_data[sd->sensor].stream);
+	poll_sensor(gspca_dev);
+
 	/* restart on each start, just in case, sometimes regs goes wrong
 	 * when using controls from app */
 	setbrightness(gspca_dev);
@@ -787,6 +876,19 @@
 	return 0;
 }
 
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+			sizeof sensor_data[sd->sensor].stream);
+	msleep(20);
+	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+			sizeof sensor_data[sd->sensor].stream);
+	msleep(20);
+	reg_w(gspca_dev, 0x0309);
+}
+
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
 			__u8 *data,			/* isoc packet */
@@ -1036,6 +1138,7 @@
 	.config = sd_config,
 	.init = sd_init,
 	.start = sd_start,
+	.stopN = sd_stopN,
 	.pkt_scan = sd_pkt_scan,
 	.querymenu = sd_querymenu,
 };
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index b7457fc..1c404e4 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -600,13 +600,14 @@
 	since we may get here before the stream has been fully set-up */
 	if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
 		while (count >= itv->dma_data_req_size) {
-			if (!ivtv_yuv_udma_stream_frame (itv, (void __user *)user_buf)) {
-				bytes_written += itv->dma_data_req_size;
-				user_buf += itv->dma_data_req_size;
-				count -= itv->dma_data_req_size;
-			} else {
-				break;
-			}
+			rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf);
+
+			if (rc < 0)
+				return rc;
+
+			bytes_written += itv->dma_data_req_size;
+			user_buf += itv->dma_data_req_size;
+			count -= itv->dma_data_req_size;
 		}
 		if (count == 0) {
 			IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 8696527..208fb54 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -509,7 +509,6 @@
 static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
 {
 	struct ivtv_open_id *id = fh;
-	struct ivtv *itv = id->itv;
 	s32 w = fmt->fmt.pix.width;
 	s32 h = fmt->fmt.pix.height;
 	int field = fmt->fmt.pix.field;
@@ -517,7 +516,22 @@
 
 	w = min(w, 720);
 	w = max(w, 2);
-	h = min(h, itv->is_out_50hz ? 576 : 480);
+	/* Why can the height be 576 even when the output is NTSC?
+
+	   Internally the buffers of the PVR350 are always set to 720x576. The
+	   decoded video frame will always be placed in the top left corner of
+	   this buffer. For any video which is not 720x576, the buffer will
+	   then be cropped to remove the unused right and lower areas, with
+	   the remaining image being scaled by the hardware to fit the display
+	   area. The video can be scaled both up and down, so a 720x480 video
+	   can be displayed full-screen on PAL and a 720x576 video can be
+	   displayed without cropping on NTSC.
+
+	   Note that the scaling only occurs on the video stream, the osd
+	   resolution is locked to the broadcast standard and not scaled.
+
+	   Thanks to Ian Armstrong for this explanation. */
+	h = min(h, 576);
 	h = max(h, 2);
 	if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
 		fmt->fmt.pix.field = field;
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
index 2fd4b4a..bae2d2b 100644
--- a/drivers/media/video/ks0127.c
+++ b/drivers/media/video/ks0127.c
@@ -33,27 +33,20 @@
  * V1.1 Gerard v.d. Horst  Added some debugoutput, reset the video-standard
  */
 
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include "ks0127.h"
-
 #include <linux/i2c.h>
 #include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
+#include "ks0127.h"
 
-#define dprintk     if (debug) printk
-
-/* i2c identification */
-#define I2C_KS0127_ADDON   0xD8
-#define I2C_KS0127_ONBOARD 0xDA
+MODULE_DESCRIPTION("KS0127 video decoder driver");
+MODULE_AUTHOR("Ryan Drake");
+MODULE_LICENSE("GPL");
 
 #define KS_TYPE_UNKNOWN	0
 #define KS_TYPE_0122S	1
@@ -204,8 +197,6 @@
 };
 
 struct ks0127 {
-	struct i2c_client *client;
-	unsigned char	addr;
 	int		format_width;
 	int		format_height;
 	int		cap_width;
@@ -220,16 +211,18 @@
 
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug output");
-MODULE_LICENSE("GPL");
 
 static u8 reg_defaults[64];
 
-
-
 static void init_reg_defaults(void)
 {
+	static int initialized;
 	u8 *table = reg_defaults;
 
+	if (initialized)
+		return;
+	initialized = 1;
+
 	table[KS_CMDA]     = 0x2c;  /* VSE=0, CCIR 601, autodetect standard */
 	table[KS_CMDB]     = 0x12;  /* VALIGN=0, AGC control and input */
 	table[KS_CMDC]     = 0x00;  /* Test options */
@@ -308,50 +301,53 @@
  * An explanation from kayork@mail.utexas.edu:
  *
  * During I2C reads, the KS0127 only samples for a stop condition
- * during the place where the acknoledge bit should be. Any standard
+ * during the place where the acknowledge bit should be. Any standard
  * I2C implementation (correctly) throws in another clock transition
  * at the 9th bit, and the KS0127 will not recognize the stop condition
  * and will continue to clock out data.
  *
  * So we have to do the read ourself.  Big deal.
-	   workaround in i2c-algo-bit
+ *	   workaround in i2c-algo-bit
  */
 
 
-static u8 ks0127_read(struct ks0127 *ks, u8 reg)
+static u8 ks0127_read(struct i2c_client *c, u8 reg)
 {
-	struct i2c_client *c = ks->client;
 	char val = 0;
 	struct i2c_msg msgs[] = {
-		{c->addr, 0, sizeof(reg), &reg},
-		{c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}};
+		{ c->addr, 0, sizeof(reg), &reg },
+		{ c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val }
+	};
 	int ret;
 
 	ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs));
 	if (ret != ARRAY_SIZE(msgs))
-		dprintk("ks0127_write error\n");
+		v4l_dbg(1, debug, c, "read error\n");
 
 	return val;
 }
 
 
-static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val)
+static void ks0127_write(struct i2c_client *c, u8 reg, u8 val)
 {
-	char msg[] = {reg, val};
+	struct ks0127 *ks = i2c_get_clientdata(c);
+	char msg[] = { reg, val };
 
-	if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg))
-		dprintk("ks0127_write error\n");
+	if (i2c_master_send(c, msg, sizeof(msg)) != sizeof(msg))
+		v4l_dbg(1, debug, c, "write error\n");
 
 	ks->regs[reg] = val;
 }
 
 
 /* generic bit-twiddling */
-static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v)
+static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v)
 {
+	struct ks0127 *ks = i2c_get_clientdata(client);
+
 	u8 val = ks->regs[reg];
 	val = (val & and_v) | or_v;
-	ks0127_write(ks, reg, val);
+	ks0127_write(client, reg, val);
 }
 
 
@@ -359,73 +355,69 @@
 /****************************************************************************
 * ks0127 private api
 ****************************************************************************/
-static void ks0127_reset(struct ks0127* ks)
+static void ks0127_reset(struct i2c_client *c)
 {
-	int i;
+	struct ks0127 *ks = i2c_get_clientdata(c);
 	u8 *table = reg_defaults;
+	int i;
 
 	ks->ks_type = KS_TYPE_UNKNOWN;
 
-	dprintk("ks0127: reset\n");
+	v4l_dbg(1, debug, c, "reset\n");
 	msleep(1);
 
 	/* initialize all registers to known values */
 	/* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */
 
-	for(i = 1; i < 33; i++)
-		ks0127_write(ks, i, table[i]);
+	for (i = 1; i < 33; i++)
+		ks0127_write(c, i, table[i]);
 
-	for(i = 35; i < 40; i++)
-		ks0127_write(ks, i, table[i]);
+	for (i = 35; i < 40; i++)
+		ks0127_write(c, i, table[i]);
 
-	for(i = 41; i < 56; i++)
-		ks0127_write(ks, i, table[i]);
+	for (i = 41; i < 56; i++)
+		ks0127_write(c, i, table[i]);
 
-	for(i = 58; i < 64; i++)
-		ks0127_write(ks, i, table[i]);
+	for (i = 58; i < 64; i++)
+		ks0127_write(c, i, table[i]);
 
 
-	if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) {
+	if ((ks0127_read(c, KS_STAT) & 0x80) == 0) {
 		ks->ks_type = KS_TYPE_0122S;
-		dprintk("ks0127: ks0122s Found\n");
+		v4l_dbg(1, debug, c, "ks0122s found\n");
 		return;
 	}
 
-	switch(ks0127_read(ks, KS_CMDE) & 0x0f) {
-
+	switch (ks0127_read(c, KS_CMDE) & 0x0f) {
 	case 0:
 		ks->ks_type = KS_TYPE_0127;
-		dprintk("ks0127: ks0127 found\n");
+		v4l_dbg(1, debug, c, "ks0127 found\n");
 		break;
 
 	case 9:
 		ks->ks_type = KS_TYPE_0127B;
-		dprintk("ks0127: ks0127B Revision A found\n");
+		v4l_dbg(1, debug, c, "ks0127B Revision A found\n");
 		break;
 
 	default:
-		dprintk("ks0127: unknown revision\n");
+		v4l_dbg(1, debug, c, "unknown revision\n");
 		break;
 	}
 }
 
-static int ks0127_command(struct i2c_client *client,
-			  unsigned int cmd, void *arg)
+static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
 {
-	struct ks0127 *ks = i2c_get_clientdata(client);
-
-	int		*iarg = (int*)arg;
-
+	struct ks0127 *ks = i2c_get_clientdata(c);
+	int		*iarg = (int *)arg;
 	int		status;
 
 	if (!ks)
 		return -ENODEV;
 
 	switch (cmd) {
-
 	case DECODER_INIT:
-		dprintk("ks0127: command DECODER_INIT\n");
-		ks0127_reset(ks);
+		v4l_dbg(1, debug, c, "DECODER_INIT\n");
+		ks0127_reset(c);
 		break;
 
 	case DECODER_SET_INPUT:
@@ -436,161 +428,160 @@
 		case KS_INPUT_COMPOSITE_4:
 		case KS_INPUT_COMPOSITE_5:
 		case KS_INPUT_COMPOSITE_6:
-			dprintk("ks0127: command DECODER_SET_INPUT %d: "
-				"Composite\n", *iarg);
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_INPUT %d: Composite\n", *iarg);
 			/* autodetect 50/60 Hz */
-			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);
 			/* VSE=0 */
-			ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+			ks0127_and_or(c, KS_CMDA,   ~0x40, 0x00);
 			/* set input line */
-			ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+			ks0127_and_or(c, KS_CMDB,   0xb0, *iarg);
 			/* non-freerunning mode */
-			ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+			ks0127_and_or(c, KS_CMDC,   0x70, 0x0a);
 			/* analog input */
-			ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+			ks0127_and_or(c, KS_CMDD,   0x03, 0x00);
 			/* enable chroma demodulation */
-			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);
 			/* chroma trap, HYBWR=1 */
-			ks0127_and_or(ks, KS_LUMA,   0x00,
+			ks0127_and_or(c, KS_LUMA,   0x00,
 				       (reg_defaults[KS_LUMA])|0x0c);
 			/* scaler fullbw, luma comb off */
-			ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+			ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);
 			/* manual chroma comb .25 .5 .25 */
-			ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90);
+			ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90);
 
 			/* chroma path delay */
-			ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90);
+			ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90);
 
-			ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
-			ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
-			ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
-			ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+			ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
+			ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
+			ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+			ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
 			break;
 
 		case KS_INPUT_SVIDEO_1:
 		case KS_INPUT_SVIDEO_2:
 		case KS_INPUT_SVIDEO_3:
-			dprintk("ks0127: command DECODER_SET_INPUT %d: "
-				"S-Video\n", *iarg);
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_INPUT %d: S-Video\n", *iarg);
 			/* autodetect 50/60 Hz */
-			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);
 			/* VSE=0 */
-			ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+			ks0127_and_or(c, KS_CMDA,   ~0x40, 0x00);
 			/* set input line */
-			ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+			ks0127_and_or(c, KS_CMDB,   0xb0, *iarg);
 			/* non-freerunning mode */
-			ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+			ks0127_and_or(c, KS_CMDC,   0x70, 0x0a);
 			/* analog input */
-			ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+			ks0127_and_or(c, KS_CMDD,   0x03, 0x00);
 			/* enable chroma demodulation */
-			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
-			ks0127_and_or(ks, KS_LUMA, 0x00,
+			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);
+			ks0127_and_or(c, KS_LUMA, 0x00,
 				       reg_defaults[KS_LUMA]);
 			/* disable luma comb */
-			ks0127_and_or(ks, KS_VERTIA, 0x08,
+			ks0127_and_or(c, KS_VERTIA, 0x08,
 				       (reg_defaults[KS_VERTIA]&0xf0)|0x01);
-			ks0127_and_or(ks, KS_VERTIC, 0x0f,
+			ks0127_and_or(c, KS_VERTIC, 0x0f,
 				       reg_defaults[KS_VERTIC]&0xf0);
 
-			ks0127_and_or(ks, KS_CHROMB, 0x0f,
+			ks0127_and_or(c, KS_CHROMB, 0x0f,
 				       reg_defaults[KS_CHROMB]&0xf0);
 
-			ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
-			ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
-			ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
-			ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+			ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
+			ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
+			ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+			ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
 			break;
 
 		case KS_INPUT_YUV656:
-			dprintk("ks0127: command DECODER_SET_INPUT 15: "
-				"YUV656\n");
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_INPUT 15: YUV656\n");
 			if (ks->norm == VIDEO_MODE_NTSC ||
 			    ks->norm == KS_STD_PAL_M)
 				/* force 60 Hz */
-				ks0127_and_or(ks, KS_CMDA,   0xfc, 0x03);
+				ks0127_and_or(c, KS_CMDA,   0xfc, 0x03);
 			else
 				/* force 50 Hz */
-				ks0127_and_or(ks, KS_CMDA,   0xfc, 0x02);
+				ks0127_and_or(c, KS_CMDA,   0xfc, 0x02);
 
-			ks0127_and_or(ks, KS_CMDA,   0xff, 0x40); /* VSE=1 */
+			ks0127_and_or(c, KS_CMDA,   0xff, 0x40); /* VSE=1 */
 			/* set input line and VALIGN */
-			ks0127_and_or(ks, KS_CMDB,   0xb0, (*iarg | 0x40));
+			ks0127_and_or(c, KS_CMDB,   0xb0, (*iarg | 0x40));
 			/* freerunning mode, */
 			/* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/
-			ks0127_and_or(ks, KS_CMDC,   0x70, 0x87);
+			ks0127_and_or(c, KS_CMDC,   0x70, 0x87);
 			/* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
-			ks0127_and_or(ks, KS_CMDD,   0x03, 0x08);
+			ks0127_and_or(c, KS_CMDD,   0x03, 0x08);
 			/* disable chroma demodulation */
-			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30);
+			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30);
 			/* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
-			ks0127_and_or(ks, KS_LUMA,   0x00, 0x71);
-			ks0127_and_or(ks, KS_VERTIC, 0x0f,
+			ks0127_and_or(c, KS_LUMA,   0x00, 0x71);
+			ks0127_and_or(c, KS_VERTIC, 0x0f,
 				       reg_defaults[KS_VERTIC]&0xf0);
 
 			/* scaler fullbw, luma comb off */
-			ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+			ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);
 
-			ks0127_and_or(ks, KS_CHROMB, 0x0f,
+			ks0127_and_or(c, KS_CHROMB, 0x0f,
 				       reg_defaults[KS_CHROMB]&0xf0);
 
-			ks0127_and_or(ks, KS_CON, 0x00, 0x00);
-			ks0127_and_or(ks, KS_BRT, 0x00, 32);	/* spec: 34 */
+			ks0127_and_or(c, KS_CON, 0x00, 0x00);
+			ks0127_and_or(c, KS_BRT, 0x00, 32);	/* spec: 34 */
 				/* spec: 229 (e5) */
-			ks0127_and_or(ks, KS_SAT, 0x00, 0xe8);
-			ks0127_and_or(ks, KS_HUE, 0x00, 0);
+			ks0127_and_or(c, KS_SAT, 0x00, 0xe8);
+			ks0127_and_or(c, KS_HUE, 0x00, 0);
 
-			ks0127_and_or(ks, KS_UGAIN, 0x00, 238);
-			ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00);
+			ks0127_and_or(c, KS_UGAIN, 0x00, 238);
+			ks0127_and_or(c, KS_VGAIN, 0x00, 0x00);
 
 			/*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
-			ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f);
-			ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00);
+			ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f);
+			ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00);
 			break;
 
 		default:
-			dprintk("ks0127: command DECODER_SET_INPUT: "
-				"Unknown input %d\n", *iarg);
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_INPUT: Unknown input %d\n", *iarg);
 			break;
 		}
 
 		/* hack: CDMLPF sometimes spontaneously switches on; */
 		/* force back off */
-		ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]);
+		ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]);
 		break;
 
 	case DECODER_SET_OUTPUT:
 		switch(*iarg) {
 		case KS_OUTPUT_YUV656E:
-			dprintk("ks0127: command DECODER_SET_OUTPUT: "
-				"OUTPUT_YUV656E (Missing)\n");
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n");
 			return -EINVAL;
-			break;
 
 		case KS_OUTPUT_EXV:
-			dprintk("ks0127: command DECODER_SET_OUTPUT: "
-				"OUTPUT_EXV\n");
-			ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09);
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_OUTPUT: OUTPUT_EXV\n");
+			ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09);
 			break;
 		}
 		break;
 
-	case DECODER_SET_NORM: //sam This block mixes old and new norm names...
+	case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */
 		/* Set to automatic SECAM/Fsc mode */
-		ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+		ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);
 
 		ks->norm = *iarg;
-		switch(*iarg)
-		{
+		switch (*iarg) {
 		/* this is untested !! */
 		/* It just detects PAL_N/NTSC_M (no special frequencies) */
 		/* And you have to set the standard a second time afterwards */
 		case VIDEO_MODE_AUTO:
-			dprintk("ks0127: command DECODER_SET_NORM: AUTO\n");
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_NORM: AUTO\n");
 
 			/* The chip determines the format */
 			/* based on the current field rate */
-			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
-			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);
+			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
 			/* This is wrong for PAL ! As I said, */
 			/* you need to set the standard once again !! */
 			ks->format_height = 240;
@@ -598,84 +589,86 @@
 			break;
 
 		case VIDEO_MODE_NTSC:
-			dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n");
-			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_NORM: NTSC_M\n");
+			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
 			ks->format_height = 240;
 			ks->format_width = 704;
 			break;
 
 		case KS_STD_NTSC_N:
-			dprintk("ks0127: command KS0127_SET_STANDARD: "
-				"NTSC_N (fixme)\n");
-			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+			v4l_dbg(1, debug, c,
+				"KS0127_SET_NORM: NTSC_N (fixme)\n");
+			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
 			ks->format_height = 240;
 			ks->format_width = 704;
 			break;
 
 		case VIDEO_MODE_PAL:
-			dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n");
-			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_NORM: PAL_N\n");
+			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
 			ks->format_height = 290;
 			ks->format_width = 704;
 			break;
 
 		case KS_STD_PAL_M:
-			dprintk("ks0127: command KS0127_SET_STANDARD: "
-				"PAL_M (fixme)\n");
-			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+			v4l_dbg(1, debug, c,
+				"KS0127_SET_NORM: PAL_M (fixme)\n");
+			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
 			ks->format_height = 290;
 			ks->format_width = 704;
 			break;
 
 		case VIDEO_MODE_SECAM:
-			dprintk("ks0127: command KS0127_SET_STANDARD: "
-				"SECAM\n");
+			v4l_dbg(1, debug, c,
+				"KS0127_SET_NORM: SECAM\n");
 			ks->format_height = 290;
 			ks->format_width = 704;
 
 			/* set to secam autodetection */
-			ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20);
-			ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+			ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20);
+			ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);
 			schedule_timeout_interruptible(HZ/10+1);
 
 			/* did it autodetect? */
-			if (ks0127_read(ks, KS_DEMOD) & 0x40)
+			if (ks0127_read(c, KS_DEMOD) & 0x40)
 				break;
 
 			/* force to secam mode */
-			ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f);
+			ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f);
 			break;
 
 		default:
-			dprintk("ks0127: command DECODER_SET_NORM: "
-				"Unknown norm %d\n", *iarg);
+			v4l_dbg(1, debug, c,
+				"DECODER_SET_NORM: Unknown norm %d\n", *iarg);
 			break;
 		}
 		break;
 
 	case DECODER_SET_PICTURE:
-		dprintk("ks0127: command DECODER_SET_PICTURE "
-			"not yet supported (fixme)\n");
+		v4l_dbg(1, debug, c,
+			"DECODER_SET_PICTURE: not yet supported\n");
 		return -EINVAL;
 
-	//sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE
-	//sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE
-	//sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE?
-	//sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE
-	//sam todo: KS0127_SET_AGC_MODE:
-	//sam todo: KS0127_SET_AGC:
-	//sam todo: KS0127_SET_CHROMA_MODE:
-	//sam todo: KS0127_SET_PIXCLK_MODE:
-	//sam todo: KS0127_SET_GAMMA_MODE:
-	//sam todo: KS0127_SET_UGAIN:
-	//sam todo: KS0127_SET_VGAIN:
-	//sam todo: KS0127_SET_INVALY:
-	//sam todo: KS0127_SET_INVALU:
-	//sam todo: KS0127_SET_INVALV:
-	//sam todo: KS0127_SET_UNUSEY:
-	//sam todo: KS0127_SET_UNUSEU:
-	//sam todo: KS0127_SET_UNUSEV:
-	//sam todo: KS0127_SET_VSALIGN_MODE:
+	/* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */
+	/* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */
+	/* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */
+	/* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */
+	/* sam todo: KS0127_SET_AGC_MODE: */
+	/* sam todo: KS0127_SET_AGC: */
+	/* sam todo: KS0127_SET_CHROMA_MODE: */
+	/* sam todo: KS0127_SET_PIXCLK_MODE: */
+	/* sam todo: KS0127_SET_GAMMA_MODE: */
+	/* sam todo: KS0127_SET_UGAIN: */
+	/* sam todo: KS0127_SET_VGAIN: */
+	/* sam todo: KS0127_SET_INVALY: */
+	/* sam todo: KS0127_SET_INVALU: */
+	/* sam todo: KS0127_SET_INVALV: */
+	/* sam todo: KS0127_SET_UNUSEY: */
+	/* sam todo: KS0127_SET_UNUSEU: */
+	/* sam todo: KS0127_SET_UNUSEV: */
+	/* sam todo: KS0127_SET_VSALIGN_MODE: */
 
 	case DECODER_ENABLE_OUTPUT:
 	{
@@ -684,34 +677,32 @@
 		iarg = arg;
 		enable = (*iarg != 0);
 		if (enable) {
-			dprintk("ks0127: command "
-					"DECODER_ENABLE_OUTPUT on "
-					"(%d)\n", enable);
+			v4l_dbg(1, debug, c,
+				"DECODER_ENABLE_OUTPUT on\n");
 			/* All output pins on */
-			ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
+			ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30);
 			/* Obey the OEN pin */
-			ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
+			ks0127_and_or(c, KS_CDEM, 0x7f, 0x00);
 		} else {
-			dprintk("ks0127: command "
-					"DECODER_ENABLE_OUTPUT off "
-					"(%d)\n", enable);
+			v4l_dbg(1, debug, c,
+				"DECODER_ENABLE_OUTPUT off\n");
 			/* Video output pins off */
-			ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
+			ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00);
 			/* Ignore the OEN pin */
-			ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
+			ks0127_and_or(c, KS_CDEM, 0x7f, 0x80);
 		}
-	}
 		break;
+	}
 
-	//sam todo: KS0127_SET_OUTPUT_MODE:
-	//sam todo: KS0127_SET_WIDTH:
-	//sam todo: KS0127_SET_HEIGHT:
-	//sam todo: KS0127_SET_HSCALE:
+	/* sam todo: KS0127_SET_OUTPUT_MODE: */
+	/* sam todo: KS0127_SET_WIDTH: */
+	/* sam todo: KS0127_SET_HEIGHT: */
+	/* sam todo: KS0127_SET_HSCALE: */
 
 	case DECODER_GET_STATUS:
-		dprintk("ks0127: command DECODER_GET_STATUS\n");
+		v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n");
 		*iarg = 0;
-		status = ks0127_read(ks, KS_STAT);
+		status = ks0127_read(c, KS_STAT);
 		if (!(status & 0x20))		 /* NOVID not set */
 			*iarg = (*iarg | DECODER_STATUS_GOOD);
 		if ((status & 0x01))		      /* CLOCK set */
@@ -722,124 +713,81 @@
 			*iarg = (*iarg | DECODER_STATUS_NTSC);
 		break;
 
-	//Catch any unknown command
+	/* Catch any unknown command */
 	default:
-		dprintk("ks0127: command unknown: %04X\n", cmd);
+		v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd);
 		return -EINVAL;
 	}
 	return 0;
 }
 
 
-
-
-static int ks0127_probe(struct i2c_adapter *adapter);
-static int ks0127_detach(struct i2c_client *client);
-static int ks0127_command(struct i2c_client *client,
-			  unsigned int cmd, void *arg);
-
-
-
 /* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1,
-				       I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END};
-static unsigned short probe[2] =	{I2C_CLIENT_END, I2C_CLIENT_END};
-static unsigned short ignore[2] = 	{I2C_CLIENT_END, I2C_CLIENT_END};
-static struct i2c_client_address_data addr_data = {
-	normal_i2c,
-	probe,
-	ignore,
+#define I2C_KS0127_ADDON   0xD8
+#define I2C_KS0127_ONBOARD 0xDA
+
+static unsigned short normal_i2c[] = {
+	I2C_KS0127_ADDON >> 1,
+	I2C_KS0127_ONBOARD >> 1,
+	I2C_CLIENT_END
 };
 
-static struct i2c_driver i2c_driver_ks0127 = {
-	.driver.name = "ks0127",
-	.id             = I2C_DRIVERID_KS0127,
-	.attach_adapter = ks0127_probe,
-	.detach_client  = ks0127_detach,
-	.command        = ks0127_command
-};
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client ks0127_client_tmpl =
-{
-	.name = "(ks0127 unset)",
-	.addr = 0,
-	.adapter = NULL,
-	.driver = &i2c_driver_ks0127,
-};
-
-static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind)
+static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id)
 {
 	struct ks0127 *ks;
-	struct i2c_client *client;
 
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (client == NULL)
-		return -ENOMEM;
-	memcpy(client, &ks0127_client_tmpl, sizeof(*client));
+	v4l_info(c, "%s chip found @ 0x%x (%s)\n",
+		c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board",
+		c->addr << 1, c->adapter->name);
 
 	ks = kzalloc(sizeof(*ks), GFP_KERNEL);
-	if (ks == NULL) {
-		kfree(client);
+	if (ks == NULL)
 		return -ENOMEM;
-	}
 
-	i2c_set_clientdata(client, ks);
-	client->adapter = adapter;
-	client->addr = addr;
-	sprintf(client->name, "ks0127-%02x", adapter->id);
+	i2c_set_clientdata(c, ks);
 
-	ks->client = client;
-	ks->addr = addr;
 	ks->ks_type = KS_TYPE_UNKNOWN;
 
 	/* power up */
-	ks0127_write(ks, KS_CMDA, 0x2c);
+	init_reg_defaults();
+	ks0127_write(c, KS_CMDA, 0x2c);
 	mdelay(10);
 
 	/* reset the device */
-	ks0127_reset(ks);
-	printk(KERN_INFO "ks0127: attach: %s video decoder\n",
-	       ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board");
-
-	i2c_attach_client(client);
+	ks0127_reset(c);
 	return 0;
 }
 
-
-static int ks0127_probe(struct i2c_adapter *adapter)
+static int ks0127_remove(struct i2c_client *c)
 {
-	if (adapter->id == I2C_HW_B_ZR36067)
-		return i2c_probe(adapter, &addr_data, ks0127_found_proc);
-	return 0;
-}
+	struct ks0127 *ks = i2c_get_clientdata(c);
 
-static int ks0127_detach(struct i2c_client *client)
-{
-	struct ks0127 *ks = i2c_get_clientdata(client);
+	ks0127_write(c, KS_OFMTA, 0x20); /* tristate */
+	ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */
 
-	ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/
-	ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */
-
-	i2c_detach_client(client);
 	kfree(ks);
-	kfree(client);
-
-	dprintk("ks0127: detach\n");
 	return 0;
 }
 
-
-static int __devinit ks0127_init_module(void)
+static int ks0127_legacy_probe(struct i2c_adapter *adapter)
 {
-	init_reg_defaults();
-	return i2c_add_driver(&i2c_driver_ks0127);
+	return adapter->id == I2C_HW_B_ZR36067;
 }
 
-static void __devexit ks0127_cleanup_module(void)
-{
-	i2c_del_driver(&i2c_driver_ks0127);
-}
+static const struct i2c_device_id ks0127_id[] = {
+	{ "ks0127", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ks0127_id);
 
-
-module_init(ks0127_init_module);
-module_exit(ks0127_cleanup_module);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "ks0127",
+	.driverid = I2C_DRIVERID_KS0127,
+	.command = ks0127_command,
+	.probe = ks0127_probe,
+	.remove = ks0127_remove,
+	.legacy_probe = ks0127_legacy_probe,
+	.id_table = ks0127_id,
+};
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 4aa82b3..adf2ba7 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -31,36 +31,24 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
 MODULE_AUTHOR("Pauline Middelink");
 MODULE_LICENSE("GPL");
 
-#include <linux/i2c.h>
-
-#define I2C_NAME(s) (s)->name
-
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <linux/video_decoder.h>
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 #define SAA7110_MAX_INPUT	9	/* 6 CVBS, 3 SVHS */
 #define SAA7110_MAX_OUTPUT	0	/* its a decoder only */
 
-#define	I2C_SAA7110		0x9C	/* or 0x9E */
-
 #define SAA7110_NR_REG		0x35
 
 struct saa7110 {
@@ -81,10 +69,7 @@
 /* I2C support functions						   */
 /* ----------------------------------------------------------------------- */
 
-static int
-saa7110_write (struct i2c_client *client,
-	       u8                 reg,
-	       u8                 value)
+static int saa7110_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct saa7110 *decoder = i2c_get_clientdata(client);
 
@@ -92,10 +77,7 @@
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static int
-saa7110_write_block (struct i2c_client *client,
-		     const u8          *data,
-		     unsigned int       len)
+static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
 {
 	int ret = -1;
 	u8 reg = *data;		/* first register to write to */
@@ -115,8 +97,8 @@
 		memcpy(decoder->reg + reg, data + 1, len - 1);
 	} else {
 		for (++data, --len; len; len--) {
-			if ((ret = saa7110_write(client, reg++,
-						 *data++)) < 0)
+			ret = saa7110_write(client, reg++, *data++);
+			if (ret < 0)
 				break;
 		}
 	}
@@ -124,8 +106,7 @@
 	return ret;
 }
 
-static inline int
-saa7110_read (struct i2c_client *client)
+static inline int saa7110_read(struct i2c_client *client)
 {
 	return i2c_smbus_read_byte(client);
 }
@@ -138,9 +119,7 @@
 #define FRESP_06H_SVIDEO 0x83	//0xC0
 
 
-static int
-saa7110_selmux (struct i2c_client *client,
-		int                chan)
+static int saa7110_selmux(struct i2c_client *client, int chan)
 {
 	static const unsigned char modes[9][8] = {
 		/* mode 0 */
@@ -197,8 +176,7 @@
 	/* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
 };
 
-static int
-determine_norm (struct i2c_client *client)
+static int determine_norm(struct i2c_client *client)
 {
 	DEFINE_WAIT(wait);
 	struct saa7110 *decoder = i2c_get_clientdata(client);
@@ -212,29 +190,23 @@
 	finish_wait(&decoder->wq, &wait);
 	status = saa7110_read(client);
 	if (status & 0x40) {
-		dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n",
-			I2C_NAME(client), status);
+		v4l_dbg(1, debug, client, "status=0x%02x (no signal)\n", status);
 		return decoder->norm;	// no change
 	}
 	if ((status & 3) == 0) {
 		saa7110_write(client, 0x06, 0x83);
 		if (status & 0x20) {
-			dprintk(1,
-				KERN_INFO
-				"%s: status=0x%02x (NTSC/no color)\n",
-				I2C_NAME(client), status);
+			v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status);
 			//saa7110_write(client,0x2E,0x81);
 			return VIDEO_MODE_NTSC;
 		}
-		dprintk(1, KERN_INFO "%s: status=0x%02x (PAL/no color)\n",
-			I2C_NAME(client), status);
+		v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status);
 		//saa7110_write(client,0x2E,0x9A);
 		return VIDEO_MODE_PAL;
 	}
 	//saa7110_write(client,0x06,0x03);
 	if (status & 0x20) {	/* 60Hz */
-		dprintk(1, KERN_INFO "%s: status=0x%02x (NTSC)\n",
-			I2C_NAME(client), status);
+		v4l_dbg(1, debug, client, "status=0x%02x (NTSC)\n", status);
 		saa7110_write(client, 0x0D, 0x86);
 		saa7110_write(client, 0x0F, 0x50);
 		saa7110_write(client, 0x11, 0x2C);
@@ -254,13 +226,11 @@
 
 	status = saa7110_read(client);
 	if ((status & 0x03) == 0x01) {
-		dprintk(1, KERN_INFO "%s: status=0x%02x (SECAM)\n",
-			I2C_NAME(client), status);
+		v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status);
 		saa7110_write(client, 0x0D, 0x87);
 		return VIDEO_MODE_SECAM;
 	}
-	dprintk(1, KERN_INFO "%s: status=0x%02x (PAL)\n", I2C_NAME(client),
-		status);
+	v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status);
 	return VIDEO_MODE_PAL;
 }
 
@@ -286,8 +256,8 @@
 		    VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
 		dc->inputs = SAA7110_MAX_INPUT;
 		dc->outputs = SAA7110_MAX_OUTPUT;
-	}
 		break;
+	}
 
 	case DECODER_GET_STATUS:
 	{
@@ -295,8 +265,8 @@
 		int res = 0;
 
 		status = saa7110_read(client);
-		dprintk(1, KERN_INFO "%s: status=0x%02x norm=%d\n",
-			I2C_NAME(client), status, decoder->norm);
+		v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n",
+			       status, decoder->norm);
 		if (!(status & 0x40))
 			res |= DECODER_STATUS_GOOD;
 		if (status & 0x03)
@@ -314,8 +284,8 @@
 			break;
 		}
 		*(int *) arg = res;
-	}
 		break;
+	}
 
 	case DECODER_SET_NORM:
 		v = *(int *) arg;
@@ -328,34 +298,24 @@
 				saa7110_write(client, 0x0F, 0x50);
 				saa7110_write(client, 0x11, 0x2C);
 				//saa7110_write(client, 0x2E, 0x81);
-				dprintk(1,
-					KERN_INFO "%s: switched to NTSC\n",
-					I2C_NAME(client));
+				v4l_dbg(1, debug, client, "switched to NTSC\n");
 				break;
 			case VIDEO_MODE_PAL:
 				saa7110_write(client, 0x0D, 0x86);
 				saa7110_write(client, 0x0F, 0x10);
 				saa7110_write(client, 0x11, 0x59);
 				//saa7110_write(client, 0x2E, 0x9A);
-				dprintk(1,
-					KERN_INFO "%s: switched to PAL\n",
-					I2C_NAME(client));
+				v4l_dbg(1, debug, client, "switched to PAL\n");
 				break;
 			case VIDEO_MODE_SECAM:
 				saa7110_write(client, 0x0D, 0x87);
 				saa7110_write(client, 0x0F, 0x10);
 				saa7110_write(client, 0x11, 0x59);
 				//saa7110_write(client, 0x2E, 0x9A);
-				dprintk(1,
-					KERN_INFO
-					"%s: switched to SECAM\n",
-					I2C_NAME(client));
+				v4l_dbg(1, debug, client, "switched to SECAM\n");
 				break;
 			case VIDEO_MODE_AUTO:
-				dprintk(1,
-					KERN_INFO
-					"%s: TV standard detection...\n",
-					I2C_NAME(client));
+				v4l_dbg(1, debug, client, "switched to AUTO\n");
 				decoder->norm = determine_norm(client);
 				*(int *) arg = decoder->norm;
 				break;
@@ -368,15 +328,12 @@
 	case DECODER_SET_INPUT:
 		v = *(int *) arg;
 		if (v < 0 || v > SAA7110_MAX_INPUT) {
-			dprintk(1,
-				KERN_INFO "%s: input=%d not available\n",
-				I2C_NAME(client), v);
+			v4l_dbg(1, debug, client, "input=%d not available\n", v);
 			return -EINVAL;
 		}
 		if (decoder->input != v) {
 			saa7110_selmux(client, v);
-			dprintk(1, KERN_INFO "%s: switched to input=%d\n",
-				I2C_NAME(client), v);
+			v4l_dbg(1, debug, client, "switched to input=%d\n", v);
 		}
 		break;
 
@@ -392,8 +349,7 @@
 		if (decoder->enable != v) {
 			decoder->enable = v;
 			saa7110_write(client, 0x0E, v ? 0x18 : 0x80);
-			dprintk(1, KERN_INFO "%s: YUV %s\n", I2C_NAME(client),
-				v ? "on" : "off");
+			v4l_dbg(1, debug, client, "YUV %s\n", v ? "on" : "off");
 		}
 		break;
 
@@ -423,23 +379,23 @@
 			saa7110_write(client, 0x07,
 				      (decoder->hue >> 8) - 128);
 		}
-	}
 		break;
+	}
 
 	case DECODER_DUMP:
+		if (!debug)
+			break;
 		for (v = 0; v < SAA7110_NR_REG; v += 16) {
 			int j;
-			dprintk(1, KERN_DEBUG "%s: %02x:", I2C_NAME(client),
-				v);
+			v4l_dbg(1, debug, client, "%02x:", v);
 			for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++)
-				dprintk(1, " %02x", decoder->reg[v + j]);
-			dprintk(1, "\n");
+				printk(KERN_CONT " %02x", decoder->reg[v + j]);
+			printk(KERN_CONT "\n");
 		}
 		break;
 
 	default:
-		dprintk(1, KERN_INFO "unknown saa7110_command??(%d)\n",
-			cmd);
+		v4l_dbg(1, debug, client, "unknown command %08x\n", cmd);
 		return -EINVAL;
 	}
 	return 0;
@@ -451,55 +407,28 @@
  * Generic i2c probe
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
-static unsigned short normal_i2c[] = {
-	I2C_SAA7110 >> 1,
-	(I2C_SAA7110 >> 1) + 1,
-	I2C_CLIENT_END
-};
 
-static unsigned short ignore = I2C_CLIENT_END;
+static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END };
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
+I2C_CLIENT_INSMOD;
 
-static struct i2c_driver i2c_driver_saa7110;
-
-static int
-saa7110_detect_client (struct i2c_adapter *adapter,
-		       int                 address,
-		       int                 kind)
+static int saa7110_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-	struct i2c_client *client;
 	struct saa7110 *decoder;
 	int rv;
 
-	dprintk(1,
-		KERN_INFO
-		"saa7110.c: detecting saa7110 client on address 0x%x\n",
-		address << 1);
-
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality
-	    (adapter,
-	     I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter,
+		I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_saa7110;
-	strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
-	if (!decoder) {
-		kfree(client);
+	if (!decoder)
 		return -ENOMEM;
-	}
 	decoder->norm = VIDEO_MODE_PAL;
 	decoder->input = 0;
 	decoder->enable = 1;
@@ -510,18 +439,10 @@
 	init_waitqueue_head(&decoder->wq);
 	i2c_set_clientdata(client, decoder);
 
-	rv = i2c_attach_client(client);
-	if (rv) {
-		kfree(client);
-		kfree(decoder);
-		return rv;
-	}
-
 	rv = saa7110_write_block(client, initseq, sizeof(initseq));
-	if (rv < 0)
-		dprintk(1, KERN_ERR "%s_attach: init status %d\n",
-			I2C_NAME(client), rv);
-	else {
+	if (rv < 0) {
+		v4l_dbg(1, debug, client, "init status %d\n", rv);
+	} else {
 		int ver, status;
 		saa7110_write(client, 0x21, 0x10);
 		saa7110_write(client, 0x0e, 0x18);
@@ -530,10 +451,8 @@
 		saa7110_write(client, 0x0D, 0x06);
 		//mdelay(150);
 		status = saa7110_read(client);
-		dprintk(1,
-			KERN_INFO
-			"%s_attach: SAA7110A version %x at 0x%02x, status=0x%02x\n",
-			I2C_NAME(client), ver, client->addr << 1, status);
+		v4l_dbg(1, debug, client, "version %x, status=0x%02x\n",
+			       ver, status);
 		saa7110_write(client, 0x0D, 0x86);
 		saa7110_write(client, 0x0F, 0x10);
 		saa7110_write(client, 0x11, 0x59);
@@ -547,58 +466,25 @@
 	return 0;
 }
 
-static int
-saa7110_attach_adapter (struct i2c_adapter *adapter)
+static int saa7110_remove(struct i2c_client *client)
 {
-	dprintk(1,
-		KERN_INFO
-		"saa7110.c: starting probe for adapter %s (0x%x)\n",
-		I2C_NAME(adapter), adapter->id);
-	return i2c_probe(adapter, &addr_data, &saa7110_detect_client);
-}
-
-static int
-saa7110_detach_client (struct i2c_client *client)
-{
-	struct saa7110 *decoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(decoder);
-	kfree(client);
-
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_saa7110 = {
-	.driver = {
-		.name = "saa7110",
-	},
-
-	.id = I2C_DRIVERID_SAA7110,
-
-	.attach_adapter = saa7110_attach_adapter,
-	.detach_client = saa7110_detach_client,
-	.command = saa7110_command,
+static const struct i2c_device_id saa7110_id[] = {
+	{ "saa7110", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, saa7110_id);
 
-static int __init
-saa7110_init (void)
-{
-	return i2c_add_driver(&i2c_driver_saa7110);
-}
-
-static void __exit
-saa7110_exit (void)
-{
-	i2c_del_driver(&i2c_driver_saa7110);
-}
-
-module_init(saa7110_init);
-module_exit(saa7110_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "saa7110",
+	.driverid = I2C_DRIVERID_SAA7110,
+	.command = saa7110_command,
+	.probe = saa7110_probe,
+	.remove = saa7110_remove,
+	.id_table = saa7110_id,
+};
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 96c3d43..a4738a2 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -28,43 +28,24 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
 #include <linux/videodev.h>
 #include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Philips SAA7111 video decoder driver");
 MODULE_AUTHOR("Dave Perks");
 MODULE_LICENSE("GPL");
 
-
-#define I2C_NAME(s) (s)->name
-
-
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 /* ----------------------------------------------------------------------- */
 
 #define SAA7111_NR_REG		0x18
@@ -77,14 +58,9 @@
 	int enable;
 };
 
-#define   I2C_SAA7111        0x48
-
 /* ----------------------------------------------------------------------- */
 
-static inline int
-saa7111_write (struct i2c_client *client,
-	       u8                 reg,
-	       u8                 value)
+static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct saa7111 *decoder = i2c_get_clientdata(client);
 
@@ -92,8 +68,7 @@
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline void
-saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
+static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct saa7111 *decoder = i2c_get_clientdata(client);
 
@@ -103,10 +78,7 @@
 	}
 }
 
-static int
-saa7111_write_block (struct i2c_client *client,
-		     const u8          *data,
-		     unsigned int       len)
+static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
 {
 	int ret = -1;
 	u8 reg;
@@ -127,18 +99,17 @@
 				    decoder->reg[reg++] = data[1];
 				len -= 2;
 				data += 2;
-			} while (len >= 2 && data[0] == reg &&
-				 block_len < 32);
-			if ((ret = i2c_master_send(client, block_data,
-						   block_len)) < 0)
+			} while (len >= 2 && data[0] == reg && block_len < 32);
+			ret = i2c_master_send(client, block_data, block_len);
+			if (ret < 0)
 				break;
 		}
 	} else {
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			if ((ret = saa7111_write(client, reg,
-						 *data++)) < 0)
+			ret = saa7111_write(client, reg, *data++);
+			if (ret < 0)
 				break;
 			len -= 2;
 		}
@@ -147,16 +118,13 @@
 	return ret;
 }
 
-static int
-saa7111_init_decoder (struct i2c_client *client,
-	      struct video_decoder_init *init)
+static int saa7111_init_decoder(struct i2c_client *client,
+		struct video_decoder_init *init)
 {
 	return saa7111_write_block(client, init->data, init->len);
 }
 
-static inline int
-saa7111_read (struct i2c_client *client,
-	      u8                 reg)
+static inline int saa7111_read(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
 }
@@ -203,28 +171,23 @@
 	0x17, 0x00,		/* 17 - VBI */
 };
 
-static int
-saa7111_command (struct i2c_client *client,
-		 unsigned int       cmd,
-		 void              *arg)
+static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	struct saa7111 *decoder = i2c_get_clientdata(client);
 
 	switch (cmd) {
-
 	case 0:
 		break;
 	case DECODER_INIT:
 	{
 		struct video_decoder_init *init = arg;
+		struct video_decoder_init vdi;
+
 		if (NULL != init)
 			return saa7111_init_decoder(client, init);
-		else {
-			struct video_decoder_init vdi;
-			vdi.data = saa7111_i2c_init;
-			vdi.len = sizeof(saa7111_i2c_init);
-			return saa7111_init_decoder(client, &vdi);
-		}
+		vdi.data = saa7111_i2c_init;
+		vdi.len = sizeof(saa7111_i2c_init);
+		return saa7111_init_decoder(client, &vdi);
 	}
 
 	case DECODER_DUMP:
@@ -234,15 +197,15 @@
 		for (i = 0; i < SAA7111_NR_REG; i += 16) {
 			int j;
 
-			printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
+			v4l_info(client, "%03x", i);
 			for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) {
-				printk(" %02x",
+				printk(KERN_CONT " %02x",
 				       saa7111_read(client, i + j));
 			}
-			printk("\n");
+			printk(KERN_CONT "\n");
 		}
-	}
 		break;
+	}
 
 	case DECODER_GET_CAPABILITIES:
 	{
@@ -255,8 +218,8 @@
 			     VIDEO_DECODER_CCIR;
 		cap->inputs = 8;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case DECODER_GET_STATUS:
 	{
@@ -265,8 +228,7 @@
 		int res;
 
 		status = saa7111_read(client, 0x1f);
-		dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
-			status);
+		v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
 		res = 0;
 		if ((status & (1 << 6)) == 0) {
 			res |= DECODER_STATUS_GOOD;
@@ -294,8 +256,8 @@
 			res |= DECODER_STATUS_COLOR;
 		}
 		*iarg = res;
-	}
 		break;
+	}
 
 	case DECODER_SET_GPIO:
 	{
@@ -362,8 +324,8 @@
 
 		}
 		decoder->norm = *iarg;
-	}
 		break;
+	}
 
 	case DECODER_SET_INPUT:
 	{
@@ -387,8 +349,8 @@
 							     3) ? 0x80 :
 							    0));
 		}
-	}
 		break;
+	}
 
 	case DECODER_SET_OUTPUT:
 	{
@@ -398,8 +360,8 @@
 		if (*iarg != 0) {
 			return -EINVAL;
 		}
-	}
 		break;
+	}
 
 	case DECODER_ENABLE_OUTPUT:
 	{
@@ -439,8 +401,8 @@
 					      (decoder->reg[0x11] & 0xf3));
 			}
 		}
-	}
 		break;
+	}
 
 	case DECODER_SET_PICTURE:
 	{
@@ -454,8 +416,8 @@
 		saa7111_write(client, 0x0c, pic->colour >> 9);
 		/* We want -128 to 127 we get 0-65535 */
 		saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
-	}
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -466,48 +428,23 @@
 
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver i2c_driver_saa7111;
-
-static int
-saa7111_detect_client (struct i2c_adapter *adapter,
-		       int                 address,
-		       int                 kind)
+static int saa7111_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	int i;
-	struct i2c_client *client;
 	struct saa7111 *decoder;
 	struct video_decoder_init vdi;
 
-	dprintk(1,
-		KERN_INFO
-		"saa7111.c: detecting saa7111 client on address 0x%x\n",
-		address << 1);
-
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_saa7111;
-	strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
 	if (decoder == NULL) {
@@ -519,82 +456,37 @@
 	decoder->enable = 1;
 	i2c_set_clientdata(client, decoder);
 
-	i = i2c_attach_client(client);
-	if (i) {
-		kfree(client);
-		kfree(decoder);
-		return i;
-	}
-
 	vdi.data = saa7111_i2c_init;
 	vdi.len = sizeof(saa7111_i2c_init);
 	i = saa7111_init_decoder(client, &vdi);
 	if (i < 0) {
-		dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
-			I2C_NAME(client), i);
+		v4l_dbg(1, debug, client, "init status %d\n", i);
 	} else {
-		dprintk(1,
-			KERN_INFO
-			"%s_attach: chip version %x at address 0x%x\n",
-			I2C_NAME(client), saa7111_read(client, 0x00) >> 4,
-			client->addr << 1);
+		v4l_dbg(1, debug, client, "revision %x\n",
+			saa7111_read(client, 0x00) >> 4);
 	}
-
 	return 0;
 }
 
-static int
-saa7111_attach_adapter (struct i2c_adapter *adapter)
+static int saa7111_remove(struct i2c_client *client)
 {
-	dprintk(1,
-		KERN_INFO
-		"saa7111.c: starting probe for adapter %s (0x%x)\n",
-		I2C_NAME(adapter), adapter->id);
-	return i2c_probe(adapter, &addr_data, &saa7111_detect_client);
-}
-
-static int
-saa7111_detach_client (struct i2c_client *client)
-{
-	struct saa7111 *decoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(decoder);
-	kfree(client);
-
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_saa7111 = {
-	.driver = {
-		.name = "saa7111",
-	},
-
-	.id = I2C_DRIVERID_SAA7111A,
-
-	.attach_adapter = saa7111_attach_adapter,
-	.detach_client = saa7111_detach_client,
-	.command = saa7111_command,
+static const struct i2c_device_id saa7111_id[] = {
+	{ "saa7111_old", 0 },	/* "saa7111" maps to the saa7115 driver */
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, saa7111_id);
 
-static int __init
-saa7111_init (void)
-{
-	return i2c_add_driver(&i2c_driver_saa7111);
-}
-
-static void __exit
-saa7111_exit (void)
-{
-	i2c_del_driver(&i2c_driver_saa7111);
-}
-
-module_init(saa7111_init);
-module_exit(saa7111_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "saa7111",
+	.driverid = I2C_DRIVERID_SAA7111A,
+	.command = saa7111_command,
+	.probe = saa7111_probe,
+	.remove = saa7111_remove,
+	.id_table = saa7111_id,
+};
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index e790755..7ca709f 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -29,43 +29,24 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
 #include <linux/videodev.h>
 #include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
 MODULE_AUTHOR("Maxim Yevtyushkin");
 MODULE_LICENSE("GPL");
 
-
-#define I2C_NAME(x) (x)->name
-
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 /* ----------------------------------------------------------------------- */
 
 struct saa7114 {
@@ -81,9 +62,6 @@
 	int playback;
 };
 
-#define   I2C_SAA7114        0x42
-#define   I2C_SAA7114A       0x40
-
 #define   I2C_DELAY   10
 
 
@@ -129,18 +107,12 @@
 
 /* ----------------------------------------------------------------------- */
 
-static inline int
-saa7114_write (struct i2c_client *client,
-	       u8                 reg,
-	       u8                 value)
+static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static int
-saa7114_write_block (struct i2c_client *client,
-		     const u8          *data,
-		     unsigned int       len)
+static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
 {
 	int ret = -1;
 	u8 reg;
@@ -160,18 +132,17 @@
 				reg++;
 				len -= 2;
 				data += 2;
-			} while (len >= 2 && data[0] == reg &&
-				 block_len < 32);
-			if ((ret = i2c_master_send(client, block_data,
-						   block_len)) < 0)
+			} while (len >= 2 && data[0] == reg && block_len < 32);
+			ret = i2c_master_send(client, block_data, block_len);
+			if (ret < 0)
 				break;
 		}
 	} else {
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			if ((ret = saa7114_write(client, reg,
-						 *data++)) < 0)
+			ret = saa7114_write(client, reg, *data++);
+			if (ret < 0)
 				break;
 			len -= 2;
 		}
@@ -180,9 +151,7 @@
 	return ret;
 }
 
-static inline int
-saa7114_read (struct i2c_client *client,
-	      u8                 reg)
+static inline int saa7114_read(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
 }
@@ -452,15 +421,11 @@
 	0xef, 0x00
 };
 
-static int
-saa7114_command (struct i2c_client *client,
-		 unsigned int       cmd,
-		 void              *arg)
+static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	struct saa7114 *decoder = i2c_get_clientdata(client);
 
 	switch (cmd) {
-
 	case 0:
 		//dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
 		//saa7114_write_block(client, init, sizeof(init));
@@ -470,27 +435,28 @@
 	{
 		int i;
 
-		dprintk(1, KERN_INFO "%s: decoder dump\n", I2C_NAME(client));
+		if (!debug)
+			break;
+		v4l_info(client, "decoder dump\n");
 
 		for (i = 0; i < 32; i += 16) {
 			int j;
 
-			printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
+			v4l_info(client, "%03x", i);
 			for (j = 0; j < 16; ++j) {
-				printk(" %02x",
+				printk(KERN_CONT " %02x",
 				       saa7114_read(client, i + j));
 			}
-			printk("\n");
+			printk(KERN_CONT "\n");
 		}
-	}
 		break;
+	}
 
 	case DECODER_GET_CAPABILITIES:
 	{
 		struct video_decoder_capability *cap = arg;
 
-		dprintk(1, KERN_DEBUG "%s: decoder get capabilities\n",
-			I2C_NAME(client));
+		v4l_dbg(1, debug, client, "get capabilities\n");
 
 		cap->flags = VIDEO_DECODER_PAL |
 			     VIDEO_DECODER_NTSC |
@@ -498,8 +464,8 @@
 			     VIDEO_DECODER_CCIR;
 		cap->inputs = 8;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case DECODER_GET_STATUS:
 	{
@@ -509,8 +475,7 @@
 
 		status = saa7114_read(client, 0x1f);
 
-		dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
-			status);
+		v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
 		res = 0;
 		if ((status & (1 << 6)) == 0) {
 			res |= DECODER_STATUS_GOOD;
@@ -538,8 +503,8 @@
 			res |= DECODER_STATUS_COLOR;
 		}
 		*iarg = res;
-	}
 		break;
+	}
 
 	case DECODER_SET_NORM:
 	{
@@ -547,12 +512,11 @@
 
 		short int hoff = 0, voff = 0, w = 0, h = 0;
 
-		dprintk(1, KERN_DEBUG "%s: decoder set norm ",
-			I2C_NAME(client));
-		switch (*iarg) {
+		v4l_dbg(1, debug, client, "set norm\n");
 
+		switch (*iarg) {
 		case VIDEO_MODE_NTSC:
-			dprintk(1, "NTSC\n");
+			v4l_dbg(1, debug, client, "NTSC\n");
 			decoder->reg[REG_ADDR(0x06)] =
 			    SAA_7114_NTSC_HSYNC_START;
 			decoder->reg[REG_ADDR(0x07)] =
@@ -571,7 +535,7 @@
 			break;
 
 		case VIDEO_MODE_PAL:
-			dprintk(1, "PAL\n");
+			v4l_dbg(1, debug, client, "PAL\n");
 			decoder->reg[REG_ADDR(0x06)] =
 			    SAA_7114_PAL_HSYNC_START;
 			decoder->reg[REG_ADDR(0x07)] =
@@ -590,9 +554,8 @@
 			break;
 
 		default:
-			dprintk(1, " Unknown video mode!!!\n");
+			v4l_dbg(1, debug, client, "Unknown video mode\n");
 			return -EINVAL;
-
 		}
 
 
@@ -644,22 +607,20 @@
 		saa7114_write(client, 0x80, 0x36);	// i-port and scaler back end clock selection
 
 		decoder->norm = *iarg;
-	}
 		break;
+	}
 
 	case DECODER_SET_INPUT:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_DEBUG "%s: decoder set input (%d)\n",
-			I2C_NAME(client), *iarg);
+		v4l_dbg(1, debug, client, "set input (%d)\n", *iarg);
 		if (*iarg < 0 || *iarg > 7) {
 			return -EINVAL;
 		}
 
 		if (decoder->input != *iarg) {
-			dprintk(1, KERN_DEBUG "%s: now setting %s input\n",
-				I2C_NAME(client),
+			v4l_dbg(1, debug, client, "now setting %s input\n",
 				*iarg >= 6 ? "S-Video" : "Composite");
 			decoder->input = *iarg;
 
@@ -690,30 +651,29 @@
 			saa7114_write(client, 0x0e,
 				      decoder->reg[REG_ADDR(0x0e)]);
 		}
-	}
 		break;
+	}
 
 	case DECODER_SET_OUTPUT:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_DEBUG "%s: decoder set output\n",
-			I2C_NAME(client));
+		v4l_dbg(1, debug, client, "set output\n");
 
 		/* not much choice of outputs */
 		if (*iarg != 0) {
 			return -EINVAL;
 		}
-	}
 		break;
+	}
 
 	case DECODER_ENABLE_OUTPUT:
 	{
 		int *iarg = arg;
 		int enable = (*iarg != 0);
 
-		dprintk(1, KERN_DEBUG "%s: decoder %s output\n",
-			I2C_NAME(client), enable ? "enable" : "disable");
+		v4l_dbg(1, debug, client, "%s output\n",
+			enable ? "enable" : "disable");
 
 		decoder->playback = !enable;
 
@@ -754,18 +714,16 @@
 			saa7114_write(client, 0x80, 0x36);
 
 		}
-	}
 		break;
+	}
 
 	case DECODER_SET_PICTURE:
 	{
 		struct video_picture *pic = arg;
 
-		dprintk(1,
-			KERN_DEBUG
-			"%s: decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
-			I2C_NAME(client), pic->brightness, pic->contrast,
-			pic->colour, pic->hue);
+		v4l_dbg(1, debug, client,
+			"decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
+			pic->brightness, pic->contrast, pic->colour, pic->hue);
 
 		if (decoder->bright != pic->brightness) {
 			/* We want 0 to 255 we get 0-65535 */
@@ -789,8 +747,8 @@
 			saa7114_write(client, 0x0d,
 				      (decoder->hue - 32768) >> 8);
 		}
-	}
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -801,58 +759,30 @@
 
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] =
-    { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver i2c_driver_saa7114;
-
-static int
-saa7114_detect_client (struct i2c_adapter *adapter,
-		       int                 address,
-		       int                 kind)
+static int saa7114_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	int i, err[30];
 	short int hoff = SAA_7114_NTSC_HOFFSET;
 	short int voff = SAA_7114_NTSC_VOFFSET;
 	short int w = SAA_7114_NTSC_WIDTH;
 	short int h = SAA_7114_NTSC_HEIGHT;
-	struct i2c_client *client;
 	struct saa7114 *decoder;
 
-	dprintk(1,
-		KERN_INFO
-		"saa7114.c: detecting saa7114 client on address 0x%x\n",
-		address << 1);
-
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_saa7114;
-	strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
-	if (decoder == NULL) {
-		kfree(client);
+	if (decoder == NULL)
 		return -ENOMEM;
-	}
 	decoder->norm = VIDEO_MODE_NTSC;
 	decoder->input = -1;
 	decoder->enable = 1;
@@ -937,8 +867,7 @@
 	decoder->reg[REG_ADDR(0x0e)] |= 1;	// combfilter on
 
 
-	dprintk(1, KERN_DEBUG "%s_attach: starting decoder init\n",
-		I2C_NAME(client));
+	v4l_dbg(1, debug, client, "starting init\n");
 
 	err[0] =
 	    saa7114_write_block(client, decoder->reg + (0x20 << 1),
@@ -962,28 +891,23 @@
 
 	for (i = 0; i <= 5; i++) {
 		if (err[i] < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s_attach: init error %d at stage %d, leaving attach.\n",
-				I2C_NAME(client), i, err[i]);
+			v4l_dbg(1, debug, client,
+				"init error %d at stage %d, leaving attach.\n",
+				i, err[i]);
 			kfree(decoder);
-			kfree(client);
-			return 0;
+			return -EIO;
 		}
 	}
 
 	for (i = 6; i < 8; i++) {
-		dprintk(1,
-			KERN_DEBUG
-			"%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
-			I2C_NAME(client), i, saa7114_read(client, i),
+		v4l_dbg(1, debug, client,
+			"reg[0x%02x] = 0x%02x (0x%02x)\n",
+			i, saa7114_read(client, i),
 			decoder->reg[REG_ADDR(i)]);
 	}
 
-	dprintk(1,
-		KERN_DEBUG
-		"%s_attach: performing decoder reset sequence\n",
-		I2C_NAME(client));
+	v4l_dbg(1, debug, client,
+		"performing decoder reset sequence\n");
 
 	err[6] = saa7114_write(client, 0x80, 0x06);	// i-port and scaler backend clock selection, task A&B off
 	err[7] = saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
@@ -991,19 +915,15 @@
 
 	for (i = 6; i <= 8; i++) {
 		if (err[i] < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s_attach: init error %d at stage %d, leaving attach.\n",
-				I2C_NAME(client), i, err[i]);
+			v4l_dbg(1, debug, client,
+				"init error %d at stage %d, leaving attach.\n",
+				i, err[i]);
 			kfree(decoder);
-			kfree(client);
-			return 0;
+			return -EIO;
 		}
 	}
 
-	dprintk(1, KERN_INFO "%s_attach: performing the rest of init\n",
-		I2C_NAME(client));
-
+	v4l_dbg(1, debug, client, "performing the rest of init\n");
 
 	err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]);
 	err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1);	// big seq
@@ -1039,37 +959,32 @@
 
 	for (i = 9; i <= 18; i++) {
 		if (err[i] < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s_attach: init error %d at stage %d, leaving attach.\n",
-				I2C_NAME(client), i, err[i]);
+			v4l_dbg(1, debug, client,
+				"init error %d at stage %d, leaving attach.\n",
+				i, err[i]);
 			kfree(decoder);
-			kfree(client);
-			return 0;
+			return -EIO;
 		}
 	}
 
 
 	for (i = 6; i < 8; i++) {
-		dprintk(1,
-			KERN_DEBUG
-			"%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
-			I2C_NAME(client), i, saa7114_read(client, i),
+		v4l_dbg(1, debug, client,
+			"reg[0x%02x] = 0x%02x (0x%02x)\n",
+			i, saa7114_read(client, i),
 			decoder->reg[REG_ADDR(i)]);
 	}
 
 
 	for (i = 0x11; i <= 0x13; i++) {
-		dprintk(1,
-			KERN_DEBUG
-			"%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
-			I2C_NAME(client), i, saa7114_read(client, i),
+		v4l_dbg(1, debug, client,
+			"reg[0x%02x] = 0x%02x (0x%02x)\n",
+			i, saa7114_read(client, i),
 			decoder->reg[REG_ADDR(i)]);
 	}
 
 
-	dprintk(1, KERN_DEBUG "%s_attach: setting video input\n",
-		I2C_NAME(client));
+	v4l_dbg(1, debug, client, "setting video input\n");
 
 	err[19] =
 	    saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]);
@@ -1080,20 +995,15 @@
 
 	for (i = 19; i <= 21; i++) {
 		if (err[i] < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s_attach: init error %d at stage %d, leaving attach.\n",
-				I2C_NAME(client), i, err[i]);
+			v4l_dbg(1, debug, client,
+				"init error %d at stage %d, leaving attach.\n",
+				i, err[i]);
 			kfree(decoder);
-			kfree(client);
-			return 0;
+			return -EIO;
 		}
 	}
 
-	dprintk(1,
-		KERN_DEBUG
-		"%s_attach: performing decoder reset sequence\n",
-		I2C_NAME(client));
+	v4l_dbg(1, debug, client, "performing decoder reset sequence\n");
 
 	err[22] = saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
 	err[23] = saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release
@@ -1102,13 +1012,11 @@
 
 	for (i = 22; i <= 24; i++) {
 		if (err[i] < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s_attach: init error %d at stage %d, leaving attach.\n",
-				I2C_NAME(client), i, err[i]);
+			v4l_dbg(1, debug, client,
+				"init error %d at stage %d, leaving attach.\n",
+				i, err[i]);
 			kfree(decoder);
-			kfree(client);
-			return 0;
+			return -EIO;
 		}
 	}
 
@@ -1116,101 +1024,45 @@
 	err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]);
 	err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]);
 
-	dprintk(1,
-		KERN_INFO
-		"%s_attach: chip version %x, decoder status 0x%02x\n",
-		I2C_NAME(client), saa7114_read(client, 0x00) >> 4,
+	v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n",
+		saa7114_read(client, 0x00) >> 4,
 		saa7114_read(client, 0x1f));
-	dprintk(1,
-		KERN_DEBUG
-		"%s_attach: power save control: 0x%02x, scaler status: 0x%02x\n",
-		I2C_NAME(client), saa7114_read(client, 0x88),
+	v4l_dbg(1, debug, client,
+		"power save control: 0x%02x, scaler status: 0x%02x\n",
+		saa7114_read(client, 0x88),
 		saa7114_read(client, 0x8f));
 
 
 	for (i = 0x94; i < 0x96; i++) {
-		dprintk(1,
-			KERN_DEBUG
-			"%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
-			I2C_NAME(client), i, saa7114_read(client, i),
+		v4l_dbg(1, debug, client,
+			"reg[0x%02x] = 0x%02x (0x%02x)\n",
+			i, saa7114_read(client, i),
 			decoder->reg[REG_ADDR(i)]);
 	}
 
-	i = i2c_attach_client(client);
-	if (i) {
-		kfree(client);
-		kfree(decoder);
-		return i;
-	}
-
 	//i = saa7114_write_block(client, init, sizeof(init));
-	i = 0;
-	if (i < 0) {
-		dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
-			I2C_NAME(client), i);
-	} else {
-		dprintk(1,
-			KERN_INFO
-			"%s_attach: chip version %x at address 0x%x\n",
-			I2C_NAME(client), saa7114_read(client, 0x00) >> 4,
-			client->addr << 1);
-	}
-
 	return 0;
 }
 
-static int
-saa7114_attach_adapter (struct i2c_adapter *adapter)
+static int saa7114_remove(struct i2c_client *client)
 {
-	dprintk(1,
-		KERN_INFO
-		"saa7114.c: starting probe for adapter %s (0x%x)\n",
-		I2C_NAME(adapter), adapter->id);
-	return i2c_probe(adapter, &addr_data, &saa7114_detect_client);
-}
-
-static int
-saa7114_detach_client (struct i2c_client *client)
-{
-	struct saa7114 *decoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(decoder);
-	kfree(client);
-
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_saa7114 = {
-	.driver = {
-		.name = "saa7114",
-	},
-
-	.id = I2C_DRIVERID_SAA7114,
-
-	.attach_adapter = saa7114_attach_adapter,
-	.detach_client = saa7114_detach_client,
-	.command = saa7114_command,
+static const struct i2c_device_id saa7114_id[] = {
+	{ "saa7114_old", 0 },	/* "saa7114" maps to the saa7115 driver */
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, saa7114_id);
 
-static int __init
-saa7114_init (void)
-{
-	return i2c_add_driver(&i2c_driver_saa7114);
-}
-
-static void __exit
-saa7114_exit (void)
-{
-	i2c_del_driver(&i2c_driver_saa7114);
-}
-
-module_init(saa7114_init);
-module_exit(saa7114_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "saa7114",
+	.driverid = I2C_DRIVERID_SAA7114,
+	.command = saa7114_command,
+	.probe = saa7114_probe,
+	.remove = saa7114_remove,
+	.id_table = saa7114_id,
+};
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index d0e83fe..cc02fb1 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -29,7 +29,7 @@
  * Note: the saa7126 is identical to the saa7127, and the saa7128 is
  * identical to the saa7129, except that the saa7126 and saa7128 have
  * macrovision anti-taping support. This driver will almost certainly
- * work find for those chips, except of course for the missing anti-taping
+ * work fine for those chips, except of course for the missing anti-taping
  * support.
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 87c1098..8c46115 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -535,11 +535,16 @@
 				struct tda1004x_config *cdec_conf,
 				struct tda827x_config *tuner_conf)
 {
-	dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
-	if (dev->dvb.frontend) {
+	struct videobuf_dvb_frontend *fe0;
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+
+	fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
+	if (fe0->dvb.frontend) {
 		if (cdec_conf->i2c_gate)
-			dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-		if (dvb_attach(tda827x_attach, dev->dvb.frontend,
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+		if (dvb_attach(tda827x_attach, fe0->dvb.frontend,
 			       cdec_conf->tuner_address,
 			       &dev->i2c_adap, tuner_conf))
 			return 0;
@@ -944,12 +949,30 @@
 {
 	int ret;
 	int attach_xc3028 = 0;
+	struct videobuf_dvb_frontend *fe0;
+
+	/* FIXME: add support for multi-frontend */
+	mutex_init(&dev->frontends.lock);
+	INIT_LIST_HEAD(&dev->frontends.felist);
+	dev->frontends.active_fe_id = 0;
+
+	printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
+
+	if (videobuf_dvb_alloc_frontend(&dev->frontends, 1) == NULL) {
+		printk(KERN_ERR "%s() failed to alloc\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
 
 	/* init struct videobuf_dvb */
 	dev->ts.nr_bufs    = 32;
 	dev->ts.nr_packets = 32*4;
-	dev->dvb.name = dev->name;
-	videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops,
+	fe0->dvb.name = dev->name;
+	videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops,
 			    &dev->pci->dev, &dev->slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_ALTERNATE,
@@ -959,47 +982,47 @@
 	switch (dev->board) {
 	case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
 		dprintk("pinnacle 300i dvb setup\n");
-		dev->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
+		fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
 		}
 		break;
 	case SAA7134_BOARD_AVERMEDIA_777:
 	case SAA7134_BOARD_AVERMEDIA_A16AR:
 		dprintk("avertv 777 dvb setup\n");
-		dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
+		fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend) {
+			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 				   &dev->i2c_adap, 0x61,
 				   TUNER_PHILIPS_TD1316);
 		}
 		break;
 	case SAA7134_BOARD_AVERMEDIA_A16D:
 		dprintk("AverMedia A16D dvb setup\n");
-		dev->dvb.frontend = dvb_attach(mt352_attach,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
 						&avermedia_xc3028_mt352_dev,
 						&dev->i2c_adap);
 		attach_xc3028 = 1;
 		break;
 	case SAA7134_BOARD_MD7134:
-		dev->dvb.frontend = dvb_attach(tda10046_attach,
+		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 					       &medion_cardbus,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend) {
+			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 				   &dev->i2c_adap, medion_cardbus.tuner_address,
 				   TUNER_PHILIPS_FMD1216ME_MK3);
 		}
 		break;
 	case SAA7134_BOARD_PHILIPS_TOUGH:
-		dev->dvb.frontend = dvb_attach(tda10046_attach,
+		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 					       &philips_tu1216_60_config,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
-			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+			fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
 		}
 		break;
 	case SAA7134_BOARD_FLYDVBTDUO:
@@ -1010,24 +1033,24 @@
 		break;
 	case SAA7134_BOARD_PHILIPS_EUROPA:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-		dev->dvb.frontend = dvb_attach(tda10046_attach,
+		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 					       &philips_europa_config,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
-			dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
-			dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
-			dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
-			dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+		if (fe0->dvb.frontend) {
+			dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+			fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+			fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+			fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+			fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
 		}
 		break;
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-		dev->dvb.frontend = dvb_attach(tda10046_attach,
+		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 					       &philips_tu1216_61_config,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
-			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+			fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
 		}
 		break;
 	case SAA7134_BOARD_KWORLD_DVBT_210:
@@ -1066,14 +1089,14 @@
 						 &tda827x_cfg_0) < 0)
 				goto dettach_frontend;
 		} else {  		/* satellite */
-			dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
-			if (dev->dvb.frontend) {
-				if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
+			fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+			if (fe0->dvb.frontend) {
+				if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63,
 									&dev->i2c_adap, 0) == NULL) {
 					wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
 					goto dettach_frontend;
 				}
-				if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
+				if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap,
 										0x08, 0, 0) == NULL) {
 					wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
 					goto dettach_frontend;
@@ -1083,11 +1106,11 @@
 		break;
 	case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
 	case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
-		dev->dvb.frontend = dvb_attach(tda10046_attach,
+		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 					       &ads_tech_duo_config,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			if (dvb_attach(tda827x_attach,dev->dvb.frontend,
+		if (fe0->dvb.frontend) {
+			if (dvb_attach(tda827x_attach,fe0->dvb.frontend,
 				   ads_tech_duo_config.tuner_address, &dev->i2c_adap,
 								&ads_duo_cfg) == NULL) {
 				wprintk("no tda827x tuner found at addr: %02x\n",
@@ -1108,15 +1131,15 @@
 						 &tda827x_cfg_0) < 0)
 				goto dettach_frontend;
 		} else {        /* satellite */
-			dev->dvb.frontend = dvb_attach(tda10086_attach,
+			fe0->dvb.frontend = dvb_attach(tda10086_attach,
 							&flydvbs, &dev->i2c_adap);
-			if (dev->dvb.frontend) {
-				struct dvb_frontend *fe = dev->dvb.frontend;
+			if (fe0->dvb.frontend) {
+				struct dvb_frontend *fe = fe0->dvb.frontend;
 				u8 dev_id = dev->eedata[2];
 				u8 data = 0xc4;
 				struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
 
-				if (dvb_attach(tda826x_attach, dev->dvb.frontend,
+				if (dvb_attach(tda826x_attach, fe0->dvb.frontend,
 						0x60, &dev->i2c_adap, 0) == NULL) {
 					wprintk("%s: Medion Quadro, no tda826x "
 						"found !\n", __func__);
@@ -1150,31 +1173,31 @@
 		}
 		break;
 	case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
-		dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
+		fe0->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend)
-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+		if (fe0->dvb.frontend)
+			dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61,
 				   NULL, DVB_PLL_TDHU2);
 		break;
 	case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
 	case SAA7134_BOARD_KWORLD_ATSC110:
-		dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
+		fe0->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend)
-			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+		if (fe0->dvb.frontend)
+			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 				   &dev->i2c_adap, 0x61,
 				   TUNER_PHILIPS_TUV1236D);
 		break;
 	case SAA7134_BOARD_FLYDVBS_LR300:
-		dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+		fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+		if (fe0->dvb.frontend) {
+			if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
 				       &dev->i2c_adap, 0) == NULL) {
 				wprintk("%s: No tda826x found!\n", __func__);
 				goto dettach_frontend;
 			}
-			if (dvb_attach(isl6421_attach, dev->dvb.frontend,
+			if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
 				       &dev->i2c_adap, 0x08, 0, 0) == NULL) {
 				wprintk("%s: No ISL6421 found!\n", __func__);
 				goto dettach_frontend;
@@ -1182,25 +1205,25 @@
 		}
 		break;
 	case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
-		dev->dvb.frontend = dvb_attach(tda10046_attach,
+		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 					       &medion_cardbus,
 					       &dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
-			dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+		if (fe0->dvb.frontend) {
+			dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+			fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
 
-			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 				   &dev->i2c_adap, medion_cardbus.tuner_address,
 				   TUNER_PHILIPS_FMD1216ME_MK3);
 		}
 		break;
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
-		dev->dvb.frontend = dvb_attach(tda10046_attach,
+		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 				&philips_europa_config,
 				&dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
-			dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
+			fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
 		}
 		break;
 	case SAA7134_BOARD_CINERGY_HT_PCMCIA:
@@ -1239,15 +1262,15 @@
 			goto dettach_frontend;
 		break;
 	case SAA7134_BOARD_PHILIPS_SNAKE:
-		dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+		fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
 						&dev->i2c_adap);
-		if (dev->dvb.frontend) {
-			if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+		if (fe0->dvb.frontend) {
+			if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
 					&dev->i2c_adap, 0) == NULL) {
 				wprintk("%s: No tda826x found!\n", __func__);
 				goto dettach_frontend;
 			}
-			if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
+			if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
 					&dev->i2c_adap, 0, 0) == NULL) {
 				wprintk("%s: No lnbp21 found!\n", __func__);
 				goto dettach_frontend;
@@ -1269,24 +1292,24 @@
 		saa7134_set_gpio(dev, 25, 0);
 		msleep(10);
 		saa7134_set_gpio(dev, 25, 1);
-		dev->dvb.frontend = dvb_attach(mt352_attach,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
 						&avermedia_xc3028_mt352_dev,
 						&dev->i2c_adap);
 		attach_xc3028 = 1;
 		break;
 	case SAA7134_BOARD_MD7134_BRIDGE_2:
-		dev->dvb.frontend = dvb_attach(tda10086_attach,
+		fe0->dvb.frontend = dvb_attach(tda10086_attach,
 						&sd1878_4m, &dev->i2c_adap);
-		if (dev->dvb.frontend) {
+		if (fe0->dvb.frontend) {
 			struct dvb_frontend *fe;
-			if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+			if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
 				  &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
 				wprintk("%s: MD7134 DVB-S, no SD1878 "
 					"found !\n", __func__);
 				goto dettach_frontend;
 			}
 			/* we need to open the i2c gate (we know it exists) */
-			fe = dev->dvb.frontend;
+			fe = fe0->dvb.frontend;
 			fe->ops.i2c_gate_ctrl(fe, 1);
 			if (dvb_attach(isl6405_attach, fe,
 					&dev->i2c_adap, 0x08, 0, 0) == NULL) {
@@ -1305,7 +1328,7 @@
 		saa7134_set_gpio(dev, 25, 0);
 		msleep(10);
 		saa7134_set_gpio(dev, 25, 1);
-		dev->dvb.frontend = dvb_attach(mt352_attach,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
 						&avermedia_xc3028_mt352_dev,
 						&dev->i2c_adap);
 		attach_xc3028 = 1;
@@ -1316,17 +1339,17 @@
 							&tda827x_cfg_2) < 0)
 				goto dettach_frontend;
 		} else {  		/* satellite */
-			dev->dvb.frontend = dvb_attach(tda10086_attach,
+			fe0->dvb.frontend = dvb_attach(tda10086_attach,
 						&flydvbs, &dev->i2c_adap);
-			if (dev->dvb.frontend) {
+			if (fe0->dvb.frontend) {
 				if (dvb_attach(tda826x_attach,
-						dev->dvb.frontend, 0x60,
+						fe0->dvb.frontend, 0x60,
 						&dev->i2c_adap, 0) == NULL) {
 					wprintk("%s: Asus Tiger 3in1, no "
 						"tda826x found!\n", __func__);
 					goto dettach_frontend;
 				}
-				if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
+				if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
 						&dev->i2c_adap, 0, 0) == NULL) {
 					wprintk("%s: Asus Tiger 3in1, no lnbp21"
 						" found!\n", __func__);
@@ -1352,10 +1375,10 @@
 			.i2c_addr  = 0x61,
 		};
 
-		if (!dev->dvb.frontend)
+		if (!fe0->dvb.frontend)
 			return -1;
 
-		fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+		fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
 		if (!fe) {
 			printk(KERN_ERR "%s/2: xc3028 attach failed\n",
 			       dev->name);
@@ -1363,40 +1386,47 @@
 		}
 	}
 
-	if (NULL == dev->dvb.frontend) {
+	if (NULL == fe0->dvb.frontend) {
 		printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
 		return -1;
 	}
 	/* define general-purpose callback pointer */
-	dev->dvb.frontend->callback = saa7134_tuner_callback;
+	fe0->dvb.frontend->callback = saa7134_tuner_callback;
 
 	/* register everything else */
-	ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
-				    adapter_nr);
+	ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+		&dev->pci->dev, adapter_nr, 0);
 
 	/* this sequence is necessary to make the tda1004x load its firmware
 	 * and to enter analog mode of hybrid boards
 	 */
 	if (!ret) {
-		if (dev->dvb.frontend->ops.init)
-			dev->dvb.frontend->ops.init(dev->dvb.frontend);
-		if (dev->dvb.frontend->ops.sleep)
-			dev->dvb.frontend->ops.sleep(dev->dvb.frontend);
-		if (dev->dvb.frontend->ops.tuner_ops.sleep)
-			dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend);
+		if (fe0->dvb.frontend->ops.init)
+			fe0->dvb.frontend->ops.init(fe0->dvb.frontend);
+		if (fe0->dvb.frontend->ops.sleep)
+			fe0->dvb.frontend->ops.sleep(fe0->dvb.frontend);
+		if (fe0->dvb.frontend->ops.tuner_ops.sleep)
+			fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend);
 	}
 	return ret;
 
 dettach_frontend:
-	if (dev->dvb.frontend)
-		dvb_frontend_detach(dev->dvb.frontend);
-	dev->dvb.frontend = NULL;
+	if (fe0->dvb.frontend)
+		dvb_frontend_detach(fe0->dvb.frontend);
+	fe0->dvb.frontend = NULL;
 
 	return -1;
 }
 
 static int dvb_fini(struct saa7134_dev *dev)
 {
+	struct videobuf_dvb_frontend *fe0;
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
+
 	/* FIXME: I suspect that this code is bogus, since the entry for
 	   Pinnacle 300I DVB-T PAL already defines the proper init to allow
 	   the detection of mt2032 (TDA9887_PORT2_INACTIVE)
@@ -1416,7 +1446,7 @@
 			u8 data = 0x80;
 			struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1};
 			struct dvb_frontend *fe;
-			fe = dev->dvb.frontend;
+			fe = fe0->dvb.frontend;
 			if (fe->ops.i2c_gate_ctrl) {
 				fe->ops.i2c_gate_ctrl(fe, 1);
 				i2c_transfer(&dev->i2c_adap, &msg, 1);
@@ -1424,8 +1454,8 @@
 			}
 		}
 	}
-	if (dev->dvb.frontend)
-		videobuf_dvb_unregister(&dev->dvb);
+	if (fe0->dvb.frontend)
+		videobuf_dvb_unregister_bus(&dev->frontends);
 	return 0;
 }
 
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 491ab1f..24096d6 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -581,7 +581,7 @@
 
 #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
 	/* SAA7134_MPEG_DVB only */
-	struct videobuf_dvb        dvb;
+	struct videobuf_dvb_frontends frontends;
 	int (*original_demod_sleep)(struct dvb_frontend *fe);
 	int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
 	int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 02fda4e..6debb65 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -25,43 +25,25 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
 #include <linux/types.h>
-#include <linux/i2c.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <linux/ioctl.h>
 #include <asm/uaccess.h>
-
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
 #include <linux/videodev.h>
 #include <linux/video_encoder.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
 MODULE_AUTHOR("Dave Perks");
 MODULE_LICENSE("GPL");
 
 
-#define I2C_NAME(s) (s)->name
-
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 /* ----------------------------------------------------------------------- */
 
 struct saa7185 {
@@ -75,32 +57,24 @@
 	int sat;
 };
 
-#define   I2C_SAA7185        0x88
-
 /* ----------------------------------------------------------------------- */
 
-static inline int
-saa7185_read (struct i2c_client *client)
+static inline int saa7185_read(struct i2c_client *client)
 {
 	return i2c_smbus_read_byte(client);
 }
 
-static int
-saa7185_write (struct i2c_client *client,
-	       u8                 reg,
-	       u8                 value)
+static int saa7185_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct saa7185 *encoder = i2c_get_clientdata(client);
 
-	dprintk(1, KERN_DEBUG "SAA7185: %02x set to %02x\n", reg, value);
+	v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value);
 	encoder->reg[reg] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static int
-saa7185_write_block (struct i2c_client *client,
-		     const u8          *data,
-		     unsigned int       len)
+static int saa7185_write_block(struct i2c_client *client,
+		const u8 *data, unsigned int len)
 {
 	int ret = -1;
 	u8 reg;
@@ -121,18 +95,17 @@
 				    encoder->reg[reg++] = data[1];
 				len -= 2;
 				data += 2;
-			} while (len >= 2 && data[0] == reg &&
-				 block_len < 32);
-			if ((ret = i2c_master_send(client, block_data,
-						   block_len)) < 0)
+			} while (len >= 2 && data[0] == reg && block_len < 32);
+			ret = i2c_master_send(client, block_data, block_len);
+			if (ret < 0)
 				break;
 		}
 	} else {
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			if ((ret = saa7185_write(client, reg,
-						 *data++)) < 0)
+			ret = saa7185_write(client, reg, *data++);
+			if (ret < 0)
 				break;
 			len -= 2;
 		}
@@ -240,15 +213,11 @@
 	0x66, 0x21,		/* FSC3 */
 };
 
-static int
-saa7185_command (struct i2c_client *client,
-		 unsigned int       cmd,
-		 void              *arg)
+static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	struct saa7185 *encoder = i2c_get_clientdata(client);
 
 	switch (cmd) {
-
 	case 0:
 		saa7185_write_block(client, init_common,
 				    sizeof(init_common));
@@ -264,7 +233,6 @@
 					    sizeof(init_pal));
 			break;
 		}
-
 		break;
 
 	case ENCODER_GET_CAPABILITIES:
@@ -276,8 +244,8 @@
 		    VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR;
 		cap->inputs = 1;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case ENCODER_SET_NORM:
 	{
@@ -286,7 +254,6 @@
 		//saa7185_write_block(client, init_common, sizeof(init_common));
 
 		switch (*iarg) {
-
 		case VIDEO_MODE_NTSC:
 			saa7185_write_block(client, init_ntsc,
 					    sizeof(init_ntsc));
@@ -300,11 +267,10 @@
 		case VIDEO_MODE_SECAM:
 		default:
 			return -EINVAL;
-
 		}
 		encoder->norm = *iarg;
-	}
 		break;
+	}
 
 	case ENCODER_SET_INPUT:
 	{
@@ -314,7 +280,6 @@
 		 *iarg = 1: input is from ZR36060 */
 
 		switch (*iarg) {
-
 		case 0:
 			/* Switch RTCE to 1 */
 			saa7185_write(client, 0x61,
@@ -332,21 +297,19 @@
 
 		default:
 			return -EINVAL;
-
 		}
-	}
 		break;
+	}
 
 	case ENCODER_SET_OUTPUT:
 	{
 		int *iarg = arg;
 
 		/* not much choice of outputs */
-		if (*iarg != 0) {
+		if (*iarg != 0)
 			return -EINVAL;
-		}
-	}
 		break;
+	}
 
 	case ENCODER_ENABLE_OUTPUT:
 	{
@@ -356,8 +319,8 @@
 		saa7185_write(client, 0x61,
 			      (encoder->reg[0x61] & 0xbf) |
 			      (encoder->enable ? 0x00 : 0x40));
-	}
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -368,138 +331,65 @@
 
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver i2c_driver_saa7185;
-
-static int
-saa7185_detect_client (struct i2c_adapter *adapter,
-		       int                 address,
-		       int                 kind)
+static int saa7185_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	int i;
-	struct i2c_client *client;
 	struct saa7185 *encoder;
 
-	dprintk(1,
-		KERN_INFO
-		"saa7185.c: detecting saa7185 client on address 0x%x\n",
-		address << 1);
-
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return 0;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &i2c_driver_saa7185;
-	strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
 	encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
-	if (encoder == NULL) {
-		kfree(client);
+	if (encoder == NULL)
 		return -ENOMEM;
-	}
 	encoder->norm = VIDEO_MODE_NTSC;
 	encoder->enable = 1;
 	i2c_set_clientdata(client, encoder);
 
-	i = i2c_attach_client(client);
-	if (i) {
-		kfree(client);
-		kfree(encoder);
-		return i;
-	}
-
 	i = saa7185_write_block(client, init_common, sizeof(init_common));
-	if (i >= 0) {
-		i = saa7185_write_block(client, init_ntsc,
-					sizeof(init_ntsc));
-	}
-	if (i < 0) {
-		dprintk(1, KERN_ERR "%s_attach: init error %d\n",
-			I2C_NAME(client), i);
-	} else {
-		dprintk(1,
-			KERN_INFO
-			"%s_attach: chip version %d at address 0x%x\n",
-			I2C_NAME(client), saa7185_read(client) >> 5,
-			client->addr << 1);
-	}
-
+	if (i >= 0)
+		i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc));
+	if (i < 0)
+		v4l_dbg(1, debug, client, "init error %d\n", i);
+	else
+		v4l_dbg(1, debug, client, "revision 0x%x\n",
+				saa7185_read(client) >> 5);
 	return 0;
 }
 
-static int
-saa7185_attach_adapter (struct i2c_adapter *adapter)
-{
-	dprintk(1,
-		KERN_INFO
-		"saa7185.c: starting probe for adapter %s (0x%x)\n",
-		I2C_NAME(adapter), adapter->id);
-	return i2c_probe(adapter, &addr_data, &saa7185_detect_client);
-}
-
-static int
-saa7185_detach_client (struct i2c_client *client)
+static int saa7185_remove(struct i2c_client *client)
 {
 	struct saa7185 *encoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
 
 	saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40);	/* SW: output off is active */
 	//saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
 
 	kfree(encoder);
-	kfree(client);
-
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_saa7185 = {
-	.driver = {
-		.name = "saa7185",	/* name */
-	},
-
-	.id = I2C_DRIVERID_SAA7185B,
-
-	.attach_adapter = saa7185_attach_adapter,
-	.detach_client = saa7185_detach_client,
-	.command = saa7185_command,
+static const struct i2c_device_id saa7185_id[] = {
+	{ "saa7185", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, saa7185_id);
 
-static int __init
-saa7185_init (void)
-{
-	return i2c_add_driver(&i2c_driver_saa7185);
-}
-
-static void __exit
-saa7185_exit (void)
-{
-	i2c_del_driver(&i2c_driver_saa7185);
-}
-
-module_init(saa7185_init);
-module_exit(saa7185_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "saa7185",
+	.driverid = I2C_DRIVERID_SAA7185B,
+	.command = saa7185_command,
+	.probe = saa7185_probe,
+	.remove = saa7185_remove,
+	.id_table = saa7185_id,
+};
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 7683809..2407607 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -40,39 +40,39 @@
 
 /* register offsets for sh7722 / sh7723 */
 
-#define CAPSR  0x00
-#define CAPCR  0x04
-#define CAMCR  0x08
-#define CMCYR  0x0c
-#define CAMOR  0x10
-#define CAPWR  0x14
-#define CAIFR  0x18
-#define CSTCR  0x20 /* not on sh7723 */
-#define CSECR  0x24 /* not on sh7723 */
-#define CRCNTR 0x28
-#define CRCMPR 0x2c
-#define CFLCR  0x30
-#define CFSZR  0x34
-#define CDWDR  0x38
-#define CDAYR  0x3c
-#define CDACR  0x40
-#define CDBYR  0x44
-#define CDBCR  0x48
-#define CBDSR  0x4c
-#define CFWCR  0x5c
-#define CLFCR  0x60
-#define CDOCR  0x64
-#define CDDCR  0x68
-#define CDDAR  0x6c
-#define CEIER  0x70
-#define CETCR  0x74
-#define CSTSR  0x7c
-#define CSRTR  0x80
-#define CDSSR  0x84
-#define CDAYR2 0x90
-#define CDACR2 0x94
-#define CDBYR2 0x98
-#define CDBCR2 0x9c
+#define CAPSR  0x00 /* Capture start register */
+#define CAPCR  0x04 /* Capture control register */
+#define CAMCR  0x08 /* Capture interface control register */
+#define CMCYR  0x0c /* Capture interface cycle  register */
+#define CAMOR  0x10 /* Capture interface offset register */
+#define CAPWR  0x14 /* Capture interface width register */
+#define CAIFR  0x18 /* Capture interface input format register */
+#define CSTCR  0x20 /* Camera strobe control register (<= sh7722) */
+#define CSECR  0x24 /* Camera strobe emission count register (<= sh7722) */
+#define CRCNTR 0x28 /* CEU register control register */
+#define CRCMPR 0x2c /* CEU register forcible control register */
+#define CFLCR  0x30 /* Capture filter control register */
+#define CFSZR  0x34 /* Capture filter size clip register */
+#define CDWDR  0x38 /* Capture destination width register */
+#define CDAYR  0x3c /* Capture data address Y register */
+#define CDACR  0x40 /* Capture data address C register */
+#define CDBYR  0x44 /* Capture data bottom-field address Y register */
+#define CDBCR  0x48 /* Capture data bottom-field address C register */
+#define CBDSR  0x4c /* Capture bundle destination size register */
+#define CFWCR  0x5c /* Firewall operation control register */
+#define CLFCR  0x60 /* Capture low-pass filter control register */
+#define CDOCR  0x64 /* Capture data output control register */
+#define CDDCR  0x68 /* Capture data complexity level register */
+#define CDDAR  0x6c /* Capture data complexity level address register */
+#define CEIER  0x70 /* Capture event interrupt enable register */
+#define CETCR  0x74 /* Capture event flag clear register */
+#define CSTSR  0x7c /* Capture status register */
+#define CSRTR  0x80 /* Capture software reset register */
+#define CDSSR  0x84 /* Capture data size register */
+#define CDAYR2 0x90 /* Capture data address Y register 2 */
+#define CDACR2 0x94 /* Capture data address C register 2 */
+#define CDBYR2 0x98 /* Capture data bottom-field address Y register 2 */
+#define CDBCR2 0x9c /* Capture data bottom-field address C register 2 */
 
 static DEFINE_MUTEX(camera_lock);
 
@@ -165,6 +165,7 @@
 	ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10);
 
 	if (pcdev->active) {
+		pcdev->active->state = VIDEOBUF_ACTIVE;
 		ceu_write(pcdev, CDAYR, videobuf_to_dma_contig(pcdev->active));
 		ceu_write(pcdev, CAPSR, 0x1); /* start capture */
 	}
@@ -236,7 +237,7 @@
 	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
 		vb, vb->baddr, vb->bsize);
 
-	vb->state = VIDEOBUF_ACTIVE;
+	vb->state = VIDEOBUF_QUEUED;
 	spin_lock_irqsave(&pcdev->lock, flags);
 	list_add_tail(&vb->queue, &pcdev->capture);
 
@@ -323,12 +324,24 @@
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+	unsigned long flags;
 
 	BUG_ON(icd != pcdev->icd);
 
 	/* disable capture, disable interrupts */
 	ceu_write(pcdev, CEIER, 0);
 	ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
+
+	/* make sure active buffer is canceled */
+	spin_lock_irqsave(&pcdev->lock, flags);
+	if (pcdev->active) {
+		list_del(&pcdev->active->queue);
+		pcdev->active->state = VIDEOBUF_ERROR;
+		wake_up_all(&pcdev->active->done);
+		pcdev->active = NULL;
+	}
+	spin_unlock_irqrestore(&pcdev->lock, flags);
+
 	icd->ops->release(icd);
 
 	dev_info(&icd->dev,
@@ -391,7 +404,20 @@
 	ceu_write(pcdev, CFLCR, 0); /* data fetch mode - no scaling */
 	ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width);
 	ceu_write(pcdev, CLFCR, 0); /* data fetch mode - no lowpass filter */
-	ceu_write(pcdev, CDOCR, 0x00000016);
+
+	/* A few words about byte order (observed in Big Endian mode)
+	 *
+	 * In data fetch mode bytes are received in chunks of 8 bytes.
+	 * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first)
+	 *
+	 * The data is however by default written to memory in reverse order:
+	 * D7, D6, D5, D4, D3, D2, D1, D0 (D7 written to lowest byte)
+	 *
+	 * The lowest three bits of CDOCR allows us to do swapping,
+	 * using 7 we swap the data bytes to match the incoming order:
+	 * D0, D1, D2, D3, D4, D5, D6, D7
+	 */
+	ceu_write(pcdev, CDOCR, 0x00000017);
 
 	ceu_write(pcdev, CDWDR, cdwdr_width);
 	ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 1adc257..bb7a9d4 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -18,15 +18,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/soc_camera.h>
-
-struct soc_camera_platform_info {
-	int iface;
-	char *format_name;
-	unsigned long format_depth;
-	struct v4l2_pix_format format;
-	unsigned long bus_param;
-	int (*set_capture)(struct soc_camera_platform_info *info, int enable);
-};
+#include <media/soc_camera_platform.h>
 
 struct soc_camera_platform_priv {
 	struct soc_camera_platform_info *info;
@@ -44,11 +36,21 @@
 
 static int soc_camera_platform_init(struct soc_camera_device *icd)
 {
+	struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+
+	if (p->power)
+		p->power(1);
+
 	return 0;
 }
 
 static int soc_camera_platform_release(struct soc_camera_device *icd)
 {
+	struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+
+	if (p->power)
+		p->power(0);
+
 	return 0;
 }
 
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index db69bc5..edaea49 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/kref.h>
 
 #include <linux/usb.h>
 #include <linux/mm.h>
@@ -560,7 +559,7 @@
 
 		urb = dev->isobufs[i].urb;
 		if (urb) {
-			if (atomic_read(&dev->urbs_used))
+			if (atomic_read(&dev->urbs_used) && is_present(dev))
 				usb_kill_urb(urb);
 			usb_free_urb(urb);
 		}
@@ -689,18 +688,14 @@
 {
 	struct stk_camera *dev = fp->private_data;
 
-	if (dev->owner != fp) {
-		usb_autopm_put_interface(dev->interface);
-		return 0;
+	if (dev->owner == fp) {
+		stk_stop_stream(dev);
+		stk_free_buffers(dev);
+		dev->owner = NULL;
 	}
 
-	stk_stop_stream(dev);
-
-	stk_free_buffers(dev);
-
-	dev->owner = NULL;
-
-	usb_autopm_put_interface(dev->interface);
+	if(is_present(dev))
+		usb_autopm_put_interface(dev->interface);
 
 	return 0;
 }
@@ -714,9 +709,6 @@
 	struct stk_sio_buffer *sbuf;
 	struct stk_camera *dev = fp->private_data;
 
-	if (dev == NULL)
-		return -EIO;
-
 	if (!is_present(dev))
 		return -EIO;
 	if (dev->owner && dev->owner != fp)
@@ -773,9 +765,6 @@
 {
 	struct stk_camera *dev = fp->private_data;
 
-	if (dev == NULL)
-		return -ENODEV;
-
 	poll_wait(fp, &dev->wait_frame, wait);
 
 	if (!is_present(dev))
@@ -1436,7 +1425,7 @@
 	wake_up_interruptible(&dev->wait_frame);
 	stk_remove_sysfs_files(&dev->vdev);
 
-	STK_INFO("Syntek USB2.0 Camera release resources"
+	STK_INFO("Syntek USB2.0 Camera release resources "
 		"video device /dev/video%d\n", dev->vdev.minor);
 
 	video_unregister_device(&dev->vdev);
diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h
index 084a85b..9f67366 100644
--- a/drivers/media/video/stk-webcam.h
+++ b/drivers/media/video/stk-webcam.h
@@ -122,7 +122,6 @@
 
 #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev)
 
-void stk_camera_delete(struct kref *);
 int stk_camera_write_reg(struct stk_camera *, u16, u8);
 int stk_camera_read_reg(struct stk_camera *, u16, int *);
 
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index bcc32fa..3b0b84c 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -242,7 +242,7 @@
 	{ TUNER_ABSENT,        		"TCL M2523_3DBH_E"},
 	{ TUNER_ABSENT,        		"TCL M2523_3DIH_E"},
 	{ TUNER_ABSENT,        		"TCL MFPE05_2_U"},
-	{ TUNER_PHILIPS_FMD1216ME_MK3,	"Philips FMD1216MEX"},
+	{ TUNER_PHILIPS_FMD1216MEX_MK3,	"Philips FMD1216MEX"},
 	{ TUNER_ABSENT,        		"Philips FRH2036B"},
 	{ TUNER_ABSENT,        		"Panasonic ENGF75_01GF"},
 	{ TUNER_ABSENT,        		"MaxLinear MXL5005"},
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
index b56cffc..917277d 100644
--- a/drivers/media/video/videobuf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -126,7 +126,6 @@
 	mutex_lock(&dvb->lock);
 	dvb->nfeeds--;
 	if (0 == dvb->nfeeds  &&  NULL != dvb->thread) {
-		// FIXME: cx8802_cancel_buffers(dev);
 		err = kthread_stop(dvb->thread);
 		dvb->thread = NULL;
 	}
@@ -134,30 +133,38 @@
 	return err;
 }
 
-/* ------------------------------------------------------------------ */
-
-int videobuf_dvb_register(struct videobuf_dvb *dvb,
+static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
 			  struct module *module,
 			  void *adapter_priv,
 			  struct device *device,
-			  short *adapter_nr)
+			  char *adapter_name,
+			  short *adapter_nr,
+			  int mfe_shared)
 {
 	int result;
 
-	mutex_init(&dvb->lock);
+	mutex_init(&fe->lock);
 
 	/* register adapter */
-	result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device,
-				      adapter_nr);
+	result = dvb_register_adapter(&fe->adapter, adapter_name, module,
+		device, adapter_nr);
 	if (result < 0) {
 		printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
-		       dvb->name, result);
-		goto fail_adapter;
+		       adapter_name, result);
 	}
-	dvb->adapter.priv = adapter_priv;
+	fe->adapter.priv = adapter_priv;
+	fe->adapter.mfe_shared = mfe_shared;
+
+	return result;
+}
+
+static int videobuf_dvb_register_frontend(struct dvb_adapter *adapter,
+	struct videobuf_dvb *dvb)
+{
+	int result;
 
 	/* register frontend */
-	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+	result = dvb_register_frontend(adapter, dvb->frontend);
 	if (result < 0) {
 		printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
 		       dvb->name, result);
@@ -183,7 +190,8 @@
 	dvb->dmxdev.filternum    = 256;
 	dvb->dmxdev.demux        = &dvb->demux.dmx;
 	dvb->dmxdev.capabilities = 0;
-	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+	result = dvb_dmxdev_init(&dvb->dmxdev, adapter);
+
 	if (result < 0) {
 		printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
 		       dvb->name, result);
@@ -214,7 +222,11 @@
 	}
 
 	/* register network adapter */
-	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+	dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
+	if (dvb->net.dvbdev == NULL) {
+		result = -ENOMEM;
+		goto fail_fe_conn;
+	}
 	return 0;
 
 fail_fe_conn:
@@ -229,30 +241,151 @@
 	dvb_unregister_frontend(dvb->frontend);
 fail_frontend:
 	dvb_frontend_detach(dvb->frontend);
-	dvb_unregister_adapter(&dvb->adapter);
-fail_adapter:
+	dvb->frontend = NULL;
+
 	return result;
 }
 
-void videobuf_dvb_unregister(struct videobuf_dvb *dvb)
-{
-	dvb_net_release(&dvb->net);
-	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-	dvb_dmxdev_release(&dvb->dmxdev);
-	dvb_dmx_release(&dvb->demux);
-	dvb_unregister_frontend(dvb->frontend);
-	dvb_frontend_detach(dvb->frontend);
-	dvb_unregister_adapter(&dvb->adapter);
-}
-
-EXPORT_SYMBOL(videobuf_dvb_register);
-EXPORT_SYMBOL(videobuf_dvb_unregister);
-
 /* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
+/* Register a single adapter and one or more frontends */
+int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
+			  struct module *module,
+			  void *adapter_priv,
+			  struct device *device,
+			  short *adapter_nr,
+			  int mfe_shared)
+{
+	struct list_head *list, *q;
+	struct videobuf_dvb_frontend *fe;
+	int res;
+
+	fe = videobuf_dvb_get_frontend(f, 1);
+	if (!fe) {
+		printk(KERN_WARNING "Unable to register the adapter which has no frontends\n");
+		return -EINVAL;
+	}
+
+	/* Bring up the adapter */
+	res = videobuf_dvb_register_adapter(f, module, adapter_priv, device,
+		fe->dvb.name, adapter_nr, mfe_shared);
+	if (res < 0) {
+		printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
+		return res;
+	}
+
+	/* Attach all of the frontends to the adapter */
+	mutex_lock(&f->lock);
+	list_for_each_safe(list, q, &f->felist) {
+		fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+		res = videobuf_dvb_register_frontend(&f->adapter, &fe->dvb);
+		if (res < 0) {
+			printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n",
+				fe->dvb.name, res);
+			goto err;
+		}
+	}
+	mutex_unlock(&f->lock);
+	return 0;
+
+err:
+	mutex_unlock(&f->lock);
+	videobuf_dvb_unregister_bus(f);
+	return res;
+}
+EXPORT_SYMBOL(videobuf_dvb_register_bus);
+
+void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f)
+{
+	struct list_head *list, *q;
+	struct videobuf_dvb_frontend *fe;
+
+	mutex_lock(&f->lock);
+	list_for_each_safe(list, q, &f->felist) {
+		fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+		if (fe->dvb.net.dvbdev) {
+			dvb_net_release(&fe->dvb.net);
+			fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+				&fe->dvb.fe_mem);
+			fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+				&fe->dvb.fe_hw);
+			dvb_dmxdev_release(&fe->dvb.dmxdev);
+			dvb_dmx_release(&fe->dvb.demux);
+			dvb_unregister_frontend(fe->dvb.frontend);
+		}
+		if (fe->dvb.frontend)
+			/* always allocated, may have been reset */
+			dvb_frontend_detach(fe->dvb.frontend);
+		list_del(list);
+		kfree(fe);
+	}
+	mutex_unlock(&f->lock);
+
+	dvb_unregister_adapter(&f->adapter);
+}
+EXPORT_SYMBOL(videobuf_dvb_unregister_bus);
+
+struct videobuf_dvb_frontend *videobuf_dvb_get_frontend(
+	struct videobuf_dvb_frontends *f, int id)
+{
+	struct list_head *list, *q;
+	struct videobuf_dvb_frontend *fe, *ret = NULL;
+
+	mutex_lock(&f->lock);
+
+	list_for_each_safe(list, q, &f->felist) {
+		fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+		if (fe->id == id) {
+			ret = fe;
+			break;
+		}
+	}
+
+	mutex_unlock(&f->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(videobuf_dvb_get_frontend);
+
+int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f,
+	struct dvb_frontend *p)
+{
+	struct list_head *list, *q;
+	struct videobuf_dvb_frontend *fe = NULL;
+	int ret = 0;
+
+	mutex_lock(&f->lock);
+
+	list_for_each_safe(list, q, &f->felist) {
+		fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+		if (fe->dvb.frontend == p) {
+			ret = fe->id;
+			break;
+		}
+	}
+
+	mutex_unlock(&f->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(videobuf_dvb_find_frontend);
+
+struct videobuf_dvb_frontend *videobuf_dvb_alloc_frontend(
+	struct videobuf_dvb_frontends *f, int id)
+{
+	struct videobuf_dvb_frontend *fe;
+
+	fe = kzalloc(sizeof(struct videobuf_dvb_frontend), GFP_KERNEL);
+	if (fe == NULL)
+		goto fail_alloc;
+
+	fe->id = id;
+	mutex_init(&fe->dvb.lock);
+
+	mutex_lock(&f->lock);
+	list_add_tail(&fe->felist, &f->felist);
+	mutex_unlock(&f->lock);
+
+fail_alloc:
+	return fe;
+}
+EXPORT_SYMBOL(videobuf_dvb_alloc_frontend);
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 65c8af1..7d7e51d 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -128,12 +128,56 @@
 	int   depth;
 };
 
-static struct vivi_fmt format = {
-	.name     = "4:2:2, packed, YUYV",
-	.fourcc   = V4L2_PIX_FMT_YUYV,
-	.depth    = 16,
+static struct vivi_fmt formats[] = {
+	{
+		.name     = "4:2:2, packed, YUYV",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.depth    = 16,
+	},
+	{
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.depth    = 16,
+	},
+	{
+		.name     = "RGB565 (LE)",
+		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+		.depth    = 16,
+	},
+	{
+		.name     = "RGB565 (BE)",
+		.fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+		.depth    = 16,
+	},
+	{
+		.name     = "RGB555 (LE)",
+		.fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+		.depth    = 16,
+	},
+	{
+		.name     = "RGB555 (BE)",
+		.fourcc   = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+		.depth    = 16,
+	},
 };
 
+static struct vivi_fmt *get_format(struct v4l2_format *f)
+{
+	struct vivi_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ARRAY_SIZE(formats); k++) {
+		fmt = &formats[k];
+		if (fmt->fourcc == f->fmt.pix.pixelformat)
+			break;
+	}
+
+	if (k == ARRAY_SIZE(formats))
+		return NULL;
+
+	return &formats[k];
+}
+
 struct sg_to_addr {
 	int pos;
 	struct scatterlist *sg;
@@ -190,6 +234,7 @@
 	struct videobuf_queue      vb_vidq;
 
 	enum v4l2_buf_type         type;
+	unsigned char              bars[8][3];
 };
 
 /* ------------------------------------------------------------------
@@ -234,13 +279,107 @@
 #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
 #define TSTAMP_MIN_X 64
 
-static void gen_line(char *basep, int inipos, int wmax,
+static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
+{
+	unsigned char r_y, g_u, b_v;
+	unsigned char *p;
+	int color;
+
+	r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
+	g_u = fh->bars[colorpos][1]; /* G or precalculated U */
+	b_v = fh->bars[colorpos][2]; /* B or precalculated V */
+
+	for (color = 0; color < 4; color++) {
+		p = buf + color;
+
+		switch (fh->fmt->fourcc) {
+		case V4L2_PIX_FMT_YUYV:
+			switch (color) {
+			case 0:
+			case 2:
+				*p = r_y;
+				break;
+			case 1:
+				*p = g_u;
+				break;
+			case 3:
+				*p = b_v;
+				break;
+			}
+			break;
+		case V4L2_PIX_FMT_UYVY:
+			switch (color) {
+			case 1:
+			case 3:
+				*p = r_y;
+				break;
+			case 0:
+				*p = g_u;
+				break;
+			case 2:
+				*p = b_v;
+				break;
+			}
+			break;
+		case V4L2_PIX_FMT_RGB565:
+			switch (color) {
+			case 0:
+			case 2:
+				*p = (g_u << 5) | b_v;
+				break;
+			case 1:
+			case 3:
+				*p = (r_y << 3) | (g_u >> 3);
+				break;
+			}
+			break;
+		case V4L2_PIX_FMT_RGB565X:
+			switch (color) {
+			case 0:
+			case 2:
+				*p = (r_y << 3) | (g_u >> 3);
+				break;
+			case 1:
+			case 3:
+				*p = (g_u << 5) | b_v;
+				break;
+			}
+			break;
+		case V4L2_PIX_FMT_RGB555:
+			switch (color) {
+			case 0:
+			case 2:
+				*p = (g_u << 5) | b_v;
+				break;
+			case 1:
+			case 3:
+				*p = (r_y << 2) | (g_u >> 3);
+				break;
+			}
+			break;
+		case V4L2_PIX_FMT_RGB555X:
+			switch (color) {
+			case 0:
+			case 2:
+				*p = (r_y << 2) | (g_u >> 3);
+				break;
+			case 1:
+			case 3:
+				*p = (g_u << 5) | b_v;
+				break;
+			}
+			break;
+		}
+	}
+}
+
+static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
 		int hmax, int line, int count, char *timestr)
 {
-	int  w, i, j, y;
+	int  w, i, j;
 	int pos = inipos;
-	char *p, *s;
-	u8   chr, r, g, b, color;
+	char *s;
+	u8 chr;
 
 	/* We will just duplicate the second pixel at the packet */
 	wmax /= 2;
@@ -248,27 +387,9 @@
 	/* Generate a standard color bar pattern */
 	for (w = 0; w < wmax; w++) {
 		int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
-		r = bars[colorpos][0];
-		g = bars[colorpos][1];
-		b = bars[colorpos][2];
 
-		for (color = 0; color < 4; color++) {
-			p = basep + pos;
-
-			switch (color) {
-			case 0:
-			case 2:
-				*p = TO_Y(r, g, b);	/* Luma */
-				break;
-			case 1:
-				*p = TO_U(r, g, b);	/* Cb */
-				break;
-			case 3:
-				*p = TO_V(r, g, b);	/* Cr */
-				break;
-			}
-			pos++;
-		}
+		gen_twopix(fh, basep + pos, colorpos);
+		pos += 4; /* only 16 bpp supported for now */
 	}
 
 	/* Checks if it is possible to show timestamp */
@@ -283,38 +404,12 @@
 		for (s = timestr; *s; s++) {
 			chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
 			for (i = 0; i < 7; i++) {
-				if (chr & 1 << (7 - i)) {
-					/* Font color*/
-					r = 0;
-					g = 198;
-					b = 0;
-				} else {
-					/* Background color */
-					r = bars[BLACK][0];
-					g = bars[BLACK][1];
-					b = bars[BLACK][2];
-				}
-
 				pos = inipos + j * 2;
-				for (color = 0; color < 4; color++) {
-					p = basep + pos;
-
-					y = TO_Y(r, g, b);
-
-					switch (color) {
-					case 0:
-					case 2:
-						*p = TO_Y(r, g, b); /* Luma */
-						break;
-					case 1:
-						*p = TO_U(r, g, b); /* Cb */
-						break;
-					case 3:
-						*p = TO_V(r, g, b); /* Cr */
-						break;
-					}
-					pos++;
-				}
+				/* Draw white font on black background */
+				if (chr & 1 << (7 - i))
+					gen_twopix(fh, basep + pos, WHITE);
+				else
+					gen_twopix(fh, basep + pos, BLACK);
 				j++;
 			}
 		}
@@ -324,8 +419,9 @@
 	return;
 }
 
-static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
+static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
 {
+	struct vivi_dev *dev = fh->dev;
 	int h , pos = 0;
 	int hmax  = buf->vb.height;
 	int wmax  = buf->vb.width;
@@ -341,7 +437,7 @@
 		return;
 
 	for (h = 0; h < hmax; h++) {
-		gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count,
+		gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
 			 dev->timestr);
 		memcpy(vbuf + pos, tmpbuf, wmax * 2);
 		pos += wmax*2;
@@ -410,7 +506,7 @@
 	do_gettimeofday(&buf->vb.ts);
 
 	/* Fill buffer */
-	vivi_fillbuff(dev, buf);
+	vivi_fillbuff(fh, buf);
 	dprintk(dev, 1, "filled buffer %p\n", buf);
 
 	wake_up(&buf->vb.done);
@@ -636,11 +732,15 @@
 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *f)
 {
-	if (f->index > 0)
+	struct vivi_fmt *fmt;
+
+	if (f->index >= ARRAY_SIZE(formats))
 		return -EINVAL;
 
-	strlcpy(f->description, format.name, sizeof(f->description));
-	f->pixelformat = format.fourcc;
+	fmt = &formats[f->index];
+
+	strlcpy(f->description, fmt->name, sizeof(f->description));
+	f->pixelformat = fmt->fourcc;
 	return 0;
 }
 
@@ -670,13 +770,12 @@
 	enum v4l2_field field;
 	unsigned int maxw, maxh;
 
-	if (format.fourcc != f->fmt.pix.pixelformat) {
-		dprintk(dev, 1, "Fourcc format (0x%08x) invalid. "
-			"Driver accepts only 0x%08x\n",
-			f->fmt.pix.pixelformat, format.fourcc);
+	fmt = get_format(f);
+	if (!fmt) {
+		dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
+			f->fmt.pix.pixelformat);
 		return -EINVAL;
 	}
-	fmt = &format;
 
 	field = f->fmt.pix.field;
 
@@ -714,6 +813,8 @@
 {
 	struct vivi_fh  *fh = priv;
 	struct videobuf_queue *q = &fh->vb_vidq;
+	unsigned char r, g, b;
+	int k, is_yuv;
 
 	int ret = vidioc_try_fmt_vid_cap(file, fh, f);
 	if (ret < 0)
@@ -727,12 +828,49 @@
 		goto out;
 	}
 
-	fh->fmt           = &format;
+	fh->fmt           = get_format(f);
 	fh->width         = f->fmt.pix.width;
 	fh->height        = f->fmt.pix.height;
 	fh->vb_vidq.field = f->fmt.pix.field;
 	fh->type          = f->type;
 
+	/* precalculate color bar values to speed up rendering */
+	for (k = 0; k < 8; k++) {
+		r = bars[k][0];
+		g = bars[k][1];
+		b = bars[k][2];
+		is_yuv = 0;
+
+		switch (fh->fmt->fourcc) {
+		case V4L2_PIX_FMT_YUYV:
+		case V4L2_PIX_FMT_UYVY:
+			is_yuv = 1;
+			break;
+		case V4L2_PIX_FMT_RGB565:
+		case V4L2_PIX_FMT_RGB565X:
+			r >>= 3;
+			g >>= 2;
+			b >>= 3;
+			break;
+		case V4L2_PIX_FMT_RGB555:
+		case V4L2_PIX_FMT_RGB555X:
+			r >>= 3;
+			g >>= 3;
+			b >>= 3;
+			break;
+		}
+
+		if (is_yuv) {
+			fh->bars[k][0] = TO_Y(r, g, b);	/* Luma */
+			fh->bars[k][1] = TO_U(r, g, b);	/* Cb */
+			fh->bars[k][2] = TO_V(r, g, b);	/* Cr */
+		} else {
+			fh->bars[k][0] = r;
+			fh->bars[k][1] = g;
+			fh->bars[k][2] = b;
+		}
+	}
+
 	ret = 0;
 out:
 	mutex_unlock(&q->vb_lock);
@@ -886,8 +1024,6 @@
 	File operations for the device
    ------------------------------------------------------------------*/
 
-#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8)
-
 static int vivi_open(struct inode *inode, struct file *file)
 {
 	int minor = iminor(inode);
@@ -936,7 +1072,7 @@
 	fh->dev      = dev;
 
 	fh->type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	fh->fmt      = &format;
+	fh->fmt      = &formats[0];
 	fh->width    = 640;
 	fh->height   = 480;
 
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 45be9ec..67aa0db 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -22,32 +22,21 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
 #include <asm/uaccess.h>
-
 #include <linux/i2c.h>
-
-#define I2C_NAME(x) (x)->name
-
-#include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev.h>
 #include <linux/video_decoder.h>
 
-#define I2C_VPX3220        0x86
-#define VPX3220_DEBUG	KERN_DEBUG "vpx3220: "
+MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
+MODULE_AUTHOR("Laurent Pinchart");
+MODULE_LICENSE("GPL");
 
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-#define dprintk(num, format, args...) \
-	do { \
-		if (debug >= num) \
-			printk(format, ##args); \
-	} while (0)
-
 #define VPX_TIMEOUT_COUNT  10
 
 /* ----------------------------------------------------------------------- */
@@ -67,10 +56,8 @@
 static char *inputs[] = { "internal", "composite", "svideo" };
 
 /* ----------------------------------------------------------------------- */
-static inline int
-vpx3220_write (struct i2c_client *client,
-	       u8                 reg,
-	       u8                 value)
+
+static inline int vpx3220_write(struct i2c_client *client, u8 reg, u8 value)
 {
 	struct vpx3220 *decoder = i2c_get_clientdata(client);
 
@@ -78,15 +65,12 @@
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int
-vpx3220_read (struct i2c_client *client,
-	      u8                 reg)
+static inline int vpx3220_read(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int
-vpx3220_fp_status (struct i2c_client *client)
+static int vpx3220_fp_status(struct i2c_client *client)
 {
 	unsigned char status;
 	unsigned int i;
@@ -106,14 +90,11 @@
 	return -1;
 }
 
-static int
-vpx3220_fp_write (struct i2c_client *client,
-		  u8                 fpaddr,
-		  u16                data)
+static int vpx3220_fp_write(struct i2c_client *client, u8 fpaddr, u16 data)
 {
 	/* Write the 16-bit address to the FPWR register */
 	if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
-		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
 		return -1;
 	}
 
@@ -122,22 +103,20 @@
 
 	/* Write the 16-bit data to the FPDAT register */
 	if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
-		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
 		return -1;
 	}
 
 	return 0;
 }
 
-static u16
-vpx3220_fp_read (struct i2c_client *client,
-		 u16                fpaddr)
+static u16 vpx3220_fp_read(struct i2c_client *client, u16 fpaddr)
 {
 	s16 data;
 
 	/* Write the 16-bit address to the FPRD register */
 	if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
-		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
 		return -1;
 	}
 
@@ -147,25 +126,22 @@
 	/* Read the 16-bit data from the FPDAT register */
 	data = i2c_smbus_read_word_data(client, 0x28);
 	if (data == -1) {
-		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
+		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
 		return -1;
 	}
 
 	return swab16(data);
 }
 
-static int
-vpx3220_write_block (struct i2c_client *client,
-		     const u8          *data,
-		     unsigned int       len)
+static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
 {
 	u8 reg;
 	int ret = -1;
 
 	while (len >= 2) {
 		reg = *data++;
-		if ((ret =
-		     vpx3220_write(client, reg, *data++)) < 0)
+		ret = vpx3220_write(client, reg, *data++);
+		if (ret < 0)
 			break;
 		len -= 2;
 	}
@@ -173,10 +149,8 @@
 	return ret;
 }
 
-static int
-vpx3220_write_fp_block (struct i2c_client *client,
-			const u16         *data,
-			unsigned int       len)
+static int vpx3220_write_fp_block(struct i2c_client *client,
+		const u16 *data, unsigned int len)
 {
 	u8 reg;
 	int ret = 0;
@@ -285,25 +259,20 @@
 	0x4b, 0x298,		/* PLL gain */
 };
 
-static void
-vpx3220_dump_i2c (struct i2c_client *client)
+static void vpx3220_dump_i2c(struct i2c_client *client)
 {
 	int len = sizeof(init_common);
 	const unsigned char *data = init_common;
 
 	while (len > 1) {
-		dprintk(1,
-			KERN_DEBUG "vpx3216b i2c reg 0x%02x data 0x%02x\n",
+		v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n",
 			*data, vpx3220_read(client, *data));
 		data += 2;
 		len -= 2;
 	}
 }
 
-static int
-vpx3220_command (struct i2c_client *client,
-		 unsigned int       cmd,
-		 void              *arg)
+static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
 	struct vpx3220 *decoder = i2c_get_clientdata(client);
 
@@ -315,7 +284,6 @@
 		vpx3220_write_fp_block(client, init_fp,
 				       sizeof(init_fp) >> 1);
 		switch (decoder->norm) {
-
 		case VIDEO_MODE_NTSC:
 			vpx3220_write_fp_block(client, init_ntsc,
 					       sizeof(init_ntsc) >> 1);
@@ -334,21 +302,20 @@
 					       sizeof(init_pal) >> 1);
 			break;
 		}
-	}
 		break;
+	}
 
 	case DECODER_DUMP:
 	{
 		vpx3220_dump_i2c(client);
-	}
 		break;
+	}
 
 	case DECODER_GET_CAPABILITIES:
 	{
 		struct video_decoder_capability *cap = arg;
 
-		dprintk(1, KERN_DEBUG "%s: DECODER_GET_CAPABILITIES\n",
-			I2C_NAME(client));
+		v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n");
 
 		cap->flags = VIDEO_DECODER_PAL |
 			     VIDEO_DECODER_NTSC |
@@ -357,20 +324,18 @@
 			     VIDEO_DECODER_CCIR;
 		cap->inputs = 3;
 		cap->outputs = 1;
-	}
 		break;
+	}
 
 	case DECODER_GET_STATUS:
 	{
 		int res = 0, status;
 
-		dprintk(1, KERN_INFO "%s: DECODER_GET_STATUS\n",
-			I2C_NAME(client));
+		v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n");
 
 		status = vpx3220_fp_read(client, 0x0f3);
 
-		dprintk(1, KERN_INFO "%s: status: 0x%04x\n", I2C_NAME(client),
-			status);
+		v4l_dbg(1, debug, client, "status: 0x%04x\n", status);
 
 		if (status < 0)
 			return status;
@@ -379,7 +344,6 @@
 			res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR;
 
 			switch (status & 0x18) {
-
 			case 0x00:
 			case 0x10:
 			case 0x14:
@@ -400,8 +364,8 @@
 		}
 
 		*(int *) arg = res;
-	}
 		break;
+	}
 
 	case DECODER_SET_NORM:
 	{
@@ -413,50 +377,43 @@
 		   choosen video norm */
 		temp_input = vpx3220_fp_read(client, 0xf2);
 
-		dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n",
-			I2C_NAME(client), *iarg);
+		v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg);
 		switch (*iarg) {
-
 		case VIDEO_MODE_NTSC:
 			vpx3220_write_fp_block(client, init_ntsc,
 					       sizeof(init_ntsc) >> 1);
-			dprintk(1, KERN_INFO "%s: norm switched to NTSC\n",
-				I2C_NAME(client));
+			v4l_dbg(1, debug, client, "norm switched to NTSC\n");
 			break;
 
 		case VIDEO_MODE_PAL:
 			vpx3220_write_fp_block(client, init_pal,
 					       sizeof(init_pal) >> 1);
-			dprintk(1, KERN_INFO "%s: norm switched to PAL\n",
-				I2C_NAME(client));
+			v4l_dbg(1, debug, client, "norm switched to PAL\n");
 			break;
 
 		case VIDEO_MODE_SECAM:
 			vpx3220_write_fp_block(client, init_secam,
 					       sizeof(init_secam) >> 1);
-			dprintk(1, KERN_INFO "%s: norm switched to SECAM\n",
-				I2C_NAME(client));
+			v4l_dbg(1, debug, client, "norm switched to SECAM\n");
 			break;
 
 		case VIDEO_MODE_AUTO:
 			/* FIXME This is only preliminary support */
 			data = vpx3220_fp_read(client, 0xf2) & 0x20;
 			vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
-			dprintk(1, KERN_INFO "%s: norm switched to Auto\n",
-				I2C_NAME(client));
+			v4l_dbg(1, debug, client, "norm switched to AUTO\n");
 			break;
 
 		default:
 			return -EINVAL;
-
 		}
 		decoder->norm = *iarg;
 
 		/* And here we set the backed up video input again */
 		vpx3220_fp_write(client, 0xf2, temp_input | 0x0010);
 		udelay(10);
-	}
 		break;
+	}
 
 	case DECODER_SET_INPUT:
 	{
@@ -475,8 +432,7 @@
 		if (*iarg < 0 || *iarg > 2)
 			return -EINVAL;
 
-		dprintk(1, KERN_INFO "%s: input switched to %s\n",
-			I2C_NAME(client), inputs[*iarg]);
+		v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]);
 
 		vpx3220_write(client, 0x33, input[*iarg][0]);
 
@@ -488,8 +444,8 @@
 				 data | (input[*iarg][1] << 5) | 0x0010);
 
 		udelay(10);
-	}
 		break;
+	}
 
 	case DECODER_SET_OUTPUT:
 	{
@@ -499,19 +455,18 @@
 		if (*iarg != 0) {
 			return -EINVAL;
 		}
-	}
 		break;
+	}
 
 	case DECODER_ENABLE_OUTPUT:
 	{
 		int *iarg = arg;
 
-		dprintk(1, KERN_DEBUG "%s: DECODER_ENABLE_OUTPUT %d\n",
-			I2C_NAME(client), *iarg);
+		v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg);
 
 		vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00));
-	}
 		break;
+	}
 
 	case DECODER_SET_PICTURE:
 	{
@@ -542,8 +497,8 @@
 			vpx3220_fp_write(client, 0x1c,
 					 ((decoder->hue - 32768) >> 6) & 0xFFF);
 		}
-	}
 		break;
+	}
 
 	default:
 		return -EINVAL;
@@ -552,8 +507,7 @@
 	return 0;
 }
 
-static int
-vpx3220_init_client (struct i2c_client *client)
+static int vpx3220_init_client(struct i2c_client *client)
 {
 	vpx3220_write_block(client, init_common, sizeof(init_common));
 	vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1);
@@ -567,115 +521,26 @@
  * Client management code
  */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] =
-    { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4,
-	I2C_CLIENT_END
-};
+static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END };
 
-static unsigned short ignore = I2C_CLIENT_END;
+I2C_CLIENT_INSMOD;
 
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.probe			= &ignore,
-	.ignore			= &ignore,
-};
-
-static struct i2c_driver vpx3220_i2c_driver;
-
-static int
-vpx3220_detach_client (struct i2c_client *client)
+static int vpx3220_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-	struct vpx3220 *decoder = i2c_get_clientdata(client);
-	int err;
-
-	err = i2c_detach_client(client);
-	if (err) {
-		return err;
-	}
-
-	kfree(decoder);
-	kfree(client);
-
-	return 0;
-}
-
-static int
-vpx3220_detect_client (struct i2c_adapter *adapter,
-		       int                 address,
-		       int                 kind)
-{
-	int err;
-	struct i2c_client *client;
 	struct vpx3220 *decoder;
-
-	dprintk(1, VPX3220_DEBUG "%s\n", __func__);
+	const char *name = NULL;
+	u8 ver;
+	u16 pn;
 
 	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality
-	    (adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
-		return 0;
-
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (client == NULL) {
-		return -ENOMEM;
-	}
-
-	client->addr = address;
-	client->adapter = adapter;
-	client->driver = &vpx3220_i2c_driver;
-
-	/* Check for manufacture ID and part number */
-	if (kind < 0) {
-		u8 id;
-		u16 pn;
-
-		id = vpx3220_read(client, 0x00);
-		if (id != 0xec) {
-			dprintk(1,
-				KERN_INFO
-				"vpx3220_attach: Wrong manufacturer ID (0x%02x)\n",
-				id);
-			kfree(client);
-			return 0;
-		}
-
-		pn = (vpx3220_read(client, 0x02) << 8) +
-		    vpx3220_read(client, 0x01);
-		switch (pn) {
-		case 0x4680:
-			strlcpy(I2C_NAME(client), "vpx3220a",
-				sizeof(I2C_NAME(client)));
-			break;
-		case 0x4260:
-			strlcpy(I2C_NAME(client), "vpx3216b",
-				sizeof(I2C_NAME(client)));
-			break;
-		case 0x4280:
-			strlcpy(I2C_NAME(client), "vpx3214c",
-				sizeof(I2C_NAME(client)));
-			break;
-		default:
-			dprintk(1,
-				KERN_INFO
-				"%s: Wrong part number (0x%04x)\n",
-				__func__, pn);
-			kfree(client);
-			return 0;
-		}
-	} else {
-		strlcpy(I2C_NAME(client), "forced vpx32xx",
-			sizeof(I2C_NAME(client)));
-	}
+	if (!i2c_check_functionality(client->adapter,
+		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
 
 	decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
-	if (decoder == NULL) {
-		kfree(client);
+	if (decoder == NULL)
 		return -ENOMEM;
-	}
 	decoder->norm = VIDEO_MODE_PAL;
 	decoder->input = 0;
 	decoder->enable = 1;
@@ -685,63 +550,52 @@
 	decoder->sat = 32768;
 	i2c_set_clientdata(client, decoder);
 
-	err = i2c_attach_client(client);
-	if (err) {
-		kfree(client);
-		kfree(decoder);
-		return err;
+	ver = i2c_smbus_read_byte_data(client, 0x00);
+	pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
+		i2c_smbus_read_byte_data(client, 0x01);
+	if (ver == 0xec) {
+		switch (pn) {
+		case 0x4680:
+			name = "vpx3220a";
+			break;
+		case 0x4260:
+			name = "vpx3216b";
+			break;
+		case 0x4280:
+			name = "vpx3214c";
+			break;
+		}
 	}
-
-	dprintk(1, KERN_INFO "%s: vpx32xx client found at address 0x%02x\n",
-		I2C_NAME(client), client->addr << 1);
+	if (name)
+		v4l_info(client, "%s found @ 0x%x (%s)\n", name,
+			client->addr << 1, client->adapter->name);
+	else
+		v4l_info(client, "chip (%02x:%04x) found @ 0x%x (%s)\n",
+			ver, pn, client->addr << 1, client->adapter->name);
 
 	vpx3220_init_client(client);
-
 	return 0;
 }
 
-static int
-vpx3220_attach_adapter (struct i2c_adapter *adapter)
+static int vpx3220_remove(struct i2c_client *client)
 {
-	int ret;
-
-	ret = i2c_probe(adapter, &addr_data, &vpx3220_detect_client);
-	dprintk(1, VPX3220_DEBUG "%s: i2c_probe returned %d\n",
-		__func__, ret);
-	return ret;
+	kfree(i2c_get_clientdata(client));
+	return 0;
 }
 
-/* -----------------------------------------------------------------------
- * Driver initialization and cleanup code
- */
-
-static struct i2c_driver vpx3220_i2c_driver = {
-	.driver = {
-		.name = "vpx3220",
-	},
-
-	.id = I2C_DRIVERID_VPX3220,
-
-	.attach_adapter = vpx3220_attach_adapter,
-	.detach_client = vpx3220_detach_client,
-	.command = vpx3220_command,
+static const struct i2c_device_id vpx3220_id[] = {
+	{ "vpx3220a", 0 },
+	{ "vpx3216b", 0 },
+	{ "vpx3214c", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, vpx3220_id);
 
-static int __init
-vpx3220_init (void)
-{
-	return i2c_add_driver(&vpx3220_i2c_driver);
-}
-
-static void __exit
-vpx3220_cleanup (void)
-{
-	i2c_del_driver(&vpx3220_i2c_driver);
-}
-
-module_init(vpx3220_init);
-module_exit(vpx3220_cleanup);
-
-MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
-MODULE_AUTHOR("Laurent Pinchart");
-MODULE_LICENSE("GPL");
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "vpx3220",
+	.driverid = I2C_DRIVERID_VPX3220,
+	.command = vpx3220_command,
+	.probe = vpx3220_probe,
+	.remove = vpx3220_remove,
+	.id_table = vpx3220_id,
+};
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
index 3282be7..fa5f2f8 100644
--- a/drivers/media/video/zoran/zoran_card.c
+++ b/drivers/media/video/zoran/zoran_card.c
@@ -817,6 +817,7 @@
 	memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
 	       sizeof(struct i2c_algo_bit_data));
 	zr->i2c_algo.data = zr;
+	zr->i2c_adapter.class = I2C_CLASS_TV_ANALOG;
 	zr->i2c_adapter.id = I2C_HW_B_ZR36067;
 	zr->i2c_adapter.client_register = zoran_i2c_client_register;
 	zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister;
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index 25de763..db11ab9 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -2996,7 +2996,6 @@
 			break;
 
 		default:
-			dprintk(3, "unsupported\n");
 			dprintk(1,
 				KERN_ERR
 				"%s: VIDIOC_S_FMT - unsupported type %d\n",
diff --git a/fs/Kconfig b/fs/Kconfig
index 9e9d70c..d0a1174 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -160,7 +160,7 @@
 	  filesystem initially.
 
 	  To compile this file system support as a module, choose M here. The
-	  module will be called ext4dev.
+	  module will be called ext4.
 
 	  If unsure, say N.
 
diff --git a/fs/Makefile b/fs/Makefile
index d0c69f5..2168c90 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -71,7 +71,7 @@
 # Do not add any filesystems before this line
 obj-$(CONFIG_REISERFS_FS)	+= reiserfs/
 obj-$(CONFIG_EXT3_FS)		+= ext3/ # Before ext2 so root fs can be ext3
-obj-$(CONFIG_EXT4_FS)		+= ext4/ # Before ext2 so root fs can be ext4dev
+obj-$(CONFIG_EXT4_FS)		+= ext4/ # Before ext2 so root fs can be ext4
 obj-$(CONFIG_JBD)		+= jbd/
 obj-$(CONFIG_JBD2)		+= jbd2/
 obj-$(CONFIG_EXT2_FS)		+= ext2/
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index bd2ece2..b9821be 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -568,8 +568,16 @@
 
 	/* this isn't the right place to decide whether block is metadata
 	 * inode.c/extents.c knows better, but for safety ... */
-	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) ||
-			ext4_should_journal_data(inode))
+	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+		metadata = 1;
+
+	/* We need to make sure we don't reuse
+	 * block released untill the transaction commit.
+	 * writeback mode have weak data consistency so
+	 * don't force data as metadata when freeing block
+	 * for writeback mode.
+	 */
+	if (metadata == 0 && !ext4_should_writeback_data(inode))
 		metadata = 1;
 
 	sb = inode->i_sb;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 6690a41..4880cc3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -511,7 +511,6 @@
 /*
  * Mount flags
  */
-#define EXT4_MOUNT_CHECK		0x00001	/* Do mount-time checks */
 #define EXT4_MOUNT_OLDALLOC		0x00002  /* Don't use the new Orlov allocator */
 #define EXT4_MOUNT_GRPID		0x00004	/* Create files with directory's group */
 #define EXT4_MOUNT_DEBUG		0x00008	/* Some debugging messages */
diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
index 6a0b40d..445fde6 100644
--- a/fs/ext4/ext4_sb.h
+++ b/fs/ext4/ext4_sb.h
@@ -99,9 +99,6 @@
 	struct inode *s_buddy_cache;
 	long s_blocks_reserved;
 	spinlock_t s_reserve_lock;
-	struct list_head s_active_transaction;
-	struct list_head s_closed_transaction;
-	struct list_head s_committed_transaction;
 	spinlock_t s_md_lock;
 	tid_t s_last_transaction;
 	unsigned short *s_mb_offsets, *s_mb_maxs;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 9b4ec9d..8dbf695 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1648,6 +1648,7 @@
 	int ret = 0, err, nr_pages, i;
 	unsigned long index, end;
 	struct pagevec pvec;
+	long pages_skipped;
 
 	BUG_ON(mpd->next_page <= mpd->first_page);
 	pagevec_init(&pvec, 0);
@@ -1655,20 +1656,30 @@
 	end = mpd->next_page - 1;
 
 	while (index <= end) {
-		/* XXX: optimize tail */
-		nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE);
+		/*
+		 * We can use PAGECACHE_TAG_DIRTY lookup here because
+		 * even though we have cleared the dirty flag on the page
+		 * We still keep the page in the radix tree with tag
+		 * PAGECACHE_TAG_DIRTY. See clear_page_dirty_for_io.
+		 * The PAGECACHE_TAG_DIRTY is cleared in set_page_writeback
+		 * which is called via the below writepage callback.
+		 */
+		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+					PAGECACHE_TAG_DIRTY,
+					min(end - index,
+					(pgoff_t)PAGEVEC_SIZE-1) + 1);
 		if (nr_pages == 0)
 			break;
 		for (i = 0; i < nr_pages; i++) {
 			struct page *page = pvec.pages[i];
 
-			index = page->index;
-			if (index > end)
-				break;
-			index++;
-
+			pages_skipped = mpd->wbc->pages_skipped;
 			err = mapping->a_ops->writepage(page, mpd->wbc);
-			if (!err)
+			if (!err && (pages_skipped == mpd->wbc->pages_skipped))
+				/*
+				 * have successfully written the page
+				 * without skipping the same
+				 */
 				mpd->pages_written++;
 			/*
 			 * In error case, we have to continue because
@@ -2104,7 +2115,6 @@
 			       struct writeback_control *wbc,
 			       struct mpage_da_data *mpd)
 {
-	long to_write;
 	int ret;
 
 	if (!mpd->get_block)
@@ -2119,19 +2129,18 @@
 	mpd->pages_written = 0;
 	mpd->retval = 0;
 
-	to_write = wbc->nr_to_write;
-
 	ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, mpd);
-
 	/*
 	 * Handle last extent of pages
 	 */
 	if (!mpd->io_done && mpd->next_page != mpd->first_page) {
 		if (mpage_da_map_blocks(mpd) == 0)
 			mpage_da_submit_io(mpd);
-	}
 
-	wbc->nr_to_write = to_write - mpd->pages_written;
+		mpd->io_done = 1;
+		ret = MPAGE_DA_EXTENT_TAIL;
+	}
+	wbc->nr_to_write -= mpd->pages_written;
 	return ret;
 }
 
@@ -2360,12 +2369,14 @@
 static int ext4_da_writepages(struct address_space *mapping,
 			      struct writeback_control *wbc)
 {
+	pgoff_t	index;
+	int range_whole = 0;
 	handle_t *handle = NULL;
-	loff_t range_start = 0;
 	struct mpage_da_data mpd;
 	struct inode *inode = mapping->host;
+	int no_nrwrite_index_update;
+	long pages_written = 0, pages_skipped;
 	int needed_blocks, ret = 0, nr_to_writebump = 0;
-	long to_write, pages_skipped = 0;
 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
 
 	/*
@@ -2385,23 +2396,26 @@
 		nr_to_writebump = sbi->s_mb_stream_request - wbc->nr_to_write;
 		wbc->nr_to_write = sbi->s_mb_stream_request;
 	}
+	if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+		range_whole = 1;
 
-	if (!wbc->range_cyclic)
-		/*
-		 * If range_cyclic is not set force range_cont
-		 * and save the old writeback_index
-		 */
-		wbc->range_cont = 1;
-
-	range_start =  wbc->range_start;
-	pages_skipped = wbc->pages_skipped;
+	if (wbc->range_cyclic)
+		index = mapping->writeback_index;
+	else
+		index = wbc->range_start >> PAGE_CACHE_SHIFT;
 
 	mpd.wbc = wbc;
 	mpd.inode = mapping->host;
 
-restart_loop:
-	to_write = wbc->nr_to_write;
-	while (!ret && to_write > 0) {
+	/*
+	 * we don't want write_cache_pages to update
+	 * nr_to_write and writeback_index
+	 */
+	no_nrwrite_index_update = wbc->no_nrwrite_index_update;
+	wbc->no_nrwrite_index_update = 1;
+	pages_skipped = wbc->pages_skipped;
+
+	while (!ret && wbc->nr_to_write > 0) {
 
 		/*
 		 * we  insert one extent at a time. So we need
@@ -2422,48 +2436,53 @@
 			dump_stack();
 			goto out_writepages;
 		}
-		to_write -= wbc->nr_to_write;
-
 		mpd.get_block = ext4_da_get_block_write;
 		ret = mpage_da_writepages(mapping, wbc, &mpd);
 
 		ext4_journal_stop(handle);
 
-		if (mpd.retval == -ENOSPC)
+		if (mpd.retval == -ENOSPC) {
+			/* commit the transaction which would
+			 * free blocks released in the transaction
+			 * and try again
+			 */
 			jbd2_journal_force_commit_nested(sbi->s_journal);
-
-		/* reset the retry count */
-		if (ret == MPAGE_DA_EXTENT_TAIL) {
+			wbc->pages_skipped = pages_skipped;
+			ret = 0;
+		} else if (ret == MPAGE_DA_EXTENT_TAIL) {
 			/*
 			 * got one extent now try with
 			 * rest of the pages
 			 */
-			to_write += wbc->nr_to_write;
+			pages_written += mpd.pages_written;
+			wbc->pages_skipped = pages_skipped;
 			ret = 0;
-		} else if (wbc->nr_to_write) {
+		} else if (wbc->nr_to_write)
 			/*
 			 * There is no more writeout needed
 			 * or we requested for a noblocking writeout
 			 * and we found the device congested
 			 */
-			to_write += wbc->nr_to_write;
 			break;
-		}
-		wbc->nr_to_write = to_write;
 	}
+	if (pages_skipped != wbc->pages_skipped)
+		printk(KERN_EMERG "This should not happen leaving %s "
+				"with nr_to_write = %ld ret = %d\n",
+				__func__, wbc->nr_to_write, ret);
 
-	if (wbc->range_cont && (pages_skipped != wbc->pages_skipped)) {
-		/* We skipped pages in this loop */
-		wbc->range_start = range_start;
-		wbc->nr_to_write = to_write +
-				wbc->pages_skipped - pages_skipped;
-		wbc->pages_skipped = pages_skipped;
-		goto restart_loop;
-	}
+	/* Update index */
+	index += pages_written;
+	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
+		/*
+		 * set the writeback_index so that range_cyclic
+		 * mode will write it back later
+		 */
+		mapping->writeback_index = index;
 
 out_writepages:
-	wbc->nr_to_write = to_write - nr_to_writebump;
-	wbc->range_start = range_start;
+	if (!no_nrwrite_index_update)
+		wbc->no_nrwrite_index_update = 0;
+	wbc->nr_to_write -= nr_to_writebump;
 	return ret;
 }
 
@@ -4175,7 +4194,6 @@
 	struct inode *inode = &(ei->vfs_inode);
 	u64 i_blocks = inode->i_blocks;
 	struct super_block *sb = inode->i_sb;
-	int err = 0;
 
 	if (i_blocks <= ~0U) {
 		/*
@@ -4185,36 +4203,27 @@
 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
 		raw_inode->i_blocks_high = 0;
 		ei->i_flags &= ~EXT4_HUGE_FILE_FL;
-	} else if (i_blocks <= 0xffffffffffffULL) {
+		return 0;
+	}
+	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
+		return -EFBIG;
+
+	if (i_blocks <= 0xffffffffffffULL) {
 		/*
 		 * i_blocks can be represented in a 48 bit variable
 		 * as multiple of 512 bytes
 		 */
-		err = ext4_update_rocompat_feature(handle, sb,
-					    EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
-		if (err)
-			goto  err_out;
-		/* i_block is stored in the split  48 bit fields */
 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
 		raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
 		ei->i_flags &= ~EXT4_HUGE_FILE_FL;
 	} else {
-		/*
-		 * i_blocks should be represented in a 48 bit variable
-		 * as multiple of  file system block size
-		 */
-		err = ext4_update_rocompat_feature(handle, sb,
-					    EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
-		if (err)
-			goto  err_out;
 		ei->i_flags |= EXT4_HUGE_FILE_FL;
 		/* i_block is stored in file system block size */
 		i_blocks = i_blocks >> (inode->i_blkbits - 9);
 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
 		raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
 	}
-err_out:
-	return err;
+	return 0;
 }
 
 /*
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index b580714..dfe17a1 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2300,6 +2300,7 @@
 	}
 
 	INIT_LIST_HEAD(&meta_group_info[i]->bb_prealloc_list);
+	meta_group_info[i]->bb_free_root.rb_node = NULL;;
 
 #ifdef DOUBLE_CHECK
 	{
@@ -2522,9 +2523,6 @@
 	}
 
 	spin_lock_init(&sbi->s_md_lock);
-	INIT_LIST_HEAD(&sbi->s_active_transaction);
-	INIT_LIST_HEAD(&sbi->s_closed_transaction);
-	INIT_LIST_HEAD(&sbi->s_committed_transaction);
 	spin_lock_init(&sbi->s_bal_lock);
 
 	sbi->s_mb_max_to_scan = MB_DEFAULT_MAX_TO_SCAN;
@@ -2553,6 +2551,8 @@
 	ext4_mb_init_per_dev_proc(sb);
 	ext4_mb_history_init(sb);
 
+	sbi->s_journal->j_commit_callback = release_blocks_on_commit;
+
 	printk(KERN_INFO "EXT4-fs: mballoc enabled\n");
 	return 0;
 }
@@ -2568,7 +2568,7 @@
 		pa = list_entry(cur, struct ext4_prealloc_space, pa_group_list);
 		list_del(&pa->pa_group_list);
 		count++;
-		kfree(pa);
+		kmem_cache_free(ext4_pspace_cachep, pa);
 	}
 	if (count)
 		mb_debug("mballoc: %u PAs left\n", count);
@@ -2582,15 +2582,6 @@
 	struct ext4_group_info *grinfo;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-	/* release freed, non-committed blocks */
-	spin_lock(&sbi->s_md_lock);
-	list_splice_init(&sbi->s_closed_transaction,
-			&sbi->s_committed_transaction);
-	list_splice_init(&sbi->s_active_transaction,
-			&sbi->s_committed_transaction);
-	spin_unlock(&sbi->s_md_lock);
-	ext4_mb_free_committed_blocks(sb);
-
 	if (sbi->s_group_info) {
 		for (i = 0; i < sbi->s_groups_count; i++) {
 			grinfo = ext4_get_group_info(sb, i);
@@ -2644,61 +2635,57 @@
 	return 0;
 }
 
-static noinline_for_stack void
-ext4_mb_free_committed_blocks(struct super_block *sb)
+/*
+ * This function is called by the jbd2 layer once the commit has finished,
+ * so we know we can free the blocks that were released with that commit.
+ */
+static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
 {
-	struct ext4_sb_info *sbi = EXT4_SB(sb);
-	int err;
-	int i;
-	int count = 0;
-	int count2 = 0;
-	struct ext4_free_metadata *md;
+	struct super_block *sb = journal->j_private;
 	struct ext4_buddy e4b;
+	struct ext4_group_info *db;
+	int err, count = 0, count2 = 0;
+	struct ext4_free_data *entry;
+	ext4_fsblk_t discard_block;
+	struct list_head *l, *ltmp;
 
-	if (list_empty(&sbi->s_committed_transaction))
-		return;
-
-	/* there is committed blocks to be freed yet */
-	do {
-		/* get next array of blocks */
-		md = NULL;
-		spin_lock(&sbi->s_md_lock);
-		if (!list_empty(&sbi->s_committed_transaction)) {
-			md = list_entry(sbi->s_committed_transaction.next,
-					struct ext4_free_metadata, list);
-			list_del(&md->list);
-		}
-		spin_unlock(&sbi->s_md_lock);
-
-		if (md == NULL)
-			break;
+	list_for_each_safe(l, ltmp, &txn->t_private_list) {
+		entry = list_entry(l, struct ext4_free_data, list);
 
 		mb_debug("gonna free %u blocks in group %lu (0x%p):",
-				md->num, md->group, md);
+			 entry->count, entry->group, entry);
 
-		err = ext4_mb_load_buddy(sb, md->group, &e4b);
+		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
 		/* we expect to find existing buddy because it's pinned */
 		BUG_ON(err != 0);
 
+		db = e4b.bd_info;
 		/* there are blocks to put in buddy to make them really free */
-		count += md->num;
+		count += entry->count;
 		count2++;
-		ext4_lock_group(sb, md->group);
-		for (i = 0; i < md->num; i++) {
-			mb_debug(" %u", md->blocks[i]);
-			mb_free_blocks(NULL, &e4b, md->blocks[i], 1);
+		ext4_lock_group(sb, entry->group);
+		/* Take it out of per group rb tree */
+		rb_erase(&entry->node, &(db->bb_free_root));
+		mb_free_blocks(NULL, &e4b, entry->start_blk, entry->count);
+
+		if (!db->bb_free_root.rb_node) {
+			/* No more items in the per group rb tree
+			 * balance refcounts from ext4_mb_free_metadata()
+			 */
+			page_cache_release(e4b.bd_buddy_page);
+			page_cache_release(e4b.bd_bitmap_page);
 		}
-		mb_debug("\n");
-		ext4_unlock_group(sb, md->group);
+		ext4_unlock_group(sb, entry->group);
+		discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb)
+			+ entry->start_blk
+			+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+		trace_mark(ext4_discard_blocks, "dev %s blk %llu count %u", sb->s_id,
+			   (unsigned long long) discard_block, entry->count);
+		sb_issue_discard(sb, discard_block, entry->count);
 
-		/* balance refcounts from ext4_mb_free_metadata() */
-		page_cache_release(e4b.bd_buddy_page);
-		page_cache_release(e4b.bd_bitmap_page);
-
-		kfree(md);
+		kmem_cache_free(ext4_free_ext_cachep, entry);
 		ext4_mb_release_desc(&e4b);
-
-	} while (md);
+	}
 
 	mb_debug("freed %u blocks in %u structures\n", count, count2);
 }
@@ -2712,6 +2699,7 @@
 
 static int ext4_mb_init_per_dev_proc(struct super_block *sb)
 {
+#ifdef CONFIG_PROC_FS
 	mode_t mode = S_IFREG | S_IRUGO | S_IWUSR;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct proc_dir_entry *proc;
@@ -2735,10 +2723,14 @@
 	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
 	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
 	return -ENOMEM;
+#else
+	return 0;
+#endif
 }
 
 static int ext4_mb_destroy_per_dev_proc(struct super_block *sb)
 {
+#ifdef CONFIG_PROC_FS
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 
 	if (sbi->s_proc == NULL)
@@ -2750,7 +2742,7 @@
 	remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_proc);
 	remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_proc);
 	remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_proc);
-
+#endif
 	return 0;
 }
 
@@ -2771,6 +2763,16 @@
 		kmem_cache_destroy(ext4_pspace_cachep);
 		return -ENOMEM;
 	}
+
+	ext4_free_ext_cachep =
+		kmem_cache_create("ext4_free_block_extents",
+				     sizeof(struct ext4_free_data),
+				     0, SLAB_RECLAIM_ACCOUNT, NULL);
+	if (ext4_free_ext_cachep == NULL) {
+		kmem_cache_destroy(ext4_pspace_cachep);
+		kmem_cache_destroy(ext4_ac_cachep);
+		return -ENOMEM;
+	}
 	return 0;
 }
 
@@ -2779,6 +2781,7 @@
 	/* XXX: synchronize_rcu(); */
 	kmem_cache_destroy(ext4_pspace_cachep);
 	kmem_cache_destroy(ext4_ac_cachep);
+	kmem_cache_destroy(ext4_free_ext_cachep);
 }
 
 
@@ -4324,8 +4327,6 @@
 		goto out1;
 	}
 
-	ext4_mb_poll_new_transaction(sb, handle);
-
 	*errp = ext4_mb_initialize_context(ac, ar);
 	if (*errp) {
 		ar->len = 0;
@@ -4384,35 +4385,20 @@
 
 	return block;
 }
-static void ext4_mb_poll_new_transaction(struct super_block *sb,
-						handle_t *handle)
+
+/*
+ * We can merge two free data extents only if the physical blocks
+ * are contiguous, AND the extents were freed by the same transaction,
+ * AND the blocks are associated with the same group.
+ */
+static int can_merge(struct ext4_free_data *entry1,
+			struct ext4_free_data *entry2)
 {
-	struct ext4_sb_info *sbi = EXT4_SB(sb);
-
-	if (sbi->s_last_transaction == handle->h_transaction->t_tid)
-		return;
-
-	/* new transaction! time to close last one and free blocks for
-	 * committed transaction. we know that only transaction can be
-	 * active, so previos transaction can be being logged and we
-	 * know that transaction before previous is known to be already
-	 * logged. this means that now we may free blocks freed in all
-	 * transactions before previous one. hope I'm clear enough ... */
-
-	spin_lock(&sbi->s_md_lock);
-	if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
-		mb_debug("new transaction %lu, old %lu\n",
-				(unsigned long) handle->h_transaction->t_tid,
-				(unsigned long) sbi->s_last_transaction);
-		list_splice_init(&sbi->s_closed_transaction,
-				&sbi->s_committed_transaction);
-		list_splice_init(&sbi->s_active_transaction,
-				&sbi->s_closed_transaction);
-		sbi->s_last_transaction = handle->h_transaction->t_tid;
-	}
-	spin_unlock(&sbi->s_md_lock);
-
-	ext4_mb_free_committed_blocks(sb);
+	if ((entry1->t_tid == entry2->t_tid) &&
+	    (entry1->group == entry2->group) &&
+	    ((entry1->start_blk + entry1->count) == entry2->start_blk))
+		return 1;
+	return 0;
 }
 
 static noinline_for_stack int
@@ -4422,57 +4408,80 @@
 	struct ext4_group_info *db = e4b->bd_info;
 	struct super_block *sb = e4b->bd_sb;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
-	struct ext4_free_metadata *md;
-	int i;
+	struct ext4_free_data *entry, *new_entry;
+	struct rb_node **n = &db->bb_free_root.rb_node, *node;
+	struct rb_node *parent = NULL, *new_node;
+
 
 	BUG_ON(e4b->bd_bitmap_page == NULL);
 	BUG_ON(e4b->bd_buddy_page == NULL);
 
+	new_entry  = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
+	new_entry->start_blk = block;
+	new_entry->group  = group;
+	new_entry->count = count;
+	new_entry->t_tid = handle->h_transaction->t_tid;
+	new_node = &new_entry->node;
+
 	ext4_lock_group(sb, group);
-	for (i = 0; i < count; i++) {
-		md = db->bb_md_cur;
-		if (md && db->bb_tid != handle->h_transaction->t_tid) {
-			db->bb_md_cur = NULL;
-			md = NULL;
-		}
-
-		if (md == NULL) {
-			ext4_unlock_group(sb, group);
-			md = kmalloc(sizeof(*md), GFP_NOFS);
-			if (md == NULL)
-				return -ENOMEM;
-			md->num = 0;
-			md->group = group;
-
-			ext4_lock_group(sb, group);
-			if (db->bb_md_cur == NULL) {
-				spin_lock(&sbi->s_md_lock);
-				list_add(&md->list, &sbi->s_active_transaction);
-				spin_unlock(&sbi->s_md_lock);
-				/* protect buddy cache from being freed,
-				 * otherwise we'll refresh it from
-				 * on-disk bitmap and lose not-yet-available
-				 * blocks */
-				page_cache_get(e4b->bd_buddy_page);
-				page_cache_get(e4b->bd_bitmap_page);
-				db->bb_md_cur = md;
-				db->bb_tid = handle->h_transaction->t_tid;
-				mb_debug("new md 0x%p for group %lu\n",
-						md, md->group);
-			} else {
-				kfree(md);
-				md = db->bb_md_cur;
-			}
-		}
-
-		BUG_ON(md->num >= EXT4_BB_MAX_BLOCKS);
-		md->blocks[md->num] = block + i;
-		md->num++;
-		if (md->num == EXT4_BB_MAX_BLOCKS) {
-			/* no more space, put full container on a sb's list */
-			db->bb_md_cur = NULL;
+	if (!*n) {
+		/* first free block exent. We need to
+		   protect buddy cache from being freed,
+		 * otherwise we'll refresh it from
+		 * on-disk bitmap and lose not-yet-available
+		 * blocks */
+		page_cache_get(e4b->bd_buddy_page);
+		page_cache_get(e4b->bd_bitmap_page);
+	}
+	while (*n) {
+		parent = *n;
+		entry = rb_entry(parent, struct ext4_free_data, node);
+		if (block < entry->start_blk)
+			n = &(*n)->rb_left;
+		else if (block >= (entry->start_blk + entry->count))
+			n = &(*n)->rb_right;
+		else {
+			ext4_error(sb, __func__,
+			    "Double free of blocks %d (%d %d)\n",
+			    block, entry->start_blk, entry->count);
+			return 0;
 		}
 	}
+
+	rb_link_node(new_node, parent, n);
+	rb_insert_color(new_node, &db->bb_free_root);
+
+	/* Now try to see the extent can be merged to left and right */
+	node = rb_prev(new_node);
+	if (node) {
+		entry = rb_entry(node, struct ext4_free_data, node);
+		if (can_merge(entry, new_entry)) {
+			new_entry->start_blk = entry->start_blk;
+			new_entry->count += entry->count;
+			rb_erase(node, &(db->bb_free_root));
+			spin_lock(&sbi->s_md_lock);
+			list_del(&entry->list);
+			spin_unlock(&sbi->s_md_lock);
+			kmem_cache_free(ext4_free_ext_cachep, entry);
+		}
+	}
+
+	node = rb_next(new_node);
+	if (node) {
+		entry = rb_entry(node, struct ext4_free_data, node);
+		if (can_merge(new_entry, entry)) {
+			new_entry->count += entry->count;
+			rb_erase(node, &(db->bb_free_root));
+			spin_lock(&sbi->s_md_lock);
+			list_del(&entry->list);
+			spin_unlock(&sbi->s_md_lock);
+			kmem_cache_free(ext4_free_ext_cachep, entry);
+		}
+	}
+	/* Add the extent to transaction's private list */
+	spin_lock(&sbi->s_md_lock);
+	list_add(&new_entry->list, &handle->h_transaction->t_private_list);
+	spin_unlock(&sbi->s_md_lock);
 	ext4_unlock_group(sb, group);
 	return 0;
 }
@@ -4500,8 +4509,6 @@
 
 	*freed = 0;
 
-	ext4_mb_poll_new_transaction(sb, handle);
-
 	sbi = EXT4_SB(sb);
 	es = EXT4_SB(sb)->s_es;
 	if (block < le32_to_cpu(es->s_first_data_block) ||
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index b3b4828..b5dff1f 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -18,6 +18,8 @@
 #include <linux/pagemap.h>
 #include <linux/seq_file.h>
 #include <linux/version.h>
+#include <linux/blkdev.h>
+#include <linux/marker.h>
 #include "ext4_jbd2.h"
 #include "ext4.h"
 #include "group.h"
@@ -98,23 +100,29 @@
 
 static struct kmem_cache *ext4_pspace_cachep;
 static struct kmem_cache *ext4_ac_cachep;
+static struct kmem_cache *ext4_free_ext_cachep;
 
-#ifdef EXT4_BB_MAX_BLOCKS
-#undef EXT4_BB_MAX_BLOCKS
-#endif
-#define EXT4_BB_MAX_BLOCKS	30
+struct ext4_free_data {
+	/* this links the free block information from group_info */
+	struct rb_node node;
 
-struct ext4_free_metadata {
-	ext4_group_t group;
-	unsigned short num;
-	ext4_grpblk_t  blocks[EXT4_BB_MAX_BLOCKS];
+	/* this links the free block information from ext4_sb_info */
 	struct list_head list;
+
+	/* group which free block extent belongs */
+	ext4_group_t group;
+
+	/* free block extent */
+	ext4_grpblk_t start_blk;
+	ext4_grpblk_t count;
+
+	/* transaction which freed this extent */
+	tid_t	t_tid;
 };
 
 struct ext4_group_info {
 	unsigned long	bb_state;
-	unsigned long	bb_tid;
-	struct ext4_free_metadata *bb_md_cur;
+	struct rb_root  bb_free_root;
 	unsigned short	bb_first_free;
 	unsigned short	bb_free;
 	unsigned short	bb_fragments;
@@ -261,8 +269,6 @@
 
 static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
 					ext4_group_t group);
-static void ext4_mb_poll_new_transaction(struct super_block *, handle_t *);
-static void ext4_mb_free_committed_blocks(struct super_block *);
 static void ext4_mb_return_to_preallocation(struct inode *inode,
 					struct ext4_buddy *e4b, sector_t block,
 					int count);
@@ -270,6 +276,7 @@
 			struct super_block *, struct ext4_prealloc_space *pa);
 static int ext4_mb_init_per_dev_proc(struct super_block *sb);
 static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
+static void release_blocks_on_commit(journal_t *journal, transaction_t *txn);
 
 
 static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index dea8f13..9b2b2bc 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -374,66 +374,6 @@
 	 */
 }
 
-int ext4_update_compat_feature(handle_t *handle,
-					struct super_block *sb, __u32 compat)
-{
-	int err = 0;
-	if (!EXT4_HAS_COMPAT_FEATURE(sb, compat)) {
-		err = ext4_journal_get_write_access(handle,
-				EXT4_SB(sb)->s_sbh);
-		if (err)
-			return err;
-		EXT4_SET_COMPAT_FEATURE(sb, compat);
-		sb->s_dirt = 1;
-		handle->h_sync = 1;
-		BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
-					"call ext4_journal_dirty_met adata");
-		err = ext4_journal_dirty_metadata(handle,
-				EXT4_SB(sb)->s_sbh);
-	}
-	return err;
-}
-
-int ext4_update_rocompat_feature(handle_t *handle,
-					struct super_block *sb, __u32 rocompat)
-{
-	int err = 0;
-	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, rocompat)) {
-		err = ext4_journal_get_write_access(handle,
-				EXT4_SB(sb)->s_sbh);
-		if (err)
-			return err;
-		EXT4_SET_RO_COMPAT_FEATURE(sb, rocompat);
-		sb->s_dirt = 1;
-		handle->h_sync = 1;
-		BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
-					"call ext4_journal_dirty_met adata");
-		err = ext4_journal_dirty_metadata(handle,
-				EXT4_SB(sb)->s_sbh);
-	}
-	return err;
-}
-
-int ext4_update_incompat_feature(handle_t *handle,
-					struct super_block *sb, __u32 incompat)
-{
-	int err = 0;
-	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, incompat)) {
-		err = ext4_journal_get_write_access(handle,
-				EXT4_SB(sb)->s_sbh);
-		if (err)
-			return err;
-		EXT4_SET_INCOMPAT_FEATURE(sb, incompat);
-		sb->s_dirt = 1;
-		handle->h_sync = 1;
-		BUFFER_TRACE(EXT4_SB(sb)->s_sbh,
-					"call ext4_journal_dirty_met adata");
-		err = ext4_journal_dirty_metadata(handle,
-				EXT4_SB(sb)->s_sbh);
-	}
-	return err;
-}
-
 /*
  * Open the external journal device
  */
@@ -904,7 +844,7 @@
 enum {
 	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
-	Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
+	Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov,
 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
 	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
 	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
@@ -915,7 +855,7 @@
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
 	Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version,
-	Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc,
+	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
 	Opt_inode_readahead_blks
 };
 
@@ -933,8 +873,6 @@
 	{Opt_err_panic, "errors=panic"},
 	{Opt_err_ro, "errors=remount-ro"},
 	{Opt_nouid32, "nouid32"},
-	{Opt_nocheck, "nocheck"},
-	{Opt_nocheck, "check=none"},
 	{Opt_debug, "debug"},
 	{Opt_oldalloc, "oldalloc"},
 	{Opt_orlov, "orlov"},
@@ -973,8 +911,6 @@
 	{Opt_extents, "extents"},
 	{Opt_noextents, "noextents"},
 	{Opt_i_version, "i_version"},
-	{Opt_mballoc, "mballoc"},
-	{Opt_nomballoc, "nomballoc"},
 	{Opt_stripe, "stripe=%u"},
 	{Opt_resize, "resize"},
 	{Opt_delalloc, "delalloc"},
@@ -1073,9 +1009,6 @@
 		case Opt_nouid32:
 			set_opt(sbi->s_mount_opt, NO_UID32);
 			break;
-		case Opt_nocheck:
-			clear_opt(sbi->s_mount_opt, CHECK);
-			break;
 		case Opt_debug:
 			set_opt(sbi->s_mount_opt, DEBUG);
 			break;
@@ -1618,14 +1551,14 @@
 		if (block_bitmap < first_block || block_bitmap > last_block) {
 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
 			       "Block bitmap for group %lu not in group "
-			       "(block %llu)!", i, block_bitmap);
+			       "(block %llu)!\n", i, block_bitmap);
 			return 0;
 		}
 		inode_bitmap = ext4_inode_bitmap(sb, gdp);
 		if (inode_bitmap < first_block || inode_bitmap > last_block) {
 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
 			       "Inode bitmap for group %lu not in group "
-			       "(block %llu)!", i, inode_bitmap);
+			       "(block %llu)!\n", i, inode_bitmap);
 			return 0;
 		}
 		inode_table = ext4_inode_table(sb, gdp);
@@ -1633,7 +1566,7 @@
 		    inode_table + sbi->s_itb_per_group - 1 > last_block) {
 			printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
 			       "Inode table for group %lu not in group "
-			       "(block %llu)!", i, inode_table);
+			       "(block %llu)!\n", i, inode_table);
 			return 0;
 		}
 		spin_lock(sb_bgl_lock(sbi, i));
@@ -1778,13 +1711,13 @@
  *
  * Note, this does *not* consider any metadata overhead for vfs i_blocks.
  */
-static loff_t ext4_max_size(int blkbits)
+static loff_t ext4_max_size(int blkbits, int has_huge_files)
 {
 	loff_t res;
 	loff_t upper_limit = MAX_LFS_FILESIZE;
 
 	/* small i_blocks in vfs inode? */
-	if (sizeof(blkcnt_t) < sizeof(u64)) {
+	if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
 		/*
 		 * CONFIG_LSF is not enabled implies the inode
 		 * i_block represent total blocks in 512 bytes
@@ -1814,7 +1747,7 @@
  * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
  * We need to be 1 filesystem block less than the 2^48 sector limit.
  */
-static loff_t ext4_max_bitmap_size(int bits)
+static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
 {
 	loff_t res = EXT4_NDIR_BLOCKS;
 	int meta_blocks;
@@ -1827,11 +1760,11 @@
 	 * total number of  512 bytes blocks of the file
 	 */
 
-	if (sizeof(blkcnt_t) < sizeof(u64)) {
+	if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
 		/*
-		 * CONFIG_LSF is not enabled implies the inode
-		 * i_block represent total blocks in 512 bytes
-		 * 32 == size of vfs inode i_blocks * 8
+		 * !has_huge_files or CONFIG_LSF is not enabled
+		 * implies the inode i_block represent total blocks in
+		 * 512 bytes 32 == size of vfs inode i_blocks * 8
 		 */
 		upper_limit = (1LL << 32) - 1;
 
@@ -1940,7 +1873,7 @@
 	int blocksize;
 	int db_count;
 	int i;
-	int needs_recovery;
+	int needs_recovery, has_huge_files;
 	__le32 features;
 	__u64 blocks_count;
 	int err;
@@ -2081,7 +2014,9 @@
 		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
-	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
+	has_huge_files = EXT4_HAS_RO_COMPAT_FEATURE(sb,
+				    EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
+	if (has_huge_files) {
 		/*
 		 * Large file size enabled file system can only be
 		 * mount if kernel is build with CONFIG_LSF
@@ -2131,8 +2066,9 @@
 		}
 	}
 
-	sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits);
-	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits);
+	sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits,
+						      has_huge_files);
+	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
 
 	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
 		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
@@ -2456,6 +2392,21 @@
 			"available.\n");
 	}
 
+	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+		printk(KERN_WARNING "EXT4-fs: Ignoring delalloc option - "
+				"requested data journaling mode\n");
+		clear_opt(sbi->s_mount_opt, DELALLOC);
+	} else if (test_opt(sb, DELALLOC))
+		printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
+
+	ext4_ext_init(sb);
+	err = ext4_mb_init(sb, needs_recovery);
+	if (err) {
+		printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n",
+		       err);
+		goto failed_mount4;
+	}
+
 	/*
 	 * akpm: core read_super() calls in here with the superblock locked.
 	 * That deadlocks, because orphan cleanup needs to lock the superblock
@@ -2475,21 +2426,6 @@
 	       test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA ? "ordered":
 	       "writeback");
 
-	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
-		printk(KERN_WARNING "EXT4-fs: Ignoring delalloc option - "
-				"requested data journaling mode\n");
-		clear_opt(sbi->s_mount_opt, DELALLOC);
-	} else if (test_opt(sb, DELALLOC))
-		printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n");
-
-	ext4_ext_init(sb);
-	err = ext4_mb_init(sb, needs_recovery);
-	if (err) {
-		printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n",
-		       err);
-		goto failed_mount4;
-	}
-
 	lock_kernel();
 	return 0;
 
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 0abe02c..8b119e1 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -995,6 +995,9 @@
 	}
 	spin_unlock(&journal->j_list_lock);
 
+	if (journal->j_commit_callback)
+		journal->j_commit_callback(journal, commit_transaction);
+
 	trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
 		   journal->j_devname, commit_transaction->t_tid,
 		   journal->j_tail_sequence);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index e5d5405..39b7805 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -52,6 +52,7 @@
 	transaction->t_expires = jiffies + journal->j_commit_interval;
 	spin_lock_init(&transaction->t_handle_lock);
 	INIT_LIST_HEAD(&transaction->t_inode_list);
+	INIT_LIST_HEAD(&transaction->t_private_list);
 
 	/* Set up the commit timer for the new transaction. */
 	journal->j_commit_timer.expires = round_jiffies(transaction->t_expires);
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 38d3c6b..f46ba4b 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -36,7 +36,6 @@
 #ifndef _DRM_H_
 #define _DRM_H_
 
-#if defined(__linux__)
 #if defined(__KERNEL__)
 #endif
 #include <asm/ioctl.h>		/* For _IO* macros */
@@ -46,22 +45,6 @@
 #define DRM_IOC_WRITE		_IOC_WRITE
 #define DRM_IOC_READWRITE	_IOC_READ|_IOC_WRITE
 #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#if defined(__FreeBSD__) && defined(IN_MODULE)
-/* Prevent name collision when including sys/ioccom.h */
-#undef ioctl
-#include <sys/ioccom.h>
-#define ioctl(a,b,c)		xf86ioctl(a,b,c)
-#else
-#include <sys/ioccom.h>
-#endif				/* __FreeBSD__ && xf86ioctl */
-#define DRM_IOCTL_NR(n)		((n) & 0xff)
-#define DRM_IOC_VOID		IOC_VOID
-#define DRM_IOC_READ		IOC_OUT
-#define DRM_IOC_WRITE		IOC_IN
-#define DRM_IOC_READWRITE	IOC_INOUT
-#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
-#endif
 
 #define DRM_MAJOR       226
 #define DRM_MAX_MINOR   15
@@ -471,6 +454,7 @@
 enum drm_vblank_seq_type {
 	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
 	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
+	_DRM_VBLANK_FLIP = 0x8000000,   /**< Scheduled buffer swap should flip */
 	_DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
 	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
 	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking */
@@ -503,6 +487,19 @@
 	struct drm_wait_vblank_reply reply;
 };
 
+#define _DRM_PRE_MODESET 1
+#define _DRM_POST_MODESET 2
+
+/**
+ * DRM_IOCTL_MODESET_CTL ioctl argument type
+ *
+ * \sa drmModesetCtl().
+ */
+struct drm_modeset_ctl {
+	uint32_t crtc;
+	uint32_t cmd;
+};
+
 /**
  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
  *
@@ -573,6 +570,34 @@
 	int drm_dd_minor;
 };
 
+/** DRM_IOCTL_GEM_CLOSE ioctl argument type */
+struct drm_gem_close {
+	/** Handle of the object to be closed. */
+	uint32_t handle;
+	uint32_t pad;
+};
+
+/** DRM_IOCTL_GEM_FLINK ioctl argument type */
+struct drm_gem_flink {
+	/** Handle for the object being named */
+	uint32_t handle;
+
+	/** Returned global name */
+	uint32_t name;
+};
+
+/** DRM_IOCTL_GEM_OPEN ioctl argument type */
+struct drm_gem_open {
+	/** Name of object being opened */
+	uint32_t name;
+
+	/** Returned handle for the object */
+	uint32_t handle;
+
+	/** Returned size of the object */
+	uint64_t size;
+};
+
 #define DRM_IOCTL_BASE			'd'
 #define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
 #define DRM_IOR(nr,type)		_IOR(DRM_IOCTL_BASE,nr,type)
@@ -587,6 +612,10 @@
 #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
 #define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)
+#define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
+#define DRM_IOCTL_GEM_CLOSE		DRM_IOW (0x09, struct drm_gem_close)
+#define DRM_IOCTL_GEM_FLINK		DRM_IOWR(0x0a, struct drm_gem_flink)
+#define DRM_IOCTL_GEM_OPEN		DRM_IOWR(0x0b, struct drm_gem_open)
 
 #define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, struct drm_unique)
 #define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, struct drm_auth)
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 1c1b13e..59c796b 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -104,6 +104,7 @@
 #define DRIVER_DMA_QUEUE   0x200
 #define DRIVER_FB_DMA      0x400
 #define DRIVER_IRQ_VBL2    0x800
+#define DRIVER_GEM         0x1000
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -387,6 +388,10 @@
 	struct drm_minor *minor;
 	int remove_auth_on_close;
 	unsigned long lock_count;
+	/** Mapping of mm object handles to object pointers. */
+	struct idr object_idr;
+	/** Lock for synchronization of access to object_idr. */
+	spinlock_t table_lock;
 	struct file *filp;
 	void *driver_priv;
 };
@@ -558,6 +563,56 @@
 };
 
 /**
+ * This structure defines the drm_mm memory object, which will be used by the
+ * DRM for its buffer objects.
+ */
+struct drm_gem_object {
+	/** Reference count of this object */
+	struct kref refcount;
+
+	/** Handle count of this object. Each handle also holds a reference */
+	struct kref handlecount;
+
+	/** Related drm device */
+	struct drm_device *dev;
+
+	/** File representing the shmem storage */
+	struct file *filp;
+
+	/**
+	 * Size of the object, in bytes.  Immutable over the object's
+	 * lifetime.
+	 */
+	size_t size;
+
+	/**
+	 * Global name for this object, starts at 1. 0 means unnamed.
+	 * Access is covered by the object_name_lock in the related drm_device
+	 */
+	int name;
+
+	/**
+	 * Memory domains. These monitor which caches contain read/write data
+	 * related to the object. When transitioning from one set of domains
+	 * to another, the driver is called to ensure that caches are suitably
+	 * flushed and invalidated
+	 */
+	uint32_t read_domains;
+	uint32_t write_domain;
+
+	/**
+	 * While validating an exec operation, the
+	 * new read/write domain values are computed here.
+	 * They will be transferred to the above values
+	 * at the point that any cache flushing occurs
+	 */
+	uint32_t pending_read_domains;
+	uint32_t pending_write_domain;
+
+	void *driver_private;
+};
+
+/**
  * DRM driver structure. This structure represent the common code for
  * a family of cards. There will one drm_device for each card present
  * in this family
@@ -580,11 +635,54 @@
 	int (*kernel_context_switch) (struct drm_device *dev, int old,
 				      int new);
 	void (*kernel_context_switch_unlock) (struct drm_device *dev);
-	int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
-	int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
 	int (*dri_library_name) (struct drm_device *dev, char *buf);
 
 	/**
+	 * get_vblank_counter - get raw hardware vblank counter
+	 * @dev: DRM device
+	 * @crtc: counter to fetch
+	 *
+	 * Driver callback for fetching a raw hardware vblank counter
+	 * for @crtc.  If a device doesn't have a hardware counter, the
+	 * driver can simply return the value of drm_vblank_count and
+	 * make the enable_vblank() and disable_vblank() hooks into no-ops,
+	 * leaving interrupts enabled at all times.
+	 *
+	 * Wraparound handling and loss of events due to modesetting is dealt
+	 * with in the DRM core code.
+	 *
+	 * RETURNS
+	 * Raw vblank counter value.
+	 */
+	u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
+
+	/**
+	 * enable_vblank - enable vblank interrupt events
+	 * @dev: DRM device
+	 * @crtc: which irq to enable
+	 *
+	 * Enable vblank interrupts for @crtc.  If the device doesn't have
+	 * a hardware vblank counter, this routine should be a no-op, since
+	 * interrupts will have to stay on to keep the count accurate.
+	 *
+	 * RETURNS
+	 * Zero on success, appropriate errno if the given @crtc's vblank
+	 * interrupt cannot be enabled.
+	 */
+	int (*enable_vblank) (struct drm_device *dev, int crtc);
+
+	/**
+	 * disable_vblank - disable vblank interrupt events
+	 * @dev: DRM device
+	 * @crtc: which irq to enable
+	 *
+	 * Disable vblank interrupts for @crtc.  If the device doesn't have
+	 * a hardware vblank counter, this routine should be a no-op, since
+	 * interrupts will have to stay on to keep the count accurate.
+	 */
+	void (*disable_vblank) (struct drm_device *dev, int crtc);
+
+	/**
 	 * Called by \c drm_device_is_agp.  Typically used to determine if a
 	 * card is really attached to AGP or not.
 	 *
@@ -601,7 +699,7 @@
 
 	irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
 	void (*irq_preinstall) (struct drm_device *dev);
-	void (*irq_postinstall) (struct drm_device *dev);
+	int (*irq_postinstall) (struct drm_device *dev);
 	void (*irq_uninstall) (struct drm_device *dev);
 	void (*reclaim_buffers) (struct drm_device *dev,
 				 struct drm_file * file_priv);
@@ -614,6 +712,18 @@
 	void (*set_version) (struct drm_device *dev,
 			     struct drm_set_version *sv);
 
+	int (*proc_init)(struct drm_minor *minor);
+	void (*proc_cleanup)(struct drm_minor *minor);
+
+	/**
+	 * Driver-specific constructor for drm_gem_objects, to set up
+	 * obj->driver_private.
+	 *
+	 * Returns 0 on success.
+	 */
+	int (*gem_init_object) (struct drm_gem_object *obj);
+	void (*gem_free_object) (struct drm_gem_object *obj);
+
 	int major;
 	int minor;
 	int patchlevel;
@@ -714,7 +824,6 @@
 
 	/** \name Context support */
 	/*@{ */
-	int irq;			/**< Interrupt used by board */
 	int irq_enabled;		/**< True if irq handler is enabled */
 	__volatile__ long context_flag;	/**< Context swapping flag */
 	__volatile__ long interrupt_flag; /**< Interruption handler flag */
@@ -730,13 +839,28 @@
 	/** \name VBLANK IRQ support */
 	/*@{ */
 
-	wait_queue_head_t vbl_queue;	/**< VBLANK wait queue */
-	atomic_t vbl_received;
-	atomic_t vbl_received2;		/**< number of secondary VBLANK interrupts */
+	/*
+	 * At load time, disabling the vblank interrupt won't be allowed since
+	 * old clients may not call the modeset ioctl and therefore misbehave.
+	 * Once the modeset ioctl *has* been called though, we can safely
+	 * disable them when unused.
+	 */
+	int vblank_disable_allowed;
+
+	wait_queue_head_t *vbl_queue;   /**< VBLANK wait queue */
+	atomic_t *_vblank_count;        /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
 	spinlock_t vbl_lock;
-	struct list_head vbl_sigs;		/**< signal list to send on VBLANK */
-	struct list_head vbl_sigs2;	/**< signals to send on secondary VBLANK */
-	unsigned int vbl_pending;
+	struct list_head *vbl_sigs;	/**< signal list to send on VBLANK */
+	atomic_t vbl_signal_pending;    /* number of signals pending on all crtcs*/
+	atomic_t *vblank_refcount;      /* number of users of vblank interruptsper crtc */
+	u32 *last_vblank;               /* protected by dev->vbl_lock, used */
+					/* for wraparound handling */
+	int *vblank_enabled;            /* so we don't call enable more than
+					   once per disable */
+	int *vblank_inmodeset;          /* Display driver is setting mode */
+	struct timer_list vblank_disable_timer;
+
+	u32 max_vblank_count;           /**< size of vblank counter register */
 	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */
 	void (*locked_tasklet_func)(struct drm_device *dev);
 
@@ -757,6 +881,7 @@
 	struct pci_controller *hose;
 #endif
 	struct drm_sg_mem *sg;	/**< Scatter gather memory */
+	int num_crtcs;                  /**< Number of CRTCs on this device */
 	void *dev_private;		/**< device private data */
 	struct drm_sigdata sigdata;	   /**< For block_all_signals */
 	sigset_t sigmask;
@@ -771,8 +896,29 @@
 	spinlock_t drw_lock;
 	struct idr drw_idr;
 	/*@} */
+
+	/** \name GEM information */
+	/*@{ */
+	spinlock_t object_name_lock;
+	struct idr object_name_idr;
+	atomic_t object_count;
+	atomic_t object_memory;
+	atomic_t pin_count;
+	atomic_t pin_memory;
+	atomic_t gtt_count;
+	atomic_t gtt_memory;
+	uint32_t gtt_total;
+	uint32_t invalidate_domains;    /* domains pending invalidation */
+	uint32_t flush_domains;         /* domains pending flush */
+	/*@} */
+
 };
 
+static inline int drm_dev_to_irq(struct drm_device *dev)
+{
+	return dev->pdev->irq;
+}
+
 static __inline__ int drm_core_check_feature(struct drm_device *dev,
 					     int feature)
 {
@@ -867,6 +1013,11 @@
 extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
 extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
 extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
+extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+				       struct page **pages,
+				       unsigned long num_pages,
+				       uint32_t gtt_offset,
+				       uint32_t type);
 extern int drm_unbind_agp(DRM_AGP_MEM * handle);
 
 				/* Misc. IOCTL support (drm_ioctl.h) */
@@ -929,6 +1080,9 @@
 extern int drm_authmagic(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 
+/* Cache management (drm_cache.c) */
+void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
+
 				/* Locking IOCTL support (drm_lock.h) */
 extern int drm_lock(struct drm_device *dev, void *data,
 		    struct drm_file *file_priv);
@@ -985,15 +1139,25 @@
 extern int drm_control(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv);
 extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
+extern int drm_irq_install(struct drm_device *dev);
 extern int drm_irq_uninstall(struct drm_device *dev);
 extern void drm_driver_irq_preinstall(struct drm_device *dev);
 extern void drm_driver_irq_postinstall(struct drm_device *dev);
 extern void drm_driver_irq_uninstall(struct drm_device *dev);
 
+extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
 extern int drm_wait_vblank(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv);
+			   struct drm_file *filp);
 extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals(struct drm_device *dev);
+extern void drm_locked_tasklet(struct drm_device *dev,
+			       void(*func)(struct drm_device *));
+extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
+extern void drm_handle_vblank(struct drm_device *dev, int crtc);
+extern int drm_vblank_get(struct drm_device *dev, int crtc);
+extern void drm_vblank_put(struct drm_device *dev, int crtc);
+/* Modesetting support */
+extern int drm_modeset_ctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
 extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
 
 				/* AGP/GART support (drm_agpsupport.h) */
@@ -1026,6 +1190,7 @@
 extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
 extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
 extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
+extern void drm_agp_chipset_flush(struct drm_device *dev);
 
 				/* Stub support (drm_stub.h) */
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
@@ -1088,6 +1253,66 @@
 extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
 extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
 
+/* Graphics Execution Manager library functions (drm_gem.c) */
+int drm_gem_init(struct drm_device *dev);
+void drm_gem_object_free(struct kref *kref);
+struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
+					    size_t size);
+void drm_gem_object_handle_free(struct kref *kref);
+
+static inline void
+drm_gem_object_reference(struct drm_gem_object *obj)
+{
+	kref_get(&obj->refcount);
+}
+
+static inline void
+drm_gem_object_unreference(struct drm_gem_object *obj)
+{
+	if (obj == NULL)
+		return;
+
+	kref_put(&obj->refcount, drm_gem_object_free);
+}
+
+int drm_gem_handle_create(struct drm_file *file_priv,
+			  struct drm_gem_object *obj,
+			  int *handlep);
+
+static inline void
+drm_gem_object_handle_reference(struct drm_gem_object *obj)
+{
+	drm_gem_object_reference(obj);
+	kref_get(&obj->handlecount);
+}
+
+static inline void
+drm_gem_object_handle_unreference(struct drm_gem_object *obj)
+{
+	if (obj == NULL)
+		return;
+
+	/*
+	 * Must bump handle count first as this may be the last
+	 * ref, in which case the object would disappear before we
+	 * checked for a name
+	 */
+	kref_put(&obj->handlecount, drm_gem_object_handle_free);
+	drm_gem_object_unreference(obj);
+}
+
+struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
+					     struct drm_file *filp,
+					     int handle);
+int drm_gem_close_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int drm_gem_open_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
+void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
+
 extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
 extern void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev);
 extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 135bd19..da04109 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -84,18 +84,18 @@
 	{0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -113,8 +113,10 @@
 	{0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-	{0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-	{0x1002, 0x5a62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5a41, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART}, \
+	{0x1002, 0x5a62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
 	{0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
@@ -122,16 +124,16 @@
 	{0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
-	{0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-	{0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
@@ -237,6 +239,10 @@
 	{0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
 	{0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
+	{0x1002, 0x796c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
+	{0x1002, 0x796d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
+	{0x1002, 0x796e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
+	{0x1002, 0x796f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
 	{0, 0, 0}
 
 #define r128_PCI_IDS \
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 05c66cf..eb4b350 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -143,6 +143,22 @@
 #define DRM_I915_GET_VBLANK_PIPE	0x0e
 #define DRM_I915_VBLANK_SWAP	0x0f
 #define DRM_I915_HWS_ADDR	0x11
+#define DRM_I915_GEM_INIT	0x13
+#define DRM_I915_GEM_EXECBUFFER	0x14
+#define DRM_I915_GEM_PIN	0x15
+#define DRM_I915_GEM_UNPIN	0x16
+#define DRM_I915_GEM_BUSY	0x17
+#define DRM_I915_GEM_THROTTLE	0x18
+#define DRM_I915_GEM_ENTERVT	0x19
+#define DRM_I915_GEM_LEAVEVT	0x1a
+#define DRM_I915_GEM_CREATE	0x1b
+#define DRM_I915_GEM_PREAD	0x1c
+#define DRM_I915_GEM_PWRITE	0x1d
+#define DRM_I915_GEM_MMAP	0x1e
+#define DRM_I915_GEM_SET_DOMAIN	0x1f
+#define DRM_I915_GEM_SW_FINISH	0x20
+#define DRM_I915_GEM_SET_TILING	0x21
+#define DRM_I915_GEM_GET_TILING	0x22
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -160,6 +176,20 @@
 #define DRM_IOCTL_I915_SET_VBLANK_PIPE	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_GET_VBLANK_PIPE	DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_VBLANK_SWAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
+#define DRM_IOCTL_I915_GEM_PIN		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
+#define DRM_IOCTL_I915_GEM_UNPIN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
+#define DRM_IOCTL_I915_GEM_BUSY		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
+#define DRM_IOCTL_I915_GEM_THROTTLE	DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
+#define DRM_IOCTL_I915_GEM_ENTERVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
+#define DRM_IOCTL_I915_GEM_LEAVEVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
+#define DRM_IOCTL_I915_GEM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
+#define DRM_IOCTL_I915_GEM_PREAD	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
+#define DRM_IOCTL_I915_GEM_PWRITE	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
+#define DRM_IOCTL_I915_GEM_MMAP		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
+#define DRM_IOCTL_I915_GEM_SET_DOMAIN	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
+#define DRM_IOCTL_I915_GEM_SW_FINISH	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
+#define DRM_IOCTL_I915_GEM_SET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
+#define DRM_IOCTL_I915_GEM_GET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -200,6 +230,8 @@
 #define I915_PARAM_IRQ_ACTIVE            1
 #define I915_PARAM_ALLOW_BATCHBUFFER     2
 #define I915_PARAM_LAST_DISPATCH         3
+#define I915_PARAM_CHIPSET_ID            4
+#define I915_PARAM_HAS_GEM               5
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -267,4 +299,305 @@
 	uint64_t addr;
 } drm_i915_hws_addr_t;
 
+struct drm_i915_gem_init {
+	/**
+	 * Beginning offset in the GTT to be managed by the DRM memory
+	 * manager.
+	 */
+	uint64_t gtt_start;
+	/**
+	 * Ending offset in the GTT to be managed by the DRM memory
+	 * manager.
+	 */
+	uint64_t gtt_end;
+};
+
+struct drm_i915_gem_create {
+	/**
+	 * Requested size for the object.
+	 *
+	 * The (page-aligned) allocated size for the object will be returned.
+	 */
+	uint64_t size;
+	/**
+	 * Returned handle for the object.
+	 *
+	 * Object handles are nonzero.
+	 */
+	uint32_t handle;
+	uint32_t pad;
+};
+
+struct drm_i915_gem_pread {
+	/** Handle for the object being read. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to read from */
+	uint64_t offset;
+	/** Length of data to read */
+	uint64_t size;
+	/**
+	 * Pointer to write the data into.
+	 *
+	 * This is a fixed-size type for 32/64 compatibility.
+	 */
+	uint64_t data_ptr;
+};
+
+struct drm_i915_gem_pwrite {
+	/** Handle for the object being written to. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to write to */
+	uint64_t offset;
+	/** Length of data to write */
+	uint64_t size;
+	/**
+	 * Pointer to read the data from.
+	 *
+	 * This is a fixed-size type for 32/64 compatibility.
+	 */
+	uint64_t data_ptr;
+};
+
+struct drm_i915_gem_mmap {
+	/** Handle for the object being mapped. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset in the object to map. */
+	uint64_t offset;
+	/**
+	 * Length of data to map.
+	 *
+	 * The value will be page-aligned.
+	 */
+	uint64_t size;
+	/**
+	 * Returned pointer the data was mapped at.
+	 *
+	 * This is a fixed-size type for 32/64 compatibility.
+	 */
+	uint64_t addr_ptr;
+};
+
+struct drm_i915_gem_set_domain {
+	/** Handle for the object */
+	uint32_t handle;
+
+	/** New read domains */
+	uint32_t read_domains;
+
+	/** New write domain */
+	uint32_t write_domain;
+};
+
+struct drm_i915_gem_sw_finish {
+	/** Handle for the object */
+	uint32_t handle;
+};
+
+struct drm_i915_gem_relocation_entry {
+	/**
+	 * Handle of the buffer being pointed to by this relocation entry.
+	 *
+	 * It's appealing to make this be an index into the mm_validate_entry
+	 * list to refer to the buffer, but this allows the driver to create
+	 * a relocation list for state buffers and not re-write it per
+	 * exec using the buffer.
+	 */
+	uint32_t target_handle;
+
+	/**
+	 * Value to be added to the offset of the target buffer to make up
+	 * the relocation entry.
+	 */
+	uint32_t delta;
+
+	/** Offset in the buffer the relocation entry will be written into */
+	uint64_t offset;
+
+	/**
+	 * Offset value of the target buffer that the relocation entry was last
+	 * written as.
+	 *
+	 * If the buffer has the same offset as last time, we can skip syncing
+	 * and writing the relocation.  This value is written back out by
+	 * the execbuffer ioctl when the relocation is written.
+	 */
+	uint64_t presumed_offset;
+
+	/**
+	 * Target memory domains read by this operation.
+	 */
+	uint32_t read_domains;
+
+	/**
+	 * Target memory domains written by this operation.
+	 *
+	 * Note that only one domain may be written by the whole
+	 * execbuffer operation, so that where there are conflicts,
+	 * the application will get -EINVAL back.
+	 */
+	uint32_t write_domain;
+};
+
+/** @{
+ * Intel memory domains
+ *
+ * Most of these just align with the various caches in
+ * the system and are used to flush and invalidate as
+ * objects end up cached in different domains.
+ */
+/** CPU cache */
+#define I915_GEM_DOMAIN_CPU		0x00000001
+/** Render cache, used by 2D and 3D drawing */
+#define I915_GEM_DOMAIN_RENDER		0x00000002
+/** Sampler cache, used by texture engine */
+#define I915_GEM_DOMAIN_SAMPLER		0x00000004
+/** Command queue, used to load batch buffers */
+#define I915_GEM_DOMAIN_COMMAND		0x00000008
+/** Instruction cache, used by shader programs */
+#define I915_GEM_DOMAIN_INSTRUCTION	0x00000010
+/** Vertex address cache */
+#define I915_GEM_DOMAIN_VERTEX		0x00000020
+/** GTT domain - aperture and scanout */
+#define I915_GEM_DOMAIN_GTT		0x00000040
+/** @} */
+
+struct drm_i915_gem_exec_object {
+	/**
+	 * User's handle for a buffer to be bound into the GTT for this
+	 * operation.
+	 */
+	uint32_t handle;
+
+	/** Number of relocations to be performed on this buffer */
+	uint32_t relocation_count;
+	/**
+	 * Pointer to array of struct drm_i915_gem_relocation_entry containing
+	 * the relocations to be performed in this buffer.
+	 */
+	uint64_t relocs_ptr;
+
+	/** Required alignment in graphics aperture */
+	uint64_t alignment;
+
+	/**
+	 * Returned value of the updated offset of the object, for future
+	 * presumed_offset writes.
+	 */
+	uint64_t offset;
+};
+
+struct drm_i915_gem_execbuffer {
+	/**
+	 * List of buffers to be validated with their relocations to be
+	 * performend on them.
+	 *
+	 * This is a pointer to an array of struct drm_i915_gem_validate_entry.
+	 *
+	 * These buffers must be listed in an order such that all relocations
+	 * a buffer is performing refer to buffers that have already appeared
+	 * in the validate list.
+	 */
+	uint64_t buffers_ptr;
+	uint32_t buffer_count;
+
+	/** Offset in the batchbuffer to start execution from. */
+	uint32_t batch_start_offset;
+	/** Bytes used in batchbuffer from batch_start_offset */
+	uint32_t batch_len;
+	uint32_t DR1;
+	uint32_t DR4;
+	uint32_t num_cliprects;
+	/** This is a struct drm_clip_rect *cliprects */
+	uint64_t cliprects_ptr;
+};
+
+struct drm_i915_gem_pin {
+	/** Handle of the buffer to be pinned. */
+	uint32_t handle;
+	uint32_t pad;
+
+	/** alignment required within the aperture */
+	uint64_t alignment;
+
+	/** Returned GTT offset of the buffer. */
+	uint64_t offset;
+};
+
+struct drm_i915_gem_unpin {
+	/** Handle of the buffer to be unpinned. */
+	uint32_t handle;
+	uint32_t pad;
+};
+
+struct drm_i915_gem_busy {
+	/** Handle of the buffer to check for busy */
+	uint32_t handle;
+
+	/** Return busy status (1 if busy, 0 if idle) */
+	uint32_t busy;
+};
+
+#define I915_TILING_NONE	0
+#define I915_TILING_X		1
+#define I915_TILING_Y		2
+
+#define I915_BIT_6_SWIZZLE_NONE		0
+#define I915_BIT_6_SWIZZLE_9		1
+#define I915_BIT_6_SWIZZLE_9_10		2
+#define I915_BIT_6_SWIZZLE_9_11		3
+#define I915_BIT_6_SWIZZLE_9_10_11	4
+/* Not seen by userland */
+#define I915_BIT_6_SWIZZLE_UNKNOWN	5
+
+struct drm_i915_gem_set_tiling {
+	/** Handle of the buffer to have its tiling state updated */
+	uint32_t handle;
+
+	/**
+	 * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
+	 * I915_TILING_Y).
+	 *
+	 * This value is to be set on request, and will be updated by the
+	 * kernel on successful return with the actual chosen tiling layout.
+	 *
+	 * The tiling mode may be demoted to I915_TILING_NONE when the system
+	 * has bit 6 swizzling that can't be managed correctly by GEM.
+	 *
+	 * Buffer contents become undefined when changing tiling_mode.
+	 */
+	uint32_t tiling_mode;
+
+	/**
+	 * Stride in bytes for the object when in I915_TILING_X or
+	 * I915_TILING_Y.
+	 */
+	uint32_t stride;
+
+	/**
+	 * Returned address bit 6 swizzling required for CPU access through
+	 * mmap mapping.
+	 */
+	uint32_t swizzle_mode;
+};
+
+struct drm_i915_gem_get_tiling {
+	/** Handle of the buffer to get tiling state for. */
+	uint32_t handle;
+
+	/**
+	 * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
+	 * I915_TILING_Y).
+	 */
+	uint32_t tiling_mode;
+
+	/**
+	 * Returned address bit 6 swizzling required for CPU access through
+	 * mmap mapping.
+	 */
+	uint32_t swizzle_mode;
+};
+
 #endif				/* _I915_DRM_H_ */
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h
index 6e4ace2..79a8ed8 100644
--- a/include/linux/dvb/frontend.h
+++ b/include/linux/dvb/frontend.h
@@ -166,6 +166,7 @@
 	VSB_16,
 	PSK_8,
 	APSK_16,
+	APSK_32,
 	DQPSK,
 } fe_modulation_t;
 
@@ -295,6 +296,7 @@
 	SYS_DVBC_ANNEX_AC,
 	SYS_DVBC_ANNEX_B,
 	SYS_DVBT,
+	SYS_DSS,
 	SYS_DVBS,
 	SYS_DVBS2,
 	SYS_DVBH,
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 493435b..01d67ba 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -60,7 +60,7 @@
 #define I2C_DRIVERID_WM8775	69	/* wm8775 audio processor	*/
 #define I2C_DRIVERID_CS53L32A	70	/* cs53l32a audio processor	*/
 #define I2C_DRIVERID_CX25840	71	/* cx2584x video encoder	*/
-#define I2C_DRIVERID_SAA7127	72	/* saa7124 video encoder	*/
+#define I2C_DRIVERID_SAA7127	72	/* saa7127 video encoder	*/
 #define I2C_DRIVERID_SAA711X	73	/* saa711x video encoders	*/
 #define I2C_DRIVERID_AKITAIOEXP	74	/* IO Expander on Sharp SL-C1000 */
 #define I2C_DRIVERID_INFRARED	75	/* I2C InfraRed on Video boards */
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 463d6f1..c7d106e 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -641,6 +641,11 @@
 	 */
 	int t_handle_count;
 
+	/*
+	 * For use by the filesystem to store fs-specific data
+	 * structures associated with the transaction
+	 */
+	struct list_head	t_private_list;
 };
 
 struct transaction_run_stats_s {
@@ -935,6 +940,10 @@
 
 	pid_t			j_last_sync_writer;
 
+	/* This function is called when a transaction is closed */
+	void			(*j_commit_callback)(journal_t *,
+						     transaction_t *);
+
 	/*
 	 * Journal statistics
 	 */
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 12b15c5..e585657 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -63,7 +63,15 @@
 	unsigned for_writepages:1;	/* This is a writepages() call */
 	unsigned range_cyclic:1;	/* range_start is cyclic */
 	unsigned more_io:1;		/* more io to be dispatched */
-	unsigned range_cont:1;
+	/*
+	 * write_cache_pages() won't update wbc->nr_to_write and
+	 * mapping->writeback_index if no_nrwrite_index_update
+	 * is set.  write_cache_pages() may write more than we
+	 * requested and we want to make sure nr_to_write and
+	 * writeback_index are updated in a consistent manner
+	 * so we use a single control to update them
+	 */
+	unsigned no_nrwrite_index_update:1;
 };
 
 /*
diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h
index 851f182..1d092b4 100644
--- a/include/media/soc_camera_platform.h
+++ b/include/media/soc_camera_platform.h
@@ -1,3 +1,13 @@
+/*
+ * Generic Platform Camera Driver Header
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #ifndef __SOC_CAMERA_H__
 #define __SOC_CAMERA_H__
 
@@ -9,6 +19,7 @@
 	unsigned long format_depth;
 	struct v4l2_pix_format format;
 	unsigned long bus_param;
+	void (*power)(int);
 	int (*set_capture)(struct soc_camera_platform_info *info, int enable);
 };
 
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 67c1f51..7d4e2db 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -123,6 +123,7 @@
 #define TUNER_TEA5761			75	/* Only FM Radio Tuner */
 #define TUNER_XC5000			76	/* Xceive Silicon Tuner */
 #define TUNER_TCL_MF02GIP_5N		77	/* TCL MF02GIP_5N */
+#define TUNER_PHILIPS_FMD1216MEX_MK3	78
 
 /* tv card specific */
 #define TDA9887_PRESENT 		(1<<0)
diff --git a/include/media/v4l2-i2c-drv-legacy.h b/include/media/v4l2-i2c-drv-legacy.h
index 975ffbf..e65dd9d 100644
--- a/include/media/v4l2-i2c-drv-legacy.h
+++ b/include/media/v4l2-i2c-drv-legacy.h
@@ -21,6 +21,17 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* NOTE: the full version of this header is in the v4l-dvb repository
+ * and allows v4l i2c drivers to be compiled on older kernels as well.
+ * The version of this header as it appears in the kernel is a stripped
+ * version (without all the backwards compatibility stuff) and so it
+ * looks a bit odd.
+ *
+ * If you look at the full version then you will understand the reason
+ * for introducing this header since you really don't want to have all
+ * the tricky backwards compatibility code in each and every i2c driver.
+ */
+
 struct v4l2_i2c_driver_data {
 	const char * const name;
 	int driverid;
diff --git a/include/media/v4l2-i2c-drv.h b/include/media/v4l2-i2c-drv.h
index 40ecef2..efdc8bf 100644
--- a/include/media/v4l2-i2c-drv.h
+++ b/include/media/v4l2-i2c-drv.h
@@ -21,6 +21,17 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* NOTE: the full version of this header is in the v4l-dvb repository
+ * and allows v4l i2c drivers to be compiled on older kernels as well.
+ * The version of this header as it appears in the kernel is a stripped
+ * version (without all the backwards compatibility stuff) and so it
+ * looks a bit odd.
+ *
+ * If you look at the full version then you will understand the reason
+ * for introducing this header since you really don't want to have all
+ * the tricky backwards compatibility code in each and every i2c driver.
+ */
+
 #ifndef __V4L2_I2C_DRV_H__
 #define __V4L2_I2C_DRV_H__
 
diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h
index b777486..80471c2 100644
--- a/include/media/videobuf-dvb.h
+++ b/include/media/videobuf-dvb.h
@@ -16,7 +16,6 @@
 	int                        nfeeds;
 
 	/* videobuf_dvb_(un)register manges this */
-	struct dvb_adapter         adapter;
 	struct dvb_demux           demux;
 	struct dmxdev              dmxdev;
 	struct dmx_frontend        fe_hw;
@@ -24,12 +23,34 @@
 	struct dvb_net             net;
 };
 
-int videobuf_dvb_register(struct videobuf_dvb *dvb,
+struct videobuf_dvb_frontend {
+	struct list_head felist;
+	int id;
+	struct videobuf_dvb dvb;
+};
+
+struct videobuf_dvb_frontends {
+	struct list_head felist;
+	struct mutex lock;
+	struct dvb_adapter adapter;
+	int active_fe_id; /* Indicates which frontend in the felist is in use */
+	int gate; /* Frontend with gate control 0=!MFE,1=fe0,2=fe1 etc */
+};
+
+int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
 			  struct module *module,
 			  void *adapter_priv,
 			  struct device *device,
-			  short *adapter_nr);
-void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
+			  short *adapter_nr,
+			  int mfe_shared);
+
+void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f);
+
+struct videobuf_dvb_frontend * videobuf_dvb_alloc_frontend(struct videobuf_dvb_frontends *f, int id);
+
+struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id);
+int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p);
+
 
 /*
  * Local variables:
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index c130a13..b40f6d5 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -876,6 +876,7 @@
 	pgoff_t end;		/* Inclusive */
 	int scanned = 0;
 	int range_whole = 0;
+	long nr_to_write = wbc->nr_to_write;
 
 	if (wbc->nonblocking && bdi_write_congested(bdi)) {
 		wbc->encountered_congestion = 1;
@@ -939,7 +940,7 @@
 				unlock_page(page);
 				ret = 0;
 			}
-			if (ret || (--(wbc->nr_to_write) <= 0))
+			if (ret || (--nr_to_write <= 0))
 				done = 1;
 			if (wbc->nonblocking && bdi_write_congested(bdi)) {
 				wbc->encountered_congestion = 1;
@@ -958,11 +959,12 @@
 		index = 0;
 		goto retry;
 	}
-	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
-		mapping->writeback_index = index;
+	if (!wbc->no_nrwrite_index_update) {
+		if (wbc->range_cyclic || (range_whole && nr_to_write > 0))
+			mapping->writeback_index = index;
+		wbc->nr_to_write = nr_to_write;
+	}
 
-	if (wbc->range_cont)
-		wbc->range_start = index << PAGE_CACHE_SHIFT;
 	return ret;
 }
 EXPORT_SYMBOL(write_cache_pages);
diff --git a/mm/shmem.c b/mm/shmem.c
index bf66d01..d87958a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2580,6 +2580,7 @@
 	shmem_unacct_size(flags, size);
 	return ERR_PTR(error);
 }
+EXPORT_SYMBOL_GPL(shmem_file_setup);
 
 /**
  * shmem_zero_setup - setup a shared anonymous mapping