Commit effbc4fd authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-intel-next' of git://people.freedesktop.org/~danvet/drm-intel into drm-core-next

Daniel Vetter wrote
First pull request for 3.5-next, slightly large than usual because new
things kept coming in since the last pull for 3.4.
Highlights:
- first batch of hw enablement for vlv (Jesse et al) and hsw (Eugeni). pci
 ids are not yet added, and there's still quite a few patches to merge
 (mostly modesetting). To make QA easier I've decided to merge this stuff
 in pieces.
- loads of cleanups and prep patches spurred by the above. Especially vlv
 is a real frankenstein chip, but also hsw is stretching our driver's
 code design. Expect more to come in this area for 3.5.
- more gmbus fixes, cleanups and improvements by Daniel Kurtz. Again,
 there are more patches needed (and some already queued up), but I wanted
 to split this a bit for better testing.
- pwrite/pread rework and retuning. This series has been in the works for
 a few months already and a lot of i-g-t tests have been created for it.
 Now it's finally ready to be merged.  Note that one patch in this series
 touches include/pagemap.h, that patch is acked-by akpm.
- reduce mappable pressure and relocation throughput improvements from
 Chris.
- mmap offset exhaustion mitigation by Chris Wilson.
- a start at figuring out which codepaths in our messy dri1/ums+gem/kms
 driver we actually need to support by bailing out of unsupported case.
 The driver now refuses to load without kms on gen6+ and disallows a few
 ioctls that userspace never used in certain cases. More of this will
 definitely come.
- More decoupling of global gtt and ppgtt.
- Improved dual-link lvds detection by Takashi Iwai.
- Shut up the compiler + plus fix the fallout (Ben)
- Inverted panel brightness handling (mostly Acer manages to break things
 in this way).
- Small fixlets and adjustements and some minor things to help debugging.

Regression-wise QA reported quite a few issues on ivb, but all of them
turned out to be hw stability issues which are already fixed in
drm-intel-fixes (QA runs the nightly regression tests on -next alone,
without -fixes automatically merged in). There's still one issue open on
snb, it looks like occlusion query writes are not quite as cache coherent
as we've expected. With some of the pwrite adjustements we can now
reliably hit this. Kernel workaround for it is in the works."

* 'drm-intel-next' of git://people.freedesktop.org/~danvet/drm-intel: (101 commits)
  drm/i915: VCS is not the last ring
  drm/i915: Add a dual link lvds quirk for MacBook Pro 8,2
  drm/i915: make quirks more verbose
  drm/i915: dump the DMA fetch addr register on pre-gen6
  drm/i915/sdvo: Include YRPB as an additional TV output type
  drm/i915: disallow gem init ioctl on ilk
  drm/i915: refuse to load on gen6+ without kms
  drm/i915: extract gt interrupt handler
  drm/i915: use render gen to switch ring irq functions
  drm/i915: rip out old HWSTAM missed irq WA for vlv
  drm/i915: open code gen6+ ring irqs
  drm/i915: ring irq cleanups
  drm/i915: add SFUSE_STRAP registers for digital port detection
  drm/i915: add WM_LINETIME registers
  drm/i915: add WRPLL clocks
  drm/i915: add LCPLL control registers
  drm/i915: add SSC offsets for SBI access
  drm/i915: add port clock selection support for HSW
  drm/i915: add S PLL control
  drm/i915: add PIXCLK_GATE register
  ...

Conflicts:
	drivers/char/agp/intel-agp.h
	drivers/char/agp/intel-gtt.c
	drivers/gpu/drm/i915/i915_debugfs.c
