aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2010-02-01 00:38:10 -0500
committerDave Airlie <airlied@redhat.com>2010-03-01 01:20:37 -0500
commit6a9ee8af344e3bd7dbd61e67037096cdf7f83289 (patch)
tree07cdb493a790cf45bc473f2fc2ea1b9a166d5191 /drivers/gpu/drm/radeon
parent9fd1de52945e06ed88a440c99ca92dab74b9b33c (diff)
vga_switcheroo: initial implementation (v15)
Many new laptops now come with 2 gpus, one to be used for low power modes and one for gaming/on-ac applications. These GPUs are typically wired to the laptop panel and VGA ports via a multiplexer unit which is controlled via ACPI methods. 4 combinations of systems typically exist - with 2 ACPI methods. Intel/ATI - Lenovo W500/T500 - use ATPX ACPI method ATI/ATI - some ASUS - use ATPX ACPI Method Intel/Nvidia - - use _DSM ACPI method Nvidia/Nvidia - - use _DSM ACPI method. TODO: This patch adds support for the ATPX method and initial bits for the _DSM methods that need to written by someone with access to the hardware. Add a proper non-debugfs interface - need to get some proper testing first. v2: add power up/down support for both devices on W500 puts i915/radeon into D3 and cuts power to radeon. v3: redo probing methods, no DMI list, drm devices call to register with switcheroo, it tries to find an ATPX method on any device and once there is two devices + ATPX it inits the switcher. v4: ATPX msg handling using buffers - should work on more machines v5: rearchitect after more mjg59 discussion - move ATPX handling to radeon driver. v6: add file headers + initial nouveau bits (to be filled out). v7: merge delayed switcher code. v8: avoid suspend/resume of gpu that is off v9: rearchitect - mjg59 is always right. - move all ATPX code to radeon, should allow simpler DSM also proper ATRM handling v10: add ATRM support for radeon BIOS, add mutex to lock vgasr_priv v11: fix bug in resuming Intel for 2nd time. v12: start fixing up nvidia code blindly. v13: blindly guess at finishing nvidia code v14: remove radeon audio hacks - fix up intel resume more like upstream v15: clean up printks + remove unnecessary igd/dis pointers mount debugfs /sys/kernel/debug/vgaswitcheroo/switch - should exist if ATPX detected + 2 cards. DIS - immediate change to discrete IGD - immediate change to IGD DDIS - delayed change to discrete DIGD - delayed change to IGD ON - turn on not in use OFF - turn off not in use Tested on W500 (Intel/ATI) and T500 (Intel/ATI) Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r--drivers/gpu/drm/radeon/Makefile3
-rw-r--r--drivers/gpu/drm/radeon/radeon.h8
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c258
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c44
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c40
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c3
9 files changed, 358 insertions, 6 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 1cc7b937b1ea..8e62fe13e31c 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -54,7 +54,8 @@ radeon-y += radeon_device.o radeon_kms.o \
54 radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ 54 radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
55 rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ 55 rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
56 r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ 56 r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
57 r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o 57 r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
58 radeon_atpx_handler.o
58 59
59radeon-$(CONFIG_COMPAT) += radeon_ioc32.o 60radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
60 61
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c0356bb193e5..a5dfb1557d3e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -118,6 +118,10 @@ struct radeon_device;
118/* 118/*
119 * BIOS. 119 * BIOS.
120 */ 120 */
121#define ATRM_BIOS_PAGE 4096
122
123bool radeon_atrm_supported(struct pci_dev *pdev);
124int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len);
121bool radeon_get_bios(struct radeon_device *rdev); 125bool radeon_get_bios(struct radeon_device *rdev);
122 126
123 127
@@ -838,6 +842,8 @@ struct radeon_device {
838 int audio_bits_per_sample; 842 int audio_bits_per_sample;
839 uint8_t audio_status_bits; 843 uint8_t audio_status_bits;
840 uint8_t audio_category_code; 844 uint8_t audio_category_code;
845
846 bool powered_down;
841}; 847};
842 848
843int radeon_device_init(struct radeon_device *rdev, 849int radeon_device_init(struct radeon_device *rdev,
@@ -1042,6 +1048,8 @@ extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enabl
1042extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); 1048extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
1043extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); 1049extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain);
1044extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); 1050extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
1051extern int radeon_resume_kms(struct drm_device *dev);
1052extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
1045 1053
1046/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ 1054/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
1047struct r100_mc_save { 1055struct r100_mc_save {
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
new file mode 100644
index 000000000000..0ae52f19071d
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -0,0 +1,258 @@
1/*
2 * Copyright (c) 2010 Red Hat Inc.
3 * Author : Dave Airlie <airlied@redhat.com>
4 *
5 * Licensed under GPLv2
6 *
7 * ATPX support for both Intel/ATI
8 */
9
10#include <linux/vga_switcheroo.h>
11#include <acpi/acpi.h>
12#include <acpi/acpi_bus.h>
13#include <linux/pci.h>
14
15#define ATPX_VERSION 0
16#define ATPX_GPU_PWR 2
17#define ATPX_MUX_SELECT 3
18
19#define ATPX_INTEGRATED 0
20#define ATPX_DISCRETE 1
21
22#define ATPX_MUX_IGD 0
23#define ATPX_MUX_DISCRETE 1
24
25static struct radeon_atpx_priv {
26 bool atpx_detected;
27 /* handle for device - and atpx */
28 acpi_handle dhandle;
29 acpi_handle atpx_handle;
30 acpi_handle atrm_handle;
31} radeon_atpx_priv;
32
33/* retrieve the ROM in 4k blocks */
34static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
35 int offset, int len)
36{
37 acpi_status status;
38 union acpi_object atrm_arg_elements[2], *obj;
39 struct acpi_object_list atrm_arg;
40 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
41
42 atrm_arg.count = 2;
43 atrm_arg.pointer = &atrm_arg_elements[0];
44
45 atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
46 atrm_arg_elements[0].integer.value = offset;
47
48 atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
49 atrm_arg_elements[1].integer.value = len;
50
51 status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
52 if (ACPI_FAILURE(status)) {
53 printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
54 return -ENODEV;
55 }
56
57 obj = (union acpi_object *)buffer.pointer;
58 memcpy(bios+offset, obj->buffer.pointer, len);
59 kfree(buffer.pointer);
60 return len;
61}
62
63bool radeon_atrm_supported(struct pci_dev *pdev)
64{
65 /* get the discrete ROM only via ATRM */
66 if (!radeon_atpx_priv.atpx_detected)
67 return false;
68
69 if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
70 return false;
71 return true;
72}
73
74
75int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len)
76{
77 return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len);
78}
79
80static int radeon_atpx_get_version(acpi_handle handle)
81{
82 acpi_status status;
83 union acpi_object atpx_arg_elements[2], *obj;
84 struct acpi_object_list atpx_arg;
85 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
86
87 atpx_arg.count = 2;
88 atpx_arg.pointer = &atpx_arg_elements[0];
89
90 atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
91 atpx_arg_elements[0].integer.value = ATPX_VERSION;
92
93 atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
94 atpx_arg_elements[1].integer.value = ATPX_VERSION;
95
96 status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
97 if (ACPI_FAILURE(status)) {
98 printk("%s: failed to call ATPX: %s\n", __func__, acpi_format_exception(status));
99 return -ENOSYS;
100 }
101 obj = (union acpi_object *)buffer.pointer;
102 if (obj && (obj->type == ACPI_TYPE_BUFFER))
103 printk(KERN_INFO "radeon atpx: version is %d\n", *((u8 *)(obj->buffer.pointer) + 2));
104 kfree(buffer.pointer);
105 return 0;
106}
107
108static int radeon_atpx_execute(acpi_handle handle, int cmd_id, u16 value)
109{
110 acpi_status status;
111 union acpi_object atpx_arg_elements[2];
112 struct acpi_object_list atpx_arg;
113 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
114 uint8_t buf[4] = {0};
115
116 if (!handle)
117 return -EINVAL;
118
119 atpx_arg.count = 2;
120 atpx_arg.pointer = &atpx_arg_elements[0];
121
122 atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
123 atpx_arg_elements[0].integer.value = cmd_id;
124
125 buf[2] = value & 0xff;
126 buf[3] = (value >> 8) & 0xff;
127
128 atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
129 atpx_arg_elements[1].buffer.length = 4;
130 atpx_arg_elements[1].buffer.pointer = buf;
131
132 status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
133 if (ACPI_FAILURE(status)) {
134 printk("%s: failed to call ATPX: %s\n", __func__, acpi_format_exception(status));
135 return -ENOSYS;
136 }
137 kfree(buffer.pointer);
138
139 return 0;
140}
141
142static int radeon_atpx_set_discrete_state(acpi_handle handle, int state)
143{
144 return radeon_atpx_execute(handle, ATPX_GPU_PWR, state);
145}
146
147static int radeon_atpx_switch_mux(acpi_handle handle, int mux_id)
148{
149 return radeon_atpx_execute(handle, ATPX_MUX_SELECT, mux_id);
150}
151
152
153static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
154{
155 if (id == VGA_SWITCHEROO_IGD)
156 radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 0);
157 else
158 radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 1);
159 return 0;
160}
161
162static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
163 enum vga_switcheroo_state state)
164{
165 /* on w500 ACPI can't change intel gpu state */
166 if (id == VGA_SWITCHEROO_IGD)
167 return 0;
168
169 radeon_atpx_set_discrete_state(radeon_atpx_priv.atpx_handle, state);
170 return 0;
171}
172
173static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
174{
175 acpi_handle dhandle, atpx_handle, atrm_handle;
176 acpi_status status;
177
178 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
179 if (!dhandle)
180 return false;
181
182 status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
183 if (ACPI_FAILURE(status))
184 return false;
185
186 status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
187 if (ACPI_FAILURE(status))
188 return false;
189
190 radeon_atpx_priv.dhandle = dhandle;
191 radeon_atpx_priv.atpx_handle = atpx_handle;
192 radeon_atpx_priv.atrm_handle = atrm_handle;
193 return true;
194}
195
196static int radeon_atpx_init(void)
197{
198 /* set up the ATPX handle */
199
200 radeon_atpx_get_version(radeon_atpx_priv.atpx_handle);
201 return 0;
202}
203
204static int radeon_atpx_get_client_id(struct pci_dev *pdev)
205{
206 if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
207 return VGA_SWITCHEROO_IGD;
208 else
209 return VGA_SWITCHEROO_DIS;
210}
211
212static struct vga_switcheroo_handler radeon_atpx_handler = {
213 .switchto = radeon_atpx_switchto,
214 .power_state = radeon_atpx_power_state,
215 .init = radeon_atpx_init,
216 .get_client_id = radeon_atpx_get_client_id,
217};
218
219static bool radeon_atpx_detect(void)
220{
221 char acpi_method_name[255] = { 0 };
222 struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
223 struct pci_dev *pdev = NULL;
224 bool has_atpx = false;
225 int vga_count = 0;
226
227 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
228 vga_count++;
229
230 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
231 }
232
233 if (has_atpx && vga_count == 2) {
234 acpi_get_name(radeon_atpx_priv.atpx_handle, ACPI_FULL_PATHNAME, &buffer);
235 printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
236 acpi_method_name);
237 radeon_atpx_priv.atpx_detected = true;
238 return true;
239 }
240 return false;
241}
242
243void radeon_register_atpx_handler(void)
244{
245 bool r;
246
247 /* detect if we have any ATPX + 2 VGA in the system */
248 r = radeon_atpx_detect();
249 if (!r)
250 return;
251
252 vga_switcheroo_register_handler(&radeon_atpx_handler);
253}
254
255void radeon_unregister_atpx_handler(void)
256{
257 vga_switcheroo_unregister_handler();
258}
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index 906921740c60..a34b909485b8 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -30,6 +30,7 @@
30#include "radeon.h" 30#include "radeon.h"
31#include "atom.h" 31#include "atom.h"
32 32
33#include <linux/vga_switcheroo.h>
33/* 34/*
34 * BIOS. 35 * BIOS.
35 */ 36 */
@@ -62,7 +63,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
62 iounmap(bios); 63 iounmap(bios);
63 return false; 64 return false;
64 } 65 }
65 memcpy(rdev->bios, bios, size); 66 memcpy_fromio(rdev->bios, bios, size);
66 iounmap(bios); 67 iounmap(bios);
67 return true; 68 return true;
68} 69}
@@ -93,6 +94,38 @@ static bool radeon_read_bios(struct radeon_device *rdev)
93 return true; 94 return true;
94} 95}
95 96
97/* ATRM is used to get the BIOS on the discrete cards in
98 * dual-gpu systems.
99 */
100static bool radeon_atrm_get_bios(struct radeon_device *rdev)
101{
102 int ret;
103 int size = 64 * 1024;
104 int i;
105
106 if (!radeon_atrm_supported(rdev->pdev))
107 return false;
108
109 rdev->bios = kmalloc(size, GFP_KERNEL);
110 if (!rdev->bios) {
111 DRM_ERROR("Unable to allocate bios\n");
112 return false;
113 }
114
115 for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
116 ret = radeon_atrm_get_bios_chunk(rdev->bios,
117 (i * ATRM_BIOS_PAGE),
118 ATRM_BIOS_PAGE);
119 if (ret <= 0)
120 break;
121 }
122
123 if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
124 kfree(rdev->bios);
125 return false;
126 }
127 return true;
128}
96static bool r700_read_disabled_bios(struct radeon_device *rdev) 129static bool r700_read_disabled_bios(struct radeon_device *rdev)
97{ 130{
98 uint32_t viph_control; 131 uint32_t viph_control;
@@ -388,16 +421,16 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev)
388 return legacy_read_disabled_bios(rdev); 421 return legacy_read_disabled_bios(rdev);
389} 422}
390 423
424
391bool radeon_get_bios(struct radeon_device *rdev) 425bool radeon_get_bios(struct radeon_device *rdev)
392{ 426{
393 bool r; 427 bool r;
394 uint16_t tmp; 428 uint16_t tmp;
395 429
396 if (rdev->flags & RADEON_IS_IGP) { 430 r = radeon_atrm_get_bios(rdev);
431 if (r == false)
397 r = igp_read_bios_from_vram(rdev); 432 r = igp_read_bios_from_vram(rdev);
398 if (r == false) 433 if (r == false)
399 r = radeon_read_bios(rdev);
400 } else
401 r = radeon_read_bios(rdev); 434 r = radeon_read_bios(rdev);
402 if (r == false) { 435 if (r == false) {
403 r = radeon_read_disabled_bios(rdev); 436 r = radeon_read_disabled_bios(rdev);
@@ -408,6 +441,7 @@ bool radeon_get_bios(struct radeon_device *rdev)
408 return false; 441 return false;
409 } 442 }
410 if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { 443 if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
444 printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]);
411 goto free_bios; 445 goto free_bios;
412 } 446 }
413 447
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 768b1509fa03..cb8d9a1dd69c 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -30,6 +30,7 @@
30#include <drm/drm_crtc_helper.h> 30#include <drm/drm_crtc_helper.h>
31#include <drm/radeon_drm.h> 31#include <drm/radeon_drm.h>
32#include <linux/vgaarb.h> 32#include <linux/vgaarb.h>
33#include <linux/vga_switcheroo.h>
33#include "radeon_reg.h" 34#include "radeon_reg.h"
34#include "radeon.h" 35#include "radeon.h"
35#include "radeon_asic.h" 36#include "radeon_asic.h"
@@ -613,6 +614,36 @@ void radeon_check_arguments(struct radeon_device *rdev)
613 } 614 }
614} 615}
615 616
617static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
618{
619 struct drm_device *dev = pci_get_drvdata(pdev);
620 struct radeon_device *rdev = dev->dev_private;
621 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
622 if (state == VGA_SWITCHEROO_ON) {
623 printk(KERN_INFO "radeon: switched on\n");
624 /* don't suspend or resume card normally */
625 rdev->powered_down = false;
626 radeon_resume_kms(dev);
627 } else {
628 printk(KERN_INFO "radeon: switched off\n");
629 radeon_suspend_kms(dev, pmm);
630 /* don't suspend or resume card normally */
631 rdev->powered_down = true;
632 }
633}
634
635static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
636{
637 struct drm_device *dev = pci_get_drvdata(pdev);
638 bool can_switch;
639
640 spin_lock(&dev->count_lock);
641 can_switch = (dev->open_count == 0);
642 spin_unlock(&dev->count_lock);
643 return can_switch;
644}
645
646
616int radeon_device_init(struct radeon_device *rdev, 647int radeon_device_init(struct radeon_device *rdev,
617 struct drm_device *ddev, 648 struct drm_device *ddev,
618 struct pci_dev *pdev, 649 struct pci_dev *pdev,
@@ -692,6 +723,9 @@ int radeon_device_init(struct radeon_device *rdev,
692 /* this will fail for cards that aren't VGA class devices, just 723 /* this will fail for cards that aren't VGA class devices, just
693 * ignore it */ 724 * ignore it */
694 vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); 725 vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
726 vga_switcheroo_register_client(rdev->pdev,
727 radeon_switcheroo_set_state,
728 radeon_switcheroo_can_switch);
695 729
696 r = radeon_init(rdev); 730 r = radeon_init(rdev);
697 if (r) 731 if (r)
@@ -723,6 +757,7 @@ void radeon_device_fini(struct radeon_device *rdev)
723 rdev->shutdown = true; 757 rdev->shutdown = true;
724 radeon_fini(rdev); 758 radeon_fini(rdev);
725 destroy_workqueue(rdev->wq); 759 destroy_workqueue(rdev->wq);
760 vga_switcheroo_unregister_client(rdev->pdev);
726 vga_client_register(rdev->pdev, NULL, NULL, NULL); 761 vga_client_register(rdev->pdev, NULL, NULL, NULL);
727 iounmap(rdev->rmmio); 762 iounmap(rdev->rmmio);
728 rdev->rmmio = NULL; 763 rdev->rmmio = NULL;
@@ -746,6 +781,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
746 } 781 }
747 rdev = dev->dev_private; 782 rdev = dev->dev_private;
748 783
784 if (rdev->powered_down)
785 return 0;
749 /* unpin the front buffers */ 786 /* unpin the front buffers */
750 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 787 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
751 struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); 788 struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
@@ -791,6 +828,9 @@ int radeon_resume_kms(struct drm_device *dev)
791{ 828{
792 struct radeon_device *rdev = dev->dev_private; 829 struct radeon_device *rdev = dev->dev_private;
793 830
831 if (rdev->powered_down)
832 return 0;
833
794 acquire_console_sem(); 834 acquire_console_sem();
795 pci_set_power_state(dev->pdev, PCI_D0); 835 pci_set_power_state(dev->pdev, PCI_D0);
796 pci_restore_state(dev->pdev); 836 pci_restore_state(dev->pdev);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 8ba3de7994d4..4ab53aa163b2 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -339,6 +339,7 @@ static int __init radeon_init(void)
339 driver = &kms_driver; 339 driver = &kms_driver;
340 driver->driver_features |= DRIVER_MODESET; 340 driver->driver_features |= DRIVER_MODESET;
341 driver->num_ioctls = radeon_max_kms_ioctl; 341 driver->num_ioctls = radeon_max_kms_ioctl;
342 radeon_register_atpx_handler();
342 } 343 }
343 /* if the vga console setting is enabled still 344 /* if the vga console setting is enabled still
344 * let modprobe override it */ 345 * let modprobe override it */
@@ -348,6 +349,7 @@ static int __init radeon_init(void)
348static void __exit radeon_exit(void) 349static void __exit radeon_exit(void)
349{ 350{
350 drm_exit(driver); 351 drm_exit(driver);
352 radeon_unregister_atpx_handler();
351} 353}
352 354
353module_init(radeon_init); 355module_init(radeon_init);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index c57ad606504d..736237195143 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -455,6 +455,9 @@ extern void r600_blit_swap(struct drm_device *dev,
455 int sx, int sy, int dx, int dy, 455 int sx, int sy, int dx, int dy,
456 int w, int h, int src_pitch, int dst_pitch, int cpp); 456 int w, int h, int src_pitch, int dst_pitch, int cpp);
457 457
458/* atpx handler */
459void radeon_register_atpx_handler(void);
460void radeon_unregister_atpx_handler(void);
458/* Flags for stats.boxes 461/* Flags for stats.boxes
459 */ 462 */
460#define RADEON_BOX_DMA_IDLE 0x1 463#define RADEON_BOX_DMA_IDLE 0x1
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index d71e346e9ab5..561719223988 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -39,6 +39,8 @@
39 39
40#include "drm_fb_helper.h" 40#include "drm_fb_helper.h"
41 41
42#include <linux/vga_switcheroo.h>
43
42struct radeon_fb_device { 44struct radeon_fb_device {
43 struct drm_fb_helper helper; 45 struct drm_fb_helper helper;
44 struct radeon_framebuffer *rfb; 46 struct radeon_framebuffer *rfb;
@@ -291,6 +293,7 @@ int radeonfb_create(struct drm_device *dev,
291 rfbdev->rdev = rdev; 293 rfbdev->rdev = rdev;
292 294
293 mutex_unlock(&rdev->ddev->struct_mutex); 295 mutex_unlock(&rdev->ddev->struct_mutex);
296 vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
294 return 0; 297 return 0;
295 298
296out_unref: 299out_unref:
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index f23b05606eb5..5db7af6b91f4 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -30,6 +30,8 @@
30#include "radeon.h" 30#include "radeon.h"
31#include "radeon_drm.h" 31#include "radeon_drm.h"
32 32
33#include <linux/vga_switcheroo.h>
34
33int radeon_driver_unload_kms(struct drm_device *dev) 35int radeon_driver_unload_kms(struct drm_device *dev)
34{ 36{
35 struct radeon_device *rdev = dev->dev_private; 37 struct radeon_device *rdev = dev->dev_private;
@@ -136,6 +138,7 @@ int radeon_driver_firstopen_kms(struct drm_device *dev)
136 138
137void radeon_driver_lastclose_kms(struct drm_device *dev) 139void radeon_driver_lastclose_kms(struct drm_device *dev)
138{ 140{
141 vga_switcheroo_process_delayed_switch();
139} 142}
140 143
141int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) 144int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)