xref: /dflybsd-src/sys/dev/drm/i915/i915_drv.c (revision 922e7c40d9037aa9c055588b57cd81c66edc5ffe)
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 
308621f407SFrançois Tigeot #include <linux/device.h>
31*922e7c40SFrançois Tigeot #include <linux/acpi.h>
3218e26a6dSFrançois Tigeot #include <drm/drmP.h>
335c6c6f23SFrançois Tigeot #include <drm/i915_drm.h>
34c4a9e910SFrançois Tigeot #include "i915_drv.h"
358621f407SFrançois Tigeot #include "i915_trace.h"
36e3adcf8fSFrançois Tigeot #include "intel_drv.h"
37c4a9e910SFrançois Tigeot 
38*922e7c40SFrançois Tigeot #include <linux/apple-gmux.h>
398621f407SFrançois Tigeot #include <linux/console.h>
409edbd4a0SFrançois Tigeot #include <linux/module.h>
41*922e7c40SFrançois Tigeot #include <linux/pm_runtime.h>
42*922e7c40SFrançois Tigeot #include <linux/vgaarb.h>
438621f407SFrançois Tigeot #include <linux/vga_switcheroo.h>
449edbd4a0SFrançois Tigeot #include <drm/drm_crtc_helper.h>
459edbd4a0SFrançois Tigeot 
46f0b54121SFrançois Tigeot static struct drm_driver driver;
47f0b54121SFrançois Tigeot 
48ba55f2f5SFrançois Tigeot #define GEN_DEFAULT_PIPEOFFSETS \
49ba55f2f5SFrançois Tigeot 	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
50ba55f2f5SFrançois Tigeot 			  PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
51ba55f2f5SFrançois Tigeot 	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
52ba55f2f5SFrançois Tigeot 			   TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
53ba55f2f5SFrançois Tigeot 	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
54ba55f2f5SFrançois Tigeot 
55ba55f2f5SFrançois Tigeot #define GEN_CHV_PIPEOFFSETS \
56ba55f2f5SFrançois Tigeot 	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
57ba55f2f5SFrançois Tigeot 			  CHV_PIPE_C_OFFSET }, \
58ba55f2f5SFrançois Tigeot 	.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
59ba55f2f5SFrançois Tigeot 			   CHV_TRANSCODER_C_OFFSET, }, \
60ba55f2f5SFrançois Tigeot 	.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
61ba55f2f5SFrançois Tigeot 			     CHV_PALETTE_C_OFFSET }
62ba55f2f5SFrançois Tigeot 
63ba55f2f5SFrançois Tigeot #define CURSOR_OFFSETS \
64ba55f2f5SFrançois Tigeot 	.cursor_offsets = { CURSOR_A_OFFSET, CURSOR_B_OFFSET, CHV_CURSOR_C_OFFSET }
65ba55f2f5SFrançois Tigeot 
66ba55f2f5SFrançois Tigeot #define IVB_CURSOR_OFFSETS \
67ba55f2f5SFrançois Tigeot 	.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
68ba55f2f5SFrançois Tigeot 
698621f407SFrançois Tigeot #define BDW_COLORS \
708621f407SFrançois Tigeot 	.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
718621f407SFrançois Tigeot #define CHV_COLORS \
728621f407SFrançois Tigeot 	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
738621f407SFrançois Tigeot 
74e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i830_info = {
758e26cdf6SFrançois Tigeot 	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
76e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
779edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
78ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
79ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
80e3adcf8fSFrançois Tigeot };
81c4a9e910SFrançois Tigeot 
82e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_845g_info = {
838e26cdf6SFrançois Tigeot 	.gen = 2, .num_pipes = 1,
84e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
859edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
86ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
87ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
88e3adcf8fSFrançois Tigeot };
89e3adcf8fSFrançois Tigeot 
90e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i85x_info = {
918e26cdf6SFrançois Tigeot 	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
92e3adcf8fSFrançois Tigeot 	.cursor_needs_physical = 1,
93e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
949edbd4a0SFrançois Tigeot 	.has_fbc = 1,
959edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
96ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
97ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
98e3adcf8fSFrançois Tigeot };
99e3adcf8fSFrançois Tigeot 
100e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i865g_info = {
1018e26cdf6SFrançois Tigeot 	.gen = 2, .num_pipes = 1,
102e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
1039edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
104ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
105ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
106e3adcf8fSFrançois Tigeot };
107e3adcf8fSFrançois Tigeot 
108e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i915g_info = {
1098e26cdf6SFrançois Tigeot 	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,
110e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
1119edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
112ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
113ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
114e3adcf8fSFrançois Tigeot };
115e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i915gm_info = {
1168e26cdf6SFrançois Tigeot 	.gen = 3, .is_mobile = 1, .num_pipes = 2,
117e3adcf8fSFrançois Tigeot 	.cursor_needs_physical = 1,
118e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
119e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
1209edbd4a0SFrançois Tigeot 	.has_fbc = 1,
1219edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
122ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
123ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
124e3adcf8fSFrançois Tigeot };
125e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i945g_info = {
1268e26cdf6SFrançois Tigeot 	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,
127e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
1289edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
129ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
130ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
131e3adcf8fSFrançois Tigeot };
132e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i945gm_info = {
1338e26cdf6SFrançois Tigeot 	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,
134e3adcf8fSFrançois Tigeot 	.has_hotplug = 1, .cursor_needs_physical = 1,
135e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
136e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
1379edbd4a0SFrançois Tigeot 	.has_fbc = 1,
1389edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
139ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
140ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
141e3adcf8fSFrançois Tigeot };
142e3adcf8fSFrançois Tigeot 
143e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i965g_info = {
1448e26cdf6SFrançois Tigeot 	.gen = 4, .is_broadwater = 1, .num_pipes = 2,
145e3adcf8fSFrançois Tigeot 	.has_hotplug = 1,
146e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
1479edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
148ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
149ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
150e3adcf8fSFrançois Tigeot };
151e3adcf8fSFrançois Tigeot 
152e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i965gm_info = {
1538e26cdf6SFrançois Tigeot 	.gen = 4, .is_crestline = 1, .num_pipes = 2,
154e3adcf8fSFrançois Tigeot 	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
155e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
156e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
1579edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
158ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
159ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
160e3adcf8fSFrançois Tigeot };
161e3adcf8fSFrançois Tigeot 
162e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_g33_info = {
1638e26cdf6SFrançois Tigeot 	.gen = 3, .is_g33 = 1, .num_pipes = 2,
164e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
165e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
1669edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING,
167ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
168ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
169e3adcf8fSFrançois Tigeot };
170e3adcf8fSFrançois Tigeot 
171e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_g45_info = {
1728e26cdf6SFrançois Tigeot 	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,
173e3adcf8fSFrançois Tigeot 	.has_pipe_cxsr = 1, .has_hotplug = 1,
1749edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING,
175ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
176ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
177e3adcf8fSFrançois Tigeot };
178e3adcf8fSFrançois Tigeot 
179e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_gm45_info = {
1808e26cdf6SFrançois Tigeot 	.gen = 4, .is_g4x = 1, .num_pipes = 2,
181e3adcf8fSFrançois Tigeot 	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
182e3adcf8fSFrançois Tigeot 	.has_pipe_cxsr = 1, .has_hotplug = 1,
183e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
1849edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING,
185ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
186ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
187e3adcf8fSFrançois Tigeot };
188e3adcf8fSFrançois Tigeot 
189e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_pineview_info = {
1908e26cdf6SFrançois Tigeot 	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,
191e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
192e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
193ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
194ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
195e3adcf8fSFrançois Tigeot };
196e3adcf8fSFrançois Tigeot 
197e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ironlake_d_info = {
1988e26cdf6SFrançois Tigeot 	.gen = 5, .num_pipes = 2,
199e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
2009edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING,
201ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
202ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
203e3adcf8fSFrançois Tigeot };
204e3adcf8fSFrançois Tigeot 
205e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ironlake_m_info = {
2068e26cdf6SFrançois Tigeot 	.gen = 5, .is_mobile = 1, .num_pipes = 2,
207e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
20800dca1bbSFrançois Tigeot 	.has_fbc = 1,
2099edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING,
210ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
211ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
212e3adcf8fSFrançois Tigeot };
213e3adcf8fSFrançois Tigeot 
214e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_sandybridge_d_info = {
2158e26cdf6SFrançois Tigeot 	.gen = 6, .num_pipes = 2,
216e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
2179edbd4a0SFrançois Tigeot 	.has_fbc = 1,
2189edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
219e3adcf8fSFrançois Tigeot 	.has_llc = 1,
220ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
221ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
222e3adcf8fSFrançois Tigeot };
223e3adcf8fSFrançois Tigeot 
224e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_sandybridge_m_info = {
2258e26cdf6SFrançois Tigeot 	.gen = 6, .is_mobile = 1, .num_pipes = 2,
226e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
227e3adcf8fSFrançois Tigeot 	.has_fbc = 1,
2289edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
229e3adcf8fSFrançois Tigeot 	.has_llc = 1,
230ba55f2f5SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
231ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
232e3adcf8fSFrançois Tigeot };
233e3adcf8fSFrançois Tigeot 
2348e26cdf6SFrançois Tigeot #define GEN7_FEATURES  \
2358e26cdf6SFrançois Tigeot 	.gen = 7, .num_pipes = 3, \
2368e26cdf6SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1, \
2379edbd4a0SFrançois Tigeot 	.has_fbc = 1, \
2389edbd4a0SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
239aee94f86SFrançois Tigeot 	.has_llc = 1, \
240aee94f86SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS, \
241aee94f86SFrançois Tigeot 	IVB_CURSOR_OFFSETS
2428e26cdf6SFrançois Tigeot 
243e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ivybridge_d_info = {
2448e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2458e26cdf6SFrançois Tigeot 	.is_ivybridge = 1,
246e3adcf8fSFrançois Tigeot };
247e3adcf8fSFrançois Tigeot 
248e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ivybridge_m_info = {
2498e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2508e26cdf6SFrançois Tigeot 	.is_ivybridge = 1,
2518e26cdf6SFrançois Tigeot 	.is_mobile = 1,
2528e26cdf6SFrançois Tigeot };
2538e26cdf6SFrançois Tigeot 
2548e26cdf6SFrançois Tigeot static const struct intel_device_info intel_ivybridge_q_info = {
2558e26cdf6SFrançois Tigeot 	GEN7_FEATURES,
2568e26cdf6SFrançois Tigeot 	.is_ivybridge = 1,
2578e26cdf6SFrançois Tigeot 	.num_pipes = 0, /* legal, last one wins */
258e3adcf8fSFrançois Tigeot };
259e3adcf8fSFrançois Tigeot 
260aee94f86SFrançois Tigeot #define VLV_FEATURES  \
261aee94f86SFrançois Tigeot 	.gen = 7, .num_pipes = 2, \
262aee94f86SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1, \
263aee94f86SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
264aee94f86SFrançois Tigeot 	.display_mmio_offset = VLV_DISPLAY_BASE, \
265aee94f86SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS, \
266aee94f86SFrançois Tigeot 	CURSOR_OFFSETS
267aee94f86SFrançois Tigeot 
268e9243325SFrançois Tigeot static const struct intel_device_info intel_valleyview_m_info = {
269aee94f86SFrançois Tigeot 	VLV_FEATURES,
270e9243325SFrançois Tigeot 	.is_valleyview = 1,
271aee94f86SFrançois Tigeot 	.is_mobile = 1,
272e9243325SFrançois Tigeot };
273e9243325SFrançois Tigeot 
274e9243325SFrançois Tigeot static const struct intel_device_info intel_valleyview_d_info = {
275aee94f86SFrançois Tigeot 	VLV_FEATURES,
276e9243325SFrançois Tigeot 	.is_valleyview = 1,
277e9243325SFrançois Tigeot };
278e9243325SFrançois Tigeot 
279aee94f86SFrançois Tigeot #define HSW_FEATURES  \
280aee94f86SFrançois Tigeot 	GEN7_FEATURES, \
281aee94f86SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \
282aee94f86SFrançois Tigeot 	.has_ddi = 1, \
283aee94f86SFrançois Tigeot 	.has_fpga_dbg = 1
284aee94f86SFrançois Tigeot 
285e9243325SFrançois Tigeot static const struct intel_device_info intel_haswell_d_info = {
286aee94f86SFrançois Tigeot 	HSW_FEATURES,
2878e26cdf6SFrançois Tigeot 	.is_haswell = 1,
288e9243325SFrançois Tigeot };
289e9243325SFrançois Tigeot 
290e9243325SFrançois Tigeot static const struct intel_device_info intel_haswell_m_info = {
291aee94f86SFrançois Tigeot 	HSW_FEATURES,
2928e26cdf6SFrançois Tigeot 	.is_haswell = 1,
2938e26cdf6SFrançois Tigeot 	.is_mobile = 1,
294e9243325SFrançois Tigeot };
295e3adcf8fSFrançois Tigeot 
2968621f407SFrançois Tigeot #define BDW_FEATURES \
2978621f407SFrançois Tigeot 	HSW_FEATURES, \
2988621f407SFrançois Tigeot 	BDW_COLORS
2998621f407SFrançois Tigeot 
3009edbd4a0SFrançois Tigeot static const struct intel_device_info intel_broadwell_d_info = {
3018621f407SFrançois Tigeot 	BDW_FEATURES,
302aee94f86SFrançois Tigeot 	.gen = 8,
3039edbd4a0SFrançois Tigeot };
3049edbd4a0SFrançois Tigeot 
3059edbd4a0SFrançois Tigeot static const struct intel_device_info intel_broadwell_m_info = {
3068621f407SFrançois Tigeot 	BDW_FEATURES,
307aee94f86SFrançois Tigeot 	.gen = 8, .is_mobile = 1,
308ba55f2f5SFrançois Tigeot };
309ba55f2f5SFrançois Tigeot 
310ba55f2f5SFrançois Tigeot static const struct intel_device_info intel_broadwell_gt3d_info = {
3118621f407SFrançois Tigeot 	BDW_FEATURES,
312aee94f86SFrançois Tigeot 	.gen = 8,
313ba55f2f5SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
314ba55f2f5SFrançois Tigeot };
315ba55f2f5SFrançois Tigeot 
316ba55f2f5SFrançois Tigeot static const struct intel_device_info intel_broadwell_gt3m_info = {
3178621f407SFrançois Tigeot 	BDW_FEATURES,
318aee94f86SFrançois Tigeot 	.gen = 8, .is_mobile = 1,
319ba55f2f5SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
320ba55f2f5SFrançois Tigeot };
321ba55f2f5SFrançois Tigeot 
322ba55f2f5SFrançois Tigeot static const struct intel_device_info intel_cherryview_info = {
323ba55f2f5SFrançois Tigeot 	.gen = 8, .num_pipes = 3,
324ba55f2f5SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
325ba55f2f5SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
326aee94f86SFrançois Tigeot 	.is_cherryview = 1,
327ba55f2f5SFrançois Tigeot 	.display_mmio_offset = VLV_DISPLAY_BASE,
328ba55f2f5SFrançois Tigeot 	GEN_CHV_PIPEOFFSETS,
329ba55f2f5SFrançois Tigeot 	CURSOR_OFFSETS,
3308621f407SFrançois Tigeot 	CHV_COLORS,
3319edbd4a0SFrançois Tigeot };
3329edbd4a0SFrançois Tigeot 
3332c9916cdSFrançois Tigeot static const struct intel_device_info intel_skylake_info = {
3348621f407SFrançois Tigeot 	BDW_FEATURES,
3352c9916cdSFrançois Tigeot 	.is_skylake = 1,
336aee94f86SFrançois Tigeot 	.gen = 9,
3372c9916cdSFrançois Tigeot };
3382c9916cdSFrançois Tigeot 
339477eb7f9SFrançois Tigeot static const struct intel_device_info intel_skylake_gt3_info = {
3408621f407SFrançois Tigeot 	BDW_FEATURES,
341477eb7f9SFrançois Tigeot 	.is_skylake = 1,
342aee94f86SFrançois Tigeot 	.gen = 9,
343477eb7f9SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
344477eb7f9SFrançois Tigeot };
345477eb7f9SFrançois Tigeot 
34619c468b4SFrançois Tigeot static const struct intel_device_info intel_broxton_info = {
34719c468b4SFrançois Tigeot 	.is_preliminary = 1,
348aee94f86SFrançois Tigeot 	.is_broxton = 1,
34919c468b4SFrançois Tigeot 	.gen = 9,
35019c468b4SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
35119c468b4SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
35219c468b4SFrançois Tigeot 	.num_pipes = 3,
35319c468b4SFrançois Tigeot 	.has_ddi = 1,
354352ff8bdSFrançois Tigeot 	.has_fpga_dbg = 1,
35519c468b4SFrançois Tigeot 	.has_fbc = 1,
35619c468b4SFrançois Tigeot 	GEN_DEFAULT_PIPEOFFSETS,
35719c468b4SFrançois Tigeot 	IVB_CURSOR_OFFSETS,
3588621f407SFrançois Tigeot 	BDW_COLORS,
35919c468b4SFrançois Tigeot };
36019c468b4SFrançois Tigeot 
361aee94f86SFrançois Tigeot static const struct intel_device_info intel_kabylake_info = {
3628621f407SFrançois Tigeot 	BDW_FEATURES,
363aee94f86SFrançois Tigeot 	.is_kabylake = 1,
364aee94f86SFrançois Tigeot 	.gen = 9,
365aee94f86SFrançois Tigeot };
366aee94f86SFrançois Tigeot 
367198d2d2aSFrançois Tigeot static const struct intel_device_info intel_kabylake_gt2_info = {
368198d2d2aSFrançois Tigeot 	BDW_FEATURES,
369198d2d2aSFrançois Tigeot 	.is_kabylake = 1,
370198d2d2aSFrançois Tigeot 	.gen = 9,
371198d2d2aSFrançois Tigeot };
372198d2d2aSFrançois Tigeot 
373aee94f86SFrançois Tigeot static const struct intel_device_info intel_kabylake_gt3_info = {
3748621f407SFrançois Tigeot 	BDW_FEATURES,
375aee94f86SFrançois Tigeot 	.is_kabylake = 1,
376aee94f86SFrançois Tigeot 	.gen = 9,
377aee94f86SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
378aee94f86SFrançois Tigeot };
379aee94f86SFrançois Tigeot 
38018a1af58SFrançois Tigeot static const struct intel_device_info intel_coffeelake_gt1_info = {
38118a1af58SFrançois Tigeot 	BDW_FEATURES, \
38218a1af58SFrançois Tigeot 	.is_kabylake = 1,
38318a1af58SFrançois Tigeot 	.gen = 9,
38418a1af58SFrançois Tigeot };
38518a1af58SFrançois Tigeot 
38618a1af58SFrançois Tigeot static const struct intel_device_info intel_coffeelake_gt2_info = {
3878bbe1960SFrançois Tigeot 	BDW_FEATURES, \
3888bbe1960SFrançois Tigeot 	.is_kabylake = 1,
3898bbe1960SFrançois Tigeot 	.gen = 9,
3908bbe1960SFrançois Tigeot };
3918bbe1960SFrançois Tigeot 
3928bbe1960SFrançois Tigeot static const struct intel_device_info intel_coffeelake_gt3_info = {
3938bbe1960SFrançois Tigeot 	BDW_FEATURES, \
3948bbe1960SFrançois Tigeot 	.is_kabylake = 1,
3958bbe1960SFrançois Tigeot 	.gen = 9,
3968bbe1960SFrançois Tigeot 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
3978bbe1960SFrançois Tigeot };
3988bbe1960SFrançois Tigeot 
3999edbd4a0SFrançois Tigeot /*
4009edbd4a0SFrançois Tigeot  * Make sure any device matches here are from most specific to most
4019edbd4a0SFrançois Tigeot  * general.  For example, since the Quanta match is based on the subsystem
4029edbd4a0SFrançois Tigeot  * and subvendor IDs, we need it to come before the more general IVB
4039edbd4a0SFrançois Tigeot  * PCI ID matches, otherwise we'll use the wrong info struct above.
4049edbd4a0SFrançois Tigeot  */
4059edbd4a0SFrançois Tigeot 
406aee94f86SFrançois Tigeot static const struct pci_device_id pciidlist[] = {
407aee94f86SFrançois Tigeot 	INTEL_I830_IDS(&intel_i830_info),
408aee94f86SFrançois Tigeot 	INTEL_I845G_IDS(&intel_845g_info),
409aee94f86SFrançois Tigeot 	INTEL_I85X_IDS(&intel_i85x_info),
410aee94f86SFrançois Tigeot 	INTEL_I865G_IDS(&intel_i865g_info),
411aee94f86SFrançois Tigeot 	INTEL_I915G_IDS(&intel_i915g_info),
412aee94f86SFrançois Tigeot 	INTEL_I915GM_IDS(&intel_i915gm_info),
413aee94f86SFrançois Tigeot 	INTEL_I945G_IDS(&intel_i945g_info),
414aee94f86SFrançois Tigeot 	INTEL_I945GM_IDS(&intel_i945gm_info),
415aee94f86SFrançois Tigeot 	INTEL_I965G_IDS(&intel_i965g_info),
416aee94f86SFrançois Tigeot 	INTEL_G33_IDS(&intel_g33_info),
417aee94f86SFrançois Tigeot 	INTEL_I965GM_IDS(&intel_i965gm_info),
418aee94f86SFrançois Tigeot 	INTEL_GM45_IDS(&intel_gm45_info),
419aee94f86SFrançois Tigeot 	INTEL_G45_IDS(&intel_g45_info),
420aee94f86SFrançois Tigeot 	INTEL_PINEVIEW_IDS(&intel_pineview_info),
421aee94f86SFrançois Tigeot 	INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
422aee94f86SFrançois Tigeot 	INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
423aee94f86SFrançois Tigeot 	INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
424aee94f86SFrançois Tigeot 	INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
425aee94f86SFrançois Tigeot 	INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
426aee94f86SFrançois Tigeot 	INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
427aee94f86SFrançois Tigeot 	INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
428aee94f86SFrançois Tigeot 	INTEL_HSW_D_IDS(&intel_haswell_d_info),
429aee94f86SFrançois Tigeot 	INTEL_HSW_M_IDS(&intel_haswell_m_info),
430aee94f86SFrançois Tigeot 	INTEL_VLV_M_IDS(&intel_valleyview_m_info),
431aee94f86SFrançois Tigeot 	INTEL_VLV_D_IDS(&intel_valleyview_d_info),
432aee94f86SFrançois Tigeot 	INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
433aee94f86SFrançois Tigeot 	INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
434aee94f86SFrançois Tigeot 	INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
435aee94f86SFrançois Tigeot 	INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
436aee94f86SFrançois Tigeot 	INTEL_CHV_IDS(&intel_cherryview_info),
437aee94f86SFrançois Tigeot 	INTEL_SKL_GT1_IDS(&intel_skylake_info),
438aee94f86SFrançois Tigeot 	INTEL_SKL_GT2_IDS(&intel_skylake_info),
439aee94f86SFrançois Tigeot 	INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
440aee94f86SFrançois Tigeot 	INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info),
441aee94f86SFrançois Tigeot 	INTEL_BXT_IDS(&intel_broxton_info),
442aee94f86SFrançois Tigeot 	INTEL_KBL_GT1_IDS(&intel_kabylake_info),
443aee94f86SFrançois Tigeot 	INTEL_KBL_GT2_IDS(&intel_kabylake_info),
444aee94f86SFrançois Tigeot 	INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
445aee94f86SFrançois Tigeot 	INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
446198d2d2aSFrançois Tigeot 	INTEL_AML_GT2_IDS(&intel_kabylake_gt2_info),
44718a1af58SFrançois Tigeot 	INTEL_CFL_S_GT1_IDS(&intel_coffeelake_gt1_info),
44818a1af58SFrançois Tigeot 	INTEL_CFL_S_GT2_IDS(&intel_coffeelake_gt2_info),
44918a1af58SFrançois Tigeot 	INTEL_CFL_H_GT2_IDS(&intel_coffeelake_gt2_info),
45018a1af58SFrançois Tigeot 	INTEL_CFL_U_GT2_IDS(&intel_coffeelake_gt2_info),
45118a1af58SFrançois Tigeot 	INTEL_CFL_U_GT3_IDS(&intel_coffeelake_gt3_info),
452e755878bSFrançois Tigeot 	INTEL_WHL_U_GT1_IDS(&intel_coffeelake_gt1_info),
453e755878bSFrançois Tigeot 	INTEL_WHL_U_GT2_IDS(&intel_coffeelake_gt2_info),
454e755878bSFrançois Tigeot 	INTEL_WHL_U_GT3_IDS(&intel_coffeelake_gt3_info),
455aee94f86SFrançois Tigeot 	{0, 0, 0}
456e3adcf8fSFrançois Tigeot };
457e3adcf8fSFrançois Tigeot 
458e9243325SFrançois Tigeot #define	PCI_VENDOR_INTEL	0x8086
459e9243325SFrançois Tigeot 
460352ff8bdSFrançois Tigeot static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
461352ff8bdSFrançois Tigeot {
462352ff8bdSFrançois Tigeot 	enum intel_pch ret = PCH_NOP;
463352ff8bdSFrançois Tigeot 
464352ff8bdSFrançois Tigeot 	/*
465352ff8bdSFrançois Tigeot 	 * In a virtualized passthrough environment we can be in a
466352ff8bdSFrançois Tigeot 	 * setup where the ISA bridge is not able to be passed through.
467352ff8bdSFrançois Tigeot 	 * In this case, a south bridge can be emulated and we have to
468352ff8bdSFrançois Tigeot 	 * make an educated guess as to which PCH is really there.
469352ff8bdSFrançois Tigeot 	 */
470352ff8bdSFrançois Tigeot 
471352ff8bdSFrançois Tigeot 	if (IS_GEN5(dev)) {
472352ff8bdSFrançois Tigeot 		ret = PCH_IBX;
473352ff8bdSFrançois Tigeot 		DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n");
474352ff8bdSFrançois Tigeot 	} else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
475352ff8bdSFrançois Tigeot 		ret = PCH_CPT;
476352ff8bdSFrançois Tigeot 		DRM_DEBUG_KMS("Assuming CouarPoint PCH\n");
477352ff8bdSFrançois Tigeot 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
478352ff8bdSFrançois Tigeot 		ret = PCH_LPT;
479352ff8bdSFrançois Tigeot 		DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
480aee94f86SFrançois Tigeot 	} else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
481352ff8bdSFrançois Tigeot 		ret = PCH_SPT;
482352ff8bdSFrançois Tigeot 		DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
483352ff8bdSFrançois Tigeot 	}
484352ff8bdSFrançois Tigeot 
485352ff8bdSFrançois Tigeot 	return ret;
486352ff8bdSFrançois Tigeot }
487352ff8bdSFrançois Tigeot 
488e9243325SFrançois Tigeot void intel_detect_pch(struct drm_device *dev)
489e9243325SFrançois Tigeot {
490e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
4915d302545SFrançois Tigeot 	device_t pch = NULL;
49227a0f882SMatthew Dillon 	struct pci_devinfo *di;
493e9243325SFrançois Tigeot 
4948e26cdf6SFrançois Tigeot 	/* In all current cases, num_pipes is equivalent to the PCH_NOP setting
4958e26cdf6SFrançois Tigeot 	 * (which really amounts to a PCH but no South Display).
4968e26cdf6SFrançois Tigeot 	 */
4978e26cdf6SFrançois Tigeot 	if (INTEL_INFO(dev)->num_pipes == 0) {
4988e26cdf6SFrançois Tigeot 		dev_priv->pch_type = PCH_NOP;
4998e26cdf6SFrançois Tigeot 		return;
5008e26cdf6SFrançois Tigeot 	}
5018e26cdf6SFrançois Tigeot 
5029edbd4a0SFrançois Tigeot 	/* XXX The ISA bridge probe causes some old Core2 machines to hang */
5039edbd4a0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen < 5)
5049edbd4a0SFrançois Tigeot 		return;
5059edbd4a0SFrançois Tigeot 
506e9243325SFrançois Tigeot 	/*
507e9243325SFrançois Tigeot 	 * The reason to probe ISA bridge instead of Dev31:Fun0 is to
508e9243325SFrançois Tigeot 	 * make graphics device passthrough work easy for VMM, that only
509e9243325SFrançois Tigeot 	 * need to expose ISA bridge to let driver know the real hardware
510e9243325SFrançois Tigeot 	 * underneath. This is a requirement from virtualization team.
5119edbd4a0SFrançois Tigeot 	 *
5129edbd4a0SFrançois Tigeot 	 * In some virtualized environments (e.g. XEN), there is irrelevant
5139edbd4a0SFrançois Tigeot 	 * ISA bridge in the system. To work reliably, we should scan trhough
5149edbd4a0SFrançois Tigeot 	 * all the ISA bridge devices and check for the first match, instead
5159edbd4a0SFrançois Tigeot 	 * of only checking the first one.
516e9243325SFrançois Tigeot 	 */
51727a0f882SMatthew Dillon 	di = NULL;
51827a0f882SMatthew Dillon 
51927a0f882SMatthew Dillon 	while ((pch = pci_iterate_class(&di, PCIC_BRIDGE, PCIS_BRIDGE_ISA))) {
520e9243325SFrançois Tigeot 		if (pci_get_vendor(pch) == PCI_VENDOR_INTEL) {
5219edbd4a0SFrançois Tigeot 			unsigned short id = pci_get_device(pch) & INTEL_PCH_DEVICE_ID_MASK;
522e9243325SFrançois Tigeot 			dev_priv->pch_id = id;
523e9243325SFrançois Tigeot 
524e9243325SFrançois Tigeot 			if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
525e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_IBX;
526e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
527e9243325SFrançois Tigeot 				WARN_ON(!IS_GEN5(dev));
528e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
529e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_CPT;
530e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found CougarPoint PCH\n");
531e9243325SFrançois Tigeot 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
532e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
533e9243325SFrançois Tigeot 				/* PantherPoint is CPT compatible */
534e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_CPT;
5359edbd4a0SFrançois Tigeot 				DRM_DEBUG_KMS("Found PantherPoint PCH\n");
536e9243325SFrançois Tigeot 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
537e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
538e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_LPT;
539e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
5402c9916cdSFrançois Tigeot 				WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
5412c9916cdSFrançois Tigeot 				WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev));
542e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
543e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_LPT;
544e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
5452c9916cdSFrançois Tigeot 				WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
5462c9916cdSFrançois Tigeot 				WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev));
5472c9916cdSFrançois Tigeot 			} else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
5482c9916cdSFrançois Tigeot 				dev_priv->pch_type = PCH_SPT;
5492c9916cdSFrançois Tigeot 				DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
550aee94f86SFrançois Tigeot 				WARN_ON(!IS_SKYLAKE(dev) &&
551aee94f86SFrançois Tigeot 					!IS_KABYLAKE(dev));
5522c9916cdSFrançois Tigeot 			} else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
5532c9916cdSFrançois Tigeot 				dev_priv->pch_type = PCH_SPT;
5542c9916cdSFrançois Tigeot 				DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
555aee94f86SFrançois Tigeot 				WARN_ON(!IS_SKYLAKE(dev) &&
556aee94f86SFrançois Tigeot 					!IS_KABYLAKE(dev));
5578621f407SFrançois Tigeot 			} else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) {
5588621f407SFrançois Tigeot 				dev_priv->pch_type = PCH_KBP;
5598621f407SFrançois Tigeot 				DRM_DEBUG_KMS("Found KabyPoint PCH\n");
5608621f407SFrançois Tigeot 				WARN_ON(!IS_KABYLAKE(dev));
561aee94f86SFrançois Tigeot 			} else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
5628621f407SFrançois Tigeot 				   (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
5638621f407SFrançois Tigeot 				   ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
5648621f407SFrançois Tigeot 				    1)) {
565352ff8bdSFrançois Tigeot 				dev_priv->pch_type = intel_virt_detect_pch(dev);
5669edbd4a0SFrançois Tigeot 			} else
5679edbd4a0SFrançois Tigeot 				continue;
5689edbd4a0SFrançois Tigeot 
5699edbd4a0SFrançois Tigeot 			break;
570e9243325SFrançois Tigeot 		}
571e9243325SFrançois Tigeot 	}
5729edbd4a0SFrançois Tigeot 	if (!pch)
5739edbd4a0SFrançois Tigeot 		DRM_DEBUG_KMS("No PCH found.\n");
5749edbd4a0SFrançois Tigeot 
575e9243325SFrançois Tigeot #if 0
576e9243325SFrançois Tigeot 	pci_dev_put(pch);
577e9243325SFrançois Tigeot #endif
578e9243325SFrançois Tigeot }
579e9243325SFrançois Tigeot 
5803d4007e0SFrançois Tigeot bool i915_semaphore_is_enabled(struct drm_device *dev)
5813d4007e0SFrançois Tigeot {
5823d4007e0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen < 6)
5839edbd4a0SFrançois Tigeot 		return false;
5849edbd4a0SFrançois Tigeot 
585ba55f2f5SFrançois Tigeot 	if (i915.semaphores >= 0)
586ba55f2f5SFrançois Tigeot 		return i915.semaphores;
5873d4007e0SFrançois Tigeot 
5881b13d190SFrançois Tigeot 	/* TODO: make semaphores and Execlists play nicely together */
5891b13d190SFrançois Tigeot 	if (i915.enable_execlists)
5901b13d190SFrançois Tigeot 		return false;
5911b13d190SFrançois Tigeot 
592ba55f2f5SFrançois Tigeot 	/* Until we get further testing... */
593ba55f2f5SFrançois Tigeot 	if (IS_GEN8(dev))
594ba55f2f5SFrançois Tigeot 		return false;
5953d4007e0SFrançois Tigeot 
5963d4007e0SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
5973d4007e0SFrançois Tigeot 	/* Enable semaphores on SNB when IO remapping is off */
5983d4007e0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
5993d4007e0SFrançois Tigeot 		return false;
6003d4007e0SFrançois Tigeot #endif
6013d4007e0SFrançois Tigeot 
6029edbd4a0SFrançois Tigeot 	return true;
6033d4007e0SFrançois Tigeot }
6043d4007e0SFrançois Tigeot 
60519c468b4SFrançois Tigeot #ifdef __DragonFly__
60619c468b4SFrançois Tigeot #define IS_BUILTIN(blah)	0
60719c468b4SFrançois Tigeot #endif
60819c468b4SFrançois Tigeot 
60924edb884SFrançois Tigeot static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
61024edb884SFrançois Tigeot {
61124edb884SFrançois Tigeot 	struct drm_device *dev = dev_priv->dev;
612aee94f86SFrançois Tigeot 	struct intel_encoder *encoder;
61324edb884SFrançois Tigeot 
61424edb884SFrançois Tigeot 	drm_modeset_lock_all(dev);
615aee94f86SFrançois Tigeot 	for_each_intel_encoder(dev, encoder)
616aee94f86SFrançois Tigeot 		if (encoder->suspend)
617aee94f86SFrançois Tigeot 			encoder->suspend(encoder);
61824edb884SFrançois Tigeot 	drm_modeset_unlock_all(dev);
61924edb884SFrançois Tigeot }
62024edb884SFrançois Tigeot 
6212c9916cdSFrançois Tigeot static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
6221b13d190SFrançois Tigeot 			      bool rpm_resume);
6238621f407SFrançois Tigeot static int vlv_suspend_complete(struct drm_i915_private *dev_priv);
62419c468b4SFrançois Tigeot 
625aee94f86SFrançois Tigeot static bool suspend_to_idle(struct drm_i915_private *dev_priv)
626aee94f86SFrançois Tigeot {
627aee94f86SFrançois Tigeot #if IS_ENABLED(CONFIG_ACPI_SLEEP)
628aee94f86SFrançois Tigeot 	if (acpi_target_system_state() < ACPI_STATE_S3)
629aee94f86SFrançois Tigeot 		return true;
630aee94f86SFrançois Tigeot #endif
631aee94f86SFrançois Tigeot 	return false;
632aee94f86SFrançois Tigeot }
6331b13d190SFrançois Tigeot 
6342c9916cdSFrançois Tigeot static int i915_drm_suspend(struct drm_device *dev)
635e3adcf8fSFrançois Tigeot {
636e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
63724edb884SFrançois Tigeot 	pci_power_t opregion_target_state;
638477eb7f9SFrançois Tigeot 	int error;
6399edbd4a0SFrançois Tigeot 
640a2fdbec6SFrançois Tigeot 	/* ignore lid events during suspend */
641a2fdbec6SFrançois Tigeot 	mutex_lock(&dev_priv->modeset_restore_lock);
642a2fdbec6SFrançois Tigeot 	dev_priv->modeset_restore = MODESET_SUSPENDED;
643a2fdbec6SFrançois Tigeot 	mutex_unlock(&dev_priv->modeset_restore_lock);
644a2fdbec6SFrançois Tigeot 
645aee94f86SFrançois Tigeot 	disable_rpm_wakeref_asserts(dev_priv);
646aee94f86SFrançois Tigeot 
6479edbd4a0SFrançois Tigeot 	/* We do a lot of poking in a lot of registers, make sure they work
6489edbd4a0SFrançois Tigeot 	 * properly. */
649ba55f2f5SFrançois Tigeot 	intel_display_set_init_power(dev_priv, true);
650a2fdbec6SFrançois Tigeot 
651e3adcf8fSFrançois Tigeot 	drm_kms_helper_poll_disable(dev);
652e3adcf8fSFrançois Tigeot 
653e3adcf8fSFrançois Tigeot #if 0
654e3adcf8fSFrançois Tigeot 	pci_save_state(dev->pdev);
655e3adcf8fSFrançois Tigeot #endif
656e3adcf8fSFrançois Tigeot 
6579edbd4a0SFrançois Tigeot 	error = i915_gem_suspend(dev);
658e3adcf8fSFrançois Tigeot 	if (error) {
659fb572d17SFrançois Tigeot 		dev_err(dev->dev,
660a2fdbec6SFrançois Tigeot 			"GEM idle failed, resume might fail\n");
661aee94f86SFrançois Tigeot 		goto out;
662e3adcf8fSFrançois Tigeot 	}
663a2fdbec6SFrançois Tigeot 
664352ff8bdSFrançois Tigeot 	intel_guc_suspend(dev);
665352ff8bdSFrançois Tigeot 
6662c9916cdSFrançois Tigeot 	intel_suspend_gt_powersave(dev);
6672c9916cdSFrançois Tigeot 
668a05eeebfSFrançois Tigeot 	intel_display_suspend(dev);
6695d0b1887SFrançois Tigeot 
67024edb884SFrançois Tigeot #if 0
67124edb884SFrançois Tigeot 	intel_dp_mst_suspend(dev);
67224edb884SFrançois Tigeot #endif
67324edb884SFrançois Tigeot 
6742c9916cdSFrançois Tigeot 	intel_runtime_pm_disable_interrupts(dev_priv);
67524edb884SFrançois Tigeot 	intel_hpd_cancel_work(dev_priv);
67624edb884SFrançois Tigeot 
67724edb884SFrançois Tigeot 	intel_suspend_encoders(dev_priv);
67824edb884SFrançois Tigeot 
6792c9916cdSFrançois Tigeot 	intel_suspend_hw(dev);
680e3adcf8fSFrançois Tigeot 
6819edbd4a0SFrançois Tigeot 	i915_gem_suspend_gtt_mappings(dev);
6829edbd4a0SFrançois Tigeot 
683e3adcf8fSFrançois Tigeot 	i915_save_state(dev);
684e3adcf8fSFrançois Tigeot 
685aee94f86SFrançois Tigeot 	opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
68624edb884SFrançois Tigeot 	intel_opregion_notify_adapter(dev, opregion_target_state);
68724edb884SFrançois Tigeot 
68824edb884SFrançois Tigeot 	intel_uncore_forcewake_reset(dev, false);
689e3adcf8fSFrançois Tigeot 	intel_opregion_fini(dev);
690e3adcf8fSFrançois Tigeot 
6915d0b1887SFrançois Tigeot #if 0
692477eb7f9SFrançois Tigeot 	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
6935d0b1887SFrançois Tigeot #endif
6945d0b1887SFrançois Tigeot 
695ba55f2f5SFrançois Tigeot 	dev_priv->suspend_count++;
696ba55f2f5SFrançois Tigeot 
69724edb884SFrançois Tigeot 	intel_display_set_init_power(dev_priv, false);
69824edb884SFrançois Tigeot 
6998621f407SFrançois Tigeot 	intel_csr_ucode_suspend(dev_priv);
700aee94f86SFrançois Tigeot 
701aee94f86SFrançois Tigeot out:
702aee94f86SFrançois Tigeot 	enable_rpm_wakeref_asserts(dev_priv);
703aee94f86SFrançois Tigeot 
704aee94f86SFrançois Tigeot 	return error;
705e3adcf8fSFrançois Tigeot }
706e3adcf8fSFrançois Tigeot 
7072c9916cdSFrançois Tigeot static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
7082c9916cdSFrançois Tigeot {
7092c9916cdSFrançois Tigeot 	struct drm_i915_private *dev_priv = drm_dev->dev_private;
710aee94f86SFrançois Tigeot 	bool fw_csr;
7112c9916cdSFrançois Tigeot 	int ret;
7122c9916cdSFrançois Tigeot 
713aee94f86SFrançois Tigeot 	disable_rpm_wakeref_asserts(dev_priv);
714aee94f86SFrançois Tigeot 
7158621f407SFrançois Tigeot 	fw_csr = !IS_BROXTON(dev_priv) &&
7168621f407SFrançois Tigeot 		suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
717aee94f86SFrançois Tigeot 	/*
718aee94f86SFrançois Tigeot 	 * In case of firmware assisted context save/restore don't manually
719aee94f86SFrançois Tigeot 	 * deinit the power domains. This also means the CSR/DMC firmware will
720aee94f86SFrançois Tigeot 	 * stay active, it will power down any HW resources as required and
721aee94f86SFrançois Tigeot 	 * also enable deeper system power states that would be blocked if the
722aee94f86SFrançois Tigeot 	 * firmware was inactive.
723aee94f86SFrançois Tigeot 	 */
724aee94f86SFrançois Tigeot 	if (!fw_csr)
725aee94f86SFrançois Tigeot 		intel_power_domains_suspend(dev_priv);
726aee94f86SFrançois Tigeot 
7278621f407SFrançois Tigeot 	ret = 0;
7288621f407SFrançois Tigeot 	if (IS_BROXTON(dev_priv))
7298621f407SFrançois Tigeot 		bxt_enable_dc9(dev_priv);
7308621f407SFrançois Tigeot 	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
7318621f407SFrançois Tigeot 		hsw_enable_pc8(dev_priv);
7328621f407SFrançois Tigeot 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
7338621f407SFrançois Tigeot 		ret = vlv_suspend_complete(dev_priv);
7342c9916cdSFrançois Tigeot 
7352c9916cdSFrançois Tigeot 	if (ret) {
7362c9916cdSFrançois Tigeot 		DRM_ERROR("Suspend complete failed: %d\n", ret);
737aee94f86SFrançois Tigeot 		if (!fw_csr)
738aee94f86SFrançois Tigeot 			intel_power_domains_init_hw(dev_priv, true);
7392c9916cdSFrançois Tigeot 
740aee94f86SFrançois Tigeot 		goto out;
7412c9916cdSFrançois Tigeot 	}
7422c9916cdSFrançois Tigeot 
7432c9916cdSFrançois Tigeot #if 0
7442c9916cdSFrançois Tigeot 	pci_disable_device(drm_dev->pdev);
7452c9916cdSFrançois Tigeot 	/*
746a05eeebfSFrançois Tigeot 	 * During hibernation on some platforms the BIOS may try to access
7472c9916cdSFrançois Tigeot 	 * the device even though it's already in D3 and hang the machine. So
7482c9916cdSFrançois Tigeot 	 * leave the device in D0 on those platforms and hope the BIOS will
749a05eeebfSFrançois Tigeot 	 * power down the device properly. The issue was seen on multiple old
750a05eeebfSFrançois Tigeot 	 * GENs with different BIOS vendors, so having an explicit blacklist
751a05eeebfSFrançois Tigeot 	 * is inpractical; apply the workaround on everything pre GEN6. The
752a05eeebfSFrançois Tigeot 	 * platforms where the issue was seen:
753a05eeebfSFrançois Tigeot 	 * Lenovo Thinkpad X301, X61s, X60, T60, X41
754a05eeebfSFrançois Tigeot 	 * Fujitsu FSC S7110
755a05eeebfSFrançois Tigeot 	 * Acer Aspire 1830T
7562c9916cdSFrançois Tigeot 	 */
757a05eeebfSFrançois Tigeot 	if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6))
7582c9916cdSFrançois Tigeot 		pci_set_power_state(drm_dev->pdev, PCI_D3hot);
7592c9916cdSFrançois Tigeot #endif
7602c9916cdSFrançois Tigeot 
761aee94f86SFrançois Tigeot 	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
762aee94f86SFrançois Tigeot 
763aee94f86SFrançois Tigeot out:
764aee94f86SFrançois Tigeot 	enable_rpm_wakeref_asserts(dev_priv);
765aee94f86SFrançois Tigeot 
766aee94f86SFrançois Tigeot 	return ret;
7672c9916cdSFrançois Tigeot }
7682c9916cdSFrançois Tigeot 
769352ff8bdSFrançois Tigeot int i915_suspend_switcheroo(device_t kdev)
770e3adcf8fSFrançois Tigeot {
7719edbd4a0SFrançois Tigeot 	struct drm_device *dev = device_get_softc(kdev);
772e3adcf8fSFrançois Tigeot 	int error;
773e3adcf8fSFrançois Tigeot 
7749edbd4a0SFrançois Tigeot 	if (!dev || !dev->dev_private) {
7759edbd4a0SFrançois Tigeot 		DRM_ERROR("dev: %p\n", dev);
776c4a9e910SFrançois Tigeot 		DRM_ERROR("DRM not initialized, aborting suspend.\n");
777c4a9e910SFrançois Tigeot 		return -ENODEV;
778c4a9e910SFrançois Tigeot 	}
779c4a9e910SFrançois Tigeot 
7802c9916cdSFrançois Tigeot #if 0
7812c9916cdSFrançois Tigeot 	if (WARN_ON_ONCE(state.event != PM_EVENT_SUSPEND &&
7822c9916cdSFrançois Tigeot 			 state.event != PM_EVENT_FREEZE))
7832c9916cdSFrançois Tigeot 		return -EINVAL;
7842c9916cdSFrançois Tigeot #endif
7852c9916cdSFrançois Tigeot 
7869edbd4a0SFrançois Tigeot 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
7879edbd4a0SFrançois Tigeot 		return 0;
7889edbd4a0SFrançois Tigeot 
7892c9916cdSFrançois Tigeot 	error = i915_drm_suspend(dev);
790e3adcf8fSFrançois Tigeot 	if (error)
7919edbd4a0SFrançois Tigeot 		return error;
7929edbd4a0SFrançois Tigeot 
7932c9916cdSFrançois Tigeot 	return i915_drm_suspend_late(dev, false);
794c4a9e910SFrançois Tigeot }
795c4a9e910SFrançois Tigeot 
7962c9916cdSFrançois Tigeot static int i915_drm_resume(struct drm_device *dev)
797c4a9e910SFrançois Tigeot {
798e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
7998621f407SFrançois Tigeot 	int ret;
8009edbd4a0SFrançois Tigeot 
801aee94f86SFrançois Tigeot 	disable_rpm_wakeref_asserts(dev_priv);
802aee94f86SFrançois Tigeot 
8038621f407SFrançois Tigeot 	ret = i915_ggtt_enable_hw(dev);
8048621f407SFrançois Tigeot 	if (ret)
8058621f407SFrançois Tigeot 		DRM_ERROR("failed to re-enable GGTT\n");
8068621f407SFrançois Tigeot 
8078621f407SFrançois Tigeot 	intel_csr_ucode_resume(dev_priv);
8088621f407SFrançois Tigeot 
8099edbd4a0SFrançois Tigeot 	mutex_lock(&dev->struct_mutex);
8109edbd4a0SFrançois Tigeot 	i915_gem_restore_gtt_mappings(dev);
8119edbd4a0SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
8129edbd4a0SFrançois Tigeot 
813c4a9e910SFrançois Tigeot 	i915_restore_state(dev);
814e3adcf8fSFrançois Tigeot 	intel_opregion_setup(dev);
815c4a9e910SFrançois Tigeot 
81619df918dSFrançois Tigeot 	intel_init_pch_refclk(dev);
817ba55f2f5SFrançois Tigeot 	drm_mode_config_reset(dev);
81819df918dSFrançois Tigeot 
819477eb7f9SFrançois Tigeot 	/*
820477eb7f9SFrançois Tigeot 	 * Interrupts have to be enabled before any batches are run. If not the
821477eb7f9SFrançois Tigeot 	 * GPU will hang. i915_gem_init_hw() will initiate batches to
822477eb7f9SFrançois Tigeot 	 * update/restore the context.
823477eb7f9SFrançois Tigeot 	 *
824477eb7f9SFrançois Tigeot 	 * Modeset enabling in intel_modeset_init_hw() also needs working
825477eb7f9SFrançois Tigeot 	 * interrupts.
826477eb7f9SFrançois Tigeot 	 */
827477eb7f9SFrançois Tigeot 	intel_runtime_pm_enable_interrupts(dev_priv);
828477eb7f9SFrançois Tigeot 
829a2fdbec6SFrançois Tigeot 	mutex_lock(&dev->struct_mutex);
830ba55f2f5SFrançois Tigeot 	if (i915_gem_init_hw(dev)) {
831ba55f2f5SFrançois Tigeot 		DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n");
832a05eeebfSFrançois Tigeot 			atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter);
833ba55f2f5SFrançois Tigeot 	}
834a2fdbec6SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
835a2fdbec6SFrançois Tigeot 
836352ff8bdSFrançois Tigeot 	intel_guc_resume(dev);
837352ff8bdSFrançois Tigeot 
83819df918dSFrançois Tigeot 	intel_modeset_init_hw(dev);
8398e26cdf6SFrançois Tigeot 
8405e269720SFrançois Tigeot 	spin_lock_irq(&dev_priv->irq_lock);
8412c9916cdSFrançois Tigeot 	if (dev_priv->display.hpd_irq_setup)
8422c9916cdSFrançois Tigeot 		dev_priv->display.hpd_irq_setup(dev);
8435e269720SFrançois Tigeot 	spin_unlock_irq(&dev_priv->irq_lock);
8442c9916cdSFrançois Tigeot 
8452c9916cdSFrançois Tigeot 	intel_dp_mst_resume(dev);
8462c9916cdSFrançois Tigeot 
847c0e85e96SFrançois Tigeot 	intel_display_resume(dev);
848c0e85e96SFrançois Tigeot 
849a2fdbec6SFrançois Tigeot 	/*
850a2fdbec6SFrançois Tigeot 	 * ... but also need to make sure that hotplug processing
851a2fdbec6SFrançois Tigeot 	 * doesn't cause havoc. Like in the driver load code we don't
852a2fdbec6SFrançois Tigeot 	 * bother with the tiny race here where we might loose hotplug
853a2fdbec6SFrançois Tigeot 	 * notifications.
854a2fdbec6SFrançois Tigeot 	 * */
8552c9916cdSFrançois Tigeot 	intel_hpd_init(dev_priv);
8568e26cdf6SFrançois Tigeot 	/* Config may have changed between suspend and resume */
857ba55f2f5SFrançois Tigeot 	drm_helper_hpd_irq_event(dev);
858c4a9e910SFrançois Tigeot 
859e3adcf8fSFrançois Tigeot 	intel_opregion_init(dev);
860e3adcf8fSFrançois Tigeot 
8611b13d190SFrançois Tigeot 	intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
862a2fdbec6SFrançois Tigeot 
863a2fdbec6SFrançois Tigeot 	mutex_lock(&dev_priv->modeset_restore_lock);
864a2fdbec6SFrançois Tigeot 	dev_priv->modeset_restore = MODESET_DONE;
865a2fdbec6SFrançois Tigeot 	mutex_unlock(&dev_priv->modeset_restore_lock);
8669edbd4a0SFrançois Tigeot 
86724edb884SFrançois Tigeot 	intel_opregion_notify_adapter(dev, PCI_D0);
86824edb884SFrançois Tigeot 
8692c9916cdSFrançois Tigeot 	drm_kms_helper_poll_enable(dev);
8702c9916cdSFrançois Tigeot 
871aee94f86SFrançois Tigeot 	enable_rpm_wakeref_asserts(dev_priv);
872aee94f86SFrançois Tigeot 
873ba55f2f5SFrançois Tigeot 	return 0;
874a2fdbec6SFrançois Tigeot }
875a2fdbec6SFrançois Tigeot 
8762c9916cdSFrançois Tigeot static int i915_drm_resume_early(struct drm_device *dev)
877c4a9e910SFrançois Tigeot {
8785d0b1887SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
8792c9916cdSFrançois Tigeot 	int ret = 0;
880c4a9e910SFrançois Tigeot 
8815d0b1887SFrançois Tigeot 	/*
8822c9916cdSFrançois Tigeot 	 * We have a resume ordering issue with the snd-hda driver also
8832c9916cdSFrançois Tigeot 	 * requiring our device to be power up. Due to the lack of a
8842c9916cdSFrançois Tigeot 	 * parent/child relationship we currently solve this with an early
8852c9916cdSFrançois Tigeot 	 * resume hook.
8862c9916cdSFrançois Tigeot 	 *
8872c9916cdSFrançois Tigeot 	 * FIXME: This should be solved with a special hdmi sink device or
8882c9916cdSFrançois Tigeot 	 * similar so that power domains can be employed.
8895d0b1887SFrançois Tigeot 	 */
890c0e85e96SFrançois Tigeot 
891c0e85e96SFrançois Tigeot 	/*
892c0e85e96SFrançois Tigeot 	 * Note that we need to set the power state explicitly, since we
893c0e85e96SFrançois Tigeot 	 * powered off the device during freeze and the PCI core won't power
894c0e85e96SFrançois Tigeot 	 * it back up for us during thaw. Powering off the device during
895c0e85e96SFrançois Tigeot 	 * freeze is not a hard requirement though, and during the
896c0e85e96SFrançois Tigeot 	 * suspend/resume phases the PCI core makes sure we get here with the
897c0e85e96SFrançois Tigeot 	 * device powered on. So in case we change our freeze logic and keep
898c0e85e96SFrançois Tigeot 	 * the device powered we can also remove the following set power state
899c0e85e96SFrançois Tigeot 	 * call.
900c0e85e96SFrançois Tigeot 	 */
9012c9916cdSFrançois Tigeot #if 0
902c0e85e96SFrançois Tigeot 	ret = pci_set_power_state(dev->pdev, PCI_D0);
903c0e85e96SFrançois Tigeot 	if (ret) {
904c0e85e96SFrançois Tigeot 		DRM_ERROR("failed to set PCI D0 power state (%d)\n", ret);
905c0e85e96SFrançois Tigeot 		goto out;
906c0e85e96SFrançois Tigeot 	}
907c0e85e96SFrançois Tigeot 
908c0e85e96SFrançois Tigeot 	/*
909c0e85e96SFrançois Tigeot 	 * Note that pci_enable_device() first enables any parent bridge
910c0e85e96SFrançois Tigeot 	 * device and only then sets the power state for this device. The
911c0e85e96SFrançois Tigeot 	 * bridge enabling is a nop though, since bridge devices are resumed
912c0e85e96SFrançois Tigeot 	 * first. The order of enabling power and enabling the device is
913c0e85e96SFrançois Tigeot 	 * imposed by the PCI core as described above, so here we preserve the
914c0e85e96SFrançois Tigeot 	 * same order for the freeze/thaw phases.
915c0e85e96SFrançois Tigeot 	 *
916c0e85e96SFrançois Tigeot 	 * TODO: eventually we should remove pci_disable_device() /
917c0e85e96SFrançois Tigeot 	 * pci_enable_enable_device() from suspend/resume. Due to how they
918c0e85e96SFrançois Tigeot 	 * depend on the device enable refcount we can't anyway depend on them
919c0e85e96SFrançois Tigeot 	 * disabling/enabling the device.
920c0e85e96SFrançois Tigeot 	 */
921aee94f86SFrançois Tigeot 	if (pci_enable_device(dev->pdev)) {
922aee94f86SFrançois Tigeot 		ret = -EIO;
923aee94f86SFrançois Tigeot 		goto out;
924aee94f86SFrançois Tigeot 	}
9252c9916cdSFrançois Tigeot 
9262c9916cdSFrançois Tigeot 	pci_set_master(dev->pdev);
9272c9916cdSFrançois Tigeot #endif
9282c9916cdSFrançois Tigeot 
929aee94f86SFrançois Tigeot 	disable_rpm_wakeref_asserts(dev_priv);
930aee94f86SFrançois Tigeot 
931aee94f86SFrançois Tigeot 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
9322c9916cdSFrançois Tigeot 		ret = vlv_resume_prepare(dev_priv, false);
9332c9916cdSFrançois Tigeot 	if (ret)
93419c468b4SFrançois Tigeot 		DRM_ERROR("Resume prepare failed: %d, continuing anyway\n",
93519c468b4SFrançois Tigeot 			  ret);
9362c9916cdSFrançois Tigeot 
9372c9916cdSFrançois Tigeot 	intel_uncore_early_sanitize(dev, true);
9382c9916cdSFrançois Tigeot 
9398621f407SFrançois Tigeot 	if (IS_BROXTON(dev)) {
9408621f407SFrançois Tigeot 		if (!dev_priv->suspended_to_idle)
9418621f407SFrançois Tigeot 			gen9_sanitize_dc_state(dev_priv);
9428621f407SFrançois Tigeot 		bxt_disable_dc9(dev_priv);
9438621f407SFrançois Tigeot 	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
9442c9916cdSFrançois Tigeot 		hsw_disable_pc8(dev_priv);
9458621f407SFrançois Tigeot 	}
9462c9916cdSFrançois Tigeot 
9472c9916cdSFrançois Tigeot 	intel_uncore_sanitize(dev);
948aee94f86SFrançois Tigeot 
9498621f407SFrançois Tigeot 	if (IS_BROXTON(dev_priv) ||
9508621f407SFrançois Tigeot 	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
951aee94f86SFrançois Tigeot 		intel_power_domains_init_hw(dev_priv, true);
952aee94f86SFrançois Tigeot 
9538621f407SFrançois Tigeot 	enable_rpm_wakeref_asserts(dev_priv);
9548621f407SFrançois Tigeot 
955aee94f86SFrançois Tigeot #if 0
956aee94f86SFrançois Tigeot out:
957aee94f86SFrançois Tigeot #endif
958aee94f86SFrançois Tigeot 	dev_priv->suspended_to_idle = false;
959aee94f86SFrançois Tigeot 
9602c9916cdSFrançois Tigeot 	return ret;
9612c9916cdSFrançois Tigeot }
9622c9916cdSFrançois Tigeot 
963352ff8bdSFrançois Tigeot int i915_resume_switcheroo(struct drm_device *dev)
9642c9916cdSFrançois Tigeot {
9652c9916cdSFrançois Tigeot 	int ret;
9662c9916cdSFrançois Tigeot 
9672c9916cdSFrançois Tigeot 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
9682c9916cdSFrançois Tigeot 		return 0;
9692c9916cdSFrançois Tigeot 
9702c9916cdSFrançois Tigeot 	ret = i915_drm_resume_early(dev);
9715d0b1887SFrançois Tigeot 	if (ret)
9725d0b1887SFrançois Tigeot 		return ret;
973e3adcf8fSFrançois Tigeot 
9742c9916cdSFrançois Tigeot 	return i915_drm_resume(dev);
975c4a9e910SFrançois Tigeot }
976c4a9e910SFrançois Tigeot 
97762e5f8e8SFrançois Tigeot /* XXX Hack for the old *BSD drm code base
97862e5f8e8SFrançois Tigeot  * The device id field is set at probe time */
97962e5f8e8SFrançois Tigeot static drm_pci_id_list_t i915_attach_list[] = {
98062e5f8e8SFrançois Tigeot 	{0x8086, 0, 0, "Intel i915 GPU"},
98162e5f8e8SFrançois Tigeot 	{0, 0, 0, NULL}
98262e5f8e8SFrançois Tigeot };
98362e5f8e8SFrançois Tigeot 
984ba55f2f5SFrançois Tigeot struct intel_device_info *
985e3adcf8fSFrançois Tigeot i915_get_device_id(int device)
986c4a9e910SFrançois Tigeot {
9878e26cdf6SFrançois Tigeot 	const struct pci_device_id *did;
988c4a9e910SFrançois Tigeot 
989e3adcf8fSFrançois Tigeot 	for (did = &pciidlist[0]; did->device != 0; did++) {
990e3adcf8fSFrançois Tigeot 		if (did->device != device)
991e3adcf8fSFrançois Tigeot 			continue;
9928e26cdf6SFrançois Tigeot 		return (struct intel_device_info *)did->driver_data;
993e3adcf8fSFrançois Tigeot 	}
994e3adcf8fSFrançois Tigeot 	return (NULL);
995c4a9e910SFrançois Tigeot }
996c4a9e910SFrançois Tigeot 
997998e2cc6SPeeter Must static int i915_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx,
998998e2cc6SPeeter Must 			    struct sysctl_oid *top)
999998e2cc6SPeeter Must {
1000998e2cc6SPeeter Must 	return drm_add_busid_modesetting(dev, ctx, top);
1001998e2cc6SPeeter Must }
1002998e2cc6SPeeter Must 
1003c4a9e910SFrançois Tigeot extern devclass_t drm_devclass;
1004e3adcf8fSFrançois Tigeot 
1005e9243325SFrançois Tigeot /**
1006e9243325SFrançois Tigeot  * i915_reset - reset chip after a hang
1007e9243325SFrançois Tigeot  * @dev: drm device to reset
1008e9243325SFrançois Tigeot  *
1009e9243325SFrançois Tigeot  * Reset the chip.  Useful if a hang is detected. Returns zero on successful
1010e9243325SFrançois Tigeot  * reset or otherwise an error code.
1011e9243325SFrançois Tigeot  *
1012e9243325SFrançois Tigeot  * Procedure is fairly simple:
1013e9243325SFrançois Tigeot  *   - reset the chip using the reset reg
1014e9243325SFrançois Tigeot  *   - re-init context state
1015e9243325SFrançois Tigeot  *   - re-init hardware status page
1016e9243325SFrançois Tigeot  *   - re-init ring buffer
1017e9243325SFrançois Tigeot  *   - re-init interrupt state
1018e9243325SFrançois Tigeot  *   - re-init display
1019e9243325SFrançois Tigeot  */
102000640ec9SFrançois Tigeot int i915_reset(struct drm_device *dev)
1021e3adcf8fSFrançois Tigeot {
1022ba55f2f5SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
10238621f407SFrançois Tigeot 	struct i915_gpu_error *error = &dev_priv->gpu_error;
10248621f407SFrançois Tigeot 	unsigned reset_counter;
1025e9243325SFrançois Tigeot 	int ret;
1026e9243325SFrançois Tigeot 
10272c9916cdSFrançois Tigeot 	intel_reset_gt_powersave(dev);
10282c9916cdSFrançois Tigeot 
1029a2fdbec6SFrançois Tigeot 	mutex_lock(&dev->struct_mutex);
1030e3adcf8fSFrançois Tigeot 
10318621f407SFrançois Tigeot 	/* Clear any previous failed attempts at recovery. Time to try again. */
10328621f407SFrançois Tigeot 	atomic_andnot(I915_WEDGED, &error->reset_counter);
10338621f407SFrançois Tigeot 
10348621f407SFrançois Tigeot 	/* Clear the reset-in-progress flag and increment the reset epoch. */
10358621f407SFrançois Tigeot 	reset_counter = atomic_inc_return(&error->reset_counter);
10368621f407SFrançois Tigeot 	if (WARN_ON(__i915_reset_in_progress(reset_counter))) {
10378621f407SFrançois Tigeot 		ret = -EIO;
10388621f407SFrançois Tigeot 		goto error;
10398621f407SFrançois Tigeot 	}
10408621f407SFrançois Tigeot 
1041e3adcf8fSFrançois Tigeot 	i915_gem_reset(dev);
1042e3adcf8fSFrançois Tigeot 
10438621f407SFrançois Tigeot 	ret = intel_gpu_reset(dev, ALL_ENGINES);
104400640ec9SFrançois Tigeot 
10455d0b1887SFrançois Tigeot 	/* Also reset the gpu hangman. */
10468621f407SFrançois Tigeot 	if (error->stop_rings != 0) {
10475d0b1887SFrançois Tigeot 		DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
10488621f407SFrançois Tigeot 		error->stop_rings = 0;
10495d0b1887SFrançois Tigeot 		if (ret == -ENODEV) {
10509edbd4a0SFrançois Tigeot 			DRM_INFO("Reset not implemented, but ignoring "
10515d0b1887SFrançois Tigeot 				 "error for simulated gpu hangs\n");
10525d0b1887SFrançois Tigeot 			ret = 0;
10535d0b1887SFrançois Tigeot 		}
10545d0b1887SFrançois Tigeot 	}
10559edbd4a0SFrançois Tigeot 
10562c9916cdSFrançois Tigeot 	if (i915_stop_ring_allow_warn(dev_priv))
10572c9916cdSFrançois Tigeot 		pr_notice("drm/i915: Resetting chip after gpu hang\n");
10582c9916cdSFrançois Tigeot 
1059e3adcf8fSFrançois Tigeot 	if (ret) {
10608621f407SFrançois Tigeot 		if (ret != -ENODEV)
10619edbd4a0SFrançois Tigeot 			DRM_ERROR("Failed to reset chip: %i\n", ret);
10628621f407SFrançois Tigeot 		else
10638621f407SFrançois Tigeot 			DRM_DEBUG_DRIVER("GPU reset disabled\n");
10648621f407SFrançois Tigeot 		goto error;
1065e3adcf8fSFrançois Tigeot 	}
1066e3adcf8fSFrançois Tigeot 
10672c9916cdSFrançois Tigeot 	intel_overlay_reset(dev_priv);
10682c9916cdSFrançois Tigeot 
1069e9243325SFrançois Tigeot 	/* Ok, now get things going again... */
1070e9243325SFrançois Tigeot 
1071e9243325SFrançois Tigeot 	/*
1072e9243325SFrançois Tigeot 	 * Everything depends on having the GTT running, so we need to start
1073e9243325SFrançois Tigeot 	 * there.  Fortunately we don't need to do this unless we reset the
1074e9243325SFrançois Tigeot 	 * chip at a PCI level.
1075e9243325SFrançois Tigeot 	 *
1076e9243325SFrançois Tigeot 	 * Next we need to restore the context, but we don't use those
1077e9243325SFrançois Tigeot 	 * yet either...
1078e9243325SFrançois Tigeot 	 *
1079e9243325SFrançois Tigeot 	 * Ring buffer needs to be re-initialized in the KMS case, or if X
1080e9243325SFrançois Tigeot 	 * was running at the time of the reset (i.e. we weren't VT
1081e9243325SFrançois Tigeot 	 * switched away).
1082e9243325SFrançois Tigeot 	 */
10839edbd4a0SFrançois Tigeot 	ret = i915_gem_init_hw(dev);
10849edbd4a0SFrançois Tigeot 	if (ret) {
10859edbd4a0SFrançois Tigeot 		DRM_ERROR("Failed hw init on reset %d\n", ret);
10868621f407SFrançois Tigeot 		goto error;
10879edbd4a0SFrançois Tigeot 	}
1088e3adcf8fSFrançois Tigeot 
10898621f407SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
10908621f407SFrançois Tigeot 
1091ba55f2f5SFrançois Tigeot 	/*
1092ba55f2f5SFrançois Tigeot 	 * rps/rc6 re-init is necessary to restore state lost after the
1093ba55f2f5SFrançois Tigeot 	 * reset and the re-install of gt irqs. Skip for ironlake per
1094ba55f2f5SFrançois Tigeot 	 * previous concerns that it doesn't respond well to some forms
1095ba55f2f5SFrançois Tigeot 	 * of re-init after reset.
1096ba55f2f5SFrançois Tigeot 	 */
1097ba55f2f5SFrançois Tigeot 	if (INTEL_INFO(dev)->gen > 5)
10982c9916cdSFrançois Tigeot 		intel_enable_gt_powersave(dev);
1099e3adcf8fSFrançois Tigeot 
1100e9243325SFrançois Tigeot 	return 0;
11018621f407SFrançois Tigeot 
11028621f407SFrançois Tigeot error:
11038621f407SFrançois Tigeot 	atomic_or(I915_WEDGED, &error->reset_counter);
11048621f407SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
11058621f407SFrançois Tigeot 	return ret;
1106e9243325SFrançois Tigeot }
1107e9243325SFrançois Tigeot 
1108ba55f2f5SFrançois Tigeot static int i915_pci_probe(device_t kdev)
1109a2fdbec6SFrançois Tigeot {
1110a2fdbec6SFrançois Tigeot 	int device, i = 0;
1111a2fdbec6SFrançois Tigeot 
1112a2fdbec6SFrançois Tigeot 	if (pci_get_class(kdev) != PCIC_DISPLAY)
1113a2fdbec6SFrançois Tigeot 		return ENXIO;
1114a2fdbec6SFrançois Tigeot 
1115a2fdbec6SFrançois Tigeot 	if (pci_get_vendor(kdev) != PCI_VENDOR_INTEL)
1116a2fdbec6SFrançois Tigeot 		return ENXIO;
1117a2fdbec6SFrançois Tigeot 
1118a2fdbec6SFrançois Tigeot 	device = pci_get_device(kdev);
1119a2fdbec6SFrançois Tigeot 
1120a2fdbec6SFrançois Tigeot 	for (i = 0; pciidlist[i].device != 0; i++) {
1121a2fdbec6SFrançois Tigeot 		if (pciidlist[i].device == device) {
1122a2fdbec6SFrançois Tigeot 			i915_attach_list[0].device = device;
1123a2fdbec6SFrançois Tigeot 			return 0;
1124a2fdbec6SFrançois Tigeot 		}
1125a2fdbec6SFrançois Tigeot 	}
1126a2fdbec6SFrançois Tigeot 
1127a2fdbec6SFrançois Tigeot 	return ENXIO;
1128a2fdbec6SFrançois Tigeot }
1129a2fdbec6SFrançois Tigeot 
11309edbd4a0SFrançois Tigeot #if 0
11319edbd4a0SFrançois Tigeot static void
11329edbd4a0SFrançois Tigeot i915_pci_remove(struct pci_dev *pdev)
11339edbd4a0SFrançois Tigeot {
11349edbd4a0SFrançois Tigeot 	struct drm_device *dev = pci_get_drvdata(pdev);
11359edbd4a0SFrançois Tigeot 
11369edbd4a0SFrançois Tigeot 	drm_put_dev(dev);
11379edbd4a0SFrançois Tigeot }
11389edbd4a0SFrançois Tigeot 
11399edbd4a0SFrançois Tigeot static int i915_pm_suspend(struct device *dev)
11409edbd4a0SFrançois Tigeot {
11419edbd4a0SFrançois Tigeot 	struct pci_dev *pdev = to_pci_dev(dev);
11429edbd4a0SFrançois Tigeot 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
11439edbd4a0SFrançois Tigeot 
11449edbd4a0SFrançois Tigeot 	if (!drm_dev || !drm_dev->dev_private) {
11459edbd4a0SFrançois Tigeot 		dev_err(dev, "DRM not initialized, aborting suspend.\n");
11469edbd4a0SFrançois Tigeot 		return -ENODEV;
11479edbd4a0SFrançois Tigeot 	}
11489edbd4a0SFrançois Tigeot 
11499edbd4a0SFrançois Tigeot 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
11509edbd4a0SFrançois Tigeot 		return 0;
11519edbd4a0SFrançois Tigeot 
11522c9916cdSFrançois Tigeot 	return i915_drm_suspend(drm_dev);
11539edbd4a0SFrançois Tigeot }
11549edbd4a0SFrançois Tigeot 
115524edb884SFrançois Tigeot static int i915_pm_suspend_late(struct device *dev)
115624edb884SFrançois Tigeot {
11572c9916cdSFrançois Tigeot 	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
115824edb884SFrançois Tigeot 
115924edb884SFrançois Tigeot 	/*
116019c468b4SFrançois Tigeot 	 * We have a suspend ordering issue with the snd-hda driver also
116124edb884SFrançois Tigeot 	 * requiring our device to be power up. Due to the lack of a
116224edb884SFrançois Tigeot 	 * parent/child relationship we currently solve this with an late
116324edb884SFrançois Tigeot 	 * suspend hook.
116424edb884SFrançois Tigeot 	 *
116524edb884SFrançois Tigeot 	 * FIXME: This should be solved with a special hdmi sink device or
116624edb884SFrançois Tigeot 	 * similar so that power domains can be employed.
116724edb884SFrançois Tigeot 	 */
116824edb884SFrançois Tigeot 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
116924edb884SFrançois Tigeot 		return 0;
117024edb884SFrançois Tigeot 
11712c9916cdSFrançois Tigeot 	return i915_drm_suspend_late(drm_dev, false);
11721b13d190SFrançois Tigeot }
117324edb884SFrançois Tigeot 
11742c9916cdSFrançois Tigeot static int i915_pm_poweroff_late(struct device *dev)
11752c9916cdSFrançois Tigeot {
11762c9916cdSFrançois Tigeot 	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
11772c9916cdSFrançois Tigeot 
11782c9916cdSFrançois Tigeot 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
11792c9916cdSFrançois Tigeot 		return 0;
11802c9916cdSFrançois Tigeot 
11812c9916cdSFrançois Tigeot 	return i915_drm_suspend_late(drm_dev, true);
11822c9916cdSFrançois Tigeot }
11832c9916cdSFrançois Tigeot 
11842c9916cdSFrançois Tigeot static int i915_pm_resume_early(struct device *dev)
11852c9916cdSFrançois Tigeot {
11862c9916cdSFrançois Tigeot 	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
11872c9916cdSFrançois Tigeot 
11882c9916cdSFrançois Tigeot 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
11892c9916cdSFrançois Tigeot 		return 0;
11902c9916cdSFrançois Tigeot 
11912c9916cdSFrançois Tigeot 	return i915_drm_resume_early(drm_dev);
119224edb884SFrançois Tigeot }
119324edb884SFrançois Tigeot 
11949edbd4a0SFrançois Tigeot static int i915_pm_resume(struct device *dev)
11959edbd4a0SFrançois Tigeot {
11962c9916cdSFrançois Tigeot 	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
11979edbd4a0SFrançois Tigeot 
11982c9916cdSFrançois Tigeot 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
11992c9916cdSFrançois Tigeot 		return 0;
12002c9916cdSFrançois Tigeot 
12012c9916cdSFrançois Tigeot 	return i915_drm_resume(drm_dev);
12029edbd4a0SFrançois Tigeot }
12032c9916cdSFrançois Tigeot #endif
12049edbd4a0SFrançois Tigeot 
1205ba55f2f5SFrançois Tigeot /*
1206ba55f2f5SFrançois Tigeot  * Save all Gunit registers that may be lost after a D3 and a subsequent
1207ba55f2f5SFrançois Tigeot  * S0i[R123] transition. The list of registers needing a save/restore is
1208ba55f2f5SFrançois Tigeot  * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
1209ba55f2f5SFrançois Tigeot  * registers in the following way:
1210ba55f2f5SFrançois Tigeot  * - Driver: saved/restored by the driver
1211ba55f2f5SFrançois Tigeot  * - Punit : saved/restored by the Punit firmware
1212ba55f2f5SFrançois Tigeot  * - No, w/o marking: no need to save/restore, since the register is R/O or
1213ba55f2f5SFrançois Tigeot  *                    used internally by the HW in a way that doesn't depend
1214ba55f2f5SFrançois Tigeot  *                    keeping the content across a suspend/resume.
1215ba55f2f5SFrançois Tigeot  * - Debug : used for debugging
1216ba55f2f5SFrançois Tigeot  *
1217ba55f2f5SFrançois Tigeot  * We save/restore all registers marked with 'Driver', with the following
1218ba55f2f5SFrançois Tigeot  * exceptions:
1219ba55f2f5SFrançois Tigeot  * - Registers out of use, including also registers marked with 'Debug'.
1220ba55f2f5SFrançois Tigeot  *   These have no effect on the driver's operation, so we don't save/restore
1221ba55f2f5SFrançois Tigeot  *   them to reduce the overhead.
1222ba55f2f5SFrançois Tigeot  * - Registers that are fully setup by an initialization function called from
1223ba55f2f5SFrançois Tigeot  *   the resume path. For example many clock gating and RPS/RC6 registers.
1224ba55f2f5SFrançois Tigeot  * - Registers that provide the right functionality with their reset defaults.
1225ba55f2f5SFrançois Tigeot  *
1226ba55f2f5SFrançois Tigeot  * TODO: Except for registers that based on the above 3 criteria can be safely
1227ba55f2f5SFrançois Tigeot  * ignored, we save/restore all others, practically treating the HW context as
1228ba55f2f5SFrançois Tigeot  * a black-box for the driver. Further investigation is needed to reduce the
1229ba55f2f5SFrançois Tigeot  * saved/restored registers even further, by following the same 3 criteria.
1230ba55f2f5SFrançois Tigeot  */
1231ba55f2f5SFrançois Tigeot static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
1232ba55f2f5SFrançois Tigeot {
1233ba55f2f5SFrançois Tigeot 	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
1234ba55f2f5SFrançois Tigeot 	int i;
1235ba55f2f5SFrançois Tigeot 
1236ba55f2f5SFrançois Tigeot 	/* GAM 0x4000-0x4770 */
1237ba55f2f5SFrançois Tigeot 	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
1238ba55f2f5SFrançois Tigeot 	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
1239ba55f2f5SFrançois Tigeot 	s->arb_mode		= I915_READ(ARB_MODE);
1240ba55f2f5SFrançois Tigeot 	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
1241ba55f2f5SFrançois Tigeot 	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
1242ba55f2f5SFrançois Tigeot 
1243ba55f2f5SFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
1244352ff8bdSFrançois Tigeot 		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS(i));
1245ba55f2f5SFrançois Tigeot 
1246ba55f2f5SFrançois Tigeot 	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
1247477eb7f9SFrançois Tigeot 	s->gfx_max_req_count	= I915_READ(GEN7_GFX_MAX_REQ_COUNT);
1248ba55f2f5SFrançois Tigeot 
1249ba55f2f5SFrançois Tigeot 	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
1250ba55f2f5SFrançois Tigeot 	s->ecochk		= I915_READ(GAM_ECOCHK);
1251ba55f2f5SFrançois Tigeot 	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
1252ba55f2f5SFrançois Tigeot 	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
1253ba55f2f5SFrançois Tigeot 
1254ba55f2f5SFrançois Tigeot 	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
1255ba55f2f5SFrançois Tigeot 
1256ba55f2f5SFrançois Tigeot 	/* MBC 0x9024-0x91D0, 0x8500 */
1257ba55f2f5SFrançois Tigeot 	s->g3dctl		= I915_READ(VLV_G3DCTL);
1258ba55f2f5SFrançois Tigeot 	s->gsckgctl		= I915_READ(VLV_GSCKGCTL);
1259ba55f2f5SFrançois Tigeot 	s->mbctl		= I915_READ(GEN6_MBCTL);
1260ba55f2f5SFrançois Tigeot 
1261ba55f2f5SFrançois Tigeot 	/* GCP 0x9400-0x9424, 0x8100-0x810C */
1262ba55f2f5SFrançois Tigeot 	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
1263ba55f2f5SFrançois Tigeot 	s->ucgctl3		= I915_READ(GEN6_UCGCTL3);
1264ba55f2f5SFrançois Tigeot 	s->rcgctl1		= I915_READ(GEN6_RCGCTL1);
1265ba55f2f5SFrançois Tigeot 	s->rcgctl2		= I915_READ(GEN6_RCGCTL2);
1266ba55f2f5SFrançois Tigeot 	s->rstctl		= I915_READ(GEN6_RSTCTL);
1267ba55f2f5SFrançois Tigeot 	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
1268ba55f2f5SFrançois Tigeot 
1269ba55f2f5SFrançois Tigeot 	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
1270ba55f2f5SFrançois Tigeot 	s->gfxpause		= I915_READ(GEN6_GFXPAUSE);
1271ba55f2f5SFrançois Tigeot 	s->rpdeuhwtc		= I915_READ(GEN6_RPDEUHWTC);
1272ba55f2f5SFrançois Tigeot 	s->rpdeuc		= I915_READ(GEN6_RPDEUC);
1273ba55f2f5SFrançois Tigeot 	s->ecobus		= I915_READ(ECOBUS);
1274ba55f2f5SFrançois Tigeot 	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
1275ba55f2f5SFrançois Tigeot 	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
1276ba55f2f5SFrançois Tigeot 	s->rp_deucsw		= I915_READ(GEN6_RPDEUCSW);
1277ba55f2f5SFrançois Tigeot 	s->rcubmabdtmr		= I915_READ(GEN6_RCUBMABDTMR);
1278ba55f2f5SFrançois Tigeot 	s->rcedata		= I915_READ(VLV_RCEDATA);
1279ba55f2f5SFrançois Tigeot 	s->spare2gh		= I915_READ(VLV_SPAREG2H);
1280ba55f2f5SFrançois Tigeot 
1281ba55f2f5SFrançois Tigeot 	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
1282ba55f2f5SFrançois Tigeot 	s->gt_imr		= I915_READ(GTIMR);
1283ba55f2f5SFrançois Tigeot 	s->gt_ier		= I915_READ(GTIER);
1284ba55f2f5SFrançois Tigeot 	s->pm_imr		= I915_READ(GEN6_PMIMR);
1285ba55f2f5SFrançois Tigeot 	s->pm_ier		= I915_READ(GEN6_PMIER);
1286ba55f2f5SFrançois Tigeot 
1287ba55f2f5SFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
1288352ff8bdSFrançois Tigeot 		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH(i));
1289ba55f2f5SFrançois Tigeot 
1290ba55f2f5SFrançois Tigeot 	/* GT SA CZ domain, 0x100000-0x138124 */
1291ba55f2f5SFrançois Tigeot 	s->tilectl		= I915_READ(TILECTL);
1292ba55f2f5SFrançois Tigeot 	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
1293ba55f2f5SFrançois Tigeot 	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
1294ba55f2f5SFrançois Tigeot 	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
1295ba55f2f5SFrançois Tigeot 	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
1296ba55f2f5SFrançois Tigeot 
1297ba55f2f5SFrançois Tigeot 	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
1298ba55f2f5SFrançois Tigeot 	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
1299ba55f2f5SFrançois Tigeot 	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
13002c9916cdSFrançois Tigeot 	s->pcbr			= I915_READ(VLV_PCBR);
1301ba55f2f5SFrançois Tigeot 	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
1302ba55f2f5SFrançois Tigeot 
1303ba55f2f5SFrançois Tigeot 	/*
1304ba55f2f5SFrançois Tigeot 	 * Not saving any of:
1305ba55f2f5SFrançois Tigeot 	 * DFT,		0x9800-0x9EC0
1306ba55f2f5SFrançois Tigeot 	 * SARB,	0xB000-0xB1FC
1307ba55f2f5SFrançois Tigeot 	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
1308ba55f2f5SFrançois Tigeot 	 * PCI CFG
1309ba55f2f5SFrançois Tigeot 	 */
1310ba55f2f5SFrançois Tigeot }
1311ba55f2f5SFrançois Tigeot 
1312ba55f2f5SFrançois Tigeot static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
1313ba55f2f5SFrançois Tigeot {
1314ba55f2f5SFrançois Tigeot 	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
1315ba55f2f5SFrançois Tigeot 	u32 val;
1316ba55f2f5SFrançois Tigeot 	int i;
1317ba55f2f5SFrançois Tigeot 
1318ba55f2f5SFrançois Tigeot 	/* GAM 0x4000-0x4770 */
1319ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
1320ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
1321ba55f2f5SFrançois Tigeot 	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
1322ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
1323ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
1324ba55f2f5SFrançois Tigeot 
1325ba55f2f5SFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
1326352ff8bdSFrançois Tigeot 		I915_WRITE(GEN7_LRA_LIMITS(i), s->lra_limits[i]);
1327ba55f2f5SFrançois Tigeot 
1328ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
1329477eb7f9SFrançois Tigeot 	I915_WRITE(GEN7_GFX_MAX_REQ_COUNT, s->gfx_max_req_count);
1330ba55f2f5SFrançois Tigeot 
1331ba55f2f5SFrançois Tigeot 	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
1332ba55f2f5SFrançois Tigeot 	I915_WRITE(GAM_ECOCHK,		s->ecochk);
1333ba55f2f5SFrançois Tigeot 	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
1334ba55f2f5SFrançois Tigeot 	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
1335ba55f2f5SFrançois Tigeot 
1336ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
1337ba55f2f5SFrançois Tigeot 
1338ba55f2f5SFrançois Tigeot 	/* MBC 0x9024-0x91D0, 0x8500 */
1339ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_G3DCTL,		s->g3dctl);
1340ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GSCKGCTL,	s->gsckgctl);
1341ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_MBCTL,		s->mbctl);
1342ba55f2f5SFrançois Tigeot 
1343ba55f2f5SFrançois Tigeot 	/* GCP 0x9400-0x9424, 0x8100-0x810C */
1344ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
1345ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_UCGCTL3,	s->ucgctl3);
1346ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RCGCTL1,	s->rcgctl1);
1347ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RCGCTL2,	s->rcgctl2);
1348ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RSTCTL,		s->rstctl);
1349ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
1350ba55f2f5SFrançois Tigeot 
1351ba55f2f5SFrançois Tigeot 	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
1352ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_GFXPAUSE,	s->gfxpause);
1353ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RPDEUHWTC,	s->rpdeuhwtc);
1354ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RPDEUC,		s->rpdeuc);
1355ba55f2f5SFrançois Tigeot 	I915_WRITE(ECOBUS,		s->ecobus);
1356ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
1357ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
1358ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RPDEUCSW,	s->rp_deucsw);
1359ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_RCUBMABDTMR,	s->rcubmabdtmr);
1360ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_RCEDATA,		s->rcedata);
1361ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
1362ba55f2f5SFrançois Tigeot 
1363ba55f2f5SFrançois Tigeot 	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
1364ba55f2f5SFrançois Tigeot 	I915_WRITE(GTIMR,		s->gt_imr);
1365ba55f2f5SFrançois Tigeot 	I915_WRITE(GTIER,		s->gt_ier);
1366ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_PMIMR,		s->pm_imr);
1367ba55f2f5SFrançois Tigeot 	I915_WRITE(GEN6_PMIER,		s->pm_ier);
1368ba55f2f5SFrançois Tigeot 
1369ba55f2f5SFrançois Tigeot 	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
1370352ff8bdSFrançois Tigeot 		I915_WRITE(GEN7_GT_SCRATCH(i), s->gt_scratch[i]);
1371ba55f2f5SFrançois Tigeot 
1372ba55f2f5SFrançois Tigeot 	/* GT SA CZ domain, 0x100000-0x138124 */
1373ba55f2f5SFrançois Tigeot 	I915_WRITE(TILECTL,			s->tilectl);
1374ba55f2f5SFrançois Tigeot 	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
1375ba55f2f5SFrançois Tigeot 	/*
1376ba55f2f5SFrançois Tigeot 	 * Preserve the GT allow wake and GFX force clock bit, they are not
1377ba55f2f5SFrançois Tigeot 	 * be restored, as they are used to control the s0ix suspend/resume
1378ba55f2f5SFrançois Tigeot 	 * sequence by the caller.
1379ba55f2f5SFrançois Tigeot 	 */
1380ba55f2f5SFrançois Tigeot 	val = I915_READ(VLV_GTLC_WAKE_CTRL);
1381ba55f2f5SFrançois Tigeot 	val &= VLV_GTLC_ALLOWWAKEREQ;
1382ba55f2f5SFrançois Tigeot 	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
1383ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
1384ba55f2f5SFrançois Tigeot 
1385ba55f2f5SFrançois Tigeot 	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
1386ba55f2f5SFrançois Tigeot 	val &= VLV_GFX_CLK_FORCE_ON_BIT;
1387ba55f2f5SFrançois Tigeot 	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
1388ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
1389ba55f2f5SFrançois Tigeot 
1390ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
1391ba55f2f5SFrançois Tigeot 
1392ba55f2f5SFrançois Tigeot 	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
1393ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
1394ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
13952c9916cdSFrançois Tigeot 	I915_WRITE(VLV_PCBR,			s->pcbr);
1396ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
1397ba55f2f5SFrançois Tigeot }
1398ba55f2f5SFrançois Tigeot 
1399ba55f2f5SFrançois Tigeot int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
1400ba55f2f5SFrançois Tigeot {
1401ba55f2f5SFrançois Tigeot 	u32 val;
1402ba55f2f5SFrançois Tigeot 	int err;
1403ba55f2f5SFrançois Tigeot 
1404ba55f2f5SFrançois Tigeot #define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
1405ba55f2f5SFrançois Tigeot 
1406ba55f2f5SFrançois Tigeot 	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
1407ba55f2f5SFrançois Tigeot 	val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
1408ba55f2f5SFrançois Tigeot 	if (force_on)
1409ba55f2f5SFrançois Tigeot 		val |= VLV_GFX_CLK_FORCE_ON_BIT;
1410ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
1411ba55f2f5SFrançois Tigeot 
1412ba55f2f5SFrançois Tigeot 	if (!force_on)
1413ba55f2f5SFrançois Tigeot 		return 0;
1414ba55f2f5SFrançois Tigeot 
1415ba55f2f5SFrançois Tigeot 	err = wait_for(COND, 20);
1416ba55f2f5SFrançois Tigeot 	if (err)
1417ba55f2f5SFrançois Tigeot 		DRM_ERROR("timeout waiting for GFX clock force-on (%08x)\n",
1418ba55f2f5SFrançois Tigeot 			  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
1419ba55f2f5SFrançois Tigeot 
1420ba55f2f5SFrançois Tigeot 	return err;
1421ba55f2f5SFrançois Tigeot #undef COND
1422ba55f2f5SFrançois Tigeot }
1423ba55f2f5SFrançois Tigeot 
1424ba55f2f5SFrançois Tigeot static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
1425ba55f2f5SFrançois Tigeot {
1426ba55f2f5SFrançois Tigeot 	u32 val;
1427ba55f2f5SFrançois Tigeot 	int err = 0;
1428ba55f2f5SFrançois Tigeot 
1429ba55f2f5SFrançois Tigeot 	val = I915_READ(VLV_GTLC_WAKE_CTRL);
1430ba55f2f5SFrançois Tigeot 	val &= ~VLV_GTLC_ALLOWWAKEREQ;
1431ba55f2f5SFrançois Tigeot 	if (allow)
1432ba55f2f5SFrançois Tigeot 		val |= VLV_GTLC_ALLOWWAKEREQ;
1433ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
1434ba55f2f5SFrançois Tigeot 	POSTING_READ(VLV_GTLC_WAKE_CTRL);
1435ba55f2f5SFrançois Tigeot 
1436ba55f2f5SFrançois Tigeot #define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
1437ba55f2f5SFrançois Tigeot 	      allow)
1438ba55f2f5SFrançois Tigeot 	err = wait_for(COND, 1);
1439ba55f2f5SFrançois Tigeot 	if (err)
1440ba55f2f5SFrançois Tigeot 		DRM_ERROR("timeout disabling GT waking\n");
1441ba55f2f5SFrançois Tigeot 	return err;
1442ba55f2f5SFrançois Tigeot #undef COND
1443ba55f2f5SFrançois Tigeot }
1444ba55f2f5SFrançois Tigeot 
1445ba55f2f5SFrançois Tigeot static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
1446ba55f2f5SFrançois Tigeot 				 bool wait_for_on)
1447ba55f2f5SFrançois Tigeot {
1448ba55f2f5SFrançois Tigeot 	u32 mask;
1449ba55f2f5SFrançois Tigeot 	u32 val;
1450ba55f2f5SFrançois Tigeot 	int err;
1451ba55f2f5SFrançois Tigeot 
1452ba55f2f5SFrançois Tigeot 	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
1453ba55f2f5SFrançois Tigeot 	val = wait_for_on ? mask : 0;
1454ba55f2f5SFrançois Tigeot #define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
1455ba55f2f5SFrançois Tigeot 	if (COND)
1456ba55f2f5SFrançois Tigeot 		return 0;
1457ba55f2f5SFrançois Tigeot 
1458ba55f2f5SFrançois Tigeot 	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
1459c0e85e96SFrançois Tigeot 		      onoff(wait_for_on),
1460ba55f2f5SFrançois Tigeot 		      I915_READ(VLV_GTLC_PW_STATUS));
1461ba55f2f5SFrançois Tigeot 
1462ba55f2f5SFrançois Tigeot 	/*
1463ba55f2f5SFrançois Tigeot 	 * RC6 transitioning can be delayed up to 2 msec (see
1464ba55f2f5SFrançois Tigeot 	 * valleyview_enable_rps), use 3 msec for safety.
1465ba55f2f5SFrançois Tigeot 	 */
1466ba55f2f5SFrançois Tigeot 	err = wait_for(COND, 3);
1467ba55f2f5SFrançois Tigeot 	if (err)
1468ba55f2f5SFrançois Tigeot 		DRM_ERROR("timeout waiting for GT wells to go %s\n",
1469c0e85e96SFrançois Tigeot 			  onoff(wait_for_on));
1470ba55f2f5SFrançois Tigeot 
1471ba55f2f5SFrançois Tigeot 	return err;
1472ba55f2f5SFrançois Tigeot #undef COND
1473ba55f2f5SFrançois Tigeot }
1474ba55f2f5SFrançois Tigeot 
1475ba55f2f5SFrançois Tigeot static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
1476ba55f2f5SFrançois Tigeot {
1477ba55f2f5SFrançois Tigeot 	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
1478ba55f2f5SFrançois Tigeot 		return;
1479ba55f2f5SFrançois Tigeot 
1480c0e85e96SFrançois Tigeot 	DRM_DEBUG_DRIVER("GT register access while GT waking disabled\n");
1481ba55f2f5SFrançois Tigeot 	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
1482ba55f2f5SFrançois Tigeot }
1483ba55f2f5SFrançois Tigeot 
14841b13d190SFrançois Tigeot static int vlv_suspend_complete(struct drm_i915_private *dev_priv)
1485ba55f2f5SFrançois Tigeot {
1486ba55f2f5SFrançois Tigeot 	u32 mask;
1487ba55f2f5SFrançois Tigeot 	int err;
1488ba55f2f5SFrançois Tigeot 
1489ba55f2f5SFrançois Tigeot 	/*
1490ba55f2f5SFrançois Tigeot 	 * Bspec defines the following GT well on flags as debug only, so
1491ba55f2f5SFrançois Tigeot 	 * don't treat them as hard failures.
1492ba55f2f5SFrançois Tigeot 	 */
1493ba55f2f5SFrançois Tigeot 	(void)vlv_wait_for_gt_wells(dev_priv, false);
1494ba55f2f5SFrançois Tigeot 
1495ba55f2f5SFrançois Tigeot 	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
1496ba55f2f5SFrançois Tigeot 	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
1497ba55f2f5SFrançois Tigeot 
1498ba55f2f5SFrançois Tigeot 	vlv_check_no_gt_access(dev_priv);
1499ba55f2f5SFrançois Tigeot 
1500ba55f2f5SFrançois Tigeot 	err = vlv_force_gfx_clock(dev_priv, true);
1501ba55f2f5SFrançois Tigeot 	if (err)
1502ba55f2f5SFrançois Tigeot 		goto err1;
1503ba55f2f5SFrançois Tigeot 
1504ba55f2f5SFrançois Tigeot 	err = vlv_allow_gt_wake(dev_priv, false);
1505ba55f2f5SFrançois Tigeot 	if (err)
1506ba55f2f5SFrançois Tigeot 		goto err2;
15072c9916cdSFrançois Tigeot 
15088621f407SFrançois Tigeot 	if (!IS_CHERRYVIEW(dev_priv))
1509ba55f2f5SFrançois Tigeot 		vlv_save_gunit_s0ix_state(dev_priv);
1510ba55f2f5SFrançois Tigeot 
1511ba55f2f5SFrançois Tigeot 	err = vlv_force_gfx_clock(dev_priv, false);
1512ba55f2f5SFrançois Tigeot 	if (err)
1513ba55f2f5SFrançois Tigeot 		goto err2;
1514ba55f2f5SFrançois Tigeot 
1515ba55f2f5SFrançois Tigeot 	return 0;
1516ba55f2f5SFrançois Tigeot 
1517ba55f2f5SFrançois Tigeot err2:
1518ba55f2f5SFrançois Tigeot 	/* For safety always re-enable waking and disable gfx clock forcing */
1519ba55f2f5SFrançois Tigeot 	vlv_allow_gt_wake(dev_priv, true);
1520ba55f2f5SFrançois Tigeot err1:
1521ba55f2f5SFrançois Tigeot 	vlv_force_gfx_clock(dev_priv, false);
1522ba55f2f5SFrançois Tigeot 
1523ba55f2f5SFrançois Tigeot 	return err;
1524ba55f2f5SFrançois Tigeot }
1525ba55f2f5SFrançois Tigeot 
15261b13d190SFrançois Tigeot static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
15271b13d190SFrançois Tigeot 				bool rpm_resume)
1528ba55f2f5SFrançois Tigeot {
1529ba55f2f5SFrançois Tigeot 	struct drm_device *dev = dev_priv->dev;
1530ba55f2f5SFrançois Tigeot 	int err;
1531ba55f2f5SFrançois Tigeot 	int ret;
1532ba55f2f5SFrançois Tigeot 
1533ba55f2f5SFrançois Tigeot 	/*
1534ba55f2f5SFrançois Tigeot 	 * If any of the steps fail just try to continue, that's the best we
1535ba55f2f5SFrançois Tigeot 	 * can do at this point. Return the first error code (which will also
1536ba55f2f5SFrançois Tigeot 	 * leave RPM permanently disabled).
1537ba55f2f5SFrançois Tigeot 	 */
1538ba55f2f5SFrançois Tigeot 	ret = vlv_force_gfx_clock(dev_priv, true);
1539ba55f2f5SFrançois Tigeot 
15408621f407SFrançois Tigeot 	if (!IS_CHERRYVIEW(dev_priv))
1541ba55f2f5SFrançois Tigeot 		vlv_restore_gunit_s0ix_state(dev_priv);
1542ba55f2f5SFrançois Tigeot 
1543ba55f2f5SFrançois Tigeot 	err = vlv_allow_gt_wake(dev_priv, true);
1544ba55f2f5SFrançois Tigeot 	if (!ret)
1545ba55f2f5SFrançois Tigeot 		ret = err;
1546ba55f2f5SFrançois Tigeot 
1547ba55f2f5SFrançois Tigeot 	err = vlv_force_gfx_clock(dev_priv, false);
1548ba55f2f5SFrançois Tigeot 	if (!ret)
1549ba55f2f5SFrançois Tigeot 		ret = err;
1550ba55f2f5SFrançois Tigeot 
1551ba55f2f5SFrançois Tigeot 	vlv_check_no_gt_access(dev_priv);
1552ba55f2f5SFrançois Tigeot 
15531b13d190SFrançois Tigeot 	if (rpm_resume) {
1554ba55f2f5SFrançois Tigeot 		intel_init_clock_gating(dev);
1555ba55f2f5SFrançois Tigeot 		i915_gem_restore_fences(dev);
15561b13d190SFrançois Tigeot 	}
1557ba55f2f5SFrançois Tigeot 
1558ba55f2f5SFrançois Tigeot 	return ret;
1559ba55f2f5SFrançois Tigeot }
1560ba55f2f5SFrançois Tigeot 
15612c9916cdSFrançois Tigeot #if 0
1562ba55f2f5SFrançois Tigeot static int intel_runtime_suspend(struct device *device)
15639edbd4a0SFrançois Tigeot {
15649edbd4a0SFrançois Tigeot 	struct pci_dev *pdev = to_pci_dev(device);
15659edbd4a0SFrançois Tigeot 	struct drm_device *dev = pci_get_drvdata(pdev);
15669edbd4a0SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
1567ba55f2f5SFrançois Tigeot 	int ret;
1568ba55f2f5SFrançois Tigeot 
1569ba55f2f5SFrançois Tigeot 	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
1570ba55f2f5SFrançois Tigeot 		return -ENODEV;
15719edbd4a0SFrançois Tigeot 
15721b13d190SFrançois Tigeot 	if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
15731b13d190SFrançois Tigeot 		return -ENODEV;
15741b13d190SFrançois Tigeot 
15759edbd4a0SFrançois Tigeot 	DRM_DEBUG_KMS("Suspending device\n");
15769edbd4a0SFrançois Tigeot 
1577ba55f2f5SFrançois Tigeot 	/*
1578ba55f2f5SFrançois Tigeot 	 * We could deadlock here in case another thread holding struct_mutex
1579ba55f2f5SFrançois Tigeot 	 * calls RPM suspend concurrently, since the RPM suspend will wait
1580ba55f2f5SFrançois Tigeot 	 * first for this RPM suspend to finish. In this case the concurrent
1581ba55f2f5SFrançois Tigeot 	 * RPM resume will be followed by its RPM suspend counterpart. Still
1582ba55f2f5SFrançois Tigeot 	 * for consistency return -EAGAIN, which will reschedule this suspend.
1583ba55f2f5SFrançois Tigeot 	 */
1584ba55f2f5SFrançois Tigeot 	if (!mutex_trylock(&dev->struct_mutex)) {
1585ba55f2f5SFrançois Tigeot 		DRM_DEBUG_KMS("device lock contention, deffering suspend\n");
1586ba55f2f5SFrançois Tigeot 		/*
1587ba55f2f5SFrançois Tigeot 		 * Bump the expiration timestamp, otherwise the suspend won't
1588ba55f2f5SFrançois Tigeot 		 * be rescheduled.
1589ba55f2f5SFrançois Tigeot 		 */
1590ba55f2f5SFrançois Tigeot 		pm_runtime_mark_last_busy(device);
1591ba55f2f5SFrançois Tigeot 
1592ba55f2f5SFrançois Tigeot 		return -EAGAIN;
1593ba55f2f5SFrançois Tigeot 	}
1594aee94f86SFrançois Tigeot 
1595aee94f86SFrançois Tigeot 	disable_rpm_wakeref_asserts(dev_priv);
1596aee94f86SFrançois Tigeot 
1597ba55f2f5SFrançois Tigeot 	/*
1598ba55f2f5SFrançois Tigeot 	 * We are safe here against re-faults, since the fault handler takes
1599ba55f2f5SFrançois Tigeot 	 * an RPM reference.
1600ba55f2f5SFrançois Tigeot 	 */
16019edbd4a0SFrançois Tigeot 	i915_gem_release_all_mmaps(dev_priv);
1602ba55f2f5SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
1603ba55f2f5SFrançois Tigeot 
1604aee94f86SFrançois Tigeot 	cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
1605aee94f86SFrançois Tigeot 
1606352ff8bdSFrançois Tigeot 	intel_guc_suspend(dev);
1607352ff8bdSFrançois Tigeot 
16082c9916cdSFrançois Tigeot 	intel_suspend_gt_powersave(dev);
16092c9916cdSFrançois Tigeot 	intel_runtime_pm_disable_interrupts(dev_priv);
1610ba55f2f5SFrançois Tigeot 
16118621f407SFrançois Tigeot 	ret = 0;
16128621f407SFrançois Tigeot 	if (IS_BROXTON(dev_priv)) {
16138621f407SFrançois Tigeot 		bxt_display_core_uninit(dev_priv);
16148621f407SFrançois Tigeot 		bxt_enable_dc9(dev_priv);
16158621f407SFrançois Tigeot 	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
16168621f407SFrançois Tigeot 		hsw_enable_pc8(dev_priv);
16178621f407SFrançois Tigeot 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
16188621f407SFrançois Tigeot 		ret = vlv_suspend_complete(dev_priv);
16198621f407SFrançois Tigeot 	}
16208621f407SFrançois Tigeot 
1621ba55f2f5SFrançois Tigeot 	if (ret) {
1622ba55f2f5SFrançois Tigeot 		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
16232c9916cdSFrançois Tigeot 		intel_runtime_pm_enable_interrupts(dev_priv);
1624ba55f2f5SFrançois Tigeot 
1625aee94f86SFrançois Tigeot 		enable_rpm_wakeref_asserts(dev_priv);
1626aee94f86SFrançois Tigeot 
1627ba55f2f5SFrançois Tigeot 		return ret;
1628ba55f2f5SFrançois Tigeot 	}
16299edbd4a0SFrançois Tigeot 
16302c9916cdSFrançois Tigeot 	intel_uncore_forcewake_reset(dev, false);
1631aee94f86SFrançois Tigeot 
1632aee94f86SFrançois Tigeot 	enable_rpm_wakeref_asserts(dev_priv);
1633aee94f86SFrançois Tigeot 	WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
1634c0e85e96SFrançois Tigeot 
1635c0e85e96SFrançois Tigeot 	if (intel_uncore_arm_unclaimed_mmio_detection(dev_priv))
1636c0e85e96SFrançois Tigeot 		DRM_ERROR("Unclaimed access detected prior to suspending\n");
1637c0e85e96SFrançois Tigeot 
16389edbd4a0SFrançois Tigeot 	dev_priv->pm.suspended = true;
16399edbd4a0SFrançois Tigeot 
16409edbd4a0SFrançois Tigeot 	/*
16411b13d190SFrançois Tigeot 	 * FIXME: We really should find a document that references the arguments
16421b13d190SFrançois Tigeot 	 * used below!
16431b13d190SFrançois Tigeot 	 */
1644a05eeebfSFrançois Tigeot 	if (IS_BROADWELL(dev)) {
1645a05eeebfSFrançois Tigeot 		/*
1646a05eeebfSFrançois Tigeot 		 * On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
1647a05eeebfSFrançois Tigeot 		 * being detected, and the call we do at intel_runtime_resume()
1648a05eeebfSFrançois Tigeot 		 * won't be able to restore them. Since PCI_D3hot matches the
1649a05eeebfSFrançois Tigeot 		 * actual specification and appears to be working, use it.
1650a05eeebfSFrançois Tigeot 		 */
1651a05eeebfSFrançois Tigeot 		intel_opregion_notify_adapter(dev, PCI_D3hot);
1652a05eeebfSFrançois Tigeot 	} else {
16531b13d190SFrançois Tigeot 		/*
16549edbd4a0SFrançois Tigeot 		 * current versions of firmware which depend on this opregion
16559edbd4a0SFrançois Tigeot 		 * notification have repurposed the D1 definition to mean
16569edbd4a0SFrançois Tigeot 		 * "runtime suspended" vs. what you would normally expect (D3)
16571b13d190SFrançois Tigeot 		 * to distinguish it from notifications that might be sent via
16581b13d190SFrançois Tigeot 		 * the suspend path.
16599edbd4a0SFrançois Tigeot 		 */
16609edbd4a0SFrançois Tigeot 		intel_opregion_notify_adapter(dev, PCI_D1);
16611b13d190SFrançois Tigeot 	}
16629edbd4a0SFrançois Tigeot 
16632c9916cdSFrançois Tigeot 	assert_forcewakes_inactive(dev_priv);
16642c9916cdSFrançois Tigeot 
16658621f407SFrançois Tigeot 	if (!IS_VALLEYVIEW(dev_priv) || !IS_CHERRYVIEW(dev_priv))
16668621f407SFrançois Tigeot 		intel_hpd_poll_init(dev_priv);
16678621f407SFrançois Tigeot 
1668ba55f2f5SFrançois Tigeot 	DRM_DEBUG_KMS("Device suspended\n");
16699edbd4a0SFrançois Tigeot 	return 0;
16709edbd4a0SFrançois Tigeot }
16719edbd4a0SFrançois Tigeot 
1672ba55f2f5SFrançois Tigeot static int intel_runtime_resume(struct device *device)
16739edbd4a0SFrançois Tigeot {
16749edbd4a0SFrançois Tigeot 	struct pci_dev *pdev = to_pci_dev(device);
16759edbd4a0SFrançois Tigeot 	struct drm_device *dev = pci_get_drvdata(pdev);
16769edbd4a0SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
16772c9916cdSFrançois Tigeot 	int ret = 0;
16789edbd4a0SFrançois Tigeot 
16791b13d190SFrançois Tigeot 	if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
16801b13d190SFrançois Tigeot 		return -ENODEV;
16819edbd4a0SFrançois Tigeot 
16829edbd4a0SFrançois Tigeot 	DRM_DEBUG_KMS("Resuming device\n");
16839edbd4a0SFrançois Tigeot 
1684aee94f86SFrançois Tigeot 	WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
1685aee94f86SFrançois Tigeot 	disable_rpm_wakeref_asserts(dev_priv);
1686aee94f86SFrançois Tigeot 
16879edbd4a0SFrançois Tigeot 	intel_opregion_notify_adapter(dev, PCI_D0);
16889edbd4a0SFrançois Tigeot 	dev_priv->pm.suspended = false;
1689c0e85e96SFrançois Tigeot 	if (intel_uncore_unclaimed_mmio(dev_priv))
1690c0e85e96SFrançois Tigeot 		DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n");
16919edbd4a0SFrançois Tigeot 
1692352ff8bdSFrançois Tigeot 	intel_guc_resume(dev);
1693352ff8bdSFrançois Tigeot 
16942c9916cdSFrançois Tigeot 	if (IS_GEN6(dev_priv))
16952c9916cdSFrançois Tigeot 		intel_init_pch_refclk(dev);
169619c468b4SFrançois Tigeot 
16978621f407SFrançois Tigeot 	if (IS_BROXTON(dev)) {
16988621f407SFrançois Tigeot 		bxt_disable_dc9(dev_priv);
16998621f407SFrançois Tigeot 		bxt_display_core_init(dev_priv, true);
17008621f407SFrançois Tigeot 		if (dev_priv->csr.dmc_payload &&
17018621f407SFrançois Tigeot 		    (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5))
17028621f407SFrançois Tigeot 			gen9_enable_dc5(dev_priv);
17038621f407SFrançois Tigeot 	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
17042c9916cdSFrançois Tigeot 		hsw_disable_pc8(dev_priv);
17058621f407SFrançois Tigeot 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
17062c9916cdSFrançois Tigeot 		ret = vlv_resume_prepare(dev_priv, true);
17078621f407SFrançois Tigeot 	}
17082c9916cdSFrançois Tigeot 
1709ba55f2f5SFrançois Tigeot 	/*
1710ba55f2f5SFrançois Tigeot 	 * No point of rolling back things in case of an error, as the best
1711ba55f2f5SFrançois Tigeot 	 * we can do is to hope that things will still work (and disable RPM).
1712ba55f2f5SFrançois Tigeot 	 */
1713ba55f2f5SFrançois Tigeot 	i915_gem_init_swizzling(dev);
1714ba55f2f5SFrançois Tigeot 	gen6_update_ring_freq(dev);
1715ba55f2f5SFrançois Tigeot 
17162c9916cdSFrançois Tigeot 	intel_runtime_pm_enable_interrupts(dev_priv);
1717352ff8bdSFrançois Tigeot 
1718352ff8bdSFrançois Tigeot 	/*
1719352ff8bdSFrançois Tigeot 	 * On VLV/CHV display interrupts are part of the display
1720352ff8bdSFrançois Tigeot 	 * power well, so hpd is reinitialized from there. For
1721352ff8bdSFrançois Tigeot 	 * everyone else do it here.
1722352ff8bdSFrançois Tigeot 	 */
1723aee94f86SFrançois Tigeot 	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
1724352ff8bdSFrançois Tigeot 		intel_hpd_init(dev_priv);
1725352ff8bdSFrançois Tigeot 
17262c9916cdSFrançois Tigeot 	intel_enable_gt_powersave(dev);
1727ba55f2f5SFrançois Tigeot 
1728aee94f86SFrançois Tigeot 	enable_rpm_wakeref_asserts(dev_priv);
1729aee94f86SFrançois Tigeot 
1730ba55f2f5SFrançois Tigeot 	if (ret)
1731ba55f2f5SFrançois Tigeot 		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
1732ba55f2f5SFrançois Tigeot 	else
1733ba55f2f5SFrançois Tigeot 		DRM_DEBUG_KMS("Device resumed\n");
1734ba55f2f5SFrançois Tigeot 
1735ba55f2f5SFrançois Tigeot 	return ret;
17369edbd4a0SFrançois Tigeot }
17379edbd4a0SFrançois Tigeot 
17389edbd4a0SFrançois Tigeot static const struct dev_pm_ops i915_pm_ops = {
17392c9916cdSFrançois Tigeot 	/*
17402c9916cdSFrançois Tigeot 	 * S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
17412c9916cdSFrançois Tigeot 	 * PMSG_RESUME]
17422c9916cdSFrançois Tigeot 	 */
17439edbd4a0SFrançois Tigeot 	.suspend = i915_pm_suspend,
17442c9916cdSFrançois Tigeot 	.suspend_late = i915_pm_suspend_late,
17452c9916cdSFrançois Tigeot 	.resume_early = i915_pm_resume_early,
17469edbd4a0SFrançois Tigeot 	.resume = i915_pm_resume,
17472c9916cdSFrançois Tigeot 
17482c9916cdSFrançois Tigeot 	/*
17492c9916cdSFrançois Tigeot 	 * S4 event handlers
17502c9916cdSFrançois Tigeot 	 * @freeze, @freeze_late    : called (1) before creating the
17512c9916cdSFrançois Tigeot 	 *                            hibernation image [PMSG_FREEZE] and
17522c9916cdSFrançois Tigeot 	 *                            (2) after rebooting, before restoring
17532c9916cdSFrançois Tigeot 	 *                            the image [PMSG_QUIESCE]
17542c9916cdSFrançois Tigeot 	 * @thaw, @thaw_early       : called (1) after creating the hibernation
17552c9916cdSFrançois Tigeot 	 *                            image, before writing it [PMSG_THAW]
17562c9916cdSFrançois Tigeot 	 *                            and (2) after failing to create or
17572c9916cdSFrançois Tigeot 	 *                            restore the image [PMSG_RECOVER]
17582c9916cdSFrançois Tigeot 	 * @poweroff, @poweroff_late: called after writing the hibernation
17592c9916cdSFrançois Tigeot 	 *                            image, before rebooting [PMSG_HIBERNATE]
17602c9916cdSFrançois Tigeot 	 * @restore, @restore_early : called after rebooting and restoring the
17612c9916cdSFrançois Tigeot 	 *                            hibernation image [PMSG_RESTORE]
17622c9916cdSFrançois Tigeot 	 */
17632c9916cdSFrançois Tigeot 	.freeze = i915_pm_suspend,
17642c9916cdSFrançois Tigeot 	.freeze_late = i915_pm_suspend_late,
17652c9916cdSFrançois Tigeot 	.thaw_early = i915_pm_resume_early,
17662c9916cdSFrançois Tigeot 	.thaw = i915_pm_resume,
17672c9916cdSFrançois Tigeot 	.poweroff = i915_pm_suspend,
17682c9916cdSFrançois Tigeot 	.poweroff_late = i915_pm_poweroff_late,
17692c9916cdSFrançois Tigeot 	.restore_early = i915_pm_resume_early,
17709edbd4a0SFrançois Tigeot 	.restore = i915_pm_resume,
17712c9916cdSFrançois Tigeot 
17722c9916cdSFrançois Tigeot 	/* S0ix (via runtime suspend) event handlers */
1773ba55f2f5SFrançois Tigeot 	.runtime_suspend = intel_runtime_suspend,
1774ba55f2f5SFrançois Tigeot 	.runtime_resume = intel_runtime_resume,
17759edbd4a0SFrançois Tigeot };
17769edbd4a0SFrançois Tigeot 
17779edbd4a0SFrançois Tigeot static const struct vm_operations_struct i915_gem_vm_ops = {
17789edbd4a0SFrançois Tigeot 	.fault = i915_gem_fault,
17799edbd4a0SFrançois Tigeot 	.open = drm_gem_vm_open,
17809edbd4a0SFrançois Tigeot 	.close = drm_gem_vm_close,
17819edbd4a0SFrançois Tigeot };
1782*922e7c40SFrançois Tigeot #endif
17839edbd4a0SFrançois Tigeot 
17849edbd4a0SFrançois Tigeot static const struct file_operations i915_driver_fops = {
17859edbd4a0SFrançois Tigeot 	.owner = THIS_MODULE,
1786*922e7c40SFrançois Tigeot #if 0
17879edbd4a0SFrançois Tigeot 	.open = drm_open,
17889edbd4a0SFrançois Tigeot 	.release = drm_release,
17899edbd4a0SFrançois Tigeot 	.unlocked_ioctl = drm_ioctl,
17909edbd4a0SFrançois Tigeot 	.mmap = drm_gem_mmap,
17919edbd4a0SFrançois Tigeot 	.poll = drm_poll,
17929edbd4a0SFrançois Tigeot 	.read = drm_read,
17939edbd4a0SFrançois Tigeot #ifdef CONFIG_COMPAT
17949edbd4a0SFrançois Tigeot 	.compat_ioctl = i915_compat_ioctl,
17959edbd4a0SFrançois Tigeot #endif
17969edbd4a0SFrançois Tigeot 	.llseek = noop_llseek,
17979edbd4a0SFrançois Tigeot #endif
1798*922e7c40SFrançois Tigeot };
17999edbd4a0SFrançois Tigeot 
1800e9587a4eSFrançois Tigeot static struct cdev_pager_ops i915_gem_vm_ops = {
1801e9587a4eSFrançois Tigeot 	.cdev_pg_fault	= i915_gem_fault,
1802e9587a4eSFrançois Tigeot 	.cdev_pg_ctor	= i915_gem_pager_ctor,
1803e9587a4eSFrançois Tigeot 	.cdev_pg_dtor	= i915_gem_pager_dtor
1804e9587a4eSFrançois Tigeot };
1805e9587a4eSFrançois Tigeot 
1806f0b54121SFrançois Tigeot static struct drm_driver driver = {
18079edbd4a0SFrançois Tigeot 	/* Don't use MTRRs here; the Xserver or userspace app should
18089edbd4a0SFrançois Tigeot 	 * deal with them for Intel hardware.
18099edbd4a0SFrançois Tigeot 	 */
18109edbd4a0SFrançois Tigeot 	.driver_features =
181163a4d045SFrançois Tigeot 	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
1812352ff8bdSFrançois Tigeot 	    DRIVER_RENDER | DRIVER_MODESET,
1813f0b54121SFrançois Tigeot 	.load = i915_driver_load,
181479f713b0SFrançois Tigeot 	.unload = i915_driver_unload,
1815ba55f2f5SFrançois Tigeot 	.open = i915_driver_open,
181679f713b0SFrançois Tigeot 	.lastclose = i915_driver_lastclose,
1817ba55f2f5SFrançois Tigeot 	.preclose = i915_driver_preclose,
1818f0b54121SFrançois Tigeot 	.postclose = i915_driver_postclose,
1819*922e7c40SFrançois Tigeot 	.set_busid = drm_pci_set_busid,
1820ba55f2f5SFrançois Tigeot 
18212c9916cdSFrançois Tigeot #if defined(CONFIG_DEBUG_FS)
18222c9916cdSFrançois Tigeot 	.debugfs_init = i915_debugfs_init,
18232c9916cdSFrançois Tigeot 	.debugfs_cleanup = i915_debugfs_cleanup,
18242c9916cdSFrançois Tigeot #endif
1825f0b54121SFrançois Tigeot 	.gem_free_object = i915_gem_free_object,
1826d4d73b30SFrançois Tigeot 	.gem_vm_ops = &i915_gem_vm_ops,
18272c9916cdSFrançois Tigeot 
1828*922e7c40SFrançois Tigeot 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
1829*922e7c40SFrançois Tigeot 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
1830*922e7c40SFrançois Tigeot 	.gem_prime_export = i915_gem_prime_export,
1831*922e7c40SFrançois Tigeot 	.gem_prime_import = i915_gem_prime_import,
1832*922e7c40SFrançois Tigeot 
1833f0b54121SFrançois Tigeot 	.dumb_create = i915_gem_dumb_create,
1834f0b54121SFrançois Tigeot 	.dumb_map_offset = i915_gem_mmap_gtt,
18359edbd4a0SFrançois Tigeot 	.dumb_destroy = drm_gem_dumb_destroy,
1836f0b54121SFrançois Tigeot 	.ioctls = i915_ioctls,
1837998e2cc6SPeeter Must 	.sysctl_init = i915_sysctl_init,
1838*922e7c40SFrançois Tigeot 	.fops = &i915_driver_fops,
1839f0b54121SFrançois Tigeot 	.name = DRIVER_NAME,
1840f0b54121SFrançois Tigeot 	.desc = DRIVER_DESC,
1841f0b54121SFrançois Tigeot 	.date = DRIVER_DATE,
1842f0b54121SFrançois Tigeot 	.major = DRIVER_MAJOR,
1843f0b54121SFrançois Tigeot 	.minor = DRIVER_MINOR,
1844f0b54121SFrançois Tigeot 	.patchlevel = DRIVER_PATCHLEVEL,
1845f0b54121SFrançois Tigeot };
1846f0b54121SFrançois Tigeot 
1847ba55f2f5SFrançois Tigeot static int __init i915_init(void);
1848ba55f2f5SFrançois Tigeot 
1849ba55f2f5SFrançois Tigeot static int
1850ba55f2f5SFrançois Tigeot i915_attach(device_t kdev)
1851ba55f2f5SFrançois Tigeot {
1852ba55f2f5SFrançois Tigeot 	struct drm_device *dev = device_get_softc(kdev);
1853bcd3cd8cSMatthew Dillon 	int error;
1854bcd3cd8cSMatthew Dillon 	int dummy;
1855ba55f2f5SFrançois Tigeot 
1856ba55f2f5SFrançois Tigeot 	dev->driver = &driver;
1857bcd3cd8cSMatthew Dillon 	error = drm_attach(kdev, i915_attach_list);
1858bcd3cd8cSMatthew Dillon 
1859bcd3cd8cSMatthew Dillon 	/*
1860bcd3cd8cSMatthew Dillon 	 * XXX hack - give the kvm_console time to come up before X starts
1861bcd3cd8cSMatthew Dillon 	 * messing with everything, avoiding at least one deadlock.
1862bcd3cd8cSMatthew Dillon 	 */
1863bcd3cd8cSMatthew Dillon 	tsleep(&dummy, 0, "i915_attach", hz*2);
1864bcd3cd8cSMatthew Dillon 
1865bcd3cd8cSMatthew Dillon 	return error;
1866ba55f2f5SFrançois Tigeot }
1867ba55f2f5SFrançois Tigeot 
1868a2fdbec6SFrançois Tigeot static device_method_t i915_methods[] = {
1869a2fdbec6SFrançois Tigeot 	/* Device interface */
1870a2fdbec6SFrançois Tigeot 	DEVMETHOD(device_probe,		i915_pci_probe),
1871a2fdbec6SFrançois Tigeot 	DEVMETHOD(device_attach,	i915_attach),
1872352ff8bdSFrançois Tigeot 	DEVMETHOD(device_suspend,	i915_suspend_switcheroo),
1873352ff8bdSFrançois Tigeot 	DEVMETHOD(device_resume,	i915_resume_switcheroo),
1874d0cc45b6SFrançois Tigeot 	DEVMETHOD(device_detach,	drm_release),
1875a2fdbec6SFrançois Tigeot 	DEVMETHOD_END
1876a2fdbec6SFrançois Tigeot };
1877a2fdbec6SFrançois Tigeot 
1878a2fdbec6SFrançois Tigeot static driver_t i915_driver = {
1879a2fdbec6SFrançois Tigeot 	"drm",
1880a2fdbec6SFrançois Tigeot 	i915_methods,
1881a2fdbec6SFrançois Tigeot 	sizeof(struct drm_device)
1882a2fdbec6SFrançois Tigeot };
1883a2fdbec6SFrançois Tigeot 
1884ba55f2f5SFrançois Tigeot static int __init i915_init(void)
1885ba55f2f5SFrançois Tigeot {
1886ba55f2f5SFrançois Tigeot 	driver.num_ioctls = i915_max_ioctl;
1887ba55f2f5SFrançois Tigeot 
1888ba55f2f5SFrançois Tigeot 	/*
1889a05eeebfSFrançois Tigeot 	 * Enable KMS by default, unless explicitly overriden by
1890a05eeebfSFrançois Tigeot 	 * either the i915.modeset prarameter or by the
1891a05eeebfSFrançois Tigeot 	 * vga_text_mode_force boot option.
1892ba55f2f5SFrançois Tigeot 	 */
1893a05eeebfSFrançois Tigeot 
1894a05eeebfSFrançois Tigeot 	if (i915.modeset == 0)
1895a05eeebfSFrançois Tigeot 		driver.driver_features &= ~DRIVER_MODESET;
1896ba55f2f5SFrançois Tigeot 
1897ba55f2f5SFrançois Tigeot 	if (vgacon_text_force() && i915.modeset == -1)
1898ba55f2f5SFrançois Tigeot 		driver.driver_features &= ~DRIVER_MODESET;
1899ba55f2f5SFrançois Tigeot 
1900ba55f2f5SFrançois Tigeot 	if (!(driver.driver_features & DRIVER_MODESET)) {
1901ba55f2f5SFrançois Tigeot 		/* Silently fail loading to not upset userspace. */
1902ba55f2f5SFrançois Tigeot 		DRM_DEBUG_DRIVER("KMS and UMS disabled.\n");
1903ba55f2f5SFrançois Tigeot 		return 0;
1904ba55f2f5SFrançois Tigeot 	}
1905ba55f2f5SFrançois Tigeot 
1906352ff8bdSFrançois Tigeot 	if (i915.nuclear_pageflip)
19072c9916cdSFrançois Tigeot 		driver.driver_features |= DRIVER_ATOMIC;
19082c9916cdSFrançois Tigeot 
1909ba55f2f5SFrançois Tigeot #if 0
1910ba55f2f5SFrançois Tigeot 	return drm_pci_init(&driver, &i915_pci_driver);
1911ba55f2f5SFrançois Tigeot #else
1912ba55f2f5SFrançois Tigeot 	return 1;
1913ba55f2f5SFrançois Tigeot #endif
1914ba55f2f5SFrançois Tigeot }
1915ba55f2f5SFrançois Tigeot 
1916477eb7f9SFrançois Tigeot #if 0
1917477eb7f9SFrançois Tigeot static void __exit i915_exit(void)
1918477eb7f9SFrançois Tigeot {
1919477eb7f9SFrançois Tigeot 	if (!(driver.driver_features & DRIVER_MODESET))
1920477eb7f9SFrançois Tigeot 		return; /* Never loaded a driver. */
1921477eb7f9SFrançois Tigeot 
1922477eb7f9SFrançois Tigeot 	drm_pci_exit(&driver, &i915_pci_driver);
1923477eb7f9SFrançois Tigeot }
1924477eb7f9SFrançois Tigeot #endif
1925477eb7f9SFrançois Tigeot 
1926bd1f95dfSFrançois Tigeot module_init(i915_init);
1927bd1f95dfSFrançois Tigeot 
19280e9fd563SFrançois Tigeot DRIVER_MODULE_ORDERED(i915, vgapci, i915_driver, drm_devclass, NULL, NULL, SI_ORDER_ANY);
19290e9fd563SFrançois Tigeot MODULE_DEPEND(i915, drm, 1, 1, 1);
19308035dd14SFrançois Tigeot #ifdef CONFIG_ACPI
19318035dd14SFrançois Tigeot MODULE_DEPEND(i915, acpi, 1, 1, 1);
19328035dd14SFrançois Tigeot #endif
1933