diff mbox

[RFC,21/21] DRM: Add VIA drm driver

Message ID alpine.LFD.2.03.1306081756530.18671@infradead.org (mailing list archive)
State New, archived
Headers show

Commit Message

James Simmons June 8, 2013, 4:57 p.m. UTC
commit f4101ca539b83c824747d657bbdc28834276fea8
Author: James Simmons <jsimmons@infradead.org>
Date:   Sat Jun 8 12:28:13 2013 -0400

    via: Piece all the TTM/KMS changes together.
    
    This updates the core VIA drm driver to support KMS/TTM/GEM. This includes
    setting up the graphics cards resources and enabling the dumb scanout api.
    
    Signed-Off-by: James Simmons <jsimmons@infradead.org>
diff mbox

Patch

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index b16c50e..b773b42 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -188,6 +188,11 @@  config DRM_SIS
 config DRM_VIA
 	tristate "Via unichrome video cards"
 	depends on DRM && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select DRM_KMS_HELPER
+	select DRM_TTM
 	help
 	  Choose this option if you have a Via unichrome or compatible video
 	  chipset. If M is selected the module will be called via.
diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile
index b537e4b..a0479bb 100644
--- a/drivers/gpu/drm/via/Makefile
+++ b/drivers/gpu/drm/via/Makefile
@@ -3,6 +3,10 @@ 
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 ccflags-y := -Iinclude/drm
-via-y    := via_irq.o via_drv.o via_map.o via_mm.o via_h1_cmdbuf.o via_verifier.o via_video.o via_h1_dma.o
+via-y    := via_drv.o via_pm.o via_i2c.o via_irq.o via_verifier.o via_ioc32.o \
+		init_ttm.o ttm_gem.o via_ttm.o via_fence.o via_sgdma.o \
+		via_h1_dma.o via_h1_cmdbuf.o \
+		via_display.o via_crtc.o via_fb.o crtc_hw.o via_clocks.o \
+		via_analog.o via_lvds.o via_tmds.o via_hdmi.o
 
-obj-$(CONFIG_DRM_VIA)	+=via.o
+obj-$(CONFIG_DRM_VIA)	+= via.o
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index f4ae203..2a8592b 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -16,72 +16,436 @@ 
  * 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
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) 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/module.h>
 
 #include <drm/drmP.h>
 #include <drm/via_drm.h>
+#include <drm/drm_pciids.h>
+
 #include "via_drv.h"
 
-#include <drm/drm_pciids.h>
+int via_modeset = 0;
+
+MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
+module_param_named(modeset, via_modeset, int, 0400);
+
+int via_hdmi_audio = 0;
+
+MODULE_PARM_DESC(audio, "HDMI Audio enable (1 = enable)");
+module_param_named(audio, via_hdmi_audio, int, 0444);
 
