| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2008 Advanced Micro Devices, Inc. | 
 | 3 |  * Copyright 2008 Red Hat Inc. | 
 | 4 |  * Copyright 2009 Jerome Glisse. | 
 | 5 |  * | 
 | 6 |  * Permission is hereby granted, free of charge, to any person obtaining a | 
 | 7 |  * copy of this software and associated documentation files (the "Software"), | 
 | 8 |  * to deal in the Software without restriction, including without limitation | 
 | 9 |  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | 
 | 10 |  * and/or sell copies of the Software, and to permit persons to whom the | 
 | 11 |  * Software is furnished to do so, subject to the following conditions: | 
 | 12 |  * | 
 | 13 |  * The above copyright notice and this permission notice shall be included in | 
 | 14 |  * all copies or substantial portions of the Software. | 
 | 15 |  * | 
 | 16 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
 | 17 |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 | 18 |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | 
 | 19 |  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | 
 | 20 |  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | 
 | 21 |  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 
 | 22 |  * OTHER DEALINGS IN THE SOFTWARE. | 
 | 23 |  * | 
 | 24 |  * Authors: Dave Airlie | 
 | 25 |  *          Alex Deucher | 
 | 26 |  *          Jerome Glisse | 
 | 27 |  */ | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 28 | /* RS600 / Radeon X1250/X1270 integrated GPU | 
 | 29 |  * | 
 | 30 |  * This file gather function specific to RS600 which is the IGP of | 
 | 31 |  * the X1250/X1270 family supporting intel CPU (while RS690/RS740 | 
 | 32 |  * is the X1250/X1270 supporting AMD CPU). The display engine are | 
 | 33 |  * the avivo one, bios is an atombios, 3D block are the one of the | 
 | 34 |  * R4XX family. The GART is different from the RS400 one and is very | 
 | 35 |  * close to the one of the R600 family (R600 likely being an evolution | 
 | 36 |  * of the RS600 GART block). | 
 | 37 |  */ | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 38 | #include "drmP.h" | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 39 | #include "radeon.h" | 
| Daniel Vetter | e699037 | 2010-03-11 21:19:17 +0000 | [diff] [blame] | 40 | #include "radeon_asic.h" | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 41 | #include "atom.h" | 
 | 42 | #include "rs600d.h" | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 43 |  | 
| Dave Airlie | 3f7dc91a | 2009-08-27 11:10:15 +1000 | [diff] [blame] | 44 | #include "rs600_reg_safe.h" | 
 | 45 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 46 | void rs600_gpu_init(struct radeon_device *rdev); | 
 | 47 | int rs600_mc_wait_for_idle(struct radeon_device *rdev); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 48 |  | 
| Alex Deucher | 3ae19b7 | 2012-02-23 17:53:37 -0500 | [diff] [blame] | 49 | void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) | 
 | 50 | { | 
 | 51 | 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; | 
 | 52 | 	int i; | 
 | 53 |  | 
 | 54 | 	if (RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset) & AVIVO_CRTC_EN) { | 
 | 55 | 		for (i = 0; i < rdev->usec_timeout; i++) { | 
 | 56 | 			if (!(RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK)) | 
 | 57 | 				break; | 
 | 58 | 			udelay(1); | 
 | 59 | 		} | 
 | 60 | 		for (i = 0; i < rdev->usec_timeout; i++) { | 
 | 61 | 			if (RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK) | 
 | 62 | 				break; | 
 | 63 | 			udelay(1); | 
 | 64 | 		} | 
 | 65 | 	} | 
 | 66 | } | 
 | 67 |  | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 68 | void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) | 
 | 69 | { | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 70 | 	/* enable the pflip int */ | 
 | 71 | 	radeon_irq_kms_pflip_irq_get(rdev, crtc); | 
 | 72 | } | 
 | 73 |  | 
 | 74 | void rs600_post_page_flip(struct radeon_device *rdev, int crtc) | 
 | 75 | { | 
 | 76 | 	/* disable the pflip int */ | 
 | 77 | 	radeon_irq_kms_pflip_irq_put(rdev, crtc); | 
 | 78 | } | 
 | 79 |  | 
 | 80 | u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | 
 | 81 | { | 
 | 82 | 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 
 | 83 | 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); | 
| Alex Deucher | f649647 | 2011-11-28 14:49:26 -0500 | [diff] [blame] | 84 | 	int i; | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 85 |  | 
 | 86 | 	/* Lock the graphics update lock */ | 
 | 87 | 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK; | 
 | 88 | 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); | 
 | 89 |  | 
 | 90 | 	/* update the scanout addresses */ | 
 | 91 | 	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | 
 | 92 | 	       (u32)crtc_base); | 
 | 93 | 	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | 
 | 94 | 	       (u32)crtc_base); | 
 | 95 |  | 
 | 96 | 	/* Wait for update_pending to go high. */ | 
| Alex Deucher | f649647 | 2011-11-28 14:49:26 -0500 | [diff] [blame] | 97 | 	for (i = 0; i < rdev->usec_timeout; i++) { | 
 | 98 | 		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) | 
 | 99 | 			break; | 
 | 100 | 		udelay(1); | 
 | 101 | 	} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 102 | 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); | 
 | 103 |  | 
 | 104 | 	/* Unlock the lock, so double-buffering can take place inside vblank */ | 
 | 105 | 	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; | 
 | 106 | 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); | 
 | 107 |  | 
 | 108 | 	/* Return current update_pending status: */ | 
 | 109 | 	return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; | 
 | 110 | } | 
 | 111 |  | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 112 | void rs600_pm_misc(struct radeon_device *rdev) | 
 | 113 | { | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 114 | 	int requested_index = rdev->pm.requested_power_state_index; | 
 | 115 | 	struct radeon_power_state *ps = &rdev->pm.power_state[requested_index]; | 
 | 116 | 	struct radeon_voltage *voltage = &ps->clock_info[0].voltage; | 
 | 117 | 	u32 tmp, dyn_pwrmgt_sclk_length, dyn_sclk_vol_cntl; | 
| Alex Deucher | 536fcd5 | 2010-04-29 16:33:38 -0400 | [diff] [blame] | 118 | 	u32 hdp_dyn_cntl, /*mc_host_dyn_cntl,*/ dyn_backbias_cntl; | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 119 |  | 
 | 120 | 	if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) { | 
 | 121 | 		if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) { | 
 | 122 | 			tmp = RREG32(voltage->gpio.reg); | 
 | 123 | 			if (voltage->active_high) | 
 | 124 | 				tmp |= voltage->gpio.mask; | 
 | 125 | 			else | 
 | 126 | 				tmp &= ~(voltage->gpio.mask); | 
 | 127 | 			WREG32(voltage->gpio.reg, tmp); | 
 | 128 | 			if (voltage->delay) | 
 | 129 | 				udelay(voltage->delay); | 
 | 130 | 		} else { | 
 | 131 | 			tmp = RREG32(voltage->gpio.reg); | 
 | 132 | 			if (voltage->active_high) | 
 | 133 | 				tmp &= ~voltage->gpio.mask; | 
 | 134 | 			else | 
 | 135 | 				tmp |= voltage->gpio.mask; | 
 | 136 | 			WREG32(voltage->gpio.reg, tmp); | 
 | 137 | 			if (voltage->delay) | 
 | 138 | 				udelay(voltage->delay); | 
 | 139 | 		} | 
