Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/radeon/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 135 kB image not shown  

Quelle  r600.c   Sprache: C

 
/*
 * Copyright 2008 Advanced Micro Devices, Inc.
 * Copyright 2008 Red Hat Inc.
 * Copyright 2009 Jerome Glisse.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Dave Airlie
 *          Alex Deucher
 *          Jerome Glisse
 */


#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/seq_file.h>
#include <linux/slab.h>

#include <drm/drm_device.h>
#include <drm/drm_vblank.h>
#include <drm/radeon_drm.h>

#include "atom.h"
#include "avivod.h"
#include "evergreen.h"
#include "r600.h"
#include "r600d.h"
#include "rv770.h"
#include "radeon.h"
#include "radeon_asic.h"
#include "radeon_audio.h"
#include "radeon_mode.h"
#include "radeon_ucode.h"

/* Firmware Names */
MODULE_FIRMWARE("radeon/R600_pfp.bin");
MODULE_FIRMWARE("radeon/R600_me.bin");
MODULE_FIRMWARE("radeon/RV610_pfp.bin");
MODULE_FIRMWARE("radeon/RV610_me.bin");
MODULE_FIRMWARE("radeon/RV630_pfp.bin");
MODULE_FIRMWARE("radeon/RV630_me.bin");
MODULE_FIRMWARE("radeon/RV620_pfp.bin");
MODULE_FIRMWARE("radeon/RV620_me.bin");
MODULE_FIRMWARE("radeon/RV635_pfp.bin");
MODULE_FIRMWARE("radeon/RV635_me.bin");
MODULE_FIRMWARE("radeon/RV670_pfp.bin");
MODULE_FIRMWARE("radeon/RV670_me.bin");
MODULE_FIRMWARE("radeon/RS780_pfp.bin");
MODULE_FIRMWARE("radeon/RS780_me.bin");
MODULE_FIRMWARE("radeon/RV770_pfp.bin");
MODULE_FIRMWARE("radeon/RV770_me.bin");
MODULE_FIRMWARE("radeon/RV770_smc.bin");
MODULE_FIRMWARE("radeon/RV730_pfp.bin");
MODULE_FIRMWARE("radeon/RV730_me.bin");
MODULE_FIRMWARE("radeon/RV730_smc.bin");
MODULE_FIRMWARE("radeon/RV740_smc.bin");
MODULE_FIRMWARE("radeon/RV710_pfp.bin");
MODULE_FIRMWARE("radeon/RV710_me.bin");
MODULE_FIRMWARE("radeon/RV710_smc.bin");
MODULE_FIRMWARE("radeon/R600_rlc.bin");
MODULE_FIRMWARE("radeon/R700_rlc.bin");
MODULE_FIRMWARE("radeon/CEDAR_pfp.bin");
MODULE_FIRMWARE("radeon/CEDAR_me.bin");
MODULE_FIRMWARE("radeon/CEDAR_rlc.bin");
MODULE_FIRMWARE("radeon/CEDAR_smc.bin");
MODULE_FIRMWARE("radeon/REDWOOD_pfp.bin");
MODULE_FIRMWARE("radeon/REDWOOD_me.bin");
MODULE_FIRMWARE("radeon/REDWOOD_rlc.bin");
MODULE_FIRMWARE("radeon/REDWOOD_smc.bin");
MODULE_FIRMWARE("radeon/JUNIPER_pfp.bin");
MODULE_FIRMWARE("radeon/JUNIPER_me.bin");
MODULE_FIRMWARE("radeon/JUNIPER_rlc.bin");
MODULE_FIRMWARE("radeon/JUNIPER_smc.bin");
MODULE_FIRMWARE("radeon/CYPRESS_pfp.bin");
MODULE_FIRMWARE("radeon/CYPRESS_me.bin");
MODULE_FIRMWARE("radeon/CYPRESS_rlc.bin");
MODULE_FIRMWARE("radeon/CYPRESS_smc.bin");
MODULE_FIRMWARE("radeon/PALM_pfp.bin");
MODULE_FIRMWARE("radeon/PALM_me.bin");
MODULE_FIRMWARE("radeon/SUMO_rlc.bin");
MODULE_FIRMWARE("radeon/SUMO_pfp.bin");
MODULE_FIRMWARE("radeon/SUMO_me.bin");
MODULE_FIRMWARE("radeon/SUMO2_pfp.bin");
MODULE_FIRMWARE("radeon/SUMO2_me.bin");

static const u32 crtc_offsets[2] = {
 0,
 AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL
};

static void r600_debugfs_mc_info_init(struct radeon_device *rdev);

/* r600,rv610,rv630,rv620,rv635,rv670 */
int r600_mc_wait_for_idle(struct radeon_device *rdev);
static void r600_gpu_init(struct radeon_device *rdev);
void r600_fini(struct radeon_device *rdev);
void r600_irq_disable(struct radeon_device *rdev);
static void r600_pcie_gen2_enable(struct radeon_device *rdev);

/*
 * Indirect registers accessor
 */

u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg)
{
 unsigned long flags;
 u32 r;

 spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
 WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
 r = RREG32(R600_RCU_DATA);
 spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
 return r;
}

void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
 unsigned long flags;

 spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
 WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
 WREG32(R600_RCU_DATA, (v));
 spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
}

u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg)
{
 unsigned long flags;
 u32 r;

 spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
 WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
 r = RREG32(R600_UVD_CTX_DATA);
 spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
 return r;
}

void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
 unsigned long flags;

 spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
 WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
 WREG32(R600_UVD_CTX_DATA, (v));
 spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
}

/**
 * r600_get_allowed_info_register - fetch the register for the info ioctl
 *
 * @rdev: radeon_device pointer
 * @reg: register offset in bytes
 * @val: register value
 *
 * Returns 0 for success or -EINVAL for an invalid register
 *
 */

int r600_get_allowed_info_register(struct radeon_device *rdev,
       u32 reg, u32 *val)
{
 switch (reg) {
 case GRBM_STATUS:
 case GRBM_STATUS2:
 case R_000E50_SRBM_STATUS:
 case DMA_STATUS_REG:
 case UVD_STATUS:
  *val = RREG32(reg);
  return 0;
 default:
  return -EINVAL;
 }
}

/**
 * r600_get_xclk - get the xclk
 *
 * @rdev: radeon_device pointer
 *
 * Returns the reference clock used by the gfx engine
 * (r6xx, IGPs, APUs).
 */

u32 r600_get_xclk(struct radeon_device *rdev)
{
 return rdev->clock.spll.reference_freq;
}