-static int via_driver_open(struct drm_device *dev, struct drm_file *file)
+static struct pci_device_id via_pci_table[] = {
+	viadrv_PCI_IDS,
+};
+MODULE_DEVICE_TABLE(pci, via_pci_table);
+
+#define SGDMA_MEMORY (256*1024)
+#define VQ_MEMORY (256*1024)
+
+#if __OS_HAS_AGP
+
+#define VIA_AGP_MODE_MASK	0x17
+#define VIA_AGPV3_MODE		0x08
+#define VIA_AGPV3_8X_MODE	0x02
+#define VIA_AGPV3_4X_MODE	0x01
+#define VIA_AGP_4X_MODE		0x04
+#define VIA_AGP_2X_MODE		0x02
+#define VIA_AGP_1X_MODE		0x01
+#define VIA_AGP_FW_MODE		0x10
+
+static int
+via_detect_agp(struct drm_device *dev)
 {
-	struct via_file_private *file_priv;
+	struct drm_via_private *dev_priv = dev->dev_private;
+	struct drm_agp_info agp_info;
+	struct drm_agp_mode mode;
+	int ret = 0;
 
-	DRM_DEBUG_DRIVER("\n");
-	file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
-	if (!file_priv)
-		return -ENOMEM;
+	ret = drm_agp_acquire(dev);
+	if (ret) {
+		DRM_ERROR("Failed acquiring AGP device.\n");
+		return ret;
+	}
+
+	ret = drm_agp_info(dev, &agp_info);
+	if (ret) {
+		DRM_ERROR("Failed detecting AGP aperture size.\n");
+		goto out_err0;
+	}
+
+	mode.mode = agp_info.mode & ~VIA_AGP_MODE_MASK;
+	if (mode.mode & VIA_AGPV3_MODE)
+		mode.mode |= VIA_AGPV3_8X_MODE;
+	else
+		mode.mode |= VIA_AGP_4X_MODE;
+
+	mode.mode |= VIA_AGP_FW_MODE;
+	ret = drm_agp_enable(dev, mode);
+	if (ret) {
+		DRM_ERROR("Failed to enable the AGP bus.\n");
+		goto out_err0;
+	}
+
+	ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_TT, agp_info.aperture_size >> PAGE_SHIFT);
+	if (!ret) {
+		DRM_INFO("Detected %lu MB of AGP Aperture at "
+			"physical address 0x%08lx.\n",
+			agp_info.aperture_size >> 20,
+			agp_info.aperture_base);
+	} else {
+out_err0:
+		drm_agp_release(dev);
+	}
+	return ret;
+}
+
+static void via_agp_engine_init(struct drm_via_private *dev_priv)
+{
+	VIA_WRITE(VIA_REG_TRANSET, 0x00100000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x00000000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x00333004);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x60000000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x61000000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x62000000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x63000000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x64000000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x7D000000);
+
+	VIA_WRITE(VIA_REG_TRANSET, 0xfe020000);
+	VIA_WRITE(VIA_REG_TRANSPACE, 0x00000000);
+}
+#endif
+
+static int
+via_mmio_setup(struct drm_device *dev)
+{
+	struct drm_via_private *dev_priv = dev->dev_private;
+	int ret, len = pci_resource_len(dev->pdev, 1);
+	void __iomem *regs = ioport_map(0x3c0, 100);
+	struct ttm_buffer_object *bo;
+	u8 val;
+
+	val = ioread8(regs + 0x03);
+	iowrite8(val | 0x1, regs + 0x03);
+	val = ioread8(regs + 0x0C);
+	iowrite8(val | 0x1, regs + 0x02);
+
+	/* Unlock Extended IO Space */
+	iowrite8(0x10, regs + 0x04);
+	iowrite8(0x01, regs + 0x05);
+	/* Unlock CRTC register protect */
+	iowrite8(0x47, regs + 0x14);
 
-	file->driver_priv = file_priv;
+	/* Enable MMIO */
+	iowrite8(0x1a, regs + 0x04);
+	val = ioread8(regs + 0x05);
+	iowrite8(val | 0x38, regs + 0x05);
 
-	INIT_LIST_HEAD(&file_priv->obj_list);
+	ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_PRIV0,
+				len >> PAGE_SHIFT);
+	if (ret)
+		return ret;
 