| Alex Deucher | 7ac9aa5 | 2010-05-27 19:25:54 -0400 | [diff] [blame] | 140 | 	} else if (voltage->type == VOLTAGE_VDDC) | 
| Alex Deucher | 8a83ec5 | 2011-04-12 14:49:23 -0400 | [diff] [blame] | 141 | 		radeon_atom_set_voltage(rdev, voltage->vddc_id, SET_VOLTAGE_TYPE_ASIC_VDDC); | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 142 |  | 
 | 143 | 	dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH); | 
 | 144 | 	dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf); | 
 | 145 | 	dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_LOLEN(0xf); | 
 | 146 | 	if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) { | 
 | 147 | 		if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) { | 
 | 148 | 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(2); | 
 | 149 | 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(2); | 
 | 150 | 		} else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) { | 
 | 151 | 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(4); | 
 | 152 | 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(4); | 
 | 153 | 		} | 
 | 154 | 	} else { | 
 | 155 | 		dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(1); | 
 | 156 | 		dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(1); | 
 | 157 | 	} | 
 | 158 | 	WREG32_PLL(DYN_PWRMGT_SCLK_LENGTH, dyn_pwrmgt_sclk_length); | 
 | 159 |  | 
 | 160 | 	dyn_sclk_vol_cntl = RREG32_PLL(DYN_SCLK_VOL_CNTL); | 
 | 161 | 	if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) { | 
 | 162 | 		dyn_sclk_vol_cntl |= IO_CG_VOLTAGE_DROP; | 
 | 163 | 		if (voltage->delay) { | 
 | 164 | 			dyn_sclk_vol_cntl |= VOLTAGE_DROP_SYNC; | 
 | 165 | 			dyn_sclk_vol_cntl |= VOLTAGE_DELAY_SEL(voltage->delay); | 
 | 166 | 		} else | 
 | 167 | 			dyn_sclk_vol_cntl &= ~VOLTAGE_DROP_SYNC; | 
 | 168 | 	} else | 
 | 169 | 		dyn_sclk_vol_cntl &= ~IO_CG_VOLTAGE_DROP; | 
 | 170 | 	WREG32_PLL(DYN_SCLK_VOL_CNTL, dyn_sclk_vol_cntl); | 
 | 171 |  | 
 | 172 | 	hdp_dyn_cntl = RREG32_PLL(HDP_DYN_CNTL); | 
 | 173 | 	if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN) | 
 | 174 | 		hdp_dyn_cntl &= ~HDP_FORCEON; | 
 | 175 | 	else | 
 | 176 | 		hdp_dyn_cntl |= HDP_FORCEON; | 
 | 177 | 	WREG32_PLL(HDP_DYN_CNTL, hdp_dyn_cntl); | 
| Alex Deucher | 536fcd5 | 2010-04-29 16:33:38 -0400 | [diff] [blame] | 178 | #if 0 | 
 | 179 | 	/* mc_host_dyn seems to cause hangs from time to time */ | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 180 | 	mc_host_dyn_cntl = RREG32_PLL(MC_HOST_DYN_CNTL); | 
 | 181 | 	if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN) | 
 | 182 | 		mc_host_dyn_cntl &= ~MC_HOST_FORCEON; | 
 | 183 | 	else | 
 | 184 | 		mc_host_dyn_cntl |= MC_HOST_FORCEON; | 
 | 185 | 	WREG32_PLL(MC_HOST_DYN_CNTL, mc_host_dyn_cntl); | 
| Alex Deucher | 536fcd5 | 2010-04-29 16:33:38 -0400 | [diff] [blame] | 186 | #endif | 
 | 187 | 	dyn_backbias_cntl = RREG32_PLL(DYN_BACKBIAS_CNTL); | 
 | 188 | 	if (ps->misc & ATOM_PM_MISCINFO2_DYNAMIC_BACK_BIAS_EN) | 
 | 189 | 		dyn_backbias_cntl |= IO_CG_BACKBIAS_EN; | 
 | 190 | 	else | 
 | 191 | 		dyn_backbias_cntl &= ~IO_CG_BACKBIAS_EN; | 
 | 192 | 	WREG32_PLL(DYN_BACKBIAS_CNTL, dyn_backbias_cntl); | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 193 |  | 
 | 194 | 	/* set pcie lanes */ | 
 | 195 | 	if ((rdev->flags & RADEON_IS_PCIE) && | 
 | 196 | 	    !(rdev->flags & RADEON_IS_IGP) && | 
| Alex Deucher | 798bcf7 | 2012-02-23 17:53:48 -0500 | [diff] [blame] | 197 | 	    rdev->asic->pm.set_pcie_lanes && | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 198 | 	    (ps->pcie_lanes != | 
 | 199 | 	     rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) { | 
 | 200 | 		radeon_set_pcie_lanes(rdev, | 
 | 201 | 				      ps->pcie_lanes); | 
| Alex Deucher | ce8a3eb | 2010-05-07 16:58:27 -0400 | [diff] [blame] | 202 | 		DRM_DEBUG("Setting: p: %d\n", ps->pcie_lanes); | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 203 | 	} | 
| Alex Deucher | 49e02b7 | 2010-04-23 17:57:27 -0400 | [diff] [blame] | 204 | } | 
 | 205 |  | 
 | 206 | void rs600_pm_prepare(struct radeon_device *rdev) | 
 | 207 | { | 
 | 208 | 	struct drm_device *ddev = rdev->ddev; | 
 | 209 | 	struct drm_crtc *crtc; | 
 | 210 | 	struct radeon_crtc *radeon_crtc; | 
 | 211 | 	u32 tmp; | 
 | 212 |  | 
 | 213 | 	/* disable any active CRTCs */ | 
 | 214 | 	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { | 
 | 215 | 		radeon_crtc = to_radeon_crtc(crtc); | 
 | 216 | 		if (radeon_crtc->enabled) { | 
 | 217 | 			tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset); | 
 | 218 | 			tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; | 
 | 219 | 			WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp); | 
 | 220 | 		} | 
 | 221 | 	} | 
 | 222 | } | 
 | 223 |  | 
 | 224 | void rs600_pm_finish(struct radeon_device *rdev) | 
 | 225 | { | 
 | 226 | 	struct drm_device *ddev = rdev->ddev; | 
 | 227 | 	struct drm_crtc *crtc; | 
 | 228 | 	struct radeon_crtc *radeon_crtc; | 
 | 229 | 	u32 tmp; | 
 | 230 |  | 
 | 231 | 	/* enable any active CRTCs */ | 
 | 232 | 	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { | 
 | 233 | 		radeon_crtc = to_radeon_crtc(crtc); | 
 | 234 | 		if (radeon_crtc->enabled) { | 
 | 235 | 			tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset); | 
 | 236 | 			tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; | 
 | 237 | 			WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp); | 
 | 238 | 		} | 
 | 239 | 	} | 
 | 240 | } | 
 | 241 |  | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 242 | /* hpd for digital panel detect/disconnect */ | 
 | 243 | bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | 
 | 244 | { | 
 | 245 | 	u32 tmp; | 
 | 246 | 	bool connected = false; | 
 | 247 |  | 
 | 248 | 	switch (hpd) { | 
 | 249 | 	case RADEON_HPD_1: | 
 | 250 | 		tmp = RREG32(R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS); | 
 | 251 | 		if (G_007D04_DC_HOT_PLUG_DETECT1_SENSE(tmp)) | 
 | 252 | 			connected = true; | 
 | 253 | 		break; | 
 | 254 | 	case RADEON_HPD_2: | 
 | 255 | 		tmp = RREG32(R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS); | 
 | 256 | 		if (G_007D14_DC_HOT_PLUG_DETECT2_SENSE(tmp)) | 
 | 257 | 			connected = true; | 
 | 258 | 		break; | 
 | 259 | 	default: | 
 | 260 | 		break; | 
 | 261 | 	} | 
 | 262 | 	return connected; | 
 | 263 | } | 
 | 264 |  | 
 | 265 | void rs600_hpd_set_polarity(struct radeon_device *rdev, | 
 | 266 | 			    enum radeon_hpd_id hpd) | 
 | 267 | { | 
 | 268 | 	u32 tmp; | 
 | 269 | 	bool connected = rs600_hpd_sense(rdev, hpd); | 
 | 270 |  | 
 | 271 | 	switch (hpd) { | 
 | 272 | 	case RADEON_HPD_1: | 
 | 273 | 		tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); | 
 | 274 | 		if (connected) | 
 | 275 | 			tmp &= ~S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); | 
 | 276 | 		else | 
 | 277 | 			tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1); | 
 | 278 | 		WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); | 
 | 279 | 		break; | 
 | 280 | 	case RADEON_HPD_2: | 
 | 281 | 		tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); | 
 | 282 | 		if (connected) | 
 | 283 | 			tmp &= ~S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); | 
 | 284 | 		else | 
 | 285 | 			tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1); | 
 | 286 | 		WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); | 
 | 287 | 		break; | 
 | 288 | 	default: | 
 | 289 | 		break; | 
 | 290 | 	} | 
 | 291 | } | 
 | 292 |  | 
 | 293 | void rs600_hpd_init(struct radeon_device *rdev) | 
 | 294 | { | 
 | 295 | 	struct drm_device *dev = rdev->ddev; | 
 | 296 | 	struct drm_connector *connector; | 
 | 297 |  | 
 | 298 | 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 
 | 299 | 		struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 
 | 300 | 		switch (radeon_connector->hpd.hpd) { | 
 | 301 | 		case RADEON_HPD_1: | 
 | 302 | 			WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 
 | 303 | 			       S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); | 
 | 304 | 			rdev->irq.hpd[0] = true; | 
 | 305 | 			break; | 
 | 306 | 		case RADEON_HPD_2: | 
 | 307 | 			WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 
 | 308 | 			       S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); | 
 | 309 | 			rdev->irq.hpd[1] = true; | 
 | 310 | 			break; | 
 | 311 | 		default: | 
 | 312 | 			break; | 
 | 313 | 		} | 
