drm: Merge tag 'v3.3-rc7' into drm-core-next
authorDave Airlie <airlied@redhat.com>
Thu, 15 Mar 2012 10:24:32 +0000 (10:24 +0000)
committerDave Airlie <airlied@redhat.com>
Thu, 15 Mar 2012 10:24:32 +0000 (10:24 +0000)
Merge the fixes so far into core-next, needed to test
intel driver.

Conflicts:
drivers/gpu/drm/i915/intel_ringbuffer.c

25 files changed:
1  2 
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/gma500/cdv_device.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/gtt.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c

@@@ -46,13 -46,39 +46,13 @@@ struct exynos_drm_fbdev 
        struct exynos_drm_gem_obj       *exynos_gem_obj;
  };
  
 -static int exynos_drm_fbdev_set_par(struct fb_info *info)
 -{
 -      struct fb_var_screeninfo *var = &info->var;
 -
 -      switch (var->bits_per_pixel) {
 -      case 32:
 -      case 24:
 -      case 18:
 -      case 16:
 -      case 12:
 -              info->fix.visual = FB_VISUAL_TRUECOLOR;
 -              break;
 -      case 1:
 -              info->fix.visual = FB_VISUAL_MONO01;
 -              break;
 -      default:
 -              info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 -              break;
 -      }
 -
 -      info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
 -
 -      return drm_fb_helper_set_par(info);
 -}
 -
 -
  static struct fb_ops exynos_drm_fb_ops = {
        .owner          = THIS_MODULE,
        .fb_fillrect    = cfb_fillrect,
        .fb_copyarea    = cfb_copyarea,
        .fb_imageblit   = cfb_imageblit,
        .fb_check_var   = drm_fb_helper_check_var,
 -      .fb_set_par     = exynos_drm_fbdev_set_par,
 +      .fb_set_par     = drm_fb_helper_set_par,
        .fb_blank       = drm_fb_helper_blank,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_setcmap     = drm_fb_helper_setcmap,
@@@ -169,66 -195,6 +169,6 @@@ out
        return ret;
  }
  
- static bool
- exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb,
-                           struct drm_fb_helper_surface_size *sizes)
- {
-       if (fb->width != sizes->surface_width)
-               return false;
-       if (fb->height != sizes->surface_height)
-               return false;
-       if (fb->bits_per_pixel != sizes->surface_bpp)
-               return false;
-       if (fb->depth != sizes->surface_depth)
-               return false;
-       return true;
- }
- static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
-                                     struct drm_fb_helper_surface_size *sizes)
- {
-       struct drm_device *dev = helper->dev;
-       struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
-       struct exynos_drm_gem_obj *exynos_gem_obj;
-       struct drm_framebuffer *fb = helper->fb;
-       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
-       unsigned long size;
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-       if (exynos_drm_fbdev_is_samefb(fb, sizes))
-               return 0;
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3);
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                                                         sizes->surface_depth);
-       if (exynos_fbdev->exynos_gem_obj)
-               exynos_drm_gem_destroy(exynos_fbdev->exynos_gem_obj);
-       if (fb->funcs->destroy)
-               fb->funcs->destroy(fb);
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-       exynos_gem_obj = exynos_drm_gem_create(dev, size);
-       if (IS_ERR(exynos_gem_obj))
-               return PTR_ERR(exynos_gem_obj);
-       exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
-       helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
-                       &exynos_gem_obj->base);
-       if (IS_ERR_OR_NULL(helper->fb)) {
-               DRM_ERROR("failed to create drm framebuffer.\n");
-               return PTR_ERR(helper->fb);
-       }
-       return exynos_drm_fbdev_update(helper, helper->fb);
- }
  static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
                                   struct drm_fb_helper_surface_size *sizes)
  {
  
        DRM_DEBUG_KMS("%s\n", __FILE__);
  
+       /*
+        * with !helper->fb, it means that this funcion is called first time
+        * and after that, the helper->fb would be used as clone mode.
+        */
        if (!helper->fb) {
                ret = exynos_drm_fbdev_create(helper, sizes);
                if (ret < 0) {
                 * because register_framebuffer() should be called.
                 */
                ret = 1;
-       } else {
-               ret = exynos_drm_fbdev_recreate(helper, sizes);
-               if (ret < 0) {
-                       DRM_ERROR("failed to reconfigure fbdev\n");
-                       return ret;
-               }
        }
  
        return ret;
@@@ -202,12 -202,13 +202,12 @@@ static inline void CDV_MSG_WRITE32(uin
        pci_dev_put(pci_root);
  }
  
 -#define PSB_APM_CMD                   0x0
 -#define PSB_APM_STS                   0x04
  #define PSB_PM_SSC                    0x20
  #define PSB_PM_SSS                    0x30
 -#define PSB_PWRGT_GFX_MASK            0x3
 -#define CDV_PWRGT_DISPLAY_CNTR                0x000fc00c
 -#define CDV_PWRGT_DISPLAY_STS         0x000fc00c
 +#define PSB_PWRGT_GFX_ON              0x02
 +#define PSB_PWRGT_GFX_OFF             0x01
 +#define PSB_PWRGT_GFX_D0              0x00
 +#define PSB_PWRGT_GFX_D3              0x03
  
  static void cdv_init_pm(struct drm_device *dev)
  {
        dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
                                                        PSB_OSPMBA) & 0xFFFF;
  
 -      /* Force power on for now */
 +      /* Power status */
        pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
 -      pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
  
 +      /* Enable the GPU */
 +      pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
 +      pwr_cnt |= PSB_PWRGT_GFX_ON;
        outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
 +
 +      /* Wait for the GPU power */
        for (i = 0; i < 5; i++) {
                u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
                if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0)
 -                      break;
 -              udelay(10);
 -      }
 -      pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
 -      pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR;
 -      outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC);
 -      for (i = 0; i < 5; i++) {
 -              u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
 -              if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0)
 -                      break;
 +                      return;
                udelay(10);
        }
 +      dev_err(dev->dev, "GPU: power management timed out.\n");
  }
  
  /**
   *
   *    Save the state we need in order to be able to restore the interface
   *    upon resume from suspend
 - *
 - *    FIXME: review
   */
  static int cdv_save_display_registers(struct drm_device *dev)
  {
 +      struct drm_psb_private *dev_priv = dev->dev_private;
 +      struct psb_save_area *regs = &dev_priv->regs;
 +      struct drm_connector *connector;
 +
 +      dev_info(dev->dev, "Saving GPU registers.\n");
 +
 +      pci_read_config_byte(dev->pdev, 0xF4, &regs->cdv.saveLBB);
 +
 +      regs->cdv.saveDSPCLK_GATE_D = REG_READ(DSPCLK_GATE_D);
 +      regs->cdv.saveRAMCLK_GATE_D = REG_READ(RAMCLK_GATE_D);
 +
 +      regs->cdv.saveDSPARB = REG_READ(DSPARB);
 +      regs->cdv.saveDSPFW[0] = REG_READ(DSPFW1);
 +      regs->cdv.saveDSPFW[1] = REG_READ(DSPFW2);
 +      regs->cdv.saveDSPFW[2] = REG_READ(DSPFW3);
 +      regs->cdv.saveDSPFW[3] = REG_READ(DSPFW4);
 +      regs->cdv.saveDSPFW[4] = REG_READ(DSPFW5);
 +      regs->cdv.saveDSPFW[5] = REG_READ(DSPFW6);
 +
 +      regs->cdv.saveADPA = REG_READ(ADPA);
 +
 +      regs->cdv.savePP_CONTROL = REG_READ(PP_CONTROL);
 +      regs->cdv.savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS);
 +      regs->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
 +      regs->saveBLC_PWM_CTL2 = REG_READ(BLC_PWM_CTL2);
 +      regs->cdv.saveLVDS = REG_READ(LVDS);
 +
 +      regs->cdv.savePFIT_CONTROL = REG_READ(PFIT_CONTROL);
 +
 +      regs->cdv.savePP_ON_DELAYS = REG_READ(PP_ON_DELAYS);
 +      regs->cdv.savePP_OFF_DELAYS = REG_READ(PP_OFF_DELAYS);
 +      regs->cdv.savePP_CYCLE = REG_READ(PP_CYCLE);
 +
 +      regs->cdv.saveVGACNTRL = REG_READ(VGACNTRL);
 +
 +      regs->cdv.saveIER = REG_READ(PSB_INT_ENABLE_R);
 +      regs->cdv.saveIMR = REG_READ(PSB_INT_MASK_R);
 +
 +      list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 +              connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
 +
        return 0;
  }
  
   */
  static int cdv_restore_display_registers(struct drm_device *dev)
  {
 +      struct drm_psb_private *dev_priv = dev->dev_private;
 +      struct psb_save_area *regs = &dev_priv->regs;
 +      struct drm_connector *connector;
 +      u32 temp;
 +
 +      pci_write_config_byte(dev->pdev, 0xF4, regs->cdv.saveLBB);
 +
 +      REG_WRITE(DSPCLK_GATE_D, regs->cdv.saveDSPCLK_GATE_D);
 +      REG_WRITE(RAMCLK_GATE_D, regs->cdv.saveRAMCLK_GATE_D);
 +
 +      /* BIOS does below anyway */
 +      REG_WRITE(DPIO_CFG, 0);
 +      REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
 +
 +      temp = REG_READ(DPLL_A);
 +      if ((temp & DPLL_SYNCLOCK_ENABLE) == 0) {
 +              REG_WRITE(DPLL_A, temp | DPLL_SYNCLOCK_ENABLE);
 +              REG_READ(DPLL_A);
 +      }
 +
 +      temp = REG_READ(DPLL_B);
 +      if ((temp & DPLL_SYNCLOCK_ENABLE) == 0) {
 +              REG_WRITE(DPLL_B, temp | DPLL_SYNCLOCK_ENABLE);
 +              REG_READ(DPLL_B);
 +      }
 +
 +      udelay(500);
 +
 +      REG_WRITE(DSPFW1, regs->cdv.saveDSPFW[0]);
 +      REG_WRITE(DSPFW2, regs->cdv.saveDSPFW[1]);
 +      REG_WRITE(DSPFW3, regs->cdv.saveDSPFW[2]);
 +      REG_WRITE(DSPFW4, regs->cdv.saveDSPFW[3]);
 +      REG_WRITE(DSPFW5, regs->cdv.saveDSPFW[4]);
 +      REG_WRITE(DSPFW6, regs->cdv.saveDSPFW[5]);
 +
 +      REG_WRITE(DSPARB, regs->cdv.saveDSPARB);
 +      REG_WRITE(ADPA, regs->cdv.saveADPA);
 +
 +      REG_WRITE(BLC_PWM_CTL2, regs->saveBLC_PWM_CTL2);
 +      REG_WRITE(LVDS, regs->cdv.saveLVDS);
 +      REG_WRITE(PFIT_CONTROL, regs->cdv.savePFIT_CONTROL);
 +      REG_WRITE(PFIT_PGM_RATIOS, regs->cdv.savePFIT_PGM_RATIOS);
 +      REG_WRITE(BLC_PWM_CTL, regs->saveBLC_PWM_CTL);
 +      REG_WRITE(PP_ON_DELAYS, regs->cdv.savePP_ON_DELAYS);
 +      REG_WRITE(PP_OFF_DELAYS, regs->cdv.savePP_OFF_DELAYS);
 +      REG_WRITE(PP_CYCLE, regs->cdv.savePP_CYCLE);
 +      REG_WRITE(PP_CONTROL, regs->cdv.savePP_CONTROL);
 +
 +      REG_WRITE(VGACNTRL, regs->cdv.saveVGACNTRL);
 +
 +      REG_WRITE(PSB_INT_ENABLE_R, regs->cdv.saveIER);
 +      REG_WRITE(PSB_INT_MASK_R, regs->cdv.saveIMR);
 +
 +      /* Fix arbitration bug */
 +      CDV_MSG_WRITE32(3, 0x30, 0x08027108);
 +
 +      drm_mode_config_reset(dev);
 +
 +      list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 +              connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
 +
 +      /* Resume the modeset for every activated CRTC */
 +      drm_helper_resume_force_mode(dev);
        return 0;
  }
  
  static int cdv_power_down(struct drm_device *dev)
  {
 +      struct drm_psb_private *dev_priv = dev->dev_private;
 +      u32 pwr_cnt, pwr_mask, pwr_sts;
 +      int tries = 5;
 +
 +      pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
 +      pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
 +      pwr_cnt |= PSB_PWRGT_GFX_OFF;
 +      pwr_mask = PSB_PWRGT_GFX_MASK;
 +
 +      outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
 +
 +      while (tries--) {
 +              pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
 +              if ((pwr_sts & pwr_mask) == PSB_PWRGT_GFX_D3)
 +                      return 0;
 +              udelay(10);
 +      }
        return 0;
  }
  
  static int cdv_power_up(struct drm_device *dev)
  {
 +      struct drm_psb_private *dev_priv = dev->dev_private;
 +      u32 pwr_cnt, pwr_mask, pwr_sts;
 +      int tries = 5;
 +
 +      pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
 +      pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
 +      pwr_cnt |= PSB_PWRGT_GFX_ON;
 +      pwr_mask = PSB_PWRGT_GFX_MASK;
 +
 +      outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
 +
 +      while (tries--) {
 +              pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
 +              if ((pwr_sts & pwr_mask) == PSB_PWRGT_GFX_D0)
 +                      return 0;
 +              udelay(10);
 +      }
        return 0;
  }
  
@@@ -452,6 -321,8 +452,8 @@@ static int cdv_chip_setup(struct drm_de
        cdv_get_core_freq(dev);
        gma_intel_opregion_init(dev);
        psb_intel_init_bios(dev);
+       REG_WRITE(PORT_HOTPLUG_EN, 0);
+       REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
        return 0;
  }
  
@@@ -111,6 -111,39 +111,6 @@@ static int psbfb_pan(struct fb_var_scre
          return 0;
  }
  
 -void psbfb_suspend(struct drm_device *dev)
 -{
 -      struct drm_framebuffer *fb;
 -
 -      console_lock();
 -      mutex_lock(&dev->mode_config.mutex);
 -      list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 -              struct psb_framebuffer *psbfb = to_psb_fb(fb);
 -              struct fb_info *info = psbfb->fbdev;
 -              fb_set_suspend(info, 1);
 -              drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
 -      }
 -      mutex_unlock(&dev->mode_config.mutex);
 -      console_unlock();
 -}
 -
 -void psbfb_resume(struct drm_device *dev)
 -{
 -      struct drm_framebuffer *fb;
 -
 -      console_lock();
 -      mutex_lock(&dev->mode_config.mutex);
 -      list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 -              struct psb_framebuffer *psbfb = to_psb_fb(fb);
 -              struct fb_info *info = psbfb->fbdev;
 -              fb_set_suspend(info, 0);
 -              drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
 -      }
 -      mutex_unlock(&dev->mode_config.mutex);
 -      console_unlock();
 -      drm_helper_disable_unused_functions(dev);
 -}
 -
  static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
  {
        struct psb_framebuffer *psbfb = vma->vm_private_data;
@@@ -214,7 -247,6 +214,6 @@@ static struct fb_ops psbfb_roll_ops = 
        .fb_imageblit = cfb_imageblit,
        .fb_pan_display = psbfb_pan,
        .fb_mmap = psbfb_mmap,
-       .fb_sync = psbfb_sync,
        .fb_ioctl = psbfb_ioctl,
  };
  
@@@ -358,7 -390,6 +357,7 @@@ static int psbfb_create(struct psb_fbde
        mode_cmd.width = sizes->surface_width;
        mode_cmd.height = sizes->surface_height;
        bpp = sizes->surface_bpp;
 +      depth = sizes->surface_depth;
  
        /* No 24bit packed */
        if (bpp == 24)
                 * is ok with some fonts
                 */
                mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines);
 -              depth = sizes->surface_depth;
  
                size = mode_cmd.pitches[0] * mode_cmd.height;
                size = ALIGN(size, PAGE_SIZE);
        fbdev->psb_fb_helper.fb = fb;
        fbdev->psb_fb_helper.fbdev = info;
  
 +      drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
        strcpy(info->fix.id, "psbfb");
  
        info->flags = FBINFO_DEFAULT;
                info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
        }
  
 -      drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
                                sizes->fb_width, sizes->fb_height);
  
        info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
        info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
  
 -      info->pixmap.size = 64 * 1024;
 -      info->pixmap.buf_align = 8;
 -      info->pixmap.access_align = 32;
 -      info->pixmap.flags = FB_PIXMAP_SYSTEM;
 -      info->pixmap.scan_align = 1;
 +      /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
  
        dev_info(dev->dev, "allocated %dx%d fb\n",
                                        psbfb->base.width, psbfb->base.height);
