i915_drv.c revision 277487
1235783Skib/* i915_drv.c -- Intel i915 driver -*- linux-c -*-
2235783Skib * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
3235783Skib */
4235783Skib/*-
5235783Skib * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6235783Skib * All Rights Reserved.
7235783Skib *
8235783Skib * Permission is hereby granted, free of charge, to any person obtaining a
9235783Skib * copy of this software and associated documentation files (the "Software"),
10235783Skib * to deal in the Software without restriction, including without limitation
11235783Skib * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12235783Skib * and/or sell copies of the Software, and to permit persons to whom the
13235783Skib * Software is furnished to do so, subject to the following conditions:
14235783Skib *
15235783Skib * The above copyright notice and this permission notice (including the next
16235783Skib * paragraph) shall be included in all copies or substantial portions of the
17235783Skib * Software.
18235783Skib *
19235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22235783Skib * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23235783Skib * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24235783Skib * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25235783Skib * OTHER DEALINGS IN THE SOFTWARE.
26235783Skib *
27235783Skib * Authors:
28235783Skib *    Gareth Hughes <gareth@valinux.com>
29235783Skib *
30235783Skib */
31235783Skib
32235783Skib#include <sys/cdefs.h>
33235783Skib__FBSDID("$FreeBSD: head/sys/dev/drm2/i915/i915_drv.c 277487 2015-01-21 16:10:37Z kib $");
34235783Skib
35235783Skib#include <dev/drm2/drmP.h>
36235783Skib#include <dev/drm2/drm.h>
37235783Skib#include <dev/drm2/drm_mm.h>
38235783Skib#include <dev/drm2/i915/i915_drm.h>
39235783Skib#include <dev/drm2/i915/i915_drv.h>
40235783Skib#include <dev/drm2/drm_pciids.h>
41235783Skib#include <dev/drm2/i915/intel_drv.h>
42235783Skib
43259016Sray#include "fb_if.h"
44259016Sray
45235783Skib/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
46235783Skibstatic drm_pci_id_list_t i915_pciidlist[] = {
47235783Skib	i915_PCI_IDS
48235783Skib};
49235783Skib
50235783Skibstatic const struct intel_device_info intel_i830_info = {
51235783Skib	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1,
52235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
53235783Skib};
54235783Skib
55235783Skibstatic const struct intel_device_info intel_845g_info = {
56235783Skib	.gen = 2,
57235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
58235783Skib};
59235783Skib
60235783Skibstatic const struct intel_device_info intel_i85x_info = {
61235783Skib	.gen = 2, .is_i85x = 1, .is_mobile = 1,
62235783Skib	.cursor_needs_physical = 1,
63235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
64235783Skib};
65235783Skib
66235783Skibstatic const struct intel_device_info intel_i865g_info = {
67235783Skib	.gen = 2,
68235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
69235783Skib};
70235783Skib
71235783Skibstatic const struct intel_device_info intel_i915g_info = {
72235783Skib	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1,
73235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
74235783Skib};
75235783Skibstatic const struct intel_device_info intel_i915gm_info = {
76235783Skib	.gen = 3, .is_mobile = 1,
77235783Skib	.cursor_needs_physical = 1,
78235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
79235783Skib	.supports_tv = 1,
80235783Skib};
81235783Skibstatic const struct intel_device_info intel_i945g_info = {
82235783Skib	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1,
83235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
84235783Skib};
85235783Skibstatic const struct intel_device_info intel_i945gm_info = {
86235783Skib	.gen = 3, .is_i945gm = 1, .is_mobile = 1,
87235783Skib	.has_hotplug = 1, .cursor_needs_physical = 1,
88235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
89235783Skib	.supports_tv = 1,
90235783Skib};
91235783Skib
92235783Skibstatic const struct intel_device_info intel_i965g_info = {
93235783Skib	.gen = 4, .is_broadwater = 1,
94235783Skib	.has_hotplug = 1,
95235783Skib	.has_overlay = 1,
96235783Skib};
97235783Skib
98235783Skibstatic const struct intel_device_info intel_i965gm_info = {
99235783Skib	.gen = 4, .is_crestline = 1,
100235783Skib	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
101235783Skib	.has_overlay = 1,
102235783Skib	.supports_tv = 1,
103235783Skib};
104235783Skib
105235783Skibstatic const struct intel_device_info intel_g33_info = {
106235783Skib	.gen = 3, .is_g33 = 1,
107235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
108235783Skib	.has_overlay = 1,
109235783Skib};
110235783Skib
111235783Skibstatic const struct intel_device_info intel_g45_info = {
112235783Skib	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1,
113235783Skib	.has_pipe_cxsr = 1, .has_hotplug = 1,
114235783Skib	.has_bsd_ring = 1,
115235783Skib};
116235783Skib
117235783Skibstatic const struct intel_device_info intel_gm45_info = {
118235783Skib	.gen = 4, .is_g4x = 1,
119235783Skib	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
120235783Skib	.has_pipe_cxsr = 1, .has_hotplug = 1,
121235783Skib	.supports_tv = 1,
122235783Skib	.has_bsd_ring = 1,
123235783Skib};
124235783Skib
125235783Skibstatic const struct intel_device_info intel_pineview_info = {
126235783Skib	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1,
127235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
128235783Skib	.has_overlay = 1,
129235783Skib};
130235783Skib
131235783Skibstatic const struct intel_device_info intel_ironlake_d_info = {
132235783Skib	.gen = 5,
133235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
134235783Skib	.has_bsd_ring = 1,
135277487Skib	.has_pch_split = 1,
136235783Skib};
137235783Skib
138235783Skibstatic const struct intel_device_info intel_ironlake_m_info = {
139235783Skib	.gen = 5, .is_mobile = 1,
140235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
141235783Skib	.has_fbc = 0, /* disabled due to buggy hardware */
142235783Skib	.has_bsd_ring = 1,
143277487Skib	.has_pch_split = 1,
144235783Skib};
145235783Skib
146235783Skibstatic const struct intel_device_info intel_sandybridge_d_info = {
147235783Skib	.gen = 6,
148235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
149235783Skib	.has_bsd_ring = 1,
150235783Skib	.has_blt_ring = 1,
151235783Skib	.has_llc = 1,
152277487Skib	.has_pch_split = 1,
153235783Skib};
154235783Skib
155235783Skibstatic const struct intel_device_info intel_sandybridge_m_info = {
156235783Skib	.gen = 6, .is_mobile = 1,
157235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
158235783Skib	.has_fbc = 1,
159235783Skib	.has_bsd_ring = 1,
160235783Skib	.has_blt_ring = 1,
161235783Skib	.has_llc = 1,
162277487Skib	.has_pch_split = 1,
163235783Skib};
164235783Skib
165235783Skibstatic const struct intel_device_info intel_ivybridge_d_info = {
166235783Skib	.is_ivybridge = 1, .gen = 7,
167235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
168235783Skib	.has_bsd_ring = 1,
169235783Skib	.has_blt_ring = 1,
170235783Skib	.has_llc = 1,
171277487Skib	.has_pch_split = 1,
172235783Skib};
173235783Skib
174235783Skibstatic const struct intel_device_info intel_ivybridge_m_info = {
175235783Skib	.is_ivybridge = 1, .gen = 7, .is_mobile = 1,
176235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
177235783Skib	.has_fbc = 0,	/* FBC is not enabled on Ivybridge mobile yet */
178235783Skib	.has_bsd_ring = 1,
179235783Skib	.has_blt_ring = 1,
180235783Skib	.has_llc = 1,
181277487Skib	.has_pch_split = 1,
182235783Skib};
183235783Skib
184277487Skib#if 0
185277487Skibstatic const struct intel_device_info intel_valleyview_m_info = {
186277487Skib	.gen = 7, .is_mobile = 1,
187277487Skib	.need_gfx_hws = 1, .has_hotplug = 1,
188277487Skib	.has_fbc = 0,
189277487Skib	.has_bsd_ring = 1,
190277487Skib	.has_blt_ring = 1,
191277487Skib	.is_valleyview = 1,
192277487Skib};
193277487Skib
194277487Skibstatic const struct intel_device_info intel_valleyview_d_info = {
195277487Skib	.gen = 7,
196277487Skib	.need_gfx_hws = 1, .has_hotplug = 1,
197277487Skib	.has_fbc = 0,
198277487Skib	.has_bsd_ring = 1,
199277487Skib	.has_blt_ring = 1,
200277487Skib	.is_valleyview = 1,
201277487Skib};
202277487Skib#endif
203277487Skib
204277487Skibstatic const struct intel_device_info intel_haswell_d_info = {
205277487Skib	.is_haswell = 1, .gen = 7,
206277487Skib	.need_gfx_hws = 1, .has_hotplug = 1,
207277487Skib	.has_bsd_ring = 1,
208277487Skib	.has_blt_ring = 1,
209277487Skib	.has_llc = 1,
210277487Skib	.has_pch_split = 1,
211277487Skib};
212277487Skib
213277487Skibstatic const struct intel_device_info intel_haswell_m_info = {
214277487Skib	.is_haswell = 1, .gen = 7, .is_mobile = 1,
215277487Skib	.need_gfx_hws = 1, .has_hotplug = 1,
216277487Skib	.has_bsd_ring = 1,
217277487Skib	.has_blt_ring = 1,
218277487Skib	.has_llc = 1,
219277487Skib	.has_pch_split = 1,
220277487Skib};
221277487Skib
222235783Skib#define INTEL_VGA_DEVICE(id, info_) {		\
223235783Skib	.device = id,				\
224235783Skib	.info = info_,				\
225235783Skib}
226235783Skib
227235783Skibstatic const struct intel_gfx_device_id {
228235783Skib	int device;
229235783Skib	const struct intel_device_info *info;
230235783Skib} pciidlist[] = {		/* aka */
231235783Skib	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
232235783Skib	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
233235783Skib	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
234235783Skib	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
235235783Skib	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
236235783Skib	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
237235783Skib	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
238235783Skib	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
239235783Skib	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
240235783Skib	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
241235783Skib	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
242235783Skib	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
243235783Skib	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
244235783Skib	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
245235783Skib	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
246235783Skib	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
247235783Skib	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
248235783Skib	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
249235783Skib	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
250235783Skib	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
251235783Skib	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
252235783Skib	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
253235783Skib	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
254235783Skib	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
255235783Skib	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
256235783Skib	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
257235783Skib	INTEL_VGA_DEVICE(0x2e92, &intel_g45_info),
258235783Skib	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
259235783Skib	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
260235783Skib	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
261235783Skib	INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
262235783Skib	INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
263235783Skib	INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info),
264235783Skib	INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info),
265235783Skib	INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
266235783Skib	INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
267235783Skib	INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
268235783Skib	INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
269235783Skib	INTEL_VGA_DEVICE(0x0156, &intel_ivybridge_m_info), /* GT1 mobile */
270235783Skib	INTEL_VGA_DEVICE(0x0166, &intel_ivybridge_m_info), /* GT2 mobile */
271235783Skib	INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
272235783Skib	INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
273235783Skib	INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
274235783Skib	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
275277487Skib	INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
276277487Skib	INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
277277487Skib	INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */
278277487Skib	INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */
279277487Skib	INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
280277487Skib	INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
281277487Skib	INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */
282235783Skib	{0, 0}
283235783Skib};
284235783Skib
285235783Skibstatic int i915_drm_freeze(struct drm_device *dev)
286235783Skib{
287235783Skib	struct drm_i915_private *dev_priv;
288235783Skib	int error;
289235783Skib
290235783Skib	dev_priv = dev->dev_private;
291235783Skib	drm_kms_helper_poll_disable(dev);
292235783Skib
293235783Skib#if 0
294235783Skib	pci_save_state(dev->pdev);
295235783Skib#endif
296235783Skib
297235783Skib	DRM_LOCK(dev);
298235783Skib	/* If KMS is active, we do the leavevt stuff here */
299235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
300235783Skib		error = -i915_gem_idle(dev);
301235783Skib		if (error) {
302235783Skib			DRM_UNLOCK(dev);
303235783Skib			device_printf(dev->device,
304235783Skib			    "GEM idle failed, resume might fail\n");
305235783Skib			return (error);
306235783Skib		}
307235783Skib		drm_irq_uninstall(dev);
308235783Skib	}
309235783Skib
310235783Skib	i915_save_state(dev);
311235783Skib
312235783Skib	intel_opregion_fini(dev);
313235783Skib
314235783Skib	/* Modeset on resume, not lid events */
315235783Skib	dev_priv->modeset_on_lid = 0;
316235783Skib	DRM_UNLOCK(dev);
317235783Skib
318235783Skib	return 0;
319235783Skib}
320235783Skib
321235783Skibstatic int
322235783Skibi915_suspend(device_t kdev)
323235783Skib{
324235783Skib	struct drm_device *dev;
325235783Skib	int error;
326235783Skib
327235783Skib	dev = device_get_softc(kdev);
328235783Skib	if (dev == NULL || dev->dev_private == NULL) {
329235783Skib		DRM_ERROR("DRM not initialized, aborting suspend.\n");
330235783Skib		return -ENODEV;
331235783Skib	}
332235783Skib
333235783Skib	DRM_DEBUG_KMS("starting suspend\n");
334235783Skib	error = i915_drm_freeze(dev);
335235783Skib	if (error)
336235783Skib		return (error);
337235783Skib
338235783Skib	error = bus_generic_suspend(kdev);
339235783Skib	DRM_DEBUG_KMS("finished suspend %d\n", error);
340235783Skib	return (error);
341235783Skib}
342235783Skib
343235783Skibstatic int i915_drm_thaw(struct drm_device *dev)
344235783Skib{
345235783Skib	struct drm_i915_private *dev_priv = dev->dev_private;
346235783Skib	int error = 0;
347235783Skib
348235783Skib	DRM_LOCK(dev);
349235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
350235783Skib		i915_gem_restore_gtt_mappings(dev);
351235783Skib	}
352235783Skib
353235783Skib	i915_restore_state(dev);
354235783Skib	intel_opregion_setup(dev);
355235783Skib
356235783Skib	/* KMS EnterVT equivalent */
357235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
358277487Skib		if (HAS_PCH_SPLIT(dev))
359277487Skib			ironlake_init_pch_refclk(dev);
360277487Skib
361235783Skib		dev_priv->mm.suspended = 0;
362235783Skib
363235783Skib		error = i915_gem_init_hw(dev);
364277487Skib		DRM_UNLOCK(dev);
365235783Skib
366277487Skib		intel_modeset_init_hw(dev);
367235783Skib		sx_xlock(&dev->mode_config.mutex);
368235783Skib		drm_mode_config_reset(dev);
369235783Skib		sx_xunlock(&dev->mode_config.mutex);
370235783Skib		drm_irq_install(dev);
371235783Skib
372235783Skib		sx_xlock(&dev->mode_config.mutex);
373235783Skib		/* Resume the modeset for every activated CRTC */
374235783Skib		drm_helper_resume_force_mode(dev);
375235783Skib		sx_xunlock(&dev->mode_config.mutex);
376235783Skib		DRM_LOCK(dev);
377235783Skib	}
378235783Skib
379235783Skib	intel_opregion_init(dev);
380235783Skib
381235783Skib	dev_priv->modeset_on_lid = 0;
382235783Skib
383235783Skib	DRM_UNLOCK(dev);
384235783Skib
385235783Skib	return error;
386235783Skib}
387235783Skib
388235783Skibstatic int
389235783Skibi915_resume(device_t kdev)
390235783Skib{
391235783Skib	struct drm_device *dev;
392235783Skib	int ret;
393235783Skib
394235783Skib	dev = device_get_softc(kdev);
395235783Skib	DRM_DEBUG_KMS("starting resume\n");
396235783Skib#if 0
397235783Skib	if (pci_enable_device(dev->pdev))
398235783Skib		return -EIO;
399235783Skib
400235783Skib	pci_set_master(dev->pdev);
401235783Skib#endif
402235783Skib
403235783Skib	ret = -i915_drm_thaw(dev);
404235783Skib	if (ret != 0)
405235783Skib		return (ret);
406235783Skib
407235783Skib	drm_kms_helper_poll_enable(dev);
408235783Skib	ret = bus_generic_resume(kdev);
409235783Skib	DRM_DEBUG_KMS("finished resume %d\n", ret);
410235783Skib	return (ret);
411235783Skib}
412235783Skib
413235783Skibstatic int
414235783Skibi915_probe(device_t kdev)
415235783Skib{
416235783Skib
417235783Skib	return drm_probe(kdev, i915_pciidlist);
418235783Skib}
419235783Skib
420235783Skibint i915_modeset;
421235783Skib
422235783Skibstatic int
423235783Skibi915_attach(device_t kdev)
424235783Skib{
425235783Skib	struct drm_device *dev;
426235783Skib
427235783Skib	dev = device_get_softc(kdev);
428235783Skib	if (i915_modeset == 1)
429235783Skib		i915_driver_info.driver_features |= DRIVER_MODESET;
430235783Skib	dev->driver = &i915_driver_info;
431235783Skib	return (drm_attach(kdev, i915_pciidlist));
432235783Skib}
433235783Skib
434259016Sraystatic struct fb_info *
435259016Srayi915_fb_helper_getinfo(device_t kdev)
436259016Sray{
437259016Sray	struct intel_fbdev *ifbdev;
438259016Sray	drm_i915_private_t *dev_priv;
439259016Sray	struct drm_device *dev;
440259016Sray	struct fb_info *info;
441259016Sray
442259016Sray	dev = device_get_softc(kdev);
443259016Sray	dev_priv = dev->dev_private;
444259016Sray	ifbdev = dev_priv->fbdev;
445259016Sray	if (ifbdev == NULL)
446259016Sray		return (NULL);
447259016Sray
448259016Sray	info = ifbdev->helper.fbdev;
449259016Sray
450259016Sray	return (info);
451259016Sray}
452259016Sray
453235783Skibconst struct intel_device_info *
454235783Skibi915_get_device_id(int device)
455235783Skib{
456235783Skib	const struct intel_gfx_device_id *did;
457235783Skib
458235783Skib	for (did = &pciidlist[0]; did->device != 0; did++) {
459235783Skib		if (did->device != device)
460235783Skib			continue;
461235783Skib		return (did->info);
462235783Skib	}
463235783Skib	return (NULL);
464235783Skib}
465235783Skib
466235783Skibstatic device_method_t i915_methods[] = {
467235783Skib	/* Device interface */
468235783Skib	DEVMETHOD(device_probe,		i915_probe),
469235783Skib	DEVMETHOD(device_attach,	i915_attach),
470235783Skib	DEVMETHOD(device_suspend,	i915_suspend),
471235783Skib	DEVMETHOD(device_resume,	i915_resume),
472235783Skib	DEVMETHOD(device_detach,	drm_detach),
473259016Sray
474259016Sray	/* Framebuffer service methods */
475259016Sray	DEVMETHOD(fb_getinfo,		i915_fb_helper_getinfo),
476259016Sray
477235783Skib	DEVMETHOD_END
478235783Skib};
479235783Skib
480235783Skibstatic driver_t i915_driver = {
481235783Skib	"drmn",
482235783Skib	i915_methods,
483235783Skib	sizeof(struct drm_device)
484235783Skib};
485235783Skib
486235783Skibextern devclass_t drm_devclass;
487235783SkibDRIVER_MODULE_ORDERED(i915kms, vgapci, i915_driver, drm_devclass, 0, 0,
488235783Skib    SI_ORDER_ANY);
489235783SkibMODULE_DEPEND(i915kms, drmn, 1, 1, 1);
490235783SkibMODULE_DEPEND(i915kms, agp, 1, 1, 1);
491235783SkibMODULE_DEPEND(i915kms, iicbus, 1, 1, 1);
492235783SkibMODULE_DEPEND(i915kms, iic, 1, 1, 1);
493235783SkibMODULE_DEPEND(i915kms, iicbb, 1, 1, 1);
494235783Skib
495235783Skibint intel_iommu_enabled = 0;
496235783SkibTUNABLE_INT("drm.i915.intel_iommu_enabled", &intel_iommu_enabled);
497277487Skibint intel_iommu_gfx_mapped = 0;
498277487SkibTUNABLE_INT("drm.i915.intel_iommu_gfx_mapped", &intel_iommu_gfx_mapped);
499235783Skib
500277487Skibint i915_prefault_disable;
501277487SkibTUNABLE_INT("drm.i915.prefault_disable", &i915_prefault_disable);
502235783Skibint i915_semaphores = -1;
503235783SkibTUNABLE_INT("drm.i915.semaphores", &i915_semaphores);
504235783Skibstatic int i915_try_reset = 1;
505235783SkibTUNABLE_INT("drm.i915.try_reset", &i915_try_reset);
506235783Skibunsigned int i915_lvds_downclock = 0;
507235783SkibTUNABLE_INT("drm.i915.lvds_downclock", &i915_lvds_downclock);
508235783Skibint i915_vbt_sdvo_panel_type = -1;
509235783SkibTUNABLE_INT("drm.i915.vbt_sdvo_panel_type", &i915_vbt_sdvo_panel_type);
510235783Skibunsigned int i915_powersave = 1;
511235783SkibTUNABLE_INT("drm.i915.powersave", &i915_powersave);
512235783Skibint i915_enable_fbc = 0;
513235783SkibTUNABLE_INT("drm.i915.enable_fbc", &i915_enable_fbc);
514235783Skibint i915_enable_rc6 = 0;
515235783SkibTUNABLE_INT("drm.i915.enable_rc6", &i915_enable_rc6);
516277487Skibint i915_lvds_channel_mode;
517277487SkibTUNABLE_INT("drm.i915.lvds_channel_mode", &i915_lvds_channel_mode);
518235783Skibint i915_panel_use_ssc = -1;
519235783SkibTUNABLE_INT("drm.i915.panel_use_ssc", &i915_panel_use_ssc);
520235783Skibint i915_panel_ignore_lid = 0;
521235783SkibTUNABLE_INT("drm.i915.panel_ignore_lid", &i915_panel_ignore_lid);
522277487Skibint i915_panel_invert_brightness;
523277487SkibTUNABLE_INT("drm.i915.panel_invert_brightness", &i915_panel_invert_brightness);
524235783Skibint i915_modeset = 1;
525235783SkibTUNABLE_INT("drm.i915.modeset", &i915_modeset);
526235783Skibint i915_enable_ppgtt = -1;
527235783SkibTUNABLE_INT("drm.i915.enable_ppgtt", &i915_enable_ppgtt);
528235783Skibint i915_enable_hangcheck = 1;
529235783SkibTUNABLE_INT("drm.i915.enable_hangcheck", &i915_enable_hangcheck);
530235783Skib
531235783Skib#define	PCI_VENDOR_INTEL		0x8086
532235783Skib#define INTEL_PCH_DEVICE_ID_MASK	0xff00
533235783Skib#define INTEL_PCH_IBX_DEVICE_ID_TYPE	0x3b00
534235783Skib#define INTEL_PCH_CPT_DEVICE_ID_TYPE	0x1c00
535235783Skib#define INTEL_PCH_PPT_DEVICE_ID_TYPE	0x1e00
536277487Skib#define INTEL_PCH_LPT_DEVICE_ID_TYPE	0x8c00
537235783Skib
538277487Skibvoid intel_detect_pch(struct drm_device *dev)
539235783Skib{
540235783Skib	struct drm_i915_private *dev_priv;
541235783Skib	device_t pch;
542235783Skib	uint32_t id;
543235783Skib
544235783Skib	dev_priv = dev->dev_private;
545235783Skib	pch = pci_find_class(PCIC_BRIDGE, PCIS_BRIDGE_ISA);
546235783Skib	if (pch != NULL && pci_get_vendor(pch) == PCI_VENDOR_INTEL) {
547235783Skib		id = pci_get_device(pch) & INTEL_PCH_DEVICE_ID_MASK;
548235783Skib		if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
549235783Skib			dev_priv->pch_type = PCH_IBX;
550277487Skib			dev_priv->num_pch_pll = 2;
551235783Skib			DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
552235783Skib		} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
553235783Skib			dev_priv->pch_type = PCH_CPT;
554277487Skib			dev_priv->num_pch_pll = 2;
555235783Skib			DRM_DEBUG_KMS("Found CougarPoint PCH\n");
556235783Skib		} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
557235783Skib			/* PantherPoint is CPT compatible */
558235783Skib			dev_priv->pch_type = PCH_CPT;
559277487Skib			dev_priv->num_pch_pll = 2;
560235783Skib			DRM_DEBUG_KMS("Found PatherPoint PCH\n");
561277487Skib		} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
562277487Skib			dev_priv->pch_type = PCH_LPT;
563277487Skib			dev_priv->num_pch_pll = 0;
564277487Skib			DRM_DEBUG_KMS("Found LynxPoint PCH\n");
565235783Skib		} else
566235783Skib			DRM_DEBUG_KMS("No PCH detected\n");
567277487Skib		KASSERT(dev_priv->num_pch_pll <= I915_NUM_PLLS,
568277487Skib		    ("num_pch_pll %d\n", dev_priv->num_pch_pll));
569235783Skib	} else
570235783Skib		DRM_DEBUG_KMS("No Intel PCI-ISA bridge found\n");
571235783Skib}
572235783Skib
573277487Skibbool i915_semaphore_is_enabled(struct drm_device *dev)
574277487Skib{
575277487Skib	if (INTEL_INFO(dev)->gen < 6)
576277487Skib		return 0;
577277487Skib
578277487Skib	if (i915_semaphores >= 0)
579277487Skib		return i915_semaphores;
580277487Skib
581277487Skib	/* Enable semaphores on SNB when IO remapping is off */
582277487Skib	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
583277487Skib		return false;
584277487Skib
585277487Skib	return 1;
586277487Skib}
587277487Skib
588235783Skibvoid
589235783Skib__gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
590235783Skib{
591235783Skib	int count;
592235783Skib
593235783Skib	count = 0;
594235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
595240917Smav		DELAY(10);
596235783Skib
597235783Skib	I915_WRITE_NOTRACE(FORCEWAKE, 1);
598235783Skib	POSTING_READ(FORCEWAKE);
599235783Skib
600235783Skib	count = 0;
601235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0)
602240917Smav		DELAY(10);
603235783Skib}
604235783Skib
605235783Skibvoid
606235783Skib__gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
607235783Skib{
608235783Skib	int count;
609235783Skib
610235783Skib	count = 0;
611235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
612240917Smav		DELAY(10);
613235783Skib
614277487Skib	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
615235783Skib	POSTING_READ(FORCEWAKE_MT);
616235783Skib
617235783Skib	count = 0;
618235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
619240917Smav		DELAY(10);
620235783Skib}
621235783Skib
622235783Skibvoid
623235783Skibgen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
624235783Skib{
625235783Skib
626235783Skib	mtx_lock(&dev_priv->gt_lock);
627235783Skib	if (dev_priv->forcewake_count++ == 0)
628235783Skib		dev_priv->display.force_wake_get(dev_priv);
629235783Skib	mtx_unlock(&dev_priv->gt_lock);
630235783Skib}
631235783Skib
632235783Skibstatic void
633235783Skibgen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
634235783Skib{
635235783Skib	u32 gtfifodbg;
636235783Skib
637235783Skib	gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
638235783Skib	if ((gtfifodbg & GT_FIFO_CPU_ERROR_MASK) != 0) {
639235783Skib		printf("MMIO read or write has been dropped %x\n", gtfifodbg);
640235783Skib		I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
641235783Skib	}
642235783Skib}
643235783Skib
644235783Skibvoid
645235783Skib__gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
646235783Skib{
647235783Skib
648235783Skib	I915_WRITE_NOTRACE(FORCEWAKE, 0);
649235783Skib	/* The below doubles as a POSTING_READ */
650235783Skib	gen6_gt_check_fifodbg(dev_priv);
651235783Skib}
652235783Skib
653235783Skibvoid
654235783Skib__gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
655235783Skib{
656235783Skib
657277487Skib	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
658235783Skib	/* The below doubles as a POSTING_READ */
659235783Skib	gen6_gt_check_fifodbg(dev_priv);
660235783Skib}
661235783Skib
662235783Skibvoid
663235783Skibgen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
664235783Skib{
665235783Skib
666235783Skib	mtx_lock(&dev_priv->gt_lock);
667235783Skib	if (--dev_priv->forcewake_count == 0)
668235783Skib 		dev_priv->display.force_wake_put(dev_priv);
669235783Skib	mtx_unlock(&dev_priv->gt_lock);
670235783Skib}
671235783Skib
672235783Skibint
673235783Skib__gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
674235783Skib{
675235783Skib	int ret = 0;
676235783Skib
677235783Skib	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
678235783Skib		int loop = 500;
679235783Skib		u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
680235783Skib		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
681240917Smav			DELAY(10);
682235783Skib			fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
683235783Skib		}
684235783Skib		if (loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES) {
685235783Skib			printf("%s loop\n", __func__);
686235783Skib			++ret;
687235783Skib		}
688235783Skib		dev_priv->gt_fifo_count = fifo;
689235783Skib	}
690235783Skib	dev_priv->gt_fifo_count--;
691235783Skib
692235783Skib	return (ret);
693235783Skib}
694235783Skib
695277487Skibvoid vlv_force_wake_get(struct drm_i915_private *dev_priv)
696277487Skib{
697277487Skib	int count;
698277487Skib
699277487Skib	count = 0;
700277487Skib
701277487Skib	/* Already awake? */
702277487Skib	if ((I915_READ(0x130094) & 0xa1) == 0xa1)
703277487Skib		return;
704277487Skib
705277487Skib	I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
706277487Skib	POSTING_READ(FORCEWAKE_VLV);
707277487Skib
708277487Skib	count = 0;
709277487Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0)
710277487Skib		DELAY(10);
711277487Skib}
712277487Skib
713277487Skibvoid vlv_force_wake_put(struct drm_i915_private *dev_priv)
714277487Skib{
715277487Skib	I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000);
716277487Skib	/* FIXME: confirm VLV behavior with Punit folks */
717277487Skib	POSTING_READ(FORCEWAKE_VLV);
718277487Skib}
719277487Skib
720235783Skibstatic int
721271705Sdumbbelli8xx_do_reset(struct drm_device *dev)
722235783Skib{
723235783Skib	struct drm_i915_private *dev_priv = dev->dev_private;
724235783Skib	int onems;
725235783Skib
726235783Skib	if (IS_I85X(dev))
727235783Skib		return -ENODEV;
728235783Skib
729235783Skib	onems = hz / 1000;
730235783Skib	if (onems == 0)
731235783Skib		onems = 1;
732235783Skib
733235783Skib	I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
734235783Skib	POSTING_READ(D_STATE);
735235783Skib
736235783Skib	if (IS_I830(dev) || IS_845G(dev)) {
737235783Skib		I915_WRITE(DEBUG_RESET_I830,
738235783Skib			   DEBUG_RESET_DISPLAY |
739235783Skib			   DEBUG_RESET_RENDER |
740235783Skib			   DEBUG_RESET_FULL);
741235783Skib		POSTING_READ(DEBUG_RESET_I830);
742235783Skib		pause("i8xxrst1", onems);
743235783Skib
744235783Skib		I915_WRITE(DEBUG_RESET_I830, 0);
745235783Skib		POSTING_READ(DEBUG_RESET_I830);
746235783Skib	}
747235783Skib
748235783Skib	pause("i8xxrst2", onems);
749235783Skib
750235783Skib	I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
751235783Skib	POSTING_READ(D_STATE);
752235783Skib
753235783Skib	return 0;
754235783Skib}
755235783Skib
756235783Skibstatic int
757235783Skibi965_reset_complete(struct drm_device *dev)
758235783Skib{
759235783Skib	u8 gdrst;
760235783Skib
761235783Skib	gdrst = pci_read_config(dev->device, I965_GDRST, 1);
762277487Skib	return (gdrst & GRDOM_RESET_ENABLE) == 0;
763235783Skib}
764235783Skib
765235783Skibstatic int
766271705Sdumbbelli965_do_reset(struct drm_device *dev)
767235783Skib{
768277487Skib	int ret;
769235783Skib	u8 gdrst;
770235783Skib
771235783Skib	/*
772235783Skib	 * Set the domains we want to reset (GRDOM/bits 2 and 3) as
773235783Skib	 * well as the reset bit (GR/bit 0).  Setting the GR bit
774235783Skib	 * triggers the reset; when done, the hardware will clear it.
775235783Skib	 */
776235783Skib	gdrst = pci_read_config(dev->device, I965_GDRST, 1);
777271705Sdumbbell	pci_write_config(dev->device, I965_GDRST,
778271705Sdumbbell	    gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE, 1);
779235783Skib
780277487Skib	ret =  wait_for(i965_reset_complete(dev), 500);
781277487Skib	if (ret)
782277487Skib		return ret;
783277487Skib
784277487Skib	/* We can't reset render&media without also resetting display ... */
785277487Skib	gdrst = pci_read_config(dev->device, I965_GDRST, 1);
786277487Skib	pci_write_config(dev->device, I965_GDRST,
787277487Skib			 gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE, 1);
788277487Skib
789277487Skib 	return wait_for(i965_reset_complete(dev), 500);
790235783Skib}
791235783Skib
792235783Skibstatic int
793271705Sdumbbellironlake_do_reset(struct drm_device *dev)
794235783Skib{
795235783Skib	struct drm_i915_private *dev_priv;
796235783Skib	u32 gdrst;
797277487Skib	int ret;
798235783Skib
799235783Skib	dev_priv = dev->dev_private;
800235783Skib	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
801271705Sdumbbell	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
802277487Skib		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
803277487Skib	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
804277487Skib	if (ret)
805277487Skib		return ret;
806277487Skib
807277487Skib	/* We can't reset render&media without also resetting display ... */
808277487Skib	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
809277487Skib	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
810277487Skib		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
811277487Skib 	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
812235783Skib}
813235783Skib
814235783Skibstatic int
815271705Sdumbbellgen6_do_reset(struct drm_device *dev)
816235783Skib{
817235783Skib	struct drm_i915_private *dev_priv;
818235783Skib	int ret;
819235783Skib
820235783Skib	dev_priv = dev->dev_private;
821235783Skib
822235783Skib	/* Hold gt_lock across reset to prevent any register access
823235783Skib	 * with forcewake not set correctly
824235783Skib	 */
825235783Skib	mtx_lock(&dev_priv->gt_lock);
826235783Skib
827235783Skib	/* Reset the chip */
828235783Skib
829235783Skib	/* GEN6_GDRST is not in the gt power well, no need to check
830235783Skib	 * for fifo space for the write or forcewake the chip for
831235783Skib	 * the read
832235783Skib	 */
833235783Skib	I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
834235783Skib
835235783Skib	/* Spin waiting for the device to ack the reset request */
836235783Skib	ret = _intel_wait_for(dev,
837256848Skib	    (I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0,
838277487Skib	    500, 0, "915rst");
839235783Skib
840235783Skib	/* If reset with a user forcewake, try to restore, otherwise turn it off */
841235783Skib 	if (dev_priv->forcewake_count)
842235783Skib 		dev_priv->display.force_wake_get(dev_priv);
843235783Skib	else
844235783Skib		dev_priv->display.force_wake_put(dev_priv);
845235783Skib
846235783Skib	/* Restore fifo count */
847235783Skib	dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
848235783Skib
849235783Skib	mtx_unlock(&dev_priv->gt_lock);
850235783Skib	return (ret);
851235783Skib}
852235783Skib
853277487Skibint
854277487Skibintel_gpu_reset(struct drm_device *dev)
855271705Sdumbbell{
856271705Sdumbbell	struct drm_i915_private *dev_priv = dev->dev_private;
857271705Sdumbbell	int ret = -ENODEV;
858271705Sdumbbell
859271705Sdumbbell	switch (INTEL_INFO(dev)->gen) {
860271705Sdumbbell	case 7:
861271705Sdumbbell	case 6:
862271705Sdumbbell		ret = gen6_do_reset(dev);
863271705Sdumbbell		break;
864271705Sdumbbell	case 5:
865271705Sdumbbell		ret = ironlake_do_reset(dev);
866271705Sdumbbell		break;
867271705Sdumbbell	case 4:
868271705Sdumbbell		ret = i965_do_reset(dev);
869271705Sdumbbell		break;
870271705Sdumbbell	case 2:
871271705Sdumbbell		ret = i8xx_do_reset(dev);
872271705Sdumbbell		break;
873271705Sdumbbell	}
874271705Sdumbbell
875271705Sdumbbell	/* Also reset the gpu hangman. */
876271705Sdumbbell	if (dev_priv->stop_rings) {
877271705Sdumbbell		DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n");
878271705Sdumbbell		dev_priv->stop_rings = 0;
879271705Sdumbbell		if (ret == -ENODEV) {
880271705Sdumbbell			DRM_ERROR("Reset not implemented, but ignoring "
881271705Sdumbbell				  "error for simulated gpu hangs\n");
882271705Sdumbbell			ret = 0;
883271705Sdumbbell		}
884271705Sdumbbell	}
885271705Sdumbbell
886271705Sdumbbell	return ret;
887271705Sdumbbell}
888271705Sdumbbell
889277487Skibint i915_reset(struct drm_device *dev)
890235783Skib{
891235783Skib	drm_i915_private_t *dev_priv = dev->dev_private;
892235783Skib	int ret;
893235783Skib
894235783Skib	if (!i915_try_reset)
895235783Skib		return (0);
896235783Skib
897235783Skib	if (!sx_try_xlock(&dev->dev_struct_lock))
898235783Skib		return (-EBUSY);
899235783Skib
900277487Skib	dev_priv->stop_rings = 0;
901277487Skib
902235783Skib	i915_gem_reset(dev);
903235783Skib
904235783Skib	ret = -ENODEV;
905277487Skib	if (time_second - dev_priv->last_gpu_reset < 5)
906235783Skib		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
907277487Skib	else
908271705Sdumbbell		ret = intel_gpu_reset(dev);
909271705Sdumbbell
910235783Skib	dev_priv->last_gpu_reset = time_second;
911235783Skib	if (ret) {
912235783Skib		DRM_ERROR("Failed to reset chip.\n");
913235783Skib		DRM_UNLOCK(dev);
914235783Skib		return (ret);
915235783Skib	}
916235783Skib
917235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
918235783Skib	    !dev_priv->mm.suspended) {
919277487Skib		struct intel_ring_buffer *ring;
920277487Skib		int i;
921277487Skib
922235783Skib		dev_priv->mm.suspended = 0;
923235783Skib
924235783Skib		i915_gem_init_swizzling(dev);
925235783Skib
926277487Skib		for_each_ring(ring, dev_priv, i)
927277487Skib			ring->init(ring);
928235783Skib
929271705Sdumbbell		i915_gem_context_init(dev);
930235783Skib		i915_gem_init_ppgtt(dev);
931235783Skib
932277487Skib		DRM_UNLOCK(dev);
933277487Skib
934277487Skib		if (drm_core_check_feature(dev, DRIVER_MODESET))
935277487Skib			intel_modeset_init_hw(dev);
936277487Skib
937277487Skib		DRM_LOCK(dev);
938235783Skib		drm_irq_uninstall(dev);
939235783Skib		DRM_UNLOCK(dev);
940235783Skib		drm_irq_install(dev);
941277487Skib	} else
942277487Skib		DRM_UNLOCK(dev);
943235783Skib
944235783Skib	return (0);
945235783Skib}
946235783Skib
947277487Skib/* We give fast paths for the really cool registers */
948277487Skib#define NEEDS_FORCE_WAKE(dev_priv, reg) \
949277487Skib       (((dev_priv)->info->gen >= 6) && \
950277487Skib        ((reg) < 0x40000) &&            \
951277487Skib        ((reg) != FORCEWAKE)) && \
952277487Skib       (!IS_VALLEYVIEW((dev_priv)->dev))
953277487Skib
954235783Skib#define __i915_read(x, y) \
955235783Skibu##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
956235783Skib	u##x val = 0; \
957235783Skib	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
958235783Skib		mtx_lock(&dev_priv->gt_lock); \
959235783Skib		if (dev_priv->forcewake_count == 0) \
960235783Skib			dev_priv->display.force_wake_get(dev_priv); \
961235783Skib		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
962235783Skib		if (dev_priv->forcewake_count == 0) \
963235783Skib			dev_priv->display.force_wake_put(dev_priv); \
964235783Skib		mtx_unlock(&dev_priv->gt_lock); \
965235783Skib	} else { \
966235783Skib		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
967235783Skib	} \
968235783Skib	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
969235783Skib	return val; \
970235783Skib}
971235783Skib
972235783Skib__i915_read(8, 8)
973235783Skib__i915_read(16, 16)
974235783Skib__i915_read(32, 32)
975235783Skib__i915_read(64, 64)
976235783Skib#undef __i915_read
977235783Skib
978235783Skib#define __i915_write(x, y) \
979235783Skibvoid i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
980235783Skib	u32 __fifo_ret = 0; \
981235783Skib	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
982235783Skib	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
983235783Skib		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
984235783Skib	} \
985235783Skib	DRM_WRITE##y(dev_priv->mmio_map, reg, val); \
986235783Skib	if (__predict_false(__fifo_ret)) { \
987235783Skib		gen6_gt_check_fifodbg(dev_priv); \
988235783Skib	} \
989235783Skib}
990235783Skib__i915_write(8, 8)
991235783Skib__i915_write(16, 16)
992235783Skib__i915_write(32, 32)
993235783Skib__i915_write(64, 64)
994235783Skib#undef __i915_write
995