Merge branch 'drm-core-next' of ../linux-2.6 into drm-next
authorDave Airlie <airlied@redhat.com>
Wed, 18 Nov 2009 00:09:55 +0000 (10:09 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 18 Nov 2009 00:09:55 +0000 (10:09 +1000)
1  2 
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_ttm.c

@@@ -186,7 -186,7 +186,7 @@@ static inline uint32_t r100_irq_ack(str
  
  int r100_irq_process(struct radeon_device *rdev)
  {
 -      uint32_t status;
 +      uint32_t status, msi_rearm;
  
        status = r100_irq_ack(rdev);
        if (!status) {
                }
                status = r100_irq_ack(rdev);
        }
 +      if (rdev->msi_enabled) {
 +              switch (rdev->family) {
 +              case CHIP_RS400:
 +              case CHIP_RS480:
 +                      msi_rearm = RREG32(RADEON_AIC_CNTL) & ~RS400_MSI_REARM;
 +                      WREG32(RADEON_AIC_CNTL, msi_rearm);
 +                      WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM);
 +                      break;
 +              default:
 +                      msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
 +                      WREG32(RADEON_MSI_REARM_EN, msi_rearm);
 +                      WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
 +                      break;
 +              }
 +      }
        return IRQ_HANDLED;
  }
  