int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
{
 unsigned fb_div = 0, ref_div, vclk_div = 0, dclk_div = 0;
 int r;

 /* bypass vclk and dclk with bclk */
 WREG32_P(CG_UPLL_FUNC_CNTL_2,
   VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1),
   ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));

 /* assert BYPASS_EN, deassert UPLL_RESET, UPLL_SLEEP and UPLL_CTLREQ */
 WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~(
   UPLL_RESET_MASK | UPLL_SLEEP_MASK | UPLL_CTLREQ_MASK));

 if (rdev->family >= CHIP_RS780)
  WREG32_P(GFX_MACRO_BYPASS_CNTL, UPLL_BYPASS_CNTL,
    ~UPLL_BYPASS_CNTL);

 if (!vclk || !dclk) {
  /* keep the Bypass mode, put PLL to sleep */
  WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
  return 0;
 }

 if (rdev->clock.spll.reference_freq == 10000)
  ref_div = 34;
 else
  ref_div = 4;

 r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 50000, 160000,
       ref_div + 1, 0xFFF, 2, 30, ~0,
       &fb_div, &vclk_div, &dclk_div);
 if (r)
  return r;

 if (rdev->family >= CHIP_RV670 && rdev->family < CHIP_RS780)
  fb_div >>= 1;
 else
  fb_div |= 1;

 r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
 if (r)
  return r;

 /* assert PLL_RESET */
 WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK);

 /* For RS780 we have to choose ref clk */
 if (rdev->family >= CHIP_RS780)
  WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_REFCLK_SRC_SEL_MASK,
    ~UPLL_REFCLK_SRC_SEL_MASK);

 /* set the required fb, ref and post divder values */
 WREG32_P(CG_UPLL_FUNC_CNTL,
   UPLL_FB_DIV(fb_div) |
   UPLL_REF_DIV(ref_div),
   ~(UPLL_FB_DIV_MASK | UPLL_REF_DIV_MASK));
 WREG32_P(CG_UPLL_FUNC_CNTL_2,
   UPLL_SW_HILEN(vclk_div >> 1) |
   UPLL_SW_LOLEN((vclk_div >> 1) + (vclk_div & 1)) |
   UPLL_SW_HILEN2(dclk_div >> 1) |
   UPLL_SW_LOLEN2((dclk_div >> 1) + (dclk_div & 1)) |
   UPLL_DIVEN_MASK | UPLL_DIVEN2_MASK,
   ~UPLL_SW_MASK);

 /* give the PLL some time to settle */
 mdelay(15);

 /* deassert PLL_RESET */
 WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);

 mdelay(15);

 /* deassert BYPASS EN */
 WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK);

 if (rdev->family >= CHIP_RS780)
  WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~UPLL_BYPASS_CNTL);

 r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
 if (r)
  return r;

 /* switch VCLK and DCLK selection */
 WREG32_P(CG_UPLL_FUNC_CNTL_2,
   VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2),
   ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));

 mdelay(100);

 return 0;
}

void dce3_program_fmt(struct drm_encoder *encoder)
{
 struct drm_device *dev = encoder->dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 int bpc = 0;
 u32 tmp = 0;
 enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE;

 if (connector) {
  struct radeon_connector *radeon_connector = to_radeon_connector(connector);
  bpc = radeon_get_monitor_bpc(connector);
  dither = radeon_connector->dither;
 }

 /* LVDS FMT is set up by atom */
 if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
  return;

 /* not needed for analog */
 if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) ||
     (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2))
  return;

 if (bpc == 0)
  return;

 switch (bpc) {
 case 6:
  if (dither == RADEON_FMT_DITHER_ENABLE)
   /* XXX sort out optimal dither settings */
   tmp |= FMT_SPATIAL_DITHER_EN;
  else
   tmp |= FMT_TRUNCATE_EN;
  break;
 case 8:
  if (dither == RADEON_FMT_DITHER_ENABLE)
   /* XXX sort out optimal dither settings */
   tmp |= (FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH);
  else
   tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH);
  break;
 case 10:
 default:
  /* not needed */
  break;
 }

 WREG32(FMT_BIT_DEPTH_CONTROL + radeon_crtc->crtc_offset, tmp);
}

/* get temperature in millidegrees */
int rv6xx_get_temp(struct radeon_device *rdev)
{
 u32 temp = (RREG32(CG_THERMAL_STATUS) & ASIC_T_MASK) >>
  ASIC_T_SHIFT;
 int actual_temp = temp & 0xff;

 if (temp & 0x100)
  actual_temp -= 256;

 return actual_temp * 1000;
}

