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