summary refs log tree commit diff
path: root/drivers/gpu/drm/radeon/radeon_device.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2010-02-02 23:10:39 +0100
committerJiri Kosina <jkosina@suse.cz>2010-02-02 23:10:39 +0100
commite1a0bdd8022317e98650e70850de73eccfcde5ad (patch)
tree462f63307118b95c8cbacee6954e4d09ee85b8d1 /drivers/gpu/drm/radeon/radeon_device.c
parent8127f4e883666c9960cfa89cffd36313748f8bab (diff)
parent1a45dcfe2525e9432cb4aba461d4994fc2befe42 (diff)
downloadlinux-e1a0bdd8022317e98650e70850de73eccfcde5ad.tar.gz
Merge branch 'master' into upstream
Conflicts:
	drivers/hid/hid-ids.h
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c149
1 files changed, 131 insertions, 18 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 41bb76fbe734..768b1509fa03 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -44,10 +44,11 @@ void radeon_surface_init(struct radeon_device *rdev)
 	if (rdev->family < CHIP_R600) {
 		int i;
 
-		for (i = 0; i < 8; i++) {
-			WREG32(RADEON_SURFACE0_INFO +
-			       i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
-			       0);
+		for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
+			if (rdev->surface_regs[i].bo)
+				radeon_bo_get_surface_reg(rdev->surface_regs[i].bo);
+			else
+				radeon_clear_surface_reg(rdev, i);
 		}
 		/* enable surfaces */
 		WREG32(RADEON_SURFACE_CNTL, 0);
@@ -208,6 +209,24 @@ bool radeon_card_posted(struct radeon_device *rdev)
 
 }
 
+bool radeon_boot_test_post_card(struct radeon_device *rdev)
+{
+	if (radeon_card_posted(rdev))
+		return true;
+
+	if (rdev->bios) {
+		DRM_INFO("GPU not posted. posting now...\n");
+		if (rdev->is_atom_bios)
+			atom_asic_init(rdev->mode_info.atom_context);
+		else
+			radeon_combios_asic_init(rdev->ddev);
+		return true;
+	} else {
+		dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+		return false;
+	}
+}
+
 int radeon_dummy_page_init(struct radeon_device *rdev)
 {
 	rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO);
@@ -372,6 +391,12 @@ int radeon_asic_init(struct radeon_device *rdev)
 		/* FIXME: not supported yet */
 		return -EINVAL;
 	}
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		rdev->asic->get_memory_clock = NULL;
+		rdev->asic->set_memory_clock = NULL;
+	}
+
 	return 0;
 }
 
@@ -462,13 +487,18 @@ int radeon_atombios_init(struct radeon_device *rdev)
 	atom_card_info->pll_write = cail_pll_write;
 
 	rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios);
+	mutex_init(&rdev->mode_info.atom_context->mutex);
 	radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
+	atom_allocate_fb_scratch(rdev->mode_info.atom_context);
 	return 0;
 }
 
 void radeon_atombios_fini(struct radeon_device *rdev)
 {
-	kfree(rdev->mode_info.atom_context);
+	if (rdev->mode_info.atom_context) {
+		kfree(rdev->mode_info.atom_context->scratch);
+		kfree(rdev->mode_info.atom_context);
+	}
 	kfree(rdev->mode_info.atom_card_info);
 }
 
@@ -514,11 +544,75 @@ void radeon_agp_disable(struct radeon_device *rdev)
 		rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
 		rdev->asic->gart_set_page = &r100_pci_gart_set_page;
 	}
+	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+}
+
+void radeon_check_arguments(struct radeon_device *rdev)
+{
+	/* vramlimit must be a power of two */
+	switch (radeon_vram_limit) {
+	case 0:
+	case 4:
+	case 8:
+	case 16:
+	case 32:
+	case 64:
+	case 128:
+	case 256:
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		break;
+	default:
+		dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
+				radeon_vram_limit);
+		radeon_vram_limit = 0;
+		break;
+	}
+	radeon_vram_limit = radeon_vram_limit << 20;
+	/* gtt size must be power of two and greater or equal to 32M */
+	switch (radeon_gart_size) {
+	case 4:
+	case 8:
+	case 16:
+		dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
+				radeon_gart_size);
+		radeon_gart_size = 512;
+		break;
+	case 32:
+	case 64:
+	case 128:
+	case 256:
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		break;
+	default:
+		dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
+				radeon_gart_size);
+		radeon_gart_size = 512;
+		break;
+	}
+	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+	/* AGP mode can only be -1, 1, 2, 4, 8 */
+	switch (radeon_agpmode) {
+	case -1:
+	case 0:
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		break;
+	default:
+		dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: "
+				"-1, 0, 1, 2, 4, 8)\n", radeon_agpmode);
+		radeon_agpmode = 0;
+		break;
+	}
 }
 