void r600_pm_get_dynpm_state(struct radeon_device *rdev)
{
 int i;

 rdev->pm.dynpm_can_upclock = true;
 rdev->pm.dynpm_can_downclock = true;

 /* power state array is low to high, default is first */
 if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) {
  int min_power_state_index = 0;

  if (rdev->pm.num_power_states > 2)
   min_power_state_index = 1;

  switch (rdev->pm.dynpm_planned_action) {
  case DYNPM_ACTION_MINIMUM:
   rdev->pm.requested_power_state_index = min_power_state_index;
   rdev->pm.requested_clock_mode_index = 0;
   rdev->pm.dynpm_can_downclock = false;
   break;
  case DYNPM_ACTION_DOWNCLOCK:
   if (rdev->pm.current_power_state_index == min_power_state_index) {
    rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
    rdev->pm.dynpm_can_downclock = false;
   } else {
    if (rdev->pm.active_crtc_count > 1) {
     for (i = 0; i < rdev->pm.num_power_states; i++) {
      if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
       continue;
      else if (i >= rdev->pm.current_power_state_index) {
       rdev->pm.requested_power_state_index =
        rdev->pm.current_power_state_index;
       break;
      } else {
       rdev->pm.requested_power_state_index = i;
       break;
      }
     }
    } else {
     if (rdev->pm.current_power_state_index == 0)
      rdev->pm.requested_power_state_index =
       rdev->pm.num_power_states - 1;
     else
      rdev->pm.requested_power_state_index =
       rdev->pm.current_power_state_index - 1;
    }
   }
   rdev->pm.requested_clock_mode_index = 0;
   /* don't use the power state if crtcs are active and no display flag is set */
   if ((rdev->pm.active_crtc_count > 0) &&
       (rdev->pm.power_state[rdev->pm.requested_power_state_index].
        clock_info[rdev->pm.requested_clock_mode_index].flags &
        RADEON_PM_MODE_NO_DISPLAY)) {
    rdev->pm.requested_power_state_index++;
   }
   break;
  case DYNPM_ACTION_UPCLOCK:
   if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
    rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
    rdev->pm.dynpm_can_upclock = false;
   } else {
    if (rdev->pm.active_crtc_count > 1) {
     for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
      if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
       continue;
      else if (i <= rdev->pm.current_power_state_index) {
       rdev->pm.requested_power_state_index =
        rdev->pm.current_power_state_index;
       break;
      } else {
       rdev->pm.requested_power_state_index = i;
       break;
      }
     }
    } else
     rdev->pm.requested_power_state_index =
      rdev->pm.current_power_state_index + 1;
   }
   rdev->pm.requested_clock_mode_index = 0;
   break;
  case DYNPM_ACTION_DEFAULT:
   rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
   rdev->pm.requested_clock_mode_index = 0;
   rdev->pm.dynpm_can_upclock = false;
   break;
  case DYNPM_ACTION_NONE:
  default:
   DRM_ERROR("Requested mode for not defined action\n");
   return;
  }
 } else {
  /* XXX select a power state based on AC/DC, single/dualhead, etc. */
  /* for now just select the first power state and switch between clock modes */
  /* power state array is low to high, default is first (0) */
  if (rdev->pm.active_crtc_count > 1) {
   rdev->pm.requested_power_state_index = -1;
   /* start at 1 as we don't want the default mode */
   for (i = 1; i < rdev->pm.num_power_states; i++) {
    if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
     continue;
    else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) ||
      (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) {
     rdev->pm.requested_power_state_index = i;
     break;
    }
   }
   /* if nothing selected, grab the default state. */
   if (rdev->pm.requested_power_state_index == -1)
    rdev->pm.requested_power_state_index = 0;
  } else
   rdev->pm.requested_power_state_index = 1;

  switch (rdev->pm.dynpm_planned_action) {
  case DYNPM_ACTION_MINIMUM:
   rdev->pm.requested_clock_mode_index = 0;
   rdev->pm.dynpm_can_downclock = false;
   break;
  case DYNPM_ACTION_DOWNCLOCK:
   if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
    if (rdev->pm.current_clock_mode_index == 0) {
     rdev->pm.requested_clock_mode_index = 0;
     rdev->pm.dynpm_can_downclock = false;
    } else
     rdev->pm.requested_clock_mode_index =
      rdev->pm.current_clock_mode_index - 1;
   } else {
    rdev->pm.requested_clock_mode_index = 0;
    rdev->pm.dynpm_can_downclock = false;
   }
   /* don't use the power state if crtcs are active and no display flag is set */
   if ((rdev->pm.active_crtc_count > 0) &&
       (rdev->pm.power_state[rdev->pm.requested_power_state_index].
        clock_info[rdev->pm.requested_clock_mode_index].flags &
        RADEON_PM_MODE_NO_DISPLAY)) {
    rdev->pm.requested_clock_mode_index++;
   }
   break;
  case DYNPM_ACTION_UPCLOCK:
   if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
    if (rdev->pm.current_clock_mode_index ==
        (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) {
     rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index;
     rdev->pm.dynpm_can_upclock = false;
    } else
     rdev->pm.requested_clock_mode_index =
      rdev->pm.current_clock_mode_index + 1;
   } else {
    rdev->pm.requested_clock_mode_index =
     rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1;
    rdev->pm.dynpm_can_upclock = false;
   }
   break;
  case DYNPM_ACTION_DEFAULT:
   rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
   rdev->pm.requested_clock_mode_index = 0;
   rdev->pm.dynpm_can_upclock = false;
   break;
  case DYNPM_ACTION_NONE:
  default:
   DRM_ERROR("Requested mode for not defined action\n");
   return;
  }
 }

 DRM_DEBUG_DRIVER("Requested: e: %d m: %d p: %d\n",
    rdev->pm.power_state[rdev->pm.requested_power_state_index].
    clock_info[rdev->pm.requested_clock_mode_index].sclk,
    rdev->pm.power_state[rdev->pm.requested_power_state_index].
    clock_info[rdev->pm.requested_clock_mode_index].mclk,
    rdev->pm.power_state[rdev->pm.requested_power_state_index].
    pcie_lanes);
}

void rs780_pm_init_profile(struct radeon_device *rdev)
{
 if (rdev->pm.num_power_states == 2) {
  /* default */
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
  /* low sh */
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
  /* mid sh */
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
  /* high sh */
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
  /* low mh */
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
  /* mid mh */
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
  /* high mh */
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
 } else if (rdev->pm.num_power_states == 3) {
  /* default */
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
  /* low sh */
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
  /* mid sh */
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
  /* high sh */
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
  /* low mh */
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
  /* mid mh */
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
  /* high mh */
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
 } else {
  /* default */
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
  /* low sh */
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
  /* mid sh */
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
  /* high sh */
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
  /* low mh */
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
  /* mid mh */
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
  /* high mh */
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
 }
}

void r600_pm_init_profile(struct radeon_device *rdev)
{
 int idx;

 if (rdev->family == CHIP_R600) {
  /* XXX */
  /* default */
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
  /* low sh */
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
  /* mid sh */
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
  /* high sh */
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
  /* low mh */
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
  /* mid mh */
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
  /* high mh */
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
  rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
 } else {
  if (rdev->pm.num_power_states < 4) {
   /* default */
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
   /* low sh */
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1;
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
   /* mid sh */
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
   /* high sh */
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
   /* low mh */
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2;
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2;
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
   /* low mh */
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2;
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
   /* high mh */
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
  } else {
   /* default */
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
   /* low sh */
   if (rdev->flags & RADEON_IS_MOBILITY)
    idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
   else
    idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
   /* mid sh */
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
   /* high sh */
   idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
   /* low mh */
   if (rdev->flags & RADEON_IS_MOBILITY)
    idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
   else
    idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
   /* mid mh */
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
   /* high mh */
   idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
   rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
  }
 }
}

void r600_pm_misc(struct radeon_device *rdev)
{
 int req_ps_idx = rdev->pm.requested_power_state_index;
 int req_cm_idx = rdev->pm.requested_clock_mode_index;
 struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
 struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;

 if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
  /* 0xff01 is a flag rather then an actual voltage */
  if (voltage->voltage == 0xff01)
   return;
  if (voltage->voltage != rdev->pm.current_vddc) {
   radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
   rdev->pm.current_vddc = voltage->voltage;
   DRM_DEBUG_DRIVER("Setting: v: %d\n", voltage->voltage);
  }
 }
}

bool r600_gui_idle(struct radeon_device *rdev)
{
 if (RREG32(GRBM_STATUS) & GUI_ACTIVE)
  return false;
 else
  return true;
}

/* hpd for digital panel detect/disconnect */
bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
{
 bool connected = false;

 if (ASIC_IS_DCE3(rdev)) {
  switch (hpd) {
  case RADEON_HPD_1:
   if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE)
    connected = true;
   break;
  case RADEON_HPD_2:
   if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE)
    connected = true;
   break;
  case RADEON_HPD_3:
   if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE)
    connected = true;
   break;
  case RADEON_HPD_4:
   if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE)
    connected = true;
   break;
   /* DCE 3.2 */
  case RADEON_HPD_5:
   if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE)
    connected = true;
   break;
  case RADEON_HPD_6:
   if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
    connected = true;
   break;
  default:
   break;
  }
 } else {
  switch (hpd) {
  case RADEON_HPD_1:
   if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
    connected = true;
   break;
  case RADEON_HPD_2:
   if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
    connected = true;
   break;
  case RADEON_HPD_3:
   if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
    connected = true;
   break;
  default:
   break;
  }
 }
 return connected;
}

void r600_hpd_set_polarity(struct radeon_device *rdev,
      enum radeon_hpd_id hpd)
{
 u32 tmp;
 bool connected = r600_hpd_sense(rdev, hpd);

