summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/atom.c2
-rw-r--r--linux-core/drm_bo.c53
-rw-r--r--linux-core/drm_fence.c3
-rw-r--r--linux-core/drm_objects.h1
-rw-r--r--linux-core/radeon_drv.c22
-rw-r--r--linux-core/radeon_fb.c2
-rw-r--r--linux-core/radeon_fence.c3
-rw-r--r--linux-core/radeon_gem.c59
-rw-r--r--linux-core/radeon_pm.c180
9 files changed, 287 insertions, 38 deletions
diff --git a/linux-core/atom.c b/linux-core/atom.c
index 33fb02f0..2a660a4f 100644
--- a/linux-core/atom.c
+++ b/linux-core/atom.c
@@ -270,7 +270,6 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr, int *ptr,
if(print)
DEBUG("MC[0x%02X]", idx);
val = gctx->card->mc_read(gctx->card, idx);
- printk(KERN_INFO "MC registers are not implemented.\n");
return 0;
}
if(saved)
@@ -452,7 +451,6 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr, int *ptr
(*ptr)++;
DEBUG("MC[0x%02X]", idx);
gctx->card->mc_write(gctx->card, idx, val);
- printk(KERN_INFO "MC registers are not implemented.\n");
return;
}
switch(align) {
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index e3ee497a..fa3e055d 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -511,6 +511,7 @@ static void drm_bo_delayed_delete(struct drm_device *dev, int remove_all)
entry = list_entry(list, struct drm_buffer_object, ddestroy);
nentry = NULL;
+ DRM_DEBUG("bo is %p, %d\n", entry, entry->num_pages);
if (next != &bm->ddestroy) {
nentry = list_entry(next, struct drm_buffer_object,
ddestroy);
@@ -1330,14 +1331,15 @@ static int drm_bo_prepare_for_validate(struct drm_buffer_object *bo,
int ret;
- DRM_DEBUG("Proposed flags 0x%016llx, Old flags 0x%016llx\n",
- (unsigned long long) bo->mem.proposed_flags,
- (unsigned long long) bo->mem.flags);
ret = drm_bo_modify_proposed_flags (bo, flags, mask);
if (ret)
return ret;
+ DRM_DEBUG("Proposed flags 0x%016llx, Old flags 0x%016llx\n",
+ (unsigned long long) bo->mem.proposed_flags,
+ (unsigned long long) bo->mem.flags);
+
ret = drm_bo_wait_unmapped(bo, no_wait);
if (ret)
return ret;
@@ -2084,3 +2086,48 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)
return 0;
}
+
+/* used to EVICT VRAM lru at suspend time */
+void drm_bo_evict_mm(struct drm_device *dev, int mem_type, int no_wait)
+{
+ struct drm_buffer_manager *bm = &dev->bm;
+ struct drm_mem_type_manager *man = &bm->man[mem_type];
+ struct drm_buffer_object *entry;
+ /* we need to migrate all objects in VRAM */
+ struct list_head *lru;
+ int ret;
+ /* evict all buffers on the LRU - won't evict pinned buffers */
+
+ mutex_lock(&dev->struct_mutex);
+ do {
+ lru = &man->lru;
+
+ if (lru->next == lru) {
+ DRM_ERROR("lru empty\n");
+ break;
+ }
+
+ entry = list_entry(lru->next, struct drm_buffer_object, lru);
+ atomic_inc(&entry->usage);
+ mutex_unlock(&dev->struct_mutex);
+ mutex_lock(&entry->mutex);
+
+ DRM_ERROR("Evicting %p %d\n", entry, entry->num_pages);
+ ret = drm_bo_evict(entry, mem_type, no_wait);
+ mutex_unlock(&entry->mutex);
+
+ if (ret)
+ DRM_ERROR("Evict failed for BO\n");
+
+ mutex_lock(&entry->mutex);
+ (void)drm_bo_expire_fence(entry, 0);
+ mutex_unlock(&entry->mutex);
+ drm_bo_usage_deref_unlocked(&entry);
+
+ mutex_lock(&dev->struct_mutex);
+ } while(0);
+
+ mutex_unlock(&dev->struct_mutex);
+
+}
+EXPORT_SYMBOL(drm_bo_evict_mm);
diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index 7130d1b0..f1c386c4 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -381,7 +381,6 @@ int drm_fence_object_wait(struct drm_fence_object *fence,
if (driver->wait)
return driver->wait(fence, lazy, !ignore_signals, mask);
-
drm_fence_object_flush(fence, mask);
if (driver->has_irq(dev, fence->fence_class, mask)) {
if (!ignore_signals)
@@ -409,8 +408,6 @@ int drm_fence_object_wait(struct drm_fence_object *fence,
}
EXPORT_SYMBOL(drm_fence_object_wait);
-
-
int drm_fence_object_emit(struct drm_fence_object *fence, uint32_t fence_flags,
uint32_t fence_class, uint32_t type)
{
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index e13475a2..acb10f96 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -796,6 +796,7 @@ extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_
extern int drm_bo_evict_cached(struct drm_buffer_object *bo);
extern void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo);
+extern void drm_bo_evict_mm(struct drm_device *dev, int mem_type, int no_wait);
/*
* Buffer object memory move- and map helpers.
* drm_bo_move.c
diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c
index 7676ca4c..9b3397ca 100644
--- a/linux-core/radeon_drv.c
+++ b/linux-core/radeon_drv.c
@@ -59,28 +59,6 @@ static int dri_library_name(struct drm_device * dev, char * buf)
"r300"));
}
-static int radeon_suspend(struct drm_device *dev, pm_message_t state)
-{
- drm_radeon_private_t *dev_priv = dev->dev_private;
-
- /* Disable *all* interrupts */
- if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
- RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
- RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
- return 0;
-}
-
-static int radeon_resume(struct drm_device *dev)
-{
- drm_radeon_private_t *dev_priv = dev->dev_private;
-
- /* Restore interrupt registers */
- if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
- RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
- RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
- return 0;
-}
-
static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
diff --git a/linux-core/radeon_fb.c b/linux-core/radeon_fb.c
index 5cb118c5..86459674 100644
--- a/linux-core/radeon_fb.c
+++ b/linux-core/radeon_fb.c
@@ -736,7 +736,7 @@ int radeonfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_heigh
}
obj_priv = fbo->driver_private;
- ret = radeon_gem_object_pin(fbo, PAGE_SIZE);
+ ret = radeon_gem_object_pin(fbo, PAGE_SIZE, RADEON_GEM_DOMAIN_VRAM);
if (ret) {
DRM_ERROR("failed to pin fb: %d\n", ret);
mutex_lock(&dev->struct_mutex);
diff --git a/linux-core/radeon_fence.c b/linux-core/radeon_fence.c
index 1b327369..591ad53b 100644
--- a/linux-core/radeon_fence.c
+++ b/linux-core/radeon_fence.c
@@ -45,6 +45,8 @@ int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class,
return -EINVAL;
radeon_emit_irq(dev);
+
+ DRM_DEBUG("emitting %d\n", dev_priv->counter);
*sequence = (uint32_t) dev_priv->counter;
*native_type = DRM_FENCE_TYPE_EXE;
@@ -60,6 +62,7 @@ static void radeon_fence_poll(struct drm_device *dev, uint32_t fence_class,
sequence = READ_BREADCRUMB(dev_priv);
+ DRM_DEBUG("polling %d\n", sequence);
drm_fence_handler(dev, 0, sequence,
DRM_FENCE_TYPE_EXE, 0);
}
diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c
index 24c806a1..98105e7c 100644
--- a/linux-core/radeon_gem.c
+++ b/linux-core/radeon_gem.c
@@ -43,7 +43,6 @@ int radeon_gem_init_object(struct drm_gem_object *obj)
obj->driver_private = obj_priv;
obj_priv->obj = obj;
-
return 0;
}
@@ -320,6 +319,8 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
int ret;
+ int flags = DRM_BO_FLAG_NO_EVICT;
+ int mask = DRM_BO_FLAG_NO_EVICT;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
@@ -329,15 +330,24 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage));
/* validate into a pin with no fence */
+ if (args->pin_domain) {
+ mask |= DRM_BO_MASK_MEM;
+ if (args->pin_domain == RADEON_GEM_DOMAIN_GTT)
+ flags |= DRM_BO_FLAG_MEM_TT;
+ else if (args->pin_domain == RADEON_GEM_DOMAIN_VRAM)
+ flags |= DRM_BO_FLAG_MEM_VRAM;
+ else
+ return -EINVAL;
+ }
if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) {
- ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT,
+ ret = drm_bo_do_validate(obj_priv->bo, flags, mask,
DRM_BO_HINT_DONT_FENCE, 0);
} else
ret = 0;
args->offset = obj_priv->bo->offset;
- DRM_DEBUG("got here %p %p\n", obj, obj_priv->bo);
+ DRM_DEBUG("got here %p %p %x\n", obj, obj_priv->bo, obj_priv->bo->offset);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
@@ -361,7 +371,7 @@ int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data,
/* validate into a pin with no fence */
- ret = drm_bo_do_validate(obj_priv->bo, DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT,
+ ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT,
DRM_BO_HINT_DONT_FENCE, 0);
mutex_lock(&dev->struct_mutex);
@@ -598,7 +608,11 @@ static int radeon_gart_init(struct drm_device *dev)
if (ret)
return -EINVAL;
- DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset);
+ dev_priv->mm.pcie_table_backup = kzalloc(RADEON_PCIGART_TABLE_SIZE, GFP_KERNEL);
+ if (!dev_priv->mm.pcie_table_backup)
+ return -EINVAL;
+
+ DRM_ERROR("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset);
ret = drm_bo_kmap(dev_priv->mm.pcie_table.bo, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT,
&dev_priv->mm.pcie_table.kmap);
if (ret)
@@ -690,10 +704,11 @@ int radeon_alloc_gart_objects(struct drm_device *dev)
}
-static void radeon_init_memory_map(struct drm_device *dev)
+void radeon_init_memory_map(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
u32 mem_size, aper_size;
+ u32 tmp;
dev_priv->mc_fb_location = radeon_read_fb_location(dev_priv);
radeon_read_agp_location(dev_priv, &dev_priv->mc_agp_loc_lo, &dev_priv->mc_agp_loc_hi);
@@ -841,6 +856,10 @@ void radeon_gem_mm_fini(struct drm_device *dev)
}
if (dev_priv->flags & RADEON_IS_PCIE) {
+ if (dev_priv->mm.pcie_table_backup) {
+ kfree(dev_priv->mm.pcie_table_backup);
+ dev_priv->mm.pcie_table_backup = NULL;
+ }
if (dev_priv->mm.pcie_table.bo) {
drm_bo_kunmap(&dev_priv->mm.pcie_table.kmap);
drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table.bo);
@@ -858,7 +877,31 @@ void radeon_gem_mm_fini(struct drm_device *dev)
}
int radeon_gem_object_pin(struct drm_gem_object *obj,
- uint32_t alignment)
+ uint32_t alignment, uint32_t pin_domain)
+{
+ struct drm_radeon_gem_object *obj_priv;
+ int ret;
+ uint32_t flags = DRM_BO_FLAG_NO_EVICT;
+ uint32_t mask = DRM_BO_FLAG_NO_EVICT;
+
+ obj_priv = obj->driver_private;
+
+ if (pin_domain) {
+ mask |= DRM_BO_MASK_MEM;
+ if (pin_domain == RADEON_GEM_DOMAIN_GTT)
+ flags |= DRM_BO_FLAG_MEM_TT;
+ else if (pin_domain == RADEON_GEM_DOMAIN_VRAM)
+ flags |= DRM_BO_FLAG_MEM_VRAM;
+ else
+ return -EINVAL;
+ }
+ ret = drm_bo_do_validate(obj_priv->bo, flags, mask,
+ DRM_BO_HINT_DONT_FENCE, 0);
+
+ return ret;
+}
+
+int radeon_gem_object_unpin(struct drm_gem_object *obj)
{
struct drm_radeon_gem_object *obj_priv;
int ret;
@@ -1335,3 +1378,5 @@ void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master
dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
}
+
+
diff --git a/linux-core/radeon_pm.c b/linux-core/radeon_pm.c
new file mode 100644
index 00000000..c7a57b97
--- /dev/null
+++ b/linux-core/radeon_pm.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * 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 shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(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.
+ *
+ * Authors: Dave Airlie
+ * Alex Deucher
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+#include "atom.h"
+
+#include "drm_crtc_helper.h"
+
+int radeon_suspend(struct drm_device *dev, pm_message_t state)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+ struct drm_framebuffer *fb;
+ int i;
+
+ if (!dev || !dev_priv) {
+ return -ENODEV;
+ }
+
+ if (state.event == PM_EVENT_PRETHAW)
+ return 0;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
+ /* unpin the front buffers */
+ list_for_each_entry(fb, &dev->mode_config.fb_kernel_list, filp_head) {
+ struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
+
+ if (!radeon_fb)
+ continue;
+
+ if (!radeon_fb->obj)
+ continue;
+
+ radeon_gem_object_unpin(radeon_fb->obj);
+ }
+
+ if (!(dev_priv->flags & RADEON_IS_IGP))
+ drm_bo_evict_mm(dev, DRM_BO_MEM_VRAM, 0);
+
+ if (dev_priv->flags & RADEON_IS_PCIE) {
+ memcpy_fromio(dev_priv->mm.pcie_table_backup, dev_priv->mm.pcie_table.kmap.virtual, RADEON_PCIGART_TABLE_SIZE);
+ }
+
+ dev_priv->pmregs.crtc_ext_cntl = RADEON_READ(RADEON_CRTC_EXT_CNTL);
+ for (i = 0; i < 8; i++)
+ dev_priv->pmregs.bios_scratch[i] = RADEON_READ(RADEON_BIOS_0_SCRATCH + (i * 4));
+
+ radeon_modeset_cp_suspend(dev);
+
+ pci_save_state(dev->pdev);
+
+ if (state.event == PM_EVENT_SUSPEND) {
+ /* Shut down the device */
+ pci_disable_device(dev->pdev);
+ pci_set_power_state(dev->pdev, PCI_D3hot);
+ }
+ return 0;
+}
+
+int radeon_resume(struct drm_device *dev)
+{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
+ struct drm_framebuffer *fb;
+ int i;
+ u32 tmp;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
+ pci_set_power_state(dev->pdev, PCI_D0);
+ pci_restore_state(dev->pdev);
+ if (pci_enable_device(dev->pdev))
+ return -1;
+ pci_set_master(dev->pdev);
+
+ /* Turn on bus mastering */
+ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+ RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+
+ /* on atom cards re init the whole card
+ and set the modes again */
+
+ if (dev_priv->is_atom_bios) {
+ struct atom_context *ctx = dev_priv->mode_info.atom_context;
+ atom_asic_init(ctx);
+ } else {
+ radeon_combios_asic_init(dev);
+ }
+
+ for (i = 0; i < 8; i++)
+ RADEON_WRITE(RADEON_BIOS_0_SCRATCH + (i * 4), dev_priv->pmregs.bios_scratch[i]);
+
+ /* VGA render mayhaps */
+ if (dev_priv->chip_family >= CHIP_RS600) {
+ uint32_t tmp;
+
+ RADEON_WRITE(AVIVO_D1VGA_CONTROL, 0);
+ RADEON_WRITE(AVIVO_D2VGA_CONTROL, 0);
+ tmp = RADEON_READ(0x300);
+ tmp &= ~(3 << 16);
+ RADEON_WRITE(0x300, tmp);
+ RADEON_WRITE(0x308, (1 << 8));
+ RADEON_WRITE(0x310, dev_priv->fb_location);
+ RADEON_WRITE(0x594, 0);
+ }
+
+ RADEON_WRITE(RADEON_CRTC_EXT_CNTL, dev_priv->pmregs.crtc_ext_cntl);
+
+ radeon_static_clocks_init(dev);
+
+ radeon_init_memory_map(dev);
+
+ if (dev_priv->flags & RADEON_IS_PCIE) {
+ memcpy_toio(dev_priv->mm.pcie_table.kmap.virtual, dev_priv->mm.pcie_table_backup, RADEON_PCIGART_TABLE_SIZE);
+ }
+
+ if (dev_priv->mm.ring.kmap.virtual)
+ memset(dev_priv->mm.ring.kmap.virtual, 0, RADEON_DEFAULT_RING_SIZE);
+
+ if (dev_priv->mm.ring_read.kmap.virtual)
+ memset(dev_priv->mm.ring_read.kmap.virtual, 0, PAGE_SIZE);
+
+ radeon_modeset_cp_resume(dev);
+
+ /* reset swi reg */
+ RADEON_WRITE(RADEON_LAST_SWI_REG, dev_priv->counter);
+
+ radeon_enable_interrupt(dev);
+
+ /* reset the context for userspace */
+ if (dev->primary->master) {
+ struct drm_radeon_master_private *master_priv = dev->primary->master->driver_priv;
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->ctx_owner = 0;
+ }
+
+ /* unpin the front buffers */
+ list_for_each_entry(fb, &dev->mode_config.fb_kernel_list, filp_head) {
+
+ struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
+
+ if (!radeon_fb)
+ continue;
+
+ if (!radeon_fb->obj)
+ continue;
+
+ radeon_gem_object_pin(radeon_fb->obj, PAGE_SIZE, RADEON_GEM_DOMAIN_VRAM);
+ }
+ /* blat the mode back in */
+ drm_helper_resume_force_mode(dev);
+
+ return 0;
+}