From patchwork Sat Jun 8 16:57:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Simmons X-Patchwork-Id: 2692921 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 398A6DF24C for ; Sat, 8 Jun 2013 17:07:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 38676E613C for ; Sat, 8 Jun 2013 10:07:46 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by gabe.freedesktop.org (Postfix) with ESMTP id 1C4A7E6119; Sat, 8 Jun 2013 09:57:29 -0700 (PDT) Received: from jsimmons (helo=localhost) by casper.infradead.org with local-esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UlMSD-0006Ac-1W; Sat, 08 Jun 2013 16:57:28 +0000 Date: Sat, 8 Jun 2013 17:57:24 +0100 (BST) From: James Simmons To: DRI development list Subject: [RFC 21/21] DRM: Add VIA drm driver Message-ID: User-Agent: Alpine 2.03 (LFD 1266 2009-07-14) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130608_175725_189768_5BEF389A X-CRM114-Status: GOOD ( 23.82 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on casper.infradead.org summary: Content analysis details: (-1.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: OpenChrome Development X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org commit f4101ca539b83c824747d657bbdc28834276fea8 Author: James Simmons 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 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 #include #include +#include + #include "via_drv.h" -#include +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 -#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 -#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 +#include + +#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