| Alex Deucher | 64912e9 | 2011-11-03 11:21:39 -0400 | [diff] [blame] | 314 | 		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 315 | 	} | 
| Jerome Glisse | 003e69f | 2010-01-07 15:39:14 +0100 | [diff] [blame] | 316 | 	if (rdev->irq.installed) | 
 | 317 | 		rs600_irq_set(rdev); | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 318 | } | 
 | 319 |  | 
 | 320 | void rs600_hpd_fini(struct radeon_device *rdev) | 
 | 321 | { | 
 | 322 | 	struct drm_device *dev = rdev->ddev; | 
 | 323 | 	struct drm_connector *connector; | 
 | 324 |  | 
 | 325 | 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 
 | 326 | 		struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 
 | 327 | 		switch (radeon_connector->hpd.hpd) { | 
 | 328 | 		case RADEON_HPD_1: | 
 | 329 | 			WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 
 | 330 | 			       S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); | 
 | 331 | 			rdev->irq.hpd[0] = false; | 
 | 332 | 			break; | 
 | 333 | 		case RADEON_HPD_2: | 
 | 334 | 			WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 
 | 335 | 			       S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); | 
 | 336 | 			rdev->irq.hpd[1] = false; | 
 | 337 | 			break; | 
 | 338 | 		default: | 
 | 339 | 			break; | 
 | 340 | 		} | 
 | 341 | 	} | 
 | 342 | } | 
 | 343 |  | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 344 | int rs600_asic_reset(struct radeon_device *rdev) | 
 | 345 | { | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 346 | 	struct rv515_mc_save save; | 
| Alex Deucher | 25b2ec5b | 2011-01-11 13:36:55 -0500 | [diff] [blame] | 347 | 	u32 status, tmp; | 
 | 348 | 	int ret = 0; | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 349 |  | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 350 | 	status = RREG32(R_000E40_RBBM_STATUS); | 
 | 351 | 	if (!G_000E40_GUI_ACTIVE(status)) { | 
 | 352 | 		return 0; | 
 | 353 | 	} | 
| Alex Deucher | 25b2ec5b | 2011-01-11 13:36:55 -0500 | [diff] [blame] | 354 | 	/* Stops all mc clients */ | 
 | 355 | 	rv515_mc_stop(rdev, &save); | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 356 | 	status = RREG32(R_000E40_RBBM_STATUS); | 
 | 357 | 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); | 
 | 358 | 	/* stop CP */ | 
 | 359 | 	WREG32(RADEON_CP_CSQ_CNTL, 0); | 
 | 360 | 	tmp = RREG32(RADEON_CP_RB_CNTL); | 
 | 361 | 	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); | 
 | 362 | 	WREG32(RADEON_CP_RB_RPTR_WR, 0); | 
 | 363 | 	WREG32(RADEON_CP_RB_WPTR, 0); | 
 | 364 | 	WREG32(RADEON_CP_RB_CNTL, tmp); | 
 | 365 | 	pci_save_state(rdev->pdev); | 
 | 366 | 	/* disable bus mastering */ | 
| Michel Dänzer | 642ce52 | 2012-01-12 16:04:11 +0100 | [diff] [blame] | 367 | 	pci_clear_master(rdev->pdev); | 
 | 368 | 	mdelay(1); | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 369 | 	/* reset GA+VAP */ | 
 | 370 | 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | | 
 | 371 | 					S_0000F0_SOFT_RESET_GA(1)); | 
 | 372 | 	RREG32(R_0000F0_RBBM_SOFT_RESET); | 
 | 373 | 	mdelay(500); | 
 | 374 | 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0); | 
 | 375 | 	mdelay(1); | 
 | 376 | 	status = RREG32(R_000E40_RBBM_STATUS); | 
 | 377 | 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); | 
 | 378 | 	/* reset CP */ | 
 | 379 | 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); | 
 | 380 | 	RREG32(R_0000F0_RBBM_SOFT_RESET); | 
 | 381 | 	mdelay(500); | 
 | 382 | 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0); | 
 | 383 | 	mdelay(1); | 
 | 384 | 	status = RREG32(R_000E40_RBBM_STATUS); | 
 | 385 | 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); | 
 | 386 | 	/* reset MC */ | 
 | 387 | 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1)); | 
 | 388 | 	RREG32(R_0000F0_RBBM_SOFT_RESET); | 
 | 389 | 	mdelay(500); | 
 | 390 | 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0); | 
 | 391 | 	mdelay(1); | 
 | 392 | 	status = RREG32(R_000E40_RBBM_STATUS); | 
 | 393 | 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); | 
 | 394 | 	/* restore PCI & busmastering */ | 
 | 395 | 	pci_restore_state(rdev->pdev); | 
 | 396 | 	/* Check if GPU is idle */ | 
 | 397 | 	if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { | 
 | 398 | 		dev_err(rdev->dev, "failed to reset GPU\n"); | 
| Alex Deucher | 25b2ec5b | 2011-01-11 13:36:55 -0500 | [diff] [blame] | 399 | 		ret = -1; | 
 | 400 | 	} else | 
 | 401 | 		dev_info(rdev->dev, "GPU reset succeed\n"); | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 402 | 	rv515_mc_resume(rdev, &save); | 
| Alex Deucher | 25b2ec5b | 2011-01-11 13:36:55 -0500 | [diff] [blame] | 403 | 	return ret; | 
| Jerome Glisse | 90aca4d | 2010-03-09 14:45:12 +0000 | [diff] [blame] | 404 | } | 
 | 405 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 406 | /* | 
 | 407 |  * GART. | 
 | 408 |  */ | 
 | 409 | void rs600_gart_tlb_flush(struct radeon_device *rdev) | 
 | 410 | { | 
 | 411 | 	uint32_t tmp; | 
 | 412 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 413 | 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL); | 
 | 414 | 	tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE; | 
 | 415 | 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 416 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 417 | 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL); | 
| Jerome Glisse | 30f69f3 | 2010-04-16 18:46:35 +0200 | [diff] [blame] | 418 | 	tmp |= S_000100_INVALIDATE_ALL_L1_TLBS(1) | S_000100_INVALIDATE_L2_CACHE(1); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 419 | 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 420 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 421 | 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL); | 
 | 422 | 	tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE; | 
 | 423 | 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp); | 
 | 424 | 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 425 | } | 
 | 426 |  | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 427 | int rs600_gart_init(struct radeon_device *rdev) | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 428 | { | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 429 | 	int r; | 
 | 430 |  | 
| Jerome Glisse | c9a1be9 | 2011-11-03 11:16:49 -0400 | [diff] [blame] | 431 | 	if (rdev->gart.robj) { | 
| Joe Perches | fce7d61 | 2010-10-30 21:08:30 +0000 | [diff] [blame] | 432 | 		WARN(1, "RS600 GART already initialized\n"); | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 433 | 		return 0; | 
 | 434 | 	} | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 435 | 	/* Initialize common gart structure */ | 
 | 436 | 	r = radeon_gart_init(rdev); | 
 | 437 | 	if (r) { | 
 | 438 | 		return r; | 
 | 439 | 	} | 
 | 440 | 	rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 441 | 	return radeon_gart_table_vram_alloc(rdev); | 
 | 442 | } | 
 | 443 |  | 
