summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2008-09-18 10:05:59 +1000
committerDave Airlie <airlied@linux.ie>2008-09-18 10:11:23 +1000
commit2a6dad31d84252d505f392f91dffd90689bb947c (patch)
tree36bde832fbc9d4aae3328ad97e7b75bf687b79f0 /shared-core
parent1062d8dcff19ded743f046e27adb889f3596ab4d (diff)
radeon: add initial suspend/resume support
plus a bunch of fixes
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/radeon_cp.c103
-rw-r--r--shared-core/radeon_drv.h21
2 files changed, 90 insertions, 34 deletions
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index 6b71360f..a34c6530 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -521,7 +521,6 @@ static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
DRM_DEBUG("\n");
#if 0
u32 tmp;
-
tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
#endif
@@ -761,8 +760,6 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
dev_priv->ring.size_l2qw);
#endif
- /* Start with assuming that writeback doesn't work */
- dev_priv->writeback_works = 0;
/* Initialize the scratch register pointer. This will cause
* the scratch register values to be written out to memory
@@ -1341,6 +1338,9 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
radeon_set_pcigart(dev_priv, 1);
}
+ /* Start with assuming that writeback doesn't work */
+ dev_priv->writeback_works = 0;
+
radeon_cp_load_microcode(dev_priv);
radeon_cp_init_ring_buffer(dev, dev_priv);
@@ -2301,14 +2301,64 @@ static void radeon_set_dynamic_clock(struct drm_device *dev, int mode)
}
-int radeon_modeset_cp_init(struct drm_device *dev)
+int radeon_modeset_cp_suspend(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int ret;
+
+ ret = radeon_do_cp_idle(dev_priv);
+ if (ret)
+ DRM_ERROR("failed to idle CP on suspend\n");
+
+ radeon_do_cp_stop(dev_priv);
+ radeon_do_engine_reset(dev);
+ if (dev_priv->flags & RADEON_IS_AGP) {
+ } else {
+ radeon_set_pcigart(dev_priv, 0);
+ }
+
+ return 0;
+}
+
+int radeon_modeset_cp_resume(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
uint32_t tmp;
+ radeon_do_wait_for_idle(dev_priv);
+#if __OS_HAS_AGP
+ if (dev_priv->flags & RADEON_IS_AGP) {
+ /* Turn off PCI GART */
+ radeon_set_pcigart(dev_priv, 0);
+ } else
+#endif
+ {
+ /* Turn on PCI GART */
+ radeon_set_pcigart(dev_priv, 1);
+ }
+ radeon_gart_flush(dev);
+
+ DRM_ERROR("microcode loading\n");
+ radeon_cp_load_microcode(dev_priv);
+ radeon_cp_init_ring_buffer(dev, dev_priv);
+
+ DRM_ERROR("engine init\n");
+ radeon_do_engine_reset(dev);
+
+ radeon_do_cp_start(dev_priv);
+ return 0;
+}
+
+int radeon_modeset_cp_init(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
/* allocate a ring and ring rptr bits from GART space */
/* these are allocated in GEM files */
+ /* Start with assuming that writeback doesn't work */
+ dev_priv->writeback_works = 0;
+
dev_priv->usec_timeout = RADEON_DEFAULT_CP_TIMEOUT;
dev_priv->ring.size = RADEON_DEFAULT_RING_SIZE;
dev_priv->cp_mode = RADEON_CSQ_PRIBM_INDBM;
@@ -2327,23 +2377,8 @@ int radeon_modeset_cp_init(struct drm_device *dev)
dev_priv->new_memmap = true;
r300_init_reg_flags(dev);
-
- radeon_cp_load_microcode(dev_priv);
- DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring.bo->offset, dev_priv->mm.ring_read.bo->offset);
-
- radeon_cp_init_ring_buffer(dev, dev_priv);
-
- /* need to enable BUS mastering in Buscntl */
- tmp = RADEON_READ(RADEON_BUS_CNTL);
- tmp &= ~RADEON_BUS_MASTER_DIS;
- RADEON_WRITE(RADEON_BUS_CNTL, tmp);
-
- radeon_do_engine_reset(dev);
- radeon_test_writeback(dev_priv);
-
- radeon_do_cp_start(dev_priv);
- return 0;
+ return radeon_modeset_cp_resume(dev);
}
static bool radeon_get_bios(struct drm_device *dev)
@@ -2418,6 +2453,20 @@ int radeon_modeset_preinit(struct drm_device *dev)
return 0;
}
+int radeon_static_clocks_init(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if ((dev_priv->flags & RADEON_IS_MOBILITY) && !radeon_is_avivo(dev_priv)) {
+ radeon_set_dynamic_clock(dev, radeon_dynclks);
+ } else if (radeon_is_avivo(dev_priv)) {
+ if (radeon_dynclks) {
+ radeon_atom_static_pwrmgt_setup(dev, 1);
+ radeon_atom_dyn_clk_setup(dev, 1);
+ }
+ }
+ radeon_force_some_clocks(dev);
+}
int radeon_driver_load(struct drm_device *dev, unsigned long flags)
{
@@ -2473,7 +2522,6 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
if (drm_core_check_feature(dev, DRIVER_MODESET))
radeon_modeset_preinit(dev);
-
radeon_get_vram_type(dev);
dev_priv->pll_errata = 0;
@@ -2493,17 +2541,8 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
dev_priv->pll_errata |= CHIP_ERRATA_PLL_DELAY;
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- if ((dev_priv->flags & RADEON_IS_MOBILITY) && !radeon_is_avivo(dev_priv)) {
- radeon_set_dynamic_clock(dev, radeon_dynclks);
- } else if (radeon_is_avivo(dev_priv)) {
- if (radeon_dynclks) {
- radeon_atom_static_pwrmgt_setup(dev, 1);
- radeon_atom_dyn_clk_setup(dev, 1);
- }
- }
- radeon_force_some_clocks(dev);
- }
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ radeon_static_clocks_init(dev);
/* init memory manager - start with all of VRAM and a 32MB GART aperture for now */
dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index 019491c7..662d9cc3 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -273,6 +273,8 @@ struct radeon_mm_info {
uint64_t gart_start;
uint64_t gart_size;
+
+ void *pcie_table_backup;
struct radeon_mm_obj pcie_table;
struct radeon_mm_obj ring;
@@ -314,6 +316,11 @@ struct drm_radeon_cs_priv {
uint32_t *reloc, uint32_t *offset);
};
+struct radeon_pm_regs {
+ uint32_t crtc_ext_cntl;
+ uint32_t bios_scratch[8];
+};
+
typedef struct drm_radeon_private {
drm_radeon_ring_buffer_t ring;
@@ -432,6 +439,8 @@ typedef struct drm_radeon_private {
/* ib bitmap */
uint64_t ib_alloc_bitmap; // TO DO replace with a real bitmap
struct drm_radeon_cs_priv cs;
+
+ struct radeon_pm_regs pmregs;
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
@@ -527,6 +536,11 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
struct drm_file *file_priv,
drm_radeon_kcmd_buffer_t *cmdbuf);
+extern int radeon_modeset_cp_suspend(struct drm_device *dev);
+extern int radeon_modeset_cp_resume(struct drm_device *dev);
+/* radeon_pm.c */
+int radeon_suspend(struct drm_device *dev, pm_message_t state);
+int radeon_resume(struct drm_device *dev);
/* Flags for stats.boxes
*/
#define RADEON_BOX_DMA_IDLE 0x1
@@ -1464,7 +1478,7 @@ do { \
* Ring control
*/
-#define RADEON_VERBOSE 0
+#define RADEON_VERBOSE 1
#define RING_LOCALS int write, _nr; unsigned int mask; u32 *ring;
@@ -1648,7 +1662,8 @@ extern int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
extern int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int radeon_gem_object_pin(struct drm_gem_object *obj,
- uint32_t alignment);
+ uint32_t alignment, uint32_t pin_domain);
+int radeon_gem_object_unpin(struct drm_gem_object *obj);
int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
@@ -1670,6 +1685,8 @@ extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *
extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv);
extern int radeon_cs_init(struct drm_device *dev);
void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master);
+void radeon_init_memory_map(struct drm_device *dev);
+
#define MARK_SAFE 1
#define MARK_CHECK_OFFSET 2