@@@ -523,21 -559,11 +522,21 @@@ static struct drm_framebuffer *psb_user
  static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                                                        u16 blue, int regno)
  {
 +      struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
 +
 +      intel_crtc->lut_r[regno] = red >> 8;
 +      intel_crtc->lut_g[regno] = green >> 8;
 +      intel_crtc->lut_b[regno] = blue >> 8;
  }
  
  static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
                                        u16 *green, u16 *blue, int regno)
  {
 +      struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
 +
 +      *red = intel_crtc->lut_r[regno] << 8;
 +      *green = intel_crtc->lut_g[regno] << 8;
 +      *blue = intel_crtc->lut_b[regno] << 8;
  }
  
  static int psbfb_probe(struct drm_fb_helper *helper,
@@@ -562,7 -588,7 +561,7 @@@ struct drm_fb_helper_funcs psb_fb_helpe
        .fb_probe = psbfb_probe,
  };
  
 -int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 +static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
  {
        struct fb_info *info;
        struct psb_framebuffer *psbfb = &fbdev->pfb;
@@@ -604,7 -630,7 +603,7 @@@ int psb_fbdev_init(struct drm_device *d
        return 0;
  }
  
 -void psb_fbdev_fini(struct drm_device *dev)
 +static void psb_fbdev_fini(struct drm_device *dev)
  {
        struct drm_psb_private *dev_priv = dev->dev_private;
  
@@@ -698,7 -724,10 +697,7 @@@ static int psb_create_backlight_propert
        if (dev_priv->backlight_property)
                return 0;
  
 -      backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
 -                                                      "backlight", 2);
 -      backlight->values[0] = 0;
 -      backlight->values[1] = 100;
 +      backlight = drm_property_create_range(dev, 0, "backlight", 0, 100);
  
        dev_priv->backlight_property = backlight;
  
@@@ -57,7 -57,7 +57,7 @@@ static inline uint32_t psb_gtt_mask_pte
   *    Given a gtt_range object return the GTT offset of the page table
   *    entries for this gtt_range
   */
 -u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
 +static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
  {
        struct drm_psb_private *dev_priv = dev->dev_private;
        unsigned long offset;
@@@ -378,7 -378,7 +378,7 @@@ void psb_gtt_free_range(struct drm_devi
        kfree(gt);
  }
  
 -void psb_gtt_alloc(struct drm_device *dev)
 +static void psb_gtt_alloc(struct drm_device *dev)
  {
        struct drm_psb_private *dev_priv = dev->dev_private;
        init_rwsem(&dev_priv->gtt.sem);
@@@ -446,10 -446,9 +446,9 @@@ int psb_gtt_init(struct drm_device *dev
        pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
        gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
                                                                >> PAGE_SHIFT;
-       /* Some CDV firmware doesn't report this currently. In which case the
-          system has 64 gtt pages */
+       /* CDV doesn't report this. In which case the system has 64 gtt pages */
        if (pg->gtt_start == 0 || gtt_pages == 0) {
-               dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
+               dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n");
                gtt_pages = 64;
                pg->gtt_start = dev_priv->pge_ctl;
        }
  
        if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
                static struct resource fudge;   /* Preferably peppermint */
-               /* This can occur on CDV SDV systems. Fudge it in this case.
+               /* This can occur on CDV systems. Fudge it in this case.
                   We really don't care what imaginary space is being allocated
                   at this point */
-               dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
+               dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n");
                pg->gatt_start = 0x40000000;
                pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
                /* This is a little confusing but in fact the GTT is providing
  #define   GEN6_MBC_SNPCR_LOW  (2<<21)
  #define   GEN6_MBC_SNPCR_MIN  (3<<21) /* only 1/16th of the cache is shared */
  
 +#define GEN6_MBCTL            0x0907c
 +#define   GEN6_MBCTL_ENABLE_BOOT_FETCH        (1 << 4)
 +#define   GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3)
 +#define   GEN6_MBCTL_BME_UPDATE_ENABLE        (1 << 2)
 +#define   GEN6_MBCTL_MAE_UPDATE_ENABLE        (1 << 1)
 +#define   GEN6_MBCTL_BOOT_FETCH_MECH  (1 << 0)
 +
  #define GEN6_GDRST    0x941c
  #define  GEN6_GRDOM_FULL              (1 << 0)
  #define  GEN6_GRDOM_RENDER            (1 << 1)
  #define  GEN6_GRDOM_MEDIA             (1 << 2)
  #define  GEN6_GRDOM_BLT                       (1 << 3)
  
 +/* PPGTT stuff */
 +#define GEN6_GTT_ADDR_ENCODE(addr)    ((addr) | (((addr) >> 28) & 0xff0))
 +
 +#define GEN6_PDE_VALID                        (1 << 0)
 +#define GEN6_PDE_LARGE_PAGE           (2 << 0) /* use 32kb pages */
 +/* gen6+ has bit 11-4 for physical addr bit 39-32 */
 +#define GEN6_PDE_ADDR_ENCODE(addr)    GEN6_GTT_ADDR_ENCODE(addr)
 +
 +#define GEN6_PTE_VALID                        (1 << 0)
 +#define GEN6_PTE_UNCACHED             (1 << 1)
 +#define GEN6_PTE_CACHE_LLC            (2 << 1)
 +#define GEN6_PTE_CACHE_LLC_MLC                (3 << 1)
 +#define GEN6_PTE_CACHE_BITS           (3 << 1)
 +#define GEN6_PTE_GFDT                 (1 << 3)
 +#define GEN6_PTE_ADDR_ENCODE(addr)    GEN6_GTT_ADDR_ENCODE(addr)
 +
 +#define RING_PP_DIR_BASE(ring)                ((ring)->mmio_base+0x228)
 +#define RING_PP_DIR_BASE_READ(ring)   ((ring)->mmio_base+0x518)
 +#define RING_PP_DIR_DCLV(ring)                ((ring)->mmio_base+0x220)
 +#define   PP_DIR_DCLV_2G              0xffffffff
 +
 +#define GAM_ECOCHK                    0x4090
 +#define   ECOCHK_SNB_BIT              (1<<10)
 +#define   ECOCHK_PPGTT_CACHE64B               (0x3<<3)
 +#define   ECOCHK_PPGTT_CACHE4B                (0x0<<3)
 +
  /* VGA stuff */
  
  #define VGA_ST01_MDA 0x3ba
  #define FENCE_REG_SANDYBRIDGE_0               0x100000
  #define   SANDYBRIDGE_FENCE_PITCH_SHIFT       32
  
 +/* control register for cpu gtt access */
 +#define TILECTL                               0x101000
 +#define   TILECTL_SWZCTL                      (1 << 0)
 +#define   TILECTL_TLB_PREFETCH_DIS    (1 << 2)
 +#define   TILECTL_BACKSNOOP_DIS               (1 << 3)
 +
  /*
   * Instruction and interrupt control regs
   */
  #define RING_MAX_IDLE(base)   ((base)+0x54)
  #define RING_HWS_PGA(base)    ((base)+0x80)
  #define RING_HWS_PGA_GEN6(base)       ((base)+0x2080)
 +#define ARB_MODE              0x04030
 +#define   ARB_MODE_SWIZZLE_SNB        (1<<4)
 +#define   ARB_MODE_SWIZZLE_IVB        (1<<5)
 +#define   ARB_MODE_ENABLE(x)  GFX_MODE_ENABLE(x)
 +#define   ARB_MODE_DISABLE(x) GFX_MODE_DISABLE(x)
  #define RENDER_HWS_PGA_GEN7   (0x04080)
 +#define RING_FAULT_REG(ring)  (0x4094 + 0x100*(ring)->id)
 +#define DONE_REG              0x40b0
  #define BSD_HWS_PGA_GEN7      (0x04180)
  #define BLT_HWS_PGA_GEN7      (0x04280)
  #define RING_ACTHD(base)      ((base)+0x74)
  #define IPEIR_I965    0x02064
  #define IPEHR_I965    0x02068
  #define INSTDONE_I965 0x0206c
 +#define RING_IPEIR(base)      ((base)+0x64)
 +#define RING_IPEHR(base)      ((base)+0x68)
 +#define RING_INSTDONE(base)   ((base)+0x6c)
 +#define RING_INSTPS(base)     ((base)+0x70)
 +#define RING_DMA_FADD(base)   ((base)+0x78)
 +#define RING_INSTPM(base)     ((base)+0xc0)
  #define INSTPS                0x02070 /* 965+ only */
  #define INSTDONE1     0x0207c /* 965+ only */
  #define ACTHD_I965    0x02074
  #define INSTDONE      0x02090
  #define NOPID         0x02094
  #define HWSTAM                0x02098
 -#define VCS_INSTDONE  0x1206C
 -#define VCS_IPEIR     0x12064
 -#define VCS_IPEHR     0x12068
 -#define VCS_ACTHD     0x12074
 -#define BCS_INSTDONE  0x2206C
 -#define BCS_IPEIR     0x22064
 -#define BCS_IPEHR     0x22068
 -#define BCS_ACTHD     0x22074
  
  #define ERROR_GEN6    0x040a0
  
  
  #define MI_MODE               0x0209c
  # define VS_TIMER_DISPATCH                            (1 << 6)
 -# define MI_FLUSH_ENABLE                              (1 << 11)
 +# define MI_FLUSH_ENABLE                              (1 << 12)
  
  #define GFX_MODE      0x02520
  #define GFX_MODE_GEN7 0x0229c
 +#define RING_MODE_GEN7(ring)  ((ring)->mmio_base+0x29c)
  #define   GFX_RUN_LIST_ENABLE         (1<<15)
  #define   GFX_TLB_INVALIDATE_ALWAYS   (1<<13)
  #define   GFX_SURFACE_FAULT_ENABLE    (1<<12)
  #define C0DRB3                        0x10206
  #define C1DRB3                        0x10606
  
 +/** snb MCH registers for reading the DRAM channel configuration */
 +#define MAD_DIMM_C0                   (MCHBAR_MIRROR_BASE_SNB + 0x5004)
 +#define MAD_DIMM_C1                   (MCHBAR_MIRROR_BASE_SNB + 0x5008)
 +#define MAD_DIMM_C2                   (MCHBAR_MIRROR_BASE_SNB + 0x500C)
 +#define   MAD_DIMM_ECC_MASK           (0x3 << 24)
 +#define   MAD_DIMM_ECC_OFF            (0x0 << 24)
 +#define   MAD_DIMM_ECC_IO_ON_LOGIC_OFF        (0x1 << 24)
 +#define   MAD_DIMM_ECC_IO_OFF_LOGIC_ON        (0x2 << 24)
 +#define   MAD_DIMM_ECC_ON             (0x3 << 24)
 +#define   MAD_DIMM_ENH_INTERLEAVE     (0x1 << 22)
 +#define   MAD_DIMM_RANK_INTERLEAVE    (0x1 << 21)
 +#define   MAD_DIMM_B_WIDTH_X16                (0x1 << 20) /* X8 chips if unset */
 +#define   MAD_DIMM_A_WIDTH_X16                (0x1 << 19) /* X8 chips if unset */
 +#define   MAD_DIMM_B_DUAL_RANK                (0x1 << 18)
 +#define   MAD_DIMM_A_DUAL_RANK                (0x1 << 17)
 +#define   MAD_DIMM_A_SELECT           (0x1 << 16)
 +/* DIMM sizes are in multiples of 256mb. */
 +#define   MAD_DIMM_B_SIZE_SHIFT               8
 +#define   MAD_DIMM_B_SIZE_MASK                (0xff << MAD_DIMM_B_SIZE_SHIFT)
 +#define   MAD_DIMM_A_SIZE_SHIFT               0
 +#define   MAD_DIMM_A_SIZE_MASK                (0xff << MAD_DIMM_A_SIZE_SHIFT)
 +
 +
  /* Clocking configuration register */
  #define CLKCFG                        0x10c00
  #define CLKCFG_FSB_400                                        (5 << 0)        /* hrawclk 100 */
  #define _VSYNC_A              0x60014
  #define _PIPEASRC     0x6001c
  #define _BCLRPAT_A    0x60020
 +#define _VSYNCSHIFT_A 0x60028
  
  /* Pipe B timing regs */
  #define _HTOTAL_B     0x61000
  #define _VSYNC_B              0x61014
  #define _PIPEBSRC     0x6101c
  #define _BCLRPAT_B    0x61020
 +#define _VSYNCSHIFT_B 0x61028
 +
  
  #define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B)
  #define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B)
  #define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B)
  #define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B)
  #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
 +#define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
  
  /* VGA port control */
  #define ADPA                  0x61100
  #define   PIPECONF_PALETTE    0
  #define   PIPECONF_GAMMA              (1<<24)
  #define   PIPECONF_FORCE_BORDER       (1<<25)
 -#define   PIPECONF_PROGRESSIVE        (0 << 21)
 -#define   PIPECONF_INTERLACE_W_FIELD_INDICATION       (6 << 21)
 -#define   PIPECONF_INTERLACE_FIELD_0_ONLY             (7 << 21)
  #define   PIPECONF_INTERLACE_MASK     (7 << 21)
 +/* Note that pre-gen3 does not support interlaced display directly. Panel
 + * fitting must be disabled on pre-ilk for interlaced. */
 +#define   PIPECONF_PROGRESSIVE                        (0 << 21)
 +#define   PIPECONF_INTERLACE_W_SYNC_SHIFT_PANEL       (4 << 21) /* gen4 only */
 +#define   PIPECONF_INTERLACE_W_SYNC_SHIFT     (5 << 21) /* gen4 only */
 +#define   PIPECONF_INTERLACE_W_FIELD_INDICATION       (6 << 21)
 +#define   PIPECONF_INTERLACE_FIELD_0_ONLY     (7 << 21) /* gen3 only */
 +/* Ironlake and later have a complete new set of values for interlaced. PFIT
 + * means panel fitter required, PF means progressive fetch, DBL means power
 + * saving pixel doubling. */
 +#define   PIPECONF_PFIT_PF_INTERLACED_ILK     (1 << 21)
 +#define   PIPECONF_INTERLACED_ILK             (3 << 21)
 +#define   PIPECONF_INTERLACED_DBL_ILK         (4 << 21) /* ilk/snb only */
 +#define   PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
  #define   PIPECONF_CXSR_DOWNCLOCK     (1<<16)
  #define   PIPECONF_BPP_MASK   (0x000000e0)
  #define   PIPECONF_BPP_8      (0<<5)
  #define  DISP_TILE_SURFACE_SWIZZLING  (1<<13)
  #define  DISP_FBC_WM_DIS              (1<<15)
  
+ /* GEN7 chicken */
+ #define GEN7_COMMON_SLICE_CHICKEN1            0x7010
+ # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC    ((1<<10) | (1<<26))
+ #define GEN7_L3CNTLREG1                               0xB01C
+ #define  GEN7_WA_FOR_GEN7_L3_CONTROL                  0x3C4FFF8C
+ #define GEN7_L3_CHICKEN_MODE_REGISTER         0xB030
+ #define  GEN7_WA_L3_CHICKEN_MODE                              0x20000000
+ /* WaCatErrorRejectionIssue */
+ #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG                0x9030
+ #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB     (1<<11)
  /* PCH */
  
  /* south display engine interrupt */
  #define _TRANS_VSYNC_A           0xe0014
  #define  TRANS_VSYNC_END_SHIFT  16
  #define  TRANS_VSYNC_START_SHIFT 0
 +#define _TRANS_VSYNCSHIFT_A   0xe0028
  
  #define _TRANSA_DATA_M1          0xe0030
  #define _TRANSA_DATA_N1          0xe0034
  #define _TRANS_VTOTAL_B          0xe100c
  #define _TRANS_VBLANK_B          0xe1010
  #define _TRANS_VSYNC_B           0xe1014
 +#define _TRANS_VSYNCSHIFT_B    0xe1028
  
  #define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B)
  #define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B)
  #define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B)
  #define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B)
  #define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B)
 +#define TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _TRANS_VSYNCSHIFT_A, \
 +                                   _TRANS_VSYNCSHIFT_B)
  
  #define _TRANSB_DATA_M1          0xe1030
  #define _TRANSB_DATA_N1          0xe1034
  #define  TRANS_FSYNC_DELAY_HB4  (3<<27)
  #define  TRANS_DP_AUDIO_ONLY    (1<<26)
  #define  TRANS_DP_VIDEO_AUDIO   (0<<26)
 +#define  TRANS_INTERLACE_MASK   (7<<21)
  #define  TRANS_PROGRESSIVE      (0<<21)
 +#define  TRANS_INTERLACED       (3<<21)
 +#define  TRANS_LEGACY_INTERLACED_ILK (2<<21)
  #define  TRANS_8BPC             (0<<5)
  #define  TRANS_10BPC            (1<<5)
  #define  TRANS_6BPC             (2<<5)
  #define  ECOBUS                                       0xa180
  #define    FORCEWAKE_MT_ENABLE                        (1<<5)
  
 +#define  GTFIFODBG                            0x120000
 +#define    GT_FIFO_CPU_ERROR_MASK             7
 +#define    GT_FIFO_OVFERR                     (1<<2)
 +#define    GT_FIFO_IAWRERR                    (1<<1)
 +#define    GT_FIFO_IARDERR                    (1<<0)
 +
  #define  GT_FIFO_FREE_ENTRIES                 0x120008
  #define    GT_FIFO_NUM_RESERVED_ENTRIES               20
  
  #define GEN6_UCGCTL2                          0x9404
+ # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE              (1 << 13)
  # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE             (1 << 12)
  # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE              (1 << 11)
  
   */
  #define GEN7_SO_WRITE_OFFSET(n)               (0x5280 + (n) * 4)
  
 +#define IBX_AUD_CONFIG_A                      0xe2000
 +#define CPT_AUD_CONFIG_A                      0xe5000
 +#define   AUD_CONFIG_N_VALUE_INDEX            (1 << 29)
 +#define   AUD_CONFIG_N_PROG_ENABLE            (1 << 28)
 +#define   AUD_CONFIG_UPPER_N_SHIFT            20
 +#define   AUD_CONFIG_UPPER_N_VALUE            (0xff << 20)
 +#define   AUD_CONFIG_LOWER_N_SHIFT            4
 +#define   AUD_CONFIG_LOWER_N_VALUE            (0xfff << 4)
 +#define   AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT   16
 +#define   AUD_CONFIG_PIXEL_CLOCK_HDMI         (0xf << 16)
 +#define   AUD_CONFIG_DISABLE_NCTS             (1 << 3)
 +
  #endif /* _I915_REG_H_ */
@@@ -75,7 -75,7 +75,7 @@@ struct intel_limit 
        intel_range_t   dot, vco, n, m, m1, m2, p, p1;
        intel_p2_t          p2;
        bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
 -                      int, int, intel_clock_t *);
 +                      int, int, intel_clock_t *, intel_clock_t *);
  };
  
  /* FDI */
  
  static bool
  intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                  int target, int refclk, intel_clock_t *best_clock);
 +                  int target, int refclk, intel_clock_t *match_clock,
 +                  intel_clock_t *best_clock);
  static bool
  intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                      int target, int refclk, intel_clock_t *best_clock);
 +                      int target, int refclk, intel_clock_t *match_clock,
 +                      intel_clock_t *best_clock);
  
  static bool
  intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
 -                    int target, int refclk, intel_clock_t *best_clock);
 +                    int target, int refclk, intel_clock_t *match_clock,
 +                    intel_clock_t *best_clock);
  static bool
  intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc,
 -                         int target, int refclk, intel_clock_t *best_clock);
 +                         int target, int refclk, intel_clock_t *match_clock,
 +                         intel_clock_t *best_clock);
  
  static inline u32 /* units of 100MHz */
  intel_fdi_link_freq(struct drm_device *dev)