 if (ASIC_IS_DCE3(rdev)) {
  switch (hpd) {
  case RADEON_HPD_1:
   tmp = RREG32(DC_HPD1_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HPDx_INT_POLARITY;
   else
    tmp |= DC_HPDx_INT_POLARITY;
   WREG32(DC_HPD1_INT_CONTROL, tmp);
   break;
  case RADEON_HPD_2:
   tmp = RREG32(DC_HPD2_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HPDx_INT_POLARITY;
   else
    tmp |= DC_HPDx_INT_POLARITY;
   WREG32(DC_HPD2_INT_CONTROL, tmp);
   break;
  case RADEON_HPD_3:
   tmp = RREG32(DC_HPD3_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HPDx_INT_POLARITY;
   else
    tmp |= DC_HPDx_INT_POLARITY;
   WREG32(DC_HPD3_INT_CONTROL, tmp);
   break;
  case RADEON_HPD_4:
   tmp = RREG32(DC_HPD4_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HPDx_INT_POLARITY;
   else
    tmp |= DC_HPDx_INT_POLARITY;
   WREG32(DC_HPD4_INT_CONTROL, tmp);
   break;
  case RADEON_HPD_5:
   tmp = RREG32(DC_HPD5_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HPDx_INT_POLARITY;
   else
    tmp |= DC_HPDx_INT_POLARITY;
   WREG32(DC_HPD5_INT_CONTROL, tmp);
   break;
   /* DCE 3.2 */
  case RADEON_HPD_6:
   tmp = RREG32(DC_HPD6_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HPDx_INT_POLARITY;
   else
    tmp |= DC_HPDx_INT_POLARITY;
   WREG32(DC_HPD6_INT_CONTROL, tmp);
   break;
  default:
   break;
  }
 } else {
  switch (hpd) {
  case RADEON_HPD_1:
   tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
   else
    tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
   WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
   break;
  case RADEON_HPD_2:
   tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
   else
    tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
   WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
   break;
  case RADEON_HPD_3:
   tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL);
   if (connected)
    tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
   else
    tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
   WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
   break;
  default:
   break;
  }
 }
}

void r600_hpd_init(struct radeon_device *rdev)
{
 struct drm_device *dev = rdev_to_drm(rdev);
 struct drm_connector *connector;
 unsigned enable = 0;

 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  struct radeon_connector *radeon_connector = to_radeon_connector(connector);

  if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
      connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
   /* don't try to enable hpd on eDP or LVDS avoid breaking the
 * aux dp channel on imac and help (but not completely fix)
 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
 */

   continue;
  }
  if (ASIC_IS_DCE3(rdev)) {
   u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
   if (ASIC_IS_DCE32(rdev))
    tmp |= DC_HPDx_EN;

   switch (radeon_connector->hpd.hpd) {
   case RADEON_HPD_1:
    WREG32(DC_HPD1_CONTROL, tmp);
    break;
   case RADEON_HPD_2:
    WREG32(DC_HPD2_CONTROL, tmp);
    break;
   case RADEON_HPD_3:
    WREG32(DC_HPD3_CONTROL, tmp);
    break;
   case RADEON_HPD_4:
    WREG32(DC_HPD4_CONTROL, tmp);
    break;
    /* DCE 3.2 */
   case RADEON_HPD_5:
    WREG32(DC_HPD5_CONTROL, tmp);
    break;
   case RADEON_HPD_6:
    WREG32(DC_HPD6_CONTROL, tmp);
    break;
   default:
    break;
   }
  } else {
   switch (radeon_connector->hpd.hpd) {
   case RADEON_HPD_1:
    WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
    break;
   case RADEON_HPD_2:
    WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN);
    break;
   case RADEON_HPD_3:
    WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN);
    break;
   default:
    break;
   }
  }
  if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
   enable |= 1 << radeon_connector->hpd.hpd;
  radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 }
 radeon_irq_kms_enable_hpd(rdev, enable);
}

void r600_hpd_fini(struct radeon_device *rdev)
{
 struct drm_device *dev = rdev_to_drm(rdev);
 struct drm_connector *connector;
 unsigned disable = 0;

 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  struct radeon_connector *radeon_connector = to_radeon_connector(connector);
  if (ASIC_IS_DCE3(rdev)) {
   switch (radeon_connector->hpd.hpd) {
   case RADEON_HPD_1:
    WREG32(DC_HPD1_CONTROL, 0);
    break;
   case RADEON_HPD_2:
    WREG32(DC_HPD2_CONTROL, 0);
    break;
   case RADEON_HPD_3:
    WREG32(DC_HPD3_CONTROL, 0);
    break;
   case RADEON_HPD_4:
    WREG32(DC_HPD4_CONTROL, 0);
    break;
    /* DCE 3.2 */
   case RADEON_HPD_5:
    WREG32(DC_HPD5_CONTROL, 0);
    break;
   case RADEON_HPD_6:
    WREG32(DC_HPD6_CONTROL, 0);
    break;
   default:
    break;
   }
  } else {
   switch (radeon_connector->hpd.hpd) {
   case RADEON_HPD_1:
    WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0);
    break;
   case RADEON_HPD_2:
    WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0);
    break;
   case RADEON_HPD_3:
    WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0);
    break;
   default:
    break;
   }
  }
  if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
   disable |= 1 << radeon_connector->hpd.hpd;
 }
 radeon_irq_kms_disable_hpd(rdev, disable);
}

/*
 * R600 PCIE GART
 */

void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
{
 unsigned i;
 u32 tmp;

 /* flush hdp cache so updates hit vram */
 if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
     !(rdev->flags & RADEON_IS_AGP)) {
  void __iomem *ptr = (void *)rdev->gart.ptr;

  /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
 * This seems to cause problems on some AGP cards. Just use the old
 * method for them.
 */

  WREG32(HDP_DEBUG1, 0);
  readl((void __iomem *)ptr);
 } else
  WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);

 WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12);
 WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12);
 WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));
 for (i = 0; i < rdev->usec_timeout; i++) {
  /* read MC_STATUS */
  tmp = RREG32(VM_CONTEXT0_REQUEST_RESPONSE);
  tmp = (tmp & RESPONSE_TYPE_MASK) >> RESPONSE_TYPE_SHIFT;
  if (tmp == 2) {
   pr_warn("[drm] r600 flush TLB failed\n");
   return;
  }
  if (tmp) {
   return;
  }
  udelay(1);
 }
}

int r600_pcie_gart_init(struct radeon_device *rdev)
{
 int r;

 if (rdev->gart.robj) {
  WARN(1, "R600 PCIE GART already initialized\n");
  return 0;
 }
 /* Initialize common gart structure */
 r = radeon_gart_init(rdev);
 if (r)
  return r;
 rdev->gart.table_size = rdev->gart.num_gpu_pages * 8;
 return radeon_gart_table_vram_alloc(rdev);
}