| Alex Deucher | e22e6d2 | 2011-07-11 20:27:23 +0000 | [diff] [blame] | 444 | static int rs600_gart_enable(struct radeon_device *rdev) | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 445 | { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 446 | 	u32 tmp; | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 447 | 	int r, i; | 
 | 448 |  | 
| Jerome Glisse | c9a1be9 | 2011-11-03 11:16:49 -0400 | [diff] [blame] | 449 | 	if (rdev->gart.robj == NULL) { | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 450 | 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); | 
 | 451 | 		return -EINVAL; | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 452 | 	} | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 453 | 	r = radeon_gart_table_vram_pin(rdev); | 
 | 454 | 	if (r) | 
 | 455 | 		return r; | 
| Dave Airlie | 8256856 | 2010-02-05 16:00:07 +1000 | [diff] [blame] | 456 | 	radeon_gart_restore(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 457 | 	/* Enable bus master */ | 
| Alex Deucher | e22e6d2 | 2011-07-11 20:27:23 +0000 | [diff] [blame] | 458 | 	tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; | 
 | 459 | 	WREG32(RADEON_BUS_CNTL, tmp); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 460 | 	/* FIXME: setup default page */ | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 461 | 	WREG32_MC(R_000100_MC_PT0_CNTL, | 
| Alex Deucher | 4f15d24 | 2009-12-05 17:55:37 -0500 | [diff] [blame] | 462 | 		  (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) | | 
 | 463 | 		   S_000100_EFFECTIVE_L2_QUEUE_SIZE(6))); | 
 | 464 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 465 | 	for (i = 0; i < 19; i++) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 466 | 		WREG32_MC(R_00016C_MC_PT0_CLIENT0_CNTL + i, | 
| Alex Deucher | 4f15d24 | 2009-12-05 17:55:37 -0500 | [diff] [blame] | 467 | 			  S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) | | 
 | 468 | 			  S_00016C_SYSTEM_ACCESS_MODE_MASK( | 
 | 469 | 				  V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS) | | 
 | 470 | 			  S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS( | 
 | 471 | 				  V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH) | | 
 | 472 | 			  S_00016C_EFFECTIVE_L1_CACHE_SIZE(3) | | 
 | 473 | 			  S_00016C_ENABLE_FRAGMENT_PROCESSING(1) | | 
 | 474 | 			  S_00016C_EFFECTIVE_L1_QUEUE_SIZE(3)); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 475 | 	} | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 476 | 	/* enable first context */ | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 477 | 	WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL, | 
| Alex Deucher | 4f15d24 | 2009-12-05 17:55:37 -0500 | [diff] [blame] | 478 | 		  S_000102_ENABLE_PAGE_TABLE(1) | | 
 | 479 | 		  S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT)); | 
 | 480 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 481 | 	/* disable all other contexts */ | 
| Alex Deucher | 4f15d24 | 2009-12-05 17:55:37 -0500 | [diff] [blame] | 482 | 	for (i = 1; i < 8; i++) | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 483 | 		WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL + i, 0); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 484 |  | 
 | 485 | 	/* setup the page table */ | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 486 | 	WREG32_MC(R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR, | 
| Alex Deucher | 4f15d24 | 2009-12-05 17:55:37 -0500 | [diff] [blame] | 487 | 		  rdev->gart.table_addr); | 
 | 488 | 	WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start); | 
 | 489 | 	WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 490 | 	WREG32_MC(R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 491 |  | 
| Alex Deucher | 4f15d24 | 2009-12-05 17:55:37 -0500 | [diff] [blame] | 492 | 	/* System context maps to VRAM space */ | 
 | 493 | 	WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start); | 
 | 494 | 	WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end); | 
 | 495 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 496 | 	/* enable page tables */ | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 497 | 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL); | 
 | 498 | 	WREG32_MC(R_000100_MC_PT0_CNTL, (tmp | S_000100_ENABLE_PT(1))); | 
 | 499 | 	tmp = RREG32_MC(R_000009_MC_CNTL1); | 
 | 500 | 	WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1))); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 501 | 	rs600_gart_tlb_flush(rdev); | 
| Tormod Volden | fcf4de5 | 2011-08-31 21:54:07 +0000 | [diff] [blame] | 502 | 	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", | 
 | 503 | 		 (unsigned)(rdev->mc.gtt_size >> 20), | 
 | 504 | 		 (unsigned long long)rdev->gart.table_addr); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 505 | 	rdev->gart.ready = true; | 
 | 506 | 	return 0; | 
 | 507 | } | 
 | 508 |  | 
 | 509 | void rs600_gart_disable(struct radeon_device *rdev) | 
 | 510 | { | 
| Jerome Glisse | 4c78867 | 2009-11-20 14:29:23 +0100 | [diff] [blame] | 511 | 	u32 tmp; | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 512 |  | 
 | 513 | 	/* FIXME: disable out of gart access */ | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 514 | 	WREG32_MC(R_000100_MC_PT0_CNTL, 0); | 
 | 515 | 	tmp = RREG32_MC(R_000009_MC_CNTL1); | 
 | 516 | 	WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES); | 
| Jerome Glisse | c9a1be9 | 2011-11-03 11:16:49 -0400 | [diff] [blame] | 517 | 	radeon_gart_table_vram_unpin(rdev); | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 518 | } | 
 | 519 |  | 
 | 520 | void rs600_gart_fini(struct radeon_device *rdev) | 
 | 521 | { | 
| Jerome Glisse | f927456 | 2010-03-17 14:44:29 +0000 | [diff] [blame] | 522 | 	radeon_gart_fini(rdev); | 
| Jerome Glisse | 4aac047 | 2009-09-14 18:29:49 +0200 | [diff] [blame] | 523 | 	rs600_gart_disable(rdev); | 
 | 524 | 	radeon_gart_table_vram_free(rdev); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 525 | } | 
 | 526 |  | 
 | 527 | #define R600_PTE_VALID     (1 << 0) | 
 | 528 | #define R600_PTE_SYSTEM    (1 << 1) | 
 | 529 | #define R600_PTE_SNOOPED   (1 << 2) | 
 | 530 | #define R600_PTE_READABLE  (1 << 5) | 
 | 531 | #define R600_PTE_WRITEABLE (1 << 6) | 
 | 532 |  | 
 | 533 | int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) | 
 | 534 | { | 
| Jerome Glisse | c9a1be9 | 2011-11-03 11:16:49 -0400 | [diff] [blame] | 535 | 	void __iomem *ptr = (void *)rdev->gart.ptr; | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 536 |  | 
 | 537 | 	if (i < 0 || i > rdev->gart.num_gpu_pages) { | 
 | 538 | 		return -EINVAL; | 
 | 539 | 	} | 
 | 540 | 	addr = addr & 0xFFFFFFFFFFFFF000ULL; | 
 | 541 | 	addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED; | 
 | 542 | 	addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE; | 
| Benjamin Herrenschmidt | a0533fb | 2011-07-13 06:28:12 +0000 | [diff] [blame] | 543 | 	writeq(addr, ptr + (i * 8)); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 544 | 	return 0; | 
 | 545 | } | 
 | 546 |  | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 547 | int rs600_irq_set(struct radeon_device *rdev) | 
 | 548 | { | 
 | 549 | 	uint32_t tmp = 0; | 
 | 550 | 	uint32_t mode_int = 0; | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 551 | 	u32 hpd1 = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL) & | 
 | 552 | 		~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); | 
 | 553 | 	u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) & | 
 | 554 | 		~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 555 | 	u32 hdmi0; | 
 | 556 | 	if (ASIC_IS_DCE2(rdev)) | 
 | 557 | 		hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) & | 
 | 558 | 			~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); | 
 | 559 | 	else | 
 | 560 | 		hdmi0 = 0; | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 561 |  | 
| Jerome Glisse | 003e69f | 2010-01-07 15:39:14 +0100 | [diff] [blame] | 562 | 	if (!rdev->irq.installed) { | 
| Joe Perches | fce7d61 | 2010-10-30 21:08:30 +0000 | [diff] [blame] | 563 | 		WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); | 
| Jerome Glisse | 003e69f | 2010-01-07 15:39:14 +0100 | [diff] [blame] | 564 | 		WREG32(R_000040_GEN_INT_CNTL, 0); | 
 | 565 | 		return -EINVAL; | 
 | 566 | 	} | 