+	ret = ttm_bo_allocate(&dev_priv->bdev, VIA_MMIO_REGSIZE, ttm_bo_type_kernel,
+				TTM_PL_FLAG_PRIV0, 1, PAGE_SIZE, false, NULL,
+				NULL, &bo);
+	if (ret)
+		goto err;
+
+	ret = ttm_bo_pin(bo, &dev_priv->mmio);
+err:
+	if (!ret)
+		DRM_INFO("Detected MMIO at physical address 0x%08llx.\n",
+			(unsigned long long) pci_resource_start(dev->pdev, 1));
+	else
+		ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_PRIV0);
+	return ret;
+}
+
+static void
+chip_revision_info(struct drm_device *dev)
+{
+	struct drm_via_private *dev_priv = dev->dev_private;
+	u8 tmp;
+
+	switch (dev->pci_device) {
+	/* Check revision of CLE266 Chip */
+	case PCI_DEVICE_ID_VIA_CLE266:
+		/* CR4F only define in CLE266.CX chip */
+		tmp = vga_rcrt(VGABASE, 0x4F);
+		vga_wcrt(VGABASE, 0x4F, 0x55);
+		if (vga_rcrt(VGABASE, 0x4F) != 0x55)
+			dev_priv->revision = CLE266_REVISION_AX;
+		else
+			dev_priv->revision = CLE266_REVISION_CX;
+		/* restore orignal CR4F value */
+		vga_wcrt(VGABASE, 0x4F, tmp);
+		break;
+
+	case PCI_DEVICE_ID_VIA_VT3157:
+		tmp = vga_rseq(VGABASE, 0x43);
+		if (tmp & 0x02) {
+			dev_priv->revision = CX700_REVISION_700M2;
+		} else if (tmp & 0x40) {
+			dev_priv->revision = CX700_REVISION_700M;
+		} else {
+			dev_priv->revision = CX700_REVISION_700;
+		}
+		break;
+
+	case PCI_DEVICE_ID_VIA_VT1122:
+	case PCI_DEVICE_ID_VIA_VX875:
+	case PCI_DEVICE_ID_VIA_VX900:
+		dev_priv->revision = vga_rseq(VGABASE, 0x3B);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int via_dumb_create(struct drm_file *filp, struct drm_device *dev,
+				struct drm_mode_create_dumb *args)
+{
+	struct drm_via_private *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	int ret;
+
+	args->pitch = round_up(args->width * (args->bpp >> 3), 16);
+	args->size = args->pitch * args->height;
+	obj = ttm_gem_create(dev, &dev_priv->bdev, TTM_PL_FLAG_VRAM,
+				false, 16, PAGE_SIZE, args->size);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	ret = drm_gem_handle_create(filp, obj, &args->handle);
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(obj);
+	return ret;
+}
+
+static int via_dumb_mmap(struct drm_file *filp, struct drm_device *dev,
+			uint32_t handle, uint64_t *offset_p)
+{
+	struct ttm_buffer_object *bo;
+	struct drm_gem_object *obj;
+
+	obj = drm_gem_object_lookup(dev, filp, handle);
+	if (!obj || !obj->driver_private)
+		return -ENOENT;
+
+	bo = obj->driver_private;
+	*offset_p = bo->addr_space_offset;
+	drm_gem_object_unreference_unlocked(obj);
 	return 0;
 }
 
-void via_driver_postclose(struct drm_device *dev, struct drm_file *file)
+static int gem_dumb_destroy(struct drm_file *filp, struct drm_device *dev,
+				uint32_t handle)
+{
+	return drm_gem_handle_delete(filp, handle);
+}
+
+static int via_driver_unload(struct drm_device *dev)
 {
-	struct via_file_private *file_priv = file->driver_priv;
+	struct drm_via_private *dev_priv = dev->dev_private;
+	struct ttm_buffer_object *bo;
+	int ret = 0;
+
+	ret = via_dma_cleanup(dev);
+	if (ret)
+		return ret;
+
+	drm_irq_uninstall(dev);
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		via_modeset_fini(dev);
+
+	via_fence_pool_fini(dev_priv->dma_fences);
+
+	drm_vblank_cleanup(dev);
+
+	/* destroy work queue. */
+	if (dev_priv->wq)
+		destroy_workqueue(dev_priv->wq);
 
-	kfree(file_priv);
+	bo = dev_priv->vq.bo;
+	if (bo) {
+		ttm_bo_unpin(bo, &dev_priv->vq);
+		ttm_bo_unref(&bo);
+	}
+
+	bo = dev_priv->gart.bo;
+	if (bo) {
+		/* enable gtt write */
+		if (pci_is_pcie(dev->pdev))
+			svga_wseq_mask(VGABASE, 0x6C, 0, BIT(7));
+		ttm_bo_unpin(bo, &dev_priv->gart);
+		ttm_bo_unref(&bo);
+	}
+
+	bo = dev_priv->mmio.bo;
+	if (bo) {
+		ttm_bo_unpin(bo, &dev_priv->mmio);
+		ttm_bo_unref(&bo);
+	}
+
+	/* mtrr delete the vram */
+	if (drm_core_has_MTRR(dev) && (dev_priv->vram_mtrr >= 0))
+        arch_phys_wc_del(dev_priv->vram_mtrr);
+
+	ttm_global_fini(&dev_priv->mem_global_ref,
+			&dev_priv->bo_global_ref,
+			&dev_priv->bdev);
+
+#if __OS_HAS_AGP
+	if (dev->agp && dev->agp->acquired)
+		drm_agp_release(dev);
+#endif
+	kfree(dev_priv);
+	return ret;
 }
 
-static struct pci_device_id pciidlist[] = {
-	viadrv_PCI_IDS
-};
+static int
+via_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+	struct drm_via_private *dev_priv;
+	int ret = 0;
+
+	dev_priv = kzalloc(sizeof(struct drm_via_private), GFP_KERNEL);
+	if (dev_priv == NULL)
+		return -ENOMEM;
+
+	dev->dev_private = (void *)dev_priv;
+	dev_priv->engine_type = chipset;
+	dev_priv->vram_mtrr = -ENXIO;
+	dev_priv->dev = dev;
+
+	via_init_command_verifier();
+
+	ret = via_ttm_init(dev_priv);
+	if (ret)
+		goto out_err;
+
+	ret = via_detect_vram(dev);
+	if (ret)
+		goto out_err;
+
+	ret = via_mmio_setup(dev);
+	if (ret) {
+		DRM_INFO("VIA MMIO region failed to map\n");
+		goto out_err;
+	}
+
+	chip_revision_info(dev);
+
+#if __OS_HAS_AGP
+	if ((dev_priv->engine_type > VIA_ENG_H2) ||
+	    (dev->agp && drm_pci_device_is_agp(dev))) {
+		ret = via_detect_agp(dev);
+		if (!ret)
+			via_agp_engine_init(dev_priv);
+		else
+			DRM_ERROR("Failed to allocate AGP\n");
+	}
+#endif
+	if (pci_is_pcie(dev->pdev)) {
+		/* allocate the gart table */
+		ret = ttm_allocate_kernel_buffer(&dev_priv->bdev, SGDMA_MEMORY,
+						16, TTM_PL_FLAG_VRAM,
+						&dev_priv->gart);
+		if (likely(!ret)) {
+			DRM_INFO("Allocated %u KB of DMA memory\n",
+				SGDMA_MEMORY >> 10);
+		} else
+			DRM_ERROR("Failed to allocate DMA memory\n");
+	}
+
+	/* allocate vq bo */
+	ret = ttm_allocate_kernel_buffer(&dev_priv->bdev, VQ_MEMORY, 16,
+					TTM_PL_FLAG_VRAM, &dev_priv->vq);
+	if (likely(!ret))
+		DRM_INFO("Allocated %u KB of memory for VQ\n", VQ_MEMORY >> 10);
+	else
+		DRM_ERROR("Failed to allocate VQ memory\n");
+
+	via_engine_init(dev);
+
+	/* setup workqueue */
+	dev_priv->wq = create_workqueue("viadrm");
+	if (dev_priv->wq == NULL) {
+		DRM_ERROR("create_workqueue failed !\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	ret = drm_vblank_init(dev, 2);
+	if (ret)
+		goto out_err;
+
+	ret = via_dmablit_init(dev);
+	if (ret)
+		goto out_err;
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = via_modeset_init(dev);
+		if (ret)
+			goto out_err;
+	}
+
+	ret = drm_irq_install(dev);
+out_err:
+	if (ret)
+		via_driver_unload(dev);
+	return ret;
+}
+
+static int via_final_context(struct drm_device *dev, int context)
+{
+	/* Linux specific until context tracking code gets ported to BSD */
+	/* Last context, perform cleanup */
+	if (dev->ctx_count == 1 && dev->dev_private) {
+		DRM_DEBUG("Last Context\n");
+		drm_irq_uninstall(dev);
+		via_dma_cleanup(dev);
+	}
+	return 1;
+}
+
+static void via_reclaim_buffers_locked(struct drm_device *dev,
+					struct drm_file *filp)
+{
+	mutex_lock(&dev->struct_mutex);
+	via_driver_dma_quiescent(dev);
+	mutex_unlock(&dev->struct_mutex);
+	return;
+}
 
 static const struct file_operations via_driver_fops = {
-	.owner = THIS_MODULE,
-	.open = drm_open,
-	.release = drm_release,
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
 	.unlocked_ioctl = drm_ioctl,
-	.mmap = drm_mmap,
-	.poll = drm_poll,
-	.fasync = drm_fasync,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl = drm_compat_ioctl,
-#endif
-	.llseek = noop_llseek,
+	.mmap		= ttm_mmap,
+	.poll		= drm_poll,
+	.fasync		= drm_fasync,
+	.llseek		= noop_llseek,
 };
 
-static struct drm_driver driver = {
+static struct drm_driver via_driver = {
 	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
-	    DRIVER_IRQ_SHARED,
+		DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
+		DRIVER_GEM | DRIVER_IRQ_SHARED,
 	.load = via_driver_load,
 	.unload = via_driver_unload,
-	.open = via_driver_open,
 	.preclose = via_reclaim_buffers_locked,
-	.postclose = via_driver_postclose,
 	.context_dtor = via_final_context,
-	.get_vblank_counter = via_get_vblank_counter,
+	.get_vblank_counter = drm_vblank_count,
 	.enable_vblank = via_enable_vblank,
 	.disable_vblank = via_disable_vblank,
 	.irq_preinstall = via_driver_irq_preinstall,
@@ -89,7 +453,11 @@  static struct drm_driver driver = {
 	.irq_uninstall = via_driver_irq_uninstall,
 	.irq_handler = via_driver_irq_handler,
 	.dma_quiescent = via_driver_dma_quiescent,
-	.lastclose = via_lastclose,
+	.gem_init_object = ttm_gem_init_object,
+	.gem_free_object = ttm_gem_free_object,
+	.dumb_create = via_dumb_create,
+	.dumb_map_offset = via_dumb_mmap,
+	.dumb_destroy = gem_dumb_destroy,
 	.ioctls = via_ioctls,
 	.fops = &via_driver_fops,
 	.name = DRIVER_NAME,
@@ -100,21 +468,60 @@  static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static int
+via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	return drm_get_pci_dev(pdev, ent, &via_driver);
+}
+
+static void
+via_pci_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_put_dev(dev);
+}
+
+#ifdef CONFIG_PM
+static int
+via_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	return 0;
+}
+
+static int
+via_pci_resume(struct pci_dev *pdev)
+{
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 static struct pci_driver via_pci_driver = {
-	.name = DRIVER_NAME,
-	.id_table = pciidlist,
+	.name		= DRIVER_NAME,
+	.id_table	= via_pci_table,
 };
 
 static int __init via_init(void)
 {
-	driver.num_ioctls = via_max_ioctl;
-	via_init_command_verifier();
-	return drm_pci_init(&driver, &via_pci_driver);
+	via_driver.num_ioctls = via_max_ioctl;
+
+	if (via_modeset) {
+		via_pci_driver.probe	= via_pci_probe;
+		via_pci_driver.remove	= via_pci_remove;
+#ifdef CONFIG_PM
+		via_pci_driver.suspend	= via_pci_suspend;
+		via_pci_driver.resume	= via_pci_resume;
+#endif
+		via_driver.driver_features |= DRIVER_MODESET;
+		via_driver.major = 3;
+		via_driver.minor = 0;
+	}
+	return drm_pci_init(&via_driver, &via_pci_driver);
 }
 
 static void __exit via_exit(void)
 {
-	drm_pci_exit(&driver, &via_pci_driver);
+	drm_pci_exit(&via_driver, &via_pci_driver);
 }
 
 module_init(via_init);
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 893a650..56c2237 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -16,7 +16,7 @@ 
  * 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
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) 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.
@@ -24,29 +24,63 @@ 
 #ifndef _VIA_DRV_H_
 #define _VIA_DRV_H_
 
-#include <drm/drm_mm.h>
-#define DRIVER_AUTHOR	"Various"
-
+#define DRIVER_AUTHOR		"Various"
 #define DRIVER_NAME		"via"
 #define DRIVER_DESC		"VIA Unichrome / Pro"
-#define DRIVER_DATE		"20070202"
+#define DRIVER_DATE		"20110221"
+
+#define DRIVER_MAJOR		3
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+#include <linux/module.h>
 
-#define DRIVER_MAJOR		2
-#define DRIVER_MINOR		11
-#define DRIVER_PATCHLEVEL	1
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_memory.h"
+#include "ttm/ttm_module.h"
+#include "ttm/ttm_page_alloc.h"
 
+#include <drm/drmP.h>
+#include <drm/via_drm.h>
+
+#include "via_regs.h"
+#include "via_fence.h"
+#include "via_dma.h"
 #include "via_verifier.h"
+#include "via_display.h"
 
-#include "via_dmablit.h"
+#define VIA_MM_ALIGN_SIZE 16
 
 #define VIA_PCI_BUF_SIZE 60000
 #define VIA_FIRE_BUF_SIZE  1024
 #define VIA_NUM_IRQS 4
 
-typedef struct drm_via_ring_buffer {
-	drm_local_map_t map;
-	char *virtual_start;
-} drm_via_ring_buffer_t;
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+#define CLE266_REVISION_AX	0x0A
+#define CLE266_REVISION_CX	0x0C
+#define CX700_REVISION_700	0x0
+#define CX700_REVISION_700M	0x1
+#define CX700_REVISION_700M2	0x2
+
+/* For VT3353 */
+#define VX800_REVISION_A	0x0f
+#define VX800_REVISION_B0	0x10
+#define VX800_REVISION_B1	0x11
+#define VX800_REVISION_B2	0x12
+
+/* For VT3409 */
+#define VX855_REVISION_A0	0x00
+#define VX855_REVISION_A1	0x01
+#define VX855_REVISION_A2	0x02
+
+/* For VT3410 */
+#define VX900_REVISION_A0	0x00
+#define VX900_REVISION_A1	0x01
+#define VX900_REVISION_A2	0x02
+#define VX900_REVISION_A3	0x03
 
 typedef uint32_t maskarray_t[5];
 
@@ -57,84 +91,162 @@  typedef struct drm_via_irq {
 	wait_queue_head_t irq_queue;
 } drm_via_irq_t;
 
-typedef struct drm_via_private {
-	drm_via_sarea_t *sarea_priv;
-	drm_local_map_t *sarea;
-	drm_local_map_t *fb;
-	drm_local_map_t *mmio;
-	unsigned long agpAddr;
-	wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
-	char *dma_ptr;
+struct sgdma_tt {
+        struct ttm_dma_tt sgdma;
+        unsigned long offset;
+};
+
+struct via_state {
+	struct vga_regset crt_regs[256];
+	struct vga_regset seq_regs[256];
+};
+
+enum via_engine {
+	VIA_ENG_H1 = 0,
+	VIA_ENG_H2,
+	VIA_ENG_H5S1,
+	VIA_ENG_H5S2VP1,
+	VIA_ENG_H6S2
+};
+
+struct drm_via_private {
+	struct drm_global_reference mem_global_ref;
+	struct ttm_bo_global_ref bo_global_ref;
+	struct ttm_bo_device bdev;
+	struct drm_device *dev;
+	int revision;
+
+	struct ttm_bo_kmap_obj dmabuf;
+	struct ttm_bo_kmap_obj mmio;
+	struct ttm_bo_kmap_obj gart;
+	struct ttm_bo_kmap_obj vq;
+
+	struct drm_fb_helper *helper;
+	int vram_mtrr;
+	u8 vram_type;
+
+	struct via_state pm_cache;
+
+	enum via_engine engine_type;
+	struct drm_via_state hc_state;
 	unsigned int dma_low;
 	unsigned int dma_high;
 	unsigned int dma_offset;
+	uint32_t dma_diff;
 	uint32_t dma_wrap;
-	volatile uint32_t *last_pause_ptr;
-	volatile uint32_t *hw_addr_ptr;
-	drm_via_ring_buffer_t ring;
-	struct timeval last_vblank;
-	int last_vblank_valid;
-	unsigned usec_per_vblank;
-	atomic_t vbl_received;
-	drm_via_state_t hc_state;
+	void __iomem *last_pause_ptr;
+	void __iomem *hw_addr_ptr;
+
 	char pci_buf[VIA_PCI_BUF_SIZE];
 	const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
 	uint32_t num_fire_offsets;
-	int chipset;
+
 	drm_via_irq_t via_irqs[VIA_NUM_IRQS];
+	struct work_struct hotplug_work;
+	struct workqueue_struct *wq;
 	unsigned num_irqs;
 	maskarray_t *irq_masks;
 	uint32_t irq_enable_mask;
 	uint32_t irq_pending_mask;
 	int *irq_map;
-	unsigned int idle_fault;
-	int vram_initialized;
-	struct drm_mm vram_mm;
-	int agp_initialized;
-	struct drm_mm agp_mm;
-	/** Mapping of userspace keys to mm objects */
-	struct idr object_idr;
-	unsigned long vram_offset;
-	unsigned long agp_offset;
-	drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
-	uint32_t dma_diff;
-} drm_via_private_t;
 
-enum via_family {
-  VIA_OTHER = 0,     /* Baseline */
-  VIA_PRO_GROUP_A,   /* Another video engine and DMA commands */
-  VIA_DX9_0          /* Same video as pro_group_a, but 3D is unsupported */
+	/* fence handling */
+	struct via_fence_pool *dma_fences;
+	int desc_size;
+
+	struct via_crtc iga[2];
+	bool spread_spectrum;
 };
 
+#define VIA_MEM_NONE		0x00
+#define VIA_MEM_SDR66		0x01
+#define VIA_MEM_SDR100		0x02
+#define VIA_MEM_SDR133		0x03
+#define VIA_MEM_DDR_200		0x04
+#define VIA_MEM_DDR_266		0x05
+#define VIA_MEM_DDR_333		0x06
+#define VIA_MEM_DDR_400		0x07
+#define VIA_MEM_DDR2_400	0x08
+#define VIA_MEM_DDR2_533	0x09
+#define VIA_MEM_DDR2_667	0x0A
+#define VIA_MEM_DDR2_800	0x0B
+#define VIA_MEM_DDR2_1066	0x0C
+#define VIA_MEM_DDR3_533	0x0D
+#define VIA_MEM_DDR3_667	0x0E
+#define VIA_MEM_DDR3_800	0x0F
+#define VIA_MEM_DDR3_1066	0x10
+#define VIA_MEM_DDR3_1333	0x11
+#define VIA_MEM_DDR3_1600	0x12
+
 /* VIA MMIO register access */
-#define VIA_BASE ((dev_priv->mmio))
+#define VIA_BASE ((dev_priv->mmio.virtual))
+
+#define VIA_READ(reg)		ioread32(VIA_BASE + reg)
+#define VIA_WRITE(reg, val)	iowrite32(val, VIA_BASE + reg)
+#define VIA_READ8(reg)		ioread8(VIA_BASE + reg)
+#define VIA_WRITE8(reg, val)	iowrite8(val, VIA_BASE + reg)
 
-#define VIA_READ(reg)		DRM_READ32(VIA_BASE, reg)
-#define VIA_WRITE(reg, val)	DRM_WRITE32(VIA_BASE, reg, val)
-#define VIA_READ8(reg)		DRM_READ8(VIA_BASE, reg)
-#define VIA_WRITE8(reg, val)	DRM_WRITE8(VIA_BASE, reg, val)
+#define VIA_WRITE_MASK(reg, data, mask)  \
+	VIA_WRITE(reg, (data & mask) | (VIA_READ(reg) & ~mask)) \
+
+#define VGABASE (VIA_BASE+VIA_MMIO_VGABASE)
 
 extern struct drm_ioctl_desc via_ioctls[];
 extern int via_max_ioctl;
 
-extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_hdmi_audio;
+
+extern void via_engine_init(struct drm_device *dev);
+
+extern int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *cmd);
+extern int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv);
 extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_wait_idle(struct drm_via_private *dev_priv);
+
+extern int via_detect_vram(struct drm_device *dev);
+
+extern int via_ttm_init(struct drm_via_private *dev_priv);
+extern struct ttm_tt *via_sgdma_backend_init(struct ttm_bo_device *bdev, unsigned long size,
+					uint32_t page_flags, struct page *dummy_read_page);
+
+extern int ttm_global_init(struct drm_global_reference *global_ref,
+				struct ttm_bo_global_ref *global_bo,
+				struct ttm_bo_driver *driver,
+				struct ttm_bo_device *bdev,
+				bool dma32);
+extern void ttm_global_fini(struct drm_global_reference *global_ref,
+				struct ttm_bo_global_ref *global_bo,
+				struct ttm_bo_device *bdev);
 
-extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
-extern int via_driver_unload(struct drm_device *dev);
+extern int ttm_bo_allocate(struct ttm_bo_device *bdev, unsigned long size,
+				enum ttm_bo_type origin, int types,
+				uint32_t byte_align, uint32_t page_align,
+				bool interruptible, struct sg_table *sg,
+				struct file *persistant_swap_storage,
+				struct ttm_buffer_object **p_bo);
+extern void ttm_placement_from_domain(struct ttm_buffer_object *bo,
+				struct ttm_placement *placement, u32 domains,
+				struct ttm_bo_device *bdev);
+extern int ttm_bo_unpin(struct ttm_buffer_object *bo, struct ttm_bo_kmap_obj *kmap);
+extern int ttm_bo_pin(struct ttm_buffer_object *bo, struct ttm_bo_kmap_obj *kmap);
+extern int ttm_allocate_kernel_buffer(struct ttm_bo_device *bdev, unsigned long size,
+				uint32_t alignment, uint32_t domain,
+				struct ttm_bo_kmap_obj *kmap);
 
-extern int via_init_context(struct drm_device *dev, int context);
-extern int via_final_context(struct drm_device *dev, int context);
+extern int ttm_mmap(struct file *filp, struct vm_area_struct *vma);
+
+extern int ttm_gem_init_object(struct drm_gem_object *obj);
+extern void ttm_gem_free_object(struct drm_gem_object *obj);
+extern struct drm_gem_object *ttm_gem_create(struct drm_device *dev,
+					struct ttm_bo_device *bdev, int type,
+					bool interruptible,
+					int byte_align, int page_align,
+					unsigned long size);
 
-extern int via_do_cleanup_map(struct drm_device *dev);
-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);
 
@@ -143,18 +255,11 @@  extern void via_driver_irq_preinstall(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_reclaim_buffers_locked(struct drm_device *dev,
-				       struct drm_file *file_priv);
-extern void via_lastclose(struct drm_device *dev);
+extern int via_dma_cleanup(struct drm_device *dev);
 
 extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
-extern void via_init_dmablit(struct drm_device *dev);
+extern int via_dmablit_init(struct drm_device *dev);
 
 #endif