static int r600_pcie_gart_enable(struct radeon_device *rdev)
{
 u32 tmp;
 int r, i;

 if (rdev->gart.robj == NULL) {
  dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
  return -EINVAL;
 }
 r = radeon_gart_table_vram_pin(rdev);
 if (r)
  return r;

 /* Setup L2 cache */
 WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
    ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
    EFFECTIVE_L2_QUEUE_SIZE(7));
 WREG32(VM_L2_CNTL2, 0);
 WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1));
 /* Setup TLB control */
 tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
  SYSTEM_ACCESS_MODE_NOT_IN_SYS |
  EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) |
  ENABLE_WAIT_L2_QUERY;
 WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING);
 WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_UVD_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_UVD_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
 WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
 WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
 WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
 WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
 WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
    RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
 WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
   (u32)(rdev->dummy_page.addr >> 12));
 for (i = 1; i < 7; i++)
  WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);

 r600_pcie_gart_tlb_flush(rdev);
 DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
   (unsigned)(rdev->mc.gtt_size >> 20),
   (unsigned long long)rdev->gart.table_addr);
 rdev->gart.ready = true;
 return 0;
}

static void r600_pcie_gart_disable(struct radeon_device *rdev)
{
 u32 tmp;
 int i;

 /* Disable all tables */
 for (i = 0; i < 7; i++)
  WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);

 /* Disable L2 cache */
 WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING |
    EFFECTIVE_L2_QUEUE_SIZE(7));
 WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1));
 /* Setup L1 TLB control */
 tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) |
  ENABLE_WAIT_L2_QUERY;
 WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_UVD_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_UVD_CNTL, tmp);
 radeon_gart_table_vram_unpin(rdev);
}

static void r600_pcie_gart_fini(struct radeon_device *rdev)
{
 radeon_gart_fini(rdev);
 r600_pcie_gart_disable(rdev);
 radeon_gart_table_vram_free(rdev);
}

static void r600_agp_enable(struct radeon_device *rdev)
{
 u32 tmp;
 int i;

 /* Setup L2 cache */
 WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
    ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
    EFFECTIVE_L2_QUEUE_SIZE(7));
 WREG32(VM_L2_CNTL2, 0);
 WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1));
 /* Setup TLB control */
 tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
  SYSTEM_ACCESS_MODE_NOT_IN_SYS |
  EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) |
  ENABLE_WAIT_L2_QUERY;
 WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING);
 WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp);
 WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
 WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
 for (i = 0; i < 7; i++)
  WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
}

int r600_mc_wait_for_idle(struct radeon_device *rdev)
{
 unsigned i;
 u32 tmp;

 for (i = 0; i < rdev->usec_timeout; i++) {
  /* read MC_STATUS */
  tmp = RREG32(R_000E50_SRBM_STATUS) & 0x3F00;
  if (!tmp)
   return 0;
  udelay(1);
 }
 return -1;
}

uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg)
{
 unsigned long flags;
 uint32_t r;

 spin_lock_irqsave(&rdev->mc_idx_lock, flags);
 WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg));
 r = RREG32(R_0028FC_MC_DATA);
 WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR);
 spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
 return r;
}

void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
 unsigned long flags;

 spin_lock_irqsave(&rdev->mc_idx_lock, flags);
 WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) |
  S_0028F8_MC_IND_WR_EN(1));
 WREG32(R_0028FC_MC_DATA, v);
 WREG32(R_0028F8_MC_INDEX, 0x7F);
 spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
}

static void r600_mc_program(struct radeon_device *rdev)
{
 struct rv515_mc_save save;
 u32 tmp;
 int i, j;

 /* Initialize HDP */
 for (i = 0, j = 0; i < 32; i++, j += 0x18) {
  WREG32((0x2c14 + j), 0x00000000);
  WREG32((0x2c18 + j), 0x00000000);
  WREG32((0x2c1c + j), 0x00000000);
  WREG32((0x2c20 + j), 0x00000000);
  WREG32((0x2c24 + j), 0x00000000);
 }
 WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);

 rv515_mc_stop(rdev, &save);
 if (r600_mc_wait_for_idle(rdev)) {
  dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
 }
 /* Lockout access through VGA aperture (doesn't exist before R600) */
 WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
 /* Update configuration */
 if (rdev->flags & RADEON_IS_AGP) {
  if (rdev->mc.vram_start < rdev->mc.gtt_start) {
   /* VRAM before AGP */
   WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
    rdev->mc.vram_start >> 12);
   WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
    rdev->mc.gtt_end >> 12);
  } else {
   /* VRAM after AGP */
   WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
    rdev->mc.gtt_start >> 12);
   WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
    rdev->mc.vram_end >> 12);
  }
 } else {
  WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
  WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12);
 }
 WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
 tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
 tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
 WREG32(MC_VM_FB_LOCATION, tmp);
 WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
 WREG32(HDP_NONSURFACE_INFO, (2 << 7));
 WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
 if (rdev->flags & RADEON_IS_AGP) {
  WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22);
  WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22);
  WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22);
 } else {
  WREG32(MC_VM_AGP_BASE, 0);
  WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
  WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
 }
 if (r600_mc_wait_for_idle(rdev)) {
  dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
 }
 rv515_mc_resume(rdev, &save);
 /* we need to own VRAM, so turn off the VGA renderer here
 * to stop it overwriting our objects */

 rv515_vga_render_disable(rdev);
}

/**
 * r600_vram_gtt_location - try to find VRAM & GTT location
 * @rdev: radeon device structure holding all necessary informations
 * @mc: memory controller structure holding memory informations
 *
 * Function will place try to place VRAM at same place as in CPU (PCI)
 * address space as some GPU seems to have issue when we reprogram at
 * different address space.
 *
 * If there is not enough space to fit the unvisible VRAM after the
 * aperture then we limit the VRAM size to the aperture.
 *
 * If we are using AGP then place VRAM adjacent to AGP aperture are we need
 * them to be in one from GPU point of view so that we can program GPU to
 * catch access outside them (weird GPU policy see ??).
 *
 * This function will never fails, worst case are limiting VRAM or GTT.
 *
 * Note: GTT start, end, size should be initialized before calling this
 * function on AGP platform.
 */

static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
{
 u64 size_bf, size_af;

 if (mc->mc_vram_size > 0xE0000000) {
  /* leave room for at least 512M GTT */
  dev_warn(rdev->dev, "limiting VRAM\n");
  mc->real_vram_size = 0xE0000000;
  mc->mc_vram_size = 0xE0000000;
 }
 if (rdev->flags & RADEON_IS_AGP) {
  size_bf = mc->gtt_start;
  size_af = mc->mc_mask - mc->gtt_end;
  if (size_bf > size_af) {
   if (mc->mc_vram_size > size_bf) {
    dev_warn(rdev->dev, "limiting VRAM\n");
    mc->real_vram_size = size_bf;
    mc->mc_vram_size = size_bf;
   }
   mc->vram_start = mc->gtt_start - mc->mc_vram_size;
  } else {
   if (mc->mc_vram_size > size_af) {
    dev_warn(rdev->dev, "limiting VRAM\n");
    mc->real_vram_size = size_af;
    mc->mc_vram_size = size_af;
   }
   mc->vram_start = mc->gtt_end + 1;
  }
  mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
  dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
    mc->mc_vram_size >> 20, mc->vram_start,
    mc->vram_end, mc->real_vram_size >> 20);
 } else {
  u64 base = 0;
  if (rdev->flags & RADEON_IS_IGP) {
   base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
   base <<= 24;
  }
  radeon_vram_location(rdev, &rdev->mc, base);
  rdev->mc.gtt_base_align = 0;
  radeon_gtt_location(rdev, mc);
 }
}