@@@ -519,8 -515,7 +519,8 @@@ static bool intel_PLL_is_valid(struct d
  
  static bool
  intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                  int target, int refclk, intel_clock_t *best_clock)
 +                  int target, int refclk, intel_clock_t *match_clock,
 +                  intel_clock_t *best_clock)
  
  {
        struct drm_device *dev = crtc->dev;
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
 +                                      if (match_clock &&
 +                                          clock.p != match_clock->p)
 +                                              continue;
  
                                        this_err = abs(clock.dot - target);
                                        if (this_err < err) {
  
  static bool
  intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                      int target, int refclk, intel_clock_t *best_clock)
 +                      int target, int refclk, intel_clock_t *match_clock,
 +                      intel_clock_t *best_clock)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
 +                                      if (match_clock &&
 +                                          clock.p != match_clock->p)
 +                                              continue;
  
                                        this_err = abs(clock.dot - target);
                                        if (this_err < err_most) {
  
  static bool
  intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                         int target, int refclk, intel_clock_t *best_clock)
 +                         int target, int refclk, intel_clock_t *match_clock,
 +                         intel_clock_t *best_clock)
  {
        struct drm_device *dev = crtc->dev;
        intel_clock_t clock;
  /* DisplayPort has only two frequencies, 162MHz and 270MHz */
  static bool
  intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
 -                    int target, int refclk, intel_clock_t *best_clock)
 +                    int target, int refclk, intel_clock_t *match_clock,
 +                    intel_clock_t *best_clock)
  {
        intel_clock_t clock;
        if (target < 200000) {
@@@ -936,10 -922,6 +936,10 @@@ void assert_pipe(struct drm_i915_privat
        u32 val;
        bool cur_state;
  
 +      /* if we need the pipe A quirk it must be always on */
 +      if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
 +              state = true;
 +
        reg = PIPECONF(pipe);
        val = I915_READ(reg);
        cur_state = !!(val & PIPECONF_ENABLE);
             pipe_name(pipe), state_string(state), state_string(cur_state));
  }
  
 -static void assert_plane_enabled(struct drm_i915_private *dev_priv,
 -                               enum plane plane)
 +static void assert_plane(struct drm_i915_private *dev_priv,
 +                       enum plane plane, bool state)
  {
        int reg;
        u32 val;
 +      bool cur_state;
  
        reg = DSPCNTR(plane);
        val = I915_READ(reg);
 -      WARN(!(val & DISPLAY_PLANE_ENABLE),
 -           "plane %c assertion failure, should be active but is disabled\n",
 -           plane_name(plane));
 +      cur_state = !!(val & DISPLAY_PLANE_ENABLE);
 +      WARN(cur_state != state,
 +           "plane %c assertion failure (expected %s, current %s)\n",
 +           plane_name(plane), state_string(state), state_string(cur_state));
  }
  
 +#define assert_plane_enabled(d, p) assert_plane(d, p, true)
 +#define assert_plane_disabled(d, p) assert_plane(d, p, false)
 +
  static void assert_planes_disabled(struct drm_i915_private *dev_priv,
                                   enum pipe pipe)
  {
        int cur_pipe;
  
        /* Planes are fixed to pipes on ILK+ */
 -      if (HAS_PCH_SPLIT(dev_priv->dev))
 +      if (HAS_PCH_SPLIT(dev_priv->dev)) {
 +              reg = DSPCNTR(pipe);
 +              val = I915_READ(reg);
 +              WARN((val & DISPLAY_PLANE_ENABLE),
 +                   "plane %c assertion failure, should be disabled but not\n",
 +                   plane_name(pipe));
                return;
 +      }
  
        /* Need to check both planes against the pipe */
        for (i = 0; i < 2; i++) {
@@@ -1100,7 -1071,7 +1100,7 @@@ static void assert_pch_hdmi_disabled(st
  {
        u32 val = I915_READ(reg);
        WARN(hdmi_pipe_enabled(dev_priv, val, pipe),
 -           "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
 +           "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
  }
  
@@@ -1266,8 -1237,7 +1266,8 @@@ static void intel_enable_transcoder(str
                                    enum pipe pipe)
  {
        int reg;
 -      u32 val;
 +      u32 val, pipeconf_val;
 +      struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
  
        /* PCH only available on ILK+ */
        BUG_ON(dev_priv->info->gen < 5);
  
        reg = TRANSCONF(pipe);
        val = I915_READ(reg);
 +      pipeconf_val = I915_READ(PIPECONF(pipe));
  
        if (HAS_PCH_IBX(dev_priv->dev)) {
                /*
                 * that in pipeconf reg.
                 */
                val &= ~PIPE_BPC_MASK;
 -              val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
 +              val |= pipeconf_val & PIPE_BPC_MASK;
        }
 +
 +      val &= ~TRANS_INTERLACE_MASK;
 +      if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
 +              if (HAS_PCH_IBX(dev_priv->dev) &&
 +                  intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO))
 +                      val |= TRANS_LEGACY_INTERLACED_ILK;
 +              else
 +                      val |= TRANS_INTERLACED;
 +      else
 +              val |= TRANS_PROGRESSIVE;
 +
        I915_WRITE(reg, val | TRANS_ENABLE);
        if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
                DRM_ERROR("failed to enable transcoder %d\n", pipe);
@@@ -2054,8 -2012,6 +2054,8 @@@ intel_pin_and_fence_fb_obj(struct drm_d
                ret = i915_gem_object_get_fence(obj, pipelined);
                if (ret)
                        goto err_unpin;
 +
 +              i915_gem_object_pin_fence(obj);
        }
  
        dev_priv->mm.interruptible = true;
@@@ -2068,12 -2024,6 +2068,12 @@@ err_interruptible
        return ret;
  }
  
 +void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
 +{
 +      i915_gem_object_unpin_fence(obj);
 +      i915_gem_object_unpin(obj);
 +}
 +
  static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                             int x, int y)
  {
@@@ -2305,7 -2255,7 +2305,7 @@@ intel_pipe_set_base(struct drm_crtc *cr
        ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
                                         LEAVE_ATOMIC_MODE_SET);
        if (ret) {
 -              i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
 +              intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
                mutex_unlock(&dev->struct_mutex);
                DRM_ERROR("failed to update base address\n");
                return ret;
  
        if (old_fb) {
                intel_wait_for_vblank(dev, intel_crtc->pipe);
 -              i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj);
 +              intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
        }
  
        mutex_unlock(&dev->struct_mutex);
@@@ -2986,7 -2936,6 +2986,7 @@@ static void ironlake_pch_enable(struct 
        I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe)));
        I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));
        I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe)));
 +      I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));
  
        intel_fdi_normal_train(crtc);
  
@@@ -3372,12 -3321,10 +3372,12 @@@ static void intel_crtc_disable(struct d
        struct drm_device *dev = crtc->dev;
  
        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 +      assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
 +      assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
  
        if (crtc->fb) {
                mutex_lock(&dev->struct_mutex);
 -              i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
 +              intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
                mutex_unlock(&dev->struct_mutex);
        }
  }
@@@ -3451,8 -3398,11 +3451,8 @@@ static bool intel_crtc_mode_fixup(struc
                        return false;
        }
  
 -      /* XXX some encoders set the crtcinfo, others don't.
 -       * Obviously we need some form of conflict resolution here...
 -       */
 -      if (adjusted_mode->crtc_htotal == 0)
 -              drm_mode_set_crtcinfo(adjusted_mode, 0);
 +      /* All interlaced capable intel hw wants timings in frames. */
 +      drm_mode_set_crtcinfo(adjusted_mode, 0);
  
        return true;
  }
