i915_drv.c revision 256848
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 256848 2013-10-21 16:22:51Z 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
43235783Skib/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
44235783Skibstatic drm_pci_id_list_t i915_pciidlist[] = {
45235783Skib	i915_PCI_IDS
46235783Skib};
47235783Skib
48235783Skibstatic const struct intel_device_info intel_i830_info = {
49235783Skib	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1,
50235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
51235783Skib};
52235783Skib
53235783Skibstatic const struct intel_device_info intel_845g_info = {
54235783Skib	.gen = 2,
55235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
56235783Skib};
57235783Skib
58235783Skibstatic const struct intel_device_info intel_i85x_info = {
59235783Skib	.gen = 2, .is_i85x = 1, .is_mobile = 1,
60235783Skib	.cursor_needs_physical = 1,
61235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
62235783Skib};
63235783Skib
64235783Skibstatic const struct intel_device_info intel_i865g_info = {
65235783Skib	.gen = 2,
66235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
67235783Skib};
68235783Skib
69235783Skibstatic const struct intel_device_info intel_i915g_info = {
70235783Skib	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1,
71235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
72235783Skib};
73235783Skibstatic const struct intel_device_info intel_i915gm_info = {
74235783Skib	.gen = 3, .is_mobile = 1,
75235783Skib	.cursor_needs_physical = 1,
76235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
77235783Skib	.supports_tv = 1,
78235783Skib};
79235783Skibstatic const struct intel_device_info intel_i945g_info = {
80235783Skib	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1,
81235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
82235783Skib};
83235783Skibstatic const struct intel_device_info intel_i945gm_info = {
84235783Skib	.gen = 3, .is_i945gm = 1, .is_mobile = 1,
85235783Skib	.has_hotplug = 1, .cursor_needs_physical = 1,
86235783Skib	.has_overlay = 1, .overlay_needs_physical = 1,
87235783Skib	.supports_tv = 1,
88235783Skib};
89235783Skib
90235783Skibstatic const struct intel_device_info intel_i965g_info = {
91235783Skib	.gen = 4, .is_broadwater = 1,
92235783Skib	.has_hotplug = 1,
93235783Skib	.has_overlay = 1,
94235783Skib};
95235783Skib
96235783Skibstatic const struct intel_device_info intel_i965gm_info = {
97235783Skib	.gen = 4, .is_crestline = 1,
98235783Skib	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
99235783Skib	.has_overlay = 1,
100235783Skib	.supports_tv = 1,
101235783Skib};
102235783Skib
103235783Skibstatic const struct intel_device_info intel_g33_info = {
104235783Skib	.gen = 3, .is_g33 = 1,
105235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
106235783Skib	.has_overlay = 1,
107235783Skib};
108235783Skib
109235783Skibstatic const struct intel_device_info intel_g45_info = {
110235783Skib	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1,
111235783Skib	.has_pipe_cxsr = 1, .has_hotplug = 1,
112235783Skib	.has_bsd_ring = 1,
113235783Skib};
114235783Skib
115235783Skibstatic const struct intel_device_info intel_gm45_info = {
116235783Skib	.gen = 4, .is_g4x = 1,
117235783Skib	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
118235783Skib	.has_pipe_cxsr = 1, .has_hotplug = 1,
119235783Skib	.supports_tv = 1,
120235783Skib	.has_bsd_ring = 1,
121235783Skib};
122235783Skib
123235783Skibstatic const struct intel_device_info intel_pineview_info = {
124235783Skib	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1,
125235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
126235783Skib	.has_overlay = 1,
127235783Skib};
128235783Skib
129235783Skibstatic const struct intel_device_info intel_ironlake_d_info = {
130235783Skib	.gen = 5,
131235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
132235783Skib	.has_bsd_ring = 1,
133235783Skib};
134235783Skib
135235783Skibstatic const struct intel_device_info intel_ironlake_m_info = {
136235783Skib	.gen = 5, .is_mobile = 1,
137235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
138235783Skib	.has_fbc = 0, /* disabled due to buggy hardware */
139235783Skib	.has_bsd_ring = 1,
140235783Skib};
141235783Skib
142235783Skibstatic const struct intel_device_info intel_sandybridge_d_info = {
143235783Skib	.gen = 6,
144235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
145235783Skib	.has_bsd_ring = 1,
146235783Skib	.has_blt_ring = 1,
147235783Skib	.has_llc = 1,
148235783Skib};
149235783Skib
150235783Skibstatic const struct intel_device_info intel_sandybridge_m_info = {
151235783Skib	.gen = 6, .is_mobile = 1,
152235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
153235783Skib	.has_fbc = 1,
154235783Skib	.has_bsd_ring = 1,
155235783Skib	.has_blt_ring = 1,
156235783Skib	.has_llc = 1,
157235783Skib};
158235783Skib
159235783Skibstatic const struct intel_device_info intel_ivybridge_d_info = {
160235783Skib	.is_ivybridge = 1, .gen = 7,
161235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
162235783Skib	.has_bsd_ring = 1,
163235783Skib	.has_blt_ring = 1,
164235783Skib	.has_llc = 1,
165235783Skib};
166235783Skib
167235783Skibstatic const struct intel_device_info intel_ivybridge_m_info = {
168235783Skib	.is_ivybridge = 1, .gen = 7, .is_mobile = 1,
169235783Skib	.need_gfx_hws = 1, .has_hotplug = 1,
170235783Skib	.has_fbc = 0,	/* FBC is not enabled on Ivybridge mobile yet */
171235783Skib	.has_bsd_ring = 1,
172235783Skib	.has_blt_ring = 1,
173235783Skib	.has_llc = 1,
174235783Skib};
175235783Skib
176235783Skib#define INTEL_VGA_DEVICE(id, info_) {		\
177235783Skib	.device = id,				\
178235783Skib	.info = info_,				\
179235783Skib}
180235783Skib
181235783Skibstatic const struct intel_gfx_device_id {
182235783Skib	int device;
183235783Skib	const struct intel_device_info *info;
184235783Skib} pciidlist[] = {		/* aka */
185235783Skib	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
186235783Skib	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
187235783Skib	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
188235783Skib	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
189235783Skib	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
190235783Skib	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
191235783Skib	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
192235783Skib	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
193235783Skib	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
194235783Skib	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
195235783Skib	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
196235783Skib	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
197235783Skib	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
198235783Skib	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
199235783Skib	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
200235783Skib	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
201235783Skib	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
202235783Skib	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
203235783Skib	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
204235783Skib	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
205235783Skib	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
206235783Skib	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
207235783Skib	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
208235783Skib	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
209235783Skib	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
210235783Skib	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
211235783Skib	INTEL_VGA_DEVICE(0x2e92, &intel_g45_info),
212235783Skib	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
213235783Skib	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
214235783Skib	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
215235783Skib	INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
216235783Skib	INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
217235783Skib	INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info),
218235783Skib	INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info),
219235783Skib	INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
220235783Skib	INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
221235783Skib	INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
222235783Skib	INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
223235783Skib	INTEL_VGA_DEVICE(0x0156, &intel_ivybridge_m_info), /* GT1 mobile */
224235783Skib	INTEL_VGA_DEVICE(0x0166, &intel_ivybridge_m_info), /* GT2 mobile */
225235783Skib	INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
226235783Skib	INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
227235783Skib	INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
228235783Skib	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
229235783Skib	{0, 0}
230235783Skib};
231235783Skib
232235783Skibstatic int i915_drm_freeze(struct drm_device *dev)
233235783Skib{
234235783Skib	struct drm_i915_private *dev_priv;
235235783Skib	int error;
236235783Skib
237235783Skib	dev_priv = dev->dev_private;
238235783Skib	drm_kms_helper_poll_disable(dev);
239235783Skib
240235783Skib#if 0
241235783Skib	pci_save_state(dev->pdev);
242235783Skib#endif
243235783Skib
244235783Skib	DRM_LOCK(dev);
245235783Skib	/* If KMS is active, we do the leavevt stuff here */
246235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
247235783Skib		error = -i915_gem_idle(dev);
248235783Skib		if (error) {
249235783Skib			DRM_UNLOCK(dev);
250235783Skib			device_printf(dev->device,
251235783Skib			    "GEM idle failed, resume might fail\n");
252235783Skib			return (error);
253235783Skib		}
254235783Skib		drm_irq_uninstall(dev);
255235783Skib	}
256235783Skib
257235783Skib	i915_save_state(dev);
258235783Skib
259235783Skib	intel_opregion_fini(dev);
260235783Skib
261235783Skib	/* Modeset on resume, not lid events */
262235783Skib	dev_priv->modeset_on_lid = 0;
263235783Skib	DRM_UNLOCK(dev);
264235783Skib
265235783Skib	return 0;
266235783Skib}
267235783Skib
268235783Skibstatic int
269235783Skibi915_suspend(device_t kdev)
270235783Skib{
271235783Skib	struct drm_device *dev;
272235783Skib	int error;
273235783Skib
274235783Skib	dev = device_get_softc(kdev);
275235783Skib	if (dev == NULL || dev->dev_private == NULL) {
276235783Skib		DRM_ERROR("DRM not initialized, aborting suspend.\n");
277235783Skib		return -ENODEV;
278235783Skib	}
279235783Skib
280235783Skib	DRM_DEBUG_KMS("starting suspend\n");
281235783Skib	error = i915_drm_freeze(dev);
282235783Skib	if (error)
283235783Skib		return (error);
284235783Skib
285235783Skib	error = bus_generic_suspend(kdev);
286235783Skib	DRM_DEBUG_KMS("finished suspend %d\n", error);
287235783Skib	return (error);
288235783Skib}
289235783Skib
290235783Skibstatic int i915_drm_thaw(struct drm_device *dev)
291235783Skib{
292235783Skib	struct drm_i915_private *dev_priv = dev->dev_private;
293235783Skib	int error = 0;
294235783Skib
295235783Skib	DRM_LOCK(dev);
296235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
297235783Skib		i915_gem_restore_gtt_mappings(dev);
298235783Skib	}
299235783Skib
300235783Skib	i915_restore_state(dev);
301235783Skib	intel_opregion_setup(dev);
302235783Skib
303235783Skib	/* KMS EnterVT equivalent */
304235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
305235783Skib		dev_priv->mm.suspended = 0;
306235783Skib
307235783Skib		error = i915_gem_init_hw(dev);
308235783Skib
309235783Skib		if (HAS_PCH_SPLIT(dev))
310235783Skib			ironlake_init_pch_refclk(dev);
311235783Skib
312235783Skib		DRM_UNLOCK(dev);
313235783Skib		sx_xlock(&dev->mode_config.mutex);
314235783Skib		drm_mode_config_reset(dev);
315235783Skib		sx_xunlock(&dev->mode_config.mutex);
316235783Skib		drm_irq_install(dev);
317235783Skib
318235783Skib		sx_xlock(&dev->mode_config.mutex);
319235783Skib		/* Resume the modeset for every activated CRTC */
320235783Skib		drm_helper_resume_force_mode(dev);
321235783Skib		sx_xunlock(&dev->mode_config.mutex);
322235783Skib
323235783Skib		if (IS_IRONLAKE_M(dev))
324235783Skib			ironlake_enable_rc6(dev);
325235783Skib		DRM_LOCK(dev);
326235783Skib	}
327235783Skib
328235783Skib	intel_opregion_init(dev);
329235783Skib
330235783Skib	dev_priv->modeset_on_lid = 0;
331235783Skib
332235783Skib	DRM_UNLOCK(dev);
333235783Skib
334235783Skib	return error;
335235783Skib}
336235783Skib
337235783Skibstatic int
338235783Skibi915_resume(device_t kdev)
339235783Skib{
340235783Skib	struct drm_device *dev;
341235783Skib	int ret;
342235783Skib
343235783Skib	dev = device_get_softc(kdev);
344235783Skib	DRM_DEBUG_KMS("starting resume\n");
345235783Skib#if 0
346235783Skib	if (pci_enable_device(dev->pdev))
347235783Skib		return -EIO;
348235783Skib
349235783Skib	pci_set_master(dev->pdev);
350235783Skib#endif
351235783Skib
352235783Skib	ret = -i915_drm_thaw(dev);
353235783Skib	if (ret != 0)
354235783Skib		return (ret);
355235783Skib
356235783Skib	drm_kms_helper_poll_enable(dev);
357235783Skib	ret = bus_generic_resume(kdev);
358235783Skib	DRM_DEBUG_KMS("finished resume %d\n", ret);
359235783Skib	return (ret);
360235783Skib}
361235783Skib
362235783Skibstatic int
363235783Skibi915_probe(device_t kdev)
364235783Skib{
365235783Skib
366235783Skib	return drm_probe(kdev, i915_pciidlist);
367235783Skib}
368235783Skib
369235783Skibint i915_modeset;
370235783Skib
371235783Skibstatic int
372235783Skibi915_attach(device_t kdev)
373235783Skib{
374235783Skib	struct drm_device *dev;
375235783Skib
376235783Skib	dev = device_get_softc(kdev);
377235783Skib	if (i915_modeset == 1)
378235783Skib		i915_driver_info.driver_features |= DRIVER_MODESET;
379235783Skib	dev->driver = &i915_driver_info;
380235783Skib	return (drm_attach(kdev, i915_pciidlist));
381235783Skib}
382235783Skib
383235783Skibconst struct intel_device_info *
384235783Skibi915_get_device_id(int device)
385235783Skib{
386235783Skib	const struct intel_gfx_device_id *did;
387235783Skib
388235783Skib	for (did = &pciidlist[0]; did->device != 0; did++) {
389235783Skib		if (did->device != device)
390235783Skib			continue;
391235783Skib		return (did->info);
392235783Skib	}
393235783Skib	return (NULL);
394235783Skib}
395235783Skib
396235783Skibstatic device_method_t i915_methods[] = {
397235783Skib	/* Device interface */
398235783Skib	DEVMETHOD(device_probe,		i915_probe),
399235783Skib	DEVMETHOD(device_attach,	i915_attach),
400235783Skib	DEVMETHOD(device_suspend,	i915_suspend),
401235783Skib	DEVMETHOD(device_resume,	i915_resume),
402235783Skib	DEVMETHOD(device_detach,	drm_detach),
403235783Skib	DEVMETHOD_END
404235783Skib};
405235783Skib
406235783Skibstatic driver_t i915_driver = {
407235783Skib	"drmn",
408235783Skib	i915_methods,
409235783Skib	sizeof(struct drm_device)
410235783Skib};
411235783Skib
412235783Skibextern devclass_t drm_devclass;
413235783SkibDRIVER_MODULE_ORDERED(i915kms, vgapci, i915_driver, drm_devclass, 0, 0,
414235783Skib    SI_ORDER_ANY);
415235783SkibMODULE_DEPEND(i915kms, drmn, 1, 1, 1);
416235783SkibMODULE_DEPEND(i915kms, agp, 1, 1, 1);
417235783SkibMODULE_DEPEND(i915kms, iicbus, 1, 1, 1);
418235783SkibMODULE_DEPEND(i915kms, iic, 1, 1, 1);
419235783SkibMODULE_DEPEND(i915kms, iicbb, 1, 1, 1);
420235783Skib
421235783Skibint intel_iommu_enabled = 0;
422235783SkibTUNABLE_INT("drm.i915.intel_iommu_enabled", &intel_iommu_enabled);
423235783Skib
424235783Skibint i915_semaphores = -1;
425235783SkibTUNABLE_INT("drm.i915.semaphores", &i915_semaphores);
426235783Skibstatic int i915_try_reset = 1;
427235783SkibTUNABLE_INT("drm.i915.try_reset", &i915_try_reset);
428235783Skibunsigned int i915_lvds_downclock = 0;
429235783SkibTUNABLE_INT("drm.i915.lvds_downclock", &i915_lvds_downclock);
430235783Skibint i915_vbt_sdvo_panel_type = -1;
431235783SkibTUNABLE_INT("drm.i915.vbt_sdvo_panel_type", &i915_vbt_sdvo_panel_type);
432235783Skibunsigned int i915_powersave = 1;
433235783SkibTUNABLE_INT("drm.i915.powersave", &i915_powersave);
434235783Skibint i915_enable_fbc = 0;
435235783SkibTUNABLE_INT("drm.i915.enable_fbc", &i915_enable_fbc);
436235783Skibint i915_enable_rc6 = 0;
437235783SkibTUNABLE_INT("drm.i915.enable_rc6", &i915_enable_rc6);
438235783Skibint i915_panel_use_ssc = -1;
439235783SkibTUNABLE_INT("drm.i915.panel_use_ssc", &i915_panel_use_ssc);
440235783Skibint i915_panel_ignore_lid = 0;
441235783SkibTUNABLE_INT("drm.i915.panel_ignore_lid", &i915_panel_ignore_lid);
442235783Skibint i915_modeset = 1;
443235783SkibTUNABLE_INT("drm.i915.modeset", &i915_modeset);
444235783Skibint i915_enable_ppgtt = -1;
445235783SkibTUNABLE_INT("drm.i915.enable_ppgtt", &i915_enable_ppgtt);
446235783Skibint i915_enable_hangcheck = 1;
447235783SkibTUNABLE_INT("drm.i915.enable_hangcheck", &i915_enable_hangcheck);
448235783Skib
449235783Skib#define	PCI_VENDOR_INTEL		0x8086
450235783Skib#define INTEL_PCH_DEVICE_ID_MASK	0xff00
451235783Skib#define INTEL_PCH_IBX_DEVICE_ID_TYPE	0x3b00
452235783Skib#define INTEL_PCH_CPT_DEVICE_ID_TYPE	0x1c00
453235783Skib#define INTEL_PCH_PPT_DEVICE_ID_TYPE	0x1e00
454235783Skib
455235783Skibvoid
456235783Skibintel_detect_pch(struct drm_device *dev)
457235783Skib{
458235783Skib	struct drm_i915_private *dev_priv;
459235783Skib	device_t pch;
460235783Skib	uint32_t id;
461235783Skib
462235783Skib	dev_priv = dev->dev_private;
463235783Skib	pch = pci_find_class(PCIC_BRIDGE, PCIS_BRIDGE_ISA);
464235783Skib	if (pch != NULL && pci_get_vendor(pch) == PCI_VENDOR_INTEL) {
465235783Skib		id = pci_get_device(pch) & INTEL_PCH_DEVICE_ID_MASK;
466235783Skib		if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
467235783Skib			dev_priv->pch_type = PCH_IBX;
468235783Skib			DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
469235783Skib		} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
470235783Skib			dev_priv->pch_type = PCH_CPT;
471235783Skib			DRM_DEBUG_KMS("Found CougarPoint PCH\n");
472235783Skib		} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
473235783Skib			/* PantherPoint is CPT compatible */
474235783Skib			dev_priv->pch_type = PCH_CPT;
475235783Skib			DRM_DEBUG_KMS("Found PatherPoint PCH\n");
476235783Skib		} else
477235783Skib			DRM_DEBUG_KMS("No PCH detected\n");
478235783Skib	} else
479235783Skib		DRM_DEBUG_KMS("No Intel PCI-ISA bridge found\n");
480235783Skib}
481235783Skib
482235783Skibvoid
483235783Skib__gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
484235783Skib{
485235783Skib	int count;
486235783Skib
487235783Skib	count = 0;
488235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
489240917Smav		DELAY(10);
490235783Skib
491235783Skib	I915_WRITE_NOTRACE(FORCEWAKE, 1);
492235783Skib	POSTING_READ(FORCEWAKE);
493235783Skib
494235783Skib	count = 0;
495235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0)
496240917Smav		DELAY(10);
497235783Skib}
498235783Skib
499235783Skibvoid
500235783Skib__gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
501235783Skib{
502235783Skib	int count;
503235783Skib
504235783Skib	count = 0;
505235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
506240917Smav		DELAY(10);
507235783Skib
508235783Skib	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
509235783Skib	POSTING_READ(FORCEWAKE_MT);
510235783Skib
511235783Skib	count = 0;
512235783Skib	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
513240917Smav		DELAY(10);
514235783Skib}
515235783Skib
516235783Skibvoid
517235783Skibgen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
518235783Skib{
519235783Skib
520235783Skib	mtx_lock(&dev_priv->gt_lock);
521235783Skib	if (dev_priv->forcewake_count++ == 0)
522235783Skib		dev_priv->display.force_wake_get(dev_priv);
523235783Skib	mtx_unlock(&dev_priv->gt_lock);
524235783Skib}
525235783Skib
526235783Skibstatic void
527235783Skibgen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
528235783Skib{
529235783Skib	u32 gtfifodbg;
530235783Skib
531235783Skib	gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
532235783Skib	if ((gtfifodbg & GT_FIFO_CPU_ERROR_MASK) != 0) {
533235783Skib		printf("MMIO read or write has been dropped %x\n", gtfifodbg);
534235783Skib		I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
535235783Skib	}
536235783Skib}
537235783Skib
538235783Skibvoid
539235783Skib__gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
540235783Skib{
541235783Skib
542235783Skib	I915_WRITE_NOTRACE(FORCEWAKE, 0);
543235783Skib	/* The below doubles as a POSTING_READ */
544235783Skib	gen6_gt_check_fifodbg(dev_priv);
545235783Skib}
546235783Skib
547235783Skibvoid
548235783Skib__gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
549235783Skib{
550235783Skib
551235783Skib	I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
552235783Skib	/* The below doubles as a POSTING_READ */
553235783Skib	gen6_gt_check_fifodbg(dev_priv);
554235783Skib}
555235783Skib
556235783Skibvoid
557235783Skibgen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
558235783Skib{
559235783Skib
560235783Skib	mtx_lock(&dev_priv->gt_lock);
561235783Skib	if (--dev_priv->forcewake_count == 0)
562235783Skib 		dev_priv->display.force_wake_put(dev_priv);
563235783Skib	mtx_unlock(&dev_priv->gt_lock);
564235783Skib}
565235783Skib
566235783Skibint
567235783Skib__gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
568235783Skib{
569235783Skib	int ret = 0;
570235783Skib
571235783Skib	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
572235783Skib		int loop = 500;
573235783Skib		u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
574235783Skib		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
575240917Smav			DELAY(10);
576235783Skib			fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
577235783Skib		}
578235783Skib		if (loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES) {
579235783Skib			printf("%s loop\n", __func__);
580235783Skib			++ret;
581235783Skib		}
582235783Skib		dev_priv->gt_fifo_count = fifo;
583235783Skib	}
584235783Skib	dev_priv->gt_fifo_count--;
585235783Skib
586235783Skib	return (ret);
587235783Skib}
588235783Skib
589235783Skibstatic int
590235783Skibi8xx_do_reset(struct drm_device *dev, u8 flags)
591235783Skib{
592235783Skib	struct drm_i915_private *dev_priv = dev->dev_private;
593235783Skib	int onems;
594235783Skib
595235783Skib	if (IS_I85X(dev))
596235783Skib		return -ENODEV;
597235783Skib
598235783Skib	onems = hz / 1000;
599235783Skib	if (onems == 0)
600235783Skib		onems = 1;
601235783Skib
602235783Skib	I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
603235783Skib	POSTING_READ(D_STATE);
604235783Skib
605235783Skib	if (IS_I830(dev) || IS_845G(dev)) {
606235783Skib		I915_WRITE(DEBUG_RESET_I830,
607235783Skib			   DEBUG_RESET_DISPLAY |
608235783Skib			   DEBUG_RESET_RENDER |
609235783Skib			   DEBUG_RESET_FULL);
610235783Skib		POSTING_READ(DEBUG_RESET_I830);
611235783Skib		pause("i8xxrst1", onems);
612235783Skib
613235783Skib		I915_WRITE(DEBUG_RESET_I830, 0);
614235783Skib		POSTING_READ(DEBUG_RESET_I830);
615235783Skib	}
616235783Skib
617235783Skib	pause("i8xxrst2", onems);
618235783Skib
619235783Skib	I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
620235783Skib	POSTING_READ(D_STATE);
621235783Skib
622235783Skib	return 0;
623235783Skib}
624235783Skib
625235783Skibstatic int
626235783Skibi965_reset_complete(struct drm_device *dev)
627235783Skib{
628235783Skib	u8 gdrst;
629235783Skib
630235783Skib	gdrst = pci_read_config(dev->device, I965_GDRST, 1);
631235783Skib	return (gdrst & 0x1);
632235783Skib}
633235783Skib
634235783Skibstatic int
635235783Skibi965_do_reset(struct drm_device *dev, u8 flags)
636235783Skib{
637235783Skib	u8 gdrst;
638235783Skib
639235783Skib	/*
640235783Skib	 * Set the domains we want to reset (GRDOM/bits 2 and 3) as
641235783Skib	 * well as the reset bit (GR/bit 0).  Setting the GR bit
642235783Skib	 * triggers the reset; when done, the hardware will clear it.
643235783Skib	 */
644235783Skib	gdrst = pci_read_config(dev->device, I965_GDRST, 1);
645235783Skib	pci_write_config(dev->device, I965_GDRST, gdrst | flags | 0x1, 1);
646235783Skib
647235783Skib	return (_intel_wait_for(dev, i965_reset_complete(dev), 500, 1,
648235783Skib	    "915rst"));
649235783Skib}
650235783Skib
651235783Skibstatic int
652235783Skibironlake_do_reset(struct drm_device *dev, u8 flags)
653235783Skib{
654235783Skib	struct drm_i915_private *dev_priv;
655235783Skib	u32 gdrst;
656235783Skib
657235783Skib	dev_priv = dev->dev_private;
658235783Skib	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
659235783Skib	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1);
660235783Skib	return (_intel_wait_for(dev,
661235783Skib	    (I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1) != 0,
662235783Skib	    500, 1, "915rst"));
663235783Skib}
664235783Skib
665235783Skibstatic int
666235783Skibgen6_do_reset(struct drm_device *dev, u8 flags)
667235783Skib{
668235783Skib	struct drm_i915_private *dev_priv;
669235783Skib	int ret;
670235783Skib
671235783Skib	dev_priv = dev->dev_private;
672235783Skib
673235783Skib	/* Hold gt_lock across reset to prevent any register access
674235783Skib	 * with forcewake not set correctly
675235783Skib	 */
676235783Skib	mtx_lock(&dev_priv->gt_lock);
677235783Skib
678235783Skib	/* Reset the chip */
679235783Skib
680235783Skib	/* GEN6_GDRST is not in the gt power well, no need to check
681235783Skib	 * for fifo space for the write or forcewake the chip for
682235783Skib	 * the read
683235783Skib	 */
684235783Skib	I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
685235783Skib
686235783Skib	/* Spin waiting for the device to ack the reset request */
687235783Skib	ret = _intel_wait_for(dev,
688256848Skib	    (I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0,
689235783Skib	    500, 1, "915rst");
690235783Skib
691235783Skib	/* If reset with a user forcewake, try to restore, otherwise turn it off */
692235783Skib 	if (dev_priv->forcewake_count)
693235783Skib 		dev_priv->display.force_wake_get(dev_priv);
694235783Skib	else
695235783Skib		dev_priv->display.force_wake_put(dev_priv);
696235783Skib
697235783Skib	/* Restore fifo count */
698235783Skib	dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
699235783Skib
700235783Skib	mtx_unlock(&dev_priv->gt_lock);
701235783Skib	return (ret);
702235783Skib}
703235783Skib
704235783Skibint
705235783Skibi915_reset(struct drm_device *dev, u8 flags)
706235783Skib{
707235783Skib	drm_i915_private_t *dev_priv = dev->dev_private;
708235783Skib	/*
709235783Skib	 * We really should only reset the display subsystem if we actually
710235783Skib	 * need to
711235783Skib	 */
712235783Skib	bool need_display = true;
713235783Skib	int ret;
714235783Skib
715235783Skib	if (!i915_try_reset)
716235783Skib		return (0);
717235783Skib
718235783Skib	if (!sx_try_xlock(&dev->dev_struct_lock))
719235783Skib		return (-EBUSY);
720235783Skib
721235783Skib	i915_gem_reset(dev);
722235783Skib
723235783Skib	ret = -ENODEV;
724235783Skib	if (time_second - dev_priv->last_gpu_reset < 5) {
725235783Skib		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
726235783Skib	} else {
727235783Skib		switch (INTEL_INFO(dev)->gen) {
728235783Skib		case 7:
729235783Skib		case 6:
730235783Skib		ret = gen6_do_reset(dev, flags);
731235783Skib		break;
732235783Skib	case 5:
733235783Skib		ret = ironlake_do_reset(dev, flags);
734235783Skib			break;
735235783Skib		case 4:
736235783Skib			ret = i965_do_reset(dev, flags);
737235783Skib			break;
738235783Skib		case 2:
739235783Skib			ret = i8xx_do_reset(dev, flags);
740235783Skib			break;
741235783Skib		}
742235783Skib	}
743235783Skib	dev_priv->last_gpu_reset = time_second;
744235783Skib	if (ret) {
745235783Skib		DRM_ERROR("Failed to reset chip.\n");
746235783Skib		DRM_UNLOCK(dev);
747235783Skib		return (ret);
748235783Skib	}
749235783Skib
750235783Skib	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
751235783Skib	    !dev_priv->mm.suspended) {
752235783Skib		dev_priv->mm.suspended = 0;
753235783Skib
754235783Skib		i915_gem_init_swizzling(dev);
755235783Skib
756235783Skib		dev_priv->rings[RCS].init(&dev_priv->rings[RCS]);
757235783Skib		if (HAS_BSD(dev))
758235783Skib			dev_priv->rings[VCS].init(&dev_priv->rings[VCS]);
759235783Skib		if (HAS_BLT(dev))
760235783Skib			dev_priv->rings[BCS].init(&dev_priv->rings[BCS]);
761235783Skib
762235783Skib		i915_gem_init_ppgtt(dev);
763235783Skib
764235783Skib		drm_irq_uninstall(dev);
765235783Skib		drm_mode_config_reset(dev);
766235783Skib		DRM_UNLOCK(dev);
767235783Skib		drm_irq_install(dev);
768235783Skib		DRM_LOCK(dev);
769235783Skib	}
770235783Skib	DRM_UNLOCK(dev);
771235783Skib
772235783Skib	if (need_display) {
773235783Skib		sx_xlock(&dev->mode_config.mutex);
774235783Skib		drm_helper_resume_force_mode(dev);
775235783Skib		sx_xunlock(&dev->mode_config.mutex);
776235783Skib	}
777235783Skib
778235783Skib	return (0);
779235783Skib}
780235783Skib
781235783Skib#define __i915_read(x, y) \
782235783Skibu##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
783235783Skib	u##x val = 0; \
784235783Skib	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
785235783Skib		mtx_lock(&dev_priv->gt_lock); \
786235783Skib		if (dev_priv->forcewake_count == 0) \
787235783Skib			dev_priv->display.force_wake_get(dev_priv); \
788235783Skib		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
789235783Skib		if (dev_priv->forcewake_count == 0) \
790235783Skib			dev_priv->display.force_wake_put(dev_priv); \
791235783Skib		mtx_unlock(&dev_priv->gt_lock); \
792235783Skib	} else { \
793235783Skib		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
794235783Skib	} \
795235783Skib	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
796235783Skib	return val; \
797235783Skib}
798235783Skib
799235783Skib__i915_read(8, 8)
800235783Skib__i915_read(16, 16)
801235783Skib__i915_read(32, 32)
802235783Skib__i915_read(64, 64)
803235783Skib#undef __i915_read
804235783Skib
805235783Skib#define __i915_write(x, y) \
806235783Skibvoid i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
807235783Skib	u32 __fifo_ret = 0; \
808235783Skib	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
809235783Skib	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
810235783Skib		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
811235783Skib	} \
812235783Skib	DRM_WRITE##y(dev_priv->mmio_map, reg, val); \
813235783Skib	if (__predict_false(__fifo_ret)) { \
814235783Skib		gen6_gt_check_fifodbg(dev_priv); \
815235783Skib	} \
816235783Skib}
817235783Skib__i915_write(8, 8)
818235783Skib__i915_write(16, 16)
819235783Skib__i915_write(32, 32)
820235783Skib__i915_write(64, 64)
821235783Skib#undef __i915_write
822