static int r600_mc_init(struct radeon_device *rdev)
{
 u32 tmp;
 int chansize, numchan;
 uint32_t h_addr, l_addr;
 unsigned long long k8_addr;

 /* Get VRAM informations */
 rdev->mc.vram_is_ddr = true;
 tmp = RREG32(RAMCFG);
 if (tmp & CHANSIZE_OVERRIDE) {
  chansize = 16;
 } else if (tmp & CHANSIZE_MASK) {
  chansize = 64;
 } else {
  chansize = 32;
 }
 tmp = RREG32(CHMAP);
 switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
 case 0:
 default:
  numchan = 1;
  break;
 case 1:
  numchan = 2;
  break;
 case 2:
  numchan = 4;
  break;
 case 3:
  numchan = 8;
  break;
 }
 rdev->mc.vram_width = numchan * chansize;
 /* Could aper size report 0 ? */
 rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
 rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
 /* Setup GPU memory space */
 rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
 rdev->mc.visible_vram_size = rdev->mc.aper_size;
 r600_vram_gtt_location(rdev, &rdev->mc);

 if (rdev->flags & RADEON_IS_IGP) {
  rs690_pm_info(rdev);
  rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);

  if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
   /* Use K8 direct mapping for fast fb access. */
   rdev->fastfb_working = false;
   h_addr = G_000012_K8_ADDR_EXT(RREG32_MC(R_000012_MC_MISC_UMA_CNTL));
   l_addr = RREG32_MC(R_000011_K8_FB_LOCATION);
   k8_addr = ((unsigned long long)h_addr) << 32 | l_addr;
#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
   if (k8_addr + rdev->mc.visible_vram_size < 0x100000000ULL)
#endif
   {
    /* FastFB shall be used with UMA memory. Here it is simply disabled when sideport
  * memory is present.
  */

    if (rdev->mc.igp_sideport_enabled == false && radeon_fastfb == 1) {
     DRM_INFO("Direct mapping: aper base at 0x%llx, replaced by direct mapping base 0x%llx.\n",
      (unsigned long long)rdev->mc.aper_base, k8_addr);
     rdev->mc.aper_base = (resource_size_t)k8_addr;
     rdev->fastfb_working = true;
    }
   }
  }
 }

 radeon_update_bandwidth_info(rdev);
 return 0;
}

int r600_vram_scratch_init(struct radeon_device *rdev)
{
 int r;

 if (rdev->vram_scratch.robj == NULL) {
  r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
         PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
         0, NULL, NULL, &rdev->vram_scratch.robj);
  if (r) {
   return r;
  }
 }

 r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
 if (unlikely(r != 0))
  return r;
 r = radeon_bo_pin(rdev->vram_scratch.robj,
     RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr);
 if (r) {
  radeon_bo_unreserve(rdev->vram_scratch.robj);
  return r;
 }
 r = radeon_bo_kmap(rdev->vram_scratch.robj,
    (void **)&rdev->vram_scratch.ptr);
 if (r)
  radeon_bo_unpin(rdev->vram_scratch.robj);
 radeon_bo_unreserve(rdev->vram_scratch.robj);

 return r;
}

void r600_vram_scratch_fini(struct radeon_device *rdev)
{
 int r;

 if (rdev->vram_scratch.robj == NULL) {
  return;
 }
 r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
 if (likely(r == 0)) {
  radeon_bo_kunmap(rdev->vram_scratch.robj);
  radeon_bo_unpin(rdev->vram_scratch.robj);
  radeon_bo_unreserve(rdev->vram_scratch.robj);
 }
 radeon_bo_unref(&rdev->vram_scratch.robj);
}

void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung)
{
 u32 tmp = RREG32(R600_BIOS_3_SCRATCH);

 if (hung)
  tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
 else
  tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;

 WREG32(R600_BIOS_3_SCRATCH, tmp);
}

static void r600_print_gpu_status_regs(struct radeon_device *rdev)
{
 dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n",
   RREG32(R_008010_GRBM_STATUS));
 dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n",
   RREG32(R_008014_GRBM_STATUS2));
 dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n",
   RREG32(R_000E50_SRBM_STATUS));
 dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n",
   RREG32(CP_STALLED_STAT1));
 dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n",
   RREG32(CP_STALLED_STAT2));
 dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n",
   RREG32(CP_BUSY_STAT));
 dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n",
   RREG32(CP_STAT));
 dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n",
  RREG32(DMA_STATUS_REG));
}

static bool r600_is_display_hung(struct radeon_device *rdev)
{
 u32 crtc_hung = 0;
 u32 crtc_status[2];
 u32 i, j, tmp;

 for (i = 0; i < rdev->num_crtc; i++) {
  if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN) {
   crtc_status[i] = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]);
   crtc_hung |= (1 << i);
  }
 }

 for (j = 0; j < 10; j++) {
  for (i = 0; i < rdev->num_crtc; i++) {
   if (crtc_hung & (1 << i)) {
    tmp = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]);
    if (tmp != crtc_status[i])
     crtc_hung &= ~(1 << i);
   }
  }
  if (crtc_hung == 0)
   return false;
  udelay(100);
 }

 return true;
}

u32 r600_gpu_check_soft_reset(struct radeon_device *rdev)
{
 u32 reset_mask = 0;
 u32 tmp;

 /* GRBM_STATUS */
 tmp = RREG32(R_008010_GRBM_STATUS);
 if (rdev->family >= CHIP_RV770) {
  if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) |
      G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) |
      G_008010_TA_BUSY(tmp) | G_008010_VGT_BUSY(tmp) |
      G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) |
      G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp))
   reset_mask |= RADEON_RESET_GFX;
 } else {
  if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) |
      G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) |
      G_008010_TA03_BUSY(tmp) | G_008010_VGT_BUSY(tmp) |
      G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) |
      G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp))
   reset_mask |= RADEON_RESET_GFX;
 }

 if (G_008010_CF_RQ_PENDING(tmp) | G_008010_PF_RQ_PENDING(tmp) |
     G_008010_CP_BUSY(tmp) | G_008010_CP_COHERENCY_BUSY(tmp))
  reset_mask |= RADEON_RESET_CP;

 if (G_008010_GRBM_EE_BUSY(tmp))
  reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP;

 /* DMA_STATUS_REG */
 tmp = RREG32(DMA_STATUS_REG);
 if (!(tmp & DMA_IDLE))
  reset_mask |= RADEON_RESET_DMA;

 /* SRBM_STATUS */
 tmp = RREG32(R_000E50_SRBM_STATUS);
 if (G_000E50_RLC_RQ_PENDING(tmp) | G_000E50_RLC_BUSY(tmp))
  reset_mask |= RADEON_RESET_RLC;

 if (G_000E50_IH_BUSY(tmp))
  reset_mask |= RADEON_RESET_IH;

 if (G_000E50_SEM_BUSY(tmp))
  reset_mask |= RADEON_RESET_SEM;

 if (G_000E50_GRBM_RQ_PENDING(tmp))
  reset_mask |= RADEON_RESET_GRBM;

 if (G_000E50_VMC_BUSY(tmp))
  reset_mask |= RADEON_RESET_VMC;

 if (G_000E50_MCB_BUSY(tmp) | G_000E50_MCDZ_BUSY(tmp) |
     G_000E50_MCDY_BUSY(tmp) | G_000E50_MCDX_BUSY(tmp) |
     G_000E50_MCDW_BUSY(tmp))
  reset_mask |= RADEON_RESET_MC;

 if (r600_is_display_hung(rdev))
  reset_mask |= RADEON_RESET_DISPLAY;

 /* Skip MC reset as it's mostly likely not hung, just busy */
 if (reset_mask & RADEON_RESET_MC) {
  DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
  reset_mask &= ~RADEON_RESET_MC;
 }

 return reset_mask;
}

