xref: /dflybsd-src/sys/dev/drm/i915/i915_drv.c (revision f0b541215c479d0172d1c9c0fe9baee6d69351ea)
1c4a9e910SFrançois Tigeot /* i915_drv.c -- Intel i915 driver -*- linux-c -*-
2c4a9e910SFrançois Tigeot  * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
3c4a9e910SFrançois Tigeot  */
4c4a9e910SFrançois Tigeot /*-
5c4a9e910SFrançois Tigeot  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6c4a9e910SFrançois Tigeot  * All Rights Reserved.
7c4a9e910SFrançois Tigeot  *
8c4a9e910SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
9c4a9e910SFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
10c4a9e910SFrançois Tigeot  * to deal in the Software without restriction, including without limitation
11c4a9e910SFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12c4a9e910SFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
13c4a9e910SFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
14c4a9e910SFrançois Tigeot  *
15c4a9e910SFrançois Tigeot  * The above copyright notice and this permission notice (including the next
16c4a9e910SFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
17c4a9e910SFrançois Tigeot  * Software.
18c4a9e910SFrançois Tigeot  *
19c4a9e910SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20c4a9e910SFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21c4a9e910SFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22c4a9e910SFrançois Tigeot  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23c4a9e910SFrançois Tigeot  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24c4a9e910SFrançois Tigeot  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25c4a9e910SFrançois Tigeot  * OTHER DEALINGS IN THE SOFTWARE.
26c4a9e910SFrançois Tigeot  *
27c4a9e910SFrançois Tigeot  * Authors:
28c4a9e910SFrançois Tigeot  *    Gareth Hughes <gareth@valinux.com>
29c4a9e910SFrançois Tigeot  *
30e3adcf8fSFrançois Tigeot  * $FreeBSD: src/sys/dev/drm2/i915/i915_drv.c,v 1.1 2012/05/22 11:07:44 kib Exp $
31c4a9e910SFrançois Tigeot  */
32c4a9e910SFrançois Tigeot 
3318e26a6dSFrançois Tigeot #include <drm/drmP.h>
345c6c6f23SFrançois Tigeot #include <drm/i915_drm.h>
35c4a9e910SFrançois Tigeot #include "i915_drv.h"
3618e26a6dSFrançois Tigeot #include <drm/drm_pciids.h>
37e3adcf8fSFrançois Tigeot #include "intel_drv.h"
38c4a9e910SFrançois Tigeot 
3919df918dSFrançois Tigeot /*		 "Specify LVDS channel mode "
4019df918dSFrançois Tigeot 		 "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)" */
4119df918dSFrançois Tigeot int i915_lvds_channel_mode __read_mostly = 0;
4219df918dSFrançois Tigeot TUNABLE_INT("drm.i915.lvds_channel_mode", &i915_lvds_channel_mode);
4319df918dSFrançois Tigeot 
44*f0b54121SFrançois Tigeot static struct drm_driver driver;
45*f0b54121SFrançois Tigeot 
46e9243325SFrançois Tigeot #define INTEL_VGA_DEVICE(id, info_) {		\
47e9243325SFrançois Tigeot 	.device = id,				\
48e9243325SFrançois Tigeot 	.info = info_,				\
49e9243325SFrançois Tigeot }
50e9243325SFrançois Tigeot 
51e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i830_info = {
52e3adcf8fSFrançois Tigeot 	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1,
53e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
54e3adcf8fSFrançois Tigeot };
55c4a9e910SFrançois Tigeot 
56e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_845g_info = {
57e3adcf8fSFrançois Tigeot 	.gen = 2,
58e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
59e3adcf8fSFrançois Tigeot };
60e3adcf8fSFrançois Tigeot 
61e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i85x_info = {
62e3adcf8fSFrançois Tigeot 	.gen = 2, .is_i85x = 1, .is_mobile = 1,
63e3adcf8fSFrançois Tigeot 	.cursor_needs_physical = 1,
64e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
65e3adcf8fSFrançois Tigeot };
66e3adcf8fSFrançois Tigeot 
67e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i865g_info = {
68e3adcf8fSFrançois Tigeot 	.gen = 2,
69e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
70e3adcf8fSFrançois Tigeot };
71e3adcf8fSFrançois Tigeot 
72e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i915g_info = {
73e3adcf8fSFrançois Tigeot 	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1,
74e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
75e3adcf8fSFrançois Tigeot };
76e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i915gm_info = {
77e3adcf8fSFrançois Tigeot 	.gen = 3, .is_mobile = 1,
78e3adcf8fSFrançois Tigeot 	.cursor_needs_physical = 1,
79e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
80e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
81e3adcf8fSFrançois Tigeot };
82e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i945g_info = {
83e3adcf8fSFrançois Tigeot 	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1,
84e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
85e3adcf8fSFrançois Tigeot };
86e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i945gm_info = {
87e3adcf8fSFrançois Tigeot 	.gen = 3, .is_i945gm = 1, .is_mobile = 1,
88e3adcf8fSFrançois Tigeot 	.has_hotplug = 1, .cursor_needs_physical = 1,
89e3adcf8fSFrançois Tigeot 	.has_overlay = 1, .overlay_needs_physical = 1,
90e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
91e3adcf8fSFrançois Tigeot };
92e3adcf8fSFrançois Tigeot 
93e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i965g_info = {
94e3adcf8fSFrançois Tigeot 	.gen = 4, .is_broadwater = 1,
95e3adcf8fSFrançois Tigeot 	.has_hotplug = 1,
96e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
97e3adcf8fSFrançois Tigeot };
98e3adcf8fSFrançois Tigeot 
99e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_i965gm_info = {
100e3adcf8fSFrançois Tigeot 	.gen = 4, .is_crestline = 1,
101e3adcf8fSFrançois Tigeot 	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,
102e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
103e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
104e3adcf8fSFrançois Tigeot };
105e3adcf8fSFrançois Tigeot 
106e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_g33_info = {
107e3adcf8fSFrançois Tigeot 	.gen = 3, .is_g33 = 1,
108e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
109e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
110e3adcf8fSFrançois Tigeot };
111e3adcf8fSFrançois Tigeot 
112e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_g45_info = {
113e3adcf8fSFrançois Tigeot 	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1,
114e3adcf8fSFrançois Tigeot 	.has_pipe_cxsr = 1, .has_hotplug = 1,
115e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
116e3adcf8fSFrançois Tigeot };
117e3adcf8fSFrançois Tigeot 
118e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_gm45_info = {
119e3adcf8fSFrançois Tigeot 	.gen = 4, .is_g4x = 1,
120e3adcf8fSFrançois Tigeot 	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,
121e3adcf8fSFrançois Tigeot 	.has_pipe_cxsr = 1, .has_hotplug = 1,
122e3adcf8fSFrançois Tigeot 	.supports_tv = 1,
123e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
124e3adcf8fSFrançois Tigeot };
125e3adcf8fSFrançois Tigeot 
126e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_pineview_info = {
127e3adcf8fSFrançois Tigeot 	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1,
128e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
129e3adcf8fSFrançois Tigeot 	.has_overlay = 1,
130e3adcf8fSFrançois Tigeot };
131e3adcf8fSFrançois Tigeot 
132e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ironlake_d_info = {
133e3adcf8fSFrançois Tigeot 	.gen = 5,
134e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
135e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
136e3adcf8fSFrançois Tigeot };
137e3adcf8fSFrançois Tigeot 
138e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ironlake_m_info = {
139e3adcf8fSFrançois Tigeot 	.gen = 5, .is_mobile = 1,
140e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
14100dca1bbSFrançois Tigeot 	.has_fbc = 1,
142e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
143e3adcf8fSFrançois Tigeot };
144e3adcf8fSFrançois Tigeot 
145e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_sandybridge_d_info = {
146e3adcf8fSFrançois Tigeot 	.gen = 6,
147e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
148e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
149e3adcf8fSFrançois Tigeot 	.has_blt_ring = 1,
150e3adcf8fSFrançois Tigeot 	.has_llc = 1,
151e9243325SFrançois Tigeot 	.has_force_wake = 1,
152e3adcf8fSFrançois Tigeot };
153e3adcf8fSFrançois Tigeot 
154e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_sandybridge_m_info = {
155e3adcf8fSFrançois Tigeot 	.gen = 6, .is_mobile = 1,
156e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
157e3adcf8fSFrançois Tigeot 	.has_fbc = 1,
158e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
159e3adcf8fSFrançois Tigeot 	.has_blt_ring = 1,
160e3adcf8fSFrançois Tigeot 	.has_llc = 1,
161e9243325SFrançois Tigeot 	.has_force_wake = 1,
162e3adcf8fSFrançois Tigeot };
163e3adcf8fSFrançois Tigeot 
164e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ivybridge_d_info = {
165e3adcf8fSFrançois Tigeot 	.is_ivybridge = 1, .gen = 7,
166e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
167e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
168e3adcf8fSFrançois Tigeot 	.has_blt_ring = 1,
169e3adcf8fSFrançois Tigeot 	.has_llc = 1,
170e9243325SFrançois Tigeot 	.has_force_wake = 1,
171e3adcf8fSFrançois Tigeot };
172e3adcf8fSFrançois Tigeot 
173e3adcf8fSFrançois Tigeot static const struct intel_device_info intel_ivybridge_m_info = {
174e3adcf8fSFrançois Tigeot 	.is_ivybridge = 1, .gen = 7, .is_mobile = 1,
175e3adcf8fSFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
176e3adcf8fSFrançois Tigeot 	.has_fbc = 0,	/* FBC is not enabled on Ivybridge mobile yet */
177e3adcf8fSFrançois Tigeot 	.has_bsd_ring = 1,
178e3adcf8fSFrançois Tigeot 	.has_blt_ring = 1,
179e3adcf8fSFrançois Tigeot 	.has_llc = 1,
180e9243325SFrançois Tigeot 	.has_force_wake = 1,
181e3adcf8fSFrançois Tigeot };
182e3adcf8fSFrançois Tigeot 
183e9243325SFrançois Tigeot static const struct intel_device_info intel_valleyview_m_info = {
184e9243325SFrançois Tigeot 	.gen = 7, .is_mobile = 1,
185e9243325SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
186e9243325SFrançois Tigeot 	.has_fbc = 0,
187e9243325SFrançois Tigeot 	.has_bsd_ring = 1,
188e9243325SFrançois Tigeot 	.has_blt_ring = 1,
189e9243325SFrançois Tigeot 	.is_valleyview = 1,
190e9243325SFrançois Tigeot };
191e9243325SFrançois Tigeot 
192e9243325SFrançois Tigeot static const struct intel_device_info intel_valleyview_d_info = {
193e9243325SFrançois Tigeot 	.gen = 7,
194e9243325SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
195e9243325SFrançois Tigeot 	.has_fbc = 0,
196e9243325SFrançois Tigeot 	.has_bsd_ring = 1,
197e9243325SFrançois Tigeot 	.has_blt_ring = 1,
198e9243325SFrançois Tigeot 	.is_valleyview = 1,
199e9243325SFrançois Tigeot };
200e9243325SFrançois Tigeot 
201e9243325SFrançois Tigeot static const struct intel_device_info intel_haswell_d_info = {
202e9243325SFrançois Tigeot 	.is_haswell = 1, .gen = 7,
203e9243325SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
204e9243325SFrançois Tigeot 	.has_bsd_ring = 1,
205e9243325SFrançois Tigeot 	.has_blt_ring = 1,
206e9243325SFrançois Tigeot 	.has_llc = 1,
207e9243325SFrançois Tigeot 	.has_force_wake = 1,
208e9243325SFrançois Tigeot };
209e9243325SFrançois Tigeot 
210e9243325SFrançois Tigeot static const struct intel_device_info intel_haswell_m_info = {
211e9243325SFrançois Tigeot 	.is_haswell = 1, .gen = 7, .is_mobile = 1,
212e9243325SFrançois Tigeot 	.need_gfx_hws = 1, .has_hotplug = 1,
213e9243325SFrançois Tigeot 	.has_bsd_ring = 1,
214e9243325SFrançois Tigeot 	.has_blt_ring = 1,
215e9243325SFrançois Tigeot 	.has_llc = 1,
216e9243325SFrançois Tigeot 	.has_force_wake = 1,
217e9243325SFrançois Tigeot };
218e3adcf8fSFrançois Tigeot 
219e3adcf8fSFrançois Tigeot static const struct intel_gfx_device_id {
220e3adcf8fSFrançois Tigeot 	int device;
221e3adcf8fSFrançois Tigeot 	const struct intel_device_info *info;
222e3adcf8fSFrançois Tigeot } pciidlist[] = {		/* aka */
223e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),		/* I830_M */
224e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),		/* 845_G */
225e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),		/* I855_GM */
226e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
227e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),		/* I865_G */
228e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),		/* I915_G */
229e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),		/* E7221_G */
230e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),		/* I915_GM */
231e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),		/* I945_G */
232e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),		/* I945_GM */
233e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),		/* I945_GME */
234e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),		/* I946_GZ */
235e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),		/* G35_G */
236e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),		/* I965_Q */
237e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),		/* I965_G */
238e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),		/* Q35_G */
239e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),		/* G33_G */
240e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),		/* Q33_G */
241e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),		/* I965_GM */
242e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),		/* I965_GME */
243e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),		/* GM45_G */
244e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),		/* IGD_E_G */
245e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),		/* Q45_G */
246e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),		/* G45_G */
247e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),		/* G41_G */
248e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),		/* B43_G */
249e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x2e92, &intel_g45_info),		/* B43_G.1 */
250e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
251e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
252e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
253e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
254e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
255e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info),
256e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info),
257e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
258e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
259e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
260e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
261e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0156, &intel_ivybridge_m_info), /* GT1 mobile */
262e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0166, &intel_ivybridge_m_info), /* GT2 mobile */
263e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
264e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
265e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
266e3adcf8fSFrançois Tigeot 	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
267e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
268e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
269e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */
270e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */
271e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */
272e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */
273e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
274e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
275e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */
276e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */
277e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */
278e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */
279e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */
280e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */
281e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */
282e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */
283e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */
284e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */
285e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */
286e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */
287e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */
288e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */
289e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */
290e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */
291e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
292e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
293e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */
294e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */
295e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */
296e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */
297e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */
298e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */
299e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */
300e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */
301e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
302e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
303e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
304e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
305e9243325SFrançois Tigeot 	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
306e3adcf8fSFrançois Tigeot 	{0, 0}
307e3adcf8fSFrançois Tigeot };
308e3adcf8fSFrançois Tigeot 
309e9243325SFrançois Tigeot #define	PCI_VENDOR_INTEL	0x8086
310e9243325SFrançois Tigeot 
311e9243325SFrançois Tigeot void intel_detect_pch(struct drm_device *dev)
312e9243325SFrançois Tigeot {
313e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
314e9243325SFrançois Tigeot 	device_t pch;
315e9243325SFrançois Tigeot 
316e9243325SFrançois Tigeot 	/*
317e9243325SFrançois Tigeot 	 * The reason to probe ISA bridge instead of Dev31:Fun0 is to
318e9243325SFrançois Tigeot 	 * make graphics device passthrough work easy for VMM, that only
319e9243325SFrançois Tigeot 	 * need to expose ISA bridge to let driver know the real hardware
320e9243325SFrançois Tigeot 	 * underneath. This is a requirement from virtualization team.
321e9243325SFrançois Tigeot 	 */
322e9243325SFrançois Tigeot 	pch = pci_find_class(PCIC_BRIDGE, PCIS_BRIDGE_ISA);
323e9243325SFrançois Tigeot 	if (pch) {
324e9243325SFrançois Tigeot 		if (pci_get_vendor(pch) == PCI_VENDOR_INTEL) {
325e9243325SFrançois Tigeot 			unsigned short id;
326e9243325SFrançois Tigeot 			id = pci_get_device(pch) & INTEL_PCH_DEVICE_ID_MASK;
327e9243325SFrançois Tigeot 			dev_priv->pch_id = id;
328e9243325SFrançois Tigeot 
329e9243325SFrançois Tigeot 			if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
330e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_IBX;
331e9243325SFrançois Tigeot 				dev_priv->num_pch_pll = 2;
332e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
333e9243325SFrançois Tigeot 				WARN_ON(!IS_GEN5(dev));
334e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
335e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_CPT;
336e9243325SFrançois Tigeot 				dev_priv->num_pch_pll = 2;
337e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found CougarPoint PCH\n");
338e9243325SFrançois Tigeot 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
339e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
340e9243325SFrançois Tigeot 				/* PantherPoint is CPT compatible */
341e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_CPT;
342e9243325SFrançois Tigeot 				dev_priv->num_pch_pll = 2;
343e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found PatherPoint PCH\n");
344e9243325SFrançois Tigeot 				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
345e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
346e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_LPT;
347e9243325SFrançois Tigeot 				dev_priv->num_pch_pll = 0;
348e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
349e9243325SFrançois Tigeot 				WARN_ON(!IS_HASWELL(dev));
350e9243325SFrançois Tigeot 			} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
351e9243325SFrançois Tigeot 				dev_priv->pch_type = PCH_LPT;
352e9243325SFrançois Tigeot 				dev_priv->num_pch_pll = 0;
353e9243325SFrançois Tigeot 				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
354e9243325SFrançois Tigeot 				WARN_ON(!IS_HASWELL(dev));
355e9243325SFrançois Tigeot 			}
356e9243325SFrançois Tigeot 			BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
357e9243325SFrançois Tigeot 		}
358e9243325SFrançois Tigeot #if 0
359e9243325SFrançois Tigeot 		pci_dev_put(pch);
360e9243325SFrançois Tigeot #endif
361e9243325SFrançois Tigeot 	}
362e9243325SFrançois Tigeot }
363e9243325SFrançois Tigeot 
3643d4007e0SFrançois Tigeot bool i915_semaphore_is_enabled(struct drm_device *dev)
3653d4007e0SFrançois Tigeot {
3663d4007e0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen < 6)
3673d4007e0SFrançois Tigeot 		return 0;
3683d4007e0SFrançois Tigeot 
3693d4007e0SFrançois Tigeot 	if (i915_semaphores >= 0)
3703d4007e0SFrançois Tigeot 		return i915_semaphores;
3713d4007e0SFrançois Tigeot 
3723d4007e0SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
3733d4007e0SFrançois Tigeot 	/* Enable semaphores on SNB when IO remapping is off */
3743d4007e0SFrançois Tigeot 	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
3753d4007e0SFrançois Tigeot 		return false;
3763d4007e0SFrançois Tigeot #endif
3773d4007e0SFrançois Tigeot 
3783d4007e0SFrançois Tigeot 	return 1;
3793d4007e0SFrançois Tigeot }
3803d4007e0SFrançois Tigeot 
381e3adcf8fSFrançois Tigeot static int i915_drm_freeze(struct drm_device *dev)
382e3adcf8fSFrançois Tigeot {
383e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
384e3adcf8fSFrançois Tigeot 
385e3adcf8fSFrançois Tigeot 	drm_kms_helper_poll_disable(dev);
386e3adcf8fSFrançois Tigeot 
387e3adcf8fSFrançois Tigeot #if 0
388e3adcf8fSFrançois Tigeot 	pci_save_state(dev->pdev);
389e3adcf8fSFrançois Tigeot #endif
390e3adcf8fSFrançois Tigeot 
391e3adcf8fSFrançois Tigeot 	/* If KMS is active, we do the leavevt stuff here */
392e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
393e9243325SFrançois Tigeot 		int error = i915_gem_idle(dev);
394e3adcf8fSFrançois Tigeot 		if (error) {
3956df74fa7SFrançois Tigeot 			device_printf(dev->dev,
396e9243325SFrançois Tigeot 				"GEM idle failed, resume might fail");
397e9243325SFrançois Tigeot 			return error;
398e3adcf8fSFrançois Tigeot 		}
399e9243325SFrançois Tigeot 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
400e9243325SFrançois Tigeot 
401e9243325SFrançois Tigeot #if 0
402e9243325SFrançois Tigeot 		intel_modeset_disable(dev);
403e9243325SFrançois Tigeot #endif
404e9243325SFrançois Tigeot 
405e3adcf8fSFrançois Tigeot 		drm_irq_uninstall(dev);
406e3adcf8fSFrançois Tigeot 	}
407e3adcf8fSFrançois Tigeot 
408e3adcf8fSFrançois Tigeot 	i915_save_state(dev);
409e3adcf8fSFrançois Tigeot 
410e3adcf8fSFrançois Tigeot 	intel_opregion_fini(dev);
411e3adcf8fSFrançois Tigeot 
412e3adcf8fSFrançois Tigeot 	/* Modeset on resume, not lid events */
413e3adcf8fSFrançois Tigeot 	dev_priv->modeset_on_lid = 0;
414e3adcf8fSFrançois Tigeot 
415e3adcf8fSFrançois Tigeot 	return 0;
416e3adcf8fSFrançois Tigeot }
417e3adcf8fSFrançois Tigeot 
418e3adcf8fSFrançois Tigeot static int
419e3adcf8fSFrançois Tigeot i915_suspend(device_t kdev)
420e3adcf8fSFrançois Tigeot {
421e3adcf8fSFrançois Tigeot 	struct drm_device *dev;
422e3adcf8fSFrançois Tigeot 	int error;
423e3adcf8fSFrançois Tigeot 
424e3adcf8fSFrançois Tigeot 	dev = device_get_softc(kdev);
425e3adcf8fSFrançois Tigeot 	if (dev == NULL || dev->dev_private == NULL) {
426c4a9e910SFrançois Tigeot 		DRM_ERROR("DRM not initialized, aborting suspend.\n");
427c4a9e910SFrançois Tigeot 		return -ENODEV;
428c4a9e910SFrançois Tigeot 	}
429c4a9e910SFrançois Tigeot 
430e3adcf8fSFrançois Tigeot 	DRM_DEBUG_KMS("starting suspend\n");
431e3adcf8fSFrançois Tigeot 	error = i915_drm_freeze(dev);
432e3adcf8fSFrançois Tigeot 	if (error)
433e3adcf8fSFrançois Tigeot 		return (error);
434c4a9e910SFrançois Tigeot 
435e3adcf8fSFrançois Tigeot 	error = bus_generic_suspend(kdev);
436e3adcf8fSFrançois Tigeot 	DRM_DEBUG_KMS("finished suspend %d\n", error);
437e3adcf8fSFrançois Tigeot 	return (error);
438c4a9e910SFrançois Tigeot }
439c4a9e910SFrançois Tigeot 
440e3adcf8fSFrançois Tigeot static int i915_drm_thaw(struct drm_device *dev)
441c4a9e910SFrançois Tigeot {
442e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
443e3adcf8fSFrançois Tigeot 	int error = 0;
444c4a9e910SFrançois Tigeot 
44519df918dSFrançois Tigeot 	intel_gt_reset(dev);
44619df918dSFrançois Tigeot 
447e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
44819df918dSFrançois Tigeot 		DRM_LOCK(dev);
449e3adcf8fSFrançois Tigeot 		i915_gem_restore_gtt_mappings(dev);
45019df918dSFrançois Tigeot 		DRM_UNLOCK(dev);
451e3adcf8fSFrançois Tigeot 	}
452e3adcf8fSFrançois Tigeot 
453c4a9e910SFrançois Tigeot 	i915_restore_state(dev);
454e3adcf8fSFrançois Tigeot 	intel_opregion_setup(dev);
455c4a9e910SFrançois Tigeot 
456e3adcf8fSFrançois Tigeot 	/* KMS EnterVT equivalent */
457e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
45819df918dSFrançois Tigeot 		intel_init_pch_refclk(dev);
45919df918dSFrançois Tigeot 
46019df918dSFrançois Tigeot 		DRM_LOCK(dev);
461e3adcf8fSFrançois Tigeot 		dev_priv->mm.suspended = 0;
462e3adcf8fSFrançois Tigeot 
463e3adcf8fSFrançois Tigeot 		error = i915_gem_init_hw(dev);
464e3adcf8fSFrançois Tigeot 		DRM_UNLOCK(dev);
46519df918dSFrançois Tigeot 
46619df918dSFrançois Tigeot 		intel_modeset_init_hw(dev);
46719df918dSFrançois Tigeot 		intel_modeset_setup_hw_state(dev, false);
468e3adcf8fSFrançois Tigeot 		drm_irq_install(dev);
469c4a9e910SFrançois Tigeot 	}
470c4a9e910SFrançois Tigeot 
471e3adcf8fSFrançois Tigeot 	intel_opregion_init(dev);
472e3adcf8fSFrançois Tigeot 
473e3adcf8fSFrançois Tigeot 	dev_priv->modeset_on_lid = 0;
474e3adcf8fSFrançois Tigeot 
47519df918dSFrançois Tigeot #if 0
47619df918dSFrançois Tigeot 	console_lock();
47719df918dSFrançois Tigeot 	intel_fbdev_set_suspend(dev, 0);
47819df918dSFrançois Tigeot 	console_unlock();
47919df918dSFrançois Tigeot #endif
480e3adcf8fSFrançois Tigeot 	return error;
481e3adcf8fSFrançois Tigeot }
482e3adcf8fSFrançois Tigeot 
483e3adcf8fSFrançois Tigeot static int
484e3adcf8fSFrançois Tigeot i915_resume(device_t kdev)
485c4a9e910SFrançois Tigeot {
486e3adcf8fSFrançois Tigeot 	struct drm_device *dev;
487e3adcf8fSFrançois Tigeot 	int ret;
488c4a9e910SFrançois Tigeot 
489e3adcf8fSFrançois Tigeot 	dev = device_get_softc(kdev);
490e3adcf8fSFrançois Tigeot 	DRM_DEBUG_KMS("starting resume\n");
491e3adcf8fSFrançois Tigeot #if 0
492e3adcf8fSFrançois Tigeot 	if (pci_enable_device(dev->pdev))
493e3adcf8fSFrançois Tigeot 		return -EIO;
494c4a9e910SFrançois Tigeot 
495e3adcf8fSFrançois Tigeot 	pci_set_master(dev->pdev);
496e3adcf8fSFrançois Tigeot #endif
497c4a9e910SFrançois Tigeot 
498e3adcf8fSFrançois Tigeot 	ret = -i915_drm_thaw(dev);
499e3adcf8fSFrançois Tigeot 	if (ret != 0)
500e3adcf8fSFrançois Tigeot 		return (ret);
501e3adcf8fSFrançois Tigeot 
502e3adcf8fSFrançois Tigeot 	drm_kms_helper_poll_enable(dev);
503e3adcf8fSFrançois Tigeot 	ret = bus_generic_resume(kdev);
504e3adcf8fSFrançois Tigeot 	DRM_DEBUG_KMS("finished resume %d\n", ret);
505e3adcf8fSFrançois Tigeot 	return (ret);
506c4a9e910SFrançois Tigeot }
507c4a9e910SFrançois Tigeot 
50862e5f8e8SFrançois Tigeot /* XXX Hack for the old *BSD drm code base
50962e5f8e8SFrançois Tigeot  * The device id field is set at probe time */
51062e5f8e8SFrançois Tigeot static drm_pci_id_list_t i915_attach_list[] = {
51162e5f8e8SFrançois Tigeot 	{0x8086, 0, 0, "Intel i915 GPU"},
51262e5f8e8SFrançois Tigeot 	{0, 0, 0, NULL}
51362e5f8e8SFrançois Tigeot };
51462e5f8e8SFrançois Tigeot 
515c4a9e910SFrançois Tigeot static int
516c4a9e910SFrançois Tigeot i915_probe(device_t kdev)
517c4a9e910SFrançois Tigeot {
51862e5f8e8SFrançois Tigeot 	int device, i = 0;
519e3adcf8fSFrançois Tigeot 
52062e5f8e8SFrançois Tigeot 	if (pci_get_class(kdev) != PCIC_DISPLAY)
52162e5f8e8SFrançois Tigeot 		return ENXIO;
52262e5f8e8SFrançois Tigeot 
52362e5f8e8SFrançois Tigeot 	if (pci_get_vendor(kdev) != PCI_VENDOR_INTEL)
52462e5f8e8SFrançois Tigeot 		return ENXIO;
52562e5f8e8SFrançois Tigeot 
52662e5f8e8SFrançois Tigeot 	device = pci_get_device(kdev);
52762e5f8e8SFrançois Tigeot 
52862e5f8e8SFrançois Tigeot 	for (i = 0; pciidlist[i].device != 0; i++) {
52962e5f8e8SFrançois Tigeot 		if (pciidlist[i].device == device) {
53062e5f8e8SFrançois Tigeot 			i915_attach_list[0].device = device;
53162e5f8e8SFrançois Tigeot 			return 0;
53262e5f8e8SFrançois Tigeot 		}
53362e5f8e8SFrançois Tigeot 	}
53462e5f8e8SFrançois Tigeot 
53562e5f8e8SFrançois Tigeot 	return ENXIO;
536c4a9e910SFrançois Tigeot }
537c4a9e910SFrançois Tigeot 
538e3adcf8fSFrançois Tigeot int i915_modeset;
539e3adcf8fSFrançois Tigeot 
540*f0b54121SFrançois Tigeot /* static int __init i915_init(void) */
541c4a9e910SFrançois Tigeot static int
542c4a9e910SFrançois Tigeot i915_attach(device_t kdev)
543c4a9e910SFrançois Tigeot {
544e3adcf8fSFrançois Tigeot 	struct drm_device *dev;
545c4a9e910SFrançois Tigeot 
546e3adcf8fSFrançois Tigeot 	dev = device_get_softc(kdev);
547*f0b54121SFrançois Tigeot 
548*f0b54121SFrançois Tigeot 	driver.num_ioctls = i915_max_ioctl;
549*f0b54121SFrançois Tigeot 
550e3adcf8fSFrançois Tigeot 	if (i915_modeset == 1)
551*f0b54121SFrançois Tigeot 		driver.driver_features |= DRIVER_MODESET;
552*f0b54121SFrançois Tigeot 
553*f0b54121SFrançois Tigeot 	dev->driver = &driver;
55462e5f8e8SFrançois Tigeot 	return (drm_attach(kdev, i915_attach_list));
555c4a9e910SFrançois Tigeot }
556c4a9e910SFrançois Tigeot 
557e3adcf8fSFrançois Tigeot const struct intel_device_info *
558e3adcf8fSFrançois Tigeot i915_get_device_id(int device)
559c4a9e910SFrançois Tigeot {
560e3adcf8fSFrançois Tigeot 	const struct intel_gfx_device_id *did;
561c4a9e910SFrançois Tigeot 
562e3adcf8fSFrançois Tigeot 	for (did = &pciidlist[0]; did->device != 0; did++) {
563e3adcf8fSFrançois Tigeot 		if (did->device != device)
564e3adcf8fSFrançois Tigeot 			continue;
565e3adcf8fSFrançois Tigeot 		return (did->info);
566e3adcf8fSFrançois Tigeot 	}
567e3adcf8fSFrançois Tigeot 	return (NULL);
568c4a9e910SFrançois Tigeot }
569c4a9e910SFrançois Tigeot 
570c4a9e910SFrançois Tigeot static device_method_t i915_methods[] = {
571c4a9e910SFrançois Tigeot 	/* Device interface */
572c4a9e910SFrançois Tigeot 	DEVMETHOD(device_probe,		i915_probe),
573c4a9e910SFrançois Tigeot 	DEVMETHOD(device_attach,	i915_attach),
574c4a9e910SFrançois Tigeot 	DEVMETHOD(device_suspend,	i915_suspend),
575c4a9e910SFrançois Tigeot 	DEVMETHOD(device_resume,	i915_resume),
576e3adcf8fSFrançois Tigeot 	DEVMETHOD(device_detach,	drm_detach),
577d3c9c58eSSascha Wildner 	DEVMETHOD_END
578c4a9e910SFrançois Tigeot };
579c4a9e910SFrançois Tigeot 
580c4a9e910SFrançois Tigeot static driver_t i915_driver = {
581c4a9e910SFrançois Tigeot 	"drm",
582c4a9e910SFrançois Tigeot 	i915_methods,
583c4a9e910SFrançois Tigeot 	sizeof(struct drm_device)
584c4a9e910SFrançois Tigeot };
585c4a9e910SFrançois Tigeot 
586c4a9e910SFrançois Tigeot extern devclass_t drm_devclass;
587e3adcf8fSFrançois Tigeot DRIVER_MODULE_ORDERED(i915kms, vgapci, i915_driver, drm_devclass, 0, 0,
588e3adcf8fSFrançois Tigeot     SI_ORDER_ANY);
589e3adcf8fSFrançois Tigeot MODULE_DEPEND(i915kms, drm, 1, 1, 1);
590e3adcf8fSFrançois Tigeot MODULE_DEPEND(i915kms, agp, 1, 1, 1);
591e3adcf8fSFrançois Tigeot MODULE_DEPEND(i915kms, iicbus, 1, 1, 1);
592e3adcf8fSFrançois Tigeot MODULE_DEPEND(i915kms, iic, 1, 1, 1);
593e3adcf8fSFrançois Tigeot MODULE_DEPEND(i915kms, iicbb, 1, 1, 1);
594e3adcf8fSFrançois Tigeot 
595e3adcf8fSFrançois Tigeot int intel_iommu_enabled = 0;
596e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.intel_iommu_enabled", &intel_iommu_enabled);
597e3adcf8fSFrançois Tigeot 
598e3adcf8fSFrançois Tigeot int i915_semaphores = -1;
599e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.semaphores", &i915_semaphores);
600e3adcf8fSFrançois Tigeot static int i915_try_reset = 1;
601e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.try_reset", &i915_try_reset);
602e3adcf8fSFrançois Tigeot unsigned int i915_lvds_downclock = 0;
603e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.lvds_downclock", &i915_lvds_downclock);
604e3adcf8fSFrançois Tigeot int i915_vbt_sdvo_panel_type = -1;
605e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.vbt_sdvo_panel_type", &i915_vbt_sdvo_panel_type);
606e3adcf8fSFrançois Tigeot unsigned int i915_powersave = 1;
607e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.powersave", &i915_powersave);
608e3adcf8fSFrançois Tigeot int i915_enable_fbc = 0;
609e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.enable_fbc", &i915_enable_fbc);
610e3adcf8fSFrançois Tigeot int i915_enable_rc6 = 0;
611e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.enable_rc6", &i915_enable_rc6);
612e3adcf8fSFrançois Tigeot int i915_panel_use_ssc = -1;
613e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.panel_use_ssc", &i915_panel_use_ssc);
614e3adcf8fSFrançois Tigeot int i915_panel_ignore_lid = 0;
615e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.panel_ignore_lid", &i915_panel_ignore_lid);
616e3adcf8fSFrançois Tigeot int i915_modeset = 1;
617e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.modeset", &i915_modeset);
618e3adcf8fSFrançois Tigeot int i915_enable_ppgtt = -1;
619e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.enable_ppgtt", &i915_enable_ppgtt);
620e3adcf8fSFrançois Tigeot int i915_enable_hangcheck = 1;
621e3adcf8fSFrançois Tigeot TUNABLE_INT("drm.i915.enable_hangcheck", &i915_enable_hangcheck);
622e3adcf8fSFrançois Tigeot 
62300640ec9SFrançois Tigeot static int i8xx_do_reset(struct drm_device *dev)
624e3adcf8fSFrançois Tigeot {
625e3adcf8fSFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
626e3adcf8fSFrançois Tigeot 
627e3adcf8fSFrançois Tigeot 	if (IS_I85X(dev))
628e3adcf8fSFrançois Tigeot 		return -ENODEV;
629e3adcf8fSFrançois Tigeot 
630e3adcf8fSFrançois Tigeot 	I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
631e3adcf8fSFrançois Tigeot 	POSTING_READ(D_STATE);
632e3adcf8fSFrançois Tigeot 
633e3adcf8fSFrançois Tigeot 	if (IS_I830(dev) || IS_845G(dev)) {
634e3adcf8fSFrançois Tigeot 		I915_WRITE(DEBUG_RESET_I830,
635e3adcf8fSFrançois Tigeot 			   DEBUG_RESET_DISPLAY |
636e3adcf8fSFrançois Tigeot 			   DEBUG_RESET_RENDER |
637e3adcf8fSFrançois Tigeot 			   DEBUG_RESET_FULL);
638e3adcf8fSFrançois Tigeot 		POSTING_READ(DEBUG_RESET_I830);
63900640ec9SFrançois Tigeot 		msleep(1);
640e3adcf8fSFrançois Tigeot 
641e3adcf8fSFrançois Tigeot 		I915_WRITE(DEBUG_RESET_I830, 0);
642e3adcf8fSFrançois Tigeot 		POSTING_READ(DEBUG_RESET_I830);
643e3adcf8fSFrançois Tigeot 	}
644e3adcf8fSFrançois Tigeot 
64500640ec9SFrançois Tigeot 	msleep(1);
646e3adcf8fSFrançois Tigeot 
647e3adcf8fSFrançois Tigeot 	I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
648e3adcf8fSFrançois Tigeot 	POSTING_READ(D_STATE);
649e3adcf8fSFrançois Tigeot 
650e3adcf8fSFrançois Tigeot 	return 0;
651e3adcf8fSFrançois Tigeot }
652e3adcf8fSFrançois Tigeot 
65300640ec9SFrançois Tigeot static int i965_reset_complete(struct drm_device *dev)
654e3adcf8fSFrançois Tigeot {
655e3adcf8fSFrançois Tigeot 	u8 gdrst;
6566df74fa7SFrançois Tigeot 	gdrst = pci_read_config(dev->dev, I965_GDRST, 1);
657e3adcf8fSFrançois Tigeot 	return (gdrst & 0x1);
658e3adcf8fSFrançois Tigeot }
659e3adcf8fSFrançois Tigeot 
66000640ec9SFrançois Tigeot static int i965_do_reset(struct drm_device *dev)
661e3adcf8fSFrançois Tigeot {
66200640ec9SFrançois Tigeot 	int ret;
663e3adcf8fSFrançois Tigeot 	u8 gdrst;
664e3adcf8fSFrançois Tigeot 
665e3adcf8fSFrançois Tigeot 	/*
666e3adcf8fSFrançois Tigeot 	 * Set the domains we want to reset (GRDOM/bits 2 and 3) as
667e3adcf8fSFrançois Tigeot 	 * well as the reset bit (GR/bit 0).  Setting the GR bit
668e3adcf8fSFrançois Tigeot 	 * triggers the reset; when done, the hardware will clear it.
669e3adcf8fSFrançois Tigeot 	 */
6706df74fa7SFrançois Tigeot 	gdrst = pci_read_config(dev->dev, I965_GDRST, 1);
67100640ec9SFrançois Tigeot 	pci_write_config(dev->dev, I965_GDRST,
67200640ec9SFrançois Tigeot 			      gdrst | GRDOM_RENDER |
67300640ec9SFrançois Tigeot 			      GRDOM_RESET_ENABLE, 1);
67400640ec9SFrançois Tigeot 	ret =  wait_for(i965_reset_complete(dev), 500);
67500640ec9SFrançois Tigeot 	if (ret)
67600640ec9SFrançois Tigeot 		return ret;
677e3adcf8fSFrançois Tigeot 
67800640ec9SFrançois Tigeot 	/* We can't reset render&media without also resetting display ... */
67900640ec9SFrançois Tigeot 	gdrst = pci_read_config(dev->dev, I965_GDRST, 1);
68000640ec9SFrançois Tigeot 	pci_write_config(dev->dev, I965_GDRST,
68100640ec9SFrançois Tigeot 			      gdrst | GRDOM_MEDIA |
68200640ec9SFrançois Tigeot 			      GRDOM_RESET_ENABLE, 1);
68300640ec9SFrançois Tigeot 
68400640ec9SFrançois Tigeot 	return wait_for(i965_reset_complete(dev), 500);
685e3adcf8fSFrançois Tigeot }
686e3adcf8fSFrançois Tigeot 
68700640ec9SFrançois Tigeot static int ironlake_do_reset(struct drm_device *dev)
688e3adcf8fSFrançois Tigeot {
68900640ec9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
690e3adcf8fSFrançois Tigeot 	u32 gdrst;
69100640ec9SFrançois Tigeot 	int ret;
692e3adcf8fSFrançois Tigeot 
693e3adcf8fSFrançois Tigeot 	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
69400640ec9SFrançois Tigeot 	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
69500640ec9SFrançois Tigeot 		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
69600640ec9SFrançois Tigeot 	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
69700640ec9SFrançois Tigeot 	if (ret)
69800640ec9SFrançois Tigeot 		return ret;
69900640ec9SFrançois Tigeot 
70000640ec9SFrançois Tigeot 	/* We can't reset render&media without also resetting display ... */
70100640ec9SFrançois Tigeot 	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
70200640ec9SFrançois Tigeot 	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
70300640ec9SFrançois Tigeot 		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
70400640ec9SFrançois Tigeot 	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
705e3adcf8fSFrançois Tigeot }
706e3adcf8fSFrançois Tigeot 
707e9243325SFrançois Tigeot static int gen6_do_reset(struct drm_device *dev)
708e3adcf8fSFrançois Tigeot {
709e9243325SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
710e3adcf8fSFrançois Tigeot 	int ret;
711e3adcf8fSFrançois Tigeot 
712e3adcf8fSFrançois Tigeot 	dev_priv = dev->dev_private;
713e3adcf8fSFrançois Tigeot 
714e3adcf8fSFrançois Tigeot 	/* Hold gt_lock across reset to prevent any register access
715e3adcf8fSFrançois Tigeot 	 * with forcewake not set correctly
716e3adcf8fSFrançois Tigeot 	 */
717e3adcf8fSFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_EXCLUSIVE);
718e3adcf8fSFrançois Tigeot 
719e3adcf8fSFrançois Tigeot 	/* Reset the chip */
720e3adcf8fSFrançois Tigeot 
721e3adcf8fSFrançois Tigeot 	/* GEN6_GDRST is not in the gt power well, no need to check
722e3adcf8fSFrançois Tigeot 	 * for fifo space for the write or forcewake the chip for
723e3adcf8fSFrançois Tigeot 	 * the read
724e3adcf8fSFrançois Tigeot 	 */
725e3adcf8fSFrançois Tigeot 	I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
726e3adcf8fSFrançois Tigeot 
727e3adcf8fSFrançois Tigeot 	/* Spin waiting for the device to ack the reset request */
72819df918dSFrançois Tigeot 	ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
729e3adcf8fSFrançois Tigeot 
730e3adcf8fSFrançois Tigeot 	/* If reset with a user forcewake, try to restore, otherwise turn it off */
731e3adcf8fSFrançois Tigeot 	if (dev_priv->forcewake_count)
732e9243325SFrançois Tigeot 		dev_priv->gt.force_wake_get(dev_priv);
733e3adcf8fSFrançois Tigeot 	else
734e9243325SFrançois Tigeot 		dev_priv->gt.force_wake_put(dev_priv);
735e3adcf8fSFrançois Tigeot 
736e3adcf8fSFrançois Tigeot 	/* Restore fifo count */
737e3adcf8fSFrançois Tigeot 	dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
738e3adcf8fSFrançois Tigeot 
739e3adcf8fSFrançois Tigeot 	lockmgr(&dev_priv->gt_lock, LK_RELEASE);
740e9243325SFrançois Tigeot 	return ret;
741e3adcf8fSFrançois Tigeot }
742e3adcf8fSFrançois Tigeot 
74300640ec9SFrançois Tigeot int intel_gpu_reset(struct drm_device *dev)
74400640ec9SFrançois Tigeot {
74500640ec9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
74600640ec9SFrançois Tigeot 	int ret = -ENODEV;
74700640ec9SFrançois Tigeot 
74800640ec9SFrançois Tigeot 	switch (INTEL_INFO(dev)->gen) {
74900640ec9SFrançois Tigeot 	case 7:
75000640ec9SFrançois Tigeot 	case 6:
75100640ec9SFrançois Tigeot 		ret = gen6_do_reset(dev);
75200640ec9SFrançois Tigeot 		break;
75300640ec9SFrançois Tigeot 	case 5:
75400640ec9SFrançois Tigeot 		ret = ironlake_do_reset(dev);
75500640ec9SFrançois Tigeot 		break;
75600640ec9SFrançois Tigeot 	case 4:
75700640ec9SFrançois Tigeot 		ret = i965_do_reset(dev);
75800640ec9SFrançois Tigeot 		break;
75900640ec9SFrançois Tigeot 	case 2:
76000640ec9SFrançois Tigeot 		ret = i8xx_do_reset(dev);
76100640ec9SFrançois Tigeot 		break;
76200640ec9SFrançois Tigeot 	}
76300640ec9SFrançois Tigeot 
76400640ec9SFrançois Tigeot 	/* Also reset the gpu hangman. */
76500640ec9SFrançois Tigeot 	if (dev_priv->stop_rings) {
76600640ec9SFrançois Tigeot 		DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n");
76700640ec9SFrançois Tigeot 		dev_priv->stop_rings = 0;
76800640ec9SFrançois Tigeot 		if (ret == -ENODEV) {
76900640ec9SFrançois Tigeot 			DRM_ERROR("Reset not implemented, but ignoring "
77000640ec9SFrançois Tigeot 				  "error for simulated gpu hangs\n");
77100640ec9SFrançois Tigeot 			ret = 0;
77200640ec9SFrançois Tigeot 		}
77300640ec9SFrançois Tigeot 	}
77400640ec9SFrançois Tigeot 
77500640ec9SFrançois Tigeot 	return ret;
77600640ec9SFrançois Tigeot }
77700640ec9SFrançois Tigeot 
778e9243325SFrançois Tigeot /**
779e9243325SFrançois Tigeot  * i915_reset - reset chip after a hang
780e9243325SFrançois Tigeot  * @dev: drm device to reset
781e9243325SFrançois Tigeot  *
782e9243325SFrançois Tigeot  * Reset the chip.  Useful if a hang is detected. Returns zero on successful
783e9243325SFrançois Tigeot  * reset or otherwise an error code.
784e9243325SFrançois Tigeot  *
785e9243325SFrançois Tigeot  * Procedure is fairly simple:
786e9243325SFrançois Tigeot  *   - reset the chip using the reset reg
787e9243325SFrançois Tigeot  *   - re-init context state
788e9243325SFrançois Tigeot  *   - re-init hardware status page
789e9243325SFrançois Tigeot  *   - re-init ring buffer
790e9243325SFrançois Tigeot  *   - re-init interrupt state
791e9243325SFrançois Tigeot  *   - re-init display
792e9243325SFrançois Tigeot  */
79300640ec9SFrançois Tigeot int i915_reset(struct drm_device *dev)
794e3adcf8fSFrançois Tigeot {
795e3adcf8fSFrançois Tigeot 	drm_i915_private_t *dev_priv = dev->dev_private;
796e9243325SFrançois Tigeot 	int ret;
797e9243325SFrançois Tigeot 
798e9243325SFrançois Tigeot 	if (!i915_try_reset)
799e9243325SFrançois Tigeot 		return 0;
800e9243325SFrançois Tigeot 
80100640ec9SFrançois Tigeot 	DRM_LOCK(dev);
802e3adcf8fSFrançois Tigeot 
803e3adcf8fSFrançois Tigeot 	i915_gem_reset(dev);
804e3adcf8fSFrançois Tigeot 
805e3adcf8fSFrançois Tigeot 	ret = -ENODEV;
80600640ec9SFrançois Tigeot 	if (time_uptime - dev_priv->last_gpu_reset < 5)
807e3adcf8fSFrançois Tigeot 		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
80800640ec9SFrançois Tigeot 	else
80900640ec9SFrançois Tigeot 		ret = intel_gpu_reset(dev);
81000640ec9SFrançois Tigeot 
811e3adcf8fSFrançois Tigeot 	dev_priv->last_gpu_reset = time_uptime;
812e3adcf8fSFrançois Tigeot 	if (ret) {
813e3adcf8fSFrançois Tigeot 		DRM_ERROR("Failed to reset chip.\n");
814e3adcf8fSFrançois Tigeot 		DRM_UNLOCK(dev);
81500640ec9SFrançois Tigeot 		return ret;
816e3adcf8fSFrançois Tigeot 	}
817e3adcf8fSFrançois Tigeot 
818e9243325SFrançois Tigeot 	/* Ok, now get things going again... */
819e9243325SFrançois Tigeot 
820e9243325SFrançois Tigeot 	/*
821e9243325SFrançois Tigeot 	 * Everything depends on having the GTT running, so we need to start
822e9243325SFrançois Tigeot 	 * there.  Fortunately we don't need to do this unless we reset the
823e9243325SFrançois Tigeot 	 * chip at a PCI level.
824e9243325SFrançois Tigeot 	 *
825e9243325SFrançois Tigeot 	 * Next we need to restore the context, but we don't use those
826e9243325SFrançois Tigeot 	 * yet either...
827e9243325SFrançois Tigeot 	 *
828e9243325SFrançois Tigeot 	 * Ring buffer needs to be re-initialized in the KMS case, or if X
829e9243325SFrançois Tigeot 	 * was running at the time of the reset (i.e. we weren't VT
830e9243325SFrançois Tigeot 	 * switched away).
831e9243325SFrançois Tigeot 	 */
832e3adcf8fSFrançois Tigeot 	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
833e3adcf8fSFrançois Tigeot 			!dev_priv->mm.suspended) {
83400640ec9SFrançois Tigeot 		struct intel_ring_buffer *ring;
83500640ec9SFrançois Tigeot 		int i;
83600640ec9SFrançois Tigeot 
837e3adcf8fSFrançois Tigeot 		dev_priv->mm.suspended = 0;
838e3adcf8fSFrançois Tigeot 
839e3adcf8fSFrançois Tigeot 		i915_gem_init_swizzling(dev);
840e3adcf8fSFrançois Tigeot 
84100640ec9SFrançois Tigeot 		for_each_ring(ring, dev_priv, i)
84200640ec9SFrançois Tigeot 			ring->init(ring);
843e3adcf8fSFrançois Tigeot 
84400640ec9SFrançois Tigeot #if 0	/* XXX: HW context support */
84500640ec9SFrançois Tigeot 		i915_gem_context_init(dev);
84600640ec9SFrançois Tigeot #endif
847e3adcf8fSFrançois Tigeot 		i915_gem_init_ppgtt(dev);
848e3adcf8fSFrançois Tigeot 
84900640ec9SFrançois Tigeot 		/*
85000640ec9SFrançois Tigeot 		 * It would make sense to re-init all the other hw state, at
85100640ec9SFrançois Tigeot 		 * least the rps/rc6/emon init done within modeset_init_hw. For
85200640ec9SFrançois Tigeot 		 * some unknown reason, this blows up my ilk, so don't.
85300640ec9SFrançois Tigeot 		 */
85400640ec9SFrançois Tigeot 
855e3adcf8fSFrançois Tigeot 		DRM_UNLOCK(dev);
856e3adcf8fSFrançois Tigeot 
85700640ec9SFrançois Tigeot 		drm_irq_uninstall(dev);
85800640ec9SFrançois Tigeot 		drm_irq_install(dev);
85900640ec9SFrançois Tigeot 	} else {
86000640ec9SFrançois Tigeot 		DRM_UNLOCK(dev);
861e3adcf8fSFrançois Tigeot 	}
862e3adcf8fSFrançois Tigeot 
863e9243325SFrançois Tigeot 	return 0;
864e9243325SFrançois Tigeot }
865e9243325SFrançois Tigeot 
866*f0b54121SFrançois Tigeot static struct drm_driver driver = {
867*f0b54121SFrançois Tigeot 	.driver_features =   DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
868*f0b54121SFrançois Tigeot 	    DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | DRIVER_LOCKLESS_IRQ |
869*f0b54121SFrançois Tigeot 	    DRIVER_GEM /*| DRIVER_MODESET*/,
870*f0b54121SFrançois Tigeot 
871*f0b54121SFrançois Tigeot 	.buf_priv_size	= sizeof(drm_i915_private_t),
872*f0b54121SFrançois Tigeot 	.load		= i915_driver_load,
873*f0b54121SFrançois Tigeot 	.open		= i915_driver_open,
874*f0b54121SFrançois Tigeot 	.unload		= i915_driver_unload,
875*f0b54121SFrançois Tigeot 	.preclose	= i915_driver_preclose,
876*f0b54121SFrançois Tigeot 	.lastclose	= i915_driver_lastclose,
877*f0b54121SFrançois Tigeot 	.postclose	= i915_driver_postclose,
878*f0b54121SFrançois Tigeot 	.device_is_agp	= i915_driver_device_is_agp,
879*f0b54121SFrançois Tigeot 	.gem_init_object = i915_gem_init_object,
880*f0b54121SFrançois Tigeot 	.gem_free_object = i915_gem_free_object,
881*f0b54121SFrançois Tigeot 	.gem_pager_ops	= &i915_gem_pager_ops,
882*f0b54121SFrançois Tigeot 	.dumb_create	= i915_gem_dumb_create,
883*f0b54121SFrançois Tigeot 	.dumb_map_offset = i915_gem_mmap_gtt,
884*f0b54121SFrançois Tigeot 	.dumb_destroy	= i915_gem_dumb_destroy,
885*f0b54121SFrançois Tigeot 
886*f0b54121SFrançois Tigeot 	.ioctls		= i915_ioctls,
887*f0b54121SFrançois Tigeot 
888*f0b54121SFrançois Tigeot 	.name		= DRIVER_NAME,
889*f0b54121SFrançois Tigeot 	.desc		= DRIVER_DESC,
890*f0b54121SFrançois Tigeot 	.date		= DRIVER_DATE,
891*f0b54121SFrançois Tigeot 	.major		= DRIVER_MAJOR,
892*f0b54121SFrançois Tigeot 	.minor		= DRIVER_MINOR,
893*f0b54121SFrançois Tigeot 	.patchlevel	= DRIVER_PATCHLEVEL,
894*f0b54121SFrançois Tigeot };
895*f0b54121SFrançois Tigeot 
896c0bdd5d9SFrançois Tigeot /* We give fast paths for the really cool registers */
897c0bdd5d9SFrançois Tigeot #define NEEDS_FORCE_WAKE(dev_priv, reg) \
898c0bdd5d9SFrançois Tigeot 	((HAS_FORCE_WAKE((dev_priv)->dev)) && \
899c0bdd5d9SFrançois Tigeot 	 ((reg) < 0x40000) &&            \
900c0bdd5d9SFrançois Tigeot 	 ((reg) != FORCEWAKE))
901c0bdd5d9SFrançois Tigeot 
902e9243325SFrançois Tigeot static bool IS_DISPLAYREG(u32 reg)
903e9243325SFrançois Tigeot {
904e9243325SFrançois Tigeot 	/*
905e9243325SFrançois Tigeot 	 * This should make it easier to transition modules over to the
906e9243325SFrançois Tigeot 	 * new register block scheme, since we can do it incrementally.
907e9243325SFrançois Tigeot 	 */
908e9243325SFrançois Tigeot 	if (reg >= VLV_DISPLAY_BASE)
909e9243325SFrançois Tigeot 		return false;
910e9243325SFrançois Tigeot 
911e9243325SFrançois Tigeot 	if (reg >= RENDER_RING_BASE &&
912e9243325SFrançois Tigeot 	    reg < RENDER_RING_BASE + 0xff)
913e9243325SFrançois Tigeot 		return false;
914e9243325SFrançois Tigeot 	if (reg >= GEN6_BSD_RING_BASE &&
915e9243325SFrançois Tigeot 	    reg < GEN6_BSD_RING_BASE + 0xff)
916e9243325SFrançois Tigeot 		return false;
917e9243325SFrançois Tigeot 	if (reg >= BLT_RING_BASE &&
918e9243325SFrançois Tigeot 	    reg < BLT_RING_BASE + 0xff)
919e9243325SFrançois Tigeot 		return false;
920e9243325SFrançois Tigeot 
921e9243325SFrançois Tigeot 	if (reg == PGTBL_ER)
922e9243325SFrançois Tigeot 		return false;
923e9243325SFrançois Tigeot 
924e9243325SFrançois Tigeot 	if (reg >= IPEIR_I965 &&
925e9243325SFrançois Tigeot 	    reg < HWSTAM)
926e9243325SFrançois Tigeot 		return false;
927e9243325SFrançois Tigeot 
928e9243325SFrançois Tigeot 	if (reg == MI_MODE)
929e9243325SFrançois Tigeot 		return false;
930e9243325SFrançois Tigeot 
931e9243325SFrançois Tigeot 	if (reg == GFX_MODE_GEN7)
932e9243325SFrançois Tigeot 		return false;
933e9243325SFrançois Tigeot 
934e9243325SFrançois Tigeot 	if (reg == RENDER_HWS_PGA_GEN7 ||
935e9243325SFrançois Tigeot 	    reg == BSD_HWS_PGA_GEN7 ||
936e9243325SFrançois Tigeot 	    reg == BLT_HWS_PGA_GEN7)
937e9243325SFrançois Tigeot 		return false;
938e9243325SFrançois Tigeot 
939e9243325SFrançois Tigeot 	if (reg == GEN6_BSD_SLEEP_PSMI_CONTROL ||
940e9243325SFrançois Tigeot 	    reg == GEN6_BSD_RNCID)
941e9243325SFrançois Tigeot 		return false;
942e9243325SFrançois Tigeot 
943e9243325SFrançois Tigeot 	if (reg == GEN6_BLITTER_ECOSKPD)
944e9243325SFrançois Tigeot 		return false;
945e9243325SFrançois Tigeot 
946e9243325SFrançois Tigeot 	if (reg >= 0x4000c &&
947e9243325SFrançois Tigeot 	    reg <= 0x4002c)
948e9243325SFrançois Tigeot 		return false;
949e9243325SFrançois Tigeot 
950e9243325SFrançois Tigeot 	if (reg >= 0x4f000 &&
951e9243325SFrançois Tigeot 	    reg <= 0x4f08f)
952e9243325SFrançois Tigeot 		return false;
953e9243325SFrançois Tigeot 
954e9243325SFrançois Tigeot 	if (reg >= 0x4f100 &&
955e9243325SFrançois Tigeot 	    reg <= 0x4f11f)
956e9243325SFrançois Tigeot 		return false;
957e9243325SFrançois Tigeot 
958e9243325SFrançois Tigeot 	if (reg >= VLV_MASTER_IER &&
959e9243325SFrançois Tigeot 	    reg <= GEN6_PMIER)
960e9243325SFrançois Tigeot 		return false;
961e9243325SFrançois Tigeot 
962e9243325SFrançois Tigeot 	if (reg >= FENCE_REG_SANDYBRIDGE_0 &&
963e9243325SFrançois Tigeot 	    reg < (FENCE_REG_SANDYBRIDGE_0 + (16*8)))
964e9243325SFrançois Tigeot 		return false;
965e9243325SFrançois Tigeot 
966e9243325SFrançois Tigeot 	if (reg >= VLV_IIR_RW &&
967e9243325SFrançois Tigeot 	    reg <= VLV_ISR)
968e9243325SFrançois Tigeot 		return false;
969e9243325SFrançois Tigeot 
970e9243325SFrançois Tigeot 	if (reg == FORCEWAKE_VLV ||
971e9243325SFrançois Tigeot 	    reg == FORCEWAKE_ACK_VLV)
972e9243325SFrançois Tigeot 		return false;
973e9243325SFrançois Tigeot 
974e9243325SFrançois Tigeot 	if (reg == GEN6_GDRST)
975e9243325SFrançois Tigeot 		return false;
976e9243325SFrançois Tigeot 
977e9243325SFrançois Tigeot 	switch (reg) {
978e9243325SFrançois Tigeot 	case _3D_CHICKEN3:
979e9243325SFrançois Tigeot 	case IVB_CHICKEN3:
980e9243325SFrançois Tigeot 	case GEN7_COMMON_SLICE_CHICKEN1:
981e9243325SFrançois Tigeot 	case GEN7_L3CNTLREG1:
982e9243325SFrançois Tigeot 	case GEN7_L3_CHICKEN_MODE_REGISTER:
983e9243325SFrançois Tigeot 	case GEN7_ROW_CHICKEN2:
984e9243325SFrançois Tigeot 	case GEN7_L3SQCREG4:
985e9243325SFrançois Tigeot 	case GEN7_SQ_CHICKEN_MBCUNIT_CONFIG:
986e9243325SFrançois Tigeot 	case GEN7_HALF_SLICE_CHICKEN1:
987e9243325SFrançois Tigeot 	case GEN6_MBCTL:
988e9243325SFrançois Tigeot 	case GEN6_UCGCTL2:
989e9243325SFrançois Tigeot 		return false;
990e9243325SFrançois Tigeot 	default:
991e9243325SFrançois Tigeot 		break;
992e9243325SFrançois Tigeot 	}
993e9243325SFrançois Tigeot 
994e9243325SFrançois Tigeot 	return true;
995e9243325SFrançois Tigeot }
996e9243325SFrançois Tigeot 
997e9243325SFrançois Tigeot static void
998e9243325SFrançois Tigeot ilk_dummy_write(struct drm_i915_private *dev_priv)
999e9243325SFrançois Tigeot {
1000e9243325SFrançois Tigeot 	/* WaIssueDummyWriteToWakeupFromRC6: Issue a dummy write to wake up the
1001e9243325SFrançois Tigeot 	 * chip from rc6 before touching it for real. MI_MODE is masked, hence
1002e9243325SFrançois Tigeot 	 * harmless to write 0 into. */
1003e9243325SFrançois Tigeot 	I915_WRITE_NOTRACE(MI_MODE, 0);
1004e3adcf8fSFrançois Tigeot }
1005e3adcf8fSFrançois Tigeot 
1006e3adcf8fSFrançois Tigeot #define __i915_read(x, y) \
1007e3adcf8fSFrançois Tigeot u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
1008e3adcf8fSFrançois Tigeot 	u##x val = 0; \
1009e9243325SFrançois Tigeot 	if (IS_GEN5(dev_priv->dev)) \
1010e9243325SFrançois Tigeot 		ilk_dummy_write(dev_priv); \
1011e3adcf8fSFrançois Tigeot 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
1012e3adcf8fSFrançois Tigeot 		lockmgr(&dev_priv->gt_lock, LK_EXCLUSIVE); \
1013e3adcf8fSFrançois Tigeot 		if (dev_priv->forcewake_count == 0) \
1014e9243325SFrançois Tigeot 			dev_priv->gt.force_wake_get(dev_priv); \
1015e3adcf8fSFrançois Tigeot 		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
1016e3adcf8fSFrançois Tigeot 		if (dev_priv->forcewake_count == 0) \
1017e9243325SFrançois Tigeot 			dev_priv->gt.force_wake_put(dev_priv); \
1018e3adcf8fSFrançois Tigeot 		lockmgr(&dev_priv->gt_lock, LK_RELEASE); \
1019e9243325SFrançois Tigeot 	} else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \
1020e9243325SFrançois Tigeot 		val = DRM_READ##y(dev_priv->mmio_map, reg + 0x180000);	\
1021e3adcf8fSFrançois Tigeot 	} else { \
1022e3adcf8fSFrançois Tigeot 		val = DRM_READ##y(dev_priv->mmio_map, reg);	\
1023e3adcf8fSFrançois Tigeot 	} \
1024e3adcf8fSFrançois Tigeot 	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
1025e3adcf8fSFrançois Tigeot 	return val; \
1026e3adcf8fSFrançois Tigeot }
1027e3adcf8fSFrançois Tigeot 
1028e3adcf8fSFrançois Tigeot __i915_read(8, 8)
1029e3adcf8fSFrançois Tigeot __i915_read(16, 16)
1030e3adcf8fSFrançois Tigeot __i915_read(32, 32)
1031e3adcf8fSFrançois Tigeot __i915_read(64, 64)
1032e3adcf8fSFrançois Tigeot #undef __i915_read
1033e3adcf8fSFrançois Tigeot 
1034e3adcf8fSFrançois Tigeot #define __i915_write(x, y) \
1035e3adcf8fSFrançois Tigeot void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
1036e3adcf8fSFrançois Tigeot 	u32 __fifo_ret = 0; \
1037e3adcf8fSFrançois Tigeot 	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
1038e3adcf8fSFrançois Tigeot 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
1039e3adcf8fSFrançois Tigeot 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
1040e3adcf8fSFrançois Tigeot 	} \
1041e9243325SFrançois Tigeot 	if (IS_GEN5(dev_priv->dev)) \
1042e9243325SFrançois Tigeot 		ilk_dummy_write(dev_priv); \
1043e9243325SFrançois Tigeot 	if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
1044e9243325SFrançois Tigeot 		DRM_ERROR("Unknown unclaimed register before writing to %x\n", reg); \
1045e9243325SFrançois Tigeot 		I915_WRITE_NOTRACE(GEN7_ERR_INT, ERR_INT_MMIO_UNCLAIMED); \
1046e9243325SFrançois Tigeot 	} \
1047e9243325SFrançois Tigeot 	if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \
1048e9243325SFrançois Tigeot 		DRM_WRITE##y(dev_priv->mmio_map, reg + 0x180000, val);	\
1049e9243325SFrançois Tigeot 	} else {							\
1050e3adcf8fSFrançois Tigeot 		DRM_WRITE##y(dev_priv->mmio_map, reg, val);		\
1051e9243325SFrançois Tigeot 	}								\
1052e9243325SFrançois Tigeot 	if (unlikely(__fifo_ret)) { \
1053e3adcf8fSFrançois Tigeot 		gen6_gt_check_fifodbg(dev_priv); \
1054e3adcf8fSFrançois Tigeot 	} \
1055e9243325SFrançois Tigeot 	if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
1056e9243325SFrançois Tigeot 		DRM_ERROR("Unclaimed write to %x\n", reg); \
1057e9243325SFrançois Tigeot 		DRM_WRITE32(dev_priv->mmio_map, GEN7_ERR_INT, ERR_INT_MMIO_UNCLAIMED);	\
1058e9243325SFrançois Tigeot 	} \
1059e3adcf8fSFrançois Tigeot }
1060e9243325SFrançois Tigeot 
1061e3adcf8fSFrançois Tigeot __i915_write(8, 8)
1062e3adcf8fSFrançois Tigeot __i915_write(16, 16)
1063e3adcf8fSFrançois Tigeot __i915_write(32, 32)
1064e3adcf8fSFrançois Tigeot __i915_write(64, 64)
1065e3adcf8fSFrançois Tigeot #undef __i915_write
1066