-/*
- * Radeon device.
- */
 int radeon_device_init(struct radeon_device *rdev,
 		       struct drm_device *ddev,
 		       struct pci_dev *pdev,
@@ -544,16 +638,24 @@ int radeon_device_init(struct radeon_device *rdev,
 	mutex_init(&rdev->cs_mutex);
 	mutex_init(&rdev->ib_pool.mutex);
 	mutex_init(&rdev->cp.mutex);
+	if (rdev->family >= CHIP_R600)
+		spin_lock_init(&rdev->ih.lock);
+	mutex_init(&rdev->gem.mutex);
 	rwlock_init(&rdev->fence_drv.lock);
 	INIT_LIST_HEAD(&rdev->gem.objects);
 
+	/* setup workqueue */
+	rdev->wq = create_workqueue("radeon");
+	if (rdev->wq == NULL)
+		return -ENOMEM;
+
 	/* Set asic functions */
 	r = radeon_asic_init(rdev);
-	if (r) {
+	if (r)
 		return r;
-	}
+	radeon_check_arguments(rdev);
 
-	if (radeon_agpmode == -1) {
+	if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) {
 		radeon_agp_disable(rdev);
 	}
 
@@ -620,6 +722,7 @@ void radeon_device_fini(struct radeon_device *rdev)
 	DRM_INFO("radeon: finishing device.\n");
 	rdev->shutdown = true;
 	radeon_fini(rdev);
+	destroy_workqueue(rdev->wq);
 	vga_client_register(rdev->pdev, NULL, NULL, NULL);
 	iounmap(rdev->rmmio);
 	rdev->rmmio = NULL;
@@ -631,38 +734,46 @@ void radeon_device_fini(struct radeon_device *rdev)
  */
 int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 {
-	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_device *rdev;
 	struct drm_crtc *crtc;
+	int r;
 
-	if (dev == NULL || rdev == NULL) {
+	if (dev == NULL || dev->dev_private == NULL) {
 		return -ENODEV;
 	}
 	if (state.event == PM_EVENT_PRETHAW) {
 		return 0;
 	}
+	rdev = dev->dev_private;
+
 	/* unpin the front buffers */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
-		struct radeon_object *robj;
+		struct radeon_bo *robj;
 
 		if (rfb == NULL || rfb->obj == NULL) {
 			continue;
 		}
 		robj = rfb->obj->driver_private;
-		if (robj != rdev->fbdev_robj) {
-			radeon_object_unpin(robj);
+		if (robj != rdev->fbdev_rbo) {
+			r = radeon_bo_reserve(robj, false);
+			if (unlikely(r == 0)) {
+				radeon_bo_unpin(robj);
+				radeon_bo_unreserve(robj);
+			}
 		}
 	}
 	/* evict vram memory */
-	radeon_object_evict_vram(rdev);
+	radeon_bo_evict_vram(rdev);
 	/* wait for gpu to finish processing current batch */
 	radeon_fence_wait_last(rdev);
 
 	radeon_save_bios_scratch_regs(rdev);
 
 	radeon_suspend(rdev);
+	radeon_hpd_fini(rdev);
 	/* evict remaining vram memory */
-	radeon_object_evict_vram(rdev);
+	radeon_bo_evict_vram(rdev);
 
 	pci_save_state(dev->pdev);
 	if (state.event == PM_EVENT_SUSPEND) {
@@ -695,6 +806,8 @@ int radeon_resume_kms(struct drm_device *dev)
 	fb_set_suspend(rdev->fbdev_info, 0);
 	release_console_sem();
 
+	/* reset hpd state */
+	radeon_hpd_init(rdev);
 	/* blat the mode back in */
 	drm_helper_resume_force_mode(dev);
 	return 0;