static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
{
 struct rv515_mc_save save;
 u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
 u32 tmp;

 if (reset_mask == 0)
  return;

 dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);

 r600_print_gpu_status_regs(rdev);

 /* Disable CP parsing/prefetching */
 if (rdev->family >= CHIP_RV770)
  WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1));
 else
  WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));

 /* disable the RLC */
 WREG32(RLC_CNTL, 0);

 if (reset_mask & RADEON_RESET_DMA) {
  /* Disable DMA */
  tmp = RREG32(DMA_RB_CNTL);
  tmp &= ~DMA_RB_ENABLE;
  WREG32(DMA_RB_CNTL, tmp);
 }

 mdelay(50);

 rv515_mc_stop(rdev, &save);
 if (r600_mc_wait_for_idle(rdev)) {
  dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
 }

 if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) {
  if (rdev->family >= CHIP_RV770)
   grbm_soft_reset |= S_008020_SOFT_RESET_DB(1) |
    S_008020_SOFT_RESET_CB(1) |
    S_008020_SOFT_RESET_PA(1) |
    S_008020_SOFT_RESET_SC(1) |
    S_008020_SOFT_RESET_SPI(1) |
    S_008020_SOFT_RESET_SX(1) |
    S_008020_SOFT_RESET_SH(1) |
    S_008020_SOFT_RESET_TC(1) |
    S_008020_SOFT_RESET_TA(1) |
    S_008020_SOFT_RESET_VC(1) |
    S_008020_SOFT_RESET_VGT(1);
  else
   grbm_soft_reset |= S_008020_SOFT_RESET_CR(1) |
    S_008020_SOFT_RESET_DB(1) |
    S_008020_SOFT_RESET_CB(1) |
    S_008020_SOFT_RESET_PA(1) |
    S_008020_SOFT_RESET_SC(1) |
    S_008020_SOFT_RESET_SMX(1) |
    S_008020_SOFT_RESET_SPI(1) |
    S_008020_SOFT_RESET_SX(1) |
    S_008020_SOFT_RESET_SH(1) |
    S_008020_SOFT_RESET_TC(1) |
    S_008020_SOFT_RESET_TA(1) |
    S_008020_SOFT_RESET_VC(1) |
    S_008020_SOFT_RESET_VGT(1);
 }

 if (reset_mask & RADEON_RESET_CP) {
  grbm_soft_reset |= S_008020_SOFT_RESET_CP(1) |
   S_008020_SOFT_RESET_VGT(1);

  srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1);
 }

 if (reset_mask & RADEON_RESET_DMA) {
  if (rdev->family >= CHIP_RV770)
   srbm_soft_reset |= RV770_SOFT_RESET_DMA;
  else
   srbm_soft_reset |= SOFT_RESET_DMA;
 }

 if (reset_mask & RADEON_RESET_RLC)
  srbm_soft_reset |= S_000E60_SOFT_RESET_RLC(1);

 if (reset_mask & RADEON_RESET_SEM)
  srbm_soft_reset |= S_000E60_SOFT_RESET_SEM(1);

 if (reset_mask & RADEON_RESET_IH)
  srbm_soft_reset |= S_000E60_SOFT_RESET_IH(1);

 if (reset_mask & RADEON_RESET_GRBM)
  srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1);

 if (!(rdev->flags & RADEON_IS_IGP)) {
  if (reset_mask & RADEON_RESET_MC)
   srbm_soft_reset |= S_000E60_SOFT_RESET_MC(1);
 }

 if (reset_mask & RADEON_RESET_VMC)
  srbm_soft_reset |= S_000E60_SOFT_RESET_VMC(1);

 if (grbm_soft_reset) {
  tmp = RREG32(R_008020_GRBM_SOFT_RESET);
  tmp |= grbm_soft_reset;
  dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
  WREG32(R_008020_GRBM_SOFT_RESET, tmp);
  tmp = RREG32(R_008020_GRBM_SOFT_RESET);

  udelay(50);

  tmp &= ~grbm_soft_reset;
  WREG32(R_008020_GRBM_SOFT_RESET, tmp);
  tmp = RREG32(R_008020_GRBM_SOFT_RESET);
 }

 if (srbm_soft_reset) {
  tmp = RREG32(SRBM_SOFT_RESET);
  tmp |= srbm_soft_reset;
  dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
  WREG32(SRBM_SOFT_RESET, tmp);
  tmp = RREG32(SRBM_SOFT_RESET);

  udelay(50);

  tmp &= ~srbm_soft_reset;
  WREG32(SRBM_SOFT_RESET, tmp);
  tmp = RREG32(SRBM_SOFT_RESET);
 }

 /* Wait a little for things to settle down */
 mdelay(1);

 rv515_mc_resume(rdev, &save);
 udelay(50);

 r600_print_gpu_status_regs(rdev);
}

