1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc.
3254885Sdumbbell * Copyright 2008 Red Hat Inc.
4254885Sdumbbell * Copyright 2009 Jerome Glisse.
5254885Sdumbbell *
6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
7254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
8254885Sdumbbell * to deal in the Software without restriction, including without limitation
9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
11254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
12254885Sdumbbell *
13254885Sdumbbell * The above copyright notice and this permission notice shall be included in
14254885Sdumbbell * all copies or substantial portions of the Software.
15254885Sdumbbell *
16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
23254885Sdumbbell *
24254885Sdumbbell * Authors: Dave Airlie
25254885Sdumbbell *          Alex Deucher
26254885Sdumbbell *          Jerome Glisse
27254885Sdumbbell */
28254885Sdumbbell
29254885Sdumbbell#include <sys/cdefs.h>
30254885Sdumbbell__FBSDID("$FreeBSD$");
31254885Sdumbbell
32254885Sdumbbell#include <dev/drm2/drmP.h>
33254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h>
34254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
35254885Sdumbbell#include "radeon_reg.h"
36254885Sdumbbell#include "radeon.h"
37254885Sdumbbell#include "atom.h"
38254885Sdumbbell
39254885Sdumbbellstatic const char radeon_family_name[][16] = {
40254885Sdumbbell	"R100",
41254885Sdumbbell	"RV100",
42254885Sdumbbell	"RS100",
43254885Sdumbbell	"RV200",
44254885Sdumbbell	"RS200",
45254885Sdumbbell	"R200",
46254885Sdumbbell	"RV250",
47254885Sdumbbell	"RS300",
48254885Sdumbbell	"RV280",
49254885Sdumbbell	"R300",
50254885Sdumbbell	"R350",
51254885Sdumbbell	"RV350",
52254885Sdumbbell	"RV380",
53254885Sdumbbell	"R420",
54254885Sdumbbell	"R423",
55254885Sdumbbell	"RV410",
56254885Sdumbbell	"RS400",
57254885Sdumbbell	"RS480",
58254885Sdumbbell	"RS600",
59254885Sdumbbell	"RS690",
60254885Sdumbbell	"RS740",
61254885Sdumbbell	"RV515",
62254885Sdumbbell	"R520",
63254885Sdumbbell	"RV530",
64254885Sdumbbell	"RV560",
65254885Sdumbbell	"RV570",
66254885Sdumbbell	"R580",
67254885Sdumbbell	"R600",
68254885Sdumbbell	"RV610",
69254885Sdumbbell	"RV630",
70254885Sdumbbell	"RV670",
71254885Sdumbbell	"RV620",
72254885Sdumbbell	"RV635",
73254885Sdumbbell	"RS780",
74254885Sdumbbell	"RS880",
75254885Sdumbbell	"RV770",
76254885Sdumbbell	"RV730",
77254885Sdumbbell	"RV710",
78254885Sdumbbell	"RV740",
79254885Sdumbbell	"CEDAR",
80254885Sdumbbell	"REDWOOD",
81254885Sdumbbell	"JUNIPER",
82254885Sdumbbell	"CYPRESS",
83254885Sdumbbell	"HEMLOCK",
84254885Sdumbbell	"PALM",
85254885Sdumbbell	"SUMO",
86254885Sdumbbell	"SUMO2",
87254885Sdumbbell	"BARTS",
88254885Sdumbbell	"TURKS",
89254885Sdumbbell	"CAICOS",
90254885Sdumbbell	"CAYMAN",
91254885Sdumbbell	"ARUBA",
92254885Sdumbbell	"TAHITI",
93254885Sdumbbell	"PITCAIRN",
94254885Sdumbbell	"VERDE",
95254885Sdumbbell	"LAST",
96254885Sdumbbell};
97254885Sdumbbell
98254885Sdumbbell/**
99254885Sdumbbell * radeon_surface_init - Clear GPU surface registers.
100254885Sdumbbell *
101254885Sdumbbell * @rdev: radeon_device pointer
102254885Sdumbbell *
103254885Sdumbbell * Clear GPU surface registers (r1xx-r5xx).
104254885Sdumbbell */
105254885Sdumbbellvoid radeon_surface_init(struct radeon_device *rdev)
106254885Sdumbbell{
107254885Sdumbbell	/* FIXME: check this out */
108254885Sdumbbell	if (rdev->family < CHIP_R600) {
109254885Sdumbbell		int i;
110254885Sdumbbell
111254885Sdumbbell		for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
112254885Sdumbbell			if (rdev->surface_regs[i].bo)
113254885Sdumbbell				radeon_bo_get_surface_reg(rdev->surface_regs[i].bo);
114254885Sdumbbell			else
115254885Sdumbbell				radeon_clear_surface_reg(rdev, i);
116254885Sdumbbell		}
117254885Sdumbbell		/* enable surfaces */
118254885Sdumbbell		WREG32(RADEON_SURFACE_CNTL, 0);
119254885Sdumbbell	}
120254885Sdumbbell}
121254885Sdumbbell
122254885Sdumbbell/*
123254885Sdumbbell * GPU scratch registers helpers function.
124254885Sdumbbell */
125254885Sdumbbell/**
126254885Sdumbbell * radeon_scratch_init - Init scratch register driver information.
127254885Sdumbbell *
128254885Sdumbbell * @rdev: radeon_device pointer
129254885Sdumbbell *
130254885Sdumbbell * Init CP scratch register driver information (r1xx-r5xx)
131254885Sdumbbell */
132254885Sdumbbellvoid radeon_scratch_init(struct radeon_device *rdev)
133254885Sdumbbell{
134254885Sdumbbell	int i;
135254885Sdumbbell
136254885Sdumbbell	/* FIXME: check this out */
137254885Sdumbbell	if (rdev->family < CHIP_R300) {
138254885Sdumbbell		rdev->scratch.num_reg = 5;
139254885Sdumbbell	} else {
140254885Sdumbbell		rdev->scratch.num_reg = 7;
141254885Sdumbbell	}
142254885Sdumbbell	rdev->scratch.reg_base = RADEON_SCRATCH_REG0;
143254885Sdumbbell	for (i = 0; i < rdev->scratch.num_reg; i++) {
144254885Sdumbbell		rdev->scratch.free[i] = true;
145254885Sdumbbell		rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4);
146254885Sdumbbell	}
147254885Sdumbbell}
148254885Sdumbbell
149254885Sdumbbell/**
150254885Sdumbbell * radeon_scratch_get - Allocate a scratch register
151254885Sdumbbell *
152254885Sdumbbell * @rdev: radeon_device pointer
153254885Sdumbbell * @reg: scratch register mmio offset
154254885Sdumbbell *
155254885Sdumbbell * Allocate a CP scratch register for use by the driver (all asics).
156254885Sdumbbell * Returns 0 on success or -EINVAL on failure.
157254885Sdumbbell */
158254885Sdumbbellint radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg)
159254885Sdumbbell{
160254885Sdumbbell	int i;
161254885Sdumbbell
162254885Sdumbbell	for (i = 0; i < rdev->scratch.num_reg; i++) {
163254885Sdumbbell		if (rdev->scratch.free[i]) {
164254885Sdumbbell			rdev->scratch.free[i] = false;
165254885Sdumbbell			*reg = rdev->scratch.reg[i];
166254885Sdumbbell			return 0;
167254885Sdumbbell		}
168254885Sdumbbell	}
169254885Sdumbbell	return -EINVAL;
170254885Sdumbbell}
171254885Sdumbbell
172254885Sdumbbell/**
173254885Sdumbbell * radeon_scratch_free - Free a scratch register
174254885Sdumbbell *
175254885Sdumbbell * @rdev: radeon_device pointer
176254885Sdumbbell * @reg: scratch register mmio offset
177254885Sdumbbell *
178254885Sdumbbell * Free a CP scratch register allocated for use by the driver (all asics)
179254885Sdumbbell */
180254885Sdumbbellvoid radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
181254885Sdumbbell{
182254885Sdumbbell	int i;
183254885Sdumbbell
184254885Sdumbbell	for (i = 0; i < rdev->scratch.num_reg; i++) {
185254885Sdumbbell		if (rdev->scratch.reg[i] == reg) {
186254885Sdumbbell			rdev->scratch.free[i] = true;
187254885Sdumbbell			return;
188254885Sdumbbell		}
189254885Sdumbbell	}
190254885Sdumbbell}
191254885Sdumbbell
192254885Sdumbbell/*
193254885Sdumbbell * radeon_wb_*()
194254885Sdumbbell * Writeback is the the method by which the the GPU updates special pages
195254885Sdumbbell * in memory with the status of certain GPU events (fences, ring pointers,
196254885Sdumbbell * etc.).
197254885Sdumbbell */
198254885Sdumbbell
199254885Sdumbbell/**
200254885Sdumbbell * radeon_wb_disable - Disable Writeback
201254885Sdumbbell *
202254885Sdumbbell * @rdev: radeon_device pointer
203254885Sdumbbell *
204254885Sdumbbell * Disables Writeback (all asics).  Used for suspend.
205254885Sdumbbell */
206254885Sdumbbellvoid radeon_wb_disable(struct radeon_device *rdev)
207254885Sdumbbell{
208254885Sdumbbell	int r;
209254885Sdumbbell
210254885Sdumbbell	if (rdev->wb.wb_obj) {
211254885Sdumbbell		r = radeon_bo_reserve(rdev->wb.wb_obj, false);
212254885Sdumbbell		if (unlikely(r != 0))
213254885Sdumbbell			return;
214254885Sdumbbell		radeon_bo_kunmap(rdev->wb.wb_obj);
215254885Sdumbbell		radeon_bo_unpin(rdev->wb.wb_obj);
216254885Sdumbbell		radeon_bo_unreserve(rdev->wb.wb_obj);
217254885Sdumbbell	}
218254885Sdumbbell	rdev->wb.enabled = false;
219254885Sdumbbell}
220254885Sdumbbell
221254885Sdumbbell/**
222254885Sdumbbell * radeon_wb_fini - Disable Writeback and free memory
223254885Sdumbbell *
224254885Sdumbbell * @rdev: radeon_device pointer
225254885Sdumbbell *
226254885Sdumbbell * Disables Writeback and frees the Writeback memory (all asics).
227254885Sdumbbell * Used at driver shutdown.
228254885Sdumbbell */
229254885Sdumbbellvoid radeon_wb_fini(struct radeon_device *rdev)
230254885Sdumbbell{
231254885Sdumbbell	radeon_wb_disable(rdev);
232254885Sdumbbell	if (rdev->wb.wb_obj) {
233254885Sdumbbell		radeon_bo_unref(&rdev->wb.wb_obj);
234254885Sdumbbell		rdev->wb.wb = NULL;
235254885Sdumbbell		rdev->wb.wb_obj = NULL;
236254885Sdumbbell	}
237254885Sdumbbell}
238254885Sdumbbell
239254885Sdumbbell/**
240254885Sdumbbell * radeon_wb_init- Init Writeback driver info and allocate memory
241254885Sdumbbell *
242254885Sdumbbell * @rdev: radeon_device pointer
243254885Sdumbbell *
244254885Sdumbbell * Disables Writeback and frees the Writeback memory (all asics).
245254885Sdumbbell * Used at driver startup.
246254885Sdumbbell * Returns 0 on success or an -error on failure.
247254885Sdumbbell */
248254885Sdumbbellint radeon_wb_init(struct radeon_device *rdev)
249254885Sdumbbell{
250254885Sdumbbell	int r;
251282199Sdumbbell	void *wb_ptr; /* FreeBSD: to please GCC 4.2. */
252254885Sdumbbell
253254885Sdumbbell	if (rdev->wb.wb_obj == NULL) {
254254885Sdumbbell		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
255254885Sdumbbell				     RADEON_GEM_DOMAIN_GTT, NULL, &rdev->wb.wb_obj);
256254885Sdumbbell		if (r) {
257254885Sdumbbell			dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
258254885Sdumbbell			return r;
259254885Sdumbbell		}
260254885Sdumbbell	}
261254885Sdumbbell	r = radeon_bo_reserve(rdev->wb.wb_obj, false);
262254885Sdumbbell	if (unlikely(r != 0)) {
263254885Sdumbbell		radeon_wb_fini(rdev);
264254885Sdumbbell		return r;
265254885Sdumbbell	}
266254885Sdumbbell	r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
267254885Sdumbbell			  &rdev->wb.gpu_addr);
268254885Sdumbbell	if (r) {
269254885Sdumbbell		radeon_bo_unreserve(rdev->wb.wb_obj);
270254885Sdumbbell		dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r);
271254885Sdumbbell		radeon_wb_fini(rdev);
272254885Sdumbbell		return r;
273254885Sdumbbell	}
274254885Sdumbbell	wb_ptr = &rdev->wb.wb;
275254885Sdumbbell	r = radeon_bo_kmap(rdev->wb.wb_obj, wb_ptr);
276254885Sdumbbell	radeon_bo_unreserve(rdev->wb.wb_obj);
277254885Sdumbbell	if (r) {
278254885Sdumbbell		dev_warn(rdev->dev, "(%d) map WB bo failed\n", r);
279254885Sdumbbell		radeon_wb_fini(rdev);
280254885Sdumbbell		return r;
281254885Sdumbbell	}
282254885Sdumbbell
283254885Sdumbbell	/* clear wb memory */
284254885Sdumbbell	memset(*(void **)wb_ptr, 0, RADEON_GPU_PAGE_SIZE);
285254885Sdumbbell	/* disable event_write fences */
286254885Sdumbbell	rdev->wb.use_event = false;
287254885Sdumbbell	/* disabled via module param */
288254885Sdumbbell	if (radeon_no_wb == 1) {
289254885Sdumbbell		rdev->wb.enabled = false;
290254885Sdumbbell	} else {
291254885Sdumbbell		if (rdev->flags & RADEON_IS_AGP) {
292254885Sdumbbell			/* often unreliable on AGP */
293254885Sdumbbell			rdev->wb.enabled = false;
294254885Sdumbbell		} else if (rdev->family < CHIP_R300) {
295254885Sdumbbell			/* often unreliable on pre-r300 */
296254885Sdumbbell			rdev->wb.enabled = false;
297254885Sdumbbell		} else {
298254885Sdumbbell			rdev->wb.enabled = true;
299254885Sdumbbell			/* event_write fences are only available on r600+ */
300254885Sdumbbell			if (rdev->family >= CHIP_R600) {
301254885Sdumbbell				rdev->wb.use_event = true;
302254885Sdumbbell			}
303254885Sdumbbell		}
304254885Sdumbbell	}
305254885Sdumbbell	/* always use writeback/events on NI, APUs */
306254885Sdumbbell	if (rdev->family >= CHIP_PALM) {
307254885Sdumbbell		rdev->wb.enabled = true;
308254885Sdumbbell		rdev->wb.use_event = true;
309254885Sdumbbell	}
310254885Sdumbbell
311254885Sdumbbell	dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis");
312254885Sdumbbell
313254885Sdumbbell	return 0;
314254885Sdumbbell}
315254885Sdumbbell
316254885Sdumbbell/**
317254885Sdumbbell * radeon_vram_location - try to find VRAM location
318254885Sdumbbell * @rdev: radeon device structure holding all necessary informations
319254885Sdumbbell * @mc: memory controller structure holding memory informations
320254885Sdumbbell * @base: base address at which to put VRAM
321254885Sdumbbell *
322254885Sdumbbell * Function will place try to place VRAM at base address provided
323254885Sdumbbell * as parameter (which is so far either PCI aperture address or
324254885Sdumbbell * for IGP TOM base address).
325254885Sdumbbell *
326254885Sdumbbell * If there is not enough space to fit the unvisible VRAM in the 32bits
327254885Sdumbbell * address space then we limit the VRAM size to the aperture.
328254885Sdumbbell *
329254885Sdumbbell * If we are using AGP and if the AGP aperture doesn't allow us to have
330254885Sdumbbell * room for all the VRAM than we restrict the VRAM to the PCI aperture
331254885Sdumbbell * size and print a warning.
332254885Sdumbbell *
333254885Sdumbbell * This function will never fails, worst case are limiting VRAM.
334254885Sdumbbell *
335254885Sdumbbell * Note: GTT start, end, size should be initialized before calling this
336254885Sdumbbell * function on AGP platform.
337254885Sdumbbell *
338254885Sdumbbell * Note: We don't explicitly enforce VRAM start to be aligned on VRAM size,
339254885Sdumbbell * this shouldn't be a problem as we are using the PCI aperture as a reference.
340254885Sdumbbell * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but
341254885Sdumbbell * not IGP.
342254885Sdumbbell *
343254885Sdumbbell * Note: we use mc_vram_size as on some board we need to program the mc to
344254885Sdumbbell * cover the whole aperture even if VRAM size is inferior to aperture size
345254885Sdumbbell * Novell bug 204882 + along with lots of ubuntu ones
346254885Sdumbbell *
347254885Sdumbbell * Note: when limiting vram it's safe to overwritte real_vram_size because
348254885Sdumbbell * we are not in case where real_vram_size is inferior to mc_vram_size (ie
349254885Sdumbbell * note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu
350254885Sdumbbell * ones)
351254885Sdumbbell *
352254885Sdumbbell * Note: IGP TOM addr should be the same as the aperture addr, we don't
353254885Sdumbbell * explicitly check for that thought.
354254885Sdumbbell *
355254885Sdumbbell * FIXME: when reducing VRAM size align new size on power of 2.
356254885Sdumbbell */
357254885Sdumbbellvoid radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)
358254885Sdumbbell{
359254885Sdumbbell	uint64_t limit = (uint64_t)radeon_vram_limit << 20;
360254885Sdumbbell
361254885Sdumbbell	mc->vram_start = base;
362254885Sdumbbell	if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {
363254885Sdumbbell		dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
364254885Sdumbbell		mc->real_vram_size = mc->aper_size;
365254885Sdumbbell		mc->mc_vram_size = mc->aper_size;
366254885Sdumbbell	}
367254885Sdumbbell	mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
368254885Sdumbbell	if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_start <= mc->gtt_end) {
369254885Sdumbbell		dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
370254885Sdumbbell		mc->real_vram_size = mc->aper_size;
371254885Sdumbbell		mc->mc_vram_size = mc->aper_size;
372254885Sdumbbell	}
373254885Sdumbbell	mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
374254885Sdumbbell	if (limit && limit < mc->real_vram_size)
375254885Sdumbbell		mc->real_vram_size = limit;
376254885Sdumbbell	dev_info(rdev->dev, "VRAM: %juM 0x%016jX - 0x%016jX (%juM used)\n",
377254885Sdumbbell			(uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start,
378254885Sdumbbell			(uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20);
379254885Sdumbbell}
380254885Sdumbbell
381254885Sdumbbell/**
382254885Sdumbbell * radeon_gtt_location - try to find GTT location
383254885Sdumbbell * @rdev: radeon device structure holding all necessary informations
384254885Sdumbbell * @mc: memory controller structure holding memory informations
385254885Sdumbbell *
386254885Sdumbbell * Function will place try to place GTT before or after VRAM.
387254885Sdumbbell *
388254885Sdumbbell * If GTT size is bigger than space left then we ajust GTT size.
389254885Sdumbbell * Thus function will never fails.
390254885Sdumbbell *
391254885Sdumbbell * FIXME: when reducing GTT size align new size on power of 2.
392254885Sdumbbell */
393254885Sdumbbellvoid radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
394254885Sdumbbell{
395254885Sdumbbell	u64 size_af, size_bf;
396254885Sdumbbell
397254885Sdumbbell	size_af = ((0xFFFFFFFF - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align;
398254885Sdumbbell	size_bf = mc->vram_start & ~mc->gtt_base_align;
399254885Sdumbbell	if (size_bf > size_af) {
400254885Sdumbbell		if (mc->gtt_size > size_bf) {
401254885Sdumbbell			dev_warn(rdev->dev, "limiting GTT\n");
402254885Sdumbbell			mc->gtt_size = size_bf;
403254885Sdumbbell		}
404254885Sdumbbell		mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size;
405254885Sdumbbell	} else {
406254885Sdumbbell		if (mc->gtt_size > size_af) {
407254885Sdumbbell			dev_warn(rdev->dev, "limiting GTT\n");
408254885Sdumbbell			mc->gtt_size = size_af;
409254885Sdumbbell		}
410254885Sdumbbell		mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align;
411254885Sdumbbell	}
412254885Sdumbbell	mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;
413254885Sdumbbell	dev_info(rdev->dev, "GTT: %juM 0x%016jX - 0x%016jX\n",
414254885Sdumbbell			(uintmax_t)mc->gtt_size >> 20, (uintmax_t)mc->gtt_start, (uintmax_t)mc->gtt_end);
415254885Sdumbbell}
416254885Sdumbbell
417254885Sdumbbell/*
418254885Sdumbbell * GPU helpers function.
419254885Sdumbbell */
420254885Sdumbbell/**
421254885Sdumbbell * radeon_card_posted - check if the hw has already been initialized
422254885Sdumbbell *
423254885Sdumbbell * @rdev: radeon_device pointer
424254885Sdumbbell *
425254885Sdumbbell * Check if the asic has been initialized (all asics).
426254885Sdumbbell * Used at driver startup.
427254885Sdumbbell * Returns true if initialized or false if not.
428254885Sdumbbell */
429254885Sdumbbellbool radeon_card_posted(struct radeon_device *rdev)
430254885Sdumbbell{
431254885Sdumbbell	uint32_t reg;
432254885Sdumbbell
433282199Sdumbbell#ifdef FREEBSD_WIP
434254885Sdumbbell	if (efi_enabled(EFI_BOOT) &&
435254885Sdumbbell	    rdev->dev->pci_subvendor == PCI_VENDOR_ID_APPLE)
436254885Sdumbbell		return false;
437282199Sdumbbell#endif /* FREEBSD_WIP */
438254885Sdumbbell
439254885Sdumbbell	/* first check CRTCs */
440254885Sdumbbell	if (ASIC_IS_DCE41(rdev)) {
441254885Sdumbbell		reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
442254885Sdumbbell			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
443254885Sdumbbell		if (reg & EVERGREEN_CRTC_MASTER_EN)
444254885Sdumbbell			return true;
445254885Sdumbbell	} else if (ASIC_IS_DCE4(rdev)) {
446254885Sdumbbell		reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
447254885Sdumbbell			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
448254885Sdumbbell			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
449254885Sdumbbell			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) |
450254885Sdumbbell			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
451254885Sdumbbell			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
452254885Sdumbbell		if (reg & EVERGREEN_CRTC_MASTER_EN)
453254885Sdumbbell			return true;
454254885Sdumbbell	} else if (ASIC_IS_AVIVO(rdev)) {
455254885Sdumbbell		reg = RREG32(AVIVO_D1CRTC_CONTROL) |
456254885Sdumbbell		      RREG32(AVIVO_D2CRTC_CONTROL);
457254885Sdumbbell		if (reg & AVIVO_CRTC_EN) {
458254885Sdumbbell			return true;
459254885Sdumbbell		}
460254885Sdumbbell	} else {
461254885Sdumbbell		reg = RREG32(RADEON_CRTC_GEN_CNTL) |
462254885Sdumbbell		      RREG32(RADEON_CRTC2_GEN_CNTL);
463254885Sdumbbell		if (reg & RADEON_CRTC_EN) {
464254885Sdumbbell			return true;
465254885Sdumbbell		}
466254885Sdumbbell	}
467254885Sdumbbell
468254885Sdumbbell	/* then check MEM_SIZE, in case the crtcs are off */
469254885Sdumbbell	if (rdev->family >= CHIP_R600)
470254885Sdumbbell		reg = RREG32(R600_CONFIG_MEMSIZE);
471254885Sdumbbell	else
472254885Sdumbbell		reg = RREG32(RADEON_CONFIG_MEMSIZE);
473254885Sdumbbell
474254885Sdumbbell	if (reg)
475254885Sdumbbell		return true;
476254885Sdumbbell
477254885Sdumbbell	return false;
478254885Sdumbbell
479254885Sdumbbell}
480254885Sdumbbell
481254885Sdumbbell/**
482254885Sdumbbell * radeon_update_bandwidth_info - update display bandwidth params
483254885Sdumbbell *
484254885Sdumbbell * @rdev: radeon_device pointer
485254885Sdumbbell *
486254885Sdumbbell * Used when sclk/mclk are switched or display modes are set.
487254885Sdumbbell * params are used to calculate display watermarks (all asics)
488254885Sdumbbell */
489254885Sdumbbellvoid radeon_update_bandwidth_info(struct radeon_device *rdev)
490254885Sdumbbell{
491254885Sdumbbell	fixed20_12 a;
492254885Sdumbbell	u32 sclk = rdev->pm.current_sclk;
493254885Sdumbbell	u32 mclk = rdev->pm.current_mclk;
494254885Sdumbbell
495254885Sdumbbell	/* sclk/mclk in Mhz */
496254885Sdumbbell	a.full = dfixed_const(100);
497254885Sdumbbell	rdev->pm.sclk.full = dfixed_const(sclk);
498254885Sdumbbell	rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a);
499254885Sdumbbell	rdev->pm.mclk.full = dfixed_const(mclk);
500254885Sdumbbell	rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a);
501254885Sdumbbell
502254885Sdumbbell	if (rdev->flags & RADEON_IS_IGP) {
503254885Sdumbbell		a.full = dfixed_const(16);
504254885Sdumbbell		/* core_bandwidth = sclk(Mhz) * 16 */
505254885Sdumbbell		rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a);
506254885Sdumbbell	}
507254885Sdumbbell}
508254885Sdumbbell
509254885Sdumbbell/**
510254885Sdumbbell * radeon_boot_test_post_card - check and possibly initialize the hw
511254885Sdumbbell *
512254885Sdumbbell * @rdev: radeon_device pointer
513254885Sdumbbell *
514254885Sdumbbell * Check if the asic is initialized and if not, attempt to initialize
515254885Sdumbbell * it (all asics).
516254885Sdumbbell * Returns true if initialized or false if not.
517254885Sdumbbell */
518254885Sdumbbellbool radeon_boot_test_post_card(struct radeon_device *rdev)
519254885Sdumbbell{
520254885Sdumbbell	if (radeon_card_posted(rdev))
521254885Sdumbbell		return true;
522254885Sdumbbell
523254885Sdumbbell	if (rdev->bios) {
524254885Sdumbbell		DRM_INFO("GPU not posted. posting now...\n");
525254885Sdumbbell		if (rdev->is_atom_bios)
526254885Sdumbbell			atom_asic_init(rdev->mode_info.atom_context);
527254885Sdumbbell		else
528254885Sdumbbell			radeon_combios_asic_init(rdev->ddev);
529254885Sdumbbell		return true;
530254885Sdumbbell	} else {
531254885Sdumbbell		dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
532254885Sdumbbell		return false;
533254885Sdumbbell	}
534254885Sdumbbell}
535254885Sdumbbell
536254885Sdumbbell/**
537254885Sdumbbell * radeon_dummy_page_init - init dummy page used by the driver
538254885Sdumbbell *
539254885Sdumbbell * @rdev: radeon_device pointer
540254885Sdumbbell *
541254885Sdumbbell * Allocate the dummy page used by the driver (all asics).
542254885Sdumbbell * This dummy page is used by the driver as a filler for gart entries
543254885Sdumbbell * when pages are taken out of the GART
544254885Sdumbbell * Returns 0 on sucess, -ENOMEM on failure.
545254885Sdumbbell */
546254885Sdumbbellint radeon_dummy_page_init(struct radeon_device *rdev)
547254885Sdumbbell{
548254885Sdumbbell	if (rdev->dummy_page.dmah)
549254885Sdumbbell		return 0;
550254885Sdumbbell	rdev->dummy_page.dmah = drm_pci_alloc(rdev->ddev,
551282199Sdumbbell	    PAGE_SIZE, PAGE_SIZE, BUS_SPACE_MAXADDR_32BIT);
552254885Sdumbbell	if (rdev->dummy_page.dmah == NULL)
553254885Sdumbbell		return -ENOMEM;
554267042Smarius	rdev->dummy_page.addr = rdev->dummy_page.dmah->busaddr;
555254885Sdumbbell	return 0;
556254885Sdumbbell}
557254885Sdumbbell
558254885Sdumbbell/**
559254885Sdumbbell * radeon_dummy_page_fini - free dummy page used by the driver
560254885Sdumbbell *
561254885Sdumbbell * @rdev: radeon_device pointer
562254885Sdumbbell *
563254885Sdumbbell * Frees the dummy page used by the driver (all asics).
564254885Sdumbbell */
565254885Sdumbbellvoid radeon_dummy_page_fini(struct radeon_device *rdev)
566254885Sdumbbell{
567254885Sdumbbell	if (rdev->dummy_page.dmah == NULL)
568254885Sdumbbell		return;
569254885Sdumbbell	drm_pci_free(rdev->ddev, rdev->dummy_page.dmah);
570254885Sdumbbell	rdev->dummy_page.dmah = NULL;
571254885Sdumbbell	rdev->dummy_page.addr = 0;
572254885Sdumbbell}
573254885Sdumbbell
574254885Sdumbbell
575254885Sdumbbell/* ATOM accessor methods */
576254885Sdumbbell/*
577254885Sdumbbell * ATOM is an interpreted byte code stored in tables in the vbios.  The
578254885Sdumbbell * driver registers callbacks to access registers and the interpreter
579254885Sdumbbell * in the driver parses the tables and executes then to program specific
580254885Sdumbbell * actions (set display modes, asic init, etc.).  See radeon_atombios.c,
581254885Sdumbbell * atombios.h, and atom.c
582254885Sdumbbell */
583254885Sdumbbell
584254885Sdumbbell/**
585254885Sdumbbell * cail_pll_read - read PLL register
586254885Sdumbbell *
587254885Sdumbbell * @info: atom card_info pointer
588254885Sdumbbell * @reg: PLL register offset
589254885Sdumbbell *
590254885Sdumbbell * Provides a PLL register accessor for the atom interpreter (r4xx+).
591254885Sdumbbell * Returns the value of the PLL register.
592254885Sdumbbell */
593254885Sdumbbellstatic uint32_t cail_pll_read(struct card_info *info, uint32_t reg)
594254885Sdumbbell{
595254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
596254885Sdumbbell	uint32_t r;
597254885Sdumbbell
598254885Sdumbbell	r = rdev->pll_rreg(rdev, reg);
599254885Sdumbbell	return r;
600254885Sdumbbell}
601254885Sdumbbell
602254885Sdumbbell/**
603254885Sdumbbell * cail_pll_write - write PLL register
604254885Sdumbbell *
605254885Sdumbbell * @info: atom card_info pointer
606254885Sdumbbell * @reg: PLL register offset
607254885Sdumbbell * @val: value to write to the pll register
608254885Sdumbbell *
609254885Sdumbbell * Provides a PLL register accessor for the atom interpreter (r4xx+).
610254885Sdumbbell */
611254885Sdumbbellstatic void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val)
612254885Sdumbbell{
613254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
614254885Sdumbbell
615254885Sdumbbell	rdev->pll_wreg(rdev, reg, val);
616254885Sdumbbell}
617254885Sdumbbell
618254885Sdumbbell/**
619254885Sdumbbell * cail_mc_read - read MC (Memory Controller) register
620254885Sdumbbell *
621254885Sdumbbell * @info: atom card_info pointer
622254885Sdumbbell * @reg: MC register offset
623254885Sdumbbell *
624254885Sdumbbell * Provides an MC register accessor for the atom interpreter (r4xx+).
625254885Sdumbbell * Returns the value of the MC register.
626254885Sdumbbell */
627254885Sdumbbellstatic uint32_t cail_mc_read(struct card_info *info, uint32_t reg)
628254885Sdumbbell{
629254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
630254885Sdumbbell	uint32_t r;
631254885Sdumbbell
632254885Sdumbbell	r = rdev->mc_rreg(rdev, reg);
633254885Sdumbbell	return r;
634254885Sdumbbell}
635254885Sdumbbell
636254885Sdumbbell/**
637254885Sdumbbell * cail_mc_write - write MC (Memory Controller) register
638254885Sdumbbell *
639254885Sdumbbell * @info: atom card_info pointer
640254885Sdumbbell * @reg: MC register offset
641254885Sdumbbell * @val: value to write to the pll register
642254885Sdumbbell *
643254885Sdumbbell * Provides a MC register accessor for the atom interpreter (r4xx+).
644254885Sdumbbell */
645254885Sdumbbellstatic void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val)
646254885Sdumbbell{
647254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
648254885Sdumbbell
649254885Sdumbbell	rdev->mc_wreg(rdev, reg, val);
650254885Sdumbbell}
651254885Sdumbbell
652254885Sdumbbell/**
653254885Sdumbbell * cail_reg_write - write MMIO register
654254885Sdumbbell *
655254885Sdumbbell * @info: atom card_info pointer
656254885Sdumbbell * @reg: MMIO register offset
657254885Sdumbbell * @val: value to write to the pll register
658254885Sdumbbell *
659254885Sdumbbell * Provides a MMIO register accessor for the atom interpreter (r4xx+).
660254885Sdumbbell */
661254885Sdumbbellstatic void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val)
662254885Sdumbbell{
663254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
664254885Sdumbbell
665254885Sdumbbell	WREG32(reg*4, val);
666254885Sdumbbell}
667254885Sdumbbell
668254885Sdumbbell/**
669254885Sdumbbell * cail_reg_read - read MMIO register
670254885Sdumbbell *
671254885Sdumbbell * @info: atom card_info pointer
672254885Sdumbbell * @reg: MMIO register offset
673254885Sdumbbell *
674254885Sdumbbell * Provides an MMIO register accessor for the atom interpreter (r4xx+).
675254885Sdumbbell * Returns the value of the MMIO register.
676254885Sdumbbell */
677254885Sdumbbellstatic uint32_t cail_reg_read(struct card_info *info, uint32_t reg)
678254885Sdumbbell{
679254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
680254885Sdumbbell	uint32_t r;
681254885Sdumbbell
682254885Sdumbbell	r = RREG32(reg*4);
683254885Sdumbbell	return r;
684254885Sdumbbell}
685254885Sdumbbell
686254885Sdumbbell/**
687254885Sdumbbell * cail_ioreg_write - write IO register
688254885Sdumbbell *
689254885Sdumbbell * @info: atom card_info pointer
690254885Sdumbbell * @reg: IO register offset
691254885Sdumbbell * @val: value to write to the pll register
692254885Sdumbbell *
693254885Sdumbbell * Provides a IO register accessor for the atom interpreter (r4xx+).
694254885Sdumbbell */
695254885Sdumbbellstatic void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val)
696254885Sdumbbell{
697254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
698254885Sdumbbell
699254885Sdumbbell	WREG32_IO(reg*4, val);
700254885Sdumbbell}
701254885Sdumbbell
702254885Sdumbbell/**
703254885Sdumbbell * cail_ioreg_read - read IO register
704254885Sdumbbell *
705254885Sdumbbell * @info: atom card_info pointer
706254885Sdumbbell * @reg: IO register offset
707254885Sdumbbell *
708254885Sdumbbell * Provides an IO register accessor for the atom interpreter (r4xx+).
709254885Sdumbbell * Returns the value of the IO register.
710254885Sdumbbell */
711254885Sdumbbellstatic uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg)
712254885Sdumbbell{
713254885Sdumbbell	struct radeon_device *rdev = info->dev->dev_private;
714254885Sdumbbell	uint32_t r;
715254885Sdumbbell
716254885Sdumbbell	r = RREG32_IO(reg*4);
717254885Sdumbbell	return r;
718254885Sdumbbell}
719254885Sdumbbell
720254885Sdumbbell/**
721254885Sdumbbell * radeon_atombios_init - init the driver info and callbacks for atombios
722254885Sdumbbell *
723254885Sdumbbell * @rdev: radeon_device pointer
724254885Sdumbbell *
725254885Sdumbbell * Initializes the driver info and register access callbacks for the
726254885Sdumbbell * ATOM interpreter (r4xx+).
727254885Sdumbbell * Returns 0 on sucess, -ENOMEM on failure.
728254885Sdumbbell * Called at driver startup.
729254885Sdumbbell */
730254885Sdumbbellint radeon_atombios_init(struct radeon_device *rdev)
731254885Sdumbbell{
732254885Sdumbbell	struct card_info *atom_card_info =
733254885Sdumbbell	    malloc(sizeof(struct card_info),
734282199Sdumbbell		DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
735254885Sdumbbell
736254885Sdumbbell	if (!atom_card_info)
737254885Sdumbbell		return -ENOMEM;
738254885Sdumbbell
739254885Sdumbbell	rdev->mode_info.atom_card_info = atom_card_info;
740254885Sdumbbell	atom_card_info->dev = rdev->ddev;
741254885Sdumbbell	atom_card_info->reg_read = cail_reg_read;
742254885Sdumbbell	atom_card_info->reg_write = cail_reg_write;
743254885Sdumbbell	/* needed for iio ops */
744254885Sdumbbell	if (rdev->rio_mem) {
745254885Sdumbbell		atom_card_info->ioreg_read = cail_ioreg_read;
746254885Sdumbbell		atom_card_info->ioreg_write = cail_ioreg_write;
747254885Sdumbbell	} else {
748254885Sdumbbell		DRM_ERROR("Unable to find PCI I/O BAR; using MMIO for ATOM IIO\n");
749254885Sdumbbell		atom_card_info->ioreg_read = cail_reg_read;
750254885Sdumbbell		atom_card_info->ioreg_write = cail_reg_write;
751254885Sdumbbell	}
752254885Sdumbbell	atom_card_info->mc_read = cail_mc_read;
753254885Sdumbbell	atom_card_info->mc_write = cail_mc_write;
754254885Sdumbbell	atom_card_info->pll_read = cail_pll_read;
755254885Sdumbbell	atom_card_info->pll_write = cail_pll_write;
756254885Sdumbbell
757254885Sdumbbell	rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios);
758254885Sdumbbell	sx_init(&rdev->mode_info.atom_context->mutex,
759254885Sdumbbell	    "drm__radeon_device__mode_info__atom_context__mutex");
760254885Sdumbbell	radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
761254885Sdumbbell	atom_allocate_fb_scratch(rdev->mode_info.atom_context);
762254885Sdumbbell	return 0;
763254885Sdumbbell}
764254885Sdumbbell
765254885Sdumbbell/**
766254885Sdumbbell * radeon_atombios_fini - free the driver info and callbacks for atombios
767254885Sdumbbell *
768254885Sdumbbell * @rdev: radeon_device pointer
769254885Sdumbbell *
770254885Sdumbbell * Frees the driver info and register access callbacks for the ATOM
771254885Sdumbbell * interpreter (r4xx+).
772254885Sdumbbell * Called at driver shutdown.
773254885Sdumbbell */
774254885Sdumbbellvoid radeon_atombios_fini(struct radeon_device *rdev)
775254885Sdumbbell{
776254885Sdumbbell	if (rdev->mode_info.atom_context) {
777254885Sdumbbell		free(rdev->mode_info.atom_context->scratch, DRM_MEM_DRIVER);
778254885Sdumbbell		atom_destroy(rdev->mode_info.atom_context);
779254885Sdumbbell	}
780254885Sdumbbell	free(rdev->mode_info.atom_card_info, DRM_MEM_DRIVER);
781254885Sdumbbell}
782254885Sdumbbell
783254885Sdumbbell/* COMBIOS */
784254885Sdumbbell/*
785254885Sdumbbell * COMBIOS is the bios format prior to ATOM. It provides
786254885Sdumbbell * command tables similar to ATOM, but doesn't have a unified
787254885Sdumbbell * parser.  See radeon_combios.c
788254885Sdumbbell */
789254885Sdumbbell
790254885Sdumbbell/**
791254885Sdumbbell * radeon_combios_init - init the driver info for combios
792254885Sdumbbell *
793254885Sdumbbell * @rdev: radeon_device pointer
794254885Sdumbbell *
795254885Sdumbbell * Initializes the driver info for combios (r1xx-r3xx).
796254885Sdumbbell * Returns 0 on sucess.
797254885Sdumbbell * Called at driver startup.
798254885Sdumbbell */
799254885Sdumbbellint radeon_combios_init(struct radeon_device *rdev)
800254885Sdumbbell{
801254885Sdumbbell	radeon_combios_initialize_bios_scratch_regs(rdev->ddev);
802254885Sdumbbell	return 0;
803254885Sdumbbell}
804254885Sdumbbell
805254885Sdumbbell/**
806254885Sdumbbell * radeon_combios_fini - free the driver info for combios
807254885Sdumbbell *
808254885Sdumbbell * @rdev: radeon_device pointer
809254885Sdumbbell *
810254885Sdumbbell * Frees the driver info for combios (r1xx-r3xx).
811254885Sdumbbell * Called at driver shutdown.
812254885Sdumbbell */
813254885Sdumbbellvoid radeon_combios_fini(struct radeon_device *rdev)
814254885Sdumbbell{
815254885Sdumbbell}
816254885Sdumbbell
817282199Sdumbbell#ifdef FREEBSD_WIP
818254885Sdumbbell/* if we get transitioned to only one device, take VGA back */
819254885Sdumbbell/**
820254885Sdumbbell * radeon_vga_set_decode - enable/disable vga decode
821254885Sdumbbell *
822254885Sdumbbell * @cookie: radeon_device pointer
823254885Sdumbbell * @state: enable/disable vga decode
824254885Sdumbbell *
825254885Sdumbbell * Enable/disable vga decode (all asics).
826254885Sdumbbell * Returns VGA resource flags.
827254885Sdumbbell */
828254885Sdumbbellstatic unsigned int radeon_vga_set_decode(void *cookie, bool state)
829254885Sdumbbell{
830254885Sdumbbell	struct radeon_device *rdev = cookie;
831254885Sdumbbell	radeon_vga_set_state(rdev, state);
832254885Sdumbbell	if (state)
833254885Sdumbbell		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
834254885Sdumbbell		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
835254885Sdumbbell	else
836254885Sdumbbell		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
837254885Sdumbbell}
838282199Sdumbbell#endif /* FREEBSD_WIP */
839254885Sdumbbell
840254885Sdumbbell/**
841254885Sdumbbell * radeon_check_pot_argument - check that argument is a power of two
842254885Sdumbbell *
843254885Sdumbbell * @arg: value to check
844254885Sdumbbell *
845254885Sdumbbell * Validates that a certain argument is a power of two (all asics).
846254885Sdumbbell * Returns true if argument is valid.
847254885Sdumbbell */
848254885Sdumbbellstatic bool radeon_check_pot_argument(int arg)
849254885Sdumbbell{
850254885Sdumbbell	return (arg & (arg - 1)) == 0;
851254885Sdumbbell}
852254885Sdumbbell
853254885Sdumbbell/**
854254885Sdumbbell * radeon_check_arguments - validate module params
855254885Sdumbbell *
856254885Sdumbbell * @rdev: radeon_device pointer
857254885Sdumbbell *
858254885Sdumbbell * Validates certain module parameters and updates
859254885Sdumbbell * the associated values used by the driver (all asics).
860254885Sdumbbell */
861254885Sdumbbellstatic void radeon_check_arguments(struct radeon_device *rdev)
862254885Sdumbbell{
863254885Sdumbbell	/* vramlimit must be a power of two */
864254885Sdumbbell	if (!radeon_check_pot_argument(radeon_vram_limit)) {
865254885Sdumbbell		dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
866254885Sdumbbell				radeon_vram_limit);
867254885Sdumbbell		radeon_vram_limit = 0;
868254885Sdumbbell	}
869254885Sdumbbell
870254885Sdumbbell	/* gtt size must be power of two and greater or equal to 32M */
871254885Sdumbbell	if (radeon_gart_size < 32) {
872254885Sdumbbell		dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
873254885Sdumbbell				radeon_gart_size);
874254885Sdumbbell		radeon_gart_size = 512;
875254885Sdumbbell
876254885Sdumbbell	} else if (!radeon_check_pot_argument(radeon_gart_size)) {
877254885Sdumbbell		dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
878254885Sdumbbell				radeon_gart_size);
879254885Sdumbbell		radeon_gart_size = 512;
880254885Sdumbbell	}
881254885Sdumbbell	rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20;
882254885Sdumbbell
883254885Sdumbbell	/* AGP mode can only be -1, 1, 2, 4, 8 */
884254885Sdumbbell	switch (radeon_agpmode) {
885254885Sdumbbell	case -1:
886254885Sdumbbell	case 0:
887254885Sdumbbell	case 1:
888254885Sdumbbell	case 2:
889254885Sdumbbell	case 4:
890254885Sdumbbell	case 8:
891254885Sdumbbell		break;
892254885Sdumbbell	default:
893254885Sdumbbell		dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: "
894254885Sdumbbell				"-1, 0, 1, 2, 4, 8)\n", radeon_agpmode);
895254885Sdumbbell		radeon_agpmode = 0;
896254885Sdumbbell		break;
897254885Sdumbbell	}
898254885Sdumbbell}
899254885Sdumbbell
900254885Sdumbbell/**
901254885Sdumbbell * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is
902254885Sdumbbell * needed for waking up.
903254885Sdumbbell *
904254885Sdumbbell * @pdev: pci dev pointer
905254885Sdumbbell */
906282199Sdumbbell#ifdef FREEBSD_WIP
907254885Sdumbbellstatic bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
908254885Sdumbbell{
909254885Sdumbbell
910254885Sdumbbell	/* 6600m in a macbook pro */
911254885Sdumbbell	if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
912254885Sdumbbell	    pdev->subsystem_device == 0x00e2) {
913254885Sdumbbell		printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n");
914254885Sdumbbell		return true;
915254885Sdumbbell	}
916254885Sdumbbell
917254885Sdumbbell	return false;
918254885Sdumbbell}
919282199Sdumbbell#endif /* FREEBSD_WIP */
920254885Sdumbbell
921254885Sdumbbell/**
922254885Sdumbbell * radeon_switcheroo_set_state - set switcheroo state
923254885Sdumbbell *
924254885Sdumbbell * @pdev: pci dev pointer
925254885Sdumbbell * @state: vga switcheroo state
926254885Sdumbbell *
927254885Sdumbbell * Callback for the switcheroo driver.  Suspends or resumes the
928254885Sdumbbell * the asics before or after it is powered up using ACPI methods.
929254885Sdumbbell */
930282199Sdumbbell#ifdef FREEBSD_WIP
931254885Sdumbbellstatic void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
932254885Sdumbbell{
933254885Sdumbbell	struct drm_device *dev = pci_get_drvdata(pdev);
934254885Sdumbbell	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
935254885Sdumbbell	if (state == VGA_SWITCHEROO_ON) {
936254885Sdumbbell		unsigned d3_delay = dev->pdev->d3_delay;
937254885Sdumbbell
938254885Sdumbbell		printk(KERN_INFO "radeon: switched on\n");
939254885Sdumbbell		/* don't suspend or resume card normally */
940254885Sdumbbell		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
941254885Sdumbbell
942254885Sdumbbell		if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev))
943254885Sdumbbell			dev->pdev->d3_delay = 20;
944254885Sdumbbell
945254885Sdumbbell		radeon_resume_kms(dev);
946254885Sdumbbell
947254885Sdumbbell		dev->pdev->d3_delay = d3_delay;
948254885Sdumbbell
949254885Sdumbbell		dev->switch_power_state = DRM_SWITCH_POWER_ON;
950254885Sdumbbell		drm_kms_helper_poll_enable(dev);
951254885Sdumbbell	} else {
952254885Sdumbbell		printk(KERN_INFO "radeon: switched off\n");
953254885Sdumbbell		drm_kms_helper_poll_disable(dev);
954254885Sdumbbell		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
955254885Sdumbbell		radeon_suspend_kms(dev, pmm);
956254885Sdumbbell		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
957254885Sdumbbell	}
958254885Sdumbbell}
959282199Sdumbbell#endif /* FREEBSD_WIP */
960254885Sdumbbell
961254885Sdumbbell/**
962254885Sdumbbell * radeon_switcheroo_can_switch - see if switcheroo state can change
963254885Sdumbbell *
964254885Sdumbbell * @pdev: pci dev pointer
965254885Sdumbbell *
966254885Sdumbbell * Callback for the switcheroo driver.  Check of the switcheroo
967254885Sdumbbell * state can be changed.
968254885Sdumbbell * Returns true if the state can be changed, false if not.
969254885Sdumbbell */
970282199Sdumbbell#ifdef FREEBSD_WIP
971254885Sdumbbellstatic bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
972254885Sdumbbell{
973254885Sdumbbell	struct drm_device *dev = pci_get_drvdata(pdev);
974254885Sdumbbell	bool can_switch;
975254885Sdumbbell
976254885Sdumbbell	spin_lock(&dev->count_lock);
977254885Sdumbbell	can_switch = (dev->open_count == 0);
978254885Sdumbbell	spin_unlock(&dev->count_lock);
979254885Sdumbbell	return can_switch;
980254885Sdumbbell}
981254885Sdumbbell
982254885Sdumbbellstatic const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
983254885Sdumbbell	.set_gpu_state = radeon_switcheroo_set_state,
984254885Sdumbbell	.reprobe = NULL,
985254885Sdumbbell	.can_switch = radeon_switcheroo_can_switch,
986254885Sdumbbell};
987282199Sdumbbell#endif /* FREEBSD_WIP */
988254885Sdumbbell
989254885Sdumbbell/**
990254885Sdumbbell * radeon_device_init - initialize the driver
991254885Sdumbbell *
992254885Sdumbbell * @rdev: radeon_device pointer
993254885Sdumbbell * @pdev: drm dev pointer
994254885Sdumbbell * @flags: driver flags
995254885Sdumbbell *
996254885Sdumbbell * Initializes the driver info and hw (all asics).
997254885Sdumbbell * Returns 0 for success or an error on failure.
998254885Sdumbbell * Called at driver startup.
999254885Sdumbbell */
1000254885Sdumbbellint radeon_device_init(struct radeon_device *rdev,
1001254885Sdumbbell		       struct drm_device *ddev,
1002254885Sdumbbell		       uint32_t flags)
1003254885Sdumbbell{
1004254885Sdumbbell	int r, i;
1005254885Sdumbbell	int dma_bits;
1006254885Sdumbbell
1007254885Sdumbbell	rdev->shutdown = false;
1008282199Sdumbbell	rdev->dev = ddev->dev;
1009254885Sdumbbell	rdev->ddev = ddev;
1010254885Sdumbbell	rdev->flags = flags;
1011254885Sdumbbell	rdev->family = flags & RADEON_FAMILY_MASK;
1012254885Sdumbbell	rdev->is_atom_bios = false;
1013254885Sdumbbell	rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT;
1014254885Sdumbbell	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
1015254885Sdumbbell	rdev->accel_working = false;
1016254885Sdumbbell	rdev->fictitious_range_registered = false;
1017275408Stijl	rdev->fictitious_agp_range_registered = false;
1018254885Sdumbbell	/* set up ring ids */
1019254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; i++) {
1020254885Sdumbbell		rdev->ring[i].idx = i;
1021254885Sdumbbell	}
1022254885Sdumbbell
1023254885Sdumbbell	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
1024254885Sdumbbell		radeon_family_name[rdev->family], ddev->pci_vendor, ddev->pci_device,
1025254885Sdumbbell		ddev->pci_subvendor, ddev->pci_subdevice);
1026254885Sdumbbell
1027254885Sdumbbell	/* mutex initialization are all done here so we
1028254885Sdumbbell	 * can recall function without having locking issues */
1029254885Sdumbbell	sx_init(&rdev->ring_lock, "drm__radeon_device__ring_lock");
1030254885Sdumbbell	sx_init(&rdev->dc_hw_i2c_mutex, "drm__radeon_device__dc_hw_i2c_mutex");
1031254885Sdumbbell	atomic_set(&rdev->ih.lock, 0);
1032254885Sdumbbell	sx_init(&rdev->gem.mutex, "drm__radeon_device__gem__mutex");
1033254885Sdumbbell	sx_init(&rdev->pm.mutex, "drm__radeon_device__pm__mutex");
1034254885Sdumbbell	sx_init(&rdev->gpu_clock_mutex, "drm__radeon_device__gpu_clock_mutex");
1035254885Sdumbbell	sx_init(&rdev->pm.mclk_lock, "drm__radeon_device__pm__mclk_lock");
1036254885Sdumbbell	sx_init(&rdev->exclusive_lock, "drm__radeon_device__exclusive_lock");
1037254885Sdumbbell	DRM_INIT_WAITQUEUE(&rdev->irq.vblank_queue);
1038254885Sdumbbell	r = radeon_gem_init(rdev);
1039254885Sdumbbell	if (r)
1040254885Sdumbbell		return r;
1041254885Sdumbbell	/* initialize vm here */
1042254885Sdumbbell	sx_init(&rdev->vm_manager.lock, "drm__radeon_device__vm_manager__lock");
1043254885Sdumbbell	/* Adjust VM size here.
1044254885Sdumbbell	 * Currently set to 4GB ((1 << 20) 4k pages).
1045254885Sdumbbell	 * Max GPUVM size for cayman and SI is 40 bits.
1046254885Sdumbbell	 */
1047254885Sdumbbell	rdev->vm_manager.max_pfn = 1 << 20;
1048254885Sdumbbell	INIT_LIST_HEAD(&rdev->vm_manager.lru_vm);
1049254885Sdumbbell
1050254885Sdumbbell	/* Set asic functions */
1051254885Sdumbbell	r = radeon_asic_init(rdev);
1052254885Sdumbbell	if (r)
1053254885Sdumbbell		return r;
1054254885Sdumbbell	radeon_check_arguments(rdev);
1055254885Sdumbbell
1056254885Sdumbbell	/* all of the newer IGP chips have an internal gart
1057254885Sdumbbell	 * However some rs4xx report as AGP, so remove that here.
1058254885Sdumbbell	 */
1059254885Sdumbbell	if ((rdev->family >= CHIP_RS400) &&
1060254885Sdumbbell	    (rdev->flags & RADEON_IS_IGP)) {
1061254885Sdumbbell		rdev->flags &= ~RADEON_IS_AGP;
1062254885Sdumbbell	}
1063254885Sdumbbell
1064254885Sdumbbell	if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) {
1065254885Sdumbbell		radeon_agp_disable(rdev);
1066254885Sdumbbell	}
1067254885Sdumbbell
1068254885Sdumbbell	/* set DMA mask + need_dma32 flags.
1069254885Sdumbbell	 * PCIE - can handle 40-bits.
1070254885Sdumbbell	 * IGP - can handle 40-bits
1071254885Sdumbbell	 * AGP - generally dma32 is safest
1072254885Sdumbbell	 * PCI - dma32 for legacy pci gart, 40 bits on newer asics
1073254885Sdumbbell	 */
1074254885Sdumbbell	rdev->need_dma32 = false;
1075254885Sdumbbell	if (rdev->flags & RADEON_IS_AGP)
1076254885Sdumbbell		rdev->need_dma32 = true;
1077254885Sdumbbell	if ((rdev->flags & RADEON_IS_PCI) &&
1078254885Sdumbbell	    (rdev->family <= CHIP_RS740))
1079254885Sdumbbell		rdev->need_dma32 = true;
1080254885Sdumbbell
1081254885Sdumbbell	dma_bits = rdev->need_dma32 ? 32 : 40;
1082282199Sdumbbell#ifdef FREEBSD_WIP
1083254885Sdumbbell	r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
1084254885Sdumbbell	if (r) {
1085254885Sdumbbell		rdev->need_dma32 = true;
1086254885Sdumbbell		dma_bits = 32;
1087254885Sdumbbell		printk(KERN_WARNING "radeon: No suitable DMA available.\n");
1088254885Sdumbbell	}
1089254885Sdumbbell	r = pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
1090254885Sdumbbell	if (r) {
1091254885Sdumbbell		pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
1092254885Sdumbbell		printk(KERN_WARNING "radeon: No coherent DMA available.\n");
1093254885Sdumbbell	}
1094282199Sdumbbell#endif /* FREEBSD_WIP */
1095254885Sdumbbell
1096254885Sdumbbell	/* Registers mapping */
1097254885Sdumbbell	/* TODO: block userspace mapping of io register */
1098254885Sdumbbell	DRM_SPININIT(&rdev->mmio_idx_lock, "drm__radeon_device__mmio_idx_lock");
1099254885Sdumbbell	rdev->rmmio_rid = PCIR_BAR(2);
1100254885Sdumbbell	rdev->rmmio = bus_alloc_resource_any(rdev->dev, SYS_RES_MEMORY,
1101254885Sdumbbell	    &rdev->rmmio_rid, RF_ACTIVE | RF_SHAREABLE);
1102254885Sdumbbell	if (rdev->rmmio == NULL) {
1103254885Sdumbbell		return -ENOMEM;
1104254885Sdumbbell	}
1105254885Sdumbbell	rdev->rmmio_base = rman_get_start(rdev->rmmio);
1106254885Sdumbbell	rdev->rmmio_size = rman_get_size(rdev->rmmio);
1107254885Sdumbbell	DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
1108254885Sdumbbell	DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
1109254885Sdumbbell
1110254885Sdumbbell	/* io port mapping */
1111254885Sdumbbell	for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
1112254885Sdumbbell		uint32_t data;
1113254885Sdumbbell
1114254885Sdumbbell		data = pci_read_config(rdev->dev, PCIR_BAR(i), 4);
1115254885Sdumbbell		if (PCI_BAR_IO(data)) {
1116254885Sdumbbell			rdev->rio_rid = PCIR_BAR(i);
1117254885Sdumbbell			rdev->rio_mem = bus_alloc_resource_any(rdev->dev,
1118254885Sdumbbell			    SYS_RES_IOPORT, &rdev->rio_rid,
1119254885Sdumbbell			    RF_ACTIVE | RF_SHAREABLE);
1120254885Sdumbbell			break;
1121254885Sdumbbell		}
1122254885Sdumbbell	}
1123254885Sdumbbell	if (rdev->rio_mem == NULL)
1124254885Sdumbbell		DRM_ERROR("Unable to find PCI I/O BAR\n");
1125254885Sdumbbell
1126254885Sdumbbell	rdev->tq = taskqueue_create("radeonkms", M_WAITOK,
1127254885Sdumbbell	    taskqueue_thread_enqueue, &rdev->tq);
1128254885Sdumbbell	taskqueue_start_threads(&rdev->tq, 1, PWAIT, "radeon taskq");
1129254885Sdumbbell
1130282199Sdumbbell#ifdef FREEBSD_WIP
1131254885Sdumbbell	/* if we have > 1 VGA cards, then disable the radeon VGA resources */
1132254885Sdumbbell	/* this will fail for cards that aren't VGA class devices, just
1133254885Sdumbbell	 * ignore it */
1134254885Sdumbbell	vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
1135254885Sdumbbell	vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops);
1136282199Sdumbbell#endif /* FREEBSD_WIP */
1137254885Sdumbbell
1138254885Sdumbbell	r = radeon_init(rdev);
1139254885Sdumbbell	if (r)
1140254885Sdumbbell		return r;
1141254885Sdumbbell
1142254885Sdumbbell	r = radeon_ib_ring_tests(rdev);
1143254885Sdumbbell	if (r)
1144254885Sdumbbell		DRM_ERROR("ib ring test failed (%d).\n", r);
1145254885Sdumbbell
1146254885Sdumbbell	if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) {
1147254885Sdumbbell		/* Acceleration not working on AGP card try again
1148254885Sdumbbell		 * with fallback to PCI or PCIE GART
1149254885Sdumbbell		 */
1150254885Sdumbbell		radeon_asic_reset(rdev);
1151254885Sdumbbell		radeon_fini(rdev);
1152254885Sdumbbell		radeon_agp_disable(rdev);
1153254885Sdumbbell		r = radeon_init(rdev);
1154254885Sdumbbell		if (r)
1155254885Sdumbbell			return r;
1156254885Sdumbbell	}
1157254885Sdumbbell
1158254885Sdumbbell	DRM_INFO("%s: Taking over the fictitious range 0x%jx-0x%jx\n",
1159254885Sdumbbell	    __func__, (uintmax_t)rdev->mc.aper_base,
1160254885Sdumbbell	    (uintmax_t)rdev->mc.aper_base + rdev->mc.visible_vram_size);
1161254885Sdumbbell	r = vm_phys_fictitious_reg_range(
1162254885Sdumbbell	    rdev->mc.aper_base,
1163254885Sdumbbell	    rdev->mc.aper_base + rdev->mc.visible_vram_size,
1164254885Sdumbbell	    VM_MEMATTR_WRITE_COMBINING);
1165254885Sdumbbell	if (r != 0) {
1166254885Sdumbbell		DRM_ERROR("Failed to register fictitious range "
1167254885Sdumbbell		    "0x%jx-0x%jx (%d).\n", (uintmax_t)rdev->mc.aper_base,
1168254885Sdumbbell		    (uintmax_t)rdev->mc.aper_base + rdev->mc.visible_vram_size, r);
1169254885Sdumbbell		return (-r);
1170254885Sdumbbell	}
1171254885Sdumbbell	rdev->fictitious_range_registered = true;
1172275408Stijl#if __OS_HAS_AGP
1173275408Stijl	if (rdev->flags & RADEON_IS_AGP) {
1174275408Stijl		DRM_INFO("%s: Taking over the fictitious range 0x%jx-0x%jx\n",
1175275408Stijl		    __func__, (uintmax_t)rdev->mc.agp_base,
1176275408Stijl		    (uintmax_t)rdev->mc.agp_base + rdev->mc.gtt_size);
1177275408Stijl		r = vm_phys_fictitious_reg_range(
1178275408Stijl		    rdev->mc.agp_base,
1179275408Stijl		    rdev->mc.agp_base + rdev->mc.gtt_size,
1180275408Stijl		    VM_MEMATTR_WRITE_COMBINING);
1181275408Stijl		if (r != 0) {
1182275408Stijl			DRM_ERROR("Failed to register fictitious range "
1183275408Stijl			    "0x%jx-0x%jx (%d).\n", (uintmax_t)rdev->mc.agp_base,
1184275408Stijl			    (uintmax_t)rdev->mc.agp_base + rdev->mc.gtt_size, r);
1185275408Stijl			return (-r);
1186275408Stijl		}
1187275408Stijl		rdev->fictitious_agp_range_registered = true;
1188275408Stijl	}
1189275408Stijl#endif
1190254885Sdumbbell
1191254885Sdumbbell	if ((radeon_testing & 1)) {
1192254885Sdumbbell		radeon_test_moves(rdev);
1193254885Sdumbbell	}
1194254885Sdumbbell	if ((radeon_testing & 2)) {
1195254885Sdumbbell		radeon_test_syncing(rdev);
1196254885Sdumbbell	}
1197254885Sdumbbell	if (radeon_benchmarking) {
1198254885Sdumbbell		radeon_benchmark(rdev, radeon_benchmarking);
1199254885Sdumbbell	}
1200254885Sdumbbell	return 0;
1201254885Sdumbbell}
1202254885Sdumbbell
1203282199Sdumbbell#ifdef FREEBSD_WIP
1204254885Sdumbbellstatic void radeon_debugfs_remove_files(struct radeon_device *rdev);
1205282199Sdumbbell#endif /* FREEBSD_WIP */
1206254885Sdumbbell
1207254885Sdumbbell/**
1208254885Sdumbbell * radeon_device_fini - tear down the driver
1209254885Sdumbbell *
1210254885Sdumbbell * @rdev: radeon_device pointer
1211254885Sdumbbell *
1212254885Sdumbbell * Tear down the driver info (all asics).
1213254885Sdumbbell * Called at driver shutdown.
1214254885Sdumbbell */
1215254885Sdumbbellvoid radeon_device_fini(struct radeon_device *rdev)
1216254885Sdumbbell{
1217254885Sdumbbell	DRM_INFO("radeon: finishing device.\n");
1218254885Sdumbbell	rdev->shutdown = true;
1219254885Sdumbbell	/* evict vram memory */
1220254885Sdumbbell	radeon_bo_evict_vram(rdev);
1221254885Sdumbbell
1222254885Sdumbbell	if (rdev->fictitious_range_registered) {
1223254885Sdumbbell		vm_phys_fictitious_unreg_range(
1224254885Sdumbbell		    rdev->mc.aper_base,
1225254885Sdumbbell		    rdev->mc.aper_base + rdev->mc.visible_vram_size);
1226254885Sdumbbell	}
1227275408Stijl#if __OS_HAS_AGP
1228275408Stijl	if (rdev->fictitious_agp_range_registered) {
1229275408Stijl		vm_phys_fictitious_unreg_range(
1230275408Stijl		    rdev->mc.agp_base,
1231275408Stijl		    rdev->mc.agp_base + rdev->mc.gtt_size);
1232275408Stijl	}
1233275408Stijl#endif
1234254885Sdumbbell
1235254885Sdumbbell	radeon_fini(rdev);
1236282199Sdumbbell#ifdef FREEBSD_WIP
1237254885Sdumbbell	vga_switcheroo_unregister_client(rdev->pdev);
1238254885Sdumbbell	vga_client_register(rdev->pdev, NULL, NULL, NULL);
1239282199Sdumbbell#endif /* FREEBSD_WIP */
1240254885Sdumbbell
1241254885Sdumbbell	if (rdev->tq != NULL) {
1242254885Sdumbbell		taskqueue_free(rdev->tq);
1243254885Sdumbbell		rdev->tq = NULL;
1244254885Sdumbbell	}
1245254885Sdumbbell
1246254885Sdumbbell	if (rdev->rio_mem)
1247254885Sdumbbell		bus_release_resource(rdev->dev, SYS_RES_IOPORT, rdev->rio_rid,
1248254885Sdumbbell		    rdev->rio_mem);
1249254885Sdumbbell	rdev->rio_mem = NULL;
1250254885Sdumbbell	bus_release_resource(rdev->dev, SYS_RES_MEMORY, rdev->rmmio_rid,
1251254885Sdumbbell	    rdev->rmmio);
1252254885Sdumbbell	rdev->rmmio = NULL;
1253282199Sdumbbell#ifdef FREEBSD_WIP
1254254885Sdumbbell	radeon_debugfs_remove_files(rdev);
1255282199Sdumbbell#endif /* FREEBSD_WIP */
1256254885Sdumbbell}
1257254885Sdumbbell
1258254885Sdumbbell
1259254885Sdumbbell/*
1260254885Sdumbbell * Suspend & resume.
1261254885Sdumbbell */
1262254885Sdumbbell/**
1263254885Sdumbbell * radeon_suspend_kms - initiate device suspend
1264254885Sdumbbell *
1265254885Sdumbbell * @pdev: drm dev pointer
1266254885Sdumbbell * @state: suspend state
1267254885Sdumbbell *
1268254885Sdumbbell * Puts the hw in the suspend state (all asics).
1269254885Sdumbbell * Returns 0 for success or an error on failure.
1270254885Sdumbbell * Called at driver suspend.
1271254885Sdumbbell */
1272254885Sdumbbellint radeon_suspend_kms(struct drm_device *dev)
1273254885Sdumbbell{
1274254885Sdumbbell	struct radeon_device *rdev;
1275254885Sdumbbell	struct drm_crtc *crtc;
1276254885Sdumbbell	struct drm_connector *connector;
1277254885Sdumbbell	int i, r;
1278254885Sdumbbell	bool force_completion = false;
1279254885Sdumbbell
1280254885Sdumbbell	if (dev == NULL || dev->dev_private == NULL) {
1281254885Sdumbbell		return -ENODEV;
1282254885Sdumbbell	}
1283282199Sdumbbell#ifdef FREEBSD_WIP
1284254885Sdumbbell	if (state.event == PM_EVENT_PRETHAW) {
1285254885Sdumbbell		return 0;
1286254885Sdumbbell	}
1287282199Sdumbbell#endif /* FREEBSD_WIP */
1288254885Sdumbbell	rdev = dev->dev_private;
1289254885Sdumbbell
1290254885Sdumbbell	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
1291254885Sdumbbell		return 0;
1292254885Sdumbbell
1293254885Sdumbbell	drm_kms_helper_poll_disable(dev);
1294254885Sdumbbell
1295254885Sdumbbell	/* turn off display hw */
1296254885Sdumbbell	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1297254885Sdumbbell		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
1298254885Sdumbbell	}
1299254885Sdumbbell
1300254885Sdumbbell	/* unpin the front buffers */
1301254885Sdumbbell	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1302254885Sdumbbell		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
1303254885Sdumbbell		struct radeon_bo *robj;
1304254885Sdumbbell
1305254885Sdumbbell		if (rfb == NULL || rfb->obj == NULL) {
1306254885Sdumbbell			continue;
1307254885Sdumbbell		}
1308254885Sdumbbell		robj = gem_to_radeon_bo(rfb->obj);
1309254885Sdumbbell		/* don't unpin kernel fb objects */
1310254885Sdumbbell		if (!radeon_fbdev_robj_is_fb(rdev, robj)) {
1311254885Sdumbbell			r = radeon_bo_reserve(robj, false);
1312254885Sdumbbell			if (r == 0) {
1313254885Sdumbbell				radeon_bo_unpin(robj);
1314254885Sdumbbell				radeon_bo_unreserve(robj);
1315254885Sdumbbell			}
1316254885Sdumbbell		}
1317254885Sdumbbell	}
1318254885Sdumbbell	/* evict vram memory */
1319254885Sdumbbell	radeon_bo_evict_vram(rdev);
1320254885Sdumbbell
1321254885Sdumbbell	sx_xlock(&rdev->ring_lock);
1322254885Sdumbbell	/* wait for gpu to finish processing current batch */
1323254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; i++) {
1324254885Sdumbbell		r = radeon_fence_wait_empty_locked(rdev, i);
1325254885Sdumbbell		if (r) {
1326254885Sdumbbell			/* delay GPU reset to resume */
1327254885Sdumbbell			force_completion = true;
1328254885Sdumbbell		}
1329254885Sdumbbell	}
1330254885Sdumbbell	if (force_completion) {
1331254885Sdumbbell		radeon_fence_driver_force_completion(rdev);
1332254885Sdumbbell	}
1333254885Sdumbbell	sx_xunlock(&rdev->ring_lock);
1334254885Sdumbbell
1335254885Sdumbbell	radeon_save_bios_scratch_regs(rdev);
1336254885Sdumbbell
1337254885Sdumbbell	radeon_pm_suspend(rdev);
1338254885Sdumbbell	radeon_suspend(rdev);
1339254885Sdumbbell	radeon_hpd_fini(rdev);
1340254885Sdumbbell	/* evict remaining vram memory */
1341254885Sdumbbell	radeon_bo_evict_vram(rdev);
1342254885Sdumbbell
1343254885Sdumbbell	radeon_agp_suspend(rdev);
1344254885Sdumbbell
1345282199Sdumbbell#ifdef FREEBSD_WIP
1346254885Sdumbbell	if (state.event == PM_EVENT_SUSPEND) {
1347254885Sdumbbell		/* Shut down the device */
1348254885Sdumbbell		pci_disable_device(dev->pdev);
1349254885Sdumbbell	}
1350254885Sdumbbell	console_lock();
1351282199Sdumbbell#endif /* FREEBSD_WIP */
1352254885Sdumbbell	radeon_fbdev_set_suspend(rdev, 1);
1353282199Sdumbbell#ifdef FREEBSD_WIP
1354254885Sdumbbell	console_unlock();
1355282199Sdumbbell#endif /* FREEBSD_WIP */
1356254885Sdumbbell	return 0;
1357254885Sdumbbell}
1358254885Sdumbbell
1359254885Sdumbbell/**
1360254885Sdumbbell * radeon_resume_kms - initiate device resume
1361254885Sdumbbell *
1362254885Sdumbbell * @pdev: drm dev pointer
1363254885Sdumbbell *
1364254885Sdumbbell * Bring the hw back to operating state (all asics).
1365254885Sdumbbell * Returns 0 for success or an error on failure.
1366254885Sdumbbell * Called at driver resume.
1367254885Sdumbbell */
1368254885Sdumbbellint radeon_resume_kms(struct drm_device *dev)
1369254885Sdumbbell{
1370254885Sdumbbell	struct drm_connector *connector;
1371254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1372254885Sdumbbell	int r;
1373254885Sdumbbell
1374254885Sdumbbell	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
1375254885Sdumbbell		return 0;
1376254885Sdumbbell
1377282199Sdumbbell#ifdef FREEBSD_WIP
1378254885Sdumbbell	console_lock();
1379254885Sdumbbell	if (pci_enable_device(dev->pdev)) {
1380254885Sdumbbell		console_unlock();
1381254885Sdumbbell		return -1;
1382254885Sdumbbell	}
1383282199Sdumbbell#endif /* FREEBSD_WIP */
1384254885Sdumbbell	/* resume AGP if in use */
1385254885Sdumbbell	radeon_agp_resume(rdev);
1386254885Sdumbbell	radeon_resume(rdev);
1387254885Sdumbbell
1388254885Sdumbbell	r = radeon_ib_ring_tests(rdev);
1389254885Sdumbbell	if (r)
1390254885Sdumbbell		DRM_ERROR("ib ring test failed (%d).\n", r);
1391254885Sdumbbell
1392254885Sdumbbell	radeon_pm_resume(rdev);
1393254885Sdumbbell	radeon_restore_bios_scratch_regs(rdev);
1394254885Sdumbbell
1395254885Sdumbbell	radeon_fbdev_set_suspend(rdev, 0);
1396282199Sdumbbell#ifdef FREEBSD_WIP
1397254885Sdumbbell	console_unlock();
1398282199Sdumbbell#endif /* FREEBSD_WIP */
1399254885Sdumbbell
1400254885Sdumbbell	/* init dig PHYs, disp eng pll */
1401254885Sdumbbell	if (rdev->is_atom_bios) {
1402254885Sdumbbell		radeon_atom_encoder_init(rdev);
1403254885Sdumbbell		radeon_atom_disp_eng_pll_init(rdev);
1404254885Sdumbbell		/* turn on the BL */
1405254885Sdumbbell		if (rdev->mode_info.bl_encoder) {
1406254885Sdumbbell			u8 bl_level = radeon_get_backlight_level(rdev,
1407254885Sdumbbell								 rdev->mode_info.bl_encoder);
1408254885Sdumbbell			radeon_set_backlight_level(rdev, rdev->mode_info.bl_encoder,
1409254885Sdumbbell						   bl_level);
1410254885Sdumbbell		}
1411254885Sdumbbell	}
1412254885Sdumbbell	/* reset hpd state */
1413254885Sdumbbell	radeon_hpd_init(rdev);
1414254885Sdumbbell	/* blat the mode back in */
1415254885Sdumbbell	drm_helper_resume_force_mode(dev);
1416254885Sdumbbell	/* turn on display hw */
1417254885Sdumbbell	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1418254885Sdumbbell		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
1419254885Sdumbbell	}
1420254885Sdumbbell
1421254885Sdumbbell	drm_kms_helper_poll_enable(dev);
1422254885Sdumbbell	return 0;
1423254885Sdumbbell}
1424254885Sdumbbell
1425254885Sdumbbell/**
1426254885Sdumbbell * radeon_gpu_reset - reset the asic
1427254885Sdumbbell *
1428254885Sdumbbell * @rdev: radeon device pointer
1429254885Sdumbbell *
1430254885Sdumbbell * Attempt the reset the GPU if it has hung (all asics).
1431254885Sdumbbell * Returns 0 for success or an error on failure.
1432254885Sdumbbell */
1433254885Sdumbbellint radeon_gpu_reset(struct radeon_device *rdev)
1434254885Sdumbbell{
1435254885Sdumbbell	unsigned ring_sizes[RADEON_NUM_RINGS];
1436254885Sdumbbell	uint32_t *ring_data[RADEON_NUM_RINGS];
1437254885Sdumbbell
1438254885Sdumbbell	bool saved = false;
1439254885Sdumbbell
1440254885Sdumbbell	int i, r;
1441254885Sdumbbell	int resched;
1442254885Sdumbbell
1443254885Sdumbbell	sx_xlock(&rdev->exclusive_lock);
1444254885Sdumbbell	radeon_save_bios_scratch_regs(rdev);
1445254885Sdumbbell	/* block TTM */
1446254885Sdumbbell	resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
1447254885Sdumbbell	radeon_suspend(rdev);
1448254885Sdumbbell
1449254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
1450254885Sdumbbell		ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i],
1451254885Sdumbbell						   &ring_data[i]);
1452254885Sdumbbell		if (ring_sizes[i]) {
1453254885Sdumbbell			saved = true;
1454254885Sdumbbell			dev_info(rdev->dev, "Saved %d dwords of commands "
1455254885Sdumbbell				 "on ring %d.\n", ring_sizes[i], i);
1456254885Sdumbbell		}
1457254885Sdumbbell	}
1458254885Sdumbbell
1459254885Sdumbbellretry:
1460254885Sdumbbell	r = radeon_asic_reset(rdev);
1461254885Sdumbbell	if (!r) {
1462254885Sdumbbell		dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n");
1463254885Sdumbbell		radeon_resume(rdev);
1464254885Sdumbbell	}
1465254885Sdumbbell
1466254885Sdumbbell	radeon_restore_bios_scratch_regs(rdev);
1467254885Sdumbbell
1468254885Sdumbbell	if (!r) {
1469254885Sdumbbell		for (i = 0; i < RADEON_NUM_RINGS; ++i) {
1470254885Sdumbbell			radeon_ring_restore(rdev, &rdev->ring[i],
1471254885Sdumbbell					    ring_sizes[i], ring_data[i]);
1472254885Sdumbbell			ring_sizes[i] = 0;
1473254885Sdumbbell			ring_data[i] = NULL;
1474254885Sdumbbell		}
1475254885Sdumbbell
1476254885Sdumbbell		r = radeon_ib_ring_tests(rdev);
1477254885Sdumbbell		if (r) {
1478254885Sdumbbell			dev_err(rdev->dev, "ib ring test failed (%d).\n", r);
1479254885Sdumbbell			if (saved) {
1480254885Sdumbbell				saved = false;
1481254885Sdumbbell				radeon_suspend(rdev);
1482254885Sdumbbell				goto retry;
1483254885Sdumbbell			}
1484254885Sdumbbell		}
1485254885Sdumbbell	} else {
1486254885Sdumbbell		radeon_fence_driver_force_completion(rdev);
1487254885Sdumbbell		for (i = 0; i < RADEON_NUM_RINGS; ++i) {
1488254885Sdumbbell			free(ring_data[i], DRM_MEM_DRIVER);
1489254885Sdumbbell		}
1490254885Sdumbbell	}
1491254885Sdumbbell
1492254885Sdumbbell	drm_helper_resume_force_mode(rdev->ddev);
1493254885Sdumbbell
1494254885Sdumbbell	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
1495254885Sdumbbell	if (r) {
1496254885Sdumbbell		/* bad news, how to tell it to userspace ? */
1497254885Sdumbbell		dev_info(rdev->dev, "GPU reset failed\n");
1498254885Sdumbbell	}
1499254885Sdumbbell
1500254885Sdumbbell	sx_xunlock(&rdev->exclusive_lock);
1501254885Sdumbbell	return r;
1502254885Sdumbbell}
1503254885Sdumbbell
1504254885Sdumbbell
1505254885Sdumbbell/*
1506254885Sdumbbell * Debugfs
1507254885Sdumbbell */
1508282199Sdumbbell#ifdef FREEBSD_WIP
1509254885Sdumbbellint radeon_debugfs_add_files(struct radeon_device *rdev,
1510254885Sdumbbell			     struct drm_info_list *files,
1511254885Sdumbbell			     unsigned nfiles)
1512254885Sdumbbell{
1513254885Sdumbbell	unsigned i;
1514254885Sdumbbell
1515254885Sdumbbell	for (i = 0; i < rdev->debugfs_count; i++) {
1516254885Sdumbbell		if (rdev->debugfs[i].files == files) {
1517254885Sdumbbell			/* Already registered */
1518254885Sdumbbell			return 0;
1519254885Sdumbbell		}
1520254885Sdumbbell	}
1521254885Sdumbbell
1522254885Sdumbbell	i = rdev->debugfs_count + 1;
1523254885Sdumbbell	if (i > RADEON_DEBUGFS_MAX_COMPONENTS) {
1524254885Sdumbbell		DRM_ERROR("Reached maximum number of debugfs components.\n");
1525254885Sdumbbell		DRM_ERROR("Report so we increase "
1526254885Sdumbbell		          "RADEON_DEBUGFS_MAX_COMPONENTS.\n");
1527254885Sdumbbell		return -EINVAL;
1528254885Sdumbbell	}
1529254885Sdumbbell	rdev->debugfs[rdev->debugfs_count].files = files;
1530254885Sdumbbell	rdev->debugfs[rdev->debugfs_count].num_files = nfiles;
1531254885Sdumbbell	rdev->debugfs_count = i;
1532254885Sdumbbell#if defined(CONFIG_DEBUG_FS)
1533254885Sdumbbell	drm_debugfs_create_files(files, nfiles,
1534254885Sdumbbell				 rdev->ddev->control->debugfs_root,
1535254885Sdumbbell				 rdev->ddev->control);
1536254885Sdumbbell	drm_debugfs_create_files(files, nfiles,
1537254885Sdumbbell				 rdev->ddev->primary->debugfs_root,
1538254885Sdumbbell				 rdev->ddev->primary);
1539254885Sdumbbell#endif
1540254885Sdumbbell	return 0;
1541254885Sdumbbell}
1542254885Sdumbbell
1543254885Sdumbbellstatic void radeon_debugfs_remove_files(struct radeon_device *rdev)
1544254885Sdumbbell{
1545254885Sdumbbell#if defined(CONFIG_DEBUG_FS)
1546254885Sdumbbell	unsigned i;
1547254885Sdumbbell
1548254885Sdumbbell	for (i = 0; i < rdev->debugfs_count; i++) {
1549254885Sdumbbell		drm_debugfs_remove_files(rdev->debugfs[i].files,
1550254885Sdumbbell					 rdev->debugfs[i].num_files,
1551254885Sdumbbell					 rdev->ddev->control);
1552254885Sdumbbell		drm_debugfs_remove_files(rdev->debugfs[i].files,
1553254885Sdumbbell					 rdev->debugfs[i].num_files,
1554254885Sdumbbell					 rdev->ddev->primary);
1555254885Sdumbbell	}
1556254885Sdumbbell#endif
1557254885Sdumbbell}
1558254885Sdumbbell
1559254885Sdumbbell#if defined(CONFIG_DEBUG_FS)
1560254885Sdumbbellint radeon_debugfs_init(struct drm_minor *minor)
1561254885Sdumbbell{
1562254885Sdumbbell	return 0;
1563254885Sdumbbell}
1564254885Sdumbbell
1565254885Sdumbbellvoid radeon_debugfs_cleanup(struct drm_minor *minor)
1566254885Sdumbbell{
1567254885Sdumbbell}
1568282199Sdumbbell#endif /* FREEBSD_WIP */
1569254885Sdumbbell#endif
1570