struct drm_bo_info_rep *rep,
struct drm_buffer_object **bo_rep)
{
- struct drm_device *dev = file_priv->head->dev;
+ struct drm_device *dev = file_priv->minor->dev;
struct drm_buffer_object *bo;
int ret;
- int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
mutex_lock(&dev->struct_mutex);
bo = drm_lookup_buffer_object(file_priv, handle, 1);
size += buffer_start & ~PAGE_MASK;
num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (num_pages == 0) {
- DRM_ERROR("Illegal buffer object size %d.\n", size);
- DRM_ERROR("Illegal buffer object size.\n");
++ DRM_ERROR("Illegal buffer object size %ld.\n", size);
return -EINVAL;
}
return -EINVAL;
}
- bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_dc;
+ /*
+ * If the buffer creation request comes in with a starting address,
+ * that points at the desired user pages to map. Otherwise, create
+ * a drm_bo_type_device buffer, which uses pages allocated from the kernel
+ */
+ bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_device;
+ /*
+ * User buffers cannot be shared
+ */
if (bo_type == drm_bo_type_user)
- req->mask &= ~DRM_BO_FLAG_SHAREABLE;
+ req->flags &= ~DRM_BO_FLAG_SHAREABLE;
- ret = drm_buffer_object_create(file_priv->head->dev,
+ ret = drm_buffer_object_create(file_priv->minor->dev,
- req->size, bo_type, req->mask,
+ req->size, bo_type, req->flags,
req->hint, req->page_alignment,
req->buffer_start, &entry);
if (ret)
DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
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_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETOUTPUT, drm_mode_getoutput, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_output_property_set_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_ROOT_ONLY | DRM_CONTROL_ALLOW),
+
++
DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl,
*/
.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,
.load = i915_driver_load,
.unload = i915_driver_unload,
- .firstopen = i915_driver_firstopen,
- .lastclose = i915_driver_lastclose,
- .preclose = i915_driver_preclose,
+/* .lastclose = i915_driver_lastclose,
+ .preclose = i915_driver_preclose, */
.suspend = i915_suspend,
.resume = i915_resume,
.device_is_agp = i915_driver_device_is_agp,
--- /dev/null
- uint32_t radeon_evict_mask(struct drm_buffer_object *bo)
+/**************************************************************************
+ *
+ * Copyright 2007 Dave Airlie
+ * 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 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Authors: Dave Airlie <airlied@linux.ie>
+ */
+
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device * dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if(dev_priv->flags & RADEON_IS_AGP)
+ return drm_agp_init_ttm(dev);
+ else
+ return ati_pcigart_init_ttm(dev, &dev_priv->gart_info, radeon_gart_flush);
+}
+
+int radeon_fence_types(struct drm_buffer_object *bo, uint32_t * class, uint32_t * type)
+{
+ *class = 0;
+ if (bo->mem.flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
+ *type = 3;
+ else
+ *type = 1;
+ return 0;
+}
+
+int radeon_invalidate_caches(struct drm_device * dev, uint64_t flags)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ BEGIN_RING(4);
+ RADEON_FLUSH_CACHE();
+ RADEON_FLUSH_ZCACHE();
+ ADVANCE_RING();
+ return 0;
+}
+
- tmp_mem.mask = DRM_BO_FLAG_MEM_TT |
++uint64_t radeon_evict_flags(struct drm_buffer_object *bo)
+{
+ switch (bo->mem.mem_type) {
+ case DRM_BO_MEM_LOCAL:
+ case DRM_BO_MEM_TT:
+ return DRM_BO_FLAG_MEM_LOCAL;
+ case DRM_BO_MEM_VRAM:
+ if (bo->mem.num_pages > 128)
+ return DRM_BO_MEM_TT;
+ else
+ return DRM_BO_MEM_LOCAL;
+ default:
+ return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED;
+ }
+}
+
+int radeon_init_mem_type(struct drm_device * dev, uint32_t type,
+ struct drm_mem_type_manager * man)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ switch (type) {
+ case DRM_BO_MEM_LOCAL:
+ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+ _DRM_FLAG_MEMTYPE_CACHED;
+ man->drm_bus_maptype = 0;
+ break;
+ case DRM_BO_MEM_VRAM:
+ man->flags = _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_NEEDS_IOREMAP;
+ man->io_addr = NULL;
+ man->drm_bus_maptype = _DRM_FRAME_BUFFER;
+ man->io_offset = drm_get_resource_start(dev, 0);
+ man->io_size = drm_get_resource_len(dev, 0);
+ break;
+ case DRM_BO_MEM_TT:
+ if (dev_priv->flags & RADEON_IS_AGP) {
+ if (!(drm_core_has_AGP(dev) && dev->agp)) {
+ DRM_ERROR("AGP is not enabled for memory type %u\n",
+ (unsigned)type);
+ return -EINVAL;
+ }
+ man->io_offset = dev->agp->agp_info.aper_base;
+ man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024;
+ man->io_addr = NULL;
+ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP;
+ man->drm_bus_maptype = _DRM_AGP;
+ } else {
+ man->io_offset = dev_priv->gart_vm_start;
+ man->io_size = dev_priv->gart_size;
+ man->io_addr = NULL;
+ man->flags = _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_MEMTYPE_CMA;
+ man->drm_bus_maptype = _DRM_SCATTER_GATHER;
+ }
+ break;
+ default:
+ DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void radeon_emit_copy_blit(struct drm_device * dev,
+ uint32_t src_offset,
+ uint32_t dst_offset,
+ uint32_t pages, int direction)
+{
+ uint32_t cur_pages;
+ uint32_t stride = PAGE_SIZE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ uint32_t format, height;
+ RING_LOCALS;
+
+ if (!dev_priv)
+ return;
+
+ /* 32-bit copy format */
+ format = RADEON_COLOR_FORMAT_ARGB8888;
+
+ /* radeon limited to 16k stride */
+ stride &= 0x3fff;
+ while(pages > 0) {
+ cur_pages = pages;
+ if (cur_pages > 2048)
+ cur_pages = 2048;
+ pages -= cur_pages;
+
+ /* needs verification */
+ BEGIN_RING(7);
+ OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+ OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (format << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+ RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+ if (direction) {
+ OUT_RING((stride << 22) | (src_offset >> 10));
+ OUT_RING((stride << 22) | (dst_offset >> 10));
+ } else {
+ OUT_RING((stride << 22) | (dst_offset >> 10));
+ OUT_RING((stride << 22) | (src_offset >> 10));
+ }
+ OUT_RING(0);
+ OUT_RING(pages); /* x - y */
+ OUT_RING((stride << 16) | cur_pages);
+ ADVANCE_RING();
+ }
+
+ BEGIN_RING(2);
+ RADEON_WAIT_UNTIL_2D_IDLE();
+ ADVANCE_RING();
+
+ return;
+}
+
+static int radeon_move_blit(struct drm_buffer_object * bo,
+ int evict, int no_wait, struct drm_bo_mem_reg *new_mem)
+{
+ struct drm_bo_mem_reg *old_mem = &bo->mem;
+ int dir = 0;
+
+ if ((old_mem->mem_type == new_mem->mem_type) &&
+ (new_mem->mm_node->start <
+ old_mem->mm_node->start + old_mem->mm_node->size)) {
+ dir = 1;
+ }
+
+ radeon_emit_copy_blit(bo->dev,
+ old_mem->mm_node->start << PAGE_SHIFT,
+ new_mem->mm_node->start << PAGE_SHIFT,
+ new_mem->num_pages, dir);
+
+
+ return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0,
+ DRM_FENCE_TYPE_EXE |
+ DRM_RADEON_FENCE_TYPE_RW,
+ DRM_RADEON_FENCE_FLAG_FLUSHED, new_mem);
+}
+
+static int radeon_move_flip(struct drm_buffer_object * bo,
+ int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
+{
+ struct drm_device *dev = bo->dev;
+ struct drm_bo_mem_reg tmp_mem;
+ int ret;
+
+ tmp_mem = *new_mem;
+ tmp_mem.mm_node = NULL;
- ret = drm_bind_ttm(bo->ttm, &tmp_mem);
++ tmp_mem.flags = DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING;
+
+ ret = drm_bo_mem_space(bo, &tmp_mem, no_wait);
+ if (ret)
+ return ret;
+
++ ret = drm_ttm_bind(bo->ttm, &tmp_mem);
+ if (ret)
+ goto out_cleanup;
+
+ ret = radeon_move_blit(bo, 1, no_wait, &tmp_mem);
+ if (ret)
+ goto out_cleanup;
+
+ ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem);
+out_cleanup:
+ if (tmp_mem.mm_node) {
+ mutex_lock(&dev->struct_mutex);
+ if (tmp_mem.mm_node != bo->pinned_node)
+ drm_mm_put_block(tmp_mem.mm_node);
+ tmp_mem.mm_node = NULL;
+ mutex_unlock(&dev->struct_mutex);
+ }
+ return ret;
+}
+
+int radeon_move(struct drm_buffer_object * bo,
+ int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
+{
+ struct drm_bo_mem_reg *old_mem = &bo->mem;
+
+ DRM_DEBUG("\n");
+ if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
+ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+ } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
+ if (radeon_move_flip(bo, evict, no_wait, new_mem))
+ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+ } else {
+ if (radeon_move_blit(bo, evict, no_wait, new_mem))
+ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+ }
+ return 0;
+}
+
radeon_PCI_IDS
};
- .evict_mask = radeon_evict_mask,
+
+#ifdef RADEON_HAVE_FENCE
+static struct drm_fence_driver radeon_fence_driver = {
+ .num_classes = 1,
+ .wrap_diff = (1 << 30),
+ .flush_diff = (1 << 29),
+ .sequence_mask = 0xffffffffU,
+ .lazy_capable = 1,
+ .emit = radeon_fence_emit_sequence,
+ .poke_flush = radeon_poke_flush,
+ .has_irq = radeon_fence_has_irq,
+};
+#endif
+#ifdef RADEON_HAVE_BUFFER
+
+static uint32_t radeon_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
+static uint32_t radeon_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
+
+static struct drm_bo_driver radeon_bo_driver = {
+ .mem_type_prio = radeon_mem_prios,
+ .mem_busy_prio = radeon_busy_prios,
+ .num_mem_type_prio = sizeof(radeon_mem_prios)/sizeof(uint32_t),
+ .num_mem_busy_prio = sizeof(radeon_busy_prios)/sizeof(uint32_t),
+ .create_ttm_backend_entry = radeon_create_ttm_backend_entry,
+ .fence_type = radeon_fence_types,
+ .invalidate_caches = radeon_invalidate_caches,
+ .init_mem_type = radeon_init_mem_type,
++ .evict_flags = radeon_evict_flags,
+ .move = radeon_move,
+};
+#endif
+
static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static struct drm_driver driver = {
.driver_features =
--- /dev/null
- .vblank_wait = NULL,
- .vblank_wait2 = NULL,
+/*
+ * Copyright 2007 Jerome Glisse.
+ * 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, 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
+ * PRECISION INSIGHT 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:
+ * Jerome Glisse <glisse@freedesktop.org>
+ */
+#include "drm_pciids.h"
+#include "radeon_ms.h"
+
+extern struct drm_fence_driver radeon_ms_fence_driver;
+extern struct drm_bo_driver radeon_ms_bo_driver;
+extern struct drm_ioctl_desc radeon_ms_ioctls[];
+extern int radeon_ms_num_ioctls;
+
+static int radeon_ms_driver_dri_library_name(struct drm_device * dev,
+ char * buf);
+static int radeon_ms_driver_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+
+static struct pci_device_id pciidlist[] = {
+ radeon_ms_PCI_IDS
+};
+
+static struct drm_driver driver = {
+ .load = radeon_ms_driver_load,
+ .firstopen = NULL,
+ .open = radeon_ms_driver_open,
+ .preclose = NULL,
+ .postclose = NULL,
+ .lastclose = radeon_ms_driver_lastclose,
+ .unload = radeon_ms_driver_unload,
+ .dma_ioctl = radeon_ms_driver_dma_ioctl,
+ .dma_ready = NULL,
+ .dma_quiescent = NULL,
+ .context_ctor = NULL,
+ .context_dtor = NULL,
+ .kernel_context_switch = NULL,
+ .kernel_context_switch_unlock = NULL,
- DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
- DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
+ .dri_library_name = radeon_ms_driver_dri_library_name,
+ .device_is_agp = NULL,
+ .irq_handler = radeon_ms_irq_handler,
+ .irq_preinstall = radeon_ms_irq_preinstall,
+ .irq_postinstall = radeon_ms_irq_postinstall,
+ .irq_uninstall = radeon_ms_irq_uninstall,
+ .reclaim_buffers = drm_core_reclaim_buffers,
+ .reclaim_buffers_locked = NULL,
+ .reclaim_buffers_idlelocked = NULL,
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+ .set_version = NULL,
+ .fb_probe = radeonfb_probe,
+ .fb_remove = radeonfb_remove,
+ .fence_driver = &radeon_ms_fence_driver,
+ .bo_driver = &radeon_ms_bo_driver,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
++ DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
+ .dev_priv_size = 0,
+ .ioctls = radeon_ms_ioctls,
+ .num_ioctls = 0,
+ .fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+#if defined(CONFIG_COMPAT) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+ .compat_ioctl = radeon_ms_compat_ioctl,
+#endif
+ },
+ .pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ .probe = radeon_ms_driver_probe,
+ .remove = __devexit_p(drm_cleanup_pci),
+ },
+};
+
+static int radeon_ms_driver_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ return drm_get_dev(pdev, ent, &driver);
+}
+
+static int radeon_ms_driver_dri_library_name(struct drm_device * dev,
+ char * buf)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+ int ret;
+
+ switch (dev_priv->family) {
+ default:
+ ret = snprintf(buf, PAGE_SIZE, "\n");
+ }
+ return ret;
+}
+
+static void __exit radeon_ms_driver_exit(void)
+{
+ drm_exit(&driver);
+}
+
+static int __init radeon_ms_driver_init(void)
+{
+ driver.num_ioctls = radeon_ms_num_ioctls;
+ return drm_init(&driver, pciidlist);
+}
+
+module_init(radeon_ms_driver_init);
+module_exit(radeon_ms_driver_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
#define DRM_IOCTL_BO_WAIT_IDLE DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg)
#define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg)
-
+#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
+#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
+#define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, struct drm_mode_get_output)
+#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA3, struct drm_mode_crtc)
+#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xA4, struct drm_mode_fb_cmd)
+#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xA5, unsigned int)
+#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
+
+#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xA7, struct drm_mode_output_set_property)
+#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xA8, struct drm_mode_get_blob)
+#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
+#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
+
+#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAB, struct drm_mode_get_property)
++
/*@}*/
/**
unsigned long next = 0;
int ret = 0;
unsigned buf_count = 0;
- struct drm_device *dev = file_priv->head->dev;
+ struct drm_device *dev = file_priv->minor->dev;
- uint32_t buf_reloc_handle, buf_handle;
-
+ uint32_t buf_handle;
+ uint32_t __user *reloc_user_ptr;
do {
if (buf_count >= *num_buffers) {
extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_emit_irq(struct drm_device * dev);
- extern void i915_user_irq_on(struct drm_i915_private *dev_priv);
- extern void i915_user_irq_off(struct drm_i915_private *dev_priv);
+extern void i915_enable_interrupt (struct drm_device *dev);
+ 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_user_irq_on(drm_i915_private_t *dev_priv);
-extern void i915_user_irq_off(drm_i915_private_t *dev_priv);
++extern void i915_user_irq_on(struct drm_i915_private *dev_priv);
++extern void i915_user_irq_off(struct drm_i915_private *dev_priv);
/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
}
/**
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ * 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)
+ {
++ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
+
+ if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
+ return 1;
+
+ return 0;
+ }
+
+ /**
* Emit a synchronous flip.
*
* This function must be called with the drawable spinlock held.
*/
static void i915_vblank_tasklet(struct drm_device *dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
struct list_head *list, *tmp, hits, *hit;
int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
- 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;
+ struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv;
u32 cpp = dev_priv->cpp, offsets[3];
u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
XY_SRC_COPY_BLT_WRITE_ALPHA |
drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);
}
}
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ #if 0
+ static int i915_in_vblank(struct drm_device *dev, int pipe)
+ {
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ unsigned long pipedsl, vblank, vtotal;
+ unsigned long vbl_start, vbl_end, cur_line;
+
+ pipedsl = pipe ? PIPEBDSL : PIPEADSL;
+ vblank = pipe ? VBLANK_B : VBLANK_A;
+ vtotal = pipe ? VTOTAL_B : VTOTAL_A;
+
+ vbl_start = I915_READ(vblank) & VBLANK_START_MASK;
+ vbl_end = (I915_READ(vblank) >> VBLANK_END_SHIFT) & VBLANK_END_MASK;
+
+ cur_line = I915_READ(pipedsl);
+
+ if (cur_line >= vbl_start)
+ return 1;
+
+ return 0;
+ }
+ #endif
+ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
+ {
++ struct drm_i915_private *dev_priv = (struct drm_i915_private *) 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)) {
+ printk(KERN_ERR "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;
+
+ /*
+ * If we're in the middle of the vblank period, the
+ * above regs won't have been updated yet, so return
+ * an incremented count to stay accurate
+ */
+ #if 0
+ if (i915_in_vblank(dev, pipe))
+ count++;
+ #endif
+ return count;
+ }
+#define HOTPLUG_CMD_CRT 1
+#define HOTPLUG_CMD_SDVOB 4
+#define HOTPLUG_CMD_SDVOC 8
+
+static struct drm_device *hotplug_dev;
+static int hotplug_cmd = 0;
+static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED;
+
+static void i915_hotplug_crt(struct drm_device *dev)
+{
+ struct drm_output *output;
+ struct intel_output *iout;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ /* find the crt output */
+ list_for_each_entry(output, &dev->mode_config.output_list, head) {
+ iout = output->driver_private;
+ if (iout->type == INTEL_OUTPUT_ANALOG)
+ break;
+ else
+ iout = 0;
+ }
+
+ if (iout == 0)
+ goto unlock;
+
+ drm_hotplug_stage_two(dev, output);
+
+unlock:
+ mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)
+{
+ struct drm_output *output = 0;
+ enum drm_output_status status;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ output = intel_sdvo_find(dev, sdvoB);
+
+ if (!output) {
+ DRM_ERROR("could not find sdvo%s output\n", sdvoB ? "B" : "C");
+ goto unlock;
+ }
+
+ status = output->funcs->detect(output);
+
+ if (status != output_status_connected)
+ DRM_DEBUG("disconnect or unkown we don't do anything then\n");
+ else
+ drm_hotplug_stage_two(dev, output);
+
+ /* wierd hw bug, sdvo stop sending interupts */
+ intel_sdvo_set_hotplug(output, 1);
+
+unlock:
+ mutex_unlock(&dev->mode_config.mutex);
+}
+/*
+ * This code is called in a more safe envirmoent to handle the hotplugs.
+ * Add code here for hotplug love to userspace.
+ */
+static void i915_hotplug_work_func(struct work_struct *work)
+{
+ struct drm_device *dev = hotplug_dev;
+ int crt;
+ int sdvoB;
+ int sdvoC;
+
+ spin_lock(&hotplug_lock);
+ crt = hotplug_cmd & HOTPLUG_CMD_CRT;
+ sdvoB = hotplug_cmd & HOTPLUG_CMD_SDVOB;
+ sdvoC = hotplug_cmd & HOTPLUG_CMD_SDVOC;
+ hotplug_cmd = 0;
+ spin_unlock(&hotplug_lock);
+
+ if (crt)
+ i915_hotplug_crt(dev);
+
+ if (sdvoB)
+ i915_hotplug_sdvo(dev, 1);
+
+ if (sdvoC)
+ i915_hotplug_sdvo(dev, 0);
+
+}
+
+static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat)
+{
+ static DECLARE_WORK(hotplug, i915_hotplug_work_func);
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ hotplug_dev = dev;
+
+ if (stat & CRT_HOTPLUG_INT_STATUS) {
+ DRM_DEBUG("CRT event\n");
+
+ if (stat & CRT_HOTPLUG_MONITOR_MASK) {
+ spin_lock(&hotplug_lock);
+ hotplug_cmd |= HOTPLUG_CMD_CRT;
+ spin_unlock(&hotplug_lock);
+ } else {
+ /* handle crt disconnects */
+ }
+ }
+
+ if (stat & SDVOB_HOTPLUG_INT_STATUS) {
+ DRM_DEBUG("sDVOB event\n");
+
+ spin_lock(&hotplug_lock);
+ hotplug_cmd |= HOTPLUG_CMD_SDVOB;
+ spin_unlock(&hotplug_lock);
+ }
+
+ if (stat & SDVOC_HOTPLUG_INT_STATUS) {
+ DRM_DEBUG("sDVOC event\n");
+
+ spin_lock(&hotplug_lock);
+ hotplug_cmd |= HOTPLUG_CMD_SDVOC;
+ spin_unlock(&hotplug_lock);
+ }
+
+ queue_work(dev_priv->wq, &hotplug);
+
+ return 0;
+}
+
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
pipea_stats = I915_READ(I915REG_PIPEASTAT);
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
- temp = I915_READ16(I915REG_INT_IDENTITY_R);
+ /* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */
- if (IS_I9XX(dev)) {
++ if (IS_I9XX(dev))
+ temp = I915_READ(I915REG_INT_IDENTITY_R);
- } else {
++ else
+ temp = I915_READ16(I915REG_INT_IDENTITY_R);
- }
+
+ temp2 = temp;
+ temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
#if 0
- DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+ /* ugly despamification of pipeb event irq */
+ if (temp & (0xFFFFFFF ^ ((1 << 5) | (1 << 7)))) {
+ DRM_DEBUG("IIR %08x\n", temp2);
+ DRM_DEBUG("MSK %08x\n", dev_priv->irq_enable_reg | USER_INT_FLAG);
+ DRM_DEBUG("M&I %08x\n", temp);
+ DRM_DEBUG("HOT %08x\n", I915_READ(PORT_HOTPLUG_STAT));
+ }
+#else
+#if 0
+ DRM_DEBUG("flag=%08x\n", temp);
#endif
+#endif
+
if (temp == 0)
return IRQ_NONE;
+ if (IS_I9XX(dev)) {
+ I915_WRITE(I915REG_INT_IDENTITY_R, temp);
+ (void) I915_READ(I915REG_INT_IDENTITY_R);
+ } else {
+ I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ (void) I915_READ16(I915REG_INT_IDENTITY_R);
+ }
+
+ /*
+ * Clear the PIPE(A|B)STAT regs before the IIR otherwise
+ * we may get extra interrupts.
+ */
+ if (temp & VSYNC_PIPEA_FLAG) {
+ drm_handle_vblank(dev, i915_get_plane(dev, 0));
+ I915_WRITE(I915REG_PIPEASTAT,
+ pipea_stats | I915_VBLANK_INTERRUPT_ENABLE |
+ I915_VBLANK_CLEAR);
+ }
++
+ if (temp & VSYNC_PIPEB_FLAG) {
+ drm_handle_vblank(dev, i915_get_plane(dev, 1));
+ I915_WRITE(I915REG_PIPEBSTAT,
+ pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE |
+ I915_VBLANK_CLEAR);
+ }
+
+ I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ (void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */
+
+ DRM_READMEMORYBARRIER();
+
+ temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG |
+ VSYNC_PIPEB_FLAG);
+
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
if (temp & USER_INT_FLAG) {
}
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
- int vblank_pipe = dev_priv->vblank_pipe;
-
- 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)
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);
}
+ /* for now lest just ack it */
+ if (temp & (1 << 17)) {
+ DRM_DEBUG("Hotplug event received\n");
+
+ temp2 = I915_READ(PORT_HOTPLUG_STAT);
+
+ i915_run_hotplug_tasklet(dev, temp2);
+
+ I915_WRITE(PORT_HOTPLUG_STAT,temp2);
+ }
+
return IRQ_HANDLED;
}
int i915_emit_irq(struct drm_device *dev)
{
-
- drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_private *dev_priv = dev->dev_private;
RING_LOCALS;
i915_kernel_lost_context(dev);
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;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
int ret = 0;
- DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
+ DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
READ_BREADCRUMB(dev_priv));
if (READ_BREADCRUMB(dev_priv) >= irq_nr)
int i915_irq_wait(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_irq_wait_t *irqwait = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_irq_wait *irqwait = data;
if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
return i915_wait_irq(dev, irqwait->irq_seq);
}
- 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;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
- struct drm_output *o;
+ int pipe = i915_get_pipe(dev, plane);
-
+
- dev_priv->irq_enable_reg = USER_INT_FLAG;
-
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+ switch (pipe) {
+ case 0:
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+ break;
+ case 1:
dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ break;
+ default:
+ DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
+ pipe);
+ break;
+ }
+
+ I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+
+ return 0;
+ }
+
+ void i915_disable_vblank(struct drm_device *dev, int plane)
+ {
-static void i915_enable_interrupt (struct drm_device *dev)
++ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ int pipe = i915_get_pipe(dev, plane);
+
+ switch (pipe) {
+ case 0:
+ dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG;
+ break;
+ case 1:
+ dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG;
+ break;
+ default:
+ DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
+ pipe);
+ break;
+ }
+
+ I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+ }
+
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
++void i915_enable_interrupt (struct drm_device *dev)
+ {
++ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
++ struct drm_output *o;
++
+ dev_priv->irq_enable_reg |= USER_INT_FLAG;
- I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+ if (IS_I9XX(dev) && dev->mode_config.num_output) {
+ dev_priv->irq_enable_reg |= HOTPLUG_FLAG;
+
+ /* Activate the CRT */
+ I915_WRITE(PORT_HOTPLUG_EN, CRT_HOTPLUG_INT_EN);
+
+ /* SDVOB */
+ o = intel_sdvo_find(dev, 1);
+ if (o && intel_sdvo_supports_hotplug(o)) {
+ intel_sdvo_set_hotplug(o, 1);
+ I915_WRITE(PORT_HOTPLUG_EN, SDVOB_HOTPLUG_INT_EN);
+ }
+
+ /* SDVOC */
+ o = intel_sdvo_find(dev, 0);
+ if (o && intel_sdvo_supports_hotplug(o)) {
+ intel_sdvo_set_hotplug(o, 1);
+ I915_WRITE(PORT_HOTPLUG_EN, SDVOC_HOTPLUG_INT_EN);
+ }
+
+ }
+
+ if (IS_I9XX(dev)) {
+ I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+ } else {
+ I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+ }
+
+ DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN));
+ DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT));
+ DRM_DEBUG("IER %08x\n",I915_READ(I915REG_INT_ENABLE_R));
+ DRM_DEBUG("SDB %08x\n",I915_READ(SDVOB));
+
+ I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+
dev_priv->irq_enabled = 1;
}
int i915_vblank_pipe_set(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_vblank_pipe_t *pipe = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_vblank_pipe *pipe = data;
if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
*/
void i915_driver_irq_preinstall(struct drm_device * dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
I915_WRITE16(I915REG_HWSTAM, 0xeffe);
- I915_WRITE16(I915REG_INT_MASK_R, 0x0);
- I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+ if (IS_I9XX(dev)) {
+ I915_WRITE(I915REG_INT_MASK_R, 0x0);
+ I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
+ } else {
+ I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+ I915_WRITE16(I915REG_INT_ENABLE_R, 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;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ int ret, num_pipes = 2;
DRM_SPININIT(&dev_priv->swaps_lock, "swap");
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
/* radeon_irq.c */
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 int radeon_emit_irq(struct drm_device * dev);
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 void radeon_do_release(struct drm_device * dev);
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 int radeon_vblank_crtc_get(struct drm_device *dev);
extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
struct drm_file *file_priv,
drm_radeon_kcmd_buffer_t *cmdbuf);
- extern uint32_t radeon_evict_mask(struct drm_buffer_object *bo);
+
+#ifdef RADEON_HAVE_FENCE
+/* i915_fence.c */
+
+
+extern void radeon_fence_handler(struct drm_device *dev);
+extern int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class,
+ uint32_t flags, uint32_t *sequence,
+ uint32_t *native_type);
+extern void radeon_poke_flush(struct drm_device *dev, uint32_t class);
+extern int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags);
+#endif
+
+#ifdef RADEON_HAVE_BUFFER
+/* radeon_buffer.c */
+extern struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device *dev);
+extern int radeon_fence_types(struct drm_buffer_object *bo, uint32_t *class, uint32_t *type);
+extern int radeon_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
++extern uint64_t radeon_evict_flags(struct drm_buffer_object *bo);
+extern int radeon_init_mem_type(struct drm_device * dev, uint32_t type,
+ struct drm_mem_type_manager * man);
+extern int radeon_move(struct drm_buffer_object * bo,
+ int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
+#endif
/* Flags for stats.boxes
*/
#define RADEON_BOX_DMA_IDLE 0x1
stat &= dev_priv->irq_enable_reg;
/* SW interrupt */
- if (stat & RADEON_SW_INT_TEST)
- DRM_WAKEUP(&dev_priv->swi_queue);
-
+ if (stat & RADEON_SW_INT_TEST) {
+ DRM_WAKEUP(&dev_priv->irq_queue);
+#ifdef RADEON_HAVE_FENCE
+ radeon_fence_handler(dev);
+#endif
+ }
-
/* 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 (stat & RADEON_CRTC_VBLANK_STAT)
+ drm_handle_vblank(dev, 0);
+ if (stat & RADEON_CRTC2_VBLANK_STAT)
+ drm_handle_vblank(dev, 1);
return IRQ_HANDLED;
}
{
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);
+ dev_priv->counter = 0;
+ DRM_INIT_WAITQUEUE(&dev_priv->irq_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)
--- /dev/null
- uint32_t radeon_ms_evict_mask(struct drm_buffer_object *bo);
+/*
+ * Copyright 2007 Jérôme Glisse
+ * Copyright 2007 Dave Airlie
+ * Copyright 2007 Alex Deucher
+ * 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, 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
+ * PRECISION INSIGHT 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:
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef __RADEON_MS_H__
+#define __RADEON_MS_H__
+
+#include "radeon_ms_drv.h"
+#include "radeon_ms_reg.h"
+#include "radeon_ms_drm.h"
+#include "radeon_ms_rom.h"
+#include "radeon_ms_properties.h"
+
+#define DRIVER_AUTHOR "Jerome Glisse, Dave Airlie, Gareth Hughes, "\
+ "Keith Whitwell, others."
+#define DRIVER_NAME "radeon_ms"
+#define DRIVER_DESC "radeon kernel modesetting"
+#define DRIVER_DATE "20071108"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+enum radeon_bus_type {
+ RADEON_PCI = 0x10000,
+ RADEON_AGP = 0x20000,
+ RADEON_PCIE = 0x30000,
+};
+
+enum radeon_family {
+ CHIP_R100,
+ CHIP_RV100,
+ CHIP_RS100,
+ CHIP_RV200,
+ CHIP_RS200,
+ CHIP_R200,
+ CHIP_RV250,
+ CHIP_RS300,
+ CHIP_RV280,
+ CHIP_R300,
+ CHIP_R350,
+ CHIP_R360,
+ CHIP_RV350,
+ CHIP_RV370,
+ CHIP_RV380,
+ CHIP_RS400,
+ CHIP_RV410,
+ CHIP_R420,
+ CHIP_R430,
+ CHIP_R480,
+ CHIP_LAST,
+};
+
+enum radeon_monitor_type {
+ MT_UNKNOWN = -1,
+ MT_NONE = 0,
+ MT_CRT = 1,
+ MT_LCD = 2,
+ MT_DFP = 3,
+ MT_CTV = 4,
+ MT_STV = 5
+};
+
+enum radeon_connector_type {
+ CONNECTOR_NONE,
+ CONNECTOR_PROPRIETARY,
+ CONNECTOR_VGA,
+ CONNECTOR_DVI_I,
+ CONNECTOR_DVI_D,
+ CONNECTOR_CTV,
+ CONNECTOR_STV,
+ CONNECTOR_UNSUPPORTED
+};
+
+enum radeon_output_type {
+ OUTPUT_NONE,
+ OUTPUT_DAC1,
+ OUTPUT_DAC2,
+ OUTPUT_TMDS,
+ OUTPUT_LVDS
+};
+
+struct radeon_state;
+
+struct radeon_ms_crtc {
+ int crtc;
+ uint16_t lut_r[256];
+ uint16_t lut_g[256];
+ uint16_t lut_b[256];
+};
+
+struct radeon_ms_i2c {
+ struct drm_device *drm_dev;
+ uint32_t reg;
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+};
+
+struct radeon_ms_connector {
+ struct radeon_ms_i2c *i2c;
+ struct edid *edid;
+ struct drm_output *output;
+ int type;
+ int monitor_type;
+ int crtc;
+ uint32_t i2c_reg;
+ char outputs[RADEON_MAX_OUTPUTS];
+ char name[32];
+};
+
+struct radeon_ms_output {
+ int type;
+ struct drm_device *dev;
+ struct radeon_ms_connector *connector;
+ int (*initialize)(struct radeon_ms_output *output);
+ enum drm_output_status (*detect)(struct radeon_ms_output *output);
+ void (*dpms)(struct radeon_ms_output *output, int mode);
+ int (*get_modes)(struct radeon_ms_output *output);
+ bool (*mode_fixup)(struct radeon_ms_output *output,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+ int (*mode_set)(struct radeon_ms_output *output,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+ void (*restore)(struct radeon_ms_output *output,
+ struct radeon_state *state);
+ void (*save)(struct radeon_ms_output *output,
+ struct radeon_state *state);
+};
+
+struct radeon_state {
+ /* memory */
+ uint32_t config_aper_0_base;
+ uint32_t config_aper_1_base;
+ uint32_t config_aper_size;
+ uint32_t mc_fb_location;
+ uint32_t display_base_addr;
+ /* irq */
+ uint32_t gen_int_cntl;
+ /* pci */
+ uint32_t aic_ctrl;
+ uint32_t aic_pt_base;
+ uint32_t aic_pt_base_lo;
+ uint32_t aic_pt_base_hi;
+ uint32_t aic_lo_addr;
+ uint32_t aic_hi_addr;
+ /* agp */
+ uint32_t agp_cntl;
+ uint32_t agp_command;
+ uint32_t agp_base;
+ uint32_t agp_base_2;
+ uint32_t bus_cntl;
+ uint32_t mc_agp_location;
+ /* cp */
+ uint32_t cp_rb_cntl;
+ uint32_t cp_rb_base;
+ uint32_t cp_rb_rptr_addr;
+ uint32_t cp_rb_wptr;
+ uint32_t cp_rb_wptr_delay;
+ uint32_t scratch_umsk;
+ uint32_t scratch_addr;
+ /* pcie */
+ uint32_t pcie_tx_gart_cntl;
+ uint32_t pcie_tx_gart_discard_rd_addr_lo;
+ uint32_t pcie_tx_gart_discard_rd_addr_hi;
+ uint32_t pcie_tx_gart_base;
+ uint32_t pcie_tx_gart_start_lo;
+ uint32_t pcie_tx_gart_start_hi;
+ uint32_t pcie_tx_gart_end_lo;
+ uint32_t pcie_tx_gart_end_hi;
+ /* surface */
+ uint32_t surface_cntl;
+ uint32_t surface0_info;
+ uint32_t surface0_lower_bound;
+ uint32_t surface0_upper_bound;
+ uint32_t surface1_info;
+ uint32_t surface1_lower_bound;
+ uint32_t surface1_upper_bound;
+ uint32_t surface2_info;
+ uint32_t surface2_lower_bound;
+ uint32_t surface2_upper_bound;
+ uint32_t surface3_info;
+ uint32_t surface3_lower_bound;
+ uint32_t surface3_upper_bound;
+ uint32_t surface4_info;
+ uint32_t surface4_lower_bound;
+ uint32_t surface4_upper_bound;
+ uint32_t surface5_info;
+ uint32_t surface5_lower_bound;
+ uint32_t surface5_upper_bound;
+ uint32_t surface6_info;
+ uint32_t surface6_lower_bound;
+ uint32_t surface6_upper_bound;
+ uint32_t surface7_info;
+ uint32_t surface7_lower_bound;
+ uint32_t surface7_upper_bound;
+ /* crtc */
+ uint32_t crtc_gen_cntl;
+ uint32_t crtc_ext_cntl;
+ uint32_t crtc_h_total_disp;
+ uint32_t crtc_h_sync_strt_wid;
+ uint32_t crtc_v_total_disp;
+ uint32_t crtc_v_sync_strt_wid;
+ uint32_t crtc_offset;
+ uint32_t crtc_offset_cntl;
+ uint32_t crtc_pitch;
+ uint32_t crtc_more_cntl;
+ uint32_t crtc_tile_x0_y0;
+ uint32_t fp_h_sync_strt_wid;
+ uint32_t fp_v_sync_strt_wid;
+ uint32_t fp_crtc_h_total_disp;
+ uint32_t fp_crtc_v_total_disp;
+ /* pll */
+ uint32_t clock_cntl_index;
+ uint32_t ppll_cntl;
+ uint32_t ppll_ref_div;
+ uint32_t ppll_div_0;
+ uint32_t ppll_div_1;
+ uint32_t ppll_div_2;
+ uint32_t ppll_div_3;
+ uint32_t vclk_ecp_cntl;
+ uint32_t htotal_cntl;
+ /* dac */
+ uint32_t dac_cntl;
+ uint32_t dac_cntl2;
+ uint32_t dac_ext_cntl;
+ uint32_t disp_misc_cntl;
+ uint32_t dac_macro_cntl;
+ uint32_t disp_pwr_man;
+ uint32_t disp_merge_cntl;
+ uint32_t disp_output_cntl;
+ uint32_t disp2_merge_cntl;
+ uint32_t dac_embedded_sync_cntl;
+ uint32_t dac_broad_pulse;
+ uint32_t dac_skew_clks;
+ uint32_t dac_incr;
+ uint32_t dac_neg_sync_level;
+ uint32_t dac_pos_sync_level;
+ uint32_t dac_blank_level;
+ uint32_t dac_sync_equalization;
+ uint32_t tv_dac_cntl;
+ uint32_t tv_master_cntl;
+};
+
+struct drm_radeon_private {
+ /* driver family specific functions */
+ int (*bus_finish)(struct drm_device *dev);
+ int (*bus_init)(struct drm_device *dev);
+ void (*bus_restore)(struct drm_device *dev, struct radeon_state *state);
+ void (*bus_save)(struct drm_device *dev, struct radeon_state *state);
+ struct drm_ttm_backend *(*create_ttm)(struct drm_device *dev);
+ void (*irq_emit)(struct drm_device *dev);
+ void (*flush_cache)(struct drm_device *dev);
+ /* bus informations */
+ void *bus;
+ uint32_t bus_type;
+ /* cp */
+ uint32_t ring_buffer_size;
+ uint32_t ring_rptr;
+ uint32_t ring_wptr;
+ uint32_t ring_mask;
+ int ring_free;
+ uint32_t ring_tail_mask;
+ uint32_t write_back_area_size;
+ struct drm_buffer_object *ring_buffer_object;
+ struct drm_bo_kmap_obj ring_buffer_map;
+ uint32_t *ring_buffer;
+ uint32_t *write_back_area;
+ const uint32_t *microcode;
+ /* card family */
+ uint32_t usec_timeout;
+ uint32_t family;
+ struct radeon_ms_output *outputs[RADEON_MAX_OUTPUTS];
+ struct radeon_ms_connector *connectors[RADEON_MAX_CONNECTORS];
+ /* drm map (MMIO, FB) */
+ struct drm_map mmio;
+ struct drm_map vram;
+ /* gpu address space */
+ uint32_t gpu_vram_size;
+ uint32_t gpu_vram_start;
+ uint32_t gpu_vram_end;
+ uint32_t gpu_gart_size;
+ uint32_t gpu_gart_start;
+ uint32_t gpu_gart_end;
+ /* state of the card when module was loaded */
+ struct radeon_state load_state;
+ /* state the driver wants */
+ struct radeon_state driver_state;
+ /* last emitted fence */
+ uint32_t fence_id_last;
+ uint32_t fence_reg;
+ /* when doing gpu stop we save here current state */
+ uint32_t crtc_ext_cntl;
+ uint32_t crtc_gen_cntl;
+ uint32_t crtc2_gen_cntl;
+ uint32_t ov0_scale_cntl;
+ /* bool & type on the hw */
+ uint8_t crtc1_dpms;
+ uint8_t crtc2_dpms;
+ uint8_t restore_state;
+ uint8_t cp_ready;
+ uint8_t bus_ready;
+ uint8_t write_back;
+ /* abstract asic specific structures */
+ struct radeon_ms_rom rom;
+ struct radeon_ms_properties properties;
+};
+
+
+/* radeon_ms_bo.c */
+int radeon_ms_bo_get_gpu_addr(struct drm_device *dev,
+ struct drm_bo_mem_reg *mem,
+ uint32_t *gpu_addr);
+int radeon_ms_bo_move(struct drm_buffer_object * bo, int evict,
+ int no_wait, struct drm_bo_mem_reg * new_mem);
+struct drm_ttm_backend *radeon_ms_create_ttm_backend(struct drm_device * dev);
++uint64_t radeon_ms_evict_flags(struct drm_buffer_object *bo);
+int radeon_ms_init_mem_type(struct drm_device * dev, uint32_t type,
+ struct drm_mem_type_manager * man);
+int radeon_ms_invalidate_caches(struct drm_device * dev, uint64_t flags);
+void radeon_ms_ttm_flush(struct drm_ttm *ttm);
+
+/* radeon_ms_bus.c */
+int radeon_ms_agp_finish(struct drm_device *dev);
+int radeon_ms_agp_init(struct drm_device *dev);
+void radeon_ms_agp_restore(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_agp_save(struct drm_device *dev, struct radeon_state *state);
+struct drm_ttm_backend *radeon_ms_pcie_create_ttm(struct drm_device *dev);
+int radeon_ms_pcie_finish(struct drm_device *dev);
+int radeon_ms_pcie_init(struct drm_device *dev);
+void radeon_ms_pcie_restore(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_pcie_save(struct drm_device *dev, struct radeon_state *state);
+
+/* radeon_ms_combios.c */
+int radeon_ms_combios_get_properties(struct drm_device *dev);
+int radeon_ms_connectors_from_combios(struct drm_device *dev);
+int radeon_ms_outputs_from_combios(struct drm_device *dev);
+
+/* radeon_ms_compat.c */
+long radeon_ms_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+/* radeon_ms_cp.c */
+int radeon_ms_cp_finish(struct drm_device *dev);
+int radeon_ms_cp_init(struct drm_device *dev);
+void radeon_ms_cp_restore(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_cp_save(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_cp_stop(struct drm_device *dev);
+int radeon_ms_cp_wait(struct drm_device *dev, int n);
+int radeon_ms_ring_emit(struct drm_device *dev, uint32_t *cmd, uint32_t count);
+
+/* radeon_ms_crtc.c */
+int radeon_ms_crtc_create(struct drm_device *dev, int crtc);
+void radeon_ms_crtc1_restore(struct drm_device *dev,
+ struct radeon_state *state);
+void radeon_ms_crtc1_save(struct drm_device *dev, struct radeon_state *state);
+
+/* radeon_ms_dac.c */
+int radeon_ms_dac1_initialize(struct radeon_ms_output *output);
+enum drm_output_status radeon_ms_dac1_detect(struct radeon_ms_output *output);
+void radeon_ms_dac1_dpms(struct radeon_ms_output *output, int mode);
+int radeon_ms_dac1_get_modes(struct radeon_ms_output *output);
+bool radeon_ms_dac1_mode_fixup(struct radeon_ms_output *output,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+int radeon_ms_dac1_mode_set(struct radeon_ms_output *output,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+void radeon_ms_dac1_restore(struct radeon_ms_output *output,
+ struct radeon_state *state);
+void radeon_ms_dac1_save(struct radeon_ms_output *output,
+ struct radeon_state *state);
+int radeon_ms_dac2_initialize(struct radeon_ms_output *output);
+enum drm_output_status radeon_ms_dac2_detect(struct radeon_ms_output *output);
+void radeon_ms_dac2_dpms(struct radeon_ms_output *output, int mode);
+int radeon_ms_dac2_get_modes(struct radeon_ms_output *output);
+bool radeon_ms_dac2_mode_fixup(struct radeon_ms_output *output,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+int radeon_ms_dac2_mode_set(struct radeon_ms_output *output,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+void radeon_ms_dac2_restore(struct radeon_ms_output *output,
+ struct radeon_state *state);
+void radeon_ms_dac2_save(struct radeon_ms_output *output,
+ struct radeon_state *state);
+
+/* radeon_ms_drm.c */
+int radeon_ms_driver_dma_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+void radeon_ms_driver_lastclose(struct drm_device * dev);
+int radeon_ms_driver_load(struct drm_device *dev, unsigned long flags);
+int radeon_ms_driver_open(struct drm_device * dev, struct drm_file *file_priv);
+int radeon_ms_driver_unload(struct drm_device *dev);
+
+/* radeon_ms_exec.c */
+int radeon_ms_execbuffer(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+/* radeon_ms_family.c */
+int radeon_ms_family_init(struct drm_device *dev);
+
+/* radeon_ms_fence.c */
+int radeon_ms_fence_emit_sequence(struct drm_device *dev, uint32_t class,
+ uint32_t flags, uint32_t *sequence,
+ uint32_t *native_type);
+void radeon_ms_fence_handler(struct drm_device * dev);
+int radeon_ms_fence_has_irq(struct drm_device *dev, uint32_t class,
+ uint32_t flags);
+int radeon_ms_fence_types(struct drm_buffer_object *bo,
+ uint32_t * class, uint32_t * type);
+void radeon_ms_poke_flush(struct drm_device * dev, uint32_t class);
+
+/* radeon_ms_fb.c */
+int radeonfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
+int radeonfb_remove(struct drm_device *dev, struct drm_crtc *crtc);
+
+/* radeon_ms_gpu.c */
+int radeon_ms_gpu_initialize(struct drm_device *dev);
+void radeon_ms_gpu_dpms(struct drm_device *dev);
+void radeon_ms_gpu_flush(struct drm_device *dev);
+void radeon_ms_gpu_restore(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_gpu_save(struct drm_device *dev, struct radeon_state *state);
+int radeon_ms_wait_for_idle(struct drm_device *dev);
+
+/* radeon_ms_i2c.c */
+void radeon_ms_i2c_destroy(struct radeon_ms_i2c *i2c);
+struct radeon_ms_i2c *radeon_ms_i2c_create(struct drm_device *dev,
+ const uint32_t reg,
+ const char *name);
+
+/* radeon_ms_irq.c */
+void radeon_ms_irq_emit(struct drm_device *dev);
+irqreturn_t radeon_ms_irq_handler(DRM_IRQ_ARGS);
+void radeon_ms_irq_preinstall(struct drm_device * dev);
+void radeon_ms_irq_postinstall(struct drm_device * dev);
+int radeon_ms_irq_init(struct drm_device *dev);
+void radeon_ms_irq_restore(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_irq_save(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_irq_uninstall(struct drm_device * dev);
+
+/* radeon_ms_output.c */
+void radeon_ms_connectors_destroy(struct drm_device *dev);
+int radeon_ms_connectors_from_properties(struct drm_device *dev);
+int radeon_ms_connectors_from_rom(struct drm_device *dev);
+void radeon_ms_outputs_destroy(struct drm_device *dev);
+int radeon_ms_outputs_from_properties(struct drm_device *dev);
+int radeon_ms_outputs_from_rom(struct drm_device *dev);
+void radeon_ms_outputs_restore(struct drm_device *dev,
+ struct radeon_state *state);
+void radeon_ms_outputs_save(struct drm_device *dev, struct radeon_state *state);
+
+/* radeon_ms_properties.c */
+int radeon_ms_properties_init(struct drm_device *dev);
+
+/* radeon_ms_rom.c */
+int radeon_ms_rom_get_properties(struct drm_device *dev);
+int radeon_ms_rom_init(struct drm_device *dev);
+
+/* radeon_ms_state.c */
+void radeon_ms_state_save(struct drm_device *dev, struct radeon_state *state);
+void radeon_ms_state_restore(struct drm_device *dev,
+ struct radeon_state *state);
+
+
+/* packect stuff **************************************************************/
+#define RADEON_CP_PACKET0 0x00000000
+#define CP_PACKET0(reg, n) \
+ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00
+# define GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
+# define GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
+# define GMC_BRUSH_NONE (15 << 4)
+# define GMC_SRC_DATATYPE_COLOR (3 << 12)
+# define ROP3_S 0x00cc0000
+# define DP_SRC_SOURCE_MEMORY (2 << 24)
+# define GMC_CLR_CMP_CNTL_DIS (1 << 28)
+# define GMC_WR_MSK_DIS (1 << 30)
+
+/* helper macro & functions ***************************************************/
+#define REG_S(rn, bn, v) (((v) << rn##__##bn##__SHIFT) & rn##__##bn##__MASK)
+#define REG_G(rn, bn, v) (((v) & rn##__##bn##__MASK) >> rn##__##bn##__SHIFT)
+#define MMIO_R(rid) mmio_read(dev_priv, rid)
+#define MMIO_W(rid, v) mmio_write(dev_priv, rid, v)
+#define PCIE_R(rid) pcie_read(dev_priv, rid)
+#define PCIE_W(rid, v) pcie_write(dev_priv, rid, v)
+#define PPLL_R(rid) pll_read(dev_priv, rid)
+#define PPLL_W(rid, v) pll_write(dev_priv, rid, v)
+
+static __inline__ uint32_t mmio_read(struct drm_radeon_private *dev_priv,
+ uint32_t offset)
+{
+ return DRM_READ32(&dev_priv->mmio, offset);
+}
+
+
+static __inline__ void mmio_write(struct drm_radeon_private *dev_priv,
+ uint32_t offset, uint32_t v)
+{
+ DRM_WRITE32(&dev_priv->mmio, offset, v);
+}
+
+static __inline__ uint32_t pcie_read(struct drm_radeon_private *dev_priv,
+ uint32_t offset)
+{
+ MMIO_W(PCIE_INDEX, REG_S(PCIE_INDEX, PCIE_INDEX, offset));
+ return MMIO_R(PCIE_DATA);
+}
+
+static __inline__ void pcie_write(struct drm_radeon_private *dev_priv,
+ uint32_t offset, uint32_t v)
+{
+ MMIO_W(PCIE_INDEX, REG_S(PCIE_INDEX, PCIE_INDEX, offset));
+ MMIO_W(PCIE_DATA, v);
+}
+
+static __inline__ void pll_index_errata(struct drm_radeon_private *dev_priv)
+{
+ uint32_t tmp, save;
+
+ /* This workaround is necessary on rv200 and RS200 or PLL
+ * reads may return garbage (among others...)
+ */
+ if (dev_priv->properties.pll_dummy_reads) {
+ tmp = MMIO_R(CLOCK_CNTL_DATA);
+ tmp = MMIO_R(CRTC_GEN_CNTL);
+ }
+ /* This function is required to workaround a hardware bug in some (all?)
+ * revisions of the R300. This workaround should be called after every
+ * CLOCK_CNTL_INDEX register access. If not, register reads afterward
+ * may not be correct.
+ */
+ if (dev_priv->properties.pll_r300_errata) {
+ tmp = save = MMIO_R(CLOCK_CNTL_INDEX);
+ tmp = tmp & ~CLOCK_CNTL_INDEX__PLL_ADDR__MASK;
+ tmp = tmp & ~CLOCK_CNTL_INDEX__PLL_WR_EN;
+ MMIO_W(CLOCK_CNTL_INDEX, tmp);
+ tmp = MMIO_R(CLOCK_CNTL_DATA);
+ MMIO_W(CLOCK_CNTL_INDEX, save);
+ }
+}
+
+static __inline__ void pll_data_errata(struct drm_radeon_private *dev_priv)
+{
+ /* This workarounds is necessary on RV100, RS100 and RS200 chips
+ * or the chip could hang on a subsequent access
+ */
+ if (dev_priv->properties.pll_delay) {
+ /* we can't deal with posted writes here ... */
+ udelay(5000);
+ }
+}
+
+static __inline__ uint32_t pll_read(struct drm_radeon_private *dev_priv,
+ uint32_t offset)
+{
+ uint32_t clock_cntl_index = dev_priv->driver_state.clock_cntl_index;
+ uint32_t data;
+
+ clock_cntl_index &= ~CLOCK_CNTL_INDEX__PLL_ADDR__MASK;
+ clock_cntl_index |= REG_S(CLOCK_CNTL_INDEX, PLL_ADDR, offset);
+ MMIO_W(CLOCK_CNTL_INDEX, clock_cntl_index);
+ pll_index_errata(dev_priv);
+ data = MMIO_R(CLOCK_CNTL_DATA);
+ pll_data_errata(dev_priv);
+ return data;
+}
+
+static __inline__ void pll_write(struct drm_radeon_private *dev_priv,
+ uint32_t offset, uint32_t value)
+{
+ uint32_t clock_cntl_index = dev_priv->driver_state.clock_cntl_index;
+
+ clock_cntl_index &= ~CLOCK_CNTL_INDEX__PLL_ADDR__MASK;
+ clock_cntl_index |= REG_S(CLOCK_CNTL_INDEX, PLL_ADDR, offset);
+ clock_cntl_index |= CLOCK_CNTL_INDEX__PLL_WR_EN;
+ MMIO_W(CLOCK_CNTL_INDEX, clock_cntl_index);
+ pll_index_errata(dev_priv);
+ MMIO_W(CLOCK_CNTL_DATA, value);
+ pll_data_errata(dev_priv);
+}
+
+#endif
--- /dev/null
- tmp_mem.mask = DRM_BO_FLAG_MEM_TT |
+/*
+ * Copyright 2007 Dave Airlie
+ * Copyright 2007 Jérôme Glisse
+ * 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 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Dave Airlie <airlied@linux.ie>
+ * Jerome Glisse <glisse@freedesktop.org>
+ */
+#include "drmP.h"
+#include "drm.h"
+
+#include "radeon_ms.h"
+
+void radeon_ms_bo_copy_blit(struct drm_device *dev,
+ uint32_t src_offset,
+ uint32_t dst_offset,
+ uint32_t pages)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+ uint32_t num_pages, stride, c;
+ uint32_t offset_inc = 0;
+ uint32_t cmd[7];
+
+ if (!dev_priv) {
+ return;
+ }
+
+ /* radeon limited to 16320=255*64 bytes per row so copy at
+ * most 2 pages */
+ num_pages = 2;
+ stride = ((num_pages * PAGE_SIZE) / 64) & 0xff;
+ while(pages > 0) {
+ if (num_pages > pages) {
+ num_pages = pages;
+ stride = ((num_pages * PAGE_SIZE) / 64) & 0xff;
+ }
+ c = pages / num_pages;
+ if (c >= 8192) {
+ c = 8191;
+ }
+ cmd[0] = CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16);
+ cmd[1] = GMC_SRC_PITCH_OFFSET_CNTL |
+ GMC_DST_PITCH_OFFSET_CNTL |
+ GMC_BRUSH_NONE |
+ (0x6 << 8) |
+ GMC_SRC_DATATYPE_COLOR |
+ ROP3_S |
+ DP_SRC_SOURCE_MEMORY |
+ GMC_CLR_CMP_CNTL_DIS |
+ GMC_WR_MSK_DIS;
+ cmd[2] = (stride << 22) | (src_offset >> 10);
+ cmd[3] = (stride << 22) | (dst_offset >> 10);
+ cmd[4] = (0 << 16) | 0;
+ cmd[5] = (0 << 16) | 0;
+ cmd[6] = ((stride * 16) << 16) | c;
+ radeon_ms_ring_emit(dev, cmd, 7);
+ offset_inc = num_pages * c * PAGE_SIZE;
+ src_offset += offset_inc;
+ dst_offset += offset_inc;
+ pages -= num_pages * c;
+ }
+ /* wait for 2d engine to go busy so wait_until stall */
+ for (c = 0; c < dev_priv->usec_timeout; c++) {
+ uint32_t status = MMIO_R(RBBM_STATUS);
+ if ((RBBM_STATUS__E2_BUSY & status) ||
+ (RBBM_STATUS__CBA2D_BUSY & status)) {
+ DRM_INFO("[radeon_ms] RBBM_STATUS 0x%08X\n", status);
+ break;
+ }
+ DRM_UDELAY(1);
+ }
+ /* Sync everything up */
+ cmd[0] = CP_PACKET0(WAIT_UNTIL, 0);
+ cmd[1] = WAIT_UNTIL__WAIT_2D_IDLECLEAN |
+ WAIT_UNTIL__WAIT_HOST_IDLECLEAN;
+ radeon_ms_ring_emit(dev, cmd, 2);
+ return;
+}
+
+static int radeon_ms_bo_move_blit(struct drm_buffer_object *bo,
+ int evict, int no_wait,
+ struct drm_bo_mem_reg *new_mem)
+{
+ struct drm_device *dev = bo->dev;
+ struct drm_bo_mem_reg *old_mem = &bo->mem;
+ uint32_t gpu_src_addr;
+ uint32_t gpu_dst_addr;
+ int ret;
+
+ ret = radeon_ms_bo_get_gpu_addr(dev, old_mem, &gpu_src_addr);
+ if (ret) {
+ return ret;
+ }
+ ret = radeon_ms_bo_get_gpu_addr(dev, new_mem, &gpu_dst_addr);
+ if (ret) {
+ return ret;
+ }
+
+ radeon_ms_bo_copy_blit(bo->dev,
+ gpu_src_addr,
+ gpu_dst_addr,
+ new_mem->num_pages);
+
+ ret = drm_bo_move_accel_cleanup(bo, evict, no_wait, 0,
+ DRM_FENCE_TYPE_EXE |
+ DRM_RADEON_FENCE_TYPE_RW,
+ DRM_RADEON_FENCE_FLAG_FLUSHED,
+ new_mem);
+ return ret;
+}
+
+static int radeon_ms_bo_move_flip(struct drm_buffer_object *bo,
+ int evict, int no_wait,
+ struct drm_bo_mem_reg *new_mem)
+{
+ struct drm_device *dev = bo->dev;
+ struct drm_bo_mem_reg tmp_mem;
+ int ret;
+
+ tmp_mem = *new_mem;
+ tmp_mem.mm_node = NULL;
- ret = drm_bind_ttm(bo->ttm, &tmp_mem);
++ tmp_mem.flags = DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_CACHED |
+ DRM_BO_FLAG_FORCE_CACHING;
+ ret = drm_bo_mem_space(bo, &tmp_mem, no_wait);
+ if (ret) {
+ return ret;
+ }
+
- uint32_t radeon_ms_evict_mask(struct drm_buffer_object *bo)
++ ret = drm_ttm_bind(bo->ttm, &tmp_mem);
+ if (ret) {
+ goto out_cleanup;
+ }
+ ret = radeon_ms_bo_move_blit(bo, 1, no_wait, &tmp_mem);
+ if (ret) {
+ goto out_cleanup;
+ }
+ ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem);
+out_cleanup:
+ if (tmp_mem.mm_node) {
+ mutex_lock(&dev->struct_mutex);
+ if (tmp_mem.mm_node != bo->pinned_node)
+ drm_mm_put_block(tmp_mem.mm_node);
+ tmp_mem.mm_node = NULL;
+ mutex_unlock(&dev->struct_mutex);
+ }
+ return ret;
+}
+
+int radeon_ms_bo_get_gpu_addr(struct drm_device *dev,
+ struct drm_bo_mem_reg *mem,
+ uint32_t *gpu_addr)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+
+ *gpu_addr = mem->mm_node->start << PAGE_SHIFT;
+ switch (mem->flags & DRM_BO_MASK_MEM) {
+ case DRM_BO_FLAG_MEM_TT:
+ *gpu_addr += dev_priv->gpu_gart_start;
+ DRM_INFO("[radeon_ms] GPU TT: 0x%08X\n", *gpu_addr);
+ break;
+ case DRM_BO_FLAG_MEM_VRAM:
+ *gpu_addr += dev_priv->gpu_vram_start;
+ DRM_INFO("[radeon_ms] GPU VRAM: 0x%08X\n", *gpu_addr);
+ break;
+ default:
+ DRM_ERROR("[radeon_ms] memory not accessible by GPU\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int radeon_ms_bo_move(struct drm_buffer_object *bo, int evict,
+ int no_wait, struct drm_bo_mem_reg *new_mem)
+{
+ struct drm_bo_mem_reg *old_mem = &bo->mem;
+ if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
+ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+ } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
+ if (radeon_ms_bo_move_flip(bo, evict, no_wait, new_mem))
+ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+ } else {
+ if (radeon_ms_bo_move_blit(bo, evict, no_wait, new_mem))
+ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+ }
+ return 0;
+}
+
+struct drm_ttm_backend *radeon_ms_create_ttm_backend(struct drm_device * dev)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+
+ if (dev_priv && dev_priv->create_ttm)
+ return dev_priv->create_ttm(dev);
+ return NULL;
+}
+
++uint64_t radeon_ms_evict_flags(struct drm_buffer_object *bo)
+{
+ switch (bo->mem.mem_type) {
+ case DRM_BO_MEM_LOCAL:
+ case DRM_BO_MEM_TT:
+ return DRM_BO_FLAG_MEM_LOCAL;
+ case DRM_BO_MEM_VRAM:
+ if (bo->mem.num_pages > 128)
+ return DRM_BO_MEM_TT;
+ else
+ return DRM_BO_MEM_LOCAL;
+ default:
+ return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED;
+ }
+}
+
+int radeon_ms_init_mem_type(struct drm_device * dev, uint32_t type,
+ struct drm_mem_type_manager * man)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+
+ switch (type) {
+ case DRM_BO_MEM_LOCAL:
+ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+ _DRM_FLAG_MEMTYPE_CACHED;
+ man->drm_bus_maptype = 0;
+ break;
+ case DRM_BO_MEM_VRAM:
+ man->flags = _DRM_FLAG_MEMTYPE_FIXED |
+ _DRM_FLAG_MEMTYPE_MAPPABLE |
+ _DRM_FLAG_NEEDS_IOREMAP;
+ man->io_addr = NULL;
+ man->drm_bus_maptype = _DRM_FRAME_BUFFER;
+ man->io_offset = dev_priv->vram.offset;
+ man->io_size = dev_priv->vram.size;
+ break;
+ case DRM_BO_MEM_TT:
+ if (!dev_priv->bus_ready) {
+ DRM_ERROR("Bus isn't initialized while "
+ "intializing TT memory type\n");
+ return -EINVAL;
+ }
+ switch(dev_priv->bus_type) {
+ case RADEON_AGP:
+ if (!(drm_core_has_AGP(dev) && dev->agp)) {
+ DRM_ERROR("AGP is not enabled for memory "
+ "type %u\n", (unsigned)type);
+ return -EINVAL;
+ }
+ man->io_offset = dev->agp->agp_info.aper_base;
+ man->io_size = dev->agp->agp_info.aper_size *
+ 1024 * 1024;
+ man->io_addr = NULL;
+ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
+ _DRM_FLAG_MEMTYPE_CSELECT |
+ _DRM_FLAG_NEEDS_IOREMAP;
+ man->drm_bus_maptype = _DRM_AGP;
+ man->gpu_offset = 0;
+ break;
+ default:
+ man->io_offset = dev_priv->gpu_gart_start;
+ man->io_size = dev_priv->gpu_gart_size;
+ man->io_addr = NULL;
+ man->flags = _DRM_FLAG_MEMTYPE_CSELECT |
+ _DRM_FLAG_MEMTYPE_MAPPABLE |
+ _DRM_FLAG_MEMTYPE_CMA;
+ man->drm_bus_maptype = _DRM_SCATTER_GATHER;
+ break;
+ }
+ break;
+ default:
+ DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int radeon_ms_invalidate_caches(struct drm_device * dev, uint64_t flags)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+
+ dev_priv->flush_cache(dev);
+ return 0;
+}
+
+void radeon_ms_ttm_flush(struct drm_ttm *ttm)
+{
+ if (!ttm)
+ return;
+
+ DRM_MEMORYBARRIER();
+}
--- /dev/null
- .evict_mask = radeon_ms_evict_mask,
+/*
+ * Copyright 2007 Jérôme Glisse
+ * Copyright 2007 Alex Deucher
+ * Copyright 2007 Dave Airlie
+ * 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, 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
+ * PRECISION INSIGHT 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:
+ * Jerome Glisse <glisse@freedesktop.org>
+ */
+#include "drm_pciids.h"
+#include "radeon_ms.h"
+
+
+static uint32_t radeon_ms_mem_prios[] = {
+ DRM_BO_MEM_VRAM,
+ DRM_BO_MEM_TT,
+ DRM_BO_MEM_LOCAL,
+};
+
+static uint32_t radeon_ms_busy_prios[] = {
+ DRM_BO_MEM_TT,
+ DRM_BO_MEM_VRAM,
+ DRM_BO_MEM_LOCAL,
+};
+
+struct drm_fence_driver radeon_ms_fence_driver = {
+ .num_classes = 1,
+ .wrap_diff = (1 << 30),
+ .flush_diff = (1 << 29),
+ .sequence_mask = 0xffffffffU,
+ .lazy_capable = 1,
+ .emit = radeon_ms_fence_emit_sequence,
+ .poke_flush = radeon_ms_poke_flush,
+ .has_irq = radeon_ms_fence_has_irq,
+};
+
+struct drm_bo_driver radeon_ms_bo_driver = {
+ .mem_type_prio = radeon_ms_mem_prios,
+ .mem_busy_prio = radeon_ms_busy_prios,
+ .num_mem_type_prio = sizeof(radeon_ms_mem_prios)/sizeof(uint32_t),
+ .num_mem_busy_prio = sizeof(radeon_ms_busy_prios)/sizeof(uint32_t),
+ .create_ttm_backend_entry = radeon_ms_create_ttm_backend,
+ .fence_type = radeon_ms_fence_types,
+ .invalidate_caches = radeon_ms_invalidate_caches,
+ .init_mem_type = radeon_ms_init_mem_type,
++ .evict_flags = radeon_ms_evict_flags,
+ .move = radeon_ms_bo_move,
+ .ttm_cache_flush = radeon_ms_ttm_flush,
+};
+
+struct drm_ioctl_desc radeon_ms_ioctls[] = {
+ DRM_IOCTL_DEF(DRM_RADEON_EXECBUFFER, radeon_ms_execbuffer, DRM_AUTH),
+};
+int radeon_ms_num_ioctls = DRM_ARRAY_SIZE(radeon_ms_ioctls);
+
+int radeon_ms_driver_dma_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_dma *d = data;
+
+ LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+ /* Please don't send us buffers.
+ */
+ if (d->send_count != 0) {
+ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+ DRM_CURRENTPID, d->send_count);
+ return -EINVAL;
+ }
+
+ /* Don't ask us buffer neither :)
+ */
+ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+ DRM_CURRENTPID, d->request_count, dma->buf_count);
+ return -EINVAL;
+}
+
+void radeon_ms_driver_lastclose(struct drm_device * dev)
+{
+}
+
+int radeon_ms_driver_load(struct drm_device *dev, unsigned long flags)
+{
+ struct drm_radeon_private *dev_priv;
+ int ret = 0;
+
+ DRM_INFO("[radeon_ms] loading\n");
+ /* allocate and clear device private structure */
+ dev_priv = drm_alloc(sizeof(struct drm_radeon_private), DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return -ENOMEM;
+ memset(dev_priv, 0, sizeof(struct drm_radeon_private));
+ dev->dev_private = (void *)dev_priv;
+
+ /* initialize modesetting structure (must be done here) */
+ drm_mode_config_init(dev);
+
+ /* flags correspond to chipset family */
+ dev_priv->usec_timeout = 100;
+ dev_priv->family = flags & 0xffffU;
+ dev_priv->bus_type = flags & 0xff0000U;
+ /* initialize family functions */
+ ret = radeon_ms_family_init(dev);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+
+ /* we don't want userspace to be able to map this so don't use
+ * drm_addmap */
+ dev_priv->mmio.offset = drm_get_resource_start(dev, 2);
+ dev_priv->mmio.size = drm_get_resource_len(dev, 2);
+ dev_priv->mmio.type = _DRM_REGISTERS;
+ dev_priv->mmio.flags = _DRM_RESTRICTED;
+ drm_core_ioremap(&dev_priv->mmio, dev);
+ /* map vram FIXME: IGP likely don't have any of this */
+ dev_priv->vram.offset = drm_get_resource_start(dev, 0);
+ dev_priv->vram.size = drm_get_resource_len(dev, 0);
+ dev_priv->vram.type = _DRM_FRAME_BUFFER;
+ dev_priv->vram.flags = _DRM_RESTRICTED;
+ drm_core_ioremap(&dev_priv->vram, dev);
+
+ /* save radeon initial state which will be restored upon module
+ * exit */
+ radeon_ms_state_save(dev, &dev_priv->load_state);
+ dev_priv->restore_state = 1;
+ memcpy(&dev_priv->driver_state, &dev_priv->load_state,
+ sizeof(struct radeon_state));
+
+ /* initialize irq */
+ ret = radeon_ms_irq_init(dev);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+
+ /* init bo driver */
+ dev_priv->fence_id_last = 1;
+ dev_priv->fence_reg = SCRATCH_REG2;
+ drm_bo_driver_init(dev);
+ /* initialize vram */
+ ret = drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, dev_priv->vram.size);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+
+ /* initialize gpu address space (only after) VRAM initialization */
+ ret = radeon_ms_gpu_initialize(dev);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+ radeon_ms_gpu_restore(dev, &dev_priv->driver_state);
+
+ /* initialize ttm */
+ ret = drm_bo_init_mm(dev, DRM_BO_MEM_TT, 0,
+ dev_priv->gpu_gart_size / RADEON_PAGE_SIZE);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+
+ /* initialize ring buffer */
+ /* set ring size to 4Mo FIXME: should make a parameter for this */
+ dev_priv->write_back_area_size = 4 * 1024;
+ dev_priv->ring_buffer_size = 4 * 1024 * 1024;
+ ret = radeon_ms_cp_init(dev);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+
+ /* initialize modesetting */
+ dev->mode_config.min_width = 0;
+ dev->mode_config.min_height = 0;
+ dev->mode_config.max_width = 4096;
+ dev->mode_config.max_height = 4096;
+ dev->mode_config.fb_base = dev_priv->vram.offset;
+ ret = radeon_ms_crtc_create(dev, 1);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+ ret = radeon_ms_outputs_from_rom(dev);
+ if (ret < 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ } else if (!ret) {
+ ret = radeon_ms_outputs_from_properties(dev);
+ if (ret < 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ } else if (ret == 0) {
+ DRM_INFO("[radeon_ms] no outputs !\n");
+ }
+ } else {
+ DRM_INFO("[radeon_ms] added %d outputs from rom.\n", ret);
+ }
+ ret = radeon_ms_connectors_from_rom(dev);
+ if (ret < 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ } else if (!ret) {
+ ret = radeon_ms_connectors_from_properties(dev);
+ if (ret < 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ } else if (!ret) {
+ DRM_INFO("[radeon_ms] no connectors !\n");
+ }
+ } else {
+ DRM_INFO("[radeon_ms] added %d connectors from rom.\n", ret);
+ }
+ radeon_ms_outputs_save(dev, &dev_priv->load_state);
+ drm_initial_config(dev, false);
+
+ ret = drm_irq_install(dev);
+ if (ret != 0) {
+ radeon_ms_driver_unload(dev);
+ return ret;
+ }
+
+ DRM_INFO("[radeon_ms] successfull initialization\n");
+ return 0;
+}
+
+int radeon_ms_driver_open(struct drm_device * dev, struct drm_file *file_priv)
+{
+ return 0;
+}
+
+
+int radeon_ms_driver_unload(struct drm_device *dev)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+
+ if (dev_priv == NULL) {
+ return 0;
+ }
+
+ /* cleanup modesetting */
+ drm_mode_config_cleanup(dev);
+ DRM_INFO("[radeon_ms] modesetting clean\n");
+ radeon_ms_outputs_restore(dev, &dev_priv->load_state);
+ radeon_ms_connectors_destroy(dev);
+ radeon_ms_outputs_destroy(dev);
+
+ /* shutdown cp engine */
+ radeon_ms_cp_finish(dev);
+ DRM_INFO("[radeon_ms] cp clean\n");
+
+ drm_irq_uninstall(dev);
+ DRM_INFO("[radeon_ms] irq uninstalled\n");
+
+ DRM_INFO("[radeon_ms] unloading\n");
+ /* clean ttm memory manager */
+ mutex_lock(&dev->struct_mutex);
+ if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT)) {
+ DRM_ERROR("TT memory manager not clean. Delaying takedown\n");
+ }
+ mutex_unlock(&dev->struct_mutex);
+ DRM_INFO("[radeon_ms] TT memory clean\n");
+ /* finish */
+ if (dev_priv->bus_finish) {
+ dev_priv->bus_finish(dev);
+ }
+ DRM_INFO("[radeon_ms] bus down\n");
+ /* clean vram memory manager */
+ mutex_lock(&dev->struct_mutex);
+ if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM)) {
+ DRM_ERROR("VRAM memory manager not clean. Delaying takedown\n");
+ }
+ mutex_unlock(&dev->struct_mutex);
+ DRM_INFO("[radeon_ms] VRAM memory clean\n");
+ /* clean memory manager */
+ drm_bo_driver_finish(dev);
+ DRM_INFO("[radeon_ms] memory manager clean\n");
+ /* restore card state */
+ if (dev_priv->restore_state) {
+ radeon_ms_state_restore(dev, &dev_priv->load_state);
+ }
+ DRM_INFO("[radeon_ms] state restored\n");
+ if (dev_priv->mmio.handle) {
+ drm_core_ioremapfree(&dev_priv->mmio, dev);
+ }
+ if (dev_priv->vram.handle) {
+ drm_core_ioremapfree(&dev_priv->vram, dev);
+ }
+ DRM_INFO("[radeon_ms] map released\n");
+ drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+
+ DRM_INFO("[radeon_ms] that's all the folks\n");
+ return 0;
+}
+