| Alex Deucher | 1b37078 | 2011-11-17 20:13:28 -0500 | [diff] [blame] | 567 | 	if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 568 | 		tmp |= S_000040_SW_INT_EN(1); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 569 | 	} | 
| Alex Deucher | 2031f77 | 2010-04-22 12:52:11 -0400 | [diff] [blame] | 570 | 	if (rdev->irq.gui_idle) { | 
 | 571 | 		tmp |= S_000040_GUI_IDLE(1); | 
 | 572 | 	} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 573 | 	if (rdev->irq.crtc_vblank_int[0] || | 
 | 574 | 	    rdev->irq.pflip[0]) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 575 | 		mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 576 | 	} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 577 | 	if (rdev->irq.crtc_vblank_int[1] || | 
 | 578 | 	    rdev->irq.pflip[1]) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 579 | 		mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 580 | 	} | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 581 | 	if (rdev->irq.hpd[0]) { | 
 | 582 | 		hpd1 |= S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); | 
 | 583 | 	} | 
 | 584 | 	if (rdev->irq.hpd[1]) { | 
 | 585 | 		hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); | 
 | 586 | 	} | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 587 | 	if (rdev->irq.afmt[0]) { | 
 | 588 | 		hdmi0 |= S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); | 
 | 589 | 	} | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 590 | 	WREG32(R_000040_GEN_INT_CNTL, tmp); | 
 | 591 | 	WREG32(R_006540_DxMODE_INT_MASK, mode_int); | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 592 | 	WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); | 
 | 593 | 	WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 594 | 	if (ASIC_IS_DCE2(rdev)) | 
 | 595 | 		WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 596 | 	return 0; | 
 | 597 | } | 
 | 598 |  | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 599 | static inline u32 rs600_irq_ack(struct radeon_device *rdev) | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 600 | { | 
| Jerome Glisse | 01ceae8 | 2009-10-07 11:08:22 +0200 | [diff] [blame] | 601 | 	uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); | 
| Alex Deucher | 2031f77 | 2010-04-22 12:52:11 -0400 | [diff] [blame] | 602 | 	uint32_t irq_mask = S_000044_SW_INT(1); | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 603 | 	u32 tmp; | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 604 |  | 
| Alex Deucher | 2031f77 | 2010-04-22 12:52:11 -0400 | [diff] [blame] | 605 | 	/* the interrupt works, but the status bit is permanently asserted */ | 
 | 606 | 	if (rdev->irq.gui_idle && radeon_gui_idle(rdev)) { | 
 | 607 | 		if (!rdev->irq.gui_idle_acked) | 
 | 608 | 			irq_mask |= S_000044_GUI_IDLE_STAT(1); | 
 | 609 | 	} | 
 | 610 |  | 
| Jerome Glisse | 01ceae8 | 2009-10-07 11:08:22 +0200 | [diff] [blame] | 611 | 	if (G_000044_DISPLAY_INT_STAT(irqs)) { | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 612 | 		rdev->irq.stat_regs.r500.disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); | 
 | 613 | 		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 614 | 			WREG32(R_006534_D1MODE_VBLANK_STATUS, | 
 | 615 | 				S_006534_D1MODE_VBLANK_ACK(1)); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 616 | 		} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 617 | 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 618 | 			WREG32(R_006D34_D2MODE_VBLANK_STATUS, | 
 | 619 | 				S_006D34_D2MODE_VBLANK_ACK(1)); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 620 | 		} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 621 | 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 622 | 			tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); | 
 | 623 | 			tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1); | 
 | 624 | 			WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); | 
 | 625 | 		} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 626 | 		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 627 | 			tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); | 
 | 628 | 			tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1); | 
 | 629 | 			WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); | 
 | 630 | 		} | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 631 | 	} else { | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 632 | 		rdev->irq.stat_regs.r500.disp_int = 0; | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 633 | 	} | 
 | 634 |  | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 635 | 	if (ASIC_IS_DCE2(rdev)) { | 
 | 636 | 		rdev->irq.stat_regs.r500.hdmi0_status = RREG32(R_007404_HDMI0_STATUS) & | 
 | 637 | 			S_007404_HDMI0_AZ_FORMAT_WTRIG(1); | 
 | 638 | 		if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) { | 
 | 639 | 			tmp = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL); | 
 | 640 | 			tmp |= S_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(1); | 
 | 641 | 			WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, tmp); | 
 | 642 | 		} | 
 | 643 | 	} else | 
 | 644 | 		rdev->irq.stat_regs.r500.hdmi0_status = 0; | 
 | 645 |  | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 646 | 	if (irqs) { | 
| Jerome Glisse | 01ceae8 | 2009-10-07 11:08:22 +0200 | [diff] [blame] | 647 | 		WREG32(R_000044_GEN_INT_STATUS, irqs); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 648 | 	} | 
 | 649 | 	return irqs & irq_mask; | 
 | 650 | } | 
 | 651 |  | 
| Jerome Glisse | ac447df | 2009-09-30 22:18:43 +0200 | [diff] [blame] | 652 | void rs600_irq_disable(struct radeon_device *rdev) | 
 | 653 | { | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 654 | 	u32 hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) & | 
 | 655 | 		~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); | 
 | 656 | 	WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); | 
| Jerome Glisse | ac447df | 2009-09-30 22:18:43 +0200 | [diff] [blame] | 657 | 	WREG32(R_000040_GEN_INT_CNTL, 0); | 
 | 658 | 	WREG32(R_006540_DxMODE_INT_MASK, 0); | 
 | 659 | 	/* Wait and acknowledge irq */ | 
 | 660 | 	mdelay(1); | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 661 | 	rs600_irq_ack(rdev); | 
| Jerome Glisse | ac447df | 2009-09-30 22:18:43 +0200 | [diff] [blame] | 662 | } | 
 | 663 |  | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 664 | int rs600_irq_process(struct radeon_device *rdev) | 
 | 665 | { | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 666 | 	u32 status, msi_rearm; | 
| Alex Deucher | d4877cf | 2009-12-04 16:56:37 -0500 | [diff] [blame] | 667 | 	bool queue_hotplug = false; | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 668 | 	bool queue_hdmi = false; | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 669 |  | 
| Alex Deucher | 2031f77 | 2010-04-22 12:52:11 -0400 | [diff] [blame] | 670 | 	/* reset gui idle ack.  the status bit is broken */ | 
 | 671 | 	rdev->irq.gui_idle_acked = false; | 
 | 672 |  | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 673 | 	status = rs600_irq_ack(rdev); | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 674 | 	if (!status && | 
 | 675 | 	    !rdev->irq.stat_regs.r500.disp_int && | 
 | 676 | 	    !rdev->irq.stat_regs.r500.hdmi0_status) { | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 677 | 		return IRQ_NONE; | 
 | 678 | 	} | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 679 | 	while (status || | 
 | 680 | 	       rdev->irq.stat_regs.r500.disp_int || | 
 | 681 | 	       rdev->irq.stat_regs.r500.hdmi0_status) { | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 682 | 		/* SW interrupt */ | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 683 | 		if (G_000044_SW_INT(status)) { | 
| Alex Deucher | 7465280 | 2011-08-25 13:39:48 -0400 | [diff] [blame] | 684 | 			radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 685 | 		} | 
| Alex Deucher | 2031f77 | 2010-04-22 12:52:11 -0400 | [diff] [blame] | 686 | 		/* GUI idle */ | 
 | 687 | 		if (G_000040_GUI_IDLE(status)) { | 
 | 688 | 			rdev->irq.gui_idle_acked = true; | 
 | 689 | 			rdev->pm.gui_idle = true; | 
 | 690 | 			wake_up(&rdev->irq.idle_queue); | 
 | 691 | 		} | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 692 | 		/* Vertical blank interrupts */ | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 693 | 		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 694 | 			if (rdev->irq.crtc_vblank_int[0]) { | 
 | 695 | 				drm_handle_vblank(rdev->ddev, 0); | 
 | 696 | 				rdev->pm.vblank_sync = true; | 
 | 697 | 				wake_up(&rdev->irq.vblank_queue); | 
 | 698 | 			} | 
| Mario Kleiner | 3e4ea74 | 2010-11-21 10:59:02 -0500 | [diff] [blame] | 699 | 			if (rdev->irq.pflip[0]) | 
 | 700 | 				radeon_crtc_handle_flip(rdev, 0); | 
| Rafał Miłecki | c913e23 | 2009-12-22 23:02:16 +0100 | [diff] [blame] | 701 | 		} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 702 | 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 703 | 			if (rdev->irq.crtc_vblank_int[1]) { | 
 | 704 | 				drm_handle_vblank(rdev->ddev, 1); | 
 | 705 | 				rdev->pm.vblank_sync = true; | 
 | 706 | 				wake_up(&rdev->irq.vblank_queue); | 
 | 707 | 			} | 
| Mario Kleiner | 3e4ea74 | 2010-11-21 10:59:02 -0500 | [diff] [blame] | 708 | 			if (rdev->irq.pflip[1]) | 
 | 709 | 				radeon_crtc_handle_flip(rdev, 1); | 
| Rafał Miłecki | c913e23 | 2009-12-22 23:02:16 +0100 | [diff] [blame] | 710 | 		} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 711 | 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Alex Deucher | d4877cf | 2009-12-04 16:56:37 -0500 | [diff] [blame] | 712 | 			queue_hotplug = true; | 
 | 713 | 			DRM_DEBUG("HPD1\n"); | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 714 | 		} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 715 | 		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 
