aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-09-21 00:33:58 -0400
committerDave Airlie <airlied@redhat.com>2009-09-21 01:00:27 -0400
commit28d520433b6375740990ab99d69b0d0067fd656b (patch)
treed3affea0fb69f84b9c924c03d78c5df23946306f
parentaadd4e17452d3d5c2269cd2b000b7de7cfb6c79e (diff)
drm/vgaarb: add VGA arbitration support to the drm and kms.
VGA arb requires DRM support for non-kms drivers, to turn on/off irqs when disabling the mem/io regions. VGA arb requires KMS support for GPUs where we can turn off VGA decoding. Currently we know how to do this for intel and radeon kms drivers, which allows them to be removed from the arbiter. This patch comes from Fedora rawhide kernel. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_irq.c27
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c20
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h1
-rw-r--r--drivers/gpu/drm/i915/intel_display.c17
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
-rw-r--r--drivers/gpu/drm/radeon/r100.c14
-rw-r--r--drivers/gpu/drm/radeon/r600.c14
-rw-r--r--drivers/gpu/drm/radeon/r600d.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h12
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c21
-rw-r--r--include/drm/drmP.h3
13 files changed, 133 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index f85aaf21e783..0a6f0b3bdc78 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -37,6 +37,7 @@
37 37
38#include <linux/interrupt.h> /* For task queue support */ 38#include <linux/interrupt.h> /* For task queue support */
39 39
40#include <linux/vgaarb.h>
40/** 41/**
41 * Get interrupt from bus id. 42 * Get interrupt from bus id.
42 * 43 *
@@ -171,6 +172,26 @@ err:
171} 172}
172EXPORT_SYMBOL(drm_vblank_init); 173EXPORT_SYMBOL(drm_vblank_init);
173 174
175static void drm_irq_vgaarb_nokms(void *cookie, bool state)
176{
177 struct drm_device *dev = cookie;
178
179 if (dev->driver->vgaarb_irq) {
180 dev->driver->vgaarb_irq(dev, state);
181 return;
182 }
183
184 if (!dev->irq_enabled)
185 return;
186
187 if (state)
188 dev->driver->irq_uninstall(dev);
189 else {
190 dev->driver->irq_preinstall(dev);
191 dev->driver->irq_postinstall(dev);
192 }
193}
194
174/** 195/**
175 * Install IRQ handler. 196 * Install IRQ handler.
176 * 197 *
@@ -231,6 +252,9 @@ int drm_irq_install(struct drm_device *dev)
231 return ret; 252 return ret;
232 } 253 }
233 254
255 if (!drm_core_check_feature(dev, DRIVER_MODESET))
256 vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL);
257
234 /* After installing handler */ 258 /* After installing handler */
235 ret = dev->driver->irq_postinstall(dev); 259 ret = dev->driver->irq_postinstall(dev);
236 if (ret < 0) { 260 if (ret < 0) {
@@ -279,6 +303,9 @@ int drm_irq_uninstall(struct drm_device * dev)
279 303
280 DRM_DEBUG("irq=%d\n", dev->pdev->irq); 304 DRM_DEBUG("irq=%d\n", dev->pdev->irq);
281 305
306 if (!drm_core_check_feature(dev, DRIVER_MODESET))
307 vga_client_register(dev->pdev, NULL, NULL, NULL);
308
282 dev->driver->irq_uninstall(dev); 309 dev->driver->irq_uninstall(dev);
283 310
284 free_irq(dev->pdev->irq, dev); 311 free_irq(dev->pdev->irq, dev);
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 9909505d070a..5a49a1867b35 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -33,6 +33,7 @@
33#include "intel_drv.h" 33#include "intel_drv.h"
34#include "i915_drm.h" 34#include "i915_drm.h"
35#include "i915_drv.h" 35#include "i915_drv.h"
36#include <linux/vgaarb.h>
36 37
37/* Really want an OS-independent resettable timer. Would like to have 38/* Really want an OS-independent resettable timer. Would like to have
38 * this loop run for (eg) 3 sec, but have the timer reset every time 39 * this loop run for (eg) 3 sec, but have the timer reset every time
@@ -1012,6 +1013,19 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
1012 return 0; 1013 return 0;
1013} 1014}
1014 1015
1016/* true = enable decode, false = disable decoder */
1017static unsigned int i915_vga_set_decode(void *cookie, bool state)
1018{
1019 struct drm_device *dev = cookie;
1020
1021 intel_modeset_vga_set_state(dev, state);
1022 if (state)
1023 return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
1024 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
1025 else
1026 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
1027}
1028
1015static int i915_load_modeset_init(struct drm_device *dev, 1029static int i915_load_modeset_init(struct drm_device *dev,
1016 unsigned long prealloc_size, 1030 unsigned long prealloc_size,
1017 unsigned long agp_size) 1031 unsigned long agp_size)
@@ -1057,6 +1071,11 @@ static int i915_load_modeset_init(struct drm_device *dev,
1057 if (ret) 1071 if (ret)
1058 DRM_INFO("failed to find VBIOS tables\n"); 1072 DRM_INFO("failed to find VBIOS tables\n");
1059 1073
1074 /* if we have > 1 VGA cards, then disable the radeon VGA resources */
1075 ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
1076 if (ret)
1077 goto destroy_ringbuffer;
1078
1060 ret = drm_irq_install(dev); 1079 ret = drm_irq_install(dev);
1061 if (ret) 1080 if (ret)
1062 goto destroy_ringbuffer; 1081 goto destroy_ringbuffer;
@@ -1324,6 +1343,7 @@ int i915_driver_unload(struct drm_device *dev)
1324 1343
1325 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 1344 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1326 drm_irq_uninstall(dev); 1345 drm_irq_uninstall(dev);
1346 vga_client_register(dev->pdev, NULL, NULL, NULL);
1327 } 1347 }
1328 1348
1329 if (dev->pdev->msi_enabled) 1349 if (dev->pdev->msi_enabled)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 77ed060b4292..a0632f8e76ac 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -766,6 +766,7 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; }
766/* modesetting */ 766/* modesetting */
767extern void intel_modeset_init(struct drm_device *dev); 767extern void intel_modeset_init(struct drm_device *dev);
768extern void intel_modeset_cleanup(struct drm_device *dev); 768extern void intel_modeset_cleanup(struct drm_device *dev);
769extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
769 770
770/** 771/**
771 * Lock test for when it's just for synchronization of ring access. 772 * Lock test for when it's just for synchronization of ring access.
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e38cd21161c8..3f7963553464 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -30,6 +30,7 @@
30 * fb aperture size and the amount of pre-reserved memory. 30 * fb aperture size and the amount of pre-reserved memory.
31 */ 31 */
32#define INTEL_GMCH_CTRL 0x52 32#define INTEL_GMCH_CTRL 0x52
33#define INTEL_GMCH_VGA_DISABLE (1 << 1)
33#define INTEL_GMCH_ENABLED 0x4 34#define INTEL_GMCH_ENABLED 0x4
34#define INTEL_GMCH_MEM_MASK 0x1 35#define INTEL_GMCH_MEM_MASK 0x1
35#define INTEL_GMCH_MEM_64M 0x1 36#define INTEL_GMCH_MEM_64M 0x1
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 155719ff99d1..0227b1652906 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3917,3 +3917,20 @@ struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
3917 3917
3918 return &intel_output->enc; 3918 return &intel_output->enc;
3919} 3919}
3920
3921/*
3922 * set vga decode state - true == enable VGA decode
3923 */
3924int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
3925{
3926 struct drm_i915_private *dev_priv = dev->dev_private;
3927 u16 gmch_ctrl;
3928
3929 pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
3930 if (state)
3931 gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
3932 else
3933 gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
3934 pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
3935 return 0;
3936}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b9e47f1e1cc0..3a0004f755d0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -178,4 +178,5 @@ extern int intel_framebuffer_create(struct drm_device *dev,
178 struct drm_mode_fb_cmd *mode_cmd, 178 struct drm_mode_fb_cmd *mode_cmd,
179 struct drm_framebuffer **fb, 179 struct drm_framebuffer **fb,
180 struct drm_gem_object *obj); 180 struct drm_gem_object *obj);
181
181#endif /* __INTEL_DRV_H__ */ 182#endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 737970b43aef..be51c5f7d0f6 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1955,6 +1955,20 @@ void r100_vram_init_sizes(struct radeon_device *rdev)
1955 rdev->mc.real_vram_size = rdev->mc.aper_size; 1955 rdev->mc.real_vram_size = rdev->mc.aper_size;
1956} 1956}
1957 1957
1958void r100_vga_set_state(struct radeon_device *rdev, bool state)
1959{
1960 uint32_t temp;
1961
1962 temp = RREG32(RADEON_CONFIG_CNTL);
1963 if (state == false) {
1964 temp &= ~(1<<8);
1965 temp |= (1<<9);
1966 } else {
1967 temp &= ~(1<<9);
1968 }
1969 WREG32(RADEON_CONFIG_CNTL, temp);
1970}
1971
1958void r100_vram_info(struct radeon_device *rdev) 1972void r100_vram_info(struct radeon_device *rdev)
1959{ 1973{
1960 r100_vram_get_type(rdev); 1974 r100_vram_get_type(rdev);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 5f42fad19190..eab31c1d6df1 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1499,6 +1499,20 @@ int r600_startup(struct radeon_device *rdev)
1499 return 0; 1499 return 0;
1500} 1500}
1501 1501
1502void r600_vga_set_state(struct radeon_device *rdev, bool state)
1503{
1504 uint32_t temp;
1505
1506 temp = RREG32(CONFIG_CNTL);
1507 if (state == false) {
1508 temp &= ~(1<<0);
1509 temp |= (1<<1);
1510 } else {
1511 temp &= ~(1<<1);
1512 }
1513 WREG32(CONFIG_CNTL, temp);
1514}
1515
1502int r600_resume(struct radeon_device *rdev) 1516int r600_resume(struct radeon_device *rdev)
1503{ 1517{
1504 int r; 1518 int r;
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 723295f59281..4a9028a85c9b 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -78,6 +78,7 @@
78#define CB_COLOR0_MASK 0x28100 78#define CB_COLOR0_MASK 0x28100
79 79
80#define CONFIG_MEMSIZE 0x5428 80#define CONFIG_MEMSIZE 0x5428
81#define CONFIG_CNTL 0x5424
81#define CP_STAT 0x8680 82#define CP_STAT 0x8680
82#define CP_COHER_BASE 0x85F8 83#define CP_COHER_BASE 0x85F8
83#define CP_DEBUG 0xC1FC 84#define CP_DEBUG 0xC1FC
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 817af8ecff10..c839b608970f 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -596,6 +596,7 @@ struct radeon_asic {
596 int (*suspend)(struct radeon_device *rdev); 596 int (*suspend)(struct radeon_device *rdev);
597 void (*errata)(struct radeon_device *rdev); 597 void (*errata)(struct radeon_device *rdev);
598 void (*vram_info)(struct radeon_device *rdev); 598 void (*vram_info)(struct radeon_device *rdev);
599 void (*vga_set_state)(struct radeon_device *rdev, bool state);
599 int (*gpu_reset)(struct radeon_device *rdev); 600 int (*gpu_reset)(struct radeon_device *rdev);
600 int (*mc_init)(struct radeon_device *rdev); 601 int (*mc_init)(struct radeon_device *rdev);
601 void (*mc_fini)(struct radeon_device *rdev); 602 void (*mc_fini)(struct radeon_device *rdev);
@@ -954,6 +955,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
954#define radeon_cs_parse(p) rdev->asic->cs_parse((p)) 955#define radeon_cs_parse(p) rdev->asic->cs_parse((p))
955#define radeon_errata(rdev) (rdev)->asic->errata((rdev)) 956#define radeon_errata(rdev) (rdev)->asic->errata((rdev))
956#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev)) 957#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev))
958#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
957#define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev)) 959#define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev))
958#define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev)) 960#define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev))
959#define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev)) 961#define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 5f2a9e6f12c5..8968f78fa1e3 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -47,6 +47,7 @@ uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
47void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); 47void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
48void r100_errata(struct radeon_device *rdev); 48void r100_errata(struct radeon_device *rdev);
49void r100_vram_info(struct radeon_device *rdev); 49void r100_vram_info(struct radeon_device *rdev);
50void r100_vga_set_state(struct radeon_device *rdev, bool state);
50int r100_gpu_reset(struct radeon_device *rdev); 51int r100_gpu_reset(struct radeon_device *rdev);
51int r100_mc_init(struct radeon_device *rdev); 52int r100_mc_init(struct radeon_device *rdev);
52void r100_mc_fini(struct radeon_device *rdev); 53void r100_mc_fini(struct radeon_device *rdev);
@@ -89,6 +90,7 @@ static struct radeon_asic r100_asic = {
89 .init = &r100_init, 90 .init = &r100_init,
90 .errata = &r100_errata, 91 .errata = &r100_errata,
91 .vram_info = &r100_vram_info, 92 .vram_info = &r100_vram_info,
93 .vga_set_state = &r100_vga_set_state,
92 .gpu_reset = &r100_gpu_reset, 94 .gpu_reset = &r100_gpu_reset,
93 .mc_init = &r100_mc_init, 95 .mc_init = &r100_mc_init,
94 .mc_fini = &r100_mc_fini, 96 .mc_fini = &r100_mc_fini,
@@ -158,6 +160,7 @@ static struct radeon_asic r300_asic = {
158 .init = &r300_init, 160 .init = &r300_init,
159 .errata = &r300_errata, 161 .errata = &r300_errata,
160 .vram_info = &r300_vram_info, 162 .vram_info = &r300_vram_info,
163 .vga_set_state = &r100_vga_set_state,
161 .gpu_reset = &r300_gpu_reset, 164 .gpu_reset = &r300_gpu_reset,
162 .mc_init = &r300_mc_init, 165 .mc_init = &r300_mc_init,
163 .mc_fini = &r300_mc_fini, 166 .mc_fini = &r300_mc_fini,
@@ -208,6 +211,7 @@ static struct radeon_asic r420_asic = {
208 .resume = &r420_resume, 211 .resume = &r420_resume,
209 .errata = NULL, 212 .errata = NULL,
210 .vram_info = NULL, 213 .vram_info = NULL,
214 .vga_set_state = &r100_vga_set_state,
211 .gpu_reset = &r300_gpu_reset, 215 .gpu_reset = &r300_gpu_reset,
212 .mc_init = NULL, 216 .mc_init = NULL,
213 .mc_fini = NULL, 217 .mc_fini = NULL,
@@ -262,6 +266,7 @@ static struct radeon_asic rs400_asic = {
262 .init = &r300_init, 266 .init = &r300_init,
263 .errata = &rs400_errata, 267 .errata = &rs400_errata,
264 .vram_info = &rs400_vram_info, 268 .vram_info = &rs400_vram_info,
269 .vga_set_state = &r100_vga_set_state,
265 .gpu_reset = &r300_gpu_reset, 270 .gpu_reset = &r300_gpu_reset,
266 .mc_init = &rs400_mc_init, 271 .mc_init = &rs400_mc_init,
267 .mc_fini = &rs400_mc_fini, 272 .mc_fini = &rs400_mc_fini,
@@ -323,6 +328,7 @@ static struct radeon_asic rs600_asic = {
323 .init = &rs600_init, 328 .init = &rs600_init,
324 .errata = &rs600_errata, 329 .errata = &rs600_errata,
325 .vram_info = &rs600_vram_info, 330 .vram_info = &rs600_vram_info,
331 .vga_set_state = &r100_vga_set_state,
326 .gpu_reset = &r300_gpu_reset, 332 .gpu_reset = &r300_gpu_reset,
327 .mc_init = &rs600_mc_init, 333 .mc_init = &rs600_mc_init,
328 .mc_fini = &rs600_mc_fini, 334 .mc_fini = &rs600_mc_fini,
@@ -372,6 +378,7 @@ static struct radeon_asic rs690_asic = {
372 .init = &rs600_init, 378 .init = &rs600_init,
373 .errata = &rs690_errata, 379 .errata = &rs690_errata,
374 .vram_info = &rs690_vram_info, 380 .vram_info = &rs690_vram_info,
381 .vga_set_state = &r100_vga_set_state,
375 .gpu_reset = &r300_gpu_reset, 382 .gpu_reset = &r300_gpu_reset,
376 .mc_init = &rs690_mc_init, 383 .mc_init = &rs690_mc_init,
377 .mc_fini = &rs690_mc_fini, 384 .mc_fini = &rs690_mc_fini,
@@ -428,6 +435,7 @@ static struct radeon_asic rv515_asic = {
428 .init = &rv515_init, 435 .init = &rv515_init,
429 .errata = &rv515_errata, 436 .errata = &rv515_errata,
430 .vram_info = &rv515_vram_info, 437 .vram_info = &rv515_vram_info,
438 .vga_set_state = &r100_vga_set_state,
431 .gpu_reset = &rv515_gpu_reset, 439 .gpu_reset = &rv515_gpu_reset,
432 .mc_init = &rv515_mc_init, 440 .mc_init = &rv515_mc_init,
433 .mc_fini = &rv515_mc_fini, 441 .mc_fini = &rv515_mc_fini,
@@ -477,6 +485,7 @@ static struct radeon_asic r520_asic = {
477 .init = &rv515_init, 485 .init = &rv515_init,
478 .errata = &r520_errata, 486 .errata = &r520_errata,
479 .vram_info = &r520_vram_info, 487 .vram_info = &r520_vram_info,
488 .vga_set_state = &r100_vga_set_state,
480 .gpu_reset = &rv515_gpu_reset, 489 .gpu_reset = &rv515_gpu_reset,
481 .mc_init = &r520_mc_init, 490 .mc_init = &r520_mc_init,
482 .mc_fini = &r520_mc_fini, 491 .mc_fini = &r520_mc_fini,
@@ -520,6 +529,7 @@ int r600_init(struct radeon_device *rdev);
520void r600_fini(struct radeon_device *rdev); 529void r600_fini(struct radeon_device *rdev);
521int r600_suspend(struct radeon_device *rdev); 530int r600_suspend(struct radeon_device *rdev);
522int r600_resume(struct radeon_device *rdev); 531int r600_resume(struct radeon_device *rdev);
532void r600_vga_set_state(struct radeon_device *rdev, bool state);
523int r600_wb_init(struct radeon_device *rdev); 533int r600_wb_init(struct radeon_device *rdev);
524void r600_wb_fini(struct radeon_device *rdev); 534void r600_wb_fini(struct radeon_device *rdev);
525void r600_cp_commit(struct radeon_device *rdev); 535void r600_cp_commit(struct radeon_device *rdev);
@@ -556,6 +566,7 @@ static struct radeon_asic r600_asic = {
556 .resume = &r600_resume, 566 .resume = &r600_resume,
557 .cp_commit = &r600_cp_commit, 567 .cp_commit = &r600_cp_commit,
558 .vram_info = NULL, 568 .vram_info = NULL,
569 .vga_set_state = &r600_vga_set_state,
559 .gpu_reset = &r600_gpu_reset, 570 .gpu_reset = &r600_gpu_reset,
560 .mc_init = NULL, 571 .mc_init = NULL,
561 .mc_fini = NULL, 572 .mc_fini = NULL,
@@ -606,6 +617,7 @@ static struct radeon_asic rv770_asic = {
606 .cp_commit = &r600_cp_commit, 617 .cp_commit = &r600_cp_commit,
607 .vram_info = NULL, 618 .vram_info = NULL,
608 .gpu_reset = &rv770_gpu_reset, 619 .gpu_reset = &rv770_gpu_reset,
620 .vga_set_state = &r600_vga_set_state,
609 .mc_init = NULL, 621 .mc_init = NULL,
610 .mc_fini = NULL, 622 .mc_fini = NULL,
611 .wb_init = &r600_wb_init, 623 .wb_init = &r600_wb_init,
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 8a40c616b534..daf5db780956 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -29,6 +29,7 @@
29#include <drm/drmP.h> 29#include <drm/drmP.h>
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 "radeon_reg.h" 33#include "radeon_reg.h"
33#include "radeon.h" 34#include "radeon.h"
34#include "radeon_asic.h" 35#include "radeon_asic.h"
@@ -480,7 +481,18 @@ void radeon_combios_fini(struct radeon_device *rdev)
480{ 481{
481} 482}
482 483
484/* if we get transitioned to only one device, tak VGA back */
485static unsigned int radeon_vga_set_decode(void *cookie, bool state)
486{
487 struct radeon_device *rdev = cookie;
483 488
489 radeon_vga_set_state(rdev, state);
490 if (state)
491 return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
492 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
493 else
494 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
495}
484/* 496/*
485 * Radeon device. 497 * Radeon device.
486 */ 498 */
@@ -578,6 +590,13 @@ int radeon_device_init(struct radeon_device *rdev,
578 if (r) { 590 if (r) {
579 return r; 591 return r;
580 } 592 }
593
594 /* if we have > 1 VGA cards, then disable the radeon VGA resources */
595 r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
596 if (r) {
597 return -EINVAL;
598 }
599
581 if (!rdev->new_init_path) { 600 if (!rdev->new_init_path) {
582 /* Setup errata flags */ 601 /* Setup errata flags */
583 radeon_errata(rdev); 602 radeon_errata(rdev);
@@ -586,7 +605,6 @@ int radeon_device_init(struct radeon_device *rdev,
586 /* Initialize surface registers */ 605 /* Initialize surface registers */
587 radeon_surface_init(rdev); 606 radeon_surface_init(rdev);
588 607
589 /* TODO: disable VGA need to use VGA request */
590 /* BIOS*/ 608 /* BIOS*/
591 if (!radeon_get_bios(rdev)) { 609 if (!radeon_get_bios(rdev)) {
592 if (ASIC_IS_AVIVO(rdev)) 610 if (ASIC_IS_AVIVO(rdev))
@@ -697,6 +715,7 @@ void radeon_device_fini(struct radeon_device *rdev)
697 radeon_agp_fini(rdev); 715 radeon_agp_fini(rdev);
698#endif 716#endif
699 radeon_irq_kms_fini(rdev); 717 radeon_irq_kms_fini(rdev);
718 vga_client_register(rdev->pdev, NULL, NULL, NULL);
700 radeon_fence_driver_fini(rdev); 719 radeon_fence_driver_fini(rdev);
701 radeon_clocks_fini(rdev); 720 radeon_clocks_fini(rdev);
702 radeon_object_fini(rdev); 721 radeon_object_fini(rdev);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index eeefb6369e19..c8e64bbadbcf 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -810,6 +810,9 @@ struct drm_driver {
810 int (*gem_init_object) (struct drm_gem_object *obj); 810 int (*gem_init_object) (struct drm_gem_object *obj);
811 void (*gem_free_object) (struct drm_gem_object *obj); 811 void (*gem_free_object) (struct drm_gem_object *obj);
812 812
813 /* vga arb irq handler */
814 void (*vgaarb_irq)(struct drm_device *dev, bool state);
815
813 /* Driver private ops for this object */ 816 /* Driver private ops for this object */
814 struct vm_operations_struct *gem_vm_ops; 817 struct vm_operations_struct *gem_vm_ops;
815 818