@@@ -4571,7 -4521,6 +4571,7 @@@ void sandybridge_update_wm(struct drm_d
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
 +      u32 val;
        int fbc_wm, plane_wm, cursor_wm;
        unsigned int enabled;
  
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
 -              I915_WRITE(WM0_PIPEA_ILK,
 -                         (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
 +              val = I915_READ(WM0_PIPEA_ILK);
 +              val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
 +              I915_WRITE(WM0_PIPEA_ILK, val |
 +                         ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
 -              I915_WRITE(WM0_PIPEB_ILK,
 -                         (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
 +              val = I915_READ(WM0_PIPEB_ILK);
 +              val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
 +              I915_WRITE(WM0_PIPEB_ILK, val |
 +                         ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
 -              I915_WRITE(WM0_PIPEC_IVB,
 -                         (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
 +              val = I915_READ(WM0_PIPEC_IVB);
 +              val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
 +              I915_WRITE(WM0_PIPEC_IVB, val |
 +                         ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
                DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
@@@ -4737,8 -4680,17 +4737,17 @@@ sandybridge_compute_sprite_srwm(struct 
  
        crtc = intel_get_crtc_for_plane(dev, plane);
        clock = crtc->mode.clock;
+       if (!clock) {
+               *sprite_wm = 0;
+               return false;
+       }
  
        line_time_us = (sprite_width * 1000) / clock;
+       if (!line_time_us) {
+               *sprite_wm = 0;
+               return false;
+       }
        line_count = (latency_ns / line_time_us + 1000) / 1000;
        line_size = sprite_width * pixel_size;
  
@@@ -4757,7 -4709,6 +4766,7 @@@ static void sandybridge_update_sprite_w
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
 +      u32 val;
        int sprite_wm, reg;
        int ret;
  
                return;
        }
  
 -      I915_WRITE(reg, I915_READ(reg) | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
 +      val = I915_READ(reg);
 +      val &= ~WM0_PIPE_SPRITE_MASK;
 +      I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
        DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm);
  
  
@@@ -5028,82 -4977,6 +5037,82 @@@ static bool intel_choose_pipe_bpp_dithe
        return display_bpc != bpc;
  }
  
 +static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      int refclk;
 +
 +      if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
 +          intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
 +              refclk = dev_priv->lvds_ssc_freq * 1000;
 +              DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
 +                            refclk / 1000);
 +      } else if (!IS_GEN2(dev)) {
 +              refclk = 96000;
 +      } else {
 +              refclk = 48000;
 +      }
 +
 +      return refclk;
 +}
 +
 +static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode,
 +                                    intel_clock_t *clock)
 +{
 +      /* SDVO TV has fixed PLL values depend on its clock range,
 +         this mirrors vbios setting. */
 +      if (adjusted_mode->clock >= 100000
 +          && adjusted_mode->clock < 140500) {
 +              clock->p1 = 2;
 +              clock->p2 = 10;
 +              clock->n = 3;
 +              clock->m1 = 16;
 +              clock->m2 = 8;
 +      } else if (adjusted_mode->clock >= 140500
 +                 && adjusted_mode->clock <= 200000) {
 +              clock->p1 = 1;
 +              clock->p2 = 10;
 +              clock->n = 6;
 +              clock->m1 = 12;
 +              clock->m2 = 8;
 +      }
 +}
 +
 +static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
 +                                   intel_clock_t *clock,
 +                                   intel_clock_t *reduced_clock)
 +{
 +      struct drm_device *dev = crtc->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      int pipe = intel_crtc->pipe;
 +      u32 fp, fp2 = 0;
 +
 +      if (IS_PINEVIEW(dev)) {
 +              fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2;
 +              if (reduced_clock)
 +                      fp2 = (1 << reduced_clock->n) << 16 |
 +                              reduced_clock->m1 << 8 | reduced_clock->m2;
 +      } else {
 +              fp = clock->n << 16 | clock->m1 << 8 | clock->m2;
 +              if (reduced_clock)
 +                      fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 |
 +                              reduced_clock->m2;
 +      }
 +
 +      I915_WRITE(FP0(pipe), fp);
 +
 +      intel_crtc->lowfreq_avail = false;
 +      if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
 +          reduced_clock && i915_powersave) {
 +              I915_WRITE(FP1(pipe), fp2);
 +              intel_crtc->lowfreq_avail = true;
 +      } else {
 +              I915_WRITE(FP1(pipe), fp);
 +      }
 +}
 +
  static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                              struct drm_display_mode *mode,
                              struct drm_display_mode *adjusted_mode,
        int plane = intel_crtc->plane;
        int refclk, num_connectors = 0;
        intel_clock_t clock, reduced_clock;
 -      u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
 +      u32 dpll, dspcntr, pipeconf, vsyncshift;
        bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
        bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
        struct drm_mode_config *mode_config = &dev->mode_config;
                num_connectors++;
        }
  
 -      if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
 -              refclk = dev_priv->lvds_ssc_freq * 1000;
 -              DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
 -                            refclk / 1000);
 -      } else if (!IS_GEN2(dev)) {
 -              refclk = 96000;
 -      } else {
 -              refclk = 48000;
 -      }
 +      refclk = i9xx_get_refclk(crtc, num_connectors);
  
        /*
         * Returns a set of divisors for the desired target clock with the given
         * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
         */
        limit = intel_limit(crtc, refclk);
 -      ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
 +      ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
 +                           &clock);
        if (!ok) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        intel_crtc_update_cursor(crtc, true);
  
        if (is_lvds && dev_priv->lvds_downclock_avail) {
 +              /*
 +               * Ensure we match the reduced clock's P to the target clock.
 +               * If the clocks don't match, we can't switch the display clock
 +               * by using the FP0/FP1. In such case we will disable the LVDS
 +               * downclock feature.
 +              */
                has_reduced_clock = limit->find_pll(limit, crtc,
                                                    dev_priv->lvds_downclock,
                                                    refclk,
 +                                                  &clock,
                                                    &reduced_clock);
 -              if (has_reduced_clock && (clock.p != reduced_clock.p)) {
 -                      /*
 -                       * If the different P is found, it means that we can't
 -                       * switch the display clock by using the FP0/FP1.
 -                       * In such case we will disable the LVDS downclock
 -                       * feature.
 -                       */
 -                      DRM_DEBUG_KMS("Different P is found for "
 -                                    "LVDS clock/downclock\n");
 -                      has_reduced_clock = 0;
 -              }
 -      }
 -      /* SDVO TV has fixed PLL values depend on its clock range,
 -         this mirrors vbios setting. */
 -      if (is_sdvo && is_tv) {
 -              if (adjusted_mode->clock >= 100000
 -                  && adjusted_mode->clock < 140500) {
 -                      clock.p1 = 2;
 -                      clock.p2 = 10;
 -                      clock.n = 3;
 -                      clock.m1 = 16;
 -                      clock.m2 = 8;
 -              } else if (adjusted_mode->clock >= 140500
 -                         && adjusted_mode->clock <= 200000) {
 -                      clock.p1 = 1;
 -                      clock.p2 = 10;
 -                      clock.n = 6;
 -                      clock.m1 = 12;
 -                      clock.m2 = 8;
 -              }
        }
  
 -      if (IS_PINEVIEW(dev)) {
 -              fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
 -              if (has_reduced_clock)
 -                      fp2 = (1 << reduced_clock.n) << 16 |
 -                              reduced_clock.m1 << 8 | reduced_clock.m2;
 -      } else {
 -              fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 -              if (has_reduced_clock)
 -                      fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
 -                              reduced_clock.m2;
 -      }
 +      if (is_sdvo && is_tv)
 +              i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
 +
 +      i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ?
 +                               &reduced_clock : NULL);
  
        dpll = DPLL_VGA_MODE_DIS;
  
        /* Set up the display plane register */
        dspcntr = DISPPLANE_GAMMA_ENABLE;
  
 -      /* Ironlake's plane is forced to pipe, bit 24 is to
 -         enable color space conversion */
        if (pipe == 0)
                dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
        else
        DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
        drm_mode_debug_printmodeline(mode);
  
 -      I915_WRITE(FP0(pipe), fp);
        I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
  
        POSTING_READ(DPLL(pipe));
                I915_WRITE(DPLL(pipe), dpll);
        }
  
 -      intel_crtc->lowfreq_avail = false;
 -      if (is_lvds && has_reduced_clock && i915_powersave) {
 -              I915_WRITE(FP1(pipe), fp2);
 -              intel_crtc->lowfreq_avail = true;
 -              if (HAS_PIPE_CXSR(dev)) {
 +      if (HAS_PIPE_CXSR(dev)) {
 +              if (intel_crtc->lowfreq_avail) {
                        DRM_DEBUG_KMS("enabling CxSR downclocking\n");
                        pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
 -              }
 -      } else {
 -              I915_WRITE(FP1(pipe), fp);
 -              if (HAS_PIPE_CXSR(dev)) {
 +              } else {
                        DRM_DEBUG_KMS("disabling CxSR downclocking\n");
                        pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
                }
        }
  
        pipeconf &= ~PIPECONF_INTERLACE_MASK;
 -      if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
 +      if (!IS_GEN2(dev) &&
 +          adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
                pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
                /* the chip adds 2 halflines automatically */
 -              adjusted_mode->crtc_vdisplay -= 1;
                adjusted_mode->crtc_vtotal -= 1;
 -              adjusted_mode->crtc_vblank_start -= 1;
                adjusted_mode->crtc_vblank_end -= 1;
 -              adjusted_mode->crtc_vsync_end -= 1;
 -              adjusted_mode->crtc_vsync_start -= 1;
 -      } else
 +              vsyncshift = adjusted_mode->crtc_hsync_start
 +                           - adjusted_mode->crtc_htotal/2;
 +      } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
 +              vsyncshift = 0;
 +      }
 +
 +      if (!IS_GEN3(dev))
 +              I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);
  
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
@@@ -5679,8 -5593,7 +5688,8 @@@ static int ironlake_crtc_mode_set(struc
         * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
         */
        limit = intel_limit(crtc, refclk);
 -      ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
 +      ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
 +                           &clock);
        if (!ok) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        intel_crtc_update_cursor(crtc, true);
  
        if (is_lvds && dev_priv->lvds_downclock_avail) {
 +              /*
 +               * Ensure we match the reduced clock's P to the target clock.
 +               * If the clocks don't match, we can't switch the display clock
 +               * by using the FP0/FP1. In such case we will disable the LVDS
 +               * downclock feature.
 +              */
                has_reduced_clock = limit->find_pll(limit, crtc,
                                                    dev_priv->lvds_downclock,
                                                    refclk,
 +                                                  &clock,
                                                    &reduced_clock);
 -              if (has_reduced_clock && (clock.p != reduced_clock.p)) {
 -                      /*
 -                       * If the different P is found, it means that we can't
 -                       * switch the display clock by using the FP0/FP1.
 -                       * In such case we will disable the LVDS downclock
 -                       * feature.
 -                       */
 -                      DRM_DEBUG_KMS("Different P is found for "
 -                                    "LVDS clock/downclock\n");
 -                      has_reduced_clock = 0;
 -              }
        }
        /* SDVO TV has fixed PLL values depend on its clock range,
           this mirrors vbios setting. */
  
        pipeconf &= ~PIPECONF_INTERLACE_MASK;
        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
 -              pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
 +              pipeconf |= PIPECONF_INTERLACED_ILK;
                /* the chip adds 2 halflines automatically */
 -              adjusted_mode->crtc_vdisplay -= 1;
                adjusted_mode->crtc_vtotal -= 1;
 -              adjusted_mode->crtc_vblank_start -= 1;
                adjusted_mode->crtc_vblank_end -= 1;
 -              adjusted_mode->crtc_vsync_end -= 1;
 -              adjusted_mode->crtc_vsync_start -= 1;
 -      } else
 +              I915_WRITE(VSYNCSHIFT(pipe),
 +                         adjusted_mode->crtc_hsync_start
 +                         - adjusted_mode->crtc_htotal/2);
 +      } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
 +              I915_WRITE(VSYNCSHIFT(pipe), 0);
 +      }
  
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
  
        intel_wait_for_vblank(dev, pipe);
  
 -      if (IS_GEN5(dev)) {
 -              /* enable address swizzle for tiling buffer */
 -              temp = I915_READ(DISP_ARB_CTL);
 -              I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
 -      }
 -
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
  