| Alex Deucher | d4877cf | 2009-12-04 16:56:37 -0500 | [diff] [blame] | 716 | 			queue_hotplug = true; | 
 | 717 | 			DRM_DEBUG("HPD2\n"); | 
| Alex Deucher | dcfdd40 | 2009-12-04 15:04:19 -0500 | [diff] [blame] | 718 | 		} | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 719 | 		if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) { | 
 | 720 | 			queue_hdmi = true; | 
 | 721 | 			DRM_DEBUG("HDMI0\n"); | 
 | 722 | 		} | 
| Alex Deucher | 6f34be5 | 2010-11-21 10:59:01 -0500 | [diff] [blame] | 723 | 		status = rs600_irq_ack(rdev); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 724 | 	} | 
| Alex Deucher | 2031f77 | 2010-04-22 12:52:11 -0400 | [diff] [blame] | 725 | 	/* reset gui idle ack.  the status bit is broken */ | 
 | 726 | 	rdev->irq.gui_idle_acked = false; | 
| Alex Deucher | d4877cf | 2009-12-04 16:56:37 -0500 | [diff] [blame] | 727 | 	if (queue_hotplug) | 
| Tejun Heo | 32c87fc | 2011-01-03 14:49:32 +0100 | [diff] [blame] | 728 | 		schedule_work(&rdev->hotplug_work); | 
| Alex Deucher | f122c61 | 2012-03-30 08:59:57 -0400 | [diff] [blame] | 729 | 	if (queue_hdmi) | 
 | 730 | 		schedule_work(&rdev->audio_work); | 
| Alex Deucher | 3e5cb98 | 2009-10-16 12:21:24 -0400 | [diff] [blame] | 731 | 	if (rdev->msi_enabled) { | 
 | 732 | 		switch (rdev->family) { | 
 | 733 | 		case CHIP_RS600: | 
 | 734 | 		case CHIP_RS690: | 
 | 735 | 		case CHIP_RS740: | 
 | 736 | 			msi_rearm = RREG32(RADEON_BUS_CNTL) & ~RS600_MSI_REARM; | 
 | 737 | 			WREG32(RADEON_BUS_CNTL, msi_rearm); | 
 | 738 | 			WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM); | 
 | 739 | 			break; | 
 | 740 | 		default: | 
| Alex Deucher | b7f5b7d | 2012-02-13 16:36:34 -0500 | [diff] [blame] | 741 | 			WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); | 
| Alex Deucher | 3e5cb98 | 2009-10-16 12:21:24 -0400 | [diff] [blame] | 742 | 			break; | 
 | 743 | 		} | 
 | 744 | 	} | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 745 | 	return IRQ_HANDLED; | 
 | 746 | } | 
 | 747 |  | 
 | 748 | u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc) | 
 | 749 | { | 
 | 750 | 	if (crtc == 0) | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 751 | 		return RREG32(R_0060A4_D1CRTC_STATUS_FRAME_COUNT); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 752 | 	else | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 753 | 		return RREG32(R_0068A4_D2CRTC_STATUS_FRAME_COUNT); | 
| Michel Dänzer | 7ed220d | 2009-08-13 11:10:51 +0200 | [diff] [blame] | 754 | } | 
 | 755 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 756 | int rs600_mc_wait_for_idle(struct radeon_device *rdev) | 
 | 757 | { | 
 | 758 | 	unsigned i; | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 759 |  | 
 | 760 | 	for (i = 0; i < rdev->usec_timeout; i++) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 761 | 		if (G_000000_MC_IDLE(RREG32_MC(R_000000_MC_STATUS))) | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 762 | 			return 0; | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 763 | 		udelay(1); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 764 | 	} | 
 | 765 | 	return -1; | 
 | 766 | } | 
 | 767 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 768 | void rs600_gpu_init(struct radeon_device *rdev) | 
 | 769 | { | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 770 | 	r420_pipes_init(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 771 | 	/* Wait for mc idle */ | 
 | 772 | 	if (rs600_mc_wait_for_idle(rdev)) | 
 | 773 | 		dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 774 | } | 
 | 775 |  | 
| Jerome Glisse | d594e46 | 2010-02-17 21:54:29 +0000 | [diff] [blame] | 776 | void rs600_mc_init(struct radeon_device *rdev) | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 777 | { | 
| Jerome Glisse | d594e46 | 2010-02-17 21:54:29 +0000 | [diff] [blame] | 778 | 	u64 base; | 
 | 779 |  | 
| Jordan Crouse | 01d73a6 | 2010-05-27 13:40:24 -0600 | [diff] [blame] | 780 | 	rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); | 
 | 781 | 	rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 782 | 	rdev->mc.vram_is_ddr = true; | 
 | 783 | 	rdev->mc.vram_width = 128; | 
| Alex Deucher | 722f294 | 2009-12-03 16:18:19 -0500 | [diff] [blame] | 784 | 	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | 
 | 785 | 	rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | 
| Jerome Glisse | 51e5fcd | 2010-02-19 14:33:54 +0000 | [diff] [blame] | 786 | 	rdev->mc.visible_vram_size = rdev->mc.aper_size; | 
| Jerome Glisse | d594e46 | 2010-02-17 21:54:29 +0000 | [diff] [blame] | 787 | 	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); | 
 | 788 | 	base = RREG32_MC(R_000004_MC_FB_LOCATION); | 
 | 789 | 	base = G_000004_MC_FB_START(base) << 16; | 
 | 790 | 	radeon_vram_location(rdev, &rdev->mc, base); | 
| Alex Deucher | 8d369bb | 2010-07-15 10:51:10 -0400 | [diff] [blame] | 791 | 	rdev->mc.gtt_base_align = 0; | 
| Jerome Glisse | d594e46 | 2010-02-17 21:54:29 +0000 | [diff] [blame] | 792 | 	radeon_gtt_location(rdev, &rdev->mc); | 
| Alex Deucher | f47299c | 2010-03-16 20:54:38 -0400 | [diff] [blame] | 793 | 	radeon_update_bandwidth_info(rdev); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 794 | } | 
 | 795 |  | 
| Jerome Glisse | c93bb85 | 2009-07-13 21:04:08 +0200 | [diff] [blame] | 796 | void rs600_bandwidth_update(struct radeon_device *rdev) | 
 | 797 | { | 
| Alex Deucher | f46c012 | 2010-03-31 00:33:27 -0400 | [diff] [blame] | 798 | 	struct drm_display_mode *mode0 = NULL; | 
 | 799 | 	struct drm_display_mode *mode1 = NULL; | 
 | 800 | 	u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt; | 
 | 801 | 	/* FIXME: implement full support */ | 
 | 802 |  | 
 | 803 | 	radeon_update_display_priority(rdev); | 
 | 804 |  | 
 | 805 | 	if (rdev->mode_info.crtcs[0]->base.enabled) | 
 | 806 | 		mode0 = &rdev->mode_info.crtcs[0]->base.mode; | 
 | 807 | 	if (rdev->mode_info.crtcs[1]->base.enabled) | 
 | 808 | 		mode1 = &rdev->mode_info.crtcs[1]->base.mode; | 
 | 809 |  | 
 | 810 | 	rs690_line_buffer_adjust(rdev, mode0, mode1); | 
 | 811 |  | 
 | 812 | 	if (rdev->disp_priority == 2) { | 
 | 813 | 		d1mode_priority_a_cnt = RREG32(R_006548_D1MODE_PRIORITY_A_CNT); | 
 | 814 | 		d2mode_priority_a_cnt = RREG32(R_006D48_D2MODE_PRIORITY_A_CNT); | 
 | 815 | 		d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); | 
 | 816 | 		d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); | 
 | 817 | 		WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); | 
 | 818 | 		WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); | 
 | 819 | 		WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); | 
 | 820 | 		WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); | 
 | 821 | 	} | 
