i915_drv.c revision 271705
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 271705 2014-09-17 08:28:50Z dumbbell $");
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,
135235783Skib};
136235783Skib
137235783Skibstatic const struct intel_device_info intel_ironlake_m_info = {
138235783Skib	.gen = 5, .is_mobile = 1,
139235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
140235783Skib	.has_fbc = 0, /* disabled due to buggy hardware */
141235783Skib	.has_bsd_ring = 1,
142235783Skib};
143235783Skib
144235783Skibstatic const struct intel_device_info intel_sandybridge_d_info = {
145235783Skib	.gen = 6,
146235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
147235783Skib	.has_bsd_ring = 1,
148235783Skib	.has_blt_ring = 1,
149235783Skib	.has_llc = 1,
150235783Skib};
151235783Skib
152235783Skibstatic const struct intel_device_info intel_sandybridge_m_info = {
153235783Skib	.gen = 6, .is_mobile = 1,
154235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
155235783Skib	.has_fbc = 1,
156235783Skib	.has_bsd_ring = 1,
157235783Skib	.has_blt_ring = 1,
158235783Skib	.has_llc = 1,
159235783Skib};
160235783Skib
161235783Skibstatic const struct intel_device_info intel_ivybridge_d_info = {
162235783Skib	.is_ivybridge = 1, .gen = 7,
163235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
164235783Skib	.has_bsd_ring = 1,
165235783Skib	.has_blt_ring = 1,
166235783Skib	.has_llc = 1,
167235783Skib};
168235783Skib
169235783Skibstatic const struct intel_device_info intel_ivybridge_m_info = {
170235783Skib	.is_ivybridge = 1, .gen = 7, .is_mobile = 1,
171235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
172235783Skib	.has_fbc = 0,	/* FBC is not enabled on Ivybridge mobile yet */
173235783Skib	.has_bsd_ring = 1,
174235783Skib	.has_blt_ring = 1,
175235783Skib	.has_llc = 1,
176235783Skib};
177235783Skib
178235783Skib#define INTEL_VGA_DEVICE(id, info_) {		\
179235783Skib	.device = id,				\
180235783Skib	.info = info_,				\
181235783Skib}
182235783Skib
183235783Skibstatic const struct intel_gfx_device_id {
184235783Skib	int device;
185235783Skib	const struct intel_device_info *info;
186235783Skib} pciidlist[] = {		/* aka */
187235783Skib	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
188235783Skib	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
189235783Skib	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
190235783Skib	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
191235783Skib	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
192235783Skib	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
193235783Skib	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
194235783Skib	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
195235783Skib	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
196235783Skib	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
197235783Skib	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
198235783Skib	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
199235783Skib	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
200235783Skib	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
201235783Skib	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
202235783Skib	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
203235783Skib	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
204235783Skib	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
205235783Skib	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
206235783Skib	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
207235783Skib	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
208235783Skib	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
209235783Skib	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
210235783Skib	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
211235783Skib	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
212235783Skib	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
213235783Skib	INTEL_VGA_DEVICE(0x2e92, &intel_g45_info),
214235783Skib	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
215235783Skib	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
216235783Skib	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
217235783Skib	INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
218235783Skib	INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
219235783Skib	INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info),
220235783Skib	INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info),
221235783Skib	INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
222235783Skib	INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
223235783Skib	INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
224235783Skib	INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
225235783Skib	INTEL_VGA_DEVICE(0x0156, &intel_ivybridge_m_info), /* GT1 mobile */
226235783Skib	INTEL_VGA_DEVICE(0x0166, &intel_ivybridge_m_info), /* GT2 mobile */
227235783Skib	INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
228235783Skib	INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
229235783Skib	INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
230235783Skib	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
231235783Skib	{0, 0}
232235783Skib};
233235783Skib
234235783Skibstatic int i915_drm_freeze(struct drm_device *dev)
235235783Skib{
236235783Skib	struct drm_i915_private *dev_priv;
237235783Skib	int error;
238235783Skib
239235783Skib	dev_priv = dev->dev_private;
240235783Skib	drm_kms_helper_poll_disable(dev);
241235783Skib
242235783Skib#if 0
243235783Skib	pci_save_state(dev->pdev);
244235783Skib#endif
245235783Skib
246235783Skib	DRM_LOCK(dev);
247235783Skib	/* If KMS is active, we do the leavevt stuff here */
248235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
249235783Skib		error = -i915_gem_idle(dev);
250235783Skib		if (error) {
251235783Skib			DRM_UNLOCK(dev);
252235783Skib			device_printf(dev->device,
253235783Skib			    "GEM idle failed, resume might fail\n");
254235783Skib			return (error);
255235783Skib		}
256235783Skib		drm_irq_uninstall(dev);
257235783Skib	}
258235783Skib
259235783Skib	i915_save_state(dev);
260235783Skib
261235783Skib	intel_opregion_fini(dev);
262235783Skib
263235783Skib	/* Modeset on resume, not lid events */
264235783Skib	dev_priv->modeset_on_lid = 0;
265235783Skib	DRM_UNLOCK(dev);
266235783Skib
267235783Skib	return 0;
268235783Skib}
269235783Skib
270235783Skibstatic int
271235783Skibi915_suspend(device_t kdev)
272235783Skib{
273235783Skib	struct drm_device *dev;
274235783Skib	int error;
275235783Skib
276235783Skib	dev = device_get_softc(kdev);
277235783Skib	if (dev == NULL || dev->dev_private == NULL) {
278235783Skib		DRM_ERROR("DRM not initialized, aborting suspend.\n");
279235783Skib		return -ENODEV;
280235783Skib	}
281235783Skib
282235783Skib	DRM_DEBUG_KMS("starting suspend\n");
283235783Skib	error = i915_drm_freeze(dev);
284235783Skib	if (error)
285235783Skib		return (error);
286235783Skib
287235783Skib	error = bus_generic_suspend(kdev);
288235783Skib	DRM_DEBUG_KMS("finished suspend %d\n", error);
289235783Skib	return (error);
290235783Skib}
291235783Skib
292235783Skibstatic int i915_drm_thaw(struct drm_device *dev)
293235783Skib{
294235783Skib	struct drm_i915_private *dev_priv = dev->dev_private;
295235783Skib	int error = 0;
296235783Skib
297235783Skib	DRM_LOCK(dev);
298235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
299235783Skib		i915_gem_restore_gtt_mappings(dev);
300235783Skib	}
301235783Skib
302235783Skib	i915_restore_state(dev);
303235783Skib	intel_opregion_setup(dev);
304235783Skib
305235783Skib	/* KMS EnterVT equivalent */
306235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
307235783Skib		dev_priv->mm.suspended = 0;
308235783Skib
309235783Skib		error = i915_gem_init_hw(dev);
310235783Skib
311235783Skib		if (HAS_PCH_SPLIT(dev))
312235783Skib			ironlake_init_pch_refclk(dev);
313235783Skib
314235783Skib		DRM_UNLOCK(dev);
315235783Skib		sx_xlock(&dev->mode_config.mutex);
316235783Skib		drm_mode_config_reset(dev);
317235783Skib		sx_xunlock(&dev->mode_config.mutex);
318235783Skib		drm_irq_install(dev);
319235783Skib
320235783Skib		sx_xlock(&dev->mode_config.mutex);
321235783Skib		/* Resume the modeset for every activated CRTC */
322235783Skib		drm_helper_resume_force_mode(dev);
323235783Skib		sx_xunlock(&dev->mode_config.mutex);
324235783Skib
325235783Skib		if (IS_IRONLAKE_M(dev))
326235783Skib			ironlake_enable_rc6(dev);
327235783Skib		DRM_LOCK(dev);
328235783Skib	}
329235783Skib
330235783Skib	intel_opregion_init(dev);
331235783Skib
332235783Skib	dev_priv->modeset_on_lid = 0;
333235783Skib
334235783Skib	DRM_UNLOCK(dev);
335235783Skib
336235783Skib	return error;
337235783Skib}
338235783Skib
339235783Skibstatic int
340235783Skibi915_resume(device_t kdev)
341235783Skib{
342235783Skib	struct drm_device *dev;
343235783Skib	int ret;
344235783Skib
345235783Skib	dev = device_get_softc(kdev);
346235783Skib	DRM_DEBUG_KMS("starting resume\n");
347235783Skib#if 0
348235783Skib	if (pci_enable_device(dev->pdev))
349235783Skib		return -EIO;
350235783Skib
351235783Skib	pci_set_master(dev->pdev);
352235783Skib#endif
353235783Skib
354235783Skib	ret = -i915_drm_thaw(dev);
355235783Skib	if (ret != 0)
356235783Skib		return (ret);
357235783Skib
358235783Skib	drm_kms_helper_poll_enable(dev);
359235783Skib	ret = bus_generic_resume(kdev);
360235783Skib	DRM_DEBUG_KMS("finished resume %d\n", ret);
361235783Skib	return (ret);
362235783Skib}
363235783Skib
364235783Skibstatic int
365235783Skibi915_probe(device_t kdev)
366235783Skib{
367235783Skib
368235783Skib	return drm_probe(kdev, i915_pciidlist);
369235783Skib}
370235783Skib
371235783Skibint i915_modeset;
372235783Skib
373235783Skibstatic int
374235783Skibi915_attach(device_t kdev)
375235783Skib{
376235783Skib	struct drm_device *dev;
377235783Skib
378235783Skib	dev = device_get_softc(kdev);
379235783Skib	if (i915_modeset == 1)
380235783Skib		i915_driver_info.driver_features |= DRIVER_MODESET;
381235783Skib	dev->driver = &i915_driver_info;
382235783Skib	return (drm_attach(kdev, i915_pciidlist));
383235783Skib}
384235783Skib
385259016Sraystatic struct fb_info *
386259016Srayi915_fb_helper_getinfo(device_t kdev)
387259016Sray{
388259016Sray	struct intel_fbdev *ifbdev;
389259016Sray	drm_i915_private_t *dev_priv;
390259016Sray	struct drm_device *dev;
391259016Sray	struct fb_info *info;
392259016Sray
393259016Sray	dev = device_get_softc(kdev);
394259016Sray	dev_priv = dev->dev_private;
395259016Sray	ifbdev = dev_priv->fbdev;
396259016Sray	if (ifbdev == NULL)
397259016Sray		return (NULL);
398259016Sray
399259016Sray	info = ifbdev->helper.fbdev;
400259016Sray
401259016Sray	return (info);
402259016Sray}
403259016Sray
404235783Skibconst struct intel_device_info *
405235783Skibi915_get_device_id(int device)
406235783Skib{
407235783Skib	const struct intel_gfx_device_id *did;
408235783Skib
409235783Skib	for (did = &pciidlist[0]; did->device != 0; did++) {
410235783Skib		if (did->device != device)
411235783Skib			continue;
412235783Skib		return (did->info);
413235783Skib	}
414235783Skib	return (NULL);
415235783Skib}
416235783Skib
417235783Skibstatic device_method_t i915_methods[] = {
418235783Skib	/* Device interface */
419235783Skib	DEVMETHOD(device_probe,		i915_probe),
420235783Skib	DEVMETHOD(device_attach,	i915_attach),
421235783Skib	DEVMETHOD(device_suspend,	i915_suspend),
422235783Skib	DEVMETHOD(device_resume,	i915_resume),
423235783Skib	DEVMETHOD(device_detach,	drm_detach),
424259016Sray
425259016Sray	/* Framebuffer service methods */
426259016Sray	DEVMETHOD(fb_getinfo,		i915_fb_helper_getinfo),
427259016Sray
428235783Skib	DEVMETHOD_END
429235783Skib};
430235783Skib
431235783Skibstatic driver_t i915_driver = {
432235783Skib	"drmn",
433235783Skib	i915_methods,
434235783Skib	sizeof(struct drm_device)
435235783Skib};
436235783Skib
437235783Skibextern devclass_t drm_devclass;
438235783SkibDRIVER_MODULE_ORDERED(i915kms, vgapci, i915_driver, drm_devclass, 0, 0,
439235783Skib    SI_ORDER_ANY);
440235783SkibMODULE_DEPEND(i915kms, drmn, 1, 1, 1);
441235783SkibMODULE_DEPEND(i915kms, agp, 1, 1, 1);
442235783SkibMODULE_DEPEND(i915kms, iicbus, 1, 1, 1);
443235783SkibMODULE_DEPEND(i915kms, iic, 1, 1, 1);
444235783SkibMODULE_DEPEND(i915kms, iicbb, 1, 1, 1);
445235783Skib
446235783Skibint intel_iommu_enabled = 0;
447235783SkibTUNABLE_INT("drm.i915.intel_iommu_enabled", &intel_iommu_enabled);
448235783Skib
449235783Skibint i915_semaphores = -1;
450235783SkibTUNABLE_INT("drm.i915.semaphores", &i915_semaphores);
451235783Skibstatic int i915_try_reset = 1;
452235783SkibTUNABLE_INT("drm.i915.try_reset", &i915_try_reset);
453235783Skibunsigned int i915_lvds_downclock = 0;
454235783SkibTUNABLE_INT("drm.i915.lvds_downclock", &i915_lvds_downclock);
455235783Skibint i915_vbt_sdvo_panel_type = -1;
456235783SkibTUNABLE_INT("drm.i915.vbt_sdvo_panel_type", &i915_vbt_sdvo_panel_type);
457235783Skibunsigned int i915_powersave = 1;
458235783SkibTUNABLE_INT("drm.i915.powersave", &i915_powersave);
459235783Skibint i915_enable_fbc = 0;
460235783SkibTUNABLE_INT("drm.i915.enable_fbc", &i915_enable_fbc);
461235783Skibint i915_enable_rc6 = 0;
462235783SkibTUNABLE_INT("drm.i915.enable_rc6", &i915_enable_rc6);
463235783Skibint i915_panel_use_ssc = -1;
464235783SkibTUNABLE_INT("drm.i915.panel_use_ssc", &i915_panel_use_ssc);
465235783Skibint i915_panel_ignore_lid = 0;
466235783SkibTUNABLE_INT("drm.i915.panel_ignore_lid", &i915_panel_ignore_lid);
467235783Skibint i915_modeset = 1;
468235783SkibTUNABLE_INT("drm.i915.modeset", &i915_modeset);
469235783Skibint i915_enable_ppgtt = -1;
470235783SkibTUNABLE_INT("drm.i915.enable_ppgtt", &i915_enable_ppgtt);
471235783Skibint i915_enable_hangcheck = 1;
472235783SkibTUNABLE_INT("drm.i915.enable_hangcheck", &i915_enable_hangcheck);
473235783Skib
474235783Skib#define	PCI_VENDOR_INTEL		0x8086
475235783Skib#define INTEL_PCH_DEVICE_ID_MASK	0xff00
476235783Skib#define INTEL_PCH_IBX_DEVICE_ID_TYPE	0x3b00
477235783Skib#define INTEL_PCH_CPT_DEVICE_ID_TYPE	0x1c00
478235783Skib#define INTEL_PCH_PPT_DEVICE_ID_TYPE	0x1e00
479235783Skib
480235783Skibvoid
481235783Skibintel_detect_pch(struct drm_device *dev)
482235783Skib{
483235783Skib	struct drm_i915_private *dev_priv;
484235783Skib	device_t pch;
485235783Skib	uint32_t id;
486235783Skib
487235783Skib	dev_priv = dev->dev_private;
488235783Skib	pch = pci_find_class(PCIC_BRIDGE, PCIS_BRIDGE_ISA);
489235783Skib	if (pch != NULL && pci_get_vendor(pch) == PCI_VENDOR_INTEL) {
490235783Skib		id = pci_get_device(pch) & INTEL_PCH_DEVICE_ID_MASK;
491235783Skib		if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
492235783Skib			dev_priv->pch_type = PCH_IBX;
493235783Skib			DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
494235783Skib		} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
495235783Skib			dev_priv->pch_type = PCH_CPT;
496235783Skib			DRM_DEBUG_KMS("Found CougarPoint PCH\n");
497235783Skib		} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
498235783Skib			/* PantherPoint is CPT compatible */
499235783Skib			dev_priv->pch_type = PCH_CPT;
500235783Skib			DRM_DEBUG_KMS("Found PatherPoint PCH\n");
501235783Skib		} else
502235783Skib			DRM_DEBUG_KMS("No PCH detected\n");
503235783Skib	} else
504235783Skib		DRM_DEBUG_KMS("No Intel PCI-ISA bridge found\n");
505235783Skib}
506235783Skib
507235783Skibvoid
508235783Skib__gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
509235783Skib{
510235783Skib	int count;
511235783Skib
512235783Skib	count = 0;
513235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
514240917Smav		DELAY(10);
515235783Skib
516235783Skib	I915_WRITE_NOTRACE(FORCEWAKE, 1);
517235783Skib	POSTING_READ(FORCEWAKE);
518235783Skib
519235783Skib	count = 0;
520235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0)
521240917Smav		DELAY(10);
522235783Skib}
523235783Skib
524235783Skibvoid
525235783Skib__gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
526235783Skib{
527235783Skib	int count;
528235783Skib
529235783Skib	count = 0;
530235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
531240917Smav		DELAY(10);
532235783Skib
533235783Skib	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
534235783Skib	POSTING_READ(FORCEWAKE_MT);
535235783Skib
536235783Skib	count = 0;
537235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
538240917Smav		DELAY(10);
539235783Skib}
540235783Skib
541235783Skibvoid
542235783Skibgen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
543235783Skib{
544235783Skib
545235783Skib	mtx_lock(&dev_priv->gt_lock);
546235783Skib	if (dev_priv->forcewake_count++ == 0)
547235783Skib		dev_priv->display.force_wake_get(dev_priv);
548235783Skib	mtx_unlock(&dev_priv->gt_lock);
549235783Skib}
550235783Skib
551235783Skibstatic void
552235783Skibgen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
553235783Skib{
554235783Skib	u32 gtfifodbg;
555235783Skib
556235783Skib	gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
557235783Skib	if ((gtfifodbg & GT_FIFO_CPU_ERROR_MASK) != 0) {
558235783Skib		printf("MMIO read or write has been dropped %x\n", gtfifodbg);
559235783Skib		I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
560235783Skib	}
561235783Skib}
562235783Skib
563235783Skibvoid
564235783Skib__gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
565235783Skib{
566235783Skib
567235783Skib	I915_WRITE_NOTRACE(FORCEWAKE, 0);
568235783Skib	/* The below doubles as a POSTING_READ */
569235783Skib	gen6_gt_check_fifodbg(dev_priv);
570235783Skib}
571235783Skib
572235783Skibvoid
573235783Skib__gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
574235783Skib{
575235783Skib
576235783Skib	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
577235783Skib	/* The below doubles as a POSTING_READ */
578235783Skib	gen6_gt_check_fifodbg(dev_priv);
579235783Skib}
580235783Skib
581235783Skibvoid
582235783Skibgen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
583235783Skib{
584235783Skib
585235783Skib	mtx_lock(&dev_priv->gt_lock);
586235783Skib	if (--dev_priv->forcewake_count == 0)
587235783Skib 		dev_priv->display.force_wake_put(dev_priv);
588235783Skib	mtx_unlock(&dev_priv->gt_lock);
589235783Skib}
590235783Skib
591235783Skibint
592235783Skib__gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
593235783Skib{
594235783Skib	int ret = 0;
595235783Skib
596235783Skib	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
597235783Skib		int loop = 500;
598235783Skib		u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
599235783Skib		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
600240917Smav			DELAY(10);
601235783Skib			fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
602235783Skib		}
603235783Skib		if (loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES) {
604235783Skib			printf("%s loop\n", __func__);
605235783Skib			++ret;
606235783Skib		}
607235783Skib		dev_priv->gt_fifo_count = fifo;
608235783Skib	}
609235783Skib	dev_priv->gt_fifo_count--;
610235783Skib
611235783Skib	return (ret);
612235783Skib}
613235783Skib
614235783Skibstatic int
615271705Sdumbbelli8xx_do_reset(struct drm_device *dev)
616235783Skib{
617235783Skib	struct drm_i915_private *dev_priv = dev->dev_private;
618235783Skib	int onems;
619235783Skib
620235783Skib	if (IS_I85X(dev))
621235783Skib		return -ENODEV;
622235783Skib
623235783Skib	onems = hz / 1000;
624235783Skib	if (onems == 0)
625235783Skib		onems = 1;
626235783Skib
627235783Skib	I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
628235783Skib	POSTING_READ(D_STATE);
629235783Skib
630235783Skib	if (IS_I830(dev) || IS_845G(dev)) {
631235783Skib		I915_WRITE(DEBUG_RESET_I830,
632235783Skib			   DEBUG_RESET_DISPLAY |
633235783Skib			   DEBUG_RESET_RENDER |
634235783Skib			   DEBUG_RESET_FULL);
635235783Skib		POSTING_READ(DEBUG_RESET_I830);
636235783Skib		pause("i8xxrst1", onems);
637235783Skib
638235783Skib		I915_WRITE(DEBUG_RESET_I830, 0);
639235783Skib		POSTING_READ(DEBUG_RESET_I830);
640235783Skib	}
641235783Skib
642235783Skib	pause("i8xxrst2", onems);
643235783Skib
644235783Skib	I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
645235783Skib	POSTING_READ(D_STATE);
646235783Skib
647235783Skib	return 0;
648235783Skib}
649235783Skib
650235783Skibstatic int
651235783Skibi965_reset_complete(struct drm_device *dev)
652235783Skib{
653235783Skib	u8 gdrst;
654235783Skib
655235783Skib	gdrst = pci_read_config(dev->device, I965_GDRST, 1);
656235783Skib	return (gdrst & 0x1);
657235783Skib}
658235783Skib
659235783Skibstatic int
660271705Sdumbbelli965_do_reset(struct drm_device *dev)
661235783Skib{
662235783Skib	u8 gdrst;
663235783Skib
664235783Skib	/*
665235783Skib	 * Set the domains we want to reset (GRDOM/bits 2 and 3) as
666235783Skib	 * well as the reset bit (GR/bit 0).  Setting the GR bit
667235783Skib	 * triggers the reset; when done, the hardware will clear it.
668235783Skib	 */
669235783Skib	gdrst = pci_read_config(dev->device, I965_GDRST, 1);
670271705Sdumbbell	pci_write_config(dev->device, I965_GDRST,
671271705Sdumbbell	    gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE, 1);
672235783Skib
673235783Skib	return (_intel_wait_for(dev, i965_reset_complete(dev), 500, 1,
674235783Skib	    "915rst"));
675235783Skib}
676235783Skib
677235783Skibstatic int
678271705Sdumbbellironlake_do_reset(struct drm_device *dev)
679235783Skib{
680235783Skib	struct drm_i915_private *dev_priv;
681235783Skib	u32 gdrst;
682235783Skib
683235783Skib	dev_priv = dev->dev_private;
684235783Skib	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
685271705Sdumbbell	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
686271705Sdumbbell	    gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
687235783Skib	return (_intel_wait_for(dev,
688235783Skib	    (I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1) != 0,
689235783Skib	    500, 1, "915rst"));
690235783Skib}
691235783Skib
692235783Skibstatic int
693271705Sdumbbellgen6_do_reset(struct drm_device *dev)
694235783Skib{
695235783Skib	struct drm_i915_private *dev_priv;
696235783Skib	int ret;
697235783Skib
698235783Skib	dev_priv = dev->dev_private;
699235783Skib
700235783Skib	/* Hold gt_lock across reset to prevent any register access
701235783Skib	 * with forcewake not set correctly
702235783Skib	 */
703235783Skib	mtx_lock(&dev_priv->gt_lock);
704235783Skib
705235783Skib	/* Reset the chip */
706235783Skib
707235783Skib	/* GEN6_GDRST is not in the gt power well, no need to check
708235783Skib	 * for fifo space for the write or forcewake the chip for
709235783Skib	 * the read
710235783Skib	 */
711235783Skib	I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
712235783Skib
713235783Skib	/* Spin waiting for the device to ack the reset request */
714235783Skib	ret = _intel_wait_for(dev,
715256848Skib	    (I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0,
716235783Skib	    500, 1, "915rst");
717235783Skib
718235783Skib	/* If reset with a user forcewake, try to restore, otherwise turn it off */
719235783Skib 	if (dev_priv->forcewake_count)
720235783Skib 		dev_priv->display.force_wake_get(dev_priv);
721235783Skib	else
722235783Skib		dev_priv->display.force_wake_put(dev_priv);
723235783Skib
724235783Skib	/* Restore fifo count */
725235783Skib	dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
726235783Skib
727235783Skib	mtx_unlock(&dev_priv->gt_lock);
728235783Skib	return (ret);
729235783Skib}
730235783Skib
731271705Sdumbbellint intel_gpu_reset(struct drm_device *dev)
732271705Sdumbbell{
733271705Sdumbbell	struct drm_i915_private *dev_priv = dev->dev_private;
734271705Sdumbbell	int ret = -ENODEV;
735271705Sdumbbell
736271705Sdumbbell	switch (INTEL_INFO(dev)->gen) {
737271705Sdumbbell	case 7:
738271705Sdumbbell	case 6:
739271705Sdumbbell		ret = gen6_do_reset(dev);
740271705Sdumbbell		break;
741271705Sdumbbell	case 5:
742271705Sdumbbell		ret = ironlake_do_reset(dev);
743271705Sdumbbell		break;
744271705Sdumbbell	case 4:
745271705Sdumbbell		ret = i965_do_reset(dev);
746271705Sdumbbell		break;
747271705Sdumbbell	case 2:
748271705Sdumbbell		ret = i8xx_do_reset(dev);
749271705Sdumbbell		break;
750271705Sdumbbell	}
751271705Sdumbbell
752271705Sdumbbell	/* Also reset the gpu hangman. */
753271705Sdumbbell	if (dev_priv->stop_rings) {
754271705Sdumbbell		DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n");
755271705Sdumbbell		dev_priv->stop_rings = 0;
756271705Sdumbbell		if (ret == -ENODEV) {
757271705Sdumbbell			DRM_ERROR("Reset not implemented, but ignoring "
758271705Sdumbbell				  "error for simulated gpu hangs\n");
759271705Sdumbbell			ret = 0;
760271705Sdumbbell		}
761271705Sdumbbell	}
762271705Sdumbbell
763271705Sdumbbell	return ret;
764271705Sdumbbell}
765271705Sdumbbell
766235783Skibint
767271705Sdumbbelli915_reset(struct drm_device *dev)
768235783Skib{
769235783Skib	drm_i915_private_t *dev_priv = dev->dev_private;
770235783Skib	/*
771235783Skib	 * We really should only reset the display subsystem if we actually
772235783Skib	 * need to
773235783Skib	 */
774235783Skib	bool need_display = true;
775235783Skib	int ret;
776235783Skib
777235783Skib	if (!i915_try_reset)
778235783Skib		return (0);
779235783Skib
780235783Skib	if (!sx_try_xlock(&dev->dev_struct_lock))
781235783Skib		return (-EBUSY);
782235783Skib
783235783Skib	i915_gem_reset(dev);
784235783Skib
785235783Skib	ret = -ENODEV;
786235783Skib	if (time_second - dev_priv->last_gpu_reset < 5) {
787235783Skib		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
788271705Sdumbbell	} else
789271705Sdumbbell		ret = intel_gpu_reset(dev);
790271705Sdumbbell
791235783Skib	dev_priv->last_gpu_reset = time_second;
792235783Skib	if (ret) {
793235783Skib		DRM_ERROR("Failed to reset chip.\n");
794235783Skib		DRM_UNLOCK(dev);
795235783Skib		return (ret);
796235783Skib	}
797235783Skib
798235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
799235783Skib	    !dev_priv->mm.suspended) {
800235783Skib		dev_priv->mm.suspended = 0;
801235783Skib
802235783Skib		i915_gem_init_swizzling(dev);
803235783Skib
804235783Skib		dev_priv->rings[RCS].init(&dev_priv->rings[RCS]);
805235783Skib		if (HAS_BSD(dev))
806235783Skib			dev_priv->rings[VCS].init(&dev_priv->rings[VCS]);
807235783Skib		if (HAS_BLT(dev))
808235783Skib			dev_priv->rings[BCS].init(&dev_priv->rings[BCS]);
809235783Skib
810271705Sdumbbell		i915_gem_context_init(dev);
811235783Skib		i915_gem_init_ppgtt(dev);
812235783Skib
813235783Skib		drm_irq_uninstall(dev);
814235783Skib		drm_mode_config_reset(dev);
815235783Skib		DRM_UNLOCK(dev);
816235783Skib		drm_irq_install(dev);
817235783Skib		DRM_LOCK(dev);
818235783Skib	}
819235783Skib	DRM_UNLOCK(dev);
820235783Skib
821235783Skib	if (need_display) {
822235783Skib		sx_xlock(&dev->mode_config.mutex);
823235783Skib		drm_helper_resume_force_mode(dev);
824235783Skib		sx_xunlock(&dev->mode_config.mutex);
825235783Skib	}
826235783Skib
827235783Skib	return (0);
828235783Skib}
829235783Skib
830235783Skib#define __i915_read(x, y) \
831235783Skibu##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
832235783Skib	u##x val = 0; \
833235783Skib	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
834235783Skib		mtx_lock(&dev_priv->gt_lock); \
835235783Skib		if (dev_priv->forcewake_count == 0) \
836235783Skib			dev_priv->display.force_wake_get(dev_priv); \
837235783Skib		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
838235783Skib		if (dev_priv->forcewake_count == 0) \
839235783Skib			dev_priv->display.force_wake_put(dev_priv); \
840235783Skib		mtx_unlock(&dev_priv->gt_lock); \
841235783Skib	} else { \
842235783Skib		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
843235783Skib	} \
844235783Skib	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
845235783Skib	return val; \
846235783Skib}
847235783Skib
848235783Skib__i915_read(8, 8)
849235783Skib__i915_read(16, 16)
850235783Skib__i915_read(32, 32)
851235783Skib__i915_read(64, 64)
852235783Skib#undef __i915_read
853235783Skib
854235783Skib#define __i915_write(x, y) \
855235783Skibvoid i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
856235783Skib	u32 __fifo_ret = 0; \
857235783Skib	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
858235783Skib	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
859235783Skib		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
860235783Skib	} \
861235783Skib	DRM_WRITE##y(dev_priv->mmio_map, reg, val); \
862235783Skib	if (__predict_false(__fifo_ret)) { \
863235783Skib		gen6_gt_check_fifodbg(dev_priv); \
864235783Skib	} \
865235783Skib}
866235783Skib__i915_write(8, 8)
867235783Skib__i915_write(16, 16)
868235783Skib__i915_write(32, 32)
869235783Skib__i915_write(64, 64)
870235783Skib#undef __i915_write
871