xref: /dflybsd-src/sys/dev/drm/i915/i915_drv.c (revision 5d0b1887e5c804219a3ca9456f1cd6c5331d02c2)
1e555d299SFrançois Tigeot /* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
2c4a9e910SFrançois Tigeot  */
3e555d299SFrançois Tigeot /*
4e555d299SFrançois Tigeot  *
5e555d299SFrançois Tigeot  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6c4a9e910SFrançois Tigeot  * All Rights Reserved.
7c4a9e910SFrançois Tigeot  *
8c4a9e910SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
9e555d299SFrançois Tigeot  * copy of this software and associated documentation files (the
10e555d299SFrançois Tigeot  * "Software"), to deal in the Software without restriction, including
11e555d299SFrançois Tigeot  * without limitation the rights to use, copy, modify, merge, publish,
12e555d299SFrançois Tigeot  * distribute, sub license, and/or sell copies of the Software, and to
13e555d299SFrançois Tigeot  * permit persons to whom the Software is furnished to do so, subject to
14e555d299SFrançois Tigeot  * the following conditions:
15c4a9e910SFrançois Tigeot  *
16e555d299SFrançois Tigeot  * The above copyright notice and this permission notice (including the
17e555d299SFrançois Tigeot  * next paragraph) shall be included in all copies or substantial portions
18e555d299SFrançois Tigeot  * of the Software.
19c4a9e910SFrançois Tigeot  *
20e555d299SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21e555d299SFrançois Tigeot  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22e555d299SFrançois Tigeot  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23e555d299SFrançois Tigeot  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
24e555d299SFrançois Tigeot  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25e555d299SFrançois Tigeot  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26e555d299SFrançois Tigeot  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27c4a9e910SFrançois Tigeot  *
28c4a9e910SFrançois Tigeot  */
29c4a9e910SFrançois Tigeot 
3018e26a6dSFrançois Tigeot #include <drm/drmP.h>
315c6c6f23SFrançois Tigeot #include <drm/i915_drm.h>
32c4a9e910SFrançois Tigeot #include "i915_drv.h"
3318e26a6dSFrançois Tigeot #include <drm/drm_pciids.h>
34e3adcf8fSFrançois Tigeot #include "intel_drv.h"
35c4a9e910SFrançois Tigeot 
3619df918dSFrançois Tigeot /*		 "Specify LVDS channel mode "
3719df918dSFrançois Tigeot 		 "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)" */
3819df918dSFrançois Tigeot int i915_lvds_channel_mode __read_mostly = 0;
3919df918dSFrançois Tigeot TUNABLE_INT("drm.i915.lvds_channel_mode", &i915_lvds_channel_mode);
4019df918dSFrançois Tigeot 
41*5d0b1887SFrançois Tigeot int i915_disable_power_well __read_mostly = 1;
42a2fdbec6SFrançois Tigeot module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
43a2fdbec6SFrançois Tigeot MODULE_PARM_DESC(disable_power_well,
44*5d0b1887SFrançois Tigeot 		 "Disable the power well when possible (default: true)");
45a2fdbec6SFrançois Tigeot 
46a2fdbec6SFrançois Tigeot bool i915_enable_hangcheck __read_mostly = true;
47a2fdbec6SFrançois Tigeot module_param_named(enable_hangcheck, i915_enable_hangcheck, bool, 0644);
48a2fdbec6SFrançois Tigeot MODULE_PARM_DESC(enable_hangcheck,
49a2fdbec6SFrançois Tigeot 		"Periodically check GPU activity for detecting hangs. "
50a2fdbec6SFrançois Tigeot 		"WARNING: Disabling this can cause system wide hangs. "
51a2fdbec6SFrançois Tigeot 		"(default: true)");
52a2fdbec6SFrançois Tigeot 
53*5d0b1887SFrançois Tigeot int i915_enable_ips __read_mostly = 1;
54*5d0b1887SFrançois Tigeot module_param_named(enable_ips, i915_enable_ips, int, 0600);
55*5d0b1887SFrançois Tigeot MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
56*5d0b1887SFrançois Tigeot 
57f0b54121SFrançois Tigeot static struct drm_driver driver;
58f0b54121SFrançois Tigeot 
598e26cdf6SFrançois Tigeot #define INTEL_VGA_DEVICE(id, info) {		\
608e26cdf6SFrançois Tigeot 	.class = PCI_BASE_CLASS_DISPLAY << 16,	\
618e26cdf6SFrançois Tigeot 	.class_mask = 0xff0000,			\
628e26cdf6SFrançois Tigeot 	.vendor = 0x8086,			\
63e9243325SFrançois Tigeot 	.device = id,				\
648e26cdf6SFrançois Tigeot 	.subvendor = PCI_ANY_ID,		\
658e26cdf6SFrançois Tigeot 	.subdevice = PCI_ANY_ID,		\
668e26cdf6SFrançois Tigeot 	.driver_data = (unsigned long) info }
678e26cdf6SFrançois Tigeot 
688e26cdf6SFrançois Tigeot #define INTEL_QUANTA_VGA_DEVICE(info) {		\
698e26cdf6SFrançois Tigeot 	.class = PCI_BASE_CLASS_DISPLAY << 16,	\
708e26cdf6SFrançois Tigeot 	.class_mask = 0xff0000,			\
718e26cdf6SFrançois Tigeot 	.vendor = 0x8086,			\
728e26cdf6SFrançois Tigeot 	.device = 0x16a,			\
738e26cdf6SFrançois Tigeot 	.subvendor = 0x152d,			\
748e26cdf6SFrançois Tigeot 	.subdevice = 0x8990,			\
758e26cdf6SFrançois Tigeot 	.driver_data = (unsigned long) info }
768e26cdf6SFrançois Tigeot 
77e9243325SFrançois Tigeot 
78e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i830_info = {
798e26cdf6SFrançois Tigeot 	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
80e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
81e3adcf8fSFrançois Tigeot };
82c4a9e910SFrançois Tigeot 
83e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_845g_info = {
848e26cdf6SFrançois Tigeot 	.gen = 2, .num_pipes = 1,
85e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
86e3adcf8fSFrançois Tigeot };
87e3adcf8fSFrançois Tigeot 
88e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i85x_info = {
898e26cdf6SFrançois Tigeot 	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
90e3adcf8fSFrançois Tigeot 	.cursor_needs_physical = 1,
91e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
92e3adcf8fSFrançois Tigeot };
93e3adcf8fSFrançois Tigeot 
94e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i865g_info = {
958e26cdf6SFrançois Tigeot 	.gen = 2, .num_pipes = 1,
96e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
97e3adcf8fSFrançois Tigeot };
98e3adcf8fSFrançois Tigeot 
99e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i915g_info = {
1008e26cdf6SFrançois Tigeot 	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
101e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
102e3adcf8fSFrançois Tigeot };
103e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i915gm_info = {
1048e26cdf6SFrançois Tigeot 	.gen = 3, .is_mobile = 1, .num_pipes = 2,
105e3adcf8fSFrançois Tigeot 	.cursor_needs_physical = 1,
106e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
107e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
108e3adcf8fSFrançois Tigeot };
109e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i945g_info = {
1108e26cdf6SFrançois Tigeot 	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
111e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
112e3adcf8fSFrançois Tigeot };
113e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i945gm_info = {
1148e26cdf6SFrançois Tigeot 	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
115e3adcf8fSFrançois Tigeot 	.has_hotplug = 1, .cursor_needs_physical = 1,
116e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
117e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
118e3adcf8fSFrançois Tigeot };
119e3adcf8fSFrançois Tigeot 
120e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i965g_info = {
1218e26cdf6SFrançois Tigeot 	.gen = 4, .is_broadwater = 1, .num_pipes = 2,
122e3adcf8fSFrançois Tigeot 	.has_hotplug = 1,
123e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
124e3adcf8fSFrançois Tigeot };
125e3adcf8fSFrançois Tigeot 
126e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i965gm_info = {
1278e26cdf6SFrançois Tigeot 	.gen = 4, .is_crestline = 1, .num_pipes = 2,
128e3adcf8fSFrançois Tigeot 	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
129e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
130e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
131e3adcf8fSFrançois Tigeot };
132e3adcf8fSFrançois Tigeot 
133e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_g33_info = {
1348e26cdf6SFrançois Tigeot 	.gen = 3, .is_g33 = 1, .num_pipes = 2,
135e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
136e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
137e3adcf8fSFrançois Tigeot };
138e3adcf8fSFrançois Tigeot 
139e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_g45_info = {
1408e26cdf6SFrançois Tigeot 	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
141e3adcf8fSFrançois Tigeot 	.has_pipe_cxsr = 1, .has_hotplug = 1,
142e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
143e3adcf8fSFrançois Tigeot };
144e3adcf8fSFrançois Tigeot 
145e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_gm45_info = {
1468e26cdf6SFrançois Tigeot 	.gen = 4, .is_g4x = 1, .num_pipes = 2,
147e3adcf8fSFrançois Tigeot 	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
148e3adcf8fSFrançois Tigeot 	.has_pipe_cxsr = 1, .has_hotplug = 1,
149e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
150e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
151e3adcf8fSFrançois Tigeot };
152e3adcf8fSFrançois Tigeot 
153e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_pineview_info = {
1548e26cdf6SFrançois Tigeot 	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
155e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
156e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
157e3adcf8fSFrançois Tigeot };
158e3adcf8fSFrançois Tigeot 
159e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ironlake_d_info = {
1608e26cdf6SFrançois Tigeot 	.gen = 5, .num_pipes = 2,
161e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
162e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
163e3adcf8fSFrançois Tigeot };
164e3adcf8fSFrançois Tigeot 
165e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ironlake_m_info = {
1668e26cdf6SFrançois Tigeot 	.gen = 5, .is_mobile = 1, .num_pipes = 2,
167e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
16800dca1bbSFrançois Tigeot 	.has_fbc = 1,
169e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
170e3adcf8fSFrançois Tigeot };
171e3adcf8fSFrançois Tigeot 
172e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_sandybridge_d_info = {
1738e26cdf6SFrançois Tigeot 	.gen = 6, .num_pipes = 2,
174e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
175e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
176e3adcf8fSFrançois Tigeot 	.has_blt_ring = 1,
177e3adcf8fSFrançois Tigeot 	.has_llc = 1,
178e9243325SFrançois Tigeot 	.has_force_wake = 1,
179e3adcf8fSFrançois Tigeot };
180e3adcf8fSFrançois Tigeot 
181e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_sandybridge_m_info = {
1828e26cdf6SFrançois Tigeot 	.gen = 6, .is_mobile = 1, .num_pipes = 2,
183e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
184e3adcf8fSFrançois Tigeot 	.has_fbc = 1,
185e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
186e3adcf8fSFrançois Tigeot 	.has_blt_ring = 1,
187e3adcf8fSFrançois Tigeot 	.has_llc = 1,
188e9243325SFrançois Tigeot 	.has_force_wake = 1,
189e3adcf8fSFrançois Tigeot };
190e3adcf8fSFrançois Tigeot 
1918e26cdf6SFrançois Tigeot #define GEN7_FEATURES  \
1928e26cdf6SFrançois Tigeot 	.gen = 7, .num_pipes = 3, \
1938e26cdf6SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1, \
1948e26cdf6SFrançois Tigeot 	.has_bsd_ring = 1, \
1958e26cdf6SFrançois Tigeot 	.has_blt_ring = 1, \
1968e26cdf6SFrançois Tigeot 	.has_llc = 1, \
1978e26cdf6SFrançois Tigeot 	.has_force_wake = 1
1988e26cdf6SFrançois Tigeot 
199e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ivybridge_d_info = {
2008e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2018e26cdf6SFrançois Tigeot 	.is_ivybridge = 1,
202e3adcf8fSFrançois Tigeot };
203e3adcf8fSFrançois Tigeot 
204e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ivybridge_m_info = {
2058e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2068e26cdf6SFrançois Tigeot 	.is_ivybridge = 1,
2078e26cdf6SFrançois Tigeot 	.is_mobile = 1,
208*5d0b1887SFrançois Tigeot 	.has_fbc = 1,
2098e26cdf6SFrançois Tigeot };
2108e26cdf6SFrançois Tigeot 
2118e26cdf6SFrançois Tigeot static const struct intel_device_info intel_ivybridge_q_info = {
2128e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2138e26cdf6SFrançois Tigeot 	.is_ivybridge = 1,
2148e26cdf6SFrançois Tigeot 	.num_pipes = 0, /* legal, last one wins */
215e3adcf8fSFrançois Tigeot };
216e3adcf8fSFrançois Tigeot 
217e9243325SFrançois Tigeot static const struct intel_device_info intel_valleyview_m_info = {
2188e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2198e26cdf6SFrançois Tigeot 	.is_mobile = 1,
2208e26cdf6SFrançois Tigeot 	.num_pipes = 2,
221e9243325SFrançois Tigeot 	.is_valleyview = 1,
222a2fdbec6SFrançois Tigeot 	.display_mmio_offset = VLV_DISPLAY_BASE,
2238e26cdf6SFrançois Tigeot 	.has_llc = 0, /* legal, last one wins */
224e9243325SFrançois Tigeot };
225e9243325SFrançois Tigeot 
226e9243325SFrançois Tigeot static const struct intel_device_info intel_valleyview_d_info = {
2278e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2288e26cdf6SFrançois Tigeot 	.num_pipes = 2,
229e9243325SFrançois Tigeot 	.is_valleyview = 1,
230a2fdbec6SFrançois Tigeot 	.display_mmio_offset = VLV_DISPLAY_BASE,
2318e26cdf6SFrançois Tigeot 	.has_llc = 0, /* legal, last one wins */
232e9243325SFrançois Tigeot };
233e9243325SFrançois Tigeot 
234e9243325SFrançois Tigeot static const struct intel_device_info intel_haswell_d_info = {
2358e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2368e26cdf6SFrançois Tigeot 	.is_haswell = 1,
237*5d0b1887SFrançois Tigeot 	.has_ddi = 1,
238*5d0b1887SFrançois Tigeot 	.has_fpga_dbg = 1,
239*5d0b1887SFrançois Tigeot 	.has_vebox_ring = 1,
240e9243325SFrançois Tigeot };
241e9243325SFrançois Tigeot 
242e9243325SFrançois Tigeot static const struct intel_device_info intel_haswell_m_info = {
2438e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2448e26cdf6SFrançois Tigeot 	.is_haswell = 1,
2458e26cdf6SFrançois Tigeot 	.is_mobile = 1,
246*5d0b1887SFrançois Tigeot 	.has_ddi = 1,
247*5d0b1887SFrançois Tigeot 	.has_fpga_dbg = 1,
248*5d0b1887SFrançois Tigeot 	.has_fbc = 1,
249*5d0b1887SFrançois Tigeot 	.has_vebox_ring = 1,
250e9243325SFrançois Tigeot };
251e3adcf8fSFrançois Tigeot 
2528e26cdf6SFrançois Tigeot static const struct pci_device_id pciidlist[] = {		/* aka */
253e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),		/* I830_M */
254e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),		/* 845_G */
255e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),		/* I855_GM */
256e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
257e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),		/* I865_G */
258e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),		/* I915_G */
259e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),		/* E7221_G */
260e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),		/* I915_GM */
261e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),		/* I945_G */
262e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),		/* I945_GM */
263e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),		/* I945_GME */
264e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),		/* I946_GZ */
265e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),		/* G35_G */
266e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),		/* I965_Q */
267e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),		/* I965_G */
268e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),		/* Q35_G */
269e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),		/* G33_G */
270e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),		/* Q33_G */
271e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),		/* I965_GM */
272e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),		/* I965_GME */
273e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),		/* GM45_G */
274e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),		/* IGD_E_G */
275e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),		/* Q45_G */
276e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),		/* G45_G */
277e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),		/* G41_G */
278e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),		/* B43_G */
279e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e92, &intel_g45_info),		/* B43_G.1 */
280e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
281e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
282e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
283e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
284e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
285e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info),
286e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info),
287e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
288e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
289e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
290e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
291e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0156, &intel_ivybridge_m_info), /* GT1 mobile */
292e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0166, &intel_ivybridge_m_info), /* GT2 mobile */
293e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
294e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
295e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
296e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
297e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
298e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
299a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT3 desktop */
300e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */
301e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */
302a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT3 server */
303e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
304e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
305e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */
306a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x040B, &intel_haswell_d_info), /* GT1 reserved */
307a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x041B, &intel_haswell_d_info), /* GT2 reserved */
308a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x042B, &intel_haswell_d_info), /* GT3 reserved */
309a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x040E, &intel_haswell_d_info), /* GT1 reserved */
310a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x041E, &intel_haswell_d_info), /* GT2 reserved */
311a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x042E, &intel_haswell_d_info), /* GT3 reserved */
312e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */
313e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */
314a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT3 desktop */
315e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */
316e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */
317a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT3 server */
318e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */
319e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */
320a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT3 mobile */
321a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C0B, &intel_haswell_d_info), /* SDV GT1 reserved */
322a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C1B, &intel_haswell_d_info), /* SDV GT2 reserved */
323a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C2B, &intel_haswell_d_info), /* SDV GT3 reserved */
324a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C0E, &intel_haswell_d_info), /* SDV GT1 reserved */
325a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C1E, &intel_haswell_d_info), /* SDV GT2 reserved */
326a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C2E, &intel_haswell_d_info), /* SDV GT3 reserved */
327e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */
328e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */
329a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT3 desktop */
330e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */
331e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */
332a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT3 server */
333e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
334e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
335a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT3 mobile */
336a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A0B, &intel_haswell_d_info), /* ULT GT1 reserved */
337a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A1B, &intel_haswell_d_info), /* ULT GT2 reserved */
338a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A2B, &intel_haswell_d_info), /* ULT GT3 reserved */
339a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A0E, &intel_haswell_m_info), /* ULT GT1 reserved */
340a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A1E, &intel_haswell_m_info), /* ULT GT2 reserved */
341a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A2E, &intel_haswell_m_info), /* ULT GT3 reserved */
342e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */
343e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */
344a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT3 desktop */
345e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */
346e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */
347a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT3 server */
348e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */
349e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
350a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT3 mobile */
351a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D0B, &intel_haswell_d_info), /* CRW GT1 reserved */
352a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D1B, &intel_haswell_d_info), /* CRW GT2 reserved */
353a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D2B, &intel_haswell_d_info), /* CRW GT3 reserved */
354a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D0E, &intel_haswell_d_info), /* CRW GT1 reserved */
355a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D1E, &intel_haswell_d_info), /* CRW GT2 reserved */
356a2fdbec6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D2E, &intel_haswell_d_info), /* CRW GT3 reserved */
357e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
3588e26cdf6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0f31, &intel_valleyview_m_info),
3598e26cdf6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0f32, &intel_valleyview_m_info),
3608e26cdf6SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0f33, &intel_valleyview_m_info),
361e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
362e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
363e3adcf8fSFrançois Tigeot 	{0, 0}
364e3adcf8fSFrançois Tigeot };
365e3adcf8fSFrançois Tigeot 
366e9243325SFrançois Tigeot #define	PCI_VENDOR_INTEL	0x8086
367e9243325SFrançois Tigeot 
368e9243325SFrançois Tigeot void intel_detect_pch(struct drm_device *dev)
369e9243325SFrançois Tigeot {
370e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
371e9243325SFrançois Tigeot 	device_t pch;
372e9243325SFrançois Tigeot 
3738e26cdf6SFrançois Tigeot 	/* In all current cases, num_pipes is equivalent to the PCH_NOP setting
3748e26cdf6SFrançois Tigeot 	 * (which really amounts to a PCH but no South Display).
3758e26cdf6SFrançois Tigeot 	 */
3768e26cdf6SFrançois Tigeot 	if (INTEL_INFO(dev)->num_pipes == 0) {
3778e26cdf6SFrançois Tigeot 		dev_priv->pch_type = PCH_NOP;
3788e26cdf6SFrançois Tigeot 		return;
3798e26cdf6SFrançois Tigeot 	}
3808e26cdf6SFrançois Tigeot 
381e9243325SFrançois Tigeot 	/*
382e9243325SFrançois Tigeot 	 * The reason to probe ISA bridge instead of Dev31:Fun0 is to
383e9243325SFrançois Tigeot 	 * make graphics device passthrough work easy for VMM, that only
384e9243325SFrançois Tigeot 	 * need to expose ISA bridge to let driver know the real hardware
385e9243325SFrançois Tigeot 	 * underneath. This is a requirement from virtualization team.
386e9243325SFrançois Tigeot 	 */
387e9243325SFrançois Tigeot 	pch = pci_find_class(PCIC_BRIDGE, PCIS_BRIDGE_ISA);
388e9243325SFrançois Tigeot 	if (pch) {
389e9243325SFrançois Tigeot 		if (pci_get_vendor(pch) == PCI_VENDOR_INTEL) {
390e9243325SFrançois Tigeot 			unsigned short id;
391e9243325SFrançois Tigeot 			id = pci_get_device(pch) & INTEL_PCH_DEVICE_ID_MASK;
392e9243325SFrançois Tigeot 			dev_priv->pch_id = id;
393e9243325SFrançois Tigeot 
394e9243325SFrançois Tigeot 			if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
395e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_IBX;
396e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
397e9243325SFrançois Tigeot 				WARN_ON(!IS_GEN5(dev));
398e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
399e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_CPT;
400e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found CougarPoint PCH\n");
401e9243325SFrançois Tigeot 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
402e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
403e9243325SFrançois Tigeot 				/* PantherPoint is CPT compatible */
404e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_CPT;
405e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found PatherPoint PCH\n");
406e9243325SFrançois Tigeot 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
407e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
408e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_LPT;
409e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
410e9243325SFrançois Tigeot 				WARN_ON(!IS_HASWELL(dev));
4118e26cdf6SFrançois Tigeot 				WARN_ON(IS_ULT(dev));
412e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
413e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_LPT;
414e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
415e9243325SFrançois Tigeot 				WARN_ON(!IS_HASWELL(dev));
4168e26cdf6SFrançois Tigeot 				WARN_ON(!IS_ULT(dev));
417e9243325SFrançois Tigeot 			}
418e9243325SFrançois Tigeot 		}
419e9243325SFrançois Tigeot #if 0
420e9243325SFrançois Tigeot 		pci_dev_put(pch);
421e9243325SFrançois Tigeot #endif
422e9243325SFrançois Tigeot 	}
423e9243325SFrançois Tigeot }
424e9243325SFrançois Tigeot 
4253d4007e0SFrançois Tigeot bool i915_semaphore_is_enabled(struct drm_device *dev)
4263d4007e0SFrançois Tigeot {
4273d4007e0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen < 6)
4283d4007e0SFrançois Tigeot 		return 0;
4293d4007e0SFrançois Tigeot 
4303d4007e0SFrançois Tigeot 	if (i915_semaphores >= 0)
4313d4007e0SFrançois Tigeot 		return i915_semaphores;
4323d4007e0SFrançois Tigeot 
4333d4007e0SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
4343d4007e0SFrançois Tigeot 	/* Enable semaphores on SNB when IO remapping is off */
4353d4007e0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
4363d4007e0SFrançois Tigeot 		return false;
4373d4007e0SFrançois Tigeot #endif
4383d4007e0SFrançois Tigeot 
4393d4007e0SFrançois Tigeot 	return 1;
4403d4007e0SFrançois Tigeot }
4413d4007e0SFrançois Tigeot 
442e3adcf8fSFrançois Tigeot static int i915_drm_freeze(struct drm_device *dev)
443e3adcf8fSFrançois Tigeot {
444e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
4458e26cdf6SFrançois Tigeot 	struct drm_crtc *crtc;
446e3adcf8fSFrançois Tigeot 
447a2fdbec6SFrançois Tigeot 	/* ignore lid events during suspend */
448a2fdbec6SFrançois Tigeot 	mutex_lock(&dev_priv->modeset_restore_lock);
449a2fdbec6SFrançois Tigeot 	dev_priv->modeset_restore = MODESET_SUSPENDED;
450a2fdbec6SFrançois Tigeot 	mutex_unlock(&dev_priv->modeset_restore_lock);
451a2fdbec6SFrançois Tigeot 
452a2fdbec6SFrançois Tigeot 	intel_set_power_well(dev, true);
453a2fdbec6SFrançois Tigeot 
454e3adcf8fSFrançois Tigeot 	drm_kms_helper_poll_disable(dev);
455e3adcf8fSFrançois Tigeot 
456e3adcf8fSFrançois Tigeot #if 0
457e3adcf8fSFrançois Tigeot 	pci_save_state(dev->pdev);
458e3adcf8fSFrançois Tigeot #endif
459e3adcf8fSFrançois Tigeot 
460e3adcf8fSFrançois Tigeot 	/* If KMS is active, we do the leavevt stuff here */
461e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
462e9243325SFrançois Tigeot 		int error = i915_gem_idle(dev);
463e3adcf8fSFrançois Tigeot 		if (error) {
464a2fdbec6SFrançois Tigeot 			dev_err(dev->pdev->dev,
465a2fdbec6SFrançois Tigeot 				"GEM idle failed, resume might fail\n");
466e9243325SFrançois Tigeot 			return error;
467e3adcf8fSFrançois Tigeot 		}
468a2fdbec6SFrançois Tigeot 
469e9243325SFrançois Tigeot 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
470e9243325SFrançois Tigeot 
471e3adcf8fSFrançois Tigeot 		drm_irq_uninstall(dev);
472a2fdbec6SFrançois Tigeot 		dev_priv->enable_hotplug_processing = false;
4738e26cdf6SFrançois Tigeot 		/*
4748e26cdf6SFrançois Tigeot 		 * Disable CRTCs directly since we want to preserve sw state
4758e26cdf6SFrançois Tigeot 		 * for _thaw.
4768e26cdf6SFrançois Tigeot 		 */
4778e26cdf6SFrançois Tigeot 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
4788e26cdf6SFrançois Tigeot 			dev_priv->display.crtc_disable(crtc);
479*5d0b1887SFrançois Tigeot 
480*5d0b1887SFrançois Tigeot 		intel_modeset_suspend_hw(dev);
481e3adcf8fSFrançois Tigeot 	}
482e3adcf8fSFrançois Tigeot 
483e3adcf8fSFrançois Tigeot 	i915_save_state(dev);
484e3adcf8fSFrançois Tigeot 
485e3adcf8fSFrançois Tigeot 	intel_opregion_fini(dev);
486e3adcf8fSFrançois Tigeot 
487*5d0b1887SFrançois Tigeot #if 0
488*5d0b1887SFrançois Tigeot 	console_lock();
489*5d0b1887SFrançois Tigeot 	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
490*5d0b1887SFrançois Tigeot 	console_unlock();
491*5d0b1887SFrançois Tigeot #endif
492*5d0b1887SFrançois Tigeot 
493e3adcf8fSFrançois Tigeot 	return 0;
494e3adcf8fSFrançois Tigeot }
495e3adcf8fSFrançois Tigeot 
496e3adcf8fSFrançois Tigeot static int
497e3adcf8fSFrançois Tigeot i915_suspend(device_t kdev)
498e3adcf8fSFrançois Tigeot {
499e3adcf8fSFrançois Tigeot 	struct drm_device *dev;
500e3adcf8fSFrançois Tigeot 	int error;
501e3adcf8fSFrançois Tigeot 
502e3adcf8fSFrançois Tigeot 	dev = device_get_softc(kdev);
503e3adcf8fSFrançois Tigeot 	if (dev == NULL || dev->dev_private == NULL) {
504c4a9e910SFrançois Tigeot 		DRM_ERROR("DRM not initialized, aborting suspend.\n");
505c4a9e910SFrançois Tigeot 		return -ENODEV;
506c4a9e910SFrançois Tigeot 	}
507c4a9e910SFrançois Tigeot 
508e3adcf8fSFrançois Tigeot 	DRM_DEBUG_KMS("starting suspend\n");
509e3adcf8fSFrançois Tigeot 	error = i915_drm_freeze(dev);
510e3adcf8fSFrançois Tigeot 	if (error)
511e3adcf8fSFrançois Tigeot 		return (error);
512c4a9e910SFrançois Tigeot 
513e3adcf8fSFrançois Tigeot 	error = bus_generic_suspend(kdev);
514e3adcf8fSFrançois Tigeot 	DRM_DEBUG_KMS("finished suspend %d\n", error);
515e3adcf8fSFrançois Tigeot 	return (error);
516c4a9e910SFrançois Tigeot }
517c4a9e910SFrançois Tigeot 
518*5d0b1887SFrançois Tigeot #if 0
519*5d0b1887SFrançois Tigeot void intel_console_resume(struct work_struct *work)
520*5d0b1887SFrançois Tigeot {
521*5d0b1887SFrançois Tigeot 	struct drm_i915_private *dev_priv =
522*5d0b1887SFrançois Tigeot 		container_of(work, struct drm_i915_private,
523*5d0b1887SFrançois Tigeot 			     console_resume_work);
524*5d0b1887SFrançois Tigeot 	struct drm_device *dev = dev_priv->dev;
525*5d0b1887SFrançois Tigeot 
526*5d0b1887SFrançois Tigeot 	console_lock();
527*5d0b1887SFrançois Tigeot 	intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
528*5d0b1887SFrançois Tigeot 	console_unlock();
529*5d0b1887SFrançois Tigeot }
530*5d0b1887SFrançois Tigeot #endif
531*5d0b1887SFrançois Tigeot 
5328e26cdf6SFrançois Tigeot static void intel_resume_hotplug(struct drm_device *dev)
5338e26cdf6SFrançois Tigeot {
5348e26cdf6SFrançois Tigeot 	struct drm_mode_config *mode_config = &dev->mode_config;
5358e26cdf6SFrançois Tigeot 	struct intel_encoder *encoder;
5368e26cdf6SFrançois Tigeot 
5378e26cdf6SFrançois Tigeot 	mutex_lock(&mode_config->mutex);
5388e26cdf6SFrançois Tigeot 	DRM_DEBUG_KMS("running encoder hotplug functions\n");
5398e26cdf6SFrançois Tigeot 
5408e26cdf6SFrançois Tigeot 	list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
5418e26cdf6SFrançois Tigeot 		if (encoder->hot_plug)
5428e26cdf6SFrançois Tigeot 			encoder->hot_plug(encoder);
5438e26cdf6SFrançois Tigeot 
5448e26cdf6SFrançois Tigeot 	mutex_unlock(&mode_config->mutex);
5458e26cdf6SFrançois Tigeot 
5468e26cdf6SFrançois Tigeot 	/* Just fire off a uevent and let userspace tell us what to do */
5478e26cdf6SFrançois Tigeot 	drm_helper_hpd_irq_event(dev);
5488e26cdf6SFrançois Tigeot }
5498e26cdf6SFrançois Tigeot 
550a2fdbec6SFrançois Tigeot static int __i915_drm_thaw(struct drm_device *dev)
551c4a9e910SFrançois Tigeot {
552e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
553e3adcf8fSFrançois Tigeot 	int error = 0;
554c4a9e910SFrançois Tigeot 
555c4a9e910SFrançois Tigeot 	i915_restore_state(dev);
556e3adcf8fSFrançois Tigeot 	intel_opregion_setup(dev);
557c4a9e910SFrançois Tigeot 
558e3adcf8fSFrançois Tigeot 	/* KMS EnterVT equivalent */
559e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
56019df918dSFrançois Tigeot 		intel_init_pch_refclk(dev);
56119df918dSFrançois Tigeot 
562a2fdbec6SFrançois Tigeot 		mutex_lock(&dev->struct_mutex);
563e3adcf8fSFrançois Tigeot 		dev_priv->mm.suspended = 0;
564e3adcf8fSFrançois Tigeot 
565e3adcf8fSFrançois Tigeot 		error = i915_gem_init_hw(dev);
566a2fdbec6SFrançois Tigeot 		mutex_unlock(&dev->struct_mutex);
567a2fdbec6SFrançois Tigeot 
568a2fdbec6SFrançois Tigeot 		/* We need working interrupts for modeset enabling ... */
569a2fdbec6SFrançois Tigeot 		drm_irq_install(dev);
57019df918dSFrançois Tigeot 
57119df918dSFrançois Tigeot 		intel_modeset_init_hw(dev);
5728e26cdf6SFrançois Tigeot 
5738e26cdf6SFrançois Tigeot 		drm_modeset_lock_all(dev);
5748e26cdf6SFrançois Tigeot 		intel_modeset_setup_hw_state(dev, true);
5758e26cdf6SFrançois Tigeot 		drm_modeset_unlock_all(dev);
576a2fdbec6SFrançois Tigeot 
577a2fdbec6SFrançois Tigeot 		/*
578a2fdbec6SFrançois Tigeot 		 * ... but also need to make sure that hotplug processing
579a2fdbec6SFrançois Tigeot 		 * doesn't cause havoc. Like in the driver load code we don't
580a2fdbec6SFrançois Tigeot 		 * bother with the tiny race here where we might loose hotplug
581a2fdbec6SFrançois Tigeot 		 * notifications.
582a2fdbec6SFrançois Tigeot 		 * */
583a2fdbec6SFrançois Tigeot 		intel_hpd_init(dev);
584a2fdbec6SFrançois Tigeot 		dev_priv->enable_hotplug_processing = true;
5858e26cdf6SFrançois Tigeot 		/* Config may have changed between suspend and resume */
5868e26cdf6SFrançois Tigeot 		intel_resume_hotplug(dev);
587c4a9e910SFrançois Tigeot 	}
588c4a9e910SFrançois Tigeot 
589e3adcf8fSFrançois Tigeot 	intel_opregion_init(dev);
590e3adcf8fSFrançois Tigeot 
591a2fdbec6SFrançois Tigeot 	/*
592a2fdbec6SFrançois Tigeot 	 * The console lock can be pretty contented on resume due
593a2fdbec6SFrançois Tigeot 	 * to all the printk activity.  Try to keep it out of the hot
594a2fdbec6SFrançois Tigeot 	 * path of resume if possible.
595a2fdbec6SFrançois Tigeot 	 */
59619df918dSFrançois Tigeot #if 0
597a2fdbec6SFrançois Tigeot 	if (console_trylock()) {
598*5d0b1887SFrançois Tigeot 		intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
59919df918dSFrançois Tigeot 		console_unlock();
600a2fdbec6SFrançois Tigeot 	} else {
601a2fdbec6SFrançois Tigeot 		schedule_work(&dev_priv->console_resume_work);
602a2fdbec6SFrançois Tigeot 	}
60319df918dSFrançois Tigeot #endif
604a2fdbec6SFrançois Tigeot 
605a2fdbec6SFrançois Tigeot 	mutex_lock(&dev_priv->modeset_restore_lock);
606a2fdbec6SFrançois Tigeot 	dev_priv->modeset_restore = MODESET_DONE;
607a2fdbec6SFrançois Tigeot 	mutex_unlock(&dev_priv->modeset_restore_lock);
608a2fdbec6SFrançois Tigeot 	return error;
609a2fdbec6SFrançois Tigeot }
610a2fdbec6SFrançois Tigeot 
611a2fdbec6SFrançois Tigeot static int i915_drm_thaw(struct drm_device *dev)
612a2fdbec6SFrançois Tigeot {
613a2fdbec6SFrançois Tigeot 	int error = 0;
614a2fdbec6SFrançois Tigeot 
615*5d0b1887SFrançois Tigeot 	intel_gt_sanitize(dev);
616a2fdbec6SFrançois Tigeot 
617a2fdbec6SFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
618a2fdbec6SFrançois Tigeot 		mutex_lock(&dev->struct_mutex);
619a2fdbec6SFrançois Tigeot 		i915_gem_restore_gtt_mappings(dev);
620a2fdbec6SFrançois Tigeot 		mutex_unlock(&dev->struct_mutex);
621a2fdbec6SFrançois Tigeot 	}
622a2fdbec6SFrançois Tigeot 
623a2fdbec6SFrançois Tigeot 	__i915_drm_thaw(dev);
624a2fdbec6SFrançois Tigeot 
625e3adcf8fSFrançois Tigeot 	return error;
626e3adcf8fSFrançois Tigeot }
627e3adcf8fSFrançois Tigeot 
628e3adcf8fSFrançois Tigeot static int
629e3adcf8fSFrançois Tigeot i915_resume(device_t kdev)
630c4a9e910SFrançois Tigeot {
631*5d0b1887SFrançois Tigeot 	struct drm_device *dev = device_get_softc(kdev);
632*5d0b1887SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
633e3adcf8fSFrançois Tigeot 	int ret;
634c4a9e910SFrançois Tigeot 
635e3adcf8fSFrançois Tigeot #if 0
636*5d0b1887SFrançois Tigeot 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
637*5d0b1887SFrançois Tigeot 		return 0;
638*5d0b1887SFrançois Tigeot 
639e3adcf8fSFrançois Tigeot 	if (pci_enable_device(dev->pdev))
640e3adcf8fSFrançois Tigeot 		return -EIO;
641c4a9e910SFrançois Tigeot 
642e3adcf8fSFrançois Tigeot 	pci_set_master(dev->pdev);
643e3adcf8fSFrançois Tigeot #endif
644c4a9e910SFrançois Tigeot 
645*5d0b1887SFrançois Tigeot 	intel_gt_sanitize(dev);
646*5d0b1887SFrançois Tigeot 
647*5d0b1887SFrançois Tigeot 	/*
648*5d0b1887SFrançois Tigeot 	 * Platforms with opregion should have sane BIOS, older ones (gen3 and
649*5d0b1887SFrançois Tigeot 	 * earlier) need this since the BIOS might clear all our scratch PTEs.
650*5d0b1887SFrançois Tigeot 	 */
651*5d0b1887SFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET) &&
652*5d0b1887SFrançois Tigeot 	    !dev_priv->opregion.header) {
653*5d0b1887SFrançois Tigeot 		mutex_lock(&dev->struct_mutex);
654*5d0b1887SFrançois Tigeot 		i915_gem_restore_gtt_mappings(dev);
655*5d0b1887SFrançois Tigeot 		mutex_unlock(&dev->struct_mutex);
656*5d0b1887SFrançois Tigeot 	}
657*5d0b1887SFrançois Tigeot 
658e3adcf8fSFrançois Tigeot 	ret = -i915_drm_thaw(dev);
659*5d0b1887SFrançois Tigeot 	if (ret)
660*5d0b1887SFrançois Tigeot 		return ret;
661*5d0b1887SFrançois Tigeot 
662*5d0b1887SFrançois Tigeot 	ret = bus_generic_resume(kdev);
663*5d0b1887SFrançois Tigeot 	if (ret)
664*5d0b1887SFrançois Tigeot 		return ret;
665e3adcf8fSFrançois Tigeot 
666e3adcf8fSFrançois Tigeot 	drm_kms_helper_poll_enable(dev);
667*5d0b1887SFrançois Tigeot 	return 0;
668c4a9e910SFrançois Tigeot }
669c4a9e910SFrançois Tigeot 
67062e5f8e8SFrançois Tigeot /* XXX Hack for the old *BSD drm code base
67162e5f8e8SFrançois Tigeot  * The device id field is set at probe time */
67262e5f8e8SFrançois Tigeot static drm_pci_id_list_t i915_attach_list[] = {
67362e5f8e8SFrançois Tigeot 	{0x8086, 0, 0, "Intel i915 GPU"},
67462e5f8e8SFrançois Tigeot 	{0, 0, 0, NULL}
67562e5f8e8SFrançois Tigeot };
67662e5f8e8SFrançois Tigeot 
677e3adcf8fSFrançois Tigeot int i915_modeset;
678e3adcf8fSFrançois Tigeot 
679f0b54121SFrançois Tigeot /* static int __init i915_init(void) */
680c4a9e910SFrançois Tigeot static int
681c4a9e910SFrançois Tigeot i915_attach(device_t kdev)
682c4a9e910SFrançois Tigeot {
683e3adcf8fSFrançois Tigeot 	struct drm_device *dev;
684c4a9e910SFrançois Tigeot 
685e3adcf8fSFrançois Tigeot 	dev = device_get_softc(kdev);
686f0b54121SFrançois Tigeot 
687f0b54121SFrançois Tigeot 	driver.num_ioctls = i915_max_ioctl;
688f0b54121SFrançois Tigeot 
689e3adcf8fSFrançois Tigeot 	if (i915_modeset == 1)
690f0b54121SFrançois Tigeot 		driver.driver_features |= DRIVER_MODESET;
691f0b54121SFrançois Tigeot 
692f0b54121SFrançois Tigeot 	dev->driver = &driver;
69362e5f8e8SFrançois Tigeot 	return (drm_attach(kdev, i915_attach_list));
694c4a9e910SFrançois Tigeot }
695c4a9e910SFrançois Tigeot 
696e3adcf8fSFrançois Tigeot const struct intel_device_info *
697e3adcf8fSFrançois Tigeot i915_get_device_id(int device)
698c4a9e910SFrançois Tigeot {
6998e26cdf6SFrançois Tigeot 	const struct pci_device_id *did;
700c4a9e910SFrançois Tigeot 
701e3adcf8fSFrançois Tigeot 	for (did = &pciidlist[0]; did->device != 0; did++) {
702e3adcf8fSFrançois Tigeot 		if (did->device != device)
703e3adcf8fSFrançois Tigeot 			continue;
7048e26cdf6SFrançois Tigeot 		return (struct intel_device_info *)did->driver_data;
705e3adcf8fSFrançois Tigeot 	}
706e3adcf8fSFrançois Tigeot 	return (NULL);
707c4a9e910SFrançois Tigeot }
708c4a9e910SFrançois Tigeot 
709c4a9e910SFrançois Tigeot extern devclass_t drm_devclass;
710e3adcf8fSFrançois Tigeot 
711e3adcf8fSFrançois Tigeot int intel_iommu_enabled = 0;
712e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.intel_iommu_enabled", &intel_iommu_enabled);
713e3adcf8fSFrançois Tigeot 
714e3adcf8fSFrançois Tigeot int i915_semaphores = -1;
715e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.semaphores", &i915_semaphores);
716e3adcf8fSFrançois Tigeot static int i915_try_reset = 1;
717e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.try_reset", &i915_try_reset);
718e3adcf8fSFrançois Tigeot unsigned int i915_lvds_downclock = 0;
719e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.lvds_downclock", &i915_lvds_downclock);
720e3adcf8fSFrançois Tigeot int i915_vbt_sdvo_panel_type = -1;
721e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.vbt_sdvo_panel_type", &i915_vbt_sdvo_panel_type);
722e3adcf8fSFrançois Tigeot unsigned int i915_powersave = 1;
723e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.powersave", &i915_powersave);
724e3adcf8fSFrançois Tigeot int i915_enable_fbc = 0;
725e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.enable_fbc", &i915_enable_fbc);
726e3adcf8fSFrançois Tigeot int i915_enable_rc6 = 0;
727e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.enable_rc6", &i915_enable_rc6);
728e3adcf8fSFrançois Tigeot int i915_panel_use_ssc = -1;
729e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.panel_use_ssc", &i915_panel_use_ssc);
730e3adcf8fSFrançois Tigeot int i915_panel_ignore_lid = 0;
731e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.panel_ignore_lid", &i915_panel_ignore_lid);
732e3adcf8fSFrançois Tigeot int i915_modeset = 1;
733e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.modeset", &i915_modeset);
734e3adcf8fSFrançois Tigeot int i915_enable_ppgtt = -1;
735e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.enable_ppgtt", &i915_enable_ppgtt);
736e3adcf8fSFrançois Tigeot 
73700640ec9SFrançois Tigeot static int i8xx_do_reset(struct drm_device *dev)
738e3adcf8fSFrançois Tigeot {
739e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
740e3adcf8fSFrançois Tigeot 
741e3adcf8fSFrançois Tigeot 	if (IS_I85X(dev))
742e3adcf8fSFrançois Tigeot 		return -ENODEV;
743e3adcf8fSFrançois Tigeot 
744e3adcf8fSFrançois Tigeot 	I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
745e3adcf8fSFrançois Tigeot 	POSTING_READ(D_STATE);
746e3adcf8fSFrançois Tigeot 
747e3adcf8fSFrançois Tigeot 	if (IS_I830(dev) || IS_845G(dev)) {
748e3adcf8fSFrançois Tigeot 		I915_WRITE(DEBUG_RESET_I830,
749e3adcf8fSFrançois Tigeot 			   DEBUG_RESET_DISPLAY |
750e3adcf8fSFrançois Tigeot 			   DEBUG_RESET_RENDER |
751e3adcf8fSFrançois Tigeot 			   DEBUG_RESET_FULL);
752e3adcf8fSFrançois Tigeot 		POSTING_READ(DEBUG_RESET_I830);
75300640ec9SFrançois Tigeot 		msleep(1);
754e3adcf8fSFrançois Tigeot 
755e3adcf8fSFrançois Tigeot 		I915_WRITE(DEBUG_RESET_I830, 0);
756e3adcf8fSFrançois Tigeot 		POSTING_READ(DEBUG_RESET_I830);
757e3adcf8fSFrançois Tigeot 	}
758e3adcf8fSFrançois Tigeot 
75900640ec9SFrançois Tigeot 	msleep(1);
760e3adcf8fSFrançois Tigeot 
761e3adcf8fSFrançois Tigeot 	I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
762e3adcf8fSFrançois Tigeot 	POSTING_READ(D_STATE);
763e3adcf8fSFrançois Tigeot 
764e3adcf8fSFrançois Tigeot 	return 0;
765e3adcf8fSFrançois Tigeot }
766e3adcf8fSFrançois Tigeot 
76700640ec9SFrançois Tigeot static int i965_reset_complete(struct drm_device *dev)
768e3adcf8fSFrançois Tigeot {
769e3adcf8fSFrançois Tigeot 	u8 gdrst;
770f0d07c12SFrançois Tigeot 	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
771f0d07c12SFrançois Tigeot 	return (gdrst & GRDOM_RESET_ENABLE) == 0;
772e3adcf8fSFrançois Tigeot }
773e3adcf8fSFrançois Tigeot 
77400640ec9SFrançois Tigeot static int i965_do_reset(struct drm_device *dev)
775e3adcf8fSFrançois Tigeot {
77600640ec9SFrançois Tigeot 	int ret;
777e3adcf8fSFrançois Tigeot 	u8 gdrst;
778e3adcf8fSFrançois Tigeot 
779e3adcf8fSFrançois Tigeot 	/*
780e3adcf8fSFrançois Tigeot 	 * Set the domains we want to reset (GRDOM/bits 2 and 3) as
781e3adcf8fSFrançois Tigeot 	 * well as the reset bit (GR/bit 0).  Setting the GR bit
782e3adcf8fSFrançois Tigeot 	 * triggers the reset; when done, the hardware will clear it.
783e3adcf8fSFrançois Tigeot 	 */
784f0d07c12SFrançois Tigeot 	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
785f0d07c12SFrançois Tigeot 	pci_write_config_byte(dev->pdev, I965_GDRST,
78600640ec9SFrançois Tigeot 			      gdrst | GRDOM_RENDER |
787f0d07c12SFrançois Tigeot 			      GRDOM_RESET_ENABLE);
78800640ec9SFrançois Tigeot 	ret =  wait_for(i965_reset_complete(dev), 500);
78900640ec9SFrançois Tigeot 	if (ret)
79000640ec9SFrançois Tigeot 		return ret;
791e3adcf8fSFrançois Tigeot 
79200640ec9SFrançois Tigeot 	/* We can't reset render&media without also resetting display ... */
793f0d07c12SFrançois Tigeot 	pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
794f0d07c12SFrançois Tigeot 	pci_write_config_byte(dev->pdev, I965_GDRST,
79500640ec9SFrançois Tigeot 			      gdrst | GRDOM_MEDIA |
796f0d07c12SFrançois Tigeot 			      GRDOM_RESET_ENABLE);
79700640ec9SFrançois Tigeot 
79800640ec9SFrançois Tigeot 	return wait_for(i965_reset_complete(dev), 500);
799e3adcf8fSFrançois Tigeot }
800e3adcf8fSFrançois Tigeot 
80100640ec9SFrançois Tigeot static int ironlake_do_reset(struct drm_device *dev)
802e3adcf8fSFrançois Tigeot {
80300640ec9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
804e3adcf8fSFrançois Tigeot 	u32 gdrst;
80500640ec9SFrançois Tigeot 	int ret;
806e3adcf8fSFrançois Tigeot 
807e3adcf8fSFrançois Tigeot 	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
8088e26cdf6SFrançois Tigeot 	gdrst &= ~GRDOM_MASK;
80900640ec9SFrançois Tigeot 	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
81000640ec9SFrançois Tigeot 		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
81100640ec9SFrançois Tigeot 	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
81200640ec9SFrançois Tigeot 	if (ret)
81300640ec9SFrançois Tigeot 		return ret;
81400640ec9SFrançois Tigeot 
81500640ec9SFrançois Tigeot 	/* We can't reset render&media without also resetting display ... */
81600640ec9SFrançois Tigeot 	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
8178e26cdf6SFrançois Tigeot 	gdrst &= ~GRDOM_MASK;
81800640ec9SFrançois Tigeot 	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
81900640ec9SFrançois Tigeot 		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
82000640ec9SFrançois Tigeot 	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
821e3adcf8fSFrançois Tigeot }
822e3adcf8fSFrançois Tigeot 
823e9243325SFrançois Tigeot static int gen6_do_reset(struct drm_device *dev)
824e3adcf8fSFrançois Tigeot {
825e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
826e3adcf8fSFrançois Tigeot 	int ret;
827e3adcf8fSFrançois Tigeot 
828e3adcf8fSFrançois Tigeot 	dev_priv = dev->dev_private;
829e3adcf8fSFrançois Tigeot 
830e3adcf8fSFrançois Tigeot 	/* Hold gt_lock across reset to prevent any register access
831e3adcf8fSFrançois Tigeot 	 * with forcewake not set correctly
832e3adcf8fSFrançois Tigeot 	 */
833e3adcf8fSFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_EXCLUSIVE);
834e3adcf8fSFrançois Tigeot 
835e3adcf8fSFrançois Tigeot 	/* Reset the chip */
836e3adcf8fSFrançois Tigeot 
837e3adcf8fSFrançois Tigeot 	/* GEN6_GDRST is not in the gt power well, no need to check
838e3adcf8fSFrançois Tigeot 	 * for fifo space for the write or forcewake the chip for
839e3adcf8fSFrançois Tigeot 	 * the read
840e3adcf8fSFrançois Tigeot 	 */
841e3adcf8fSFrançois Tigeot 	I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
842e3adcf8fSFrançois Tigeot 
843e3adcf8fSFrançois Tigeot 	/* Spin waiting for the device to ack the reset request */
84419df918dSFrançois Tigeot 	ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
845e3adcf8fSFrançois Tigeot 
846e3adcf8fSFrançois Tigeot 	/* If reset with a user forcewake, try to restore, otherwise turn it off */
847e3adcf8fSFrançois Tigeot 	if (dev_priv->forcewake_count)
848e9243325SFrançois Tigeot 		dev_priv->gt.force_wake_get(dev_priv);
849e3adcf8fSFrançois Tigeot 	else
850e9243325SFrançois Tigeot 		dev_priv->gt.force_wake_put(dev_priv);
851e3adcf8fSFrançois Tigeot 
852e3adcf8fSFrançois Tigeot 	/* Restore fifo count */
853e3adcf8fSFrançois Tigeot 	dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
854e3adcf8fSFrançois Tigeot 
855e3adcf8fSFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_RELEASE);
856e9243325SFrançois Tigeot 	return ret;
857e3adcf8fSFrançois Tigeot }
858e3adcf8fSFrançois Tigeot 
85900640ec9SFrançois Tigeot int intel_gpu_reset(struct drm_device *dev)
86000640ec9SFrançois Tigeot {
86100640ec9SFrançois Tigeot 	switch (INTEL_INFO(dev)->gen) {
86200640ec9SFrançois Tigeot 	case 7:
863*5d0b1887SFrançois Tigeot 	case 6: return gen6_do_reset(dev);
864*5d0b1887SFrançois Tigeot 	case 5: return ironlake_do_reset(dev);
865*5d0b1887SFrançois Tigeot 	case 4: return i965_do_reset(dev);
866*5d0b1887SFrançois Tigeot 	case 2: return i8xx_do_reset(dev);
867*5d0b1887SFrançois Tigeot 	default: return -ENODEV;
86800640ec9SFrançois Tigeot 	}
86900640ec9SFrançois Tigeot }
87000640ec9SFrançois Tigeot 
871e9243325SFrançois Tigeot /**
872e9243325SFrançois Tigeot  * i915_reset - reset chip after a hang
873e9243325SFrançois Tigeot  * @dev: drm device to reset
874e9243325SFrançois Tigeot  *
875e9243325SFrançois Tigeot  * Reset the chip.  Useful if a hang is detected. Returns zero on successful
876e9243325SFrançois Tigeot  * reset or otherwise an error code.
877e9243325SFrançois Tigeot  *
878e9243325SFrançois Tigeot  * Procedure is fairly simple:
879e9243325SFrançois Tigeot  *   - reset the chip using the reset reg
880e9243325SFrançois Tigeot  *   - re-init context state
881e9243325SFrançois Tigeot  *   - re-init hardware status page
882e9243325SFrançois Tigeot  *   - re-init ring buffer
883e9243325SFrançois Tigeot  *   - re-init interrupt state
884e9243325SFrançois Tigeot  *   - re-init display
885e9243325SFrançois Tigeot  */
88600640ec9SFrançois Tigeot int i915_reset(struct drm_device *dev)
887e3adcf8fSFrançois Tigeot {
888e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
889*5d0b1887SFrançois Tigeot 	bool simulated;
890e9243325SFrançois Tigeot 	int ret;
891e9243325SFrançois Tigeot 
892e9243325SFrançois Tigeot 	if (!i915_try_reset)
893e9243325SFrançois Tigeot 		return 0;
894e9243325SFrançois Tigeot 
895a2fdbec6SFrançois Tigeot 	mutex_lock(&dev->struct_mutex);
896e3adcf8fSFrançois Tigeot 
897e3adcf8fSFrançois Tigeot 	i915_gem_reset(dev);
898e3adcf8fSFrançois Tigeot 
899*5d0b1887SFrançois Tigeot 	simulated = dev_priv->gpu_error.stop_rings != 0;
900*5d0b1887SFrançois Tigeot 
901*5d0b1887SFrançois Tigeot 	if (!simulated && get_seconds() - dev_priv->gpu_error.last_reset < 5) {
902e3adcf8fSFrançois Tigeot 		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
903*5d0b1887SFrançois Tigeot 		ret = -ENODEV;
904*5d0b1887SFrançois Tigeot 	} else {
90500640ec9SFrançois Tigeot 		ret = intel_gpu_reset(dev);
90600640ec9SFrançois Tigeot 
907*5d0b1887SFrançois Tigeot 		/* Also reset the gpu hangman. */
908*5d0b1887SFrançois Tigeot 		if (simulated) {
909*5d0b1887SFrançois Tigeot 			DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
910*5d0b1887SFrançois Tigeot 			dev_priv->gpu_error.stop_rings = 0;
911*5d0b1887SFrançois Tigeot 			if (ret == -ENODEV) {
912*5d0b1887SFrançois Tigeot 				DRM_ERROR("Reset not implemented, but ignoring "
913*5d0b1887SFrançois Tigeot 					  "error for simulated gpu hangs\n");
914*5d0b1887SFrançois Tigeot 				ret = 0;
915*5d0b1887SFrançois Tigeot 			}
916*5d0b1887SFrançois Tigeot 		} else
917*5d0b1887SFrançois Tigeot 			dev_priv->gpu_error.last_reset = get_seconds();
918*5d0b1887SFrançois Tigeot 	}
919e3adcf8fSFrançois Tigeot 	if (ret) {
920e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to reset chip.\n");
921a2fdbec6SFrançois Tigeot 		mutex_unlock(&dev->struct_mutex);
92200640ec9SFrançois Tigeot 		return ret;
923e3adcf8fSFrançois Tigeot 	}
924e3adcf8fSFrançois Tigeot 
925e9243325SFrançois Tigeot 	/* Ok, now get things going again... */
926e9243325SFrançois Tigeot 
927e9243325SFrançois Tigeot 	/*
928e9243325SFrançois Tigeot 	 * Everything depends on having the GTT running, so we need to start
929e9243325SFrançois Tigeot 	 * there.  Fortunately we don't need to do this unless we reset the
930e9243325SFrançois Tigeot 	 * chip at a PCI level.
931e9243325SFrançois Tigeot 	 *
932e9243325SFrançois Tigeot 	 * Next we need to restore the context, but we don't use those
933e9243325SFrançois Tigeot 	 * yet either...
934e9243325SFrançois Tigeot 	 *
935e9243325SFrançois Tigeot 	 * Ring buffer needs to be re-initialized in the KMS case, or if X
936e9243325SFrançois Tigeot 	 * was running at the time of the reset (i.e. we weren't VT
937e9243325SFrançois Tigeot 	 * switched away).
938e9243325SFrançois Tigeot 	 */
939e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
940e3adcf8fSFrançois Tigeot 			!dev_priv->mm.suspended) {
94100640ec9SFrançois Tigeot 		struct intel_ring_buffer *ring;
94200640ec9SFrançois Tigeot 		int i;
94300640ec9SFrançois Tigeot 
944e3adcf8fSFrançois Tigeot 		dev_priv->mm.suspended = 0;
945e3adcf8fSFrançois Tigeot 
946e3adcf8fSFrançois Tigeot 		i915_gem_init_swizzling(dev);
947e3adcf8fSFrançois Tigeot 
94800640ec9SFrançois Tigeot 		for_each_ring(ring, dev_priv, i)
94900640ec9SFrançois Tigeot 			ring->init(ring);
950e3adcf8fSFrançois Tigeot 
95100640ec9SFrançois Tigeot 		i915_gem_context_init(dev);
9528e26cdf6SFrançois Tigeot 		if (dev_priv->mm.aliasing_ppgtt) {
9538e26cdf6SFrançois Tigeot 			ret = dev_priv->mm.aliasing_ppgtt->enable(dev);
9548e26cdf6SFrançois Tigeot 			if (ret)
9558e26cdf6SFrançois Tigeot 				i915_gem_cleanup_aliasing_ppgtt(dev);
9568e26cdf6SFrançois Tigeot 		}
957e3adcf8fSFrançois Tigeot 
95800640ec9SFrançois Tigeot 		/*
95900640ec9SFrançois Tigeot 		 * It would make sense to re-init all the other hw state, at
96000640ec9SFrançois Tigeot 		 * least the rps/rc6/emon init done within modeset_init_hw. For
96100640ec9SFrançois Tigeot 		 * some unknown reason, this blows up my ilk, so don't.
96200640ec9SFrançois Tigeot 		 */
96300640ec9SFrançois Tigeot 
964a2fdbec6SFrançois Tigeot 		mutex_unlock(&dev->struct_mutex);
965e3adcf8fSFrançois Tigeot 
96600640ec9SFrançois Tigeot 		drm_irq_uninstall(dev);
96700640ec9SFrançois Tigeot 		drm_irq_install(dev);
968a2fdbec6SFrançois Tigeot 		intel_hpd_init(dev);
96900640ec9SFrançois Tigeot 	} else {
970a2fdbec6SFrançois Tigeot 		mutex_unlock(&dev->struct_mutex);
971e3adcf8fSFrançois Tigeot 	}
972e3adcf8fSFrançois Tigeot 
973e9243325SFrançois Tigeot 	return 0;
974e9243325SFrançois Tigeot }
975e9243325SFrançois Tigeot 
976a2fdbec6SFrançois Tigeot static int
977a2fdbec6SFrançois Tigeot i915_pci_probe(device_t kdev)
978a2fdbec6SFrançois Tigeot {
979a2fdbec6SFrançois Tigeot 	int device, i = 0;
980a2fdbec6SFrançois Tigeot 
981a2fdbec6SFrançois Tigeot 	if (pci_get_class(kdev) != PCIC_DISPLAY)
982a2fdbec6SFrançois Tigeot 		return ENXIO;
983a2fdbec6SFrançois Tigeot 
984a2fdbec6SFrançois Tigeot 	if (pci_get_vendor(kdev) != PCI_VENDOR_INTEL)
985a2fdbec6SFrançois Tigeot 		return ENXIO;
986a2fdbec6SFrançois Tigeot 
987a2fdbec6SFrançois Tigeot 	device = pci_get_device(kdev);
988a2fdbec6SFrançois Tigeot 
989a2fdbec6SFrançois Tigeot 	for (i = 0; pciidlist[i].device != 0; i++) {
990a2fdbec6SFrançois Tigeot 		if (pciidlist[i].device == device) {
991a2fdbec6SFrançois Tigeot 			i915_attach_list[0].device = device;
992a2fdbec6SFrançois Tigeot 			return 0;
993a2fdbec6SFrançois Tigeot 		}
994a2fdbec6SFrançois Tigeot 	}
995a2fdbec6SFrançois Tigeot 
996a2fdbec6SFrançois Tigeot 	return ENXIO;
997a2fdbec6SFrançois Tigeot }
998a2fdbec6SFrançois Tigeot 
999f0b54121SFrançois Tigeot static struct drm_driver driver = {
100079f713b0SFrançois Tigeot 	.driver_features =   DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
100179f713b0SFrançois Tigeot 	    DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | DRIVER_LOCKLESS_IRQ |
100279f713b0SFrançois Tigeot 	    DRIVER_GEM /*| DRIVER_MODESET*/,
100379f713b0SFrançois Tigeot 
100479f713b0SFrançois Tigeot 	.buf_priv_size	= sizeof(drm_i915_private_t),
1005f0b54121SFrançois Tigeot 	.load		= i915_driver_load,
10062aa08105SFrançois Tigeot 	.open		= i915_driver_open,
100779f713b0SFrançois Tigeot 	.unload		= i915_driver_unload,
10082aa08105SFrançois Tigeot 	.preclose	= i915_driver_preclose,
100979f713b0SFrançois Tigeot 	.lastclose	= i915_driver_lastclose,
1010f0b54121SFrançois Tigeot 	.postclose	= i915_driver_postclose,
1011f0b54121SFrançois Tigeot 	.device_is_agp	= i915_driver_device_is_agp,
1012f0b54121SFrançois Tigeot 	.gem_init_object = i915_gem_init_object,
1013f0b54121SFrançois Tigeot 	.gem_free_object = i915_gem_free_object,
1014f0b54121SFrançois Tigeot 	.gem_pager_ops	= &i915_gem_pager_ops,
1015f0b54121SFrançois Tigeot 	.dumb_create	= i915_gem_dumb_create,
1016f0b54121SFrançois Tigeot 	.dumb_map_offset = i915_gem_mmap_gtt,
1017f0b54121SFrançois Tigeot 	.dumb_destroy	= i915_gem_dumb_destroy,
101879f713b0SFrançois Tigeot 
1019f0b54121SFrançois Tigeot 	.ioctls		= i915_ioctls,
1020f0b54121SFrançois Tigeot 
1021f0b54121SFrançois Tigeot 	.name		= DRIVER_NAME,
1022f0b54121SFrançois Tigeot 	.desc		= DRIVER_DESC,
1023f0b54121SFrançois Tigeot 	.date		= DRIVER_DATE,
1024f0b54121SFrançois Tigeot 	.major		= DRIVER_MAJOR,
1025f0b54121SFrançois Tigeot 	.minor		= DRIVER_MINOR,
1026f0b54121SFrançois Tigeot 	.patchlevel	= DRIVER_PATCHLEVEL,
1027f0b54121SFrançois Tigeot };
1028f0b54121SFrançois Tigeot 
1029a2fdbec6SFrançois Tigeot static device_method_t i915_methods[] = {
1030a2fdbec6SFrançois Tigeot 	/* Device interface */
1031a2fdbec6SFrançois Tigeot 	DEVMETHOD(device_probe,		i915_pci_probe),
1032a2fdbec6SFrançois Tigeot 	DEVMETHOD(device_attach,	i915_attach),
1033a2fdbec6SFrançois Tigeot 	DEVMETHOD(device_suspend,	i915_suspend),
1034a2fdbec6SFrançois Tigeot 	DEVMETHOD(device_resume,	i915_resume),
1035d0cc45b6SFrançois Tigeot 	DEVMETHOD(device_detach,	drm_release),
1036a2fdbec6SFrançois Tigeot 	DEVMETHOD_END
1037a2fdbec6SFrançois Tigeot };
1038a2fdbec6SFrançois Tigeot 
1039a2fdbec6SFrançois Tigeot static driver_t i915_driver = {
1040a2fdbec6SFrançois Tigeot 	"drm",
1041a2fdbec6SFrançois Tigeot 	i915_methods,
1042a2fdbec6SFrançois Tigeot 	sizeof(struct drm_device)
1043a2fdbec6SFrançois Tigeot };
1044a2fdbec6SFrançois Tigeot 
1045a2fdbec6SFrançois Tigeot DRIVER_MODULE_ORDERED(i915kms, vgapci, i915_driver, drm_devclass, 0, 0,
1046a2fdbec6SFrançois Tigeot     SI_ORDER_ANY);
1047a2fdbec6SFrançois Tigeot MODULE_DEPEND(i915kms, drm, 1, 1, 1);
1048a2fdbec6SFrançois Tigeot MODULE_DEPEND(i915kms, agp, 1, 1, 1);
1049a2fdbec6SFrançois Tigeot MODULE_DEPEND(i915kms, iicbus, 1, 1, 1);
1050a2fdbec6SFrançois Tigeot MODULE_DEPEND(i915kms, iic, 1, 1, 1);
1051a2fdbec6SFrançois Tigeot MODULE_DEPEND(i915kms, iicbb, 1, 1, 1);
1052a2fdbec6SFrançois Tigeot 
1053c0bdd5d9SFrançois Tigeot /* We give fast paths for the really cool registers */
1054c0bdd5d9SFrançois Tigeot #define NEEDS_FORCE_WAKE(dev_priv, reg) \
1055c0bdd5d9SFrançois Tigeot 	((HAS_FORCE_WAKE((dev_priv)->dev)) && \
1056c0bdd5d9SFrançois Tigeot 	 ((reg) < 0x40000) &&            \
1057c0bdd5d9SFrançois Tigeot 	 ((reg) != FORCEWAKE))
1058e9243325SFrançois Tigeot static void
1059e9243325SFrançois Tigeot ilk_dummy_write(struct drm_i915_private *dev_priv)
1060e9243325SFrançois Tigeot {
1061*5d0b1887SFrançois Tigeot 	/* WaIssueDummyWriteToWakeupFromRC6:ilk Issue a dummy write to wake up
1062*5d0b1887SFrançois Tigeot 	 * the chip from rc6 before touching it for real. MI_MODE is masked,
1063*5d0b1887SFrançois Tigeot 	 * hence harmless to write 0 into. */
1064e9243325SFrançois Tigeot 	I915_WRITE_NOTRACE(MI_MODE, 0);
1065e3adcf8fSFrançois Tigeot }
1066e3adcf8fSFrançois Tigeot 
10678e26cdf6SFrançois Tigeot static void
10688e26cdf6SFrançois Tigeot hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
10698e26cdf6SFrançois Tigeot {
1070*5d0b1887SFrançois Tigeot 	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
10718e26cdf6SFrançois Tigeot 	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
10728e26cdf6SFrançois Tigeot 		DRM_ERROR("Unknown unclaimed register before writing to %x\n",
10738e26cdf6SFrançois Tigeot 			  reg);
10748e26cdf6SFrançois Tigeot 		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
10758e26cdf6SFrançois Tigeot 	}
10768e26cdf6SFrançois Tigeot }
10778e26cdf6SFrançois Tigeot 
10788e26cdf6SFrançois Tigeot static void
10798e26cdf6SFrançois Tigeot hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
10808e26cdf6SFrançois Tigeot {
1081*5d0b1887SFrançois Tigeot 	if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
10828e26cdf6SFrançois Tigeot 	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
10838e26cdf6SFrançois Tigeot 		DRM_ERROR("Unclaimed write to %x\n", reg);
10848e26cdf6SFrançois Tigeot 		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
10858e26cdf6SFrançois Tigeot 	}
10868e26cdf6SFrançois Tigeot }
10878e26cdf6SFrançois Tigeot 
1088e3adcf8fSFrançois Tigeot #define __i915_read(x, y) \
1089e3adcf8fSFrançois Tigeot u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
1090e3adcf8fSFrançois Tigeot 	u##x val = 0; \
1091*5d0b1887SFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_EXCLUSIVE); \
1092e9243325SFrançois Tigeot 	if (IS_GEN5(dev_priv->dev)) \
1093e9243325SFrançois Tigeot 		ilk_dummy_write(dev_priv); \
1094e3adcf8fSFrançois Tigeot 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
1095e3adcf8fSFrançois Tigeot 		if (dev_priv->forcewake_count == 0) \
1096e9243325SFrançois Tigeot 			dev_priv->gt.force_wake_get(dev_priv); \
1097e3adcf8fSFrançois Tigeot 		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
1098e3adcf8fSFrançois Tigeot 		if (dev_priv->forcewake_count == 0) \
1099e9243325SFrançois Tigeot 			dev_priv->gt.force_wake_put(dev_priv); \
1100e3adcf8fSFrançois Tigeot 	} else { \
1101e3adcf8fSFrançois Tigeot 		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
1102e3adcf8fSFrançois Tigeot 	} \
1103*5d0b1887SFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_RELEASE); \
1104e3adcf8fSFrançois Tigeot 	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
1105e3adcf8fSFrançois Tigeot 	return val; \
1106e3adcf8fSFrançois Tigeot }
1107e3adcf8fSFrançois Tigeot 
1108e3adcf8fSFrançois Tigeot __i915_read(8, 8)
1109e3adcf8fSFrançois Tigeot __i915_read(16, 16)
1110e3adcf8fSFrançois Tigeot __i915_read(32, 32)
1111e3adcf8fSFrançois Tigeot __i915_read(64, 64)
1112e3adcf8fSFrançois Tigeot #undef __i915_read
1113e3adcf8fSFrançois Tigeot 
1114e3adcf8fSFrançois Tigeot #define __i915_write(x, y) \
1115e3adcf8fSFrançois Tigeot void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
1116e3adcf8fSFrançois Tigeot 	u32 __fifo_ret = 0; \
1117e3adcf8fSFrançois Tigeot 	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
1118*5d0b1887SFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_EXCLUSIVE); \
1119e3adcf8fSFrançois Tigeot 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
1120e3adcf8fSFrançois Tigeot 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
1121e3adcf8fSFrançois Tigeot 	} \
1122e9243325SFrançois Tigeot 	if (IS_GEN5(dev_priv->dev)) \
1123e9243325SFrançois Tigeot 		ilk_dummy_write(dev_priv); \
11248e26cdf6SFrançois Tigeot 	hsw_unclaimed_reg_clear(dev_priv, reg); \
1125e3adcf8fSFrançois Tigeot 	DRM_WRITE##y(dev_priv->mmio_map, reg, val); \
1126e9243325SFrançois Tigeot 	if (unlikely(__fifo_ret)) { \
1127e3adcf8fSFrançois Tigeot 		gen6_gt_check_fifodbg(dev_priv); \
1128e3adcf8fSFrançois Tigeot 	} \
11298e26cdf6SFrançois Tigeot 	hsw_unclaimed_reg_check(dev_priv, reg); \
1130*5d0b1887SFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_RELEASE); \
1131e3adcf8fSFrançois Tigeot }
1132e9243325SFrançois Tigeot 
1133e3adcf8fSFrançois Tigeot __i915_write(8, 8)
1134e3adcf8fSFrançois Tigeot __i915_write(16, 16)
1135e3adcf8fSFrançois Tigeot __i915_write(32, 32)
1136e3adcf8fSFrançois Tigeot __i915_write(64, 64)
1137e3adcf8fSFrançois Tigeot #undef __i915_write
113817878c63SFrançois Tigeot 
113917878c63SFrançois Tigeot static const struct register_whitelist {
114017878c63SFrançois Tigeot 	uint64_t offset;
114117878c63SFrançois Tigeot 	uint32_t size;
114217878c63SFrançois Tigeot 	uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
114317878c63SFrançois Tigeot } whitelist[] = {
114417878c63SFrançois Tigeot 	{ RING_TIMESTAMP(RENDER_RING_BASE), 8, 0xF0 },
114517878c63SFrançois Tigeot };
114617878c63SFrançois Tigeot 
114717878c63SFrançois Tigeot int i915_reg_read_ioctl(struct drm_device *dev,
114817878c63SFrançois Tigeot 			void *data, struct drm_file *file)
114917878c63SFrançois Tigeot {
115017878c63SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
115117878c63SFrançois Tigeot 	struct drm_i915_reg_read *reg = data;
115217878c63SFrançois Tigeot 	struct register_whitelist const *entry = whitelist;
115317878c63SFrançois Tigeot 	int i;
115417878c63SFrançois Tigeot 
115517878c63SFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
115617878c63SFrançois Tigeot 		if (entry->offset == reg->offset &&
115717878c63SFrançois Tigeot 		    (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
115817878c63SFrançois Tigeot 			break;
115917878c63SFrançois Tigeot 	}
116017878c63SFrançois Tigeot 
116117878c63SFrançois Tigeot 	if (i == ARRAY_SIZE(whitelist))
116217878c63SFrançois Tigeot 		return -EINVAL;
116317878c63SFrançois Tigeot 
116417878c63SFrançois Tigeot 	switch (entry->size) {
116517878c63SFrançois Tigeot 	case 8:
116617878c63SFrançois Tigeot 		reg->val = I915_READ64(reg->offset);
116717878c63SFrançois Tigeot 		break;
116817878c63SFrançois Tigeot 	case 4:
116917878c63SFrançois Tigeot 		reg->val = I915_READ(reg->offset);
117017878c63SFrançois Tigeot 		break;
117117878c63SFrançois Tigeot 	case 2:
117217878c63SFrançois Tigeot 		reg->val = I915_READ16(reg->offset);
117317878c63SFrançois Tigeot 		break;
117417878c63SFrançois Tigeot 	case 1:
117517878c63SFrançois Tigeot 		reg->val = I915_READ8(reg->offset);
117617878c63SFrançois Tigeot 		break;
117717878c63SFrançois Tigeot 	default:
117817878c63SFrançois Tigeot 		WARN_ON(1);
117917878c63SFrançois Tigeot 		return -EINVAL;
118017878c63SFrançois Tigeot 	}
118117878c63SFrançois Tigeot 
118217878c63SFrançois Tigeot 	return 0;
118317878c63SFrançois Tigeot }
1184