| Jerome Glisse | c93bb85 | 2009-07-13 21:04:08 +0200 | [diff] [blame] | 822 | } | 
 | 823 |  | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 824 | uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg) | 
 | 825 | { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 826 | 	WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) | | 
 | 827 | 		S_000070_MC_IND_CITF_ARB0(1)); | 
 | 828 | 	return RREG32(R_000074_MC_IND_DATA); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 829 | } | 
 | 830 |  | 
 | 831 | void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | 
 | 832 | { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 833 | 	WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) | | 
 | 834 | 		S_000070_MC_IND_CITF_ARB0(1) | S_000070_MC_IND_WR_EN(1)); | 
 | 835 | 	WREG32(R_000074_MC_IND_DATA, v); | 
 | 836 | } | 
 | 837 |  | 
 | 838 | void rs600_debugfs(struct radeon_device *rdev) | 
 | 839 | { | 
 | 840 | 	if (r100_debugfs_rbbm_init(rdev)) | 
 | 841 | 		DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | 
| Jerome Glisse | 771fe6b | 2009-06-05 14:42:42 +0200 | [diff] [blame] | 842 | } | 
| Dave Airlie | 3f7dc91a | 2009-08-27 11:10:15 +1000 | [diff] [blame] | 843 |  | 
| Jerome Glisse | 3bc6853 | 2009-10-01 09:39:24 +0200 | [diff] [blame] | 844 | void rs600_set_safe_registers(struct radeon_device *rdev) | 
| Dave Airlie | 3f7dc91a | 2009-08-27 11:10:15 +1000 | [diff] [blame] | 845 | { | 
 | 846 | 	rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm; | 
 | 847 | 	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs600_reg_safe_bm); | 
| Jerome Glisse | 3bc6853 | 2009-10-01 09:39:24 +0200 | [diff] [blame] | 848 | } | 
 | 849 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 850 | static void rs600_mc_program(struct radeon_device *rdev) | 
 | 851 | { | 
 | 852 | 	struct rv515_mc_save save; | 
 | 853 |  | 
 | 854 | 	/* Stops all mc clients */ | 
 | 855 | 	rv515_mc_stop(rdev, &save); | 
 | 856 |  | 
 | 857 | 	/* Wait for mc idle */ | 
 | 858 | 	if (rs600_mc_wait_for_idle(rdev)) | 
 | 859 | 		dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); | 
 | 860 |  | 
 | 861 | 	/* FIXME: What does AGP means for such chipset ? */ | 
 | 862 | 	WREG32_MC(R_000005_MC_AGP_LOCATION, 0x0FFFFFFF); | 
 | 863 | 	WREG32_MC(R_000006_AGP_BASE, 0); | 
 | 864 | 	WREG32_MC(R_000007_AGP_BASE_2, 0); | 
 | 865 | 	/* Program MC */ | 
 | 866 | 	WREG32_MC(R_000004_MC_FB_LOCATION, | 
 | 867 | 			S_000004_MC_FB_START(rdev->mc.vram_start >> 16) | | 
 | 868 | 			S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16)); | 
 | 869 | 	WREG32(R_000134_HDP_FB_LOCATION, | 
 | 870 | 		S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); | 
 | 871 |  | 
 | 872 | 	rv515_mc_resume(rdev, &save); | 
 | 873 | } | 
 | 874 |  | 
 | 875 | static int rs600_startup(struct radeon_device *rdev) | 
 | 876 | { | 
 | 877 | 	int r; | 
 | 878 |  | 
 | 879 | 	rs600_mc_program(rdev); | 
 | 880 | 	/* Resume clock */ | 
 | 881 | 	rv515_clock_startup(rdev); | 
 | 882 | 	/* Initialize GPU configuration (# pipes, ...) */ | 
 | 883 | 	rs600_gpu_init(rdev); | 
 | 884 | 	/* Initialize GART (initialize after TTM so we can allocate | 
 | 885 | 	 * memory through TTM but finalize after TTM) */ | 
 | 886 | 	r = rs600_gart_enable(rdev); | 
 | 887 | 	if (r) | 
 | 888 | 		return r; | 
| Alex Deucher | 724c80e | 2010-08-27 18:25:25 -0400 | [diff] [blame] | 889 |  | 
 | 890 | 	/* allocate wb buffer */ | 
 | 891 | 	r = radeon_wb_init(rdev); | 
 | 892 | 	if (r) | 
 | 893 | 		return r; | 
 | 894 |  | 
| Jerome Glisse | 30eb77f | 2011-11-20 20:45:34 +0000 | [diff] [blame] | 895 | 	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); | 
 | 896 | 	if (r) { | 
 | 897 | 		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); | 
 | 898 | 		return r; | 
 | 899 | 	} | 
 | 900 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 901 | 	/* Enable IRQ */ | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 902 | 	rs600_irq_set(rdev); | 
| Jerome Glisse | cafe660 | 2010-01-07 12:39:21 +0100 | [diff] [blame] | 903 | 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 904 | 	/* 1M ring buffer */ | 
 | 905 | 	r = r100_cp_init(rdev, 1024 * 1024); | 
 | 906 | 	if (r) { | 
| Paul Bolle | ec4f2ac | 2011-01-28 23:32:04 +0100 | [diff] [blame] | 907 | 		dev_err(rdev->dev, "failed initializing CP (%d).\n", r); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 908 | 		return r; | 
 | 909 | 	} | 
| Rafał Miłecki | fe50ac7 | 2010-06-19 12:24:57 +0200 | [diff] [blame] | 910 |  | 
| Jerome Glisse | b15ba51 | 2011-11-15 11:48:34 -0500 | [diff] [blame] | 911 | 	r = radeon_ib_pool_start(rdev); | 
 | 912 | 	if (r) | 
 | 913 | 		return r; | 
 | 914 |  | 
| Christian König | 7bd560e | 2012-05-02 15:11:12 +0200 | [diff] [blame] | 915 | 	r = radeon_ib_ring_tests(rdev); | 
 | 916 | 	if (r) | 
| Jerome Glisse | b15ba51 | 2011-11-15 11:48:34 -0500 | [diff] [blame] | 917 | 		return r; | 
| Jerome Glisse | b15ba51 | 2011-11-15 11:48:34 -0500 | [diff] [blame] | 918 |  | 
| Alex Deucher | d4e30ef | 2012-06-04 17:18:51 -0400 | [diff] [blame] | 919 | 	r = r600_audio_init(rdev); | 
 | 920 | 	if (r) { | 
 | 921 | 		dev_err(rdev->dev, "failed initializing audio\n"); | 
 | 922 | 		return r; | 
 | 923 | 	} | 
 | 924 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 925 | 	return 0; | 
 | 926 | } | 
 | 927 |  | 
 | 928 | int rs600_resume(struct radeon_device *rdev) | 
 | 929 | { | 
| Jerome Glisse | 6b7746e | 2012-02-20 17:57:20 -0500 | [diff] [blame] | 930 | 	int r; | 
 | 931 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 932 | 	/* Make sur GART are not working */ | 
 | 933 | 	rs600_gart_disable(rdev); | 
 | 934 | 	/* Resume clock before doing reset */ | 
 | 935 | 	rv515_clock_startup(rdev); | 
 | 936 | 	/* Reset gpu before posting otherwise ATOM will enter infinite loop */ | 
| Jerome Glisse | a2d07b7 | 2010-03-09 14:45:11 +0000 | [diff] [blame] | 937 | 	if (radeon_asic_reset(rdev)) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 938 | 		dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", | 
 | 939 | 			RREG32(R_000E40_RBBM_STATUS), | 
 | 940 | 			RREG32(R_0007C0_CP_STAT)); | 
 | 941 | 	} | 
 | 942 | 	/* post */ | 
 | 943 | 	atom_asic_init(rdev->mode_info.atom_context); | 
 | 944 | 	/* Resume clock after posting */ | 
 | 945 | 	rv515_clock_startup(rdev); | 