parents 6a7068b4 ec34a01d
...@@ -982,6 +982,20 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -982,6 +982,20 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
i8k.restricted [HW] Allow controlling fans only if SYS_ADMIN i8k.restricted [HW] Allow controlling fans only if SYS_ADMIN
capability is set. capability is set.
i915.invert_brightness=
[DRM] Invert the sense of the variable that is used to
set the brightness of the panel backlight. Normally a
brightness value of 0 indicates backlight switched off,
and the maximum of the brightness value sets the backlight
to maximum brightness. If this parameter is set to 0
(default) and the machine requires it, or this parameter
is set to 1, a brightness value of 0 sets the backlight
to maximum brightness, and the maximum of the brightness
value switches the backlight off.
-1 -- never invert brightness
0 -- machine default
1 -- force brightness inversion
icn= [HW,ISDN] icn= [HW,ISDN]
Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]] Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
......
...@@ -907,6 +907,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ...@@ -907,6 +907,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB), ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB),
ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB), ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB),
ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB), ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB),
ID(PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB),
{ } { }
}; };
......
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
#define G4x_GMCH_SIZE_VT_2M (G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN) #define G4x_GMCH_SIZE_VT_2M (G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN)
#define GFX_FLSH_CNTL 0x2170 /* 915+ */ #define GFX_FLSH_CNTL 0x2170 /* 915+ */
#define GFX_FLSH_CNTL_VLV 0x101008
#define I810_DRAM_CTL 0x3000 #define I810_DRAM_CTL 0x3000
#define I810_DRAM_ROW_0 0x00000001 #define I810_DRAM_ROW_0 0x00000001
...@@ -235,6 +236,19 @@ ...@@ -235,6 +236,19 @@
#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB 0x0158 /* Server */ #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB 0x0158 /* Server */
#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG 0x015A #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG 0x015A
#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A
#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB 0x0F00 /* VLV1 */
#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG 0x0F30
#define PCI_DEVICE_ID_INTEL_HASWELL_HB 0x0400 /* Desktop */
#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG 0x0402
#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG 0x0412
#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB 0x0404 /* Mobile */
#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG 0x0406
#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG 0x0416
#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB 0x0408 /* Server */
#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG 0x040a
#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG 0x041a
#define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */
#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04
int intel_gmch_probe(struct pci_dev *pdev, int intel_gmch_probe(struct pci_dev *pdev,
struct agp_bridge_data *bridge); struct agp_bridge_data *bridge);
......
...@@ -1179,6 +1179,20 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry, ...@@ -1179,6 +1179,20 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry,
writel(addr | pte_flags, intel_private.gtt + entry); writel(addr | pte_flags, intel_private.gtt + entry);
} }
static void valleyview_write_entry(dma_addr_t addr, unsigned int entry,
unsigned int flags)
{
u32 pte_flags;
pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
/* gen6 has bit11-4 for physical addr bit39-32 */
addr |= (addr >> 28) & 0xff0;
writel(addr | pte_flags, intel_private.gtt + entry);
writel(1, intel_private.registers + GFX_FLSH_CNTL_VLV);
}
static void gen6_cleanup(void) static void gen6_cleanup(void)
{ {
} }
...@@ -1205,12 +1219,16 @@ static inline int needs_idle_maps(void) ...@@ -1205,12 +1219,16 @@ static inline int needs_idle_maps(void)
static int i9xx_setup(void) static int i9xx_setup(void)
{ {
u32 reg_addr; u32 reg_addr;
int size = KB(512);
pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &reg_addr); pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &reg_addr);
reg_addr &= 0xfff80000; reg_addr &= 0xfff80000;
intel_private.registers = ioremap(reg_addr, 128 * 4096); if (INTEL_GTT_GEN >= 7)
size = MB(2);
intel_private.registers = ioremap(reg_addr, size);
if (!intel_private.registers) if (!intel_private.registers)
return -ENOMEM; return -ENOMEM;
...@@ -1354,6 +1372,15 @@ static const struct intel_gtt_driver sandybridge_gtt_driver = { ...@@ -1354,6 +1372,15 @@ static const struct intel_gtt_driver sandybridge_gtt_driver = {
.check_flags = gen6_check_flags, .check_flags = gen6_check_flags,
.chipset_flush = i9xx_chipset_flush, .chipset_flush = i9xx_chipset_flush,
}; };
static const struct intel_gtt_driver valleyview_gtt_driver = {
.gen = 7,
.setup = i9xx_setup,
.cleanup = gen6_cleanup,
.write_entry = valleyview_write_entry,
.dma_mask_size = 40,
.check_flags = gen6_check_flags,
.chipset_flush = i9xx_chipset_flush,
};
/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
* driver and gmch_driver must be non-null, and find_gmch will determine * driver and gmch_driver must be non-null, and find_gmch will determine
...@@ -1460,6 +1487,22 @@ static const struct intel_gtt_driver_description { ...@@ -1460,6 +1487,22 @@ static const struct intel_gtt_driver_description {
"Ivybridge", &sandybridge_gtt_driver }, "Ivybridge", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG, { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG,
"Ivybridge", &sandybridge_gtt_driver }, "Ivybridge", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG,
"ValleyView", &valleyview_gtt_driver },
{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG,
"Haswell", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG,
"Haswell", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG,
"Haswell", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG,
"Haswell", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG,
"Haswell", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG,
"Haswell", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_HASWELL_SDV,
"Haswell", &sandybridge_gtt_driver },
{ 0, NULL, NULL } { 0, NULL, NULL }
}; };
......
...@@ -98,3 +98,26 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages) ...@@ -98,3 +98,26 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
#endif #endif
} }
EXPORT_SYMBOL(drm_clflush_pages); EXPORT_SYMBOL(drm_clflush_pages);
void
drm_clflush_virt_range(char *addr, unsigned long length)
{
#if defined(CONFIG_X86)
if (cpu_has_clflush) {
char *end = addr + length;
mb();
for (; addr < end; addr += boot_cpu_data.x86_clflush_size)
clflush(addr);
clflush(end - 1);
mb();
return;
}
if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
printk(KERN_ERR "Timed out waiting for cache flush.\n");
#else
printk(KERN_ERR "Architecture has no drm_cache.c support\n");
WARN_ON_ONCE(1);
#endif
}
EXPORT_SYMBOL(drm_clflush_virt_range);
...@@ -468,7 +468,45 @@ static int i915_interrupt_info(struct seq_file *m, void *data) ...@@ -468,7 +468,45 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
if (ret) if (ret)
return ret; return ret;
if (!HAS_PCH_SPLIT(dev)) { if (IS_VALLEYVIEW(dev)) {
seq_printf(m, "Display IER:\t%08x\n",
I915_READ(VLV_IER));
seq_printf(m, "Display IIR:\t%08x\n",
I915_READ(VLV_IIR));
seq_printf(m, "Display IIR_RW:\t%08x\n",
I915_READ(VLV_IIR_RW));
seq_printf(m, "Display IMR:\t%08x\n",
I915_READ(VLV_IMR));
for_each_pipe(pipe)
seq_printf(m, "Pipe %c stat:\t%08x\n",
pipe_name(pipe),
I915_READ(PIPESTAT(pipe)));
seq_printf(m, "Master IER:\t%08x\n",
I915_READ(VLV_MASTER_IER));
seq_printf(m, "Render IER:\t%08x\n",
I915_READ(GTIER));
seq_printf(m, "Render IIR:\t%08x\n",
I915_READ(GTIIR));
seq_printf(m, "Render IMR:\t%08x\n",
I915_READ(GTIMR));
seq_printf(m, "PM IER:\t\t%08x\n",
I915_READ(GEN6_PMIER));
seq_printf(m, "PM IIR:\t\t%08x\n",
I915_READ(GEN6_PMIIR));
seq_printf(m, "PM IMR:\t\t%08x\n",
I915_READ(GEN6_PMIMR));
seq_printf(m, "Port hotplug:\t%08x\n",
I915_READ(PORT_HOTPLUG_EN));
seq_printf(m, "DPFLIPSTAT:\t%08x\n",
I915_READ(VLV_DPFLIPSTAT));
seq_printf(m, "DPINVGTT:\t%08x\n",
I915_READ(DPINVGTT));
} else if (!HAS_PCH_SPLIT(dev)) {
seq_printf(m, "Interrupt enable: %08x\n", seq_printf(m, "Interrupt enable: %08x\n",
I915_READ(IER)); I915_READ(IER));
seq_printf(m, "Interrupt identity: %08x\n", seq_printf(m, "Interrupt identity: %08x\n",
...@@ -704,6 +742,7 @@ static void i915_ring_error_state(struct seq_file *m, ...@@ -704,6 +742,7 @@ static void i915_ring_error_state(struct seq_file *m,
struct drm_i915_error_state *error, struct drm_i915_error_state *error,
unsigned ring) unsigned ring)
{ {
BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
seq_printf(m, "%s command stream:\n", ring_str(ring)); seq_printf(m, "%s command stream:\n", ring_str(ring));
seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]);
seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]);
...@@ -718,8 +757,8 @@ static void i915_ring_error_state(struct seq_file *m, ...@@ -718,8 +757,8 @@ static void i915_ring_error_state(struct seq_file *m,
if (INTEL_INFO(dev)->gen >= 4) if (INTEL_INFO(dev)->gen >= 4)
seq_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); seq_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]);
seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]);
seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
if (INTEL_INFO(dev)->gen >= 6) { if (INTEL_INFO(dev)->gen >= 6) {
seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]); seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
seq_printf(m, " SYNC_0: 0x%08x\n", seq_printf(m, " SYNC_0: 0x%08x\n",
error->semaphore_mboxes[ring][0]); error->semaphore_mboxes[ring][0]);
...@@ -1502,6 +1541,53 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) ...@@ -1502,6 +1541,53 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
return 0; return 0;
} }
static int i915_dpio_info(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
if (!IS_VALLEYVIEW(dev)) {
seq_printf(m, "unsupported\n");
return 0;
}
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
if (ret)
return ret;
seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_DIV_A));
seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_DIV_B));
seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_REFSFR_A));
seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_REFSFR_B));
seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
seq_printf(m, "DPIO_LFP_COEFF_A: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_A));
seq_printf(m, "DPIO_LFP_COEFF_B: 0x%08x\n",
intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_B));
seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
mutex_unlock(&dev->mode_config.mutex);
return 0;
}
static ssize_t static ssize_t
i915_wedged_read(struct file *filp, i915_wedged_read(struct file *filp,
char __user *ubuf, char __user *ubuf,
...@@ -1836,6 +1922,7 @@ static struct drm_info_list i915_debugfs_list[] = { ...@@ -1836,6 +1922,7 @@ static struct drm_info_list i915_debugfs_list[] = {
{"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0}, {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},
{"i915_swizzle_info", i915_swizzle_info, 0}, {"i915_swizzle_info", i915_swizzle_info, 0},
{"i915_ppgtt_info", i915_ppgtt_info, 0}, {"i915_ppgtt_info", i915_ppgtt_info, 0},
{"i915_dpio", i915_dpio_info, 0},
}; };
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
* *
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
...@@ -43,6 +45,7 @@ ...@@ -43,6 +45,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <acpi/video.h> #include <acpi/video.h>
#include <asm/pat.h>
static void i915_write_hws_pga(struct drm_device *dev) static void i915_write_hws_pga(struct drm_device *dev)
{ {
...@@ -787,6 +790,9 @@ static int i915_getparam(struct drm_device *dev, void *data, ...@@ -787,6 +790,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_LLC: case I915_PARAM_HAS_LLC:
value = HAS_LLC(dev); value = HAS_LLC(dev);
break; break;
case I915_PARAM_HAS_ALIASING_PPGTT:
value = dev_priv->mm.aliasing_ppgtt ? 1 : 0;
break;
default: default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n", DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param); param->param);
...@@ -1158,14 +1164,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ ...@@ -1158,14 +1164,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
struct drm_device *dev = pci_get_drvdata(pdev); struct drm_device *dev = pci_get_drvdata(pdev);
pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
if (state == VGA_SWITCHEROO_ON) { if (state == VGA_SWITCHEROO_ON) {
printk(KERN_INFO "i915: switched on\n"); pr_info("switched on\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
/* i915 resume handler doesn't set to D0 */ /* i915 resume handler doesn't set to D0 */
pci_set_power_state(dev->pdev, PCI_D0); pci_set_power_state(dev->pdev, PCI_D0);
i915_resume(dev); i915_resume(dev);
dev->switch_power_state = DRM_SWITCH_POWER_ON; dev->switch_power_state = DRM_SWITCH_POWER_ON;
} else { } else {
printk(KERN_ERR "i915: switched off\n"); pr_err("switched off\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
i915_suspend(dev, pmm); i915_suspend(dev, pmm);
dev->switch_power_state = DRM_SWITCH_POWER_OFF; dev->switch_power_state = DRM_SWITCH_POWER_OFF;
...@@ -1216,10 +1222,8 @@ static int i915_load_gem_init(struct drm_device *dev) ...@@ -1216,10 +1222,8 @@ static int i915_load_gem_init(struct drm_device *dev)
/* PPGTT pdes are stolen from global gtt ptes, so shrink the /* PPGTT pdes are stolen from global gtt ptes, so shrink the
* aperture accordingly when using aliasing ppgtt. */ * aperture accordingly when using aliasing ppgtt. */
gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE; gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
/* For paranoia keep the guard page in between. */
gtt_size -= PAGE_SIZE;
i915_gem_do_init(dev, 0, mappable_size, gtt_size); i915_gem_init_global_gtt(dev, 0, mappable_size, gtt_size);
ret = i915_gem_init_aliasing_ppgtt(dev); ret = i915_gem_init_aliasing_ppgtt(dev);
if (ret) { if (ret) {
...@@ -1237,7 +1241,8 @@ static int i915_load_gem_init(struct drm_device *dev) ...@@ -1237,7 +1241,8 @@ static int i915_load_gem_init(struct drm_device *dev)
* should be enough to keep any prefetching inside of the * should be enough to keep any prefetching inside of the
* aperture. * aperture.
*/ */
i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE); i915_gem_init_global_gtt(dev, 0, mappable_size,
gtt_size);
} }
ret = i915_gem_init_hw(dev); ret = i915_gem_init_hw(dev);
...@@ -1931,6 +1936,29 @@ ips_ping_for_i915_load(void) ...@@ -1931,6 +1936,29 @@ ips_ping_for_i915_load(void)
} }
} }
static void
i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
unsigned long size)
{
dev_priv->mm.gtt_mtrr = -1;
#if defined(CONFIG_X86_PAT)
if (cpu_has_pat)
return;
#endif
/* Set up a WC MTRR for non-PAT systems. This is more common than
* one would think, because the kernel disables PAT on first
* generation Core chips because WC PAT gets overridden by a UC
* MTRR if present. Even if a UC MTRR isn't present.
*/
dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1);
if (dev_priv->mm.gtt_mtrr < 0) {
DRM_INFO("MTRR allocation failed. Graphics "
"performance may suffer.\n");
}
}
/** /**
* i915_driver_load - setup chip and create an initial config * i915_driver_load - setup chip and create an initial config
* @dev: DRM device * @dev: DRM device
...@@ -1945,8 +1973,16 @@ ips_ping_for_i915_load(void) ...@@ -1945,8 +1973,16 @@ ips_ping_for_i915_load(void)
int i915_driver_load(struct drm_device *dev, unsigned long flags) int i915_driver_load(struct drm_device *dev, unsigned long flags)
{ {
struct drm_i915_private *dev_priv; struct drm_i915_private *dev_priv;
struct intel_device_info *info;
int ret = 0, mmio_bar; int ret = 0, mmio_bar;
uint32_t agp_size; uint32_t aperture_size;
info = (struct intel_device_info *) flags;
/* Refuse to load on gen6+ without kms enabled. */
if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
/* i915 has 4 more counters */ /* i915 has 4 more counters */
dev->counters += 4; dev->counters += 4;
...@@ -1961,7 +1997,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1961,7 +1997,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = (void *)dev_priv; dev->dev_private = (void *)dev_priv;
dev_priv->dev = dev; dev_priv->dev = dev;
dev_priv->info = (struct intel_device_info *) flags; dev_priv->info = info;
if (i915_get_bridge_dev(dev)) { if (i915_get_bridge_dev(dev)) {
ret = -EIO; ret = -EIO;
...@@ -2000,27 +2036,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -2000,27 +2036,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto out_rmmap; goto out_rmmap;
} }
agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
dev_priv->mm.gtt_mapping = dev_priv->mm.gtt_mapping =
io_mapping_create_wc(dev->agp->base, agp_size); io_mapping_create_wc(dev->agp->base, aperture_size);
if (dev_priv->mm.gtt_mapping == NULL) { if (dev_priv->mm.gtt_mapping == NULL) {
ret = -EIO; ret = -EIO;
goto out_rmmap; goto out_rmmap;
} }
/* Set up a WC MTRR for non-PAT systems. This is more common than i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size);
* one would think, because the kernel disables PAT on first
* generation Core chips because WC PAT gets overridden by a UC
* MTRR if present. Even if a UC MTRR isn't present.
*/
dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
agp_size,
MTRR_TYPE_WRCOMB, 1);
if (dev_priv->mm.gtt_mtrr < 0) {
DRM_INFO("MTRR allocation failed. Graphics "
"performance may suffer.\n");
}
/* The i915 workqueue is primarily used for batched retirement of /* The i915 workqueue is primarily used for batched retirement of
* requests (and thus managing bo) once the task has been completed * requests (and thus managing bo) once the task has been completed
...@@ -2272,7 +2297,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) ...@@ -2272,7 +2297,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
* mode setting case, we want to restore the kernel's initial mode (just * mode setting case, we want to restore the kernel's initial mode (just
* in case the last client left us in a bad state). * in case the last client left us in a bad state).
* *
* Additionally, in the non-mode setting case, we'll tear down the AGP * Additionally, in the non-mode setting case, we'll tear down the GTT
* and DMA structures, since the kernel won't be using them, and clea * and DMA structures, since the kernel won't be using them, and clea
* up any GEM state. * up any GEM state.
*/ */
...@@ -2350,16 +2375,10 @@ struct drm_ioctl_desc i915_ioctls[] = { ...@@ -2350,16 +2375,10 @@ struct drm_ioctl_desc i915_ioctls[] = {
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
/** /*
* Determine if the device really is AGP or not. * This is really ugly: Because old userspace abused the linux agp interface to
* * manage the gtt, we need to claim that all intel devices are agp. For
* All Intel graphics chipsets are treated as AGP, even if they are really * otherwise the drm core refuses to initialize the agp support code.
* PCI-e.
*
* \param dev The device to be tested.
*
* \returns
* A value of 1 is always retured to indictate every i9x5 is AGP.
*/ */
int i915_driver_device_is_agp(struct drm_device * dev) int i915_driver_device_is_agp(struct drm_device * dev)
{ {
......
...@@ -84,6 +84,12 @@ MODULE_PARM_DESC(lvds_downclock, ...@@ -84,6 +84,12 @@ MODULE_PARM_DESC(lvds_downclock,
"Use panel (LVDS/eDP) downclocking for power savings " "Use panel (LVDS/eDP) downclocking for power savings "
"(default: false)"); "(default: false)");
int i915_lvds_channel_mode __read_mostly;
module_param_named(lvds_channel_mode, i915_lvds_channel_mode, int, 0600);
MODULE_PARM_DESC(lvds_channel_mode,
"Specify LVDS channel mode "
"(0=probe BIOS [default], 1=single-channel, 2=dual-channel)");
int i915_panel_use_ssc __read_mostly = -1; int i915_panel_use_ssc __read_mostly = -1;
module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600); module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
MODULE_PARM_DESC(lvds_use_ssc, MODULE_PARM_DESC(lvds_use_ssc,
...@@ -93,8 +99,8 @@ MODULE_PARM_DESC(lvds_use_ssc, ...@@ -93,8 +99,8 @@ MODULE_PARM_DESC(lvds_use_ssc,
int i915_vbt_sdvo_panel_type __read_mostly = -1; int i915_vbt_sdvo_panel_type __read_mostly = -1;
module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600); module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
MODULE_PARM_DESC(vbt_sdvo_panel_type, MODULE_PARM_DESC(vbt_sdvo_panel_type,
"Override selection of SDVO panel mode in the VBT " "Override/Ignore selection of SDVO panel mode in the VBT "
"(default: auto)"); "(-2=ignore, -1=auto [default], index in VBT BIOS table)");
static bool i915_try_reset __read_mostly = true; static bool i915_try_reset __read_mostly = true;
module_param_named(reset, i915_try_reset, bool, 0600); module_param_named(reset, i915_try_reset, bool, 0600);
...@@ -209,6 +215,7 @@ static const struct intel_device_info intel_ironlake_d_info = { ...@@ -209,6 +215,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
.gen = 5, .gen = 5,
.need_gfx_hws = 1, .has_hotplug = 1, .need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1, .has_bsd_ring = 1,
.has_pch_split = 1,
}; };
static const struct intel_device_info intel_ironlake_m_info = { static const struct intel_device_info intel_ironlake_m_info = {
...@@ -216,6 +223,7 @@ static const struct intel_device_info intel_ironlake_m_info = { ...@@ -216,6 +223,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
.need_gfx_hws = 1, .has_hotplug = 1, .need_gfx_hws = 1, .has_hotplug = 1,
.has_fbc = 1, .has_fbc = 1,
.has_bsd_ring = 1, .has_bsd_ring = 1,
.has_pch_split = 1,
}; };
static const struct intel_device_info intel_sandybridge_d_info = { static const struct intel_device_info intel_sandybridge_d_info = {
...@@ -224,6 +232,7 @@ static const struct intel_device_info intel_sandybridge_d_info = { ...@@ -224,6 +232,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {
.has_bsd_ring = 1, .has_bsd_ring = 1,
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1,
}; };
static const struct intel_device_info intel_sandybridge_m_info = { static const struct intel_device_info intel_sandybridge_m_info = {
...@@ -233,6 +242,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { ...@@ -233,6 +242,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
.has_bsd_ring = 1, .has_bsd_ring = 1,
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1,
}; };
static const struct intel_device_info intel_ivybridge_d_info = { static const struct intel_device_info intel_ivybridge_d_info = {
...@@ -241,6 +251,7 @@ static const struct intel_device_info intel_ivybridge_d_info = { ...@@ -241,6 +251,7 @@ static const struct intel_device_info intel_ivybridge_d_info = {
.has_bsd_ring = 1, .has_bsd_ring = 1,
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1,
}; };
static const struct intel_device_info intel_ivybridge_m_info = { static const struct intel_device_info intel_ivybridge_m_info = {
...@@ -250,6 +261,43 @@ static const struct intel_device_info intel_ivybridge_m_info = { ...@@ -250,6 +261,43 @@ static const struct intel_device_info intel_ivybridge_m_info = {
.has_bsd_ring = 1, .has_bsd_ring = 1,
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1,
};
static const struct intel_device_info intel_valleyview_m_info = {
.gen = 7, .is_mobile = 1,
.need_gfx_hws = 1, .has_hotplug = 1,
.has_fbc = 0,
.has_bsd_ring = 1,
.has_blt_ring = 1,
.is_valleyview = 1,
};
static const struct intel_device_info intel_valleyview_d_info = {
.gen = 7,
.need_gfx_hws = 1, .has_hotplug = 1,
.has_fbc = 0,
.has_bsd_ring = 1,
.has_blt_ring = 1,
.is_valleyview = 1,
};
static const struct intel_device_info intel_haswell_d_info = {
.is_haswell = 1, .gen = 7,
.need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
.has_blt_ring = 1,
.has_llc = 1,
.has_pch_split = 1,
};
static const struct intel_device_info intel_haswell_m_info = {
.is_haswell = 1, .gen = 7, .is_mobile = 1,
.need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
.has_blt_ring = 1,
.has_llc = 1,
.has_pch_split = 1,
}; };
static const struct pci_device_id pciidlist[] = { /* aka */ static const struct pci_device_id pciidlist[] = { /* aka */
...@@ -308,6 +356,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist); ...@@ -308,6 +356,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00 #define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00
#define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00 #define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00
#define INTEL_PCH_LPT_DEVICE_ID_TYPE 0x8c00
void intel_detect_pch(struct drm_device *dev) void intel_detect_pch(struct drm_device *dev)
{ {
...@@ -336,6 +385,9 @@ void intel_detect_pch(struct drm_device *dev) ...@@ -336,6 +385,9 @@ void intel_detect_pch(struct drm_device *dev)
/* PantherPoint is CPT compatible */ /* PantherPoint is CPT compatible */
dev_priv->pch_type = PCH_CPT; dev_priv->pch_type = PCH_CPT;
DRM_DEBUG_KMS("Found PatherPoint PCH\n"); DRM_DEBUG_KMS("Found PatherPoint PCH\n");
} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_LPT;
DRM_DEBUG_KMS("Found LynxPoint PCH\n");
} }
} }
pci_dev_put(pch); pci_dev_put(pch);
...@@ -446,6 +498,31 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) ...@@ -446,6 +498,31 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
return ret; return ret;
} }
void vlv_force_wake_get(struct drm_i915_private *dev_priv)
{
int count;
count = 0;
/* Already awake? */
if ((I915_READ(0x130094) & 0xa1) == 0xa1)
return;
I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
POSTING_READ(FORCEWAKE_VLV);
count = 0;
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0)
udelay(10);
}
void vlv_force_wake_put(struct drm_i915_private *dev_priv)
{
I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000);
/* FIXME: confirm VLV behavior with Punit folks */
POSTING_READ(FORCEWAKE_VLV);
}
static int i915_drm_freeze(struct drm_device *dev) static int i915_drm_freeze(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -993,6 +1070,13 @@ MODULE_AUTHOR(DRIVER_AUTHOR); ...@@ -993,6 +1070,13 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights"); MODULE_LICENSE("GPL and additional rights");
/* We give fast paths for the really cool registers */
#define NEEDS_FORCE_WAKE(dev_priv, reg) \
(((dev_priv)->info->gen >= 6) && \
((reg) < 0x40000) && \
((reg) != FORCEWAKE)) && \
(!IS_VALLEYVIEW((dev_priv)->dev))
#define __i915_read(x, y) \ #define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
u##x val = 0; \ u##x val = 0; \
......
...@@ -63,6 +63,16 @@ enum plane { ...@@ -63,6 +63,16 @@ enum plane {
}; };
#define plane_name(p) ((p) + 'A') #define plane_name(p) ((p) + 'A')
enum port {
PORT_A = 0,
PORT_B,
PORT_C,
PORT_D,
PORT_E,
I915_MAX_PORTS
};
#define port_name(p) ((p) + 'A')
#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
#define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++)
...@@ -255,6 +265,9 @@ struct intel_device_info { ...@@ -255,6 +265,9 @@ struct intel_device_info {
u8 is_broadwater:1; u8 is_broadwater:1;
u8 is_crestline:1; u8 is_crestline:1;
u8 is_ivybridge:1; u8 is_ivybridge:1;
u8 is_valleyview:1;
u8 has_pch_split:1;
u8 is_haswell:1;
u8 has_fbc:1; u8 has_fbc:1;
u8 has_pipe_cxsr:1; u8 has_pipe_cxsr:1;
u8 has_hotplug:1; u8 has_hotplug:1;
...@@ -291,10 +304,12 @@ enum no_fbc_reason { ...@@ -291,10 +304,12 @@ enum no_fbc_reason {
enum intel_pch { enum intel_pch {
PCH_IBX, /* Ibexpeak PCH */ PCH_IBX, /* Ibexpeak PCH */
PCH_CPT, /* Cougarpoint PCH */ PCH_CPT, /* Cougarpoint PCH */
PCH_LPT, /* Lynxpoint PCH */
}; };
#define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_PIPEA_FORCE (1<<0)
#define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_LVDS_SSC_DISABLE (1<<1)
#define QUIRK_INVERT_BRIGHTNESS (1<<2)
struct intel_fbdev; struct intel_fbdev;
struct intel_fbc_work; struct intel_fbc_work;
...@@ -302,7 +317,6 @@ struct intel_fbc_work; ...@@ -302,7 +317,6 @@ struct intel_fbc_work;
struct intel_gmbus { struct intel_gmbus {
struct i2c_adapter adapter; struct i2c_adapter adapter;
bool force_bit; bool force_bit;
bool has_gpio;
u32 reg0; u32 reg0;
u32 gpio_reg; u32 gpio_reg;
struct i2c_algo_bit_data bit_algo; struct i2c_algo_bit_data bit_algo;
...@@ -326,12 +340,17 @@ typedef struct drm_i915_private { ...@@ -326,12 +340,17 @@ typedef struct drm_i915_private {
/** gt_lock is also taken in irq contexts. */ /** gt_lock is also taken in irq contexts. */
struct spinlock gt_lock; struct spinlock gt_lock;
struct intel_gmbus *gmbus; struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
/** gmbus_mutex protects against concurrent usage of the single hw gmbus /** gmbus_mutex protects against concurrent usage of the single hw gmbus
* controller on different i2c buses. */ * controller on different i2c buses. */
struct mutex gmbus_mutex; struct mutex gmbus_mutex;
/**
* Base address of the gmbus and gpio block.
*/
uint32_t gpio_mmio_base;
struct pci_dev *bridge_dev; struct pci_dev *bridge_dev;
struct intel_ring_buffer ring[I915_NUM_RINGS]; struct intel_ring_buffer ring[I915_NUM_RINGS];
uint32_t next_seqno; uint32_t next_seqno;
...@@ -354,6 +373,10 @@ typedef struct drm_i915_private { ...@@ -354,6 +373,10 @@ typedef struct drm_i915_private {
/* protects the irq masks */ /* protects the irq masks */
spinlock_t irq_lock; spinlock_t irq_lock;
/* DPIO indirect register protection */
spinlock_t dpio_lock;
/** Cached value of IMR to avoid reads in updating the bitfield */ /** Cached value of IMR to avoid reads in updating the bitfield */
u32 pipestat[2]; u32 pipestat[2];
u32 irq_mask; u32 irq_mask;
...@@ -405,6 +428,8 @@ typedef struct drm_i915_private { ...@@ -405,6 +428,8 @@ typedef struct drm_i915_private {
unsigned int lvds_use_ssc:1; unsigned int lvds_use_ssc:1;
unsigned int display_clock_mode:1; unsigned int display_clock_mode:1;
int lvds_ssc_freq; int lvds_ssc_freq;
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
unsigned int lvds_val; /* used for checking LVDS channel mode */
struct { struct {
int rate; int rate;
int lanes; int lanes;
...@@ -881,6 +906,7 @@ struct drm_i915_gem_object { ...@@ -881,6 +906,7 @@ struct drm_i915_gem_object {
unsigned int cache_level:2; unsigned int cache_level:2;
unsigned int has_aliasing_ppgtt_mapping:1; unsigned int has_aliasing_ppgtt_mapping:1;
unsigned int has_global_gtt_mapping:1;
struct page **pages; struct page **pages;
...@@ -918,13 +944,6 @@ struct drm_i915_gem_object { ...@@ -918,13 +944,6 @@ struct drm_i915_gem_object {
/** Record of address bit 17 of each page at last unbind. */ /** Record of address bit 17 of each page at last unbind. */
unsigned long *bit_17; unsigned long *bit_17;
/**
* If present, while GEM_DOMAIN_CPU is in the read domain this array
* flags which individual pages are valid.
*/
uint8_t *page_cpu_valid;
/** User space pin count and filp owning the pin */ /** User space pin count and filp owning the pin */
uint32_t user_pin_count; uint32_t user_pin_count;
struct drm_file *pin_filp; struct drm_file *pin_filp;
...@@ -1001,6 +1020,8 @@ struct drm_i915_file_private { ...@@ -1001,6 +1020,8 @@ struct drm_i915_file_private {
#define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) #define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042)
#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046)
#define IS_IVYBRIDGE(dev) (INTEL_INFO(dev)->is_ivybridge) #define IS_IVYBRIDGE(dev) (INTEL_INFO(dev)->is_ivybridge)
#define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview)
#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
/* /*
...@@ -1044,10 +1065,11 @@ struct drm_i915_file_private { ...@@ -1044,10 +1065,11 @@ struct drm_i915_file_private {
#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) #define HAS_PCH_SPLIT(dev) (INTEL_INFO(dev)->has_pch_split)
#define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)
#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
...@@ -1081,6 +1103,7 @@ extern int i915_panel_ignore_lid __read_mostly; ...@@ -1081,6 +1103,7 @@ extern int i915_panel_ignore_lid __read_mostly;
extern unsigned int i915_powersave __read_mostly; extern unsigned int i915_powersave __read_mostly;
extern int i915_semaphores __read_mostly; extern int i915_semaphores __read_mostly;
extern unsigned int i915_lvds_downclock __read_mostly; extern unsigned int i915_lvds_downclock __read_mostly;
extern int i915_lvds_channel_mode __read_mostly;
extern int i915_panel_use_ssc __read_mostly; extern int i915_panel_use_ssc __read_mostly;
extern int i915_vbt_sdvo_panel_type __read_mostly; extern int i915_vbt_sdvo_panel_type __read_mostly;
extern int i915_enable_rc6 __read_mostly; extern int i915_enable_rc6 __read_mostly;
...@@ -1264,10 +1287,6 @@ int __must_check i915_gem_init_hw(struct drm_device *dev); ...@@ -1264,10 +1287,6 @@ int __must_check i915_gem_init_hw(struct drm_device *dev);
void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_init_swizzling(struct drm_device *dev);
void i915_gem_init_ppgtt(struct drm_device *dev); void i915_gem_init_ppgtt(struct drm_device *dev);
void i915_gem_cleanup_ringbuffer(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
void i915_gem_do_init(struct drm_device *dev,
unsigned long start,
unsigned long mappable_end,
unsigned long end);
int __must_check i915_gpu_idle(struct drm_device *dev, bool do_retire); int __must_check i915_gpu_idle(struct drm_device *dev, bool do_retire);
int __must_check i915_gem_idle(struct drm_device *dev); int __must_check i915_gem_idle(struct drm_device *dev);
int __must_check i915_add_request(struct intel_ring_buffer *ring, int __must_check i915_add_request(struct intel_ring_buffer *ring,
...@@ -1281,6 +1300,8 @@ int __must_check ...@@ -1281,6 +1300,8 @@ int __must_check
i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
bool write); bool write);
int __must_check int __must_check
i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write);
int __must_check
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 alignment, u32 alignment,
struct intel_ring_buffer *pipelined); struct intel_ring_buffer *pipelined);
...@@ -1311,10 +1332,15 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, ...@@ -1311,10 +1332,15 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
void i915_gem_restore_gtt_mappings(struct drm_device *dev); void i915_gem_restore_gtt_mappings(struct drm_device *dev);
int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj); int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level); enum i915_cache_level cache_level);
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj); void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
void i915_gem_init_global_gtt(struct drm_device *dev,
unsigned long start,
unsigned long mappable_end,
unsigned long end);
/* i915_gem_evict.c */ /* i915_gem_evict.c */
int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size, int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size,
...@@ -1357,6 +1383,13 @@ extern int i915_restore_state(struct drm_device *dev); ...@@ -1357,6 +1383,13 @@ extern int i915_restore_state(struct drm_device *dev);
/* intel_i2c.c */ /* intel_i2c.c */
extern int intel_setup_gmbus(struct drm_device *dev); extern int intel_setup_gmbus(struct drm_device *dev);
extern void intel_teardown_gmbus(struct drm_device *dev); extern void intel_teardown_gmbus(struct drm_device *dev);
extern inline bool intel_gmbus_is_port_valid(unsigned port)
{
return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD);
}
extern struct i2c_adapter *intel_gmbus_get_adapter(
struct drm_i915_private *dev_priv, unsigned port);
extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
...@@ -1409,6 +1442,9 @@ extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv); ...@@ -1409,6 +1442,9 @@ extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv);
extern void vlv_force_wake_get(struct drm_i915_private *dev_priv);
extern void vlv_force_wake_put(struct drm_i915_private *dev_priv);
/* overlay */ /* overlay */
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
...@@ -1450,12 +1486,6 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); ...@@ -1450,12 +1486,6 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
/* We give fast paths for the really cool registers */
#define NEEDS_FORCE_WAKE(dev_priv, reg) \
(((dev_priv)->info->gen >= 6) && \
((reg) < 0x40000) && \
((reg) != FORCEWAKE))
#define __i915_read(x, y) \ #define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
......
This diff is collapsed.
...@@ -266,6 +266,12 @@ eb_destroy(struct eb_objects *eb) ...@@ -266,6 +266,12 @@ eb_destroy(struct eb_objects *eb)
kfree(eb); kfree(eb);
} }
static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
{
return (obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
obj->cache_level != I915_CACHE_NONE);
}
static int static int
i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
struct eb_objects *eb, struct eb_objects *eb,
...@@ -273,6 +279,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, ...@@ -273,6 +279,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
{ {
struct drm_device *dev = obj->base.dev; struct drm_device *dev = obj->base.dev;
struct drm_gem_object *target_obj; struct drm_gem_object *target_obj;
struct drm_i915_gem_object *target_i915_obj;
uint32_t target_offset; uint32_t target_offset;
int ret = -EINVAL; int ret = -EINVAL;
...@@ -281,7 +288,8 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, ...@@ -281,7 +288,8 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
if (unlikely(target_obj == NULL)) if (unlikely(target_obj == NULL))
return -ENOENT; return -ENOENT;
target_offset = to_intel_bo(target_obj)->gtt_offset; target_i915_obj = to_intel_bo(target_obj);
target_offset = target_i915_obj->gtt_offset;
/* The target buffer should have appeared before us in the /* The target buffer should have appeared before us in the
* exec_object list, so it should have a GTT space bound by now. * exec_object list, so it should have a GTT space bound by now.
...@@ -352,11 +360,19 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, ...@@ -352,11 +360,19 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
return ret; return ret;
} }
/* We can't wait for rendering with pagefaults disabled */
if (obj->active && in_atomic())
return -EFAULT;
reloc->delta += target_offset; reloc->delta += target_offset;
if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { if (use_cpu_reloc(obj)) {
uint32_t page_offset = reloc->offset & ~PAGE_MASK; uint32_t page_offset = reloc->offset & ~PAGE_MASK;
char *vaddr; char *vaddr;
ret = i915_gem_object_set_to_cpu_domain(obj, 1);
if (ret)
return ret;
vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]); vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]);
*(uint32_t *)(vaddr + page_offset) = reloc->delta; *(uint32_t *)(vaddr + page_offset) = reloc->delta;
kunmap_atomic(vaddr); kunmap_atomic(vaddr);
...@@ -365,10 +381,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, ...@@ -365,10 +381,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
uint32_t __iomem *reloc_entry; uint32_t __iomem *reloc_entry;
void __iomem *reloc_page; void __iomem *reloc_page;
/* We can't wait for rendering with pagefaults disabled */
if (obj->active && in_atomic())
return -EFAULT;
ret = i915_gem_object_set_to_gtt_domain(obj, 1); ret = i915_gem_object_set_to_gtt_domain(obj, 1);
if (ret) if (ret)
return ret; return ret;
...@@ -383,6 +395,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, ...@@ -383,6 +395,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
io_mapping_unmap_atomic(reloc_page); io_mapping_unmap_atomic(reloc_page);
} }
/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
* pipe_control writes because the gpu doesn't properly redirect them
* through the ppgtt for non_secure batchbuffers. */
if (unlikely(IS_GEN6(dev) &&
reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
!target_i915_obj->has_global_gtt_mapping)) {
i915_gem_gtt_bind_object(target_i915_obj,
target_i915_obj->cache_level);
}
/* and update the user's relocation entry */ /* and update the user's relocation entry */
reloc->presumed_offset = target_offset; reloc->presumed_offset = target_offset;
...@@ -393,30 +415,46 @@ static int ...@@ -393,30 +415,46 @@ static int
i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
struct eb_objects *eb) struct eb_objects *eb)
{ {
#define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry))
struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)];
struct drm_i915_gem_relocation_entry __user *user_relocs; struct drm_i915_gem_relocation_entry __user *user_relocs;
struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
int i, ret; int remain, ret;
user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
for (i = 0; i < entry->relocation_count; i++) {
struct drm_i915_gem_relocation_entry reloc;
if (__copy_from_user_inatomic(&reloc, remain = entry->relocation_count;
user_relocs+i, while (remain) {
sizeof(reloc))) struct drm_i915_gem_relocation_entry *r = stack_reloc;
int count = remain;
if (count > ARRAY_SIZE(stack_reloc))
count = ARRAY_SIZE(stack_reloc);
remain -= count;
if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0])))
return -EFAULT; return -EFAULT;
ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc); do {
if (ret) u64 offset = r->presumed_offset;
return ret;
if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, ret = i915_gem_execbuffer_relocate_entry(obj, eb, r);
&reloc.presumed_offset, if (ret)
sizeof(reloc.presumed_offset))) return ret;
return -EFAULT;
if (r->presumed_offset != offset &&
__copy_to_user_inatomic(&user_relocs->presumed_offset,
&r->presumed_offset,
sizeof(r->presumed_offset))) {
return -EFAULT;
}
user_relocs++;
r++;
} while (--count);
} }
return 0; return 0;
#undef N_RELOC
} }
static int static int
...@@ -464,6 +502,13 @@ i915_gem_execbuffer_relocate(struct drm_device *dev, ...@@ -464,6 +502,13 @@ i915_gem_execbuffer_relocate(struct drm_device *dev,
#define __EXEC_OBJECT_HAS_FENCE (1<<31) #define __EXEC_OBJECT_HAS_FENCE (1<<31)
static int
need_reloc_mappable(struct drm_i915_gem_object *obj)
{
struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
return entry->relocation_count && !use_cpu_reloc(obj);
}
static int static int
pin_and_fence_object(struct drm_i915_gem_object *obj, pin_and_fence_object(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
...@@ -477,8 +522,7 @@ pin_and_fence_object(struct drm_i915_gem_object *obj, ...@@ -477,8 +522,7 @@ pin_and_fence_object(struct drm_i915_gem_object *obj,
has_fenced_gpu_access && has_fenced_gpu_access &&
entry->flags & EXEC_OBJECT_NEEDS_FENCE && entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
obj->tiling_mode != I915_TILING_NONE; obj->tiling_mode != I915_TILING_NONE;
need_mappable = need_mappable = need_fence || need_reloc_mappable(obj);
entry->relocation_count ? true : need_fence;
ret = i915_gem_object_pin(obj, entry->alignment, need_mappable); ret = i915_gem_object_pin(obj, entry->alignment, need_mappable);
if (ret) if (ret)
...@@ -535,8 +579,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, ...@@ -535,8 +579,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
has_fenced_gpu_access && has_fenced_gpu_access &&
entry->flags & EXEC_OBJECT_NEEDS_FENCE && entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
obj->tiling_mode != I915_TILING_NONE; obj->tiling_mode != I915_TILING_NONE;
need_mappable = need_mappable = need_fence || need_reloc_mappable(obj);
entry->relocation_count ? true : need_fence;
if (need_mappable) if (need_mappable)
list_move(&obj->exec_list, &ordered_objects); list_move(&obj->exec_list, &ordered_objects);
...@@ -576,8 +619,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, ...@@ -576,8 +619,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
has_fenced_gpu_access && has_fenced_gpu_access &&
entry->flags & EXEC_OBJECT_NEEDS_FENCE && entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
obj->tiling_mode != I915_TILING_NONE; obj->tiling_mode != I915_TILING_NONE;
need_mappable = need_mappable = need_fence || need_reloc_mappable(obj);
entry->relocation_count ? true : need_fence;
if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) || if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) ||
(need_mappable && !obj->map_and_fenceable)) (need_mappable && !obj->map_and_fenceable))
...@@ -955,7 +997,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, ...@@ -955,7 +997,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
if (!access_ok(VERIFY_WRITE, ptr, length)) if (!access_ok(VERIFY_WRITE, ptr, length))
return -EFAULT; return -EFAULT;
if (fault_in_pages_readable(ptr, length)) if (fault_in_multipages_readable(ptr, length))
return -EFAULT; return -EFAULT;
} }
......
...@@ -346,42 +346,28 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) ...@@ -346,42 +346,28 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) { list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
i915_gem_clflush_object(obj); i915_gem_clflush_object(obj);
i915_gem_gtt_rebind_object(obj, obj->cache_level); i915_gem_gtt_bind_object(obj, obj->cache_level);
} }
intel_gtt_chipset_flush(); intel_gtt_chipset_flush();
} }
int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj) int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev; struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
unsigned int agp_type = cache_level_to_agp_type(dev, obj->cache_level);
int ret;
if (dev_priv->mm.gtt->needs_dmar) { if (dev_priv->mm.gtt->needs_dmar)
ret = intel_gtt_map_memory(obj->pages, return intel_gtt_map_memory(obj->pages,
obj->base.size >> PAGE_SHIFT, obj->base.size >> PAGE_SHIFT,
&obj->sg_list, &obj->sg_list,
&obj->num_sg); &obj->num_sg);
if (ret != 0) else
return ret; return 0;
intel_gtt_insert_sg_entries(obj->sg_list,
obj->num_sg,
obj->gtt_space->start >> PAGE_SHIFT,
agp_type);
} else
intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
obj->base.size >> PAGE_SHIFT,
obj->pages,
agp_type);
return 0;
} }
void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level) enum i915_cache_level cache_level)
{ {
struct drm_device *dev = obj->base.dev; struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -399,9 +385,19 @@ void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, ...@@ -399,9 +385,19 @@ void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
obj->base.size >> PAGE_SHIFT, obj->base.size >> PAGE_SHIFT,
obj->pages, obj->pages,
agp_type); agp_type);
obj->has_global_gtt_mapping = 1;
} }
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
{
intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
obj->base.size >> PAGE_SHIFT);
obj->has_global_gtt_mapping = 0;
}
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev; struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -409,9 +405,6 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) ...@@ -409,9 +405,6 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
interruptible = do_idling(dev_priv); interruptible = do_idling(dev_priv);
intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
obj->base.size >> PAGE_SHIFT);
if (obj->sg_list) { if (obj->sg_list) {
intel_gtt_unmap_memory(obj->sg_list, obj->num_sg); intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);
obj->sg_list = NULL; obj->sg_list = NULL;
...@@ -419,3 +412,23 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) ...@@ -419,3 +412,23 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
undo_idling(dev_priv, interruptible); undo_idling(dev_priv, interruptible);
} }
void i915_gem_init_global_gtt(struct drm_device *dev,
unsigned long start,
unsigned long mappable_end,
unsigned long end)
{
drm_i915_private_t *dev_priv = dev->dev_private;
/* Substract the guard page ... */
drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE);
dev_priv->mm.gtt_start = start;
dev_priv->mm.gtt_mappable_end = mappable_end;
dev_priv->mm.gtt_end = end;
dev_priv->mm.gtt_total = end - start;
dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
/* ... but ensure that we clear the entire range. */
intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE);
}
This diff is collapsed.
This diff is collapsed.
...@@ -182,8 +182,6 @@ static void intel_dsm_platform_mux_info(void) ...@@ -182,8 +182,6 @@ static void intel_dsm_platform_mux_info(void)
DRM_DEBUG_DRIVER(" hpd mux info: %s\n", DRM_DEBUG_DRIVER(" hpd mux info: %s\n",
intel_dsm_mux_type(info->buffer.pointer[3])); intel_dsm_mux_type(info->buffer.pointer[3]));
} }
} else {
DRM_ERROR("MUX INFO call failed\n");
} }
out: out:
......
...@@ -174,6 +174,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data, ...@@ -174,6 +174,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
} }
/* get lvds_fp_timing entry
* this function may return NULL if the corresponding entry is invalid
*/
static const struct lvds_fp_timing *
get_lvds_fp_timing(const struct bdb_header *bdb,
const struct bdb_lvds_lfp_data *data,
const struct bdb_lvds_lfp_data_ptrs *ptrs,
int index)
{
size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
size_t ofs;
if (index >= ARRAY_SIZE(ptrs->ptr))
return NULL;
ofs = ptrs->ptr[index].fp_timing_offset;
if (ofs < data_ofs ||
ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
return NULL;
return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
}
/* Try to find integrated panel data */ /* Try to find integrated panel data */
static void static void
parse_lfp_panel_data(struct drm_i915_private *dev_priv, parse_lfp_panel_data(struct drm_i915_private *dev_priv,
...@@ -183,6 +205,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -183,6 +205,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
const struct bdb_lvds_lfp_data *lvds_lfp_data; const struct bdb_lvds_lfp_data *lvds_lfp_data;
const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
const struct lvds_dvo_timing *panel_dvo_timing; const struct lvds_dvo_timing *panel_dvo_timing;
const struct lvds_fp_timing *fp_timing;
struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *panel_fixed_mode;
int i, downclock; int i, downclock;
...@@ -244,6 +267,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -244,6 +267,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
"Normal Clock %dKHz, downclock %dKHz\n", "Normal Clock %dKHz, downclock %dKHz\n",
panel_fixed_mode->clock, 10*downclock); panel_fixed_mode->clock, 10*downclock);
} }
fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
lvds_lfp_data_ptrs,
lvds_options->panel_type);
if (fp_timing) {
/* check the resolution, just to be sure */
if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
fp_timing->y_res == panel_fixed_mode->vdisplay) {
dev_priv->bios_lvds_val = fp_timing->lvds_reg_val;
DRM_DEBUG_KMS("VBT initial LVDS value %x\n",
dev_priv->bios_lvds_val);
}
}
} }
/* Try to find sdvo panel data */ /* Try to find sdvo panel data */
...@@ -256,6 +292,11 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, ...@@ -256,6 +292,11 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
int index; int index;
index = i915_vbt_sdvo_panel_type; index = i915_vbt_sdvo_panel_type;
if (index == -2) {
DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n");
return;
}
if (index == -1) { if (index == -1) {
struct bdb_sdvo_lvds_options *sdvo_lvds_options; struct bdb_sdvo_lvds_options *sdvo_lvds_options;
...@@ -332,11 +373,11 @@ parse_general_definitions(struct drm_i915_private *dev_priv, ...@@ -332,11 +373,11 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
if (block_size >= sizeof(*general)) { if (block_size >= sizeof(*general)) {
int bus_pin = general->crt_ddc_gmbus_pin; int bus_pin = general->crt_ddc_gmbus_pin;
DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
if (bus_pin >= 1 && bus_pin <= 6) if (intel_gmbus_is_port_valid(bus_pin))
dev_priv->crt_ddc_pin = bus_pin; dev_priv->crt_ddc_pin = bus_pin;
} else { } else {
DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
block_size); block_size);
} }
} }
} }
......
...@@ -278,9 +278,10 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) ...@@ -278,9 +278,10 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) { if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
struct edid *edid; struct edid *edid;
bool is_digital = false; bool is_digital = false;
struct i2c_adapter *i2c;
edid = drm_get_edid(connector, i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); edid = drm_get_edid(connector, i2c);
/* /*
* This may be a DVI-I connector with a shared DDC * This may be a DVI-I connector with a shared DDC
* link between analog and digital outputs, so we * link between analog and digital outputs, so we
...@@ -483,15 +484,16 @@ static int intel_crt_get_modes(struct drm_connector *connector) ...@@ -483,15 +484,16 @@ static int intel_crt_get_modes(struct drm_connector *connector)
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int ret; int ret;
struct i2c_adapter *i2c;
ret = intel_ddc_get_modes(connector, i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); ret = intel_ddc_get_modes(connector, i2c);
if (ret || !IS_G4X(dev)) if (ret || !IS_G4X(dev))
return ret; return ret;
/* Try to probe digital port for output in DVI-I -> VGA mode. */ /* Try to probe digital port for output in DVI-I -> VGA mode. */
return intel_ddc_get_modes(connector, i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
&dev_priv->gmbus[GMBUS_PORT_DPB].adapter); return intel_ddc_get_modes(connector, i2c);
} }
static int intel_crt_set_property(struct drm_connector *connector, static int intel_crt_set_property(struct drm_connector *connector,
...@@ -543,7 +545,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { ...@@ -543,7 +545,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id) static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
{ {
DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident); DRM_INFO("Skipping CRT initialization for %s\n", id->ident);
return 1; return 1;
} }
......
This diff is collapsed.
...@@ -45,6 +45,18 @@ ...@@ -45,6 +45,18 @@
ret__; \ ret__; \
}) })
#define wait_for_atomic_us(COND, US) ({ \
int i, ret__ = -ETIMEDOUT; \
for (i = 0; i < (US); i++) { \
if ((COND)) { \
ret__ = 0; \
break; \
} \
udelay(1); \
} \
ret__; \
})
#define wait_for(COND, MS) _wait_for(COND, MS, 1) #define wait_for(COND, MS) _wait_for(COND, MS, 1)
#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) #define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
...@@ -293,7 +305,8 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector) ...@@ -293,7 +305,8 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector)
extern void intel_crt_init(struct drm_device *dev); extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device); extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
bool is_sdvob);
extern void intel_dvo_init(struct drm_device *dev); extern void intel_dvo_init(struct drm_device *dev);
extern void intel_tv_init(struct drm_device *dev); extern void intel_tv_init(struct drm_device *dev);
extern void intel_mark_busy(struct drm_device *dev, extern void intel_mark_busy(struct drm_device *dev,
...@@ -419,4 +432,6 @@ extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, ...@@ -419,4 +432,6 @@ extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data, extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg);
#endif /* __INTEL_DRV_H__ */ #endif /* __INTEL_DRV_H__ */
...@@ -243,7 +243,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector) ...@@ -243,7 +243,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
* that's not the case. * that's not the case.
*/ */
intel_ddc_get_modes(connector, intel_ddc_get_modes(connector,
&dev_priv->gmbus[GMBUS_PORT_DPC].adapter); intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPC));
if (!list_empty(&connector->probed_modes)) if (!list_empty(&connector->probed_modes))
return 1; return 1;
...@@ -375,7 +375,7 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -375,7 +375,7 @@ void intel_dvo_init(struct drm_device *dev)
* special cases, but otherwise default to what's defined * special cases, but otherwise default to what's defined
* in the spec. * in the spec.
*/ */
if (dvo->gpio != 0) if (intel_gmbus_is_port_valid(dvo->gpio))
gpio = dvo->gpio; gpio = dvo->gpio;
else if (dvo->type == INTEL_DVO_CHIP_LVDS) else if (dvo->type == INTEL_DVO_CHIP_LVDS)
gpio = GMBUS_PORT_SSC; gpio = GMBUS_PORT_SSC;
...@@ -386,7 +386,7 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -386,7 +386,7 @@ void intel_dvo_init(struct drm_device *dev)
* It appears that everything is on GPIOE except for panels * It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA). * on i830 laptops, which are on GPIOB (DVOA).
*/ */
i2c = &dev_priv->gmbus[gpio].adapter; i2c = intel_gmbus_get_adapter(dev_priv, gpio);
intel_dvo->dev = *dvo; intel_dvo->dev = *dvo;
if (!dvo->dev_ops->init(&intel_dvo->dev, i2c)) if (!dvo->dev_ops->init(&intel_dvo->dev, i2c))
......
...@@ -177,6 +177,37 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder, ...@@ -177,6 +177,37 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder,
I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
} }
static void vlv_write_infoframe(struct drm_encoder *encoder,
struct dip_infoframe *frame)
{
uint32_t *data = (uint32_t *)frame;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
unsigned i, len = DIP_HEADER_SIZE + frame->len;
u32 flags, val = I915_READ(reg);
intel_wait_for_vblank(dev, intel_crtc->pipe);
flags = intel_infoframe_index(frame);
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
for (i = 0; i < len; i += 4) {
I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
data++;
}
flags |= intel_infoframe_flags(frame);
I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
}
static void intel_set_infoframe(struct drm_encoder *encoder, static void intel_set_infoframe(struct drm_encoder *encoder,
struct dip_infoframe *frame) struct dip_infoframe *frame)
{ {
...@@ -334,7 +365,8 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) ...@@ -334,7 +365,8 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_hdmi_sink = false;
intel_hdmi->has_audio = false; intel_hdmi->has_audio = false;
edid = drm_get_edid(connector, edid = drm_get_edid(connector,
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); intel_gmbus_get_adapter(dev_priv,
intel_hdmi->ddc_bus));
if (edid) { if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) { if (edid->input & DRM_EDID_INPUT_DIGITAL) {
...@@ -367,7 +399,8 @@ static int intel_hdmi_get_modes(struct drm_connector *connector) ...@@ -367,7 +399,8 @@ static int intel_hdmi_get_modes(struct drm_connector *connector)
*/ */
return intel_ddc_get_modes(connector, return intel_ddc_get_modes(connector,
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); intel_gmbus_get_adapter(dev_priv,
intel_hdmi->ddc_bus));
} }
static bool static bool
...@@ -379,7 +412,8 @@ intel_hdmi_detect_audio(struct drm_connector *connector) ...@@ -379,7 +412,8 @@ intel_hdmi_detect_audio(struct drm_connector *connector)
bool has_audio = false; bool has_audio = false;
edid = drm_get_edid(connector, edid = drm_get_edid(connector,
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); intel_gmbus_get_adapter(dev_priv,
intel_hdmi->ddc_bus));
if (edid) { if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) if (edid->input & DRM_EDID_INPUT_DIGITAL)
has_audio = drm_detect_monitor_audio(edid); has_audio = drm_detect_monitor_audio(edid);
...@@ -549,7 +583,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -549,7 +583,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
if (!HAS_PCH_SPLIT(dev)) { if (!HAS_PCH_SPLIT(dev)) {
intel_hdmi->write_infoframe = i9xx_write_infoframe; intel_hdmi->write_infoframe = i9xx_write_infoframe;
I915_WRITE(VIDEO_DIP_CTL, 0); I915_WRITE(VIDEO_DIP_CTL, 0);
} else { } else if (IS_VALLEYVIEW(dev)) {
intel_hdmi->write_infoframe = vlv_write_infoframe;
for_each_pipe(i)
I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0);
} else {
intel_hdmi->write_infoframe = ironlake_write_infoframe; intel_hdmi->write_infoframe = ironlake_write_infoframe;
for_each_pipe(i) for_each_pipe(i)
I915_WRITE(TVIDEO_DIP_CTL(i), 0); I915_WRITE(TVIDEO_DIP_CTL(i), 0);
......
This diff is collapsed.
...@@ -474,7 +474,7 @@ static int intel_lvds_get_modes(struct drm_connector *connector) ...@@ -474,7 +474,7 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id) static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
{ {
DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident); DRM_INFO("Skipping forced modeset for %s\n", id->ident);
return 1; return 1;
} }
...@@ -622,7 +622,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = { ...@@ -622,7 +622,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
{ {
DRM_DEBUG_KMS("Skipping LVDS initialization for %s\n", id->ident); DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
return 1; return 1;
} }
...@@ -845,8 +845,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, ...@@ -845,8 +845,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
child->device_type != DEVICE_TYPE_LFP) child->device_type != DEVICE_TYPE_LFP)
continue; continue;
if (child->i2c_pin) if (intel_gmbus_is_port_valid(child->i2c_pin))
*i2c_pin = child->i2c_pin; *i2c_pin = child->i2c_pin;
/* However, we cannot trust the BIOS writers to populate /* However, we cannot trust the BIOS writers to populate
* the VBT correctly. Since LVDS requires additional * the VBT correctly. Since LVDS requires additional
...@@ -987,7 +987,8 @@ bool intel_lvds_init(struct drm_device *dev) ...@@ -987,7 +987,8 @@ bool intel_lvds_init(struct drm_device *dev)
* preferred mode is the right one. * preferred mode is the right one.
*/ */
intel_lvds->edid = drm_get_edid(connector, intel_lvds->edid = drm_get_edid(connector,
&dev_priv->gmbus[pin].adapter); intel_gmbus_get_adapter(dev_priv,
pin));
if (intel_lvds->edid) { if (intel_lvds->edid) {
if (drm_add_edid_modes(connector, if (drm_add_edid_modes(connector,
intel_lvds->edid)) { intel_lvds->edid)) {
......
...@@ -56,7 +56,8 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) ...@@ -56,7 +56,8 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus)
} }
}; };
return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2; return i2c_transfer(intel_gmbus_get_adapter(dev_priv, ddc_bus),
msgs, 2) == 2;
} }
/** /**
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
* *
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/acpi_io.h> #include <linux/acpi_io.h>
#include <acpi/video.h> #include <acpi/video.h>
...@@ -355,7 +357,7 @@ static void intel_didl_outputs(struct drm_device *dev) ...@@ -355,7 +357,7 @@ static void intel_didl_outputs(struct drm_device *dev)
} }
if (!acpi_video_bus) { if (!acpi_video_bus) {
printk(KERN_WARNING "No ACPI video bus found\n"); pr_warn("No ACPI video bus found\n");
return; return;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment