xref: /dragonfly/sys/dev/drm/radeon/rs600.c (revision ec5b6af4)
1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot  * Copyright 2008 Advanced Micro Devices, Inc.
3926deccbSFrançois Tigeot  * Copyright 2008 Red Hat Inc.
4926deccbSFrançois Tigeot  * Copyright 2009 Jerome Glisse.
5926deccbSFrançois Tigeot  *
6926deccbSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
7926deccbSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
8926deccbSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
9926deccbSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10926deccbSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
11926deccbSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
12926deccbSFrançois Tigeot  *
13926deccbSFrançois Tigeot  * The above copyright notice and this permission notice shall be included in
14926deccbSFrançois Tigeot  * all copies or substantial portions of the Software.
15926deccbSFrançois Tigeot  *
16926deccbSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17926deccbSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18926deccbSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19926deccbSFrançois Tigeot  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20926deccbSFrançois Tigeot  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21926deccbSFrançois Tigeot  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22926deccbSFrançois Tigeot  * OTHER DEALINGS IN THE SOFTWARE.
23926deccbSFrançois Tigeot  *
24926deccbSFrançois Tigeot  * Authors: Dave Airlie
25926deccbSFrançois Tigeot  *          Alex Deucher
26926deccbSFrançois Tigeot  *          Jerome Glisse
27926deccbSFrançois Tigeot  */
28926deccbSFrançois Tigeot /* RS600 / Radeon X1250/X1270 integrated GPU
29926deccbSFrançois Tigeot  *
30926deccbSFrançois Tigeot  * This file gather function specific to RS600 which is the IGP of
31926deccbSFrançois Tigeot  * the X1250/X1270 family supporting intel CPU (while RS690/RS740
32926deccbSFrançois Tigeot  * is the X1250/X1270 supporting AMD CPU). The display engine are
33926deccbSFrançois Tigeot  * the avivo one, bios is an atombios, 3D block are the one of the
34926deccbSFrançois Tigeot  * R4XX family. The GART is different from the RS400 one and is very
35926deccbSFrançois Tigeot  * close to the one of the R600 family (R600 likely being an evolution
36926deccbSFrançois Tigeot  * of the RS600 GART block).
37926deccbSFrançois Tigeot  */
38926deccbSFrançois Tigeot #include <drm/drmP.h>
39926deccbSFrançois Tigeot #include "radeon.h"
40926deccbSFrançois Tigeot #include "radeon_asic.h"
41c59a5c48SFrançois Tigeot #include "radeon_audio.h"
42926deccbSFrançois Tigeot #include "atom.h"
43926deccbSFrançois Tigeot #include "rs600d.h"
44926deccbSFrançois Tigeot 
45926deccbSFrançois Tigeot #include "rs600_reg_safe.h"
46926deccbSFrançois Tigeot 
47926deccbSFrançois Tigeot static void rs600_gpu_init(struct radeon_device *rdev);
48926deccbSFrançois Tigeot 
49926deccbSFrançois Tigeot static const u32 crtc_offsets[2] =
50926deccbSFrançois Tigeot {
51926deccbSFrançois Tigeot 	0,
52926deccbSFrançois Tigeot 	AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL
53926deccbSFrançois Tigeot };
54926deccbSFrançois Tigeot 
avivo_is_in_vblank(struct radeon_device * rdev,int crtc)55f43cf1b1SMichael Neumann static bool avivo_is_in_vblank(struct radeon_device *rdev, int crtc)
56f43cf1b1SMichael Neumann {
57f43cf1b1SMichael Neumann 	if (RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK)
58f43cf1b1SMichael Neumann 		return true;
59f43cf1b1SMichael Neumann 	else
60f43cf1b1SMichael Neumann 		return false;
61f43cf1b1SMichael Neumann }
62f43cf1b1SMichael Neumann 
avivo_is_counter_moving(struct radeon_device * rdev,int crtc)63f43cf1b1SMichael Neumann static bool avivo_is_counter_moving(struct radeon_device *rdev, int crtc)
64f43cf1b1SMichael Neumann {
65f43cf1b1SMichael Neumann 	u32 pos1, pos2;
66f43cf1b1SMichael Neumann 
67f43cf1b1SMichael Neumann 	pos1 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + crtc_offsets[crtc]);
68f43cf1b1SMichael Neumann 	pos2 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + crtc_offsets[crtc]);
69f43cf1b1SMichael Neumann 
70f43cf1b1SMichael Neumann 	if (pos1 != pos2)
71f43cf1b1SMichael Neumann 		return true;
72f43cf1b1SMichael Neumann 	else
73f43cf1b1SMichael Neumann 		return false;
74f43cf1b1SMichael Neumann }
75f43cf1b1SMichael Neumann 
76f43cf1b1SMichael Neumann /**
77f43cf1b1SMichael Neumann  * avivo_wait_for_vblank - vblank wait asic callback.
78f43cf1b1SMichael Neumann  *
79f43cf1b1SMichael Neumann  * @rdev: radeon_device pointer
80f43cf1b1SMichael Neumann  * @crtc: crtc to wait for vblank on
81f43cf1b1SMichael Neumann  *
82f43cf1b1SMichael Neumann  * Wait for vblank on the requested crtc (r5xx-r7xx).
83f43cf1b1SMichael Neumann  */
avivo_wait_for_vblank(struct radeon_device * rdev,int crtc)84926deccbSFrançois Tigeot void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
85926deccbSFrançois Tigeot {
86f43cf1b1SMichael Neumann 	unsigned i = 0;
87926deccbSFrançois Tigeot 
88926deccbSFrançois Tigeot 	if (crtc >= rdev->num_crtc)
89926deccbSFrançois Tigeot 		return;
90926deccbSFrançois Tigeot 
91f43cf1b1SMichael Neumann 	if (!(RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[crtc]) & AVIVO_CRTC_EN))
92f43cf1b1SMichael Neumann 		return;
93f43cf1b1SMichael Neumann 
94f43cf1b1SMichael Neumann 	/* depending on when we hit vblank, we may be close to active; if so,
95f43cf1b1SMichael Neumann 	 * wait for another frame.
96f43cf1b1SMichael Neumann 	 */
97f43cf1b1SMichael Neumann 	while (avivo_is_in_vblank(rdev, crtc)) {
98f43cf1b1SMichael Neumann 		if (i++ % 100 == 0) {
99f43cf1b1SMichael Neumann 			if (!avivo_is_counter_moving(rdev, crtc))
100926deccbSFrançois Tigeot 				break;
101926deccbSFrançois Tigeot 		}
102f43cf1b1SMichael Neumann 	}
103f43cf1b1SMichael Neumann 
104f43cf1b1SMichael Neumann 	while (!avivo_is_in_vblank(rdev, crtc)) {
105f43cf1b1SMichael Neumann 		if (i++ % 100 == 0) {
106f43cf1b1SMichael Neumann 			if (!avivo_is_counter_moving(rdev, crtc))
107926deccbSFrançois Tigeot 				break;
108926deccbSFrançois Tigeot 		}
109926deccbSFrançois Tigeot 	}
110926deccbSFrançois Tigeot }
111926deccbSFrançois Tigeot 
rs600_page_flip(struct radeon_device * rdev,int crtc_id,u64 crtc_base,bool async)112d78d3a22SFrançois Tigeot void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
113926deccbSFrançois Tigeot {
114926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
115926deccbSFrançois Tigeot 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
116926deccbSFrançois Tigeot 	int i;
117926deccbSFrançois Tigeot 
118926deccbSFrançois Tigeot 	/* Lock the graphics update lock */
119926deccbSFrançois Tigeot 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
120926deccbSFrançois Tigeot 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
121926deccbSFrançois Tigeot 
122926deccbSFrançois Tigeot 	/* update the scanout addresses */
123d78d3a22SFrançois Tigeot 	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
124d78d3a22SFrançois Tigeot 	       async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
125926deccbSFrançois Tigeot 	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
126926deccbSFrançois Tigeot 	       (u32)crtc_base);
127926deccbSFrançois Tigeot 	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
128926deccbSFrançois Tigeot 	       (u32)crtc_base);
129926deccbSFrançois Tigeot 
130926deccbSFrançois Tigeot 	/* Wait for update_pending to go high. */
131926deccbSFrançois Tigeot 	for (i = 0; i < rdev->usec_timeout; i++) {
132926deccbSFrançois Tigeot 		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
133926deccbSFrançois Tigeot 			break;
134c4ef309bSzrj 		udelay(1);
135926deccbSFrançois Tigeot 	}
136926deccbSFrançois Tigeot 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
137926deccbSFrançois Tigeot 
138926deccbSFrançois Tigeot 	/* Unlock the lock, so double-buffering can take place inside vblank */
139926deccbSFrançois Tigeot 	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
140926deccbSFrançois Tigeot 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
141c6f73aabSFrançois Tigeot }
142c6f73aabSFrançois Tigeot 
rs600_page_flip_pending(struct radeon_device * rdev,int crtc_id)143c6f73aabSFrançois Tigeot bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id)
144c6f73aabSFrançois Tigeot {
145c6f73aabSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
146926deccbSFrançois Tigeot 
147926deccbSFrançois Tigeot 	/* Return current update_pending status: */
148c6f73aabSFrançois Tigeot 	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
149c6f73aabSFrançois Tigeot 		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
150c6f73aabSFrançois Tigeot }
151c6f73aabSFrançois Tigeot 
avivo_program_fmt(struct drm_encoder * encoder)152c6f73aabSFrançois Tigeot void avivo_program_fmt(struct drm_encoder *encoder)
153c6f73aabSFrançois Tigeot {
154c6f73aabSFrançois Tigeot 	struct drm_device *dev = encoder->dev;
155c6f73aabSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
156c6f73aabSFrançois Tigeot 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
157c6f73aabSFrançois Tigeot 	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
158c6f73aabSFrançois Tigeot 	int bpc = 0;
159c6f73aabSFrançois Tigeot 	u32 tmp = 0;
160c6f73aabSFrançois Tigeot 	enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE;
161c6f73aabSFrançois Tigeot 
162c6f73aabSFrançois Tigeot 	if (connector) {
163c6f73aabSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
164c6f73aabSFrançois Tigeot 		bpc = radeon_get_monitor_bpc(connector);
165c6f73aabSFrançois Tigeot 		dither = radeon_connector->dither;
166c6f73aabSFrançois Tigeot 	}
167c6f73aabSFrançois Tigeot 
168c6f73aabSFrançois Tigeot 	/* LVDS FMT is set up by atom */
169c6f73aabSFrançois Tigeot 	if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
170c6f73aabSFrançois Tigeot 		return;
171c6f73aabSFrançois Tigeot 
172c6f73aabSFrançois Tigeot 	if (bpc == 0)
173c6f73aabSFrançois Tigeot 		return;
174c6f73aabSFrançois Tigeot 
175c6f73aabSFrançois Tigeot 	switch (bpc) {
176c6f73aabSFrançois Tigeot 	case 6:
177c6f73aabSFrançois Tigeot 		if (dither == RADEON_FMT_DITHER_ENABLE)
178c6f73aabSFrançois Tigeot 			/* XXX sort out optimal dither settings */
179c6f73aabSFrançois Tigeot 			tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
180c6f73aabSFrançois Tigeot 		else
181c6f73aabSFrançois Tigeot 			tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN;
182c6f73aabSFrançois Tigeot 		break;
183c6f73aabSFrançois Tigeot 	case 8:
184c6f73aabSFrançois Tigeot 		if (dither == RADEON_FMT_DITHER_ENABLE)
185c6f73aabSFrançois Tigeot 			/* XXX sort out optimal dither settings */
186c6f73aabSFrançois Tigeot 			tmp |= (AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN |
187c6f73aabSFrançois Tigeot 				AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH);
188c6f73aabSFrançois Tigeot 		else
189c6f73aabSFrançois Tigeot 			tmp |= (AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN |
190c6f73aabSFrançois Tigeot 				AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH);
191c6f73aabSFrançois Tigeot 		break;
192c6f73aabSFrançois Tigeot 	case 10:
193c6f73aabSFrançois Tigeot 	default:
194c6f73aabSFrançois Tigeot 		/* not needed */
195c6f73aabSFrançois Tigeot 		break;
196c6f73aabSFrançois Tigeot 	}
197c6f73aabSFrançois Tigeot 
198c6f73aabSFrançois Tigeot 	switch (radeon_encoder->encoder_id) {
199c6f73aabSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
200c6f73aabSFrançois Tigeot 		WREG32(AVIVO_TMDSA_BIT_DEPTH_CONTROL, tmp);
201c6f73aabSFrançois Tigeot 		break;
202c6f73aabSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
203c6f73aabSFrançois Tigeot 		WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, tmp);
204c6f73aabSFrançois Tigeot 		break;
205c6f73aabSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
206c6f73aabSFrançois Tigeot 		WREG32(AVIVO_DVOA_BIT_DEPTH_CONTROL, tmp);
207c6f73aabSFrançois Tigeot 		break;
208c6f73aabSFrançois Tigeot 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
209c6f73aabSFrançois Tigeot 		WREG32(AVIVO_DDIA_BIT_DEPTH_CONTROL, tmp);
210c6f73aabSFrançois Tigeot 		break;
211c6f73aabSFrançois Tigeot 	default:
212c6f73aabSFrançois Tigeot 		break;
213c6f73aabSFrançois Tigeot 	}
214926deccbSFrançois Tigeot }
215926deccbSFrançois Tigeot 
rs600_pm_misc(struct radeon_device * rdev)216926deccbSFrançois Tigeot void rs600_pm_misc(struct radeon_device *rdev)
217926deccbSFrançois Tigeot {
218926deccbSFrançois Tigeot 	int requested_index = rdev->pm.requested_power_state_index;
219926deccbSFrançois Tigeot 	struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
220926deccbSFrançois Tigeot 	struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
221926deccbSFrançois Tigeot 	u32 tmp, dyn_pwrmgt_sclk_length, dyn_sclk_vol_cntl;
222926deccbSFrançois Tigeot 	u32 hdp_dyn_cntl, /*mc_host_dyn_cntl,*/ dyn_backbias_cntl;
223926deccbSFrançois Tigeot 
224926deccbSFrançois Tigeot 	if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) {
225926deccbSFrançois Tigeot 		if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
226926deccbSFrançois Tigeot 			tmp = RREG32(voltage->gpio.reg);
227926deccbSFrançois Tigeot 			if (voltage->active_high)
228926deccbSFrançois Tigeot 				tmp |= voltage->gpio.mask;
229926deccbSFrançois Tigeot 			else
230926deccbSFrançois Tigeot 				tmp &= ~(voltage->gpio.mask);
231926deccbSFrançois Tigeot 			WREG32(voltage->gpio.reg, tmp);
232926deccbSFrançois Tigeot 			if (voltage->delay)
233c4ef309bSzrj 				udelay(voltage->delay);
234926deccbSFrançois Tigeot 		} else {
235926deccbSFrançois Tigeot 			tmp = RREG32(voltage->gpio.reg);
236926deccbSFrançois Tigeot 			if (voltage->active_high)
237926deccbSFrançois Tigeot 				tmp &= ~voltage->gpio.mask;
238926deccbSFrançois Tigeot 			else
239926deccbSFrançois Tigeot 				tmp |= voltage->gpio.mask;
240926deccbSFrançois Tigeot 			WREG32(voltage->gpio.reg, tmp);
241926deccbSFrançois Tigeot 			if (voltage->delay)
242c4ef309bSzrj 				udelay(voltage->delay);
243926deccbSFrançois Tigeot 		}
244926deccbSFrançois Tigeot 	} else if (voltage->type == VOLTAGE_VDDC)
245926deccbSFrançois Tigeot 		radeon_atom_set_voltage(rdev, voltage->vddc_id, SET_VOLTAGE_TYPE_ASIC_VDDC);
246926deccbSFrançois Tigeot 
247926deccbSFrançois Tigeot 	dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
248926deccbSFrançois Tigeot 	dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
249926deccbSFrançois Tigeot 	dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_LOLEN(0xf);
250926deccbSFrançois Tigeot 	if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) {
251926deccbSFrançois Tigeot 		if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) {
252926deccbSFrançois Tigeot 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(2);
253926deccbSFrançois Tigeot 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(2);
254926deccbSFrançois Tigeot 		} else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) {
255926deccbSFrançois Tigeot 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(4);
256926deccbSFrançois Tigeot 			dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(4);
257926deccbSFrançois Tigeot 		}
258926deccbSFrançois Tigeot 	} else {
259926deccbSFrançois Tigeot 		dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(1);
260926deccbSFrançois Tigeot 		dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(1);
261926deccbSFrançois Tigeot 	}
262926deccbSFrançois Tigeot 	WREG32_PLL(DYN_PWRMGT_SCLK_LENGTH, dyn_pwrmgt_sclk_length);
263926deccbSFrançois Tigeot 
264926deccbSFrançois Tigeot 	dyn_sclk_vol_cntl = RREG32_PLL(DYN_SCLK_VOL_CNTL);
265926deccbSFrançois Tigeot 	if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) {
266926deccbSFrançois Tigeot 		dyn_sclk_vol_cntl |= IO_CG_VOLTAGE_DROP;
267926deccbSFrançois Tigeot 		if (voltage->delay) {
268926deccbSFrançois Tigeot 			dyn_sclk_vol_cntl |= VOLTAGE_DROP_SYNC;
269926deccbSFrançois Tigeot 			dyn_sclk_vol_cntl |= VOLTAGE_DELAY_SEL(voltage->delay);
270926deccbSFrançois Tigeot 		} else
271926deccbSFrançois Tigeot 			dyn_sclk_vol_cntl &= ~VOLTAGE_DROP_SYNC;
272926deccbSFrançois Tigeot 	} else
273926deccbSFrançois Tigeot 		dyn_sclk_vol_cntl &= ~IO_CG_VOLTAGE_DROP;
274926deccbSFrançois Tigeot 	WREG32_PLL(DYN_SCLK_VOL_CNTL, dyn_sclk_vol_cntl);
275926deccbSFrançois Tigeot 
276926deccbSFrançois Tigeot 	hdp_dyn_cntl = RREG32_PLL(HDP_DYN_CNTL);
277926deccbSFrançois Tigeot 	if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN)
278926deccbSFrançois Tigeot 		hdp_dyn_cntl &= ~HDP_FORCEON;
279926deccbSFrançois Tigeot 	else
280926deccbSFrançois Tigeot 		hdp_dyn_cntl |= HDP_FORCEON;
281926deccbSFrançois Tigeot 	WREG32_PLL(HDP_DYN_CNTL, hdp_dyn_cntl);
282926deccbSFrançois Tigeot #if 0
283926deccbSFrançois Tigeot 	/* mc_host_dyn seems to cause hangs from time to time */
284926deccbSFrançois Tigeot 	mc_host_dyn_cntl = RREG32_PLL(MC_HOST_DYN_CNTL);
285926deccbSFrançois Tigeot 	if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN)
286926deccbSFrançois Tigeot 		mc_host_dyn_cntl &= ~MC_HOST_FORCEON;
287926deccbSFrançois Tigeot 	else
288926deccbSFrançois Tigeot 		mc_host_dyn_cntl |= MC_HOST_FORCEON;
289926deccbSFrançois Tigeot 	WREG32_PLL(MC_HOST_DYN_CNTL, mc_host_dyn_cntl);
290926deccbSFrançois Tigeot #endif
291926deccbSFrançois Tigeot 	dyn_backbias_cntl = RREG32_PLL(DYN_BACKBIAS_CNTL);
292926deccbSFrançois Tigeot 	if (ps->misc & ATOM_PM_MISCINFO2_DYNAMIC_BACK_BIAS_EN)
293926deccbSFrançois Tigeot 		dyn_backbias_cntl |= IO_CG_BACKBIAS_EN;
294926deccbSFrançois Tigeot 	else
295926deccbSFrançois Tigeot 		dyn_backbias_cntl &= ~IO_CG_BACKBIAS_EN;
296926deccbSFrançois Tigeot 	WREG32_PLL(DYN_BACKBIAS_CNTL, dyn_backbias_cntl);
297926deccbSFrançois Tigeot 
298926deccbSFrançois Tigeot 	/* set pcie lanes */
299926deccbSFrançois Tigeot 	if ((rdev->flags & RADEON_IS_PCIE) &&
300926deccbSFrançois Tigeot 	    !(rdev->flags & RADEON_IS_IGP) &&
301926deccbSFrançois Tigeot 	    rdev->asic->pm.set_pcie_lanes &&
302926deccbSFrançois Tigeot 	    (ps->pcie_lanes !=
303926deccbSFrançois Tigeot 	     rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
304926deccbSFrançois Tigeot 		radeon_set_pcie_lanes(rdev,
305926deccbSFrançois Tigeot 				      ps->pcie_lanes);
306926deccbSFrançois Tigeot 		DRM_DEBUG("Setting: p: %d\n", ps->pcie_lanes);
307926deccbSFrançois Tigeot 	}
308926deccbSFrançois Tigeot }
309926deccbSFrançois Tigeot 
rs600_pm_prepare(struct radeon_device * rdev)310926deccbSFrançois Tigeot void rs600_pm_prepare(struct radeon_device *rdev)
311926deccbSFrançois Tigeot {
312926deccbSFrançois Tigeot 	struct drm_device *ddev = rdev->ddev;
313926deccbSFrançois Tigeot 	struct drm_crtc *crtc;
314926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc;
315926deccbSFrançois Tigeot 	u32 tmp;
316926deccbSFrançois Tigeot 
317926deccbSFrançois Tigeot 	/* disable any active CRTCs */
318926deccbSFrançois Tigeot 	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
319926deccbSFrançois Tigeot 		radeon_crtc = to_radeon_crtc(crtc);
320926deccbSFrançois Tigeot 		if (radeon_crtc->enabled) {
321926deccbSFrançois Tigeot 			tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset);
322926deccbSFrançois Tigeot 			tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
323926deccbSFrançois Tigeot 			WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
324926deccbSFrançois Tigeot 		}
325926deccbSFrançois Tigeot 	}
326926deccbSFrançois Tigeot }
327926deccbSFrançois Tigeot 
rs600_pm_finish(struct radeon_device * rdev)328926deccbSFrançois Tigeot void rs600_pm_finish(struct radeon_device *rdev)
329926deccbSFrançois Tigeot {
330926deccbSFrançois Tigeot 	struct drm_device *ddev = rdev->ddev;
331926deccbSFrançois Tigeot 	struct drm_crtc *crtc;
332926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc;
333926deccbSFrançois Tigeot 	u32 tmp;
334926deccbSFrançois Tigeot 
335926deccbSFrançois Tigeot 	/* enable any active CRTCs */
336926deccbSFrançois Tigeot 	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
337926deccbSFrançois Tigeot 		radeon_crtc = to_radeon_crtc(crtc);
338926deccbSFrançois Tigeot 		if (radeon_crtc->enabled) {
339926deccbSFrançois Tigeot 			tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset);
340926deccbSFrançois Tigeot 			tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
341926deccbSFrançois Tigeot 			WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
342926deccbSFrançois Tigeot 		}
343926deccbSFrançois Tigeot 	}
344926deccbSFrançois Tigeot }
345926deccbSFrançois Tigeot 
346926deccbSFrançois Tigeot /* hpd for digital panel detect/disconnect */
rs600_hpd_sense(struct radeon_device * rdev,enum radeon_hpd_id hpd)347926deccbSFrançois Tigeot bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
348926deccbSFrançois Tigeot {
349926deccbSFrançois Tigeot 	u32 tmp;
350926deccbSFrançois Tigeot 	bool connected = false;
351926deccbSFrançois Tigeot 
352926deccbSFrançois Tigeot 	switch (hpd) {
353926deccbSFrançois Tigeot 	case RADEON_HPD_1:
354926deccbSFrançois Tigeot 		tmp = RREG32(R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS);
355926deccbSFrançois Tigeot 		if (G_007D04_DC_HOT_PLUG_DETECT1_SENSE(tmp))
356926deccbSFrançois Tigeot 			connected = true;
357926deccbSFrançois Tigeot 		break;
358926deccbSFrançois Tigeot 	case RADEON_HPD_2:
359926deccbSFrançois Tigeot 		tmp = RREG32(R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS);
360926deccbSFrançois Tigeot 		if (G_007D14_DC_HOT_PLUG_DETECT2_SENSE(tmp))
361926deccbSFrançois Tigeot 			connected = true;
362926deccbSFrançois Tigeot 		break;
363926deccbSFrançois Tigeot 	default:
364926deccbSFrançois Tigeot 		break;
365926deccbSFrançois Tigeot 	}
366926deccbSFrançois Tigeot 	return connected;
367926deccbSFrançois Tigeot }
368926deccbSFrançois Tigeot 
rs600_hpd_set_polarity(struct radeon_device * rdev,enum radeon_hpd_id hpd)369926deccbSFrançois Tigeot void rs600_hpd_set_polarity(struct radeon_device *rdev,
370926deccbSFrançois Tigeot 			    enum radeon_hpd_id hpd)
371926deccbSFrançois Tigeot {
372926deccbSFrançois Tigeot 	u32 tmp;
373926deccbSFrançois Tigeot 	bool connected = rs600_hpd_sense(rdev, hpd);
374926deccbSFrançois Tigeot 
375926deccbSFrançois Tigeot 	switch (hpd) {
376926deccbSFrançois Tigeot 	case RADEON_HPD_1:
377926deccbSFrançois Tigeot 		tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
378926deccbSFrançois Tigeot 		if (connected)
379926deccbSFrançois Tigeot 			tmp &= ~S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1);
380926deccbSFrançois Tigeot 		else
381926deccbSFrançois Tigeot 			tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1);
382926deccbSFrançois Tigeot 		WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
383926deccbSFrançois Tigeot 		break;
384926deccbSFrançois Tigeot 	case RADEON_HPD_2:
385926deccbSFrançois Tigeot 		tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
386926deccbSFrançois Tigeot 		if (connected)
387926deccbSFrançois Tigeot 			tmp &= ~S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1);
388926deccbSFrançois Tigeot 		else
389926deccbSFrançois Tigeot 			tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1);
390926deccbSFrançois Tigeot 		WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
391926deccbSFrançois Tigeot 		break;
392926deccbSFrançois Tigeot 	default:
393926deccbSFrançois Tigeot 		break;
394926deccbSFrançois Tigeot 	}
395926deccbSFrançois Tigeot }
396926deccbSFrançois Tigeot 
rs600_hpd_init(struct radeon_device * rdev)397926deccbSFrançois Tigeot void rs600_hpd_init(struct radeon_device *rdev)
398926deccbSFrançois Tigeot {
399926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
400926deccbSFrançois Tigeot 	struct drm_connector *connector;
401926deccbSFrançois Tigeot 	unsigned enable = 0;
402926deccbSFrançois Tigeot 
403926deccbSFrançois Tigeot 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
404926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
405926deccbSFrançois Tigeot 		switch (radeon_connector->hpd.hpd) {
406926deccbSFrançois Tigeot 		case RADEON_HPD_1:
407926deccbSFrançois Tigeot 			WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL,
408926deccbSFrançois Tigeot 			       S_007D00_DC_HOT_PLUG_DETECT1_EN(1));
409926deccbSFrançois Tigeot 			break;
410926deccbSFrançois Tigeot 		case RADEON_HPD_2:
411926deccbSFrançois Tigeot 			WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL,
412926deccbSFrançois Tigeot 			       S_007D10_DC_HOT_PLUG_DETECT2_EN(1));
413926deccbSFrançois Tigeot 			break;
414926deccbSFrançois Tigeot 		default:
415926deccbSFrançois Tigeot 			break;
416926deccbSFrançois Tigeot 		}
417d78d3a22SFrançois Tigeot 		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
418926deccbSFrançois Tigeot 			enable |= 1 << radeon_connector->hpd.hpd;
419926deccbSFrançois Tigeot 		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
420926deccbSFrançois Tigeot 	}
421926deccbSFrançois Tigeot 	radeon_irq_kms_enable_hpd(rdev, enable);
422926deccbSFrançois Tigeot }
423926deccbSFrançois Tigeot 
rs600_hpd_fini(struct radeon_device * rdev)424926deccbSFrançois Tigeot void rs600_hpd_fini(struct radeon_device *rdev)
425926deccbSFrançois Tigeot {
426926deccbSFrançois Tigeot 	struct drm_device *dev = rdev->ddev;
427926deccbSFrançois Tigeot 	struct drm_connector *connector;
428926deccbSFrançois Tigeot 	unsigned disable = 0;
429926deccbSFrançois Tigeot 
430926deccbSFrançois Tigeot 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
431926deccbSFrançois Tigeot 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
432926deccbSFrançois Tigeot 		switch (radeon_connector->hpd.hpd) {
433926deccbSFrançois Tigeot 		case RADEON_HPD_1:
434926deccbSFrançois Tigeot 			WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL,
435926deccbSFrançois Tigeot 			       S_007D00_DC_HOT_PLUG_DETECT1_EN(0));
436926deccbSFrançois Tigeot 			break;
437926deccbSFrançois Tigeot 		case RADEON_HPD_2:
438926deccbSFrançois Tigeot 			WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL,
439926deccbSFrançois Tigeot 			       S_007D10_DC_HOT_PLUG_DETECT2_EN(0));
440926deccbSFrançois Tigeot 			break;
441926deccbSFrançois Tigeot 		default:
442926deccbSFrançois Tigeot 			break;
443926deccbSFrançois Tigeot 		}
444d78d3a22SFrançois Tigeot 		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
445926deccbSFrançois Tigeot 			disable |= 1 << radeon_connector->hpd.hpd;
446926deccbSFrançois Tigeot 	}
447926deccbSFrançois Tigeot 	radeon_irq_kms_disable_hpd(rdev, disable);
448926deccbSFrançois Tigeot }
449926deccbSFrançois Tigeot 
rs600_asic_reset(struct radeon_device * rdev,bool hard)450d78d3a22SFrançois Tigeot int rs600_asic_reset(struct radeon_device *rdev, bool hard)
451926deccbSFrançois Tigeot {
452926deccbSFrançois Tigeot 	struct rv515_mc_save save;
453926deccbSFrançois Tigeot 	u32 status, tmp;
454926deccbSFrançois Tigeot 	int ret = 0;
455926deccbSFrançois Tigeot 
456926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
457926deccbSFrançois Tigeot 	if (!G_000E40_GUI_ACTIVE(status)) {
458926deccbSFrançois Tigeot 		return 0;
459926deccbSFrançois Tigeot 	}
460926deccbSFrançois Tigeot 	/* Stops all mc clients */
461926deccbSFrançois Tigeot 	rv515_mc_stop(rdev, &save);
462926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
463926deccbSFrançois Tigeot 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
464926deccbSFrançois Tigeot 	/* stop CP */
465926deccbSFrançois Tigeot 	WREG32(RADEON_CP_CSQ_CNTL, 0);
466926deccbSFrançois Tigeot 	tmp = RREG32(RADEON_CP_RB_CNTL);
467926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
468926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_RPTR_WR, 0);
469926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_WPTR, 0);
470926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_CNTL, tmp);
471fb572d17SFrançois Tigeot 	pci_save_state(device_get_parent(rdev->dev->bsddev));
472926deccbSFrançois Tigeot 	/* disable bus mastering */
473fb572d17SFrançois Tigeot 	pci_disable_busmaster(rdev->dev->bsddev);
474c4ef309bSzrj 	mdelay(1);
475926deccbSFrançois Tigeot 	/* reset GA+VAP */
476926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
477926deccbSFrançois Tigeot 					S_0000F0_SOFT_RESET_GA(1));
478926deccbSFrançois Tigeot 	RREG32(R_0000F0_RBBM_SOFT_RESET);
479c4ef309bSzrj 	mdelay(500);
480926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
481c4ef309bSzrj 	mdelay(1);
482926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
483926deccbSFrançois Tigeot 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
484926deccbSFrançois Tigeot 	/* reset CP */
485926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
486926deccbSFrançois Tigeot 	RREG32(R_0000F0_RBBM_SOFT_RESET);
487c4ef309bSzrj 	mdelay(500);
488926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
489c4ef309bSzrj 	mdelay(1);
490926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
491926deccbSFrançois Tigeot 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
492926deccbSFrançois Tigeot 	/* reset MC */
493926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1));
494926deccbSFrançois Tigeot 	RREG32(R_0000F0_RBBM_SOFT_RESET);
495c4ef309bSzrj 	mdelay(500);
496926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
497c4ef309bSzrj 	mdelay(1);
498926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
499926deccbSFrançois Tigeot 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
500926deccbSFrançois Tigeot 	/* restore PCI & busmastering */
501fb572d17SFrançois Tigeot 	pci_restore_state(device_get_parent(rdev->dev->bsddev));
502926deccbSFrançois Tigeot 	/* Check if GPU is idle */
503926deccbSFrançois Tigeot 	if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
504926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed to reset GPU\n");
505926deccbSFrançois Tigeot 		ret = -1;
506926deccbSFrançois Tigeot 	} else
507926deccbSFrançois Tigeot 		dev_info(rdev->dev, "GPU reset succeed\n");
508926deccbSFrançois Tigeot 	rv515_mc_resume(rdev, &save);
509926deccbSFrançois Tigeot 	return ret;
510926deccbSFrançois Tigeot }
511926deccbSFrançois Tigeot 
512926deccbSFrançois Tigeot /*
513926deccbSFrançois Tigeot  * GART.
514926deccbSFrançois Tigeot  */
rs600_gart_tlb_flush(struct radeon_device * rdev)515926deccbSFrançois Tigeot void rs600_gart_tlb_flush(struct radeon_device *rdev)
516926deccbSFrançois Tigeot {
517926deccbSFrançois Tigeot 	uint32_t tmp;
518926deccbSFrançois Tigeot 
519926deccbSFrançois Tigeot 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
520926deccbSFrançois Tigeot 	tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE;
521926deccbSFrançois Tigeot 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
522926deccbSFrançois Tigeot 
523926deccbSFrançois Tigeot 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
524926deccbSFrançois Tigeot 	tmp |= S_000100_INVALIDATE_ALL_L1_TLBS(1) | S_000100_INVALIDATE_L2_CACHE(1);
525926deccbSFrançois Tigeot 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
526926deccbSFrançois Tigeot 
527926deccbSFrançois Tigeot 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
528926deccbSFrançois Tigeot 	tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE;
529926deccbSFrançois Tigeot 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
530926deccbSFrançois Tigeot 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
531926deccbSFrançois Tigeot }
532926deccbSFrançois Tigeot 
rs600_gart_init(struct radeon_device * rdev)533926deccbSFrançois Tigeot static int rs600_gart_init(struct radeon_device *rdev)
534926deccbSFrançois Tigeot {
535926deccbSFrançois Tigeot 	int r;
536926deccbSFrançois Tigeot 
537926deccbSFrançois Tigeot 	if (rdev->gart.robj) {
538c4ef309bSzrj 		WARN(1, "RS600 GART already initialized\n");
539926deccbSFrançois Tigeot 		return 0;
540926deccbSFrançois Tigeot 	}
541926deccbSFrançois Tigeot 	/* Initialize common gart structure */
542926deccbSFrançois Tigeot 	r = radeon_gart_init(rdev);
543926deccbSFrançois Tigeot 	if (r) {
544926deccbSFrançois Tigeot 		return r;
545926deccbSFrançois Tigeot 	}
546926deccbSFrançois Tigeot 	rdev->gart.table_size = rdev->gart.num_gpu_pages * 8;
547926deccbSFrançois Tigeot 	return radeon_gart_table_vram_alloc(rdev);
548926deccbSFrançois Tigeot }
549926deccbSFrançois Tigeot 
rs600_gart_enable(struct radeon_device * rdev)550926deccbSFrançois Tigeot static int rs600_gart_enable(struct radeon_device *rdev)
551926deccbSFrançois Tigeot {
552926deccbSFrançois Tigeot 	u32 tmp;
553926deccbSFrançois Tigeot 	int r, i;
554926deccbSFrançois Tigeot 
555926deccbSFrançois Tigeot 	if (rdev->gart.robj == NULL) {
556926deccbSFrançois Tigeot 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
557926deccbSFrançois Tigeot 		return -EINVAL;
558926deccbSFrançois Tigeot 	}
559926deccbSFrançois Tigeot 	r = radeon_gart_table_vram_pin(rdev);
560926deccbSFrançois Tigeot 	if (r)
561926deccbSFrançois Tigeot 		return r;
562926deccbSFrançois Tigeot 	/* Enable bus master */
563926deccbSFrançois Tigeot 	tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
564926deccbSFrançois Tigeot 	WREG32(RADEON_BUS_CNTL, tmp);
565926deccbSFrançois Tigeot 	/* FIXME: setup default page */
566926deccbSFrançois Tigeot 	WREG32_MC(R_000100_MC_PT0_CNTL,
567926deccbSFrançois Tigeot 		  (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) |
568926deccbSFrançois Tigeot 		   S_000100_EFFECTIVE_L2_QUEUE_SIZE(6)));
569926deccbSFrançois Tigeot 
570926deccbSFrançois Tigeot 	for (i = 0; i < 19; i++) {
571926deccbSFrançois Tigeot 		WREG32_MC(R_00016C_MC_PT0_CLIENT0_CNTL + i,
572926deccbSFrançois Tigeot 			  S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) |
573926deccbSFrançois Tigeot 			  S_00016C_SYSTEM_ACCESS_MODE_MASK(
574926deccbSFrançois Tigeot 				  V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS) |
575926deccbSFrançois Tigeot 			  S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(
576926deccbSFrançois Tigeot 				  V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH) |
577926deccbSFrançois Tigeot 			  S_00016C_EFFECTIVE_L1_CACHE_SIZE(3) |
578926deccbSFrançois Tigeot 			  S_00016C_ENABLE_FRAGMENT_PROCESSING(1) |
579926deccbSFrançois Tigeot 			  S_00016C_EFFECTIVE_L1_QUEUE_SIZE(3));
580926deccbSFrançois Tigeot 	}
581926deccbSFrançois Tigeot 	/* enable first context */
582926deccbSFrançois Tigeot 	WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL,
583926deccbSFrançois Tigeot 		  S_000102_ENABLE_PAGE_TABLE(1) |
584926deccbSFrançois Tigeot 		  S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT));
585926deccbSFrançois Tigeot 
586926deccbSFrançois Tigeot 	/* disable all other contexts */
587926deccbSFrançois Tigeot 	for (i = 1; i < 8; i++)
588926deccbSFrançois Tigeot 		WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL + i, 0);
589926deccbSFrançois Tigeot 
590926deccbSFrançois Tigeot 	/* setup the page table */
591926deccbSFrançois Tigeot 	WREG32_MC(R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
592926deccbSFrançois Tigeot 		  rdev->gart.table_addr);
593926deccbSFrançois Tigeot 	WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start);
594926deccbSFrançois Tigeot 	WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end);
595926deccbSFrançois Tigeot 	WREG32_MC(R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
596926deccbSFrançois Tigeot 
597926deccbSFrançois Tigeot 	/* System context maps to VRAM space */
598926deccbSFrançois Tigeot 	WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start);
599926deccbSFrançois Tigeot 	WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end);
600926deccbSFrançois Tigeot 
601926deccbSFrançois Tigeot 	/* enable page tables */
602926deccbSFrançois Tigeot 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
603926deccbSFrançois Tigeot 	WREG32_MC(R_000100_MC_PT0_CNTL, (tmp | S_000100_ENABLE_PT(1)));
604926deccbSFrançois Tigeot 	tmp = RREG32_MC(R_000009_MC_CNTL1);
605926deccbSFrançois Tigeot 	WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1)));
606926deccbSFrançois Tigeot 	rs600_gart_tlb_flush(rdev);
607926deccbSFrançois Tigeot 	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
608926deccbSFrançois Tigeot 		 (unsigned)(rdev->mc.gtt_size >> 20),
609926deccbSFrançois Tigeot 		 (unsigned long long)rdev->gart.table_addr);
610926deccbSFrançois Tigeot 	rdev->gart.ready = true;
611926deccbSFrançois Tigeot 	return 0;
612926deccbSFrançois Tigeot }
613926deccbSFrançois Tigeot 
rs600_gart_disable(struct radeon_device * rdev)614926deccbSFrançois Tigeot static void rs600_gart_disable(struct radeon_device *rdev)
615926deccbSFrançois Tigeot {
616926deccbSFrançois Tigeot 	u32 tmp;
617926deccbSFrançois Tigeot 
618926deccbSFrançois Tigeot 	/* FIXME: disable out of gart access */
619926deccbSFrançois Tigeot 	WREG32_MC(R_000100_MC_PT0_CNTL, 0);
620926deccbSFrançois Tigeot 	tmp = RREG32_MC(R_000009_MC_CNTL1);
621926deccbSFrançois Tigeot 	WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
622926deccbSFrançois Tigeot 	radeon_gart_table_vram_unpin(rdev);
623926deccbSFrançois Tigeot }
624926deccbSFrançois Tigeot 
rs600_gart_fini(struct radeon_device * rdev)625926deccbSFrançois Tigeot static void rs600_gart_fini(struct radeon_device *rdev)
626926deccbSFrançois Tigeot {
627926deccbSFrançois Tigeot 	radeon_gart_fini(rdev);
628926deccbSFrançois Tigeot 	rs600_gart_disable(rdev);
629926deccbSFrançois Tigeot 	radeon_gart_table_vram_free(rdev);
630926deccbSFrançois Tigeot }
631926deccbSFrançois Tigeot 
rs600_gart_get_page_entry(uint64_t addr,uint32_t flags)6327dcf36dcSFrançois Tigeot uint64_t rs600_gart_get_page_entry(uint64_t addr, uint32_t flags)
633926deccbSFrançois Tigeot {
634926deccbSFrançois Tigeot 	addr = addr & 0xFFFFFFFFFFFFF000ULL;
635c6f73aabSFrançois Tigeot 	addr |= R600_PTE_SYSTEM;
636c6f73aabSFrançois Tigeot 	if (flags & RADEON_GART_PAGE_VALID)
637c6f73aabSFrançois Tigeot 		addr |= R600_PTE_VALID;
638c6f73aabSFrançois Tigeot 	if (flags & RADEON_GART_PAGE_READ)
639c6f73aabSFrançois Tigeot 		addr |= R600_PTE_READABLE;
640c6f73aabSFrançois Tigeot 	if (flags & RADEON_GART_PAGE_WRITE)
641c6f73aabSFrançois Tigeot 		addr |= R600_PTE_WRITEABLE;
642c6f73aabSFrançois Tigeot 	if (flags & RADEON_GART_PAGE_SNOOP)
643c6f73aabSFrançois Tigeot 		addr |= R600_PTE_SNOOPED;
6447dcf36dcSFrançois Tigeot 	return addr;
6457dcf36dcSFrançois Tigeot }
6467dcf36dcSFrançois Tigeot 
rs600_gart_set_page(struct radeon_device * rdev,unsigned i,uint64_t entry)6477dcf36dcSFrançois Tigeot void rs600_gart_set_page(struct radeon_device *rdev, unsigned i,
6487dcf36dcSFrançois Tigeot 			 uint64_t entry)
6497dcf36dcSFrançois Tigeot {
6507dcf36dcSFrançois Tigeot 	void __iomem *ptr = (void *)rdev->gart.ptr;
6517dcf36dcSFrançois Tigeot 	writeq(entry, (uint8_t *)ptr + (i * 8));
652926deccbSFrançois Tigeot }
653926deccbSFrançois Tigeot 
rs600_irq_set(struct radeon_device * rdev)654926deccbSFrançois Tigeot int rs600_irq_set(struct radeon_device *rdev)
655926deccbSFrançois Tigeot {
656926deccbSFrançois Tigeot 	uint32_t tmp = 0;
657926deccbSFrançois Tigeot 	uint32_t mode_int = 0;
658926deccbSFrançois Tigeot 	u32 hpd1 = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL) &
659926deccbSFrançois Tigeot 		~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1);
660926deccbSFrançois Tigeot 	u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) &
661926deccbSFrançois Tigeot 		~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
662926deccbSFrançois Tigeot 	u32 hdmi0;
663926deccbSFrançois Tigeot 	if (ASIC_IS_DCE2(rdev))
664926deccbSFrançois Tigeot 		hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) &
665926deccbSFrançois Tigeot 			~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1);
666926deccbSFrançois Tigeot 	else
667926deccbSFrançois Tigeot 		hdmi0 = 0;
668926deccbSFrançois Tigeot 
669926deccbSFrançois Tigeot 	if (!rdev->irq.installed) {
670c4ef309bSzrj 		WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
671926deccbSFrançois Tigeot 		WREG32(R_000040_GEN_INT_CNTL, 0);
672926deccbSFrançois Tigeot 		return -EINVAL;
673926deccbSFrançois Tigeot 	}
674926deccbSFrançois Tigeot 	if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
675926deccbSFrançois Tigeot 		tmp |= S_000040_SW_INT_EN(1);
676926deccbSFrançois Tigeot 	}
677926deccbSFrançois Tigeot 	if (rdev->irq.crtc_vblank_int[0] ||
678926deccbSFrançois Tigeot 	    atomic_read(&rdev->irq.pflip[0])) {
679926deccbSFrançois Tigeot 		mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1);
680926deccbSFrançois Tigeot 	}
681926deccbSFrançois Tigeot 	if (rdev->irq.crtc_vblank_int[1] ||
682926deccbSFrançois Tigeot 	    atomic_read(&rdev->irq.pflip[1])) {
683926deccbSFrançois Tigeot 		mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1);
684926deccbSFrançois Tigeot 	}
685926deccbSFrançois Tigeot 	if (rdev->irq.hpd[0]) {
686926deccbSFrançois Tigeot 		hpd1 |= S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1);
687926deccbSFrançois Tigeot 	}
688926deccbSFrançois Tigeot 	if (rdev->irq.hpd[1]) {
689926deccbSFrançois Tigeot 		hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
690926deccbSFrançois Tigeot 	}
691926deccbSFrançois Tigeot 	if (rdev->irq.afmt[0]) {
692926deccbSFrançois Tigeot 		hdmi0 |= S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1);
693926deccbSFrançois Tigeot 	}
694926deccbSFrançois Tigeot 	WREG32(R_000040_GEN_INT_CNTL, tmp);
695926deccbSFrançois Tigeot 	WREG32(R_006540_DxMODE_INT_MASK, mode_int);
696926deccbSFrançois Tigeot 	WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
697926deccbSFrançois Tigeot 	WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
698926deccbSFrançois Tigeot 	if (ASIC_IS_DCE2(rdev))
699926deccbSFrançois Tigeot 		WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
7007dcf36dcSFrançois Tigeot 
7017dcf36dcSFrançois Tigeot 	/* posting read */
7027dcf36dcSFrançois Tigeot 	RREG32(R_000040_GEN_INT_CNTL);
7037dcf36dcSFrançois Tigeot 
704926deccbSFrançois Tigeot 	return 0;
705926deccbSFrançois Tigeot }
706926deccbSFrançois Tigeot 
rs600_irq_ack(struct radeon_device * rdev)707926deccbSFrançois Tigeot static inline u32 rs600_irq_ack(struct radeon_device *rdev)
708926deccbSFrançois Tigeot {
709926deccbSFrançois Tigeot 	uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS);
710926deccbSFrançois Tigeot 	uint32_t irq_mask = S_000044_SW_INT(1);
711926deccbSFrançois Tigeot 	u32 tmp;
712926deccbSFrançois Tigeot 
713926deccbSFrançois Tigeot 	if (G_000044_DISPLAY_INT_STAT(irqs)) {
714926deccbSFrançois Tigeot 		rdev->irq.stat_regs.r500.disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
715926deccbSFrançois Tigeot 		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
716926deccbSFrançois Tigeot 			WREG32(R_006534_D1MODE_VBLANK_STATUS,
717926deccbSFrançois Tigeot 				S_006534_D1MODE_VBLANK_ACK(1));
718926deccbSFrançois Tigeot 		}
719926deccbSFrançois Tigeot 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
720926deccbSFrançois Tigeot 			WREG32(R_006D34_D2MODE_VBLANK_STATUS,
721926deccbSFrançois Tigeot 				S_006D34_D2MODE_VBLANK_ACK(1));
722926deccbSFrançois Tigeot 		}
723926deccbSFrançois Tigeot 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
724926deccbSFrançois Tigeot 			tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
725926deccbSFrançois Tigeot 			tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1);
726926deccbSFrançois Tigeot 			WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
727926deccbSFrançois Tigeot 		}
728926deccbSFrançois Tigeot 		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
729926deccbSFrançois Tigeot 			tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
730926deccbSFrançois Tigeot 			tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1);
731926deccbSFrançois Tigeot 			WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
732926deccbSFrançois Tigeot 		}
733926deccbSFrançois Tigeot 	} else {
734926deccbSFrançois Tigeot 		rdev->irq.stat_regs.r500.disp_int = 0;
735926deccbSFrançois Tigeot 	}
736926deccbSFrançois Tigeot 
737926deccbSFrançois Tigeot 	if (ASIC_IS_DCE2(rdev)) {
738926deccbSFrançois Tigeot 		rdev->irq.stat_regs.r500.hdmi0_status = RREG32(R_007404_HDMI0_STATUS) &
739926deccbSFrançois Tigeot 			S_007404_HDMI0_AZ_FORMAT_WTRIG(1);
740926deccbSFrançois Tigeot 		if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) {
741926deccbSFrançois Tigeot 			tmp = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL);
742926deccbSFrançois Tigeot 			tmp |= S_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(1);
743926deccbSFrançois Tigeot 			WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, tmp);
744926deccbSFrançois Tigeot 		}
745926deccbSFrançois Tigeot 	} else
746926deccbSFrançois Tigeot 		rdev->irq.stat_regs.r500.hdmi0_status = 0;
747926deccbSFrançois Tigeot 
748926deccbSFrançois Tigeot 	if (irqs) {
749926deccbSFrançois Tigeot 		WREG32(R_000044_GEN_INT_STATUS, irqs);
750926deccbSFrançois Tigeot 	}
751926deccbSFrançois Tigeot 	return irqs & irq_mask;
752926deccbSFrançois Tigeot }
753926deccbSFrançois Tigeot 
rs600_irq_disable(struct radeon_device * rdev)754926deccbSFrançois Tigeot void rs600_irq_disable(struct radeon_device *rdev)
755926deccbSFrançois Tigeot {
756926deccbSFrançois Tigeot 	u32 hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) &
757926deccbSFrançois Tigeot 		~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1);
758926deccbSFrançois Tigeot 	WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
759926deccbSFrançois Tigeot 	WREG32(R_000040_GEN_INT_CNTL, 0);
760926deccbSFrançois Tigeot 	WREG32(R_006540_DxMODE_INT_MASK, 0);
761926deccbSFrançois Tigeot 	/* Wait and acknowledge irq */
762c4ef309bSzrj 	mdelay(1);
763926deccbSFrançois Tigeot 	rs600_irq_ack(rdev);
764926deccbSFrançois Tigeot }
765926deccbSFrançois Tigeot 
rs600_irq_process(struct radeon_device * rdev)766926deccbSFrançois Tigeot irqreturn_t rs600_irq_process(struct radeon_device *rdev)
767926deccbSFrançois Tigeot {
768926deccbSFrançois Tigeot 	u32 status, msi_rearm;
769926deccbSFrançois Tigeot 	bool queue_hotplug = false;
770926deccbSFrançois Tigeot 	bool queue_hdmi = false;
771926deccbSFrançois Tigeot 
772926deccbSFrançois Tigeot 	status = rs600_irq_ack(rdev);
773926deccbSFrançois Tigeot 	if (!status &&
774926deccbSFrançois Tigeot 	    !rdev->irq.stat_regs.r500.disp_int &&
775926deccbSFrançois Tigeot 	    !rdev->irq.stat_regs.r500.hdmi0_status) {
776926deccbSFrançois Tigeot 		return IRQ_NONE;
777926deccbSFrançois Tigeot 	}
778926deccbSFrançois Tigeot 	while (status ||
779926deccbSFrançois Tigeot 	       rdev->irq.stat_regs.r500.disp_int ||
780926deccbSFrançois Tigeot 	       rdev->irq.stat_regs.r500.hdmi0_status) {
781926deccbSFrançois Tigeot 		/* SW interrupt */
782926deccbSFrançois Tigeot 		if (G_000044_SW_INT(status)) {
783926deccbSFrançois Tigeot 			radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
784926deccbSFrançois Tigeot 		}
785926deccbSFrançois Tigeot 		/* Vertical blank interrupts */
786926deccbSFrançois Tigeot 		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
787926deccbSFrançois Tigeot 			if (rdev->irq.crtc_vblank_int[0]) {
788926deccbSFrançois Tigeot 				drm_handle_vblank(rdev->ddev, 0);
789926deccbSFrançois Tigeot 				rdev->pm.vblank_sync = true;
790c4ef309bSzrj 				wake_up(&rdev->irq.vblank_queue);
791926deccbSFrançois Tigeot 			}
792926deccbSFrançois Tigeot 			if (atomic_read(&rdev->irq.pflip[0]))
793c6f73aabSFrançois Tigeot 				radeon_crtc_handle_vblank(rdev, 0);
794926deccbSFrançois Tigeot 		}
795926deccbSFrançois Tigeot 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
796926deccbSFrançois Tigeot 			if (rdev->irq.crtc_vblank_int[1]) {
797926deccbSFrançois Tigeot 				drm_handle_vblank(rdev->ddev, 1);
798926deccbSFrançois Tigeot 				rdev->pm.vblank_sync = true;
799c4ef309bSzrj 				wake_up(&rdev->irq.vblank_queue);
800926deccbSFrançois Tigeot 			}
801926deccbSFrançois Tigeot 			if (atomic_read(&rdev->irq.pflip[1]))
802c6f73aabSFrançois Tigeot 				radeon_crtc_handle_vblank(rdev, 1);
803926deccbSFrançois Tigeot 		}
804926deccbSFrançois Tigeot 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
805926deccbSFrançois Tigeot 			queue_hotplug = true;
806926deccbSFrançois Tigeot 			DRM_DEBUG("HPD1\n");
807926deccbSFrançois Tigeot 		}
808926deccbSFrançois Tigeot 		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
809926deccbSFrançois Tigeot 			queue_hotplug = true;
810926deccbSFrançois Tigeot 			DRM_DEBUG("HPD2\n");
811926deccbSFrançois Tigeot 		}
812926deccbSFrançois Tigeot 		if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) {
813926deccbSFrançois Tigeot 			queue_hdmi = true;
814926deccbSFrançois Tigeot 			DRM_DEBUG("HDMI0\n");
815926deccbSFrançois Tigeot 		}
816926deccbSFrançois Tigeot 		status = rs600_irq_ack(rdev);
817926deccbSFrançois Tigeot 	}
818926deccbSFrançois Tigeot 	if (queue_hotplug)
819c59a5c48SFrançois Tigeot 		schedule_delayed_work(&rdev->hotplug_work, 0);
820926deccbSFrançois Tigeot 	if (queue_hdmi)
8212c5cc6b9SFrançois Tigeot 		schedule_work(&rdev->audio_work);
822926deccbSFrançois Tigeot 	if (rdev->msi_enabled) {
823926deccbSFrançois Tigeot 		switch (rdev->family) {
824926deccbSFrançois Tigeot 		case CHIP_RS600:
825926deccbSFrançois Tigeot 		case CHIP_RS690:
826926deccbSFrançois Tigeot 		case CHIP_RS740:
827926deccbSFrançois Tigeot 			msi_rearm = RREG32(RADEON_BUS_CNTL) & ~RS600_MSI_REARM;
828926deccbSFrançois Tigeot 			WREG32(RADEON_BUS_CNTL, msi_rearm);
829926deccbSFrançois Tigeot 			WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM);
830926deccbSFrançois Tigeot 			break;
831926deccbSFrançois Tigeot 		default:
832926deccbSFrançois Tigeot 			WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
833926deccbSFrançois Tigeot 			break;
834926deccbSFrançois Tigeot 		}
835926deccbSFrançois Tigeot 	}
836926deccbSFrançois Tigeot 	return IRQ_HANDLED;
837926deccbSFrançois Tigeot }
838926deccbSFrançois Tigeot 
rs600_get_vblank_counter(struct radeon_device * rdev,int crtc)839926deccbSFrançois Tigeot u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc)
840926deccbSFrançois Tigeot {
841926deccbSFrançois Tigeot 	if (crtc == 0)
842926deccbSFrançois Tigeot 		return RREG32(R_0060A4_D1CRTC_STATUS_FRAME_COUNT);
843926deccbSFrançois Tigeot 	else
844926deccbSFrançois Tigeot 		return RREG32(R_0068A4_D2CRTC_STATUS_FRAME_COUNT);
845926deccbSFrançois Tigeot }
846926deccbSFrançois Tigeot 
rs600_mc_wait_for_idle(struct radeon_device * rdev)847926deccbSFrançois Tigeot int rs600_mc_wait_for_idle(struct radeon_device *rdev)
848926deccbSFrançois Tigeot {
849926deccbSFrançois Tigeot 	unsigned i;
850926deccbSFrançois Tigeot 
851926deccbSFrançois Tigeot 	for (i = 0; i < rdev->usec_timeout; i++) {
852926deccbSFrançois Tigeot 		if (G_000000_MC_IDLE(RREG32_MC(R_000000_MC_STATUS)))
853926deccbSFrançois Tigeot 			return 0;
854c4ef309bSzrj 		udelay(1);
855926deccbSFrançois Tigeot 	}
856926deccbSFrançois Tigeot 	return -1;
857926deccbSFrançois Tigeot }
858926deccbSFrançois Tigeot 
rs600_gpu_init(struct radeon_device * rdev)859926deccbSFrançois Tigeot static void rs600_gpu_init(struct radeon_device *rdev)
860926deccbSFrançois Tigeot {
861926deccbSFrançois Tigeot 	r420_pipes_init(rdev);
862926deccbSFrançois Tigeot 	/* Wait for mc idle */
863926deccbSFrançois Tigeot 	if (rs600_mc_wait_for_idle(rdev))
864926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
865926deccbSFrançois Tigeot }
866926deccbSFrançois Tigeot 
rs600_mc_init(struct radeon_device * rdev)867926deccbSFrançois Tigeot static void rs600_mc_init(struct radeon_device *rdev)
868926deccbSFrançois Tigeot {
869926deccbSFrançois Tigeot 	u64 base;
870926deccbSFrançois Tigeot 
8714a26d795SImre Vadasz 	rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
8724a26d795SImre Vadasz 	rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
873926deccbSFrançois Tigeot 	rdev->mc.vram_is_ddr = true;
874926deccbSFrançois Tigeot 	rdev->mc.vram_width = 128;
875926deccbSFrançois Tigeot 	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
876926deccbSFrançois Tigeot 	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
877926deccbSFrançois Tigeot 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
878926deccbSFrançois Tigeot 	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
879926deccbSFrançois Tigeot 	base = RREG32_MC(R_000004_MC_FB_LOCATION);
880926deccbSFrançois Tigeot 	base = G_000004_MC_FB_START(base) << 16;
881926deccbSFrançois Tigeot 	radeon_vram_location(rdev, &rdev->mc, base);
882926deccbSFrançois Tigeot 	rdev->mc.gtt_base_align = 0;
883926deccbSFrançois Tigeot 	radeon_gtt_location(rdev, &rdev->mc);
884926deccbSFrançois Tigeot 	radeon_update_bandwidth_info(rdev);
885926deccbSFrançois Tigeot }
886926deccbSFrançois Tigeot 
rs600_bandwidth_update(struct radeon_device * rdev)887926deccbSFrançois Tigeot void rs600_bandwidth_update(struct radeon_device *rdev)
888926deccbSFrançois Tigeot {
889926deccbSFrançois Tigeot 	struct drm_display_mode *mode0 = NULL;
890926deccbSFrançois Tigeot 	struct drm_display_mode *mode1 = NULL;
891926deccbSFrançois Tigeot 	u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt;
892926deccbSFrançois Tigeot 	/* FIXME: implement full support */
893926deccbSFrançois Tigeot 
894591d5043SFrançois Tigeot 	if (!rdev->mode_info.mode_config_initialized)
895591d5043SFrançois Tigeot 		return;
896591d5043SFrançois Tigeot 
897926deccbSFrançois Tigeot 	radeon_update_display_priority(rdev);
898926deccbSFrançois Tigeot 
899926deccbSFrançois Tigeot 	if (rdev->mode_info.crtcs[0]->base.enabled)
900926deccbSFrançois Tigeot 		mode0 = &rdev->mode_info.crtcs[0]->base.mode;
901926deccbSFrançois Tigeot 	if (rdev->mode_info.crtcs[1]->base.enabled)
902926deccbSFrançois Tigeot 		mode1 = &rdev->mode_info.crtcs[1]->base.mode;
903926deccbSFrançois Tigeot 
904926deccbSFrançois Tigeot 	rs690_line_buffer_adjust(rdev, mode0, mode1);
905926deccbSFrançois Tigeot 
906926deccbSFrançois Tigeot 	if (rdev->disp_priority == 2) {
907926deccbSFrançois Tigeot 		d1mode_priority_a_cnt = RREG32(R_006548_D1MODE_PRIORITY_A_CNT);
908926deccbSFrançois Tigeot 		d2mode_priority_a_cnt = RREG32(R_006D48_D2MODE_PRIORITY_A_CNT);
909926deccbSFrançois Tigeot 		d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
910926deccbSFrançois Tigeot 		d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
911926deccbSFrançois Tigeot 		WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
912926deccbSFrançois Tigeot 		WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
913926deccbSFrançois Tigeot 		WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
914926deccbSFrançois Tigeot 		WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
915926deccbSFrançois Tigeot 	}
916926deccbSFrançois Tigeot }
917926deccbSFrançois Tigeot 
rs600_mc_rreg(struct radeon_device * rdev,uint32_t reg)918926deccbSFrançois Tigeot uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg)
919926deccbSFrançois Tigeot {
920c6f73aabSFrançois Tigeot 	u32 r;
921c6f73aabSFrançois Tigeot 
922*ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->mc_idx_lock, LK_EXCLUSIVE);
923926deccbSFrançois Tigeot 	WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) |
924926deccbSFrançois Tigeot 		S_000070_MC_IND_CITF_ARB0(1));
925c6f73aabSFrançois Tigeot 	r = RREG32(R_000074_MC_IND_DATA);
926*ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->mc_idx_lock, LK_RELEASE);
927c6f73aabSFrançois Tigeot 	return r;
928926deccbSFrançois Tigeot }
929926deccbSFrançois Tigeot 
rs600_mc_wreg(struct radeon_device * rdev,uint32_t reg,uint32_t v)930926deccbSFrançois Tigeot void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
931926deccbSFrançois Tigeot {
932*ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->mc_idx_lock, LK_EXCLUSIVE);
933926deccbSFrançois Tigeot 	WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) |
934926deccbSFrançois Tigeot 		S_000070_MC_IND_CITF_ARB0(1) | S_000070_MC_IND_WR_EN(1));
935926deccbSFrançois Tigeot 	WREG32(R_000074_MC_IND_DATA, v);
936*ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->mc_idx_lock, LK_RELEASE);
937926deccbSFrançois Tigeot }
938926deccbSFrançois Tigeot 
rs600_debugfs(struct radeon_device * rdev)939926deccbSFrançois Tigeot static void rs600_debugfs(struct radeon_device *rdev)
940926deccbSFrançois Tigeot {
941926deccbSFrançois Tigeot 	if (r100_debugfs_rbbm_init(rdev))
942926deccbSFrançois Tigeot 		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
943926deccbSFrançois Tigeot }
944926deccbSFrançois Tigeot 
rs600_set_safe_registers(struct radeon_device * rdev)945926deccbSFrançois Tigeot void rs600_set_safe_registers(struct radeon_device *rdev)
946926deccbSFrançois Tigeot {
947926deccbSFrançois Tigeot 	rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm;
948c4ef309bSzrj 	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs600_reg_safe_bm);
949926deccbSFrançois Tigeot }
950926deccbSFrançois Tigeot 
rs600_mc_program(struct radeon_device * rdev)951926deccbSFrançois Tigeot static void rs600_mc_program(struct radeon_device *rdev)
952926deccbSFrançois Tigeot {
953926deccbSFrançois Tigeot 	struct rv515_mc_save save;
954926deccbSFrançois Tigeot 
955926deccbSFrançois Tigeot 	/* Stops all mc clients */
956926deccbSFrançois Tigeot 	rv515_mc_stop(rdev, &save);
957926deccbSFrançois Tigeot 
958926deccbSFrançois Tigeot 	/* Wait for mc idle */
959926deccbSFrançois Tigeot 	if (rs600_mc_wait_for_idle(rdev))
960926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
961926deccbSFrançois Tigeot 
962926deccbSFrançois Tigeot 	/* FIXME: What does AGP means for such chipset ? */
963926deccbSFrançois Tigeot 	WREG32_MC(R_000005_MC_AGP_LOCATION, 0x0FFFFFFF);
964926deccbSFrançois Tigeot 	WREG32_MC(R_000006_AGP_BASE, 0);
965926deccbSFrançois Tigeot 	WREG32_MC(R_000007_AGP_BASE_2, 0);
966926deccbSFrançois Tigeot 	/* Program MC */
967926deccbSFrançois Tigeot 	WREG32_MC(R_000004_MC_FB_LOCATION,
968926deccbSFrançois Tigeot 			S_000004_MC_FB_START(rdev->mc.vram_start >> 16) |
969926deccbSFrançois Tigeot 			S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16));
970926deccbSFrançois Tigeot 	WREG32(R_000134_HDP_FB_LOCATION,
971926deccbSFrançois Tigeot 		S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));
972926deccbSFrançois Tigeot 
973926deccbSFrançois Tigeot 	rv515_mc_resume(rdev, &save);
974926deccbSFrançois Tigeot }
975926deccbSFrançois Tigeot 
rs600_startup(struct radeon_device * rdev)976926deccbSFrançois Tigeot static int rs600_startup(struct radeon_device *rdev)
977926deccbSFrançois Tigeot {
978926deccbSFrançois Tigeot 	int r;
979926deccbSFrançois Tigeot 
980926deccbSFrançois Tigeot 	rs600_mc_program(rdev);
981926deccbSFrançois Tigeot 	/* Resume clock */
982926deccbSFrançois Tigeot 	rv515_clock_startup(rdev);
983926deccbSFrançois Tigeot 	/* Initialize GPU configuration (# pipes, ...) */
984926deccbSFrançois Tigeot 	rs600_gpu_init(rdev);
985926deccbSFrançois Tigeot 	/* Initialize GART (initialize after TTM so we can allocate
986926deccbSFrançois Tigeot 	 * memory through TTM but finalize after TTM) */
987926deccbSFrançois Tigeot 	r = rs600_gart_enable(rdev);
988926deccbSFrançois Tigeot 	if (r)
989926deccbSFrançois Tigeot 		return r;
990926deccbSFrançois Tigeot 
991926deccbSFrançois Tigeot 	/* allocate wb buffer */
992926deccbSFrançois Tigeot 	r = radeon_wb_init(rdev);
993926deccbSFrançois Tigeot 	if (r)
994926deccbSFrançois Tigeot 		return r;
995926deccbSFrançois Tigeot 
996926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
997926deccbSFrançois Tigeot 	if (r) {
998926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
999926deccbSFrançois Tigeot 		return r;
1000926deccbSFrançois Tigeot 	}
1001926deccbSFrançois Tigeot 
1002926deccbSFrançois Tigeot 	/* Enable IRQ */
1003f43cf1b1SMichael Neumann 	if (!rdev->irq.installed) {
1004f43cf1b1SMichael Neumann 		r = radeon_irq_kms_init(rdev);
1005f43cf1b1SMichael Neumann 		if (r)
1006f43cf1b1SMichael Neumann 			return r;
1007f43cf1b1SMichael Neumann 	}
1008f43cf1b1SMichael Neumann 
1009926deccbSFrançois Tigeot 	rs600_irq_set(rdev);
1010926deccbSFrançois Tigeot 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
1011926deccbSFrançois Tigeot 	/* 1M ring buffer */
1012926deccbSFrançois Tigeot 	r = r100_cp_init(rdev, 1024 * 1024);
1013926deccbSFrançois Tigeot 	if (r) {
1014926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
1015926deccbSFrançois Tigeot 		return r;
1016926deccbSFrançois Tigeot 	}
1017926deccbSFrançois Tigeot 
1018926deccbSFrançois Tigeot 	r = radeon_ib_pool_init(rdev);
1019926deccbSFrançois Tigeot 	if (r) {
1020926deccbSFrançois Tigeot 		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
1021926deccbSFrançois Tigeot 		return r;
1022926deccbSFrançois Tigeot 	}
1023926deccbSFrançois Tigeot 
1024c59a5c48SFrançois Tigeot 	r = radeon_audio_init(rdev);
1025926deccbSFrançois Tigeot 	if (r) {
1026926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing audio\n");
1027926deccbSFrançois Tigeot 		return r;
1028926deccbSFrançois Tigeot 	}
1029926deccbSFrançois Tigeot 
1030926deccbSFrançois Tigeot 	return 0;
1031926deccbSFrançois Tigeot }
1032926deccbSFrançois Tigeot 
rs600_resume(struct radeon_device * rdev)1033926deccbSFrançois Tigeot int rs600_resume(struct radeon_device *rdev)
1034926deccbSFrançois Tigeot {
1035926deccbSFrançois Tigeot 	int r;
1036926deccbSFrançois Tigeot 
1037926deccbSFrançois Tigeot 	/* Make sur GART are not working */
1038926deccbSFrançois Tigeot 	rs600_gart_disable(rdev);
1039926deccbSFrançois Tigeot 	/* Resume clock before doing reset */
1040926deccbSFrançois Tigeot 	rv515_clock_startup(rdev);
1041926deccbSFrançois Tigeot 	/* Reset gpu before posting otherwise ATOM will enter infinite loop */
1042926deccbSFrançois Tigeot 	if (radeon_asic_reset(rdev)) {
1043926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
1044926deccbSFrançois Tigeot 			RREG32(R_000E40_RBBM_STATUS),
1045926deccbSFrançois Tigeot 			RREG32(R_0007C0_CP_STAT));
1046926deccbSFrançois Tigeot 	}
1047926deccbSFrançois Tigeot 	/* post */
1048926deccbSFrançois Tigeot 	atom_asic_init(rdev->mode_info.atom_context);
1049926deccbSFrançois Tigeot 	/* Resume clock after posting */
1050926deccbSFrançois Tigeot 	rv515_clock_startup(rdev);
1051926deccbSFrançois Tigeot 	/* Initialize surface registers */
1052926deccbSFrançois Tigeot 	radeon_surface_init(rdev);
1053926deccbSFrançois Tigeot 
1054926deccbSFrançois Tigeot 	rdev->accel_working = true;
1055926deccbSFrançois Tigeot 	r = rs600_startup(rdev);
1056926deccbSFrançois Tigeot 	if (r) {
1057926deccbSFrançois Tigeot 		rdev->accel_working = false;
1058926deccbSFrançois Tigeot 	}
1059926deccbSFrançois Tigeot 	return r;
1060926deccbSFrançois Tigeot }
1061926deccbSFrançois Tigeot 
rs600_suspend(struct radeon_device * rdev)1062926deccbSFrançois Tigeot int rs600_suspend(struct radeon_device *rdev)
1063926deccbSFrançois Tigeot {
1064c6f73aabSFrançois Tigeot 	radeon_pm_suspend(rdev);
1065c59a5c48SFrançois Tigeot 	radeon_audio_fini(rdev);
1066926deccbSFrançois Tigeot 	r100_cp_disable(rdev);
1067926deccbSFrançois Tigeot 	radeon_wb_disable(rdev);
1068926deccbSFrançois Tigeot 	rs600_irq_disable(rdev);
1069926deccbSFrançois Tigeot 	rs600_gart_disable(rdev);
1070926deccbSFrançois Tigeot 	return 0;
1071926deccbSFrançois Tigeot }
1072926deccbSFrançois Tigeot 
rs600_fini(struct radeon_device * rdev)1073926deccbSFrançois Tigeot void rs600_fini(struct radeon_device *rdev)
1074926deccbSFrançois Tigeot {
1075c6f73aabSFrançois Tigeot 	radeon_pm_fini(rdev);
1076c59a5c48SFrançois Tigeot 	radeon_audio_fini(rdev);
1077926deccbSFrançois Tigeot 	r100_cp_fini(rdev);
1078926deccbSFrançois Tigeot 	radeon_wb_fini(rdev);
1079926deccbSFrançois Tigeot 	radeon_ib_pool_fini(rdev);
1080926deccbSFrançois Tigeot 	radeon_gem_fini(rdev);
1081926deccbSFrançois Tigeot 	rs600_gart_fini(rdev);
1082926deccbSFrançois Tigeot 	radeon_irq_kms_fini(rdev);
1083926deccbSFrançois Tigeot 	radeon_fence_driver_fini(rdev);
1084926deccbSFrançois Tigeot 	radeon_bo_fini(rdev);
1085926deccbSFrançois Tigeot 	radeon_atombios_fini(rdev);
1086c4ef309bSzrj 	kfree(rdev->bios);
1087926deccbSFrançois Tigeot 	rdev->bios = NULL;
1088926deccbSFrançois Tigeot }
1089926deccbSFrançois Tigeot 
rs600_init(struct radeon_device * rdev)1090926deccbSFrançois Tigeot int rs600_init(struct radeon_device *rdev)
1091926deccbSFrançois Tigeot {
1092926deccbSFrançois Tigeot 	int r;
1093926deccbSFrançois Tigeot 
1094926deccbSFrançois Tigeot 	/* Disable VGA */
1095926deccbSFrançois Tigeot 	rv515_vga_render_disable(rdev);
1096926deccbSFrançois Tigeot 	/* Initialize scratch registers */
1097926deccbSFrançois Tigeot 	radeon_scratch_init(rdev);
1098926deccbSFrançois Tigeot 	/* Initialize surface registers */
1099926deccbSFrançois Tigeot 	radeon_surface_init(rdev);
1100926deccbSFrançois Tigeot 	/* restore some register to sane defaults */
1101926deccbSFrançois Tigeot 	r100_restore_sanity(rdev);
1102926deccbSFrançois Tigeot 	/* BIOS */
1103926deccbSFrançois Tigeot 	if (!radeon_get_bios(rdev)) {
1104926deccbSFrançois Tigeot 		if (ASIC_IS_AVIVO(rdev))
1105926deccbSFrançois Tigeot 			return -EINVAL;
1106926deccbSFrançois Tigeot 	}
1107926deccbSFrançois Tigeot 	if (rdev->is_atom_bios) {
1108926deccbSFrançois Tigeot 		r = radeon_atombios_init(rdev);
1109926deccbSFrançois Tigeot 		if (r)
1110926deccbSFrançois Tigeot 			return r;
1111926deccbSFrançois Tigeot 	} else {
1112926deccbSFrançois Tigeot 		dev_err(rdev->dev, "Expecting atombios for RS600 GPU\n");
1113926deccbSFrançois Tigeot 		return -EINVAL;
1114926deccbSFrançois Tigeot 	}
1115926deccbSFrançois Tigeot 	/* Reset gpu before posting otherwise ATOM will enter infinite loop */
1116926deccbSFrançois Tigeot 	if (radeon_asic_reset(rdev)) {
1117926deccbSFrançois Tigeot 		dev_warn(rdev->dev,
1118926deccbSFrançois Tigeot 			"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
1119926deccbSFrançois Tigeot 			RREG32(R_000E40_RBBM_STATUS),
1120926deccbSFrançois Tigeot 			RREG32(R_0007C0_CP_STAT));
1121926deccbSFrançois Tigeot 	}
1122926deccbSFrançois Tigeot 	/* check if cards are posted or not */
1123926deccbSFrançois Tigeot 	if (radeon_boot_test_post_card(rdev) == false)
1124926deccbSFrançois Tigeot 		return -EINVAL;
1125926deccbSFrançois Tigeot 
1126926deccbSFrançois Tigeot 	/* Initialize clocks */
1127926deccbSFrançois Tigeot 	radeon_get_clock_info(rdev->ddev);
1128926deccbSFrançois Tigeot 	/* initialize memory controller */
1129926deccbSFrançois Tigeot 	rs600_mc_init(rdev);
1130926deccbSFrançois Tigeot 	rs600_debugfs(rdev);
1131926deccbSFrançois Tigeot 	/* Fence driver */
1132926deccbSFrançois Tigeot 	r = radeon_fence_driver_init(rdev);
1133926deccbSFrançois Tigeot 	if (r)
1134926deccbSFrançois Tigeot 		return r;
1135926deccbSFrançois Tigeot 	/* Memory manager */
1136926deccbSFrançois Tigeot 	r = radeon_bo_init(rdev);
1137926deccbSFrançois Tigeot 	if (r)
1138926deccbSFrançois Tigeot 		return r;
1139926deccbSFrançois Tigeot 	r = rs600_gart_init(rdev);
1140926deccbSFrançois Tigeot 	if (r)
1141926deccbSFrançois Tigeot 		return r;
1142926deccbSFrançois Tigeot 	rs600_set_safe_registers(rdev);
1143926deccbSFrançois Tigeot 
1144c6f73aabSFrançois Tigeot 	/* Initialize power management */
1145c6f73aabSFrançois Tigeot 	radeon_pm_init(rdev);
1146c6f73aabSFrançois Tigeot 
1147926deccbSFrançois Tigeot 	rdev->accel_working = true;
1148926deccbSFrançois Tigeot 	r = rs600_startup(rdev);
1149926deccbSFrançois Tigeot 	if (r) {
1150926deccbSFrançois Tigeot 		/* Somethings want wront with the accel init stop accel */
1151926deccbSFrançois Tigeot 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
1152926deccbSFrançois Tigeot 		r100_cp_fini(rdev);
1153926deccbSFrançois Tigeot 		radeon_wb_fini(rdev);
1154926deccbSFrançois Tigeot 		radeon_ib_pool_fini(rdev);
1155926deccbSFrançois Tigeot 		rs600_gart_fini(rdev);
1156926deccbSFrançois Tigeot 		radeon_irq_kms_fini(rdev);
1157926deccbSFrançois Tigeot 		rdev->accel_working = false;
1158926deccbSFrançois Tigeot 	}
1159926deccbSFrançois Tigeot 	return 0;
1160926deccbSFrançois Tigeot }
1161