| Dave Airlie | 550e2d9 | 2009-12-09 14:15:38 +1000 | [diff] [blame] | 946 | 	/* Initialize surface registers */ | 
 | 947 | 	radeon_surface_init(rdev); | 
| Jerome Glisse | b15ba51 | 2011-11-15 11:48:34 -0500 | [diff] [blame] | 948 |  | 
 | 949 | 	rdev->accel_working = true; | 
| Jerome Glisse | 6b7746e | 2012-02-20 17:57:20 -0500 | [diff] [blame] | 950 | 	r = rs600_startup(rdev); | 
 | 951 | 	if (r) { | 
 | 952 | 		rdev->accel_working = false; | 
 | 953 | 	} | 
 | 954 | 	return r; | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 955 | } | 
 | 956 |  | 
 | 957 | int rs600_suspend(struct radeon_device *rdev) | 
 | 958 | { | 
| Jerome Glisse | b15ba51 | 2011-11-15 11:48:34 -0500 | [diff] [blame] | 959 | 	radeon_ib_pool_suspend(rdev); | 
| Rafał Miłecki | fe50ac7 | 2010-06-19 12:24:57 +0200 | [diff] [blame] | 960 | 	r600_audio_fini(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 961 | 	r100_cp_disable(rdev); | 
| Alex Deucher | 724c80e | 2010-08-27 18:25:25 -0400 | [diff] [blame] | 962 | 	radeon_wb_disable(rdev); | 
| Jerome Glisse | ac447df | 2009-09-30 22:18:43 +0200 | [diff] [blame] | 963 | 	rs600_irq_disable(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 964 | 	rs600_gart_disable(rdev); | 
 | 965 | 	return 0; | 
 | 966 | } | 
 | 967 |  | 
 | 968 | void rs600_fini(struct radeon_device *rdev) | 
 | 969 | { | 
| Rafał Miłecki | fe50ac7 | 2010-06-19 12:24:57 +0200 | [diff] [blame] | 970 | 	r600_audio_fini(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 971 | 	r100_cp_fini(rdev); | 
| Alex Deucher | 724c80e | 2010-08-27 18:25:25 -0400 | [diff] [blame] | 972 | 	radeon_wb_fini(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 973 | 	r100_ib_fini(rdev); | 
 | 974 | 	radeon_gem_fini(rdev); | 
 | 975 | 	rs600_gart_fini(rdev); | 
 | 976 | 	radeon_irq_kms_fini(rdev); | 
 | 977 | 	radeon_fence_driver_fini(rdev); | 
| Jerome Glisse | 4c78867 | 2009-11-20 14:29:23 +0100 | [diff] [blame] | 978 | 	radeon_bo_fini(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 979 | 	radeon_atombios_fini(rdev); | 
 | 980 | 	kfree(rdev->bios); | 
 | 981 | 	rdev->bios = NULL; | 
 | 982 | } | 
 | 983 |  | 
| Jerome Glisse | 3bc6853 | 2009-10-01 09:39:24 +0200 | [diff] [blame] | 984 | int rs600_init(struct radeon_device *rdev) | 
 | 985 | { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 986 | 	int r; | 
 | 987 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 988 | 	/* Disable VGA */ | 
 | 989 | 	rv515_vga_render_disable(rdev); | 
 | 990 | 	/* Initialize scratch registers */ | 
 | 991 | 	radeon_scratch_init(rdev); | 
 | 992 | 	/* Initialize surface registers */ | 
 | 993 | 	radeon_surface_init(rdev); | 
| Dave Airlie | 4c712e6 | 2010-07-15 12:13:50 +1000 | [diff] [blame] | 994 | 	/* restore some register to sane defaults */ | 
 | 995 | 	r100_restore_sanity(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 996 | 	/* BIOS */ | 
 | 997 | 	if (!radeon_get_bios(rdev)) { | 
 | 998 | 		if (ASIC_IS_AVIVO(rdev)) | 
 | 999 | 			return -EINVAL; | 
 | 1000 | 	} | 
 | 1001 | 	if (rdev->is_atom_bios) { | 
 | 1002 | 		r = radeon_atombios_init(rdev); | 
 | 1003 | 		if (r) | 
 | 1004 | 			return r; | 
 | 1005 | 	} else { | 
 | 1006 | 		dev_err(rdev->dev, "Expecting atombios for RS600 GPU\n"); | 
 | 1007 | 		return -EINVAL; | 
 | 1008 | 	} | 
 | 1009 | 	/* Reset gpu before posting otherwise ATOM will enter infinite loop */ | 
| Jerome Glisse | a2d07b7 | 2010-03-09 14:45:11 +0000 | [diff] [blame] | 1010 | 	if (radeon_asic_reset(rdev)) { | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1011 | 		dev_warn(rdev->dev, | 
 | 1012 | 			"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", | 
 | 1013 | 			RREG32(R_000E40_RBBM_STATUS), | 
 | 1014 | 			RREG32(R_0007C0_CP_STAT)); | 
 | 1015 | 	} | 
 | 1016 | 	/* check if cards are posted or not */ | 
| Dave Airlie | 72542d7 | 2009-12-01 14:06:31 +1000 | [diff] [blame] | 1017 | 	if (radeon_boot_test_post_card(rdev) == false) | 
 | 1018 | 		return -EINVAL; | 
 | 1019 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1020 | 	/* Initialize clocks */ | 
 | 1021 | 	radeon_get_clock_info(rdev->ddev); | 
| Jerome Glisse | d594e46 | 2010-02-17 21:54:29 +0000 | [diff] [blame] | 1022 | 	/* initialize memory controller */ | 
 | 1023 | 	rs600_mc_init(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1024 | 	rs600_debugfs(rdev); | 
 | 1025 | 	/* Fence driver */ | 
| Jerome Glisse | 30eb77f | 2011-11-20 20:45:34 +0000 | [diff] [blame] | 1026 | 	r = radeon_fence_driver_init(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1027 | 	if (r) | 
 | 1028 | 		return r; | 
 | 1029 | 	r = radeon_irq_kms_init(rdev); | 
 | 1030 | 	if (r) | 
 | 1031 | 		return r; | 
 | 1032 | 	/* Memory manager */ | 
| Jerome Glisse | 4c78867 | 2009-11-20 14:29:23 +0100 | [diff] [blame] | 1033 | 	r = radeon_bo_init(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1034 | 	if (r) | 
 | 1035 | 		return r; | 
 | 1036 | 	r = rs600_gart_init(rdev); | 
 | 1037 | 	if (r) | 
 | 1038 | 		return r; | 
 | 1039 | 	rs600_set_safe_registers(rdev); | 
| Jerome Glisse | b15ba51 | 2011-11-15 11:48:34 -0500 | [diff] [blame] | 1040 |  | 
 | 1041 | 	r = radeon_ib_pool_init(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1042 | 	rdev->accel_working = true; | 
| Jerome Glisse | b15ba51 | 2011-11-15 11:48:34 -0500 | [diff] [blame] | 1043 | 	if (r) { | 
 | 1044 | 		dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | 
 | 1045 | 		rdev->accel_working = false; | 
 | 1046 | 	} | 
 | 1047 |  | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1048 | 	r = rs600_startup(rdev); | 
 | 1049 | 	if (r) { | 
 | 1050 | 		/* Somethings want wront with the accel init stop accel */ | 
 | 1051 | 		dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1052 | 		r100_cp_fini(rdev); | 
| Alex Deucher | 724c80e | 2010-08-27 18:25:25 -0400 | [diff] [blame] | 1053 | 		radeon_wb_fini(rdev); | 
| Jerome Glisse | c010f80 | 2009-09-30 22:09:06 +0200 | [diff] [blame] | 1054 | 		r100_ib_fini(rdev); | 
 | 1055 | 		rs600_gart_fini(rdev); | 
 | 1056 | 		radeon_irq_kms_fini(rdev); | 
 | 1057 | 		rdev->accel_working = false; | 
 | 1058 | 	} | 
| Dave Airlie | 3f7dc91a | 2009-08-27 11:10:15 +1000 | [diff] [blame] | 1059 | 	return 0; | 
 | 1060 | } |