@@@ -255,7 -240,7 +255,7 @@@ int r100_wb_init(struct radeon_device *
        int r;
  
        if (rdev->wb.wb_obj == NULL) {
 -              r = radeon_object_create(rdev, NULL, 4096,
 +              r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
                                         true,
                                         RADEON_GEM_DOMAIN_GTT,
                                         false, &rdev->wb.wb_obj);
@@@ -578,19 -563,19 +578,19 @@@ int r100_cp_init(struct radeon_device *
        indirect1_start = 16;
        /* cp setup */
        WREG32(0x718, pre_write_timer | (pre_write_limit << 28));
 -      WREG32(RADEON_CP_RB_CNTL,
 -#ifdef __BIG_ENDIAN
 -             RADEON_BUF_SWAP_32BIT |
 -#endif
 -             REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
 +      tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
               REG_SET(RADEON_RB_BLKSZ, rb_blksz) |
               REG_SET(RADEON_MAX_FETCH, max_fetch) |
               RADEON_RB_NO_UPDATE);
 +#ifdef __BIG_ENDIAN
 +      tmp |= RADEON_BUF_SWAP_32BIT;
 +#endif
 +      WREG32(RADEON_CP_RB_CNTL, tmp);
 +
        /* Set ring address */
        DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr);
        WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr);
        /* Force read & write ptr to 0 */
 -      tmp = RREG32(RADEON_CP_RB_CNTL);
        WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
        WREG32(RADEON_CP_RB_RPTR_WR, 0);
        WREG32(RADEON_CP_RB_WPTR, 0);
@@@ -1778,6 -1763,20 +1778,20 @@@ void r100_vram_init_sizes(struct radeon
                rdev->mc.real_vram_size = rdev->mc.aper_size;
  }
  
+ void r100_vga_set_state(struct radeon_device *rdev, bool state)
+ {
+       uint32_t temp;
+       temp = RREG32(RADEON_CONFIG_CNTL);
+       if (state == false) {
+               temp &= ~(1<<8);
+               temp |= (1<<9);
+       } else {
+               temp &= ~(1<<9);
+       }
+       WREG32(RADEON_CONFIG_CNTL, temp);
+ }
  void r100_vram_info(struct radeon_device *rdev)
  {
        r100_vram_get_type(rdev);
@@@ -2365,7 -2364,7 +2379,7 @@@ void r100_bandwidth_update(struct radeo
        /*
          Find the total latency for the display data.
        */
 -      disp_latency_overhead.full = rfixed_const(80);
 +      disp_latency_overhead.full = rfixed_const(8);
        disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
        mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
        mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
  static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
  {
        DRM_ERROR("pitch                      %d\n", t->pitch);
 +      DRM_ERROR("use_pitch                  %d\n", t->use_pitch);
        DRM_ERROR("width                      %d\n", t->width);
 +      DRM_ERROR("width_11                   %d\n", t->width_11);
        DRM_ERROR("height                     %d\n", t->height);
 +      DRM_ERROR("height_11                  %d\n", t->height_11);
        DRM_ERROR("num levels                 %d\n", t->num_levels);
        DRM_ERROR("depth                      %d\n", t->txdepth);
        DRM_ERROR("bpp                        %d\n", t->cpp);
@@@ -2627,17 -2623,15 +2641,17 @@@ static int r100_cs_track_texture_check(
                                else
                                        w = track->textures[u].pitch / (1 << i);
                        } else {
 -                              w = track->textures[u].width / (1 << i);
 +                              w = track->textures[u].width;
                                if (rdev->family >= CHIP_RV515)
                                        w |= track->textures[u].width_11;
 +                              w = w / (1 << i);
                                if (track->textures[u].roundup_w)
                                        w = roundup_pow_of_two(w);
                        }
 -                      h = track->textures[u].height / (1 << i);
 +                      h = track->textures[u].height;
                        if (rdev->family >= CHIP_RV515)
                                h |= track->textures[u].height_11;
 +                      h = h / (1 << i);
                        if (track->textures[u].roundup_h)
                                h = roundup_pow_of_two(h);
                        size += w * h;
@@@ -339,10 -339,11 +339,10 @@@ int r600_mc_init(struct radeon_device *
  {
        fixed20_12 a;
        u32 tmp;
 -      int chansize;
 +      int chansize, numchan;
        int r;
  
        /* Get VRAM informations */
 -      rdev->mc.vram_width = 128;
        rdev->mc.vram_is_ddr = true;
        tmp = RREG32(RAMCFG);
        if (tmp & CHANSIZE_OVERRIDE) {
        } else {
                chansize = 32;
        }
 -      if (rdev->family == CHIP_R600) {
 -              rdev->mc.vram_width = 8 * chansize;
 -      } else if (rdev->family == CHIP_RV670) {
 -              rdev->mc.vram_width = 4 * chansize;
 -      } else if ((rdev->family == CHIP_RV610) ||
 -                      (rdev->family == CHIP_RV620)) {
 -              rdev->mc.vram_width = chansize;
 -      } else if ((rdev->family == CHIP_RV630) ||
 -                      (rdev->family == CHIP_RV635)) {
 -              rdev->mc.vram_width = 2 * chansize;
 +      tmp = RREG32(CHMAP);
 +      switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
 +      case 0:
 +      default:
 +              numchan = 1;
 +              break;
 +      case 1:
 +              numchan = 2;
 +              break;
 +      case 2:
 +              numchan = 4;
 +              break;
 +      case 3:
 +              numchan = 8;
 +              break;
        }
 +      rdev->mc.vram_width = numchan * chansize;
        /* Could aper size report 0 ? */
        rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
        rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
                        rdev->mc.gtt_location = rdev->mc.mc_vram_size;
                }
        } else {
 -              if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
 -                      rdev->mc.vram_location = (RREG32(MC_VM_FB_LOCATION) &
 -                                                              0xFFFF) << 24;
 -                      rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
 -                      tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
 -                      if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
 -                              /* Enough place after vram */
 -                              rdev->mc.gtt_location = tmp;
 -                      } else if (rdev->mc.vram_location >= rdev->mc.gtt_size) {
 -                              /* Enough place before vram */
 +              rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
 +              rdev->mc.vram_location = (RREG32(MC_VM_FB_LOCATION) &
 +                                                      0xFFFF) << 24;
 +              tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
 +              if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
 +                      /* Enough place after vram */
 +                      rdev->mc.gtt_location = tmp;
 +              } else if (rdev->mc.vram_location >= rdev->mc.gtt_size) {
 +                      /* Enough place before vram */
 +                      rdev->mc.gtt_location = 0;
 +              } else {
 +                      /* Not enough place after or before shrink
 +                       * gart size
 +                       */
 +                      if (rdev->mc.vram_location > (0xFFFFFFFFUL - tmp)) {
                                rdev->mc.gtt_location = 0;
 +                              rdev->mc.gtt_size = rdev->mc.vram_location;
                        } else {
 -                              /* Not enough place after or before shrink
 -                               * gart size
 -                               */
 -                              if (rdev->mc.vram_location > (0xFFFFFFFFUL - tmp)) {
 -                                      rdev->mc.gtt_location = 0;
 -                                      rdev->mc.gtt_size = rdev->mc.vram_location;
 -                              } else {
 -                                      rdev->mc.gtt_location = tmp;
 -                                      rdev->mc.gtt_size = 0xFFFFFFFFUL - tmp;
 -                              }
 +                              rdev->mc.gtt_location = tmp;
 +                              rdev->mc.gtt_size = 0xFFFFFFFFUL - tmp;
                        }
 -                      rdev->mc.gtt_location = rdev->mc.mc_vram_size;
 -              } else {
 -                      rdev->mc.vram_location = 0x00000000UL;
 -                      rdev->mc.gtt_location = rdev->mc.mc_vram_size;
 -                      rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
                }
 +              rdev->mc.gtt_location = rdev->mc.mc_vram_size;
        }
        rdev->mc.vram_start = rdev->mc.vram_location;
        rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
@@@ -858,8 -859,7 +858,8 @@@ void r600_gpu_init(struct radeon_devic
            ((rdev->family) == CHIP_RV630) ||
            ((rdev->family) == CHIP_RV610) ||
            ((rdev->family) == CHIP_RV620) ||
 -          ((rdev->family) == CHIP_RS780)) {
 +          ((rdev->family) == CHIP_RS780) ||
 +          ((rdev->family) == CHIP_RS880)) {
                WREG32(DB_DEBUG, PREZ_MUST_WAIT_FOR_POSTZ_DONE);
        } else {
                WREG32(DB_DEBUG, 0);
        tmp = RREG32(SQ_MS_FIFO_SIZES);
        if (((rdev->family) == CHIP_RV610) ||
            ((rdev->family) == CHIP_RV620) ||
 -          ((rdev->family) == CHIP_RS780)) {
 +          ((rdev->family) == CHIP_RS780) ||
 +          ((rdev->family) == CHIP_RS880)) {
                tmp = (CACHE_FIFO_SIZE(0xa) |
                       FETCH_FIFO_HIWATER(0xa) |
                       DONE_FIFO_HIWATER(0xe0) |
                                            NUM_ES_STACK_ENTRIES(0));
        } else if (((rdev->family) == CHIP_RV610) ||
                   ((rdev->family) == CHIP_RV620) ||
 -                 ((rdev->family) == CHIP_RS780)) {
 +                 ((rdev->family) == CHIP_RS780) ||
 +                 ((rdev->family) == CHIP_RS880)) {
                /* no vertex cache */
                sq_config &= ~VC_ENABLE;
  
  
        if (((rdev->family) == CHIP_RV610) ||
            ((rdev->family) == CHIP_RV620) ||
 -          ((rdev->family) == CHIP_RS780)) {
 +          ((rdev->family) == CHIP_RS780) ||
 +          ((rdev->family) == CHIP_RS880)) {
                WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(TC_ONLY));
        } else {
                WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC));
        tmp = rdev->config.r600.max_pipes * 16;
        switch (rdev->family) {
        case CHIP_RV610:
 -      case CHIP_RS780:
        case CHIP_RV620:
 +      case CHIP_RS780:
 +      case CHIP_RS880:
                tmp += 32;
                break;
        case CHIP_RV670:
  
        switch (rdev->family) {
        case CHIP_RV610:
 -      case CHIP_RS780:
        case CHIP_RV620:
 +      case CHIP_RS780:
 +      case CHIP_RS880:
                tmp = TC_L2_SIZE(8);
                break;
        case CHIP_RV630:
@@@ -1272,17 -1267,19 +1272,17 @@@ int r600_cp_resume(struct radeon_devic
  
        /* Set ring buffer size */
        rb_bufsz = drm_order(rdev->cp.ring_size / 8);
 +      tmp = RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
  #ifdef __BIG_ENDIAN
 -      WREG32(CP_RB_CNTL, BUF_SWAP_32BIT | RB_NO_UPDATE |
 -              (drm_order(4096/8) << 8) | rb_bufsz);
 -#else
 -      WREG32(CP_RB_CNTL, RB_NO_UPDATE | (drm_order(4096/8) << 8) | rb_bufsz);
 +      tmp |= BUF_SWAP_32BIT;
  #endif
 +      WREG32(CP_RB_CNTL, tmp);
        WREG32(CP_SEM_WAIT_TIMER, 0x4);
  
        /* Set the write pointer delay */
        WREG32(CP_RB_WPTR_DELAY, 0);
  
        /* Initialize the ring buffer's read and write pointers */
 -      tmp = RREG32(CP_RB_CNTL);
        WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA);
        WREG32(CP_RB_RPTR_WR, 0);
        WREG32(CP_RB_WPTR, 0);
@@@ -1403,7 -1400,7 +1403,7 @@@ int r600_wb_enable(struct radeon_devic
        int r;
  
        if (rdev->wb.wb_obj == NULL) {
 -              r = radeon_object_create(rdev, NULL, 4096, true,
 +              r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
                                RADEON_GEM_DOMAIN_GTT, false, &rdev->wb.wb_obj);
                if (r) {
                        dev_warn(rdev->dev, "failed to create WB buffer (%d).\n", r);
@@@ -1453,8 -1450,8 +1453,8 @@@ int r600_copy_blit(struct radeon_devic
                   uint64_t src_offset, uint64_t dst_offset,
                   unsigned num_pages, struct radeon_fence *fence)
  {
 -      r600_blit_prepare_copy(rdev, num_pages * 4096);
 -      r600_kms_blit_copy(rdev, src_offset, dst_offset, num_pages * 4096);
 +      r600_blit_prepare_copy(rdev, num_pages * RADEON_GPU_PAGE_SIZE);
 +      r600_kms_blit_copy(rdev, src_offset, dst_offset, num_pages * RADEON_GPU_PAGE_SIZE);
        r600_blit_done_copy(rdev, fence);
        return 0;
  }
@@@ -1537,6 -1534,20 +1537,20 @@@ int r600_startup(struct radeon_device *
        return 0;
  }
  
+ void r600_vga_set_state(struct radeon_device *rdev, bool state)
+ {
+       uint32_t temp;
+       temp = RREG32(CONFIG_CNTL);
+       if (state == false) {
+               temp &= ~(1<<0);
+               temp |= (1<<1);
+       } else {
+               temp &= ~(1<<1);
+       }
+       WREG32(CONFIG_CNTL, temp);
+ }
  int r600_resume(struct radeon_device *rdev)
  {
        int r;
@@@ -1621,13 -1632,10 +1635,13 @@@ int r600_init(struct radeon_device *rde
        r600_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 +      /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
        r = radeon_clocks_init(rdev);
        if (r)
                return r;
 +      /* Initialize power management */
 +      radeon_pm_init(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
        if (r)
@@@ -78,6 -78,7 +78,7 @@@
  #define CB_COLOR0_MASK                                  0x28100
  
  #define       CONFIG_MEMSIZE                                  0x5428
+ #define CONFIG_CNTL                                   0x5424
  #define       CP_STAT                                         0x8680
  #define       CP_COHER_BASE                                   0x85F8
  #define       CP_DEBUG                                        0xC1FC
  #define       PCIE_PORT_INDEX                                 0x0038
  #define       PCIE_PORT_DATA                                  0x003C
  
 +#define CHMAP                                         0x2004
 +#define               NOOFCHAN_SHIFT                                  12
 +#define               NOOFCHAN_MASK                                   0x00003000
 +
  #define RAMCFG                                                0x2408
  #define               NOOFBANK_SHIFT                                  0
  #define               NOOFBANK_MASK                                   0x00000001
@@@ -139,10 -139,6 +139,10 @@@ struct radeon_clock 
        uint32_t default_sclk;
  };
  
 +/*
 + * Power management
 + */
 +int radeon_pm_init(struct radeon_device *rdev);
  
  /*
   * Fences.
@@@ -280,8 -276,6 +280,8 @@@ union radeon_gart_table 
        struct radeon_gart_table_vram   vram;
  };
  
 +#define RADEON_GPU_PAGE_SIZE 4096
 +
  struct radeon_gart {
        dma_addr_t                      table_addr;
        unsigned                        num_gpu_pages;
@@@ -596,6 -590,7 +596,7 @@@ struct radeon_asic 
        void (*fini)(struct radeon_device *rdev);
        int (*resume)(struct radeon_device *rdev);
        int (*suspend)(struct radeon_device *rdev);
+       void (*vga_set_state)(struct radeon_device *rdev, bool state);
        int (*gpu_reset)(struct radeon_device *rdev);
        void (*gart_tlb_flush)(struct radeon_device *rdev);
        int (*gart_set_page)(struct radeon_device *rdev, int i, uint64_t addr);
                    uint64_t dst_offset,
                    unsigned num_pages,
                    struct radeon_fence *fence);
 +      uint32_t (*get_engine_clock)(struct radeon_device *rdev);
        void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock);
 +      uint32_t (*get_memory_clock)(struct radeon_device *rdev);
        void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
        void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
        void (*set_clock_gating)(struct radeon_device *rdev, int enable);
@@@ -790,7 -783,6 +791,7 @@@ struct radeon_device 
        const struct firmware *me_fw;   /* all family ME firmware */
        const struct firmware *pfp_fw;  /* r6/700 PFP firmware */
        struct r600_blit r600_blit;
 +      int msi_enabled; /* msi enabled */
  };
  
  int radeon_device_init(struct radeon_device *rdev,
@@@ -945,6 -937,7 +946,7 @@@ static inline void radeon_ring_write(st
  #define radeon_resume(rdev) (rdev)->asic->resume((rdev))
  #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
  #define radeon_cs_parse(p) rdev->asic->cs_parse((p))
+ #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
  #define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev))
  #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev))
  #define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart_set_page((rdev), (i), (p))
  #define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f))
  #define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f))
  #define radeon_copy(rdev, s, d, np, f) (rdev)->asic->copy((rdev), (s), (d), (np), (f))
 +#define radeon_get_engine_clock(rdev) (rdev)->asic->get_engine_clock((rdev))
  #define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
 +#define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev))
  #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
  #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
  #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
  /*
   * common functions
   */
 +uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev);
  void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
  void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
  
 +uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev);
  void radeon_atom_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
 +uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev);
  void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock);
  void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
  
@@@ -50,6 -47,7 +50,7 @@@ extern int r100_suspend(struct radeon_d
  extern int r100_resume(struct radeon_device *rdev);
  uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
  void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+ void r100_vga_set_state(struct radeon_device *rdev, bool state);
  int r100_gpu_reset(struct radeon_device *rdev);
  u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
  void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
@@@ -81,6 -79,7 +82,7 @@@ static struct radeon_asic r100_asic = 
        .fini = &r100_fini,
        .suspend = &r100_suspend,
        .resume = &r100_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r100_gpu_reset,
        .gart_tlb_flush = &r100_pci_gart_tlb_flush,
        .gart_set_page = &r100_pci_gart_set_page,
@@@ -96,9 -95,7 +98,9 @@@
        .copy_blit = &r100_copy_blit,
        .copy_dma = NULL,
        .copy = &r100_copy_blit,
 +      .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
 +      .get_memory_clock = NULL,
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@@ -135,6 -132,7 +137,7 @@@ static struct radeon_asic r300_asic = 
        .fini = &r300_fini,
        .suspend = &r300_suspend,
        .resume = &r300_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
        .gart_tlb_flush = &r100_pci_gart_tlb_flush,
        .gart_set_page = &r100_pci_gart_set_page,
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
 +      .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
 +      .get_memory_clock = NULL,
        .set_memory_clock = NULL,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@@ -173,6 -169,7 +176,7 @@@ static struct radeon_asic r420_asic = 
        .fini = &r420_fini,
        .suspend = &r420_suspend,
        .resume = &r420_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
        .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
        .gart_set_page = &rv370_pcie_gart_set_page,
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
 +      .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
 +      .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@@ -216,6 -211,7 +220,7 @@@ static struct radeon_asic rs400_asic = 
        .fini = &rs400_fini,
        .suspend = &rs400_suspend,
        .resume = &rs400_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
        .gart_tlb_flush = &rs400_gart_tlb_flush,
        .gart_set_page = &rs400_gart_set_page,
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
 +      .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
 +      .get_memory_clock = NULL,
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@@ -263,6 -257,7 +268,7 @@@ static struct radeon_asic rs600_asic = 
        .fini = &rs600_fini,
        .suspend = &rs600_suspend,
        .resume = &rs600_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
        .gart_tlb_flush = &rs600_gart_tlb_flush,
        .gart_set_page = &rs600_gart_set_page,
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
 +      .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
 +      .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@@ -303,6 -296,7 +309,7 @@@ static struct radeon_asic rs690_asic = 
        .fini = &rs690_fini,
        .suspend = &rs690_suspend,
        .resume = &rs690_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
        .gart_tlb_flush = &rs400_gart_tlb_flush,
        .gart_set_page = &rs400_gart_set_page,
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r300_copy_dma,
 +      .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
 +      .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@@ -349,6 -341,7 +356,7 @@@ static struct radeon_asic rv515_asic = 
        .fini = &rv515_fini,
        .suspend = &rv515_suspend,
        .resume = &rv515_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &rv515_gpu_reset,
        .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
        .gart_set_page = &rv370_pcie_gart_set_page,
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
 +      .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
 +      .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@@ -386,6 -377,7 +394,7 @@@ static struct radeon_asic r520_asic = 
        .fini = &rv515_fini,
        .suspend = &rv515_suspend,
        .resume = &r520_resume,
+       .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &rv515_gpu_reset,
        .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
        .gart_set_page = &rv370_pcie_gart_set_page,
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
 +      .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
 +      .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@@ -419,6 -409,7 +428,7 @@@ int r600_init(struct radeon_device *rde
  void r600_fini(struct radeon_device *rdev);
  int r600_suspend(struct radeon_device *rdev);
  int r600_resume(struct radeon_device *rdev);
+ void r600_vga_set_state(struct radeon_device *rdev, bool state);
  int r600_wb_init(struct radeon_device *rdev);
  void r600_wb_fini(struct radeon_device *rdev);
  void r600_cp_commit(struct radeon_device *rdev);
@@@ -452,6 -443,7 +462,7 @@@ static struct radeon_asic r600_asic = 
        .suspend = &r600_suspend,
        .resume = &r600_resume,
        .cp_commit = &r600_cp_commit,
+       .vga_set_state = &r600_vga_set_state,
        .gpu_reset = &r600_gpu_reset,
        .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
        .gart_set_page = &rs600_gart_set_page,
        .copy_blit = &r600_copy_blit,
        .copy_dma = &r600_copy_blit,
        .copy = &r600_copy_blit,
 +      .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
 +      .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@@ -491,6 -481,7 +502,7 @@@ static struct radeon_asic rv770_asic = 
        .resume = &rv770_resume,
        .cp_commit = &r600_cp_commit,
        .gpu_reset = &rv770_gpu_reset,
+       .vga_set_state = &r600_vga_set_state,
        .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
        .gart_set_page = &rs600_gart_set_page,
        .ring_test = &r600_ring_test,
        .copy_blit = &r600_copy_blit,
        .copy_dma = &r600_copy_blit,
        .copy = &r600_copy_blit,
 +      .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
 +      .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@@ -29,6 -29,7 +29,7 @@@
  #include <drm/drmP.h>
  #include <drm/drm_crtc_helper.h>
  #include <drm/radeon_drm.h>
+ #include <linux/vgaarb.h>
  #include "radeon_reg.h"
  #include "radeon.h"
  #include "radeon_asic.h"
@@@ -443,24 -444,20 +444,24 @@@ static uint32_t cail_reg_read(struct ca
        return r;
  }
  
 -static struct card_info atom_card_info = {
 -      .dev = NULL,
 -      .reg_read = cail_reg_read,
 -      .reg_write = cail_reg_write,
 -      .mc_read = cail_mc_read,
 -      .mc_write = cail_mc_write,
 -      .pll_read = cail_pll_read,
 -      .pll_write = cail_pll_write,
 -};
 -
  int radeon_atombios_init(struct radeon_device *rdev)
  {
 -      atom_card_info.dev = rdev->ddev;
 -      rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios);
 +      struct card_info *atom_card_info =
 +          kzalloc(sizeof(struct card_info), GFP_KERNEL);
 +
 +      if (!atom_card_info)
 +              return -ENOMEM;
 +
 +      rdev->mode_info.atom_card_info = atom_card_info;
 +      atom_card_info->dev = rdev->ddev;
 +      atom_card_info->reg_read = cail_reg_read;
 +      atom_card_info->reg_write = cail_reg_write;
 +      atom_card_info->mc_read = cail_mc_read;
 +      atom_card_info->mc_write = cail_mc_write;
 +      atom_card_info->pll_read = cail_pll_read;
 +      atom_card_info->pll_write = cail_pll_write;
 +
 +      rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios);
        radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
        return 0;
  }
  void radeon_atombios_fini(struct radeon_device *rdev)
  {
        kfree(rdev->mode_info.atom_context);
 +      kfree(rdev->mode_info.atom_card_info);
  }
  
  int radeon_combios_init(struct radeon_device *rdev)
@@@ -481,6 -477,18 +482,18 @@@ void radeon_combios_fini(struct radeon_
  {
  }
  
+ /* if we get transitioned to only one device, tak VGA back */
+ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
+ {
+       struct radeon_device *rdev = cookie;
+       radeon_vga_set_state(rdev, state);
+       if (state)
+               return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
+                      VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+       else
+               return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+ }
  void radeon_agp_disable(struct radeon_device *rdev)
  {
        rdev->flags &= ~RADEON_IS_AGP;
@@@ -573,9 -581,15 +586,15 @@@ int radeon_device_init(struct radeon_de
        DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
        DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
  
+       /* if we have > 1 VGA cards, then disable the radeon VGA resources */
+       /* this will fail for cards that aren't VGA class devices, just
+        * ignore it */
+       vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
        r = radeon_init(rdev);
        if (r)
                return r;
        if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) {
                /* Acceleration not working on AGP card try again
                 * with fallback to PCI or PCIE GART
@@@ -600,8 -614,8 +619,8 @@@ void radeon_device_fini(struct radeon_d
  {
        DRM_INFO("radeon: finishing device.\n");
        rdev->shutdown = true;
-       /* Order matter so becarefull if you rearrange anythings */
        radeon_fini(rdev);
+       vga_client_register(rdev->pdev, NULL, NULL, NULL);
        iounmap(rdev->rmmio);
        rdev->rmmio = NULL;
  }
@@@ -295,12 -295,6 +295,12 @@@ static int radeon_move_vram_ram(struct 
        if (unlikely(r)) {
                return r;
        }
 +
 +      r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement);
 +      if (unlikely(r)) {
 +              goto out_cleanup;
 +      }
 +
        r = ttm_tt_bind(bo->ttm, &tmp_mem);
        if (unlikely(r)) {
                goto out_cleanup;
@@@ -536,7 -530,7 +536,7 @@@ void radeon_ttm_fini(struct radeon_devi
  }
  
  static struct vm_operations_struct radeon_ttm_vm_ops;
- static struct vm_operations_struct *ttm_vm_ops = NULL;
+ static const struct vm_operations_struct *ttm_vm_ops = NULL;
  
  static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
  {