@@@ -6164,18 -6086,15 +6173,18 @@@ static void ironlake_write_eld(struct d
        uint32_t i;
        int len;
        int hdmiw_hdmiedid;
 +      int aud_config;
        int aud_cntl_st;
        int aud_cntrl_st2;
  
        if (HAS_PCH_IBX(connector->dev)) {
                hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
 +              aud_config = IBX_AUD_CONFIG_A;
                aud_cntl_st = IBX_AUD_CNTL_ST_A;
                aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
        } else {
                hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
 +              aud_config = CPT_AUD_CONFIG_A;
                aud_cntl_st = CPT_AUD_CNTL_ST_A;
                aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
        }
        i = to_intel_crtc(crtc)->pipe;
        hdmiw_hdmiedid += i * 0x100;
        aud_cntl_st += i * 0x100;
 +      aud_config += i * 0x100;
  
        DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
  
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
                DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
                eld[5] |= (1 << 2);     /* Conn_Type, 0x1 = DisplayPort */
 -      }
 +              I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
 +      } else
 +              I915_WRITE(aud_config, 0);
  
        if (intel_eld_uptodate(connector,
                               aud_cntrl_st2, eldv,
@@@ -6268,7 -6184,7 +6277,7 @@@ void intel_crtc_load_lut(struct drm_crt
        int i;
  
        /* The clocks have to be on to load the palette. */
-       if (!crtc->enabled)
+       if (!crtc->enabled || !intel_crtc->active)
                return;
  
        /* use legacy palette for Ironlake */
@@@ -6654,7 -6570,7 +6663,7 @@@ intel_framebuffer_create_for_mode(struc
        mode_cmd.height = mode->vdisplay;
        mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
                                                                bpp);
-       mode_cmd.pixel_format = 0;
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
  
        return intel_framebuffer_create(dev, &mode_cmd, obj);
  }
@@@ -7011,7 -6927,9 +7020,7 @@@ static void intel_increase_pllclock(str
        if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
                DRM_DEBUG_DRIVER("upclocking LVDS\n");
  
 -              /* Unlock panel regs */
 -              I915_WRITE(PP_CONTROL,
 -                         I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
 +              assert_panel_unlocked(dev_priv, pipe);
  
                dpll &= ~DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
                dpll = I915_READ(dpll_reg);
                if (dpll & DISPLAY_RATE_SELECT_FPA1)
                        DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
 -
 -              /* ...and lock them again */
 -              I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
        }
  
        /* Schedule downclock */
@@@ -7049,7 -6970,9 +7058,7 @@@ static void intel_decrease_pllclock(str
        if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
                DRM_DEBUG_DRIVER("downclocking LVDS\n");
  
 -              /* Unlock panel regs */
 -              I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
 -                         PANEL_UNLOCK_REGS);
 +              assert_panel_unlocked(dev_priv, pipe);
  
                dpll |= DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
                dpll = I915_READ(dpll_reg);
                if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
                        DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
 -
 -              /* ...and lock them again */
 -              I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
        }
  
  }
@@@ -7171,7 -7097,7 +7180,7 @@@ static void intel_unpin_work_fn(struct 
                container_of(__work, struct intel_unpin_work, work);
  
        mutex_lock(&work->dev->struct_mutex);
 -      i915_gem_object_unpin(work->old_fb_obj);
 +      intel_unpin_fb_obj(work->old_fb_obj);
        drm_gem_object_unreference(&work->pending_flip_obj->base);
        drm_gem_object_unreference(&work->old_fb_obj->base);
  
@@@ -7321,7 -7247,7 +7330,7 @@@ static int intel_gen2_queue_flip(struc
                 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
        OUT_RING(fb->pitches[0]);
        OUT_RING(obj->gtt_offset + offset);
 -      OUT_RING(MI_NOOP);
 +      OUT_RING(0); /* aux display base address, unused */
        ADVANCE_LP_RING();
  out:
        return ret;
@@@ -7755,9 -7681,10 +7764,9 @@@ static void intel_setup_outputs(struct 
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
        bool dpd_is_edp = false;
 -      bool has_lvds = false;
 +      bool has_lvds;
  
 -      if (IS_MOBILE(dev) && !IS_I830(dev))
 -              has_lvds = intel_lvds_init(dev);
 +      has_lvds = intel_lvds_init(dev);
        if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
                /* disable the panel fitter on everything but LVDS */
                I915_WRITE(PFIT_CONTROL, 0);
@@@ -7912,8 -7839,7 +7921,8 @@@ int intel_framebuffer_init(struct drm_d
        case DRM_FORMAT_VYUY:
                break;
        default:
 -              DRM_ERROR("unsupported pixel format\n");
 +              DRM_DEBUG_KMS("unsupported pixel format %u\n",
 +                              mode_cmd->pixel_format);
                return -EINVAL;
        }
  
@@@ -8235,7 -8161,6 +8244,7 @@@ void gen6_enable_rps(struct drm_i915_pr
        u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
        u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
        u32 pcu_mbox, rc6_mask = 0;
 +      u32 gtfifodbg;
        int cur_freq, min_freq, max_freq;
        int i;
  
         */
        I915_WRITE(GEN6_RC_STATE, 0);
        mutex_lock(&dev_priv->dev->struct_mutex);
 +
 +      /* Clear the DBG now so we don't confuse earlier errors */
 +      if ((gtfifodbg = I915_READ(GTFIFODBG))) {
 +              DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg);
 +              I915_WRITE(GTFIFODBG, gtfifodbg);
 +      }
 +
        gen6_gt_force_wake_get(dev_priv);
  
        /* disable the counters and set deterministic thresholds */
        I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
  
        if (intel_enable_rc6(dev_priv->dev))
-               rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
-                       GEN6_RC_CTL_RC6_ENABLE;
+               rc6_mask = GEN6_RC_CTL_RC6_ENABLE |
+                       ((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0);
  
        I915_WRITE(GEN6_RC_CONTROL,
                   rc6_mask |
@@@ -8554,12 -8472,32 +8563,32 @@@ static void ivybridge_init_clock_gating
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
  
+       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+        * This implements the WaDisableRCZUnitClockGating workaround.
+        */
+       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
        I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
  
        I915_WRITE(IVB_CHICKEN3,
                   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
                   CHICKEN3_DGMG_DONE_FIX_DISABLE);
  
+       /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
+       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
+                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+       /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
+       I915_WRITE(GEN7_L3CNTLREG1,
+                       GEN7_WA_FOR_GEN7_L3_CONTROL);
+       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
+                       GEN7_WA_L3_CHICKEN_MODE);
+       /* This is required by WaCatErrorRejectionIssue */
+       I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+                       I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+                       GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
        for_each_pipe(pipe) {
                I915_WRITE(DSPCNTR(pipe),
                           I915_READ(DSPCNTR(pipe)) |
@@@ -9098,9 -9036,6 +9127,9 @@@ void intel_modeset_init(struct drm_devi
        dev->mode_config.min_width = 0;
        dev->mode_config.min_height = 0;
  
 +      dev->mode_config.preferred_depth = 24;
 +      dev->mode_config.prefer_shadow = 1;
 +
        dev->mode_config.funcs = (void *)&intel_mode_funcs;
  
        intel_init_quirks(dev);
@@@ -52,6 -52,20 +52,6 @@@ static inline int ring_space(struct int
        return space;
  }
  
 -static u32 i915_gem_get_seqno(struct drm_device *dev)
 -{
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 -      u32 seqno;
 -
 -      seqno = dev_priv->next_seqno;
 -
 -      /* reserve 0 for non-seqno */
 -      if (++dev_priv->next_seqno == 0)
 -              dev_priv->next_seqno = 1;
 -
 -      return seqno;
 -}
 -
  static int
  render_ring_flush(struct intel_ring_buffer *ring,
                  u32   invalidate_domains,
@@@ -287,7 -301,7 +287,7 @@@ static int init_ring_common(struct inte
  
        I915_WRITE_CTL(ring,
                        ((ring->size - PAGE_SIZE) & RING_NR_PAGES)
-                       | RING_REPORT_64K | RING_VALID);
+                       | RING_VALID);
  
        /* If the head is still not zero, the ring is dead */
        if ((I915_READ_CTL(ring) & RING_VALID) == 0 ||
@@@ -385,6 -399,8 +385,6 @@@ static int init_render_ring(struct inte
  
        if (INTEL_INFO(dev)->gen > 3) {
                int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
 -              if (IS_GEN6(dev) || IS_GEN7(dev))
 -                      mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
                I915_WRITE(MI_MODE, mode);
                if (IS_GEN7(dev))
                        I915_WRITE(GFX_MODE_GEN7,
@@@ -451,7 -467,7 +451,7 @@@ gen6_add_request(struct intel_ring_buff
        mbox1_reg = ring->signal_mbox[0];
        mbox2_reg = ring->signal_mbox[1];
  
 -      *seqno = i915_gem_get_seqno(ring->dev);
 +      *seqno = i915_gem_next_request_seqno(ring);
  
        update_mboxes(ring, *seqno, mbox1_reg);
        update_mboxes(ring, *seqno, mbox2_reg);
@@@ -549,7 -565,8 +549,7 @@@ static in
  pc_render_add_request(struct intel_ring_buffer *ring,
                      u32 *result)
  {
 -      struct drm_device *dev = ring->dev;
 -      u32 seqno = i915_gem_get_seqno(dev);
 +      u32 seqno = i915_gem_next_request_seqno(ring);
        struct pipe_control *pc = ring->private;
        u32 scratch_addr = pc->gtt_offset + 128;
        int ret;
        PIPE_CONTROL_FLUSH(ring, scratch_addr);
        scratch_addr += 128;
        PIPE_CONTROL_FLUSH(ring, scratch_addr);
 +
        intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
                        PIPE_CONTROL_WRITE_FLUSH |
                        PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
@@@ -601,7 -617,8 +601,7 @@@ static in
  render_ring_add_request(struct intel_ring_buffer *ring,
                        u32 *result)
  {
 -      struct drm_device *dev = ring->dev;
 -      u32 seqno = i915_gem_get_seqno(dev);
 +      u32 seqno = i915_gem_next_request_seqno(ring);
        int ret;
  
        ret = intel_ring_begin(ring, 4);
@@@ -727,13 -744,13 +727,13 @@@ void intel_ring_setup_status_page(struc
         */
        if (IS_GEN7(dev)) {
                switch (ring->id) {
 -              case RING_RENDER:
 +              case RCS:
                        mmio = RENDER_HWS_PGA_GEN7;
                        break;
 -              case RING_BLT:
 +              case BCS:
                        mmio = BLT_HWS_PGA_GEN7;
                        break;
 -              case RING_BSD:
 +              case VCS:
                        mmio = BSD_HWS_PGA_GEN7;
                        break;
                }
@@@ -775,7 -792,7 +775,7 @@@ ring_add_request(struct intel_ring_buff
        if (ret)
                return ret;
  
 -      seqno = i915_gem_get_seqno(ring->dev);
 +      seqno = i915_gem_next_request_seqno(ring);
  
        intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
        intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
@@@ -799,7 -816,8 +799,7 @@@ gen6_ring_get_irq(struct intel_ring_buf
        /* It looks like we need to prevent the gt from suspending while waiting
         * for an notifiy irq, otherwise irqs seem to get lost on at least the
         * blt/bsd rings on ivb. */
 -      if (IS_GEN7(dev))
 -              gen6_gt_force_wake_get(dev_priv);
 +      gen6_gt_force_wake_get(dev_priv);
  
        spin_lock(&ring->irq_lock);
        if (ring->irq_refcount++ == 0) {
@@@ -826,7 -844,8 +826,7 @@@ gen6_ring_put_irq(struct intel_ring_buf
        }
        spin_unlock(&ring->irq_lock);
  
 -      if (IS_GEN7(dev))
 -              gen6_gt_force_wake_put(dev_priv);
 +      gen6_gt_force_wake_put(dev_priv);
  }
  
  static bool
@@@ -1108,105 -1127,11 +1108,93 @@@ static int intel_wrap_ring_buffer(struc
        return 0;
  }
  
 +static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
 +{
 +      struct drm_i915_private *dev_priv = ring->dev->dev_private;
 +      bool was_interruptible;
 +      int ret;
 +
 +      /* XXX As we have not yet audited all the paths to check that
 +       * they are ready for ERESTARTSYS from intel_ring_begin, do not
 +       * allow us to be interruptible by a signal.
 +       */
 +      was_interruptible = dev_priv->mm.interruptible;
 +      dev_priv->mm.interruptible = false;
 +
 +      ret = i915_wait_request(ring, seqno, true);
 +
 +      dev_priv->mm.interruptible = was_interruptible;
 +
 +      return ret;
 +}
 +
 +static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
 +{
 +      struct drm_i915_gem_request *request;
 +      u32 seqno = 0;
 +      int ret;
 +
 +      i915_gem_retire_requests_ring(ring);
 +
 +      if (ring->last_retired_head != -1) {
 +              ring->head = ring->last_retired_head;
 +              ring->last_retired_head = -1;
 +              ring->space = ring_space(ring);
 +              if (ring->space >= n)
 +                      return 0;
 +      }
 +
 +      list_for_each_entry(request, &ring->request_list, list) {
 +              int space;
 +
 +              if (request->tail == -1)
 +                      continue;
 +
 +              space = request->tail - (ring->tail + 8);
 +              if (space < 0)
 +                      space += ring->size;
 +              if (space >= n) {
 +                      seqno = request->seqno;
 +                      break;
 +              }
 +
 +              /* Consume this request in case we need more space than
 +               * is available and so need to prevent a race between
 +               * updating last_retired_head and direct reads of
 +               * I915_RING_HEAD. It also provides a nice sanity check.
 +               */
 +              request->tail = -1;
 +      }
 +
 +      if (seqno == 0)
 +              return -ENOSPC;
 +
 +      ret = intel_ring_wait_seqno(ring, seqno);
 +      if (ret)
 +              return ret;
 +
 +      if (WARN_ON(ring->last_retired_head == -1))
 +              return -ENOSPC;
 +
 +      ring->head = ring->last_retired_head;
 +      ring->last_retired_head = -1;
 +      ring->space = ring_space(ring);
 +      if (WARN_ON(ring->space < n))
 +              return -ENOSPC;
 +
 +      return 0;
 +}
 +
  int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
  {
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long end;
-       u32 head;
-       /* If the reported head position has wrapped or hasn't advanced,
-        * fallback to the slow and accurate path.
-        */
-       head = intel_read_status_page(ring, 4);
-       if (head > ring->head) {
-               ring->head = head;
-               ring->space = ring_space(ring);
-               if (ring->space >= n)
-                       return 0;
-       }
 +      int ret;
 +
 +      ret = intel_ring_wait_request(ring, n);
 +      if (ret != -ENOSPC)
 +              return ret;
  
        trace_i915_ring_wait_begin(ring);
        if (drm_core_check_feature(dev, DRIVER_GEM))
@@@ -1275,7 -1200,7 +1263,7 @@@ void intel_ring_advance(struct intel_ri
  
  static const struct intel_ring_buffer render_ring = {
        .name                   = "render ring",
 -      .id                     = RING_RENDER,
 +      .id                     = RCS,
        .mmio_base              = RENDER_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
        .init                   = init_render_ring,
  
  static const struct intel_ring_buffer bsd_ring = {
        .name                   = "bsd ring",
 -      .id                     = RING_BSD,
 +      .id                     = VCS,
        .mmio_base              = BSD_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
        .init                   = init_ring_common,
@@@ -1408,7 -1333,7 +1396,7 @@@ gen6_bsd_ring_put_irq(struct intel_ring
  /* ring buffer for Video Codec for Gen6+ */
  static const struct intel_ring_buffer gen6_bsd_ring = {
        .name                   = "gen6 bsd ring",
 -      .id                     = RING_BSD,
 +      .id                     = VCS,
        .mmio_base              = GEN6_BSD_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
        .init                   = init_ring_common,
@@@ -1444,13 -1369,79 +1432,13 @@@ blt_ring_put_irq(struct intel_ring_buff
                          GEN6_BLITTER_USER_INTERRUPT);
  }
  
 -
 -/* Workaround for some stepping of SNB,
 - * each time when BLT engine ring tail moved,
 - * the first command in the ring to be parsed
 - * should be MI_BATCH_BUFFER_START
 - */
 -#define NEED_BLT_WORKAROUND(dev) \
 -      (IS_GEN6(dev) && (dev->pdev->revision < 8))
 -
 -static inline struct drm_i915_gem_object *
 -to_blt_workaround(struct intel_ring_buffer *ring)
 -{
 -      return ring->private;
 -}
 -
 -static int blt_ring_init(struct intel_ring_buffer *ring)
 -{
 -      if (NEED_BLT_WORKAROUND(ring->dev)) {
 -              struct drm_i915_gem_object *obj;
 -              u32 *ptr;
 -              int ret;
 -
 -              obj = i915_gem_alloc_object(ring->dev, 4096);
 -              if (obj == NULL)
 -                      return -ENOMEM;
 -
 -              ret = i915_gem_object_pin(obj, 4096, true);
 -              if (ret) {
 -                      drm_gem_object_unreference(&obj->base);
 -                      return ret;
 -              }
 -
 -              ptr = kmap(obj->pages[0]);
 -              *ptr++ = MI_BATCH_BUFFER_END;
 -              *ptr++ = MI_NOOP;
 -              kunmap(obj->pages[0]);
 -
 -              ret = i915_gem_object_set_to_gtt_domain(obj, false);
 -              if (ret) {
 -                      i915_gem_object_unpin(obj);
 -                      drm_gem_object_unreference(&obj->base);
 -                      return ret;
 -              }
 -
 -              ring->private = obj;
 -      }
 -
 -      return init_ring_common(ring);
 -}
 -
 -static int blt_ring_begin(struct intel_ring_buffer *ring,
 -                        int num_dwords)
 -{
 -      if (ring->private) {
 -              int ret = intel_ring_begin(ring, num_dwords+2);
 -              if (ret)
 -                      return ret;
 -
 -              intel_ring_emit(ring, MI_BATCH_BUFFER_START);
 -              intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset);
 -
 -              return 0;
 -      } else
 -              return intel_ring_begin(ring, 4);
 -}
 -
  static int blt_ring_flush(struct intel_ring_buffer *ring,
                          u32 invalidate, u32 flush)
  {
        uint32_t cmd;
        int ret;
  
 -      ret = blt_ring_begin(ring, 4);
 +      ret = intel_ring_begin(ring, 4);
        if (ret)
                return ret;
  
        return 0;
  }
  
 -static void blt_ring_cleanup(struct intel_ring_buffer *ring)
 -{
 -      if (!ring->private)
 -              return;
 -
 -      i915_gem_object_unpin(ring->private);
 -      drm_gem_object_unreference(ring->private);
 -      ring->private = NULL;
 -}
 -
  static const struct intel_ring_buffer gen6_blt_ring = {
        .name                   = "blt ring",
 -      .id                     = RING_BLT,
 +      .id                     = BCS,
        .mmio_base              = BLT_RING_BASE,
        .size                   = 32 * PAGE_SIZE,
 -      .init                   = blt_ring_init,
 +      .init                   = init_ring_common,
        .write_tail             = ring_write_tail,
        .flush                  = blt_ring_flush,
        .add_request            = gen6_add_request,
        .irq_get                = blt_ring_get_irq,
        .irq_put                = blt_ring_put_irq,
        .dispatch_execbuffer    = gen6_ring_dispatch_execbuffer,
 -      .cleanup                = blt_ring_cleanup,
        .sync_to                = gen6_blt_ring_sync_to,
        .semaphore_register     = {MI_SEMAPHORE_SYNC_BR,
                                   MI_SEMAPHORE_SYNC_BV,
@@@ -43,37 -43,6 +43,37 @@@ void evergreen_pcie_gen2_enable(struct 
  extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev,
                                     int ring, u32 cp_int_cntl);
  
 +void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
 +                           unsigned *bankh, unsigned *mtaspect,
 +                           unsigned *tile_split)
 +{
 +      *bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK;
 +      *bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK;
 +      *mtaspect = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
 +      *tile_split = (tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK;
 +      switch (*bankw) {
 +      default:
 +      case 1: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_1; break;
 +      case 2: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_2; break;
 +      case 4: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_4; break;
 +      case 8: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_8; break;
 +      }
 +      switch (*bankh) {
 +      default:
 +      case 1: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_1; break;
 +      case 2: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_2; break;
 +      case 4: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_4; break;
 +      case 8: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_8; break;
 +      }
 +      switch (*mtaspect) {
 +      default:
 +      case 1: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1; break;
 +      case 2: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2; break;
 +      case 4: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4; break;
 +      case 8: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8; break;
 +      }
 +}
 +
  void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
  {
        u16 ctl, v;
        }
  }
  
 +void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
 +{
 +      struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
 +      int i;
 +
 +      if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) {
 +              for (i = 0; i < rdev->usec_timeout; i++) {
 +                      if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK))
 +                              break;
 +                      udelay(1);
 +              }
 +              for (i = 0; i < rdev->usec_timeout; i++) {
 +                      if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)
 +                              break;
 +                      udelay(1);
 +              }
 +      }
 +}
 +
  void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc)
  {
        /* enable the pflip int */
@@@ -1539,7 -1489,7 +1539,7 @@@ int evergreen_cp_resume(struct radeon_d
  
        evergreen_cp_start(rdev);
        ring->ready = true;
 -      r = radeon_ring_test(rdev, ring);
 +      r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring);
        if (r) {
                ring->ready = false;
                return r;
@@@ -3197,7 -3147,7 +3197,7 @@@ static int evergreen_startup(struct rad
        r = evergreen_blit_init(rdev);
        if (r) {
                r600_blit_fini(rdev);
 -              rdev->asic->copy = NULL;
 +              rdev->asic->copy.copy = NULL;
                dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
        }
  
        if (r)
                return r;
  
 -      r = r600_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                DRM_ERROR("radeon: failed testing IB (%d).\n", r);
                rdev->accel_working = false;
@@@ -3273,6 -3223,7 +3273,7 @@@ int evergreen_resume(struct radeon_devi
        r = evergreen_startup(rdev);
        if (r) {
                DRM_ERROR("evergreen startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }
  
@@@ -1318,7 -1318,7 +1318,7 @@@ int cayman_cp_resume(struct radeon_devi
        rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
        rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
        /* this only test cp0 */
 -      r = radeon_ring_test(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
 +      r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
                rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
@@@ -1466,7 -1466,7 +1466,7 @@@ static int cayman_startup(struct radeon
        r = evergreen_blit_init(rdev);
        if (r) {
                r600_blit_fini(rdev);
 -              rdev->asic->copy = NULL;
 +              rdev->asic->copy.copy = NULL;
                dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
        }
  
        if (r)
                return r;
  
 -      r = r600_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                DRM_ERROR("radeon: failed testing IB (%d).\n", r);
                rdev->accel_working = false;
@@@ -1547,6 -1547,7 +1547,7 @@@ int cayman_resume(struct radeon_device 
        r = cayman_startup(rdev);
        if (r) {
                DRM_ERROR("cayman startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }
        return r;
@@@ -65,40 -65,6 +65,40 @@@ MODULE_FIRMWARE(FIRMWARE_R520)
  
  #include "r100_track.h"
  
 +void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
 +{
 +      struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
 +      int i;
 +
 +      if (radeon_crtc->crtc_id == 0) {
 +              if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) {
 +                      for (i = 0; i < rdev->usec_timeout; i++) {
 +                              if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR))
 +                                      break;
 +                              udelay(1);
 +                      }
 +                      for (i = 0; i < rdev->usec_timeout; i++) {
 +                              if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)
 +                                      break;
 +                              udelay(1);
 +                      }
 +              }
 +      } else {
 +              if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) {
 +                      for (i = 0; i < rdev->usec_timeout; i++) {
 +                              if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR))
 +                                      break;
 +                              udelay(1);
 +                      }
 +                      for (i = 0; i < rdev->usec_timeout; i++) {
 +                              if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)
 +                                      break;
 +                              udelay(1);
 +                      }
 +              }
 +      }
 +}
 +
  /* This files gather functions specifics to:
   * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
   */
@@@ -121,27 -87,23 +121,27 @@@ int r100_reloc_pitch_offset(struct rade
                r100_cs_dump_packet(p, pkt);
                return r;
        }
 +
        value = radeon_get_ib_value(p, idx);
        tmp = value & 0x003fffff;
        tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
  
 -      if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 -              tile_flags |= RADEON_DST_TILE_MACRO;
 -      if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
 -              if (reg == RADEON_SRC_PITCH_OFFSET) {
 -                      DRM_ERROR("Cannot src blit from microtiled surface\n");
 -                      r100_cs_dump_packet(p, pkt);
 -                      return -EINVAL;
 +      if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
 +              if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 +                      tile_flags |= RADEON_DST_TILE_MACRO;
 +              if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
 +                      if (reg == RADEON_SRC_PITCH_OFFSET) {
 +                              DRM_ERROR("Cannot src blit from microtiled surface\n");
 +                              r100_cs_dump_packet(p, pkt);
 +                              return -EINVAL;
 +                      }
 +                      tile_flags |= RADEON_DST_TILE_MICRO;
                }
 -              tile_flags |= RADEON_DST_TILE_MICRO;
 -      }
  
 -      tmp |= tile_flags;
 -      p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
 +              tmp |= tile_flags;
 +              p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
 +      } else
 +              p->ib->ptr[idx] = (value & 0xffc00000) | tmp;
        return 0;
  }
  
@@@ -450,7 -412,7 +450,7 @@@ void r100_pm_misc(struct radeon_device 
        /* set pcie lanes */
        if ((rdev->flags & RADEON_IS_PCIE) &&
            !(rdev->flags & RADEON_IS_IGP) &&
 -          rdev->asic->set_pcie_lanes &&
 +          rdev->asic->pm.set_pcie_lanes &&
            (ps->pcie_lanes !=
             rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
                radeon_set_pcie_lanes(rdev,
@@@ -630,8 -592,8 +630,8 @@@ int r100_pci_gart_init(struct radeon_de
        if (r)
                return r;
        rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
 -      rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
 -      rdev->asic->gart_set_page = &r100_pci_gart_set_page;
 +      rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush;
 +      rdev->asic->gart.set_page = &r100_pci_gart_set_page;
        return radeon_gart_table_ram_alloc(rdev);
  }
  
@@@ -827,9 -789,7 +827,7 @@@ int r100_irq_process(struct radeon_devi
                        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);
+                       WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
                        break;
                }
        }
@@@ -970,8 -930,9 +968,8 @@@ static int r100_cp_wait_for_idle(struc
        return -1;
  }
  
 -void r100_ring_start(struct radeon_device *rdev)
 +void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring)
  {
 -      struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        int r;
  
        r = radeon_ring_lock(rdev, ring, 2);
@@@ -1182,8 -1143,8 +1180,8 @@@ int r100_cp_init(struct radeon_device *
        WREG32(RADEON_CP_RB_WPTR_DELAY, 0);
        WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D);
        WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM);
 -      radeon_ring_start(rdev);
 -      r = radeon_ring_test(rdev, ring);
 +      radeon_ring_start(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
 +      r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring);
        if (r) {
                DRM_ERROR("radeon: cp isn't working (%d).\n", r);
                return r;
@@@ -1591,17 -1552,7 +1589,17 @@@ static int r100_packet0_check(struct ra
                        r100_cs_dump_packet(p, pkt);
                        return r;
                }
 -              ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 +              if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
 +                      if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 +                              tile_flags |= RADEON_TXO_MACRO_TILE;
 +                      if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
 +                              tile_flags |= RADEON_TXO_MICRO_TILE_X2;
 +
 +                      tmp = idx_value & ~(0x7 << 2);
 +                      tmp |= tile_flags;
 +                      ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset);
 +              } else
 +                      ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
                track->textures[i].robj = reloc->robj;
                track->tex_dirty = true;
                break;
                        r100_cs_dump_packet(p, pkt);
                        return r;
                }
 +              if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
 +                      if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 +                              tile_flags |= RADEON_COLOR_TILE_ENABLE;
 +                      if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
 +                              tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
  
 -              if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 -                      tile_flags |= RADEON_COLOR_TILE_ENABLE;
 -              if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
 -                      tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
 -
 -              tmp = idx_value & ~(0x7 << 16);
 -              tmp |= tile_flags;
 -              ib[idx] = tmp;
 +                      tmp = idx_value & ~(0x7 << 16);
 +                      tmp |= tile_flags;
 +                      ib[idx] = tmp;
 +              } else
 +                      ib[idx] = idx_value;
  
                track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
                track->cb_dirty = true;
@@@ -3742,7 -3691,7 +3740,7 @@@ void r100_ring_ib_execute(struct radeon
        radeon_ring_write(ring, ib->length_dw);
  }
  
 -int r100_ib_test(struct radeon_device *rdev)
 +int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
  {
        struct radeon_ib *ib;
        uint32_t scratch;
@@@ -3967,7 -3916,7 +3965,7 @@@ static int r100_startup(struct radeon_d
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int r100_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCI)
                r100_pci_gart_disable(rdev);
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return r100_startup(rdev);
+       r = r100_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int r100_suspend(struct radeon_device *rdev)
@@@ -105,8 -105,8 +105,8 @@@ int rv370_pcie_gart_init(struct radeon_
        if (r)
                DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
        rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
 -      rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
 -      rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
 +      rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush;
 +      rdev->asic->gart.set_page = &rv370_pcie_gart_set_page;
        return radeon_gart_table_vram_alloc(rdev);
  }
  
@@@ -206,8 -206,9 +206,8 @@@ void r300_fence_ring_emit(struct radeon
        radeon_ring_write(ring, RADEON_SW_INT_FIRE);
  }
  
 -void r300_ring_start(struct radeon_device *rdev)
 +void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring)
  {
 -      struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        unsigned gb_tile_config;
        int r;
  
@@@ -1418,7 -1419,7 +1418,7 @@@ static int r300_startup(struct radeon_d
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int r300_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return r300_startup(rdev);
+       r = r300_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int r300_suspend(struct radeon_device *rdev)
@@@ -279,7 -279,7 +279,7 @@@ static int r420_startup(struct radeon_d
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int r420_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return r420_startup(rdev);
+       r = r420_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int r420_suspend(struct radeon_device *rdev)
@@@ -33,7 -33,7 +33,7 @@@
  
  /* This files gather functions specifics to: r520,rv530,rv560,rv570,r580 */
  
 -static int r520_mc_wait_for_idle(struct radeon_device *rdev)
 +int r520_mc_wait_for_idle(struct radeon_device *rdev)
  {
        unsigned i;
        uint32_t tmp;
@@@ -207,7 -207,7 +207,7 @@@ static int r520_startup(struct radeon_d
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int r520_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return r520_startup(rdev);
+       r = r520_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int r520_init(struct radeon_device *rdev)
@@@ -2226,7 -2226,7 +2226,7 @@@ int r600_cp_resume(struct radeon_devic
  
        r600_cp_start(rdev);
        ring->ready = true;
 -      r = radeon_ring_test(rdev, ring);
 +      r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring);
        if (r) {
                ring->ready = false;
                return r;
@@@ -2362,6 -2362,9 +2362,9 @@@ void r600_semaphore_ring_emit(struct ra
        uint64_t addr = semaphore->gpu_addr;
        unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL;
  
+       if (rdev->family < CHIP_CAYMAN)
+               sel |= PACKET3_SEM_WAIT_ON_SIGNAL;
        radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1));
        radeon_ring_write(ring, addr & 0xffffffff);
        radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel);
@@@ -2449,7 -2452,7 +2452,7 @@@ int r600_startup(struct radeon_device *
        r = r600_blit_init(rdev);
        if (r) {
                r600_blit_fini(rdev);
 -              rdev->asic->copy = NULL;
 +              rdev->asic->copy.copy = NULL;
                dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
        }
  
        if (r)
                return r;
  
 -      r = r600_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                DRM_ERROR("radeon: failed testing IB (%d).\n", r);
                rdev->accel_working = false;
@@@ -2529,6 -2532,7 +2532,7 @@@ int r600_resume(struct radeon_device *r
        r = r600_startup(rdev);
        if (r) {
                DRM_ERROR("r600 startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }
  
@@@ -2697,14 -2701,13 +2701,14 @@@ void r600_ring_ib_execute(struct radeon
        radeon_ring_write(ring, ib->length_dw);
  }
  
 -int r600_ib_test(struct radeon_device *rdev, int ring)
 +int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
  {
        struct radeon_ib *ib;
        uint32_t scratch;
        uint32_t tmp = 0;
        unsigned i;
        int r;
 +      int ring_index = radeon_ring_index(rdev, ring);
  
        r = radeon_scratch_get(rdev, &scratch);
        if (r) {
                return r;
        }
        WREG32(scratch, 0xCAFEDEAD);
 -      r = radeon_ib_get(rdev, ring, &ib, 256);
 +      r = radeon_ib_get(rdev, ring_index, &ib, 256);
        if (r) {
                DRM_ERROR("radeon: failed to get ib (%d).\n", r);
                return r;
        ib->ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1);
        ib->ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
        ib->ptr[2] = 0xDEADBEEF;
 -      ib->ptr[3] = PACKET2(0);
 -      ib->ptr[4] = PACKET2(0);
 -      ib->ptr[5] = PACKET2(0);
 -      ib->ptr[6] = PACKET2(0);
 -      ib->ptr[7] = PACKET2(0);
 -      ib->ptr[8] = PACKET2(0);
 -      ib->ptr[9] = PACKET2(0);
 -      ib->ptr[10] = PACKET2(0);
 -      ib->ptr[11] = PACKET2(0);
 -      ib->ptr[12] = PACKET2(0);
 -      ib->ptr[13] = PACKET2(0);
 -      ib->ptr[14] = PACKET2(0);
 -      ib->ptr[15] = PACKET2(0);
 -      ib->length_dw = 16;
 +      ib->length_dw = 3;
        r = radeon_ib_schedule(rdev, ib);
        if (r) {
                radeon_scratch_free(rdev, scratch);
@@@ -55,17 -55,12 +55,17 @@@ struct r600_cs_track 
        struct radeon_bo        *cb_color_frag_bo[8];
        struct radeon_bo        *cb_color_tile_bo[8];
        u32                     cb_color_info[8];
 +      u32                     cb_color_view[8];
        u32                     cb_color_size_idx[8];
        u32                     cb_target_mask;
        u32                     cb_shader_mask;
        u32                     cb_color_size[8];
        u32                     vgt_strmout_en;
        u32                     vgt_strmout_buffer_en;
 +      struct radeon_bo        *vgt_strmout_bo[4];
 +      u64                     vgt_strmout_bo_mc[4];
 +      u32                     vgt_strmout_bo_offset[4];
 +      u32                     vgt_strmout_size[4];
        u32                     db_depth_control;
        u32                     db_depth_info;
        u32                     db_depth_size_idx;
@@@ -78,9 -73,9 +78,9 @@@
  
  #define FMT_8_BIT(fmt, vc)   [fmt] = { 1, 1, 1, vc, CHIP_R600 }
  #define FMT_16_BIT(fmt, vc)  [fmt] = { 1, 1, 2, vc, CHIP_R600 }
 -#define FMT_24_BIT(fmt)      [fmt] = { 1, 1, 3,  0, CHIP_R600 }
 +#define FMT_24_BIT(fmt)      [fmt] = { 1, 1, 4,  0, CHIP_R600 }
  #define FMT_32_BIT(fmt, vc)  [fmt] = { 1, 1, 4, vc, CHIP_R600 }
 -#define FMT_48_BIT(fmt)      [fmt] = { 1, 1, 6,  0, CHIP_R600 }
 +#define FMT_48_BIT(fmt)      [fmt] = { 1, 1, 8,  0, CHIP_R600 }
  #define FMT_64_BIT(fmt, vc)  [fmt] = { 1, 1, 8, vc, CHIP_R600 }
  #define FMT_96_BIT(fmt)      [fmt] = { 1, 1, 12, 0, CHIP_R600 }
  #define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 }
@@@ -112,7 -107,7 +112,7 @@@ static const struct gpu_formats color_f
  
        /* 24-bit */
        FMT_24_BIT(V_038004_FMT_8_8_8),
 -                                             
 +
        /* 32-bit */
        FMT_32_BIT(V_038004_COLOR_32, 1),
        FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1),
        [V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
  };
  
 -static bool fmt_is_valid_color(u32 format)
 +bool r600_fmt_is_valid_color(u32 format)
  {
        if (format >= ARRAY_SIZE(color_formats_table))
                return false;
 -      
 +
        if (color_formats_table[format].valid_color)
                return true;
  
        return false;
  }
  
 -static bool fmt_is_valid_texture(u32 format, enum radeon_family family)
 +bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family)
  {
        if (format >= ARRAY_SIZE(color_formats_table))
                return false;
 -      
 +
        if (family < color_formats_table[format].min_family)
                return false;
  
        return false;
  }
  
 -static int fmt_get_blocksize(u32 format)
 +int r600_fmt_get_blocksize(u32 format)
  {
        if (format >= ARRAY_SIZE(color_formats_table))
                return 0;
        return color_formats_table[format].blocksize;
  }
  
 -static int fmt_get_nblocksx(u32 format, u32 w)
 +int r600_fmt_get_nblocksx(u32 format, u32 w)
  {
        unsigned bw;
  
        return (w + bw - 1) / bw;
  }
  
 -static int fmt_get_nblocksy(u32 format, u32 h)
 +int r600_fmt_get_nblocksy(u32 format, u32 h)
  {
        unsigned bh;
  
@@@ -261,7 -256,7 +261,7 @@@ static int r600_get_array_mode_alignmen
                break;
        case ARRAY_LINEAR_ALIGNED:
                *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize));
 -              *height_align = tile_height;
 +              *height_align = 1;
                *depth_align = 1;
                *base_align = values->group_size;
                break;
                *base_align = values->group_size;
                break;
        case ARRAY_2D_TILED_THIN1:
 -              *pitch_align = max((u32)macro_tile_width,
 -                                (u32)(((values->group_size / tile_height) /
 -                                       (values->blocksize * values->nsamples)) *
 -                                      values->nbanks)) * tile_width;
 +              *pitch_align = max((u32)macro_tile_width * tile_width,
 +                              (u32)((values->group_size * values->nbanks) /
 +                              (values->blocksize * values->nsamples * tile_width)));
                *height_align = macro_tile_height * tile_height;
                *depth_align = 1;
                *base_align = max(macro_tile_bytes,
@@@ -300,7 -296,6 +300,7 @@@ static void r600_cs_track_init(struct r
                track->cb_color_size[i] = 0;
                track->cb_color_size_idx[i] = 0;
                track->cb_color_info[i] = 0;
 +              track->cb_color_view[i] = 0xFFFFFFFF;
                track->cb_color_bo[i] = NULL;
                track->cb_color_bo_offset[i] = 0xFFFFFFFF;
                track->cb_color_bo_mc[i] = 0xFFFFFFFF;
        track->db_depth_size = 0xFFFFFFFF;
        track->db_depth_size_idx = 0;
        track->db_depth_control = 0xFFFFFFFF;
 +
 +      for (i = 0; i < 4; i++) {
 +              track->vgt_strmout_size[i] = 0;
 +              track->vgt_strmout_bo[i] = NULL;
 +              track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
 +              track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
 +      }
  }
  
  static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        volatile u32 *ib = p->ib->ptr;
        unsigned array_mode;
        u32 format;
 +
        if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
                dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
                return -EINVAL;
        }
        size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
        format = G_0280A0_FORMAT(track->cb_color_info[i]);
 -      if (!fmt_is_valid_color(format)) {
 +      if (!r600_fmt_is_valid_color(format)) {
                dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
                         __func__, __LINE__, format,
                        i, track->cb_color_info[i]);
        array_check.nbanks = track->nbanks;
        array_check.npipes = track->npipes;
        array_check.nsamples = track->nsamples;
 -      array_check.blocksize = fmt_get_blocksize(format);
 +      array_check.blocksize = r600_fmt_get_blocksize(format);
        if (r600_get_array_mode_alignment(&array_check,
                                          &pitch_align, &height_align, &depth_align, &base_align)) {
                dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
        }
  
        /* check offset */
 -      tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format);
 +      tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format);
 +      switch (array_mode) {
 +      default:
 +      case V_0280A0_ARRAY_LINEAR_GENERAL:
 +      case V_0280A0_ARRAY_LINEAR_ALIGNED:
 +              tmp += track->cb_color_view[i] & 0xFF;
 +              break;
 +      case V_0280A0_ARRAY_1D_TILED_THIN1:
 +      case V_0280A0_ARRAY_2D_TILED_THIN1:
 +              tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp;
 +              break;
 +      }
        if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
                if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
                        /* the initial DDX does bad things with the CB size occasionally */
                         * broken userspace.
                         */
                } else {
 -                      dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big\n", __func__, i,
 -                               array_mode,
 +                      dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n",
 +                               __func__, i, array_mode,
                                 track->cb_color_bo_offset[i], tmp,
 -                               radeon_bo_size(track->cb_color_bo[i]));
 +                               radeon_bo_size(track->cb_color_bo[i]),
 +                               pitch, height, r600_fmt_get_nblocksx(format, pitch),
 +                               r600_fmt_get_nblocksy(format, height),
 +                               r600_fmt_get_blocksize(format));
                        return -EINVAL;
                }
        }
@@@ -457,28 -430,11 +457,28 @@@ static int r600_cs_track_check(struct r
        /* on legacy kernel we don't perform advanced check */
        if (p->rdev == NULL)
                return 0;
 -      /* we don't support out buffer yet */
 -      if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
 -              dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
 -              return -EINVAL;
 +
 +      /* check streamout */
 +      if (track->vgt_strmout_en) {
 +              for (i = 0; i < 4; i++) {
 +                      if (track->vgt_strmout_buffer_en & (1 << i)) {
 +                              if (track->vgt_strmout_bo[i]) {
 +                                      u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
 +                                              (u64)track->vgt_strmout_size[i];
 +                                      if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
 +                                              DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
 +                                                        i, offset,
 +                                                        radeon_bo_size(track->vgt_strmout_bo[i]));
 +                                              return -EINVAL;
 +                                      }
 +                              } else {
 +                                      dev_warn(p->dev, "No buffer for streamout %d\n", i);
 +                                      return -EINVAL;
 +                              }
 +                      }
 +              }
        }
 +
        /* check that we have a cb for each enabled target, we don't check
         * shader_mask because it seems mesa isn't always setting it :(
         */
@@@ -1019,39 -975,6 +1019,39 @@@ static int r600_cs_check_reg(struct rad
        case R_028B20_VGT_STRMOUT_BUFFER_EN:
                track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
                break;
 +      case VGT_STRMOUT_BUFFER_BASE_0:
 +      case VGT_STRMOUT_BUFFER_BASE_1:
 +      case VGT_STRMOUT_BUFFER_BASE_2:
 +      case VGT_STRMOUT_BUFFER_BASE_3:
 +              r = r600_cs_packet_next_reloc(p, &reloc);
 +              if (r) {
 +                      dev_warn(p->dev, "bad SET_CONTEXT_REG "
 +                                      "0x%04X\n", reg);
 +                      return -EINVAL;
 +              }
 +              tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
 +              track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
 +              ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 +              track->vgt_strmout_bo[tmp] = reloc->robj;
 +              track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
 +              break;
 +      case VGT_STRMOUT_BUFFER_SIZE_0:
 +      case VGT_STRMOUT_BUFFER_SIZE_1:
 +      case VGT_STRMOUT_BUFFER_SIZE_2:
 +      case VGT_STRMOUT_BUFFER_SIZE_3:
 +              tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
 +              /* size in register is DWs, convert to bytes */
 +              track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
 +              break;
 +      case CP_COHER_BASE:
 +              r = r600_cs_packet_next_reloc(p, &reloc);
 +              if (r) {
 +                      dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
 +                                      "0x%04X\n", reg);
 +                      return -EINVAL;
 +              }
 +              ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 +              break;
        case R_028238_CB_TARGET_MASK:
                track->cb_target_mask = radeon_get_ib_value(p, idx);
                break;
                        track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
                }
                break;
 +      case R_028080_CB_COLOR0_VIEW:
 +      case R_028084_CB_COLOR1_VIEW:
 +      case R_028088_CB_COLOR2_VIEW:
 +      case R_02808C_CB_COLOR3_VIEW:
 +      case R_028090_CB_COLOR4_VIEW:
 +      case R_028094_CB_COLOR5_VIEW:
 +      case R_028098_CB_COLOR6_VIEW:
 +      case R_02809C_CB_COLOR7_VIEW:
 +              tmp = (reg - R_028080_CB_COLOR0_VIEW) / 4;
 +              track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
 +              break;
        case R_028060_CB_COLOR0_SIZE:
        case R_028064_CB_COLOR1_SIZE:
        case R_028068_CB_COLOR2_SIZE:
        return 0;
  }
  
 -static unsigned mip_minify(unsigned size, unsigned level)
 +unsigned r600_mip_minify(unsigned size, unsigned level)
  {
        unsigned val;
  
@@@ -1308,22 -1220,22 +1308,22 @@@ static void r600_texture_size(unsigned 
        unsigned nlevels = llevel - blevel + 1;
  
        *l0_size = -1;
 -      blocksize = fmt_get_blocksize(format);
 +      blocksize = r600_fmt_get_blocksize(format);
  
 -      w0 = mip_minify(w0, 0);
 -      h0 = mip_minify(h0, 0);
 -      d0 = mip_minify(d0, 0);
 +      w0 = r600_mip_minify(w0, 0);
 +      h0 = r600_mip_minify(h0, 0);
 +      d0 = r600_mip_minify(d0, 0);
        for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
 -              width = mip_minify(w0, i);
 -              nbx = fmt_get_nblocksx(format, width);
 +              width = r600_mip_minify(w0, i);
 +              nbx = r600_fmt_get_nblocksx(format, width);
  
                nbx = round_up(nbx, block_align);
  
 -              height = mip_minify(h0, i);
 -              nby = fmt_get_nblocksy(format, height);
 +              height = r600_mip_minify(h0, i);
 +              nby = r600_fmt_get_nblocksy(format, height);
                nby = round_up(nby, height_align);
  
 -              depth = mip_minify(d0, i);
 +              depth = r600_mip_minify(d0, i);
  
                size = nbx * nby * blocksize;
                if (nfaces)
@@@ -1392,6 -1304,7 +1392,7 @@@ static int r600_check_texture_resource(
        h0 = G_038004_TEX_HEIGHT(word1) + 1;
        d0 = G_038004_TEX_DEPTH(word1);
        nfaces = 1;
+       array = 0;
        switch (G_038000_DIM(word0)) {
        case V_038000_SQ_TEX_DIM_1D:
        case V_038000_SQ_TEX_DIM_2D:
                return -EINVAL;
        }
        format = G_038004_DATA_FORMAT(word1);
 -      if (!fmt_is_valid_texture(format, p->family)) {
 +      if (!r600_fmt_is_valid_texture(format, p->family)) {
                dev_warn(p->dev, "%s:%d texture invalid format %d\n",
                         __func__, __LINE__, format);
                return -EINVAL;
        array_check.nbanks = track->nbanks;
        array_check.npipes = track->npipes;
        array_check.nsamples = 1;
 -      array_check.blocksize = fmt_get_blocksize(format);
 +      array_check.blocksize = r600_fmt_get_blocksize(format);
        if (r600_get_array_mode_alignment(&array_check,
                                          &pitch_align, &height_align, &depth_align, &base_align)) {
                dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
        word1 = radeon_get_ib_value(p, idx + 5);
        blevel = G_038010_BASE_LEVEL(word0);
        llevel = G_038014_LAST_LEVEL(word1);
 +      if (blevel > llevel) {
 +              dev_warn(p->dev, "texture blevel %d > llevel %d\n",
 +                       blevel, llevel);
 +      }
        if (array == 1) {
                barray = G_038014_BASE_ARRAY(word1);
                larray = G_038014_LAST_ARRAY(word1);
                          &l0_size, &mipmap_size);
        /* using get ib will give us the offset into the texture bo */
        if ((l0_size + word2) > radeon_bo_size(texture)) {
 -              dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
 -                      w0, h0, format, word2, l0_size, radeon_bo_size(texture));
 +              dev_warn(p->dev, "texture bo too small ((%d %d) (%d %d) %d %d %d -> %d have %ld)\n",
 +                       w0, h0, pitch_align, height_align,
 +                       array_check.array_mode, format, word2,
 +                       l0_size, radeon_bo_size(texture));
                dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align);
                return -EINVAL;
        }
        return 0;
  }
  
 +static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
 +{
 +      u32 m, i;
 +
 +      i = (reg >> 7);
 +      if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
 +              dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 +              return false;
 +      }
 +      m = 1 << ((reg >> 2) & 31);
 +      if (!(r600_reg_safe_bm[i] & m))
 +              return true;
 +      dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 +      return false;
 +}
 +
  static int r600_packet3_check(struct radeon_cs_parser *p,
                                struct radeon_cs_packet *pkt)
  {
                        return -EINVAL;
                }
                break;
 +      case PACKET3_STRMOUT_BUFFER_UPDATE:
 +              if (pkt->count != 4) {
 +                      DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
 +                      return -EINVAL;
 +              }
 +              /* Updating memory at DST_ADDRESS. */
 +              if (idx_value & 0x1) {
 +                      u64 offset;
 +                      r = r600_cs_packet_next_reloc(p, &reloc);
 +                      if (r) {
 +                              DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
 +                              return -EINVAL;
 +                      }
 +                      offset = radeon_get_ib_value(p, idx+1);
 +                      offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
 +                      if ((offset + 4) > radeon_bo_size(reloc->robj)) {
 +                              DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
 +                                        offset + 4, radeon_bo_size(reloc->robj));
 +                              return -EINVAL;
 +                      }
 +                      ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 +                      ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 +              }
 +              /* Reading data from SRC_ADDRESS. */
 +              if (((idx_value >> 1) & 0x3) == 2) {
 +                      u64 offset;
 +                      r = r600_cs_packet_next_reloc(p, &reloc);
 +                      if (r) {
 +                              DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
 +                              return -EINVAL;
 +                      }
 +                      offset = radeon_get_ib_value(p, idx+3);
 +                      offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
 +                      if ((offset + 4) > radeon_bo_size(reloc->robj)) {
 +                              DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
 +                                        offset + 4, radeon_bo_size(reloc->robj));
 +                              return -EINVAL;
 +                      }
 +                      ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 +                      ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 +              }
 +              break;
 +      case PACKET3_COPY_DW:
 +              if (pkt->count != 4) {
 +                      DRM_ERROR("bad COPY_DW (invalid count)\n");
 +                      return -EINVAL;
 +              }
 +              if (idx_value & 0x1) {
 +                      u64 offset;
 +                      /* SRC is memory. */
 +                      r = r600_cs_packet_next_reloc(p, &reloc);
 +                      if (r) {
 +                              DRM_ERROR("bad COPY_DW (missing src reloc)\n");
 +                              return -EINVAL;
 +                      }
 +                      offset = radeon_get_ib_value(p, idx+1);
 +                      offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
 +                      if ((offset + 4) > radeon_bo_size(reloc->robj)) {
 +                              DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
 +                                        offset + 4, radeon_bo_size(reloc->robj));
 +                              return -EINVAL;
 +                      }
 +                      ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 +                      ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 +              } else {
 +                      /* SRC is a reg. */
 +                      reg = radeon_get_ib_value(p, idx+1) << 2;
 +                      if (!r600_is_safe_reg(p, reg, idx+1))
 +                              return -EINVAL;
 +              }
 +              if (idx_value & 0x2) {
 +                      u64 offset;
 +                      /* DST is memory. */
 +                      r = r600_cs_packet_next_reloc(p, &reloc);
 +                      if (r) {
 +                              DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
 +                              return -EINVAL;
 +                      }
 +                      offset = radeon_get_ib_value(p, idx+3);
 +                      offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
 +                      if ((offset + 4) > radeon_bo_size(reloc->robj)) {
 +                              DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
 +                                        offset + 4, radeon_bo_size(reloc->robj));
 +                              return -EINVAL;
 +                      }
 +                      ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 +                      ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 +              } else {
 +                      /* DST is a reg. */
 +                      reg = radeon_get_ib_value(p, idx+3) << 2;
 +                      if (!r600_is_safe_reg(p, reg, idx+3))
 +                              return -EINVAL;
 +              }
 +              break;
        case PACKET3_NOP:
                break;
        default:
  
  #define CB_COLOR0_SIZE                                  0x28060
  #define CB_COLOR0_VIEW                                  0x28080
 +#define R_028080_CB_COLOR0_VIEW                      0x028080
 +#define   S_028080_SLICE_START(x)                      (((x) & 0x7FF) << 0)
 +#define   G_028080_SLICE_START(x)                      (((x) >> 0) & 0x7FF)
 +#define   C_028080_SLICE_START                         0xFFFFF800
 +#define   S_028080_SLICE_MAX(x)                        (((x) & 0x7FF) << 13)
 +#define   G_028080_SLICE_MAX(x)                        (((x) >> 13) & 0x7FF)
 +#define   C_028080_SLICE_MAX                           0xFF001FFF
 +#define R_028084_CB_COLOR1_VIEW                      0x028084
 +#define R_028088_CB_COLOR2_VIEW                      0x028088
 +#define R_02808C_CB_COLOR3_VIEW                      0x02808C
 +#define R_028090_CB_COLOR4_VIEW                      0x028090
 +#define R_028094_CB_COLOR5_VIEW                      0x028094
 +#define R_028098_CB_COLOR6_VIEW                      0x028098
 +#define R_02809C_CB_COLOR7_VIEW                      0x02809C
  #define CB_COLOR0_INFO                                  0x280a0
  #     define CB_FORMAT(x)                             ((x) << 2)
  #       define CB_ARRAY_MODE(x)                         ((x) << 8)
  #define       VGT_STRMOUT_BUFFER_OFFSET_1                     0x28AEC
  #define       VGT_STRMOUT_BUFFER_OFFSET_2                     0x28AFC
  #define       VGT_STRMOUT_BUFFER_OFFSET_3                     0x28B0C
 +#define VGT_STRMOUT_BUFFER_SIZE_0                     0x28AD0
 +#define VGT_STRMOUT_BUFFER_SIZE_1                     0x28AE0
 +#define VGT_STRMOUT_BUFFER_SIZE_2                     0x28AF0
 +#define VGT_STRMOUT_BUFFER_SIZE_3                     0x28B00
 +
  #define       VGT_STRMOUT_EN                                  0x28AB0
  #define       VGT_VERTEX_REUSE_BLOCK_CNTL                     0x28C58
  #define               VTX_REUSE_DEPTH_MASK                            0x000000FF
  #define       PACKET3_STRMOUT_BUFFER_UPDATE                   0x34
  #define       PACKET3_INDIRECT_BUFFER_MP                      0x38
  #define       PACKET3_MEM_SEMAPHORE                           0x39
+ #              define PACKET3_SEM_WAIT_ON_SIGNAL    (0x1 << 12)
  #              define PACKET3_SEM_SEL_SIGNAL      (0x6 << 29)
  #              define PACKET3_SEM_SEL_WAIT        (0x7 << 29)
  #define       PACKET3_MPEG_INDEX                              0x3A
 +#define       PACKET3_COPY_DW                                 0x3B
  #define       PACKET3_WAIT_REG_MEM                            0x3C
  #define       PACKET3_MEM_WRITE                               0x3D
  #define       PACKET3_INDIRECT_BUFFER                         0x32
@@@ -85,6 -85,12 +85,6 @@@ int radeon_cs_parser_relocs(struct rade
                        radeon_bo_list_add_object(&p->relocs[i].lobj,
                                                  &p->validated);
  
 -                      if (p->relocs[i].robj->tbo.sync_obj && !(r->flags & RADEON_RELOC_DONT_SYNC)) {
 -                              struct radeon_fence *fence = p->relocs[i].robj->tbo.sync_obj;
 -                              if (!radeon_fence_signaled(fence)) {
 -                                      p->sync_to_ring[fence->ring] = true;
 -                              }
 -                      }
                } else
                        p->relocs[i].handle = 0;
        }
@@@ -112,24 -118,11 +112,24 @@@ static int radeon_cs_get_ring(struct ra
  
  static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
  {
 +      bool sync_to_ring[RADEON_NUM_RINGS] = { };
        int i, r;
  
 +      for (i = 0; i < p->nrelocs; i++) {
 +              if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj)
 +                      continue;
 +
 +              if (!(p->relocs[i].flags & RADEON_RELOC_DONT_SYNC)) {
 +                      struct radeon_fence *fence = p->relocs[i].robj->tbo.sync_obj;
 +                      if (!radeon_fence_signaled(fence)) {
 +                              sync_to_ring[fence->ring] = true;
 +                      }
 +              }
 +      }
 +
        for (i = 0; i < RADEON_NUM_RINGS; ++i) {
                /* no need to sync to our own or unused rings */
 -              if (i == p->ring || !p->sync_to_ring[i] || !p->rdev->ring[i].ready)
 +              if (i == p->ring || !sync_to_ring[i] || !p->rdev->ring[i].ready)
                        continue;
  
                if (!p->ib->fence->semaphore) {
@@@ -348,7 -341,7 +348,7 @@@ static int radeon_cs_ib_chunk(struct ra
                return r;
        }
        parser->ib->length_dw = ib_chunk->length_dw;
 -      r = radeon_cs_parse(parser);
 +      r = radeon_cs_parse(rdev, parser->ring, parser);
        if (r || parser->parser_error) {
                DRM_ERROR("Invalid command stream !\n");
                return r;
@@@ -460,6 -453,10 +460,10 @@@ int radeon_cs_ioctl(struct drm_device *
        int r;
  
        radeon_mutex_lock(&rdev->cs_mutex);
+       if (!rdev->accel_working) {
+               radeon_mutex_unlock(&rdev->cs_mutex);
+               return -EBUSY;
+       }
        /* initialize parser */
        memset(&parser, 0, sizeof(struct radeon_cs_parser));
        parser.filp = filp;
@@@ -303,17 -303,8 +303,17 @@@ void radeon_crtc_handle_flip(struct rad
        if (update_pending &&
            (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id,
                                                               &vpos, &hpos)) &&
 -          (vpos >=0) &&
 -          (vpos < (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100)) {
 +          ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
 +           (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
 +              /* crtc didn't flip in this target vblank interval,
 +               * but flip is pending in crtc. Based on the current
 +               * scanout position we know that the current frame is
 +               * (nearly) complete and the flip will (likely)
 +               * complete before the start of the next frame.
 +               */
 +              update_pending = 0;
 +      }
 +      if (update_pending) {
                /* crtc didn't flip in this target vblank interval,
                 * but flip is pending in crtc. It will complete it
                 * in next vblank interval, so complete the flip at
@@@ -1087,15 -1078,21 +1087,21 @@@ static const struct drm_framebuffer_fun
        .create_handle = radeon_user_framebuffer_create_handle,
  };
  
- void
+ int
  radeon_framebuffer_init(struct drm_device *dev,
                        struct radeon_framebuffer *rfb,
                        struct drm_mode_fb_cmd2 *mode_cmd,
                        struct drm_gem_object *obj)
  {
+       int ret;
        rfb->obj = obj;
-       drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs);
+       ret = drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs);
+       if (ret) {
+               rfb->obj = NULL;
+               return ret;
+       }
        drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd);
+       return 0;
  }
  
  static struct drm_framebuffer *
@@@ -1105,6 -1102,7 +1111,7 @@@ radeon_user_framebuffer_create(struct d
  {
        struct drm_gem_object *obj;
        struct radeon_framebuffer *radeon_fb;
+       int ret;
  
        obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
        if (obj ==  NULL) {
        if (radeon_fb == NULL)
                return ERR_PTR(-ENOMEM);
  
-       radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);
+       ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);
+       if (ret) {
+               kfree(radeon_fb);
+               drm_gem_object_unreference_unlocked(obj);
+               return NULL;
+       }
  
        return &radeon_fb->base;
  }
@@@ -1133,6 -1136,11 +1145,6 @@@ static const struct drm_mode_config_fun
        .output_poll_changed = radeon_output_poll_changed
  };
  
 -struct drm_prop_enum_list {
 -      int type;
 -      char *name;
 -};
 -
  static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] =
  {     { 0, "driver" },
        { 1, "bios" },
@@@ -1157,53 -1165,86 +1169,53 @@@ static struct drm_prop_enum_list radeon
  
  static int radeon_modeset_create_props(struct radeon_device *rdev)
  {
 -      int i, sz;
 +      int sz;
  
        if (rdev->is_atom_bios) {
                rdev->mode_info.coherent_mode_property =
 -                      drm_property_create(rdev->ddev,
 -                                          DRM_MODE_PROP_RANGE,
 -                                          "coherent", 2);
 +                      drm_property_create_range(rdev->ddev, 0 , "coherent", 0, 1);
                if (!rdev->mode_info.coherent_mode_property)
                        return -ENOMEM;
 -
 -              rdev->mode_info.coherent_mode_property->values[0] = 0;
 -              rdev->mode_info.coherent_mode_property->values[1] = 1;
        }
  
        if (!ASIC_IS_AVIVO(rdev)) {
                sz = ARRAY_SIZE(radeon_tmds_pll_enum_list);
                rdev->mode_info.tmds_pll_property =
 -                      drm_property_create(rdev->ddev,
 -                                          DRM_MODE_PROP_ENUM,
 -                                          "tmds_pll", sz);
 -              for (i = 0; i < sz; i++) {
 -                      drm_property_add_enum(rdev->mode_info.tmds_pll_property,
 -                                            i,
 -                                            radeon_tmds_pll_enum_list[i].type,
 -                                            radeon_tmds_pll_enum_list[i].name);
 -              }
 +                      drm_property_create_enum(rdev->ddev, 0,
 +                                          "tmds_pll",
 +                                          radeon_tmds_pll_enum_list, sz);
        }
  
        rdev->mode_info.load_detect_property =
 -              drm_property_create(rdev->ddev,
 -                                  DRM_MODE_PROP_RANGE,
 -                                  "load detection", 2);
 +              drm_property_create_range(rdev->ddev, 0, "load detection", 0, 1);
        if (!rdev->mode_info.load_detect_property)
                return -ENOMEM;
 -      rdev->mode_info.load_detect_property->values[0] = 0;
 -      rdev->mode_info.load_detect_property->values[1] = 1;
  
        drm_mode_create_scaling_mode_property(rdev->ddev);
  
        sz = ARRAY_SIZE(radeon_tv_std_enum_list);
        rdev->mode_info.tv_std_property =
 -              drm_property_create(rdev->ddev,
 -                                  DRM_MODE_PROP_ENUM,
 -                                  "tv standard", sz);
 -      for (i = 0; i < sz; i++) {
 -              drm_property_add_enum(rdev->mode_info.tv_std_property,
 -                                    i,
 -                                    radeon_tv_std_enum_list[i].type,
 -                                    radeon_tv_std_enum_list[i].name);
 -      }
 +              drm_property_create_enum(rdev->ddev, 0,
 +                                  "tv standard",
 +                                  radeon_tv_std_enum_list, sz);
  
        sz = ARRAY_SIZE(radeon_underscan_enum_list);
        rdev->mode_info.underscan_property =
 -              drm_property_create(rdev->ddev,
 -                                  DRM_MODE_PROP_ENUM,
 -                                  "underscan", sz);
 -      for (i = 0; i < sz; i++) {
 -              drm_property_add_enum(rdev->mode_info.underscan_property,
 -                                    i,
 -                                    radeon_underscan_enum_list[i].type,
 -                                    radeon_underscan_enum_list[i].name);
 -      }
 +              drm_property_create_enum(rdev->ddev, 0,
 +                                  "underscan",
 +                                  radeon_underscan_enum_list, sz);
  
        rdev->mode_info.underscan_hborder_property =
 -              drm_property_create(rdev->ddev,
 -                                      DRM_MODE_PROP_RANGE,
 -                                      "underscan hborder", 2);
 +              drm_property_create_range(rdev->ddev, 0,
 +                                      "underscan hborder", 0, 128);
        if (!rdev->mode_info.underscan_hborder_property)
                return -ENOMEM;
 -      rdev->mode_info.underscan_hborder_property->values[0] = 0;
 -      rdev->mode_info.underscan_hborder_property->values[1] = 128;
  
        rdev->mode_info.underscan_vborder_property =
 -              drm_property_create(rdev->ddev,
 -                                      DRM_MODE_PROP_RANGE,
 -                                      "underscan vborder", 2);
 +              drm_property_create_range(rdev->ddev, 0,
 +                                      "underscan vborder", 0, 128);
        if (!rdev->mode_info.underscan_vborder_property)
                return -ENOMEM;
 -      rdev->mode_info.underscan_vborder_property->values[0] = 0;
 -      rdev->mode_info.underscan_vborder_property->values[1] = 128;
  
        return 0;
  }
@@@ -1249,9 -1290,6 +1261,9 @@@ int radeon_modeset_init(struct radeon_d
                rdev->ddev->mode_config.max_height = 4096;
        }
  
 +      rdev->ddev->mode_config.preferred_depth = 24;
 +      rdev->ddev->mode_config.prefer_shadow = 1;
 +
        rdev->ddev->mode_config.fb_base = rdev->mc.aper_base;
  
        ret = radeon_modeset_create_props(rdev);
@@@ -209,6 -209,11 +209,11 @@@ static int radeonfb_create(struct radeo
                                                          sizes->surface_depth);
  
        ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
+       if (ret) {
+               DRM_ERROR("failed to create fbcon object %d\n", ret);
+               return ret;
+       }
        rbo = gem_to_radeon_bo(gobj);
  
        /* okay we have an object now allocate the framebuffer */
  
        info->par = rfbdev;
  
-       radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
+       ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
+       if (ret) {
+               DRM_ERROR("failed to initalise framebuffer %d\n", ret);
+               goto out_unref;
+       }
  
        fb = &rfbdev->rfb.base;
  
        info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
        info->apertures->ranges[0].size = rdev->mc.aper_size;
  
 -      info->pixmap.size = 64*1024;
 -      info->pixmap.buf_align = 8;
 -      info->pixmap.access_align = 32;
 -      info->pixmap.flags = FB_PIXMAP_SYSTEM;
 -      info->pixmap.scan_align = 1;
 +      /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
  
        if (info->screen_base == NULL) {
                ret = -ENOSPC;
@@@ -478,9 -478,7 +478,9 @@@ static struct drm_info_list radeon_debu
  static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
  {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
 -      struct radeon_ib *ib = node->info_ent->data;
 +      struct drm_device *dev = node->minor->dev;
 +      struct radeon_device *rdev = dev->dev_private;
 +      struct radeon_ib *ib = &rdev->ib_pool.ibs[*((unsigned*)node->info_ent->data)];
        unsigned i;
  
        if (ib == NULL) {
  
  static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
  static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
 +static unsigned radeon_debugfs_ib_idx[RADEON_IB_POOL_SIZE];
  #endif
  
  int radeon_debugfs_ring_init(struct radeon_device *rdev)
  {
  #if defined(CONFIG_DEBUG_FS)
-       return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list,
-                                       ARRAY_SIZE(radeon_debugfs_ring_info_list));
+       if (rdev->family >= CHIP_CAYMAN)
+               return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list,
+                                               ARRAY_SIZE(radeon_debugfs_ring_info_list));
+       else
+               return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, 1);
  #else
        return 0;
  #endif
@@@ -517,11 -517,10 +520,11 @@@ int radeon_debugfs_ib_init(struct radeo
  
        for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
                sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
 +              radeon_debugfs_ib_idx[i] = i;
                radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
                radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info;
                radeon_debugfs_ib_list[i].driver_features = 0;
 -              radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i];
 +              radeon_debugfs_ib_list[i].data = &radeon_debugfs_ib_idx[i];
        }
        return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list,
                                        RADEON_IB_POOL_SIZE);
@@@ -430,7 -430,7 +430,7 @@@ static int rs400_startup(struct radeon_
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int rs400_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        rs400_gart_disable(rdev);
        /* Resume clock before doing reset */
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return rs400_startup(rdev);
+       r = rs400_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int rs400_suspend(struct radeon_device *rdev)
  void rs600_gpu_init(struct radeon_device *rdev);
  int rs600_mc_wait_for_idle(struct radeon_device *rdev);
  
 +void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
 +{
 +      struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
 +      int i;
 +
 +      if (RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset) & AVIVO_CRTC_EN) {
 +              for (i = 0; i < rdev->usec_timeout; i++) {
 +                      if (!(RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK))
 +                              break;
 +                      udelay(1);
 +              }
 +              for (i = 0; i < rdev->usec_timeout; i++) {
 +                      if (RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK)
 +                              break;
 +                      udelay(1);
 +              }
 +      }
 +}
 +
  void rs600_pre_page_flip(struct radeon_device *rdev, int crtc)
  {
        /* enable the pflip int */
@@@ -194,7 -175,7 +194,7 @@@ void rs600_pm_misc(struct radeon_devic
        /* set pcie lanes */
        if ((rdev->flags & RADEON_IS_PCIE) &&
            !(rdev->flags & RADEON_IS_IGP) &&
 -          rdev->asic->set_pcie_lanes &&
 +          rdev->asic->pm.set_pcie_lanes &&
            (ps->pcie_lanes !=
             rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
                radeon_set_pcie_lanes(rdev,
@@@ -703,9 -684,7 +703,7 @@@ int rs600_irq_process(struct radeon_dev
                        WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_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);
+                       WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
                        break;
                }
        }
@@@ -885,7 -864,7 +883,7 @@@ static int rs600_startup(struct radeon_
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int rs600_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        rs600_gart_disable(rdev);
        /* Resume clock before doing reset */
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return rs600_startup(rdev);
+       r = rs600_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int rs600_suspend(struct radeon_device *rdev)
@@@ -31,7 -31,7 +31,7 @@@
  #include "atom.h"
  #include "rs690d.h"
  
 -static int rs690_mc_wait_for_idle(struct radeon_device *rdev)
 +int rs690_mc_wait_for_idle(struct radeon_device *rdev)
  {
        unsigned i;
        uint32_t tmp;
@@@ -647,7 -647,7 +647,7 @@@ static int rs690_startup(struct radeon_
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int rs690_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        rs400_gart_disable(rdev);
        /* Resume clock before doing reset */
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return rs690_startup(rdev);
+       r = rs690_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int rs690_suspend(struct radeon_device *rdev)
@@@ -53,8 -53,9 +53,8 @@@ void rv515_debugfs(struct radeon_devic
        }
  }
  
 -void rv515_ring_start(struct radeon_device *rdev)
 +void rv515_ring_start(struct radeon_device *rdev, struct radeon_ring *ring)
  {
 -      struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        int r;
  
        r = radeon_ring_lock(rdev, ring, 64);
@@@ -412,7 -413,7 +412,7 @@@ static int rv515_startup(struct radeon_
        if (r)
                return r;
  
 -      r = r100_ib_test(rdev);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
  
  int rv515_resume(struct radeon_device *rdev)
  {
+       int r;
        /* Make sur GART are not working */
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
        radeon_surface_init(rdev);
  
        rdev->accel_working = true;
-       return rv515_startup(rdev);
+       r =  rv515_startup(rdev);
+       if (r) {
+               rdev->accel_working = false;
+       }
+       return r;
  }
  
  int rv515_suspend(struct radeon_device *rdev)
@@@ -1074,7 -1074,7 +1074,7 @@@ static int rv770_startup(struct radeon_
        r = r600_blit_init(rdev);
        if (r) {
                r600_blit_fini(rdev);
 -              rdev->asic->copy = NULL;
 +              rdev->asic->copy.copy = NULL;
                dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
        }
  
        if (r)
                return r;
  
 -      r = r600_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX);
 +      r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "IB test failed (%d).\n", r);
                rdev->accel_working = false;
@@@ -1139,6 -1139,7 +1139,7 @@@ int rv770_resume(struct radeon_device *
        r = rv770_startup(rdev);
        if (r) {
                DRM_ERROR("r600 startup failed on resume\n");
+               rdev->accel_working = false;
                return r;
        }