static void r600_gpu_pci_config_reset(struct radeon_device *rdev)
{
 struct rv515_mc_save save;
 u32 tmp, i;

 dev_info(rdev->dev, "GPU pci config reset\n");

 /* disable dpm? */

 /* Disable CP parsing/prefetching */
 if (rdev->family >= CHIP_RV770)
  WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1));
 else
  WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));

 /* disable the RLC */
 WREG32(RLC_CNTL, 0);

 /* Disable DMA */
 tmp = RREG32(DMA_RB_CNTL);
 tmp &= ~DMA_RB_ENABLE;
 WREG32(DMA_RB_CNTL, tmp);

 mdelay(50);

 /* set mclk/sclk to bypass */
 if (rdev->family >= CHIP_RV770)
  rv770_set_clk_bypass_mode(rdev);
 /* disable BM */
 pci_clear_master(rdev->pdev);
 /* disable mem access */
 rv515_mc_stop(rdev, &save);
 if (r600_mc_wait_for_idle(rdev)) {
  dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
 }

 /* BIF reset workaround.  Not sure if this is needed on 6xx */
 tmp = RREG32(BUS_CNTL);
 tmp |= VGA_COHE_SPEC_TIMER_DIS;
 WREG32(BUS_CNTL, tmp);

 tmp = RREG32(BIF_SCRATCH0);

 /* reset */
 radeon_pci_config_reset(rdev);
 mdelay(1);

 /* BIF reset workaround.  Not sure if this is needed on 6xx */
 tmp = SOFT_RESET_BIF;
 WREG32(SRBM_SOFT_RESET, tmp);
 mdelay(1);
 WREG32(SRBM_SOFT_RESET, 0);

 /* wait for asic to come out of reset */
 for (i = 0; i < rdev->usec_timeout; i++) {
  if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
   break;
  udelay(1);
 }
}

int r600_asic_reset(struct radeon_device *rdev, bool hard)
{
 u32 reset_mask;

 if (hard) {
  r600_gpu_pci_config_reset(rdev);
  return 0;
 }

 reset_mask = r600_gpu_check_soft_reset(rdev);

 if (reset_mask)
  r600_set_bios_scratch_engine_hung(rdev, true);

 /* try soft reset */
 r600_gpu_soft_reset(rdev, reset_mask);

 reset_mask = r600_gpu_check_soft_reset(rdev);

 /* try pci config reset */
 if (reset_mask && radeon_hard_reset)
  r600_gpu_pci_config_reset(rdev);

 reset_mask = r600_gpu_check_soft_reset(rdev);

 if (!reset_mask)
  r600_set_bios_scratch_engine_hung(rdev, false);

 return 0;
}

/**
 * r600_gfx_is_lockup - Check if the GFX engine is locked up
 *
 * @rdev: radeon_device pointer
 * @ring: radeon_ring structure holding ring information
 *
 * Check if the GFX engine is locked up.
 * Returns true if the engine appears to be locked up, false if not.
 */

bool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
{
 u32 reset_mask = r600_gpu_check_soft_reset(rdev);

 if (!(reset_mask & (RADEON_RESET_GFX |
       RADEON_RESET_COMPUTE |
       RADEON_RESET_CP))) {
  radeon_ring_lockup_update(rdev, ring);
  return false;
 }
 return radeon_ring_test_lockup(rdev, ring);
}

u32 r6xx_remap_render_backend(struct radeon_device *rdev,
         u32 tiling_pipe_num,
         u32 max_rb_num,
         u32 total_max_rb_num,
         u32 disabled_rb_mask)
{
 u32 rendering_pipe_num, rb_num_width, req_rb_num;
 u32 pipe_rb_ratio, pipe_rb_remain, tmp;
 u32 data = 0, mask = 1 << (max_rb_num - 1);
 unsigned i, j;

 /* mask out the RBs that don't exist on that asic */
 tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff);
 /* make sure at least one RB is available */
 if ((tmp & 0xff) != 0xff)
  disabled_rb_mask = tmp;

 rendering_pipe_num = 1 << tiling_pipe_num;
 req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask);
 BUG_ON(rendering_pipe_num < req_rb_num);

 pipe_rb_ratio = rendering_pipe_num / req_rb_num;
 pipe_rb_remain = rendering_pipe_num - pipe_rb_ratio * req_rb_num;

 if (rdev->family <= CHIP_RV740) {
  /* r6xx/r7xx */
  rb_num_width = 2;
 } else {
  /* eg+ */
  rb_num_width = 4;
 }

 for (i = 0; i < max_rb_num; i++) {
  if (!(mask & disabled_rb_mask)) {
   for (j = 0; j < pipe_rb_ratio; j++) {
    data <<= rb_num_width;
    data |= max_rb_num - i - 1;
   }
   if (pipe_rb_remain) {
    data <<= rb_num_width;
    data |= max_rb_num - i - 1;
    pipe_rb_remain--;
   }
  }
  mask >>= 1;
 }

 return data;
}

int r600_count_pipe_bits(uint32_t val)
{
 return hweight32(val);
}

static void r600_gpu_init(struct radeon_device *rdev)
{
 u32 tiling_config;
 u32 ramcfg;
 u32 cc_gc_shader_pipe_config;
 u32 tmp;
 int i, j;
 u32 sq_config;
 u32 sq_gpr_resource_mgmt_1 = 0;
 u32 sq_gpr_resource_mgmt_2 = 0;
 u32 sq_thread_resource_mgmt = 0;
 u32 sq_stack_resource_mgmt_1 = 0;
 u32 sq_stack_resource_mgmt_2 = 0;
 u32 disabled_rb_mask;

 rdev->config.r600.tiling_group_size = 256;
 switch (rdev->family) {
 case CHIP_R600:
  rdev->config.r600.max_pipes = 4;
  rdev->config.r600.max_tile_pipes = 8;
  rdev->config.r600.max_simds = 4;
  rdev->config.r600.max_backends = 4;
  rdev->config.r600.max_gprs = 256;
  rdev->config.r600.max_threads = 192;
  rdev->config.r600.max_stack_entries = 256;
  rdev->config.r600.max_hw_contexts = 8;
  rdev->config.r600.max_gs_threads = 16;
  rdev->config.r600.sx_max_export_size = 128;
  rdev->config.r600.sx_max_export_pos_size = 16;
  rdev->config.r600.sx_max_export_smx_size = 128;
  rdev->config.r600.sq_num_cf_insts = 2;
  break;
 case CHIP_RV630:
 case CHIP_RV635:
  rdev->config.r600.max_pipes = 2;
  rdev->config.r600.max_tile_pipes = 2;
  rdev->config.r600.max_simds = 3;
  rdev->config.r600.max_backends = 1;
  rdev->config.r600.max_gprs = 128;
  rdev->config.r600.max_threads = 192;
  rdev->config.r600.max_stack_entries = 128;
  rdev->config.r600.max_hw_contexts = 8;
  rdev->config.r600.max_gs_threads = 4;
  rdev->config.r600.sx_max_export_size = 128;
  rdev->config.r600.sx_max_export_pos_size = 16;
  rdev->config.r600.sx_max_export_smx_size = 128;
  rdev->config.r600.sq_num_cf_insts = 2;
  break;
 case CHIP_RV610:
 case CHIP_RV620:
 case CHIP_RS780:
 case CHIP_RS880:
  rdev->config.r600.max_pipes = 1;
  rdev->config.r600.max_tile_pipes = 1;
  rdev->config.r600.max_simds = 2;
  rdev->config.r600.max_backends = 1;
  rdev->config.r600.max_gprs = 128;
  rdev->config.r600.max_threads = 192;
  rdev->config.r600.max_stack_entries = 128;
  rdev->config.r600.max_hw_contexts = 4;
  rdev->config.r600.max_gs_threads = 4;
  rdev->config.r600.sx_max_export_size = 128;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.23 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.