From 311bf8c0a909df19d46199a82607382d27fa48e8 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 29 Nov 2010 21:07:53 -0500 Subject: [PATCH] un-rebase drm-intel-big-hammer & make-lvds-work, update would_have_oomkilled --- drm-intel-2.6.37-rc2.patch | 24423 ---------------- drm-intel-big-hammer.patch | 16 +- drm-intel-make-lvds-work.patch | 19 +- kernel.spec | 7 +- linux-2.6-debug-vm-would-have-oomkilled.patch | 69 +- 5 files changed, 57 insertions(+), 24477 deletions(-) delete mode 100644 drm-intel-2.6.37-rc2.patch diff --git a/drm-intel-2.6.37-rc2.patch b/drm-intel-2.6.37-rc2.patch deleted file mode 100644 index e2a9d28bc..000000000 --- a/drm-intel-2.6.37-rc2.patch +++ /dev/null @@ -1,24423 +0,0 @@ - drivers/char/agp/Makefile | 1 + - drivers/char/agp/intel-agp.c | 201 +--- - drivers/char/agp/intel-agp.h | 43 +- - drivers/char/agp/intel-gtt.c | 1614 ++++++++++----------- - drivers/gpu/drm/drm_edid.c | 92 +- - drivers/gpu/drm/i915/Makefile | 4 +- - drivers/gpu/drm/i915/dvo_ch7017.c | 66 +- - drivers/gpu/drm/i915/dvo_ch7xxx.c | 10 +- - drivers/gpu/drm/i915/dvo_ivch.c | 10 +- - drivers/gpu/drm/i915/dvo_sil164.c | 10 +- - drivers/gpu/drm/i915/dvo_tfp410.c | 10 +- - drivers/gpu/drm/i915/i915_debugfs.c | 337 ++++- - drivers/gpu/drm/i915/i915_dma.c | 360 ++---- - drivers/gpu/drm/i915/i915_drv.c | 219 ++- - drivers/gpu/drm/i915/i915_drv.h | 272 +++-- - drivers/gpu/drm/i915/i915_gem.c | 2292 +++++++++++++++--------------- - drivers/gpu/drm/i915/i915_gem_debug.c | 148 ++- - drivers/gpu/drm/i915/i915_gem_evict.c | 72 +- - drivers/gpu/drm/i915/i915_gem_tiling.c | 54 +- - drivers/gpu/drm/i915/i915_irq.c | 259 ++-- - drivers/gpu/drm/i915/i915_reg.h | 335 +++-- - drivers/gpu/drm/i915/i915_suspend.c | 32 +- - drivers/gpu/drm/i915/intel_acpi.c | 286 ++++ - drivers/gpu/drm/i915/intel_bios.c | 234 +++- - drivers/gpu/drm/i915/intel_bios.h | 6 +- - drivers/gpu/drm/i915/intel_crt.c | 127 +- - drivers/gpu/drm/i915/intel_display.c | 2374 ++++++++++++++++--------------- - drivers/gpu/drm/i915/intel_dp.c | 658 ++++++--- - drivers/gpu/drm/i915/intel_drv.h | 161 ++- - drivers/gpu/drm/i915/intel_dvo.c | 69 +- - drivers/gpu/drm/i915/intel_fb.c | 29 +- - drivers/gpu/drm/i915/intel_hdmi.c | 193 ++- - drivers/gpu/drm/i915/intel_i2c.c | 484 +++++-- - drivers/gpu/drm/i915/intel_lvds.c | 445 +++--- - drivers/gpu/drm/i915/intel_modes.c | 16 +- - drivers/gpu/drm/i915/intel_opregion.c | 517 +++++++ - drivers/gpu/drm/i915/intel_overlay.c | 1004 +++++++------ - drivers/gpu/drm/i915/intel_panel.c | 109 ++ - drivers/gpu/drm/i915/intel_ringbuffer.c | 580 +++++--- - drivers/gpu/drm/i915/intel_ringbuffer.h | 84 +- - drivers/gpu/drm/i915/intel_sdvo.c | 1076 +++++++-------- - drivers/gpu/drm/i915/intel_tv.c | 165 +-- - include/drm/drm_crtc.h | 1 + - include/drm/drm_dp_helper.h | 3 + - include/drm/i915_drm.h | 6 +- - include/drm/intel-gtt.h | 18 + - 46 files changed, 8590 insertions(+), 6496 deletions(-) - -diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile -index 627f542..8eb56e2 100644 ---- a/drivers/char/agp/Makefile -+++ b/drivers/char/agp/Makefile -@@ -13,6 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o - obj-$(CONFIG_AGP_PARISC) += parisc-agp.o - obj-$(CONFIG_AGP_I460) += i460-agp.o - obj-$(CONFIG_AGP_INTEL) += intel-agp.o -+obj-$(CONFIG_AGP_INTEL) += intel-gtt.o - obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o - obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o - obj-$(CONFIG_AGP_SIS) += sis-agp.o -diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c -index cd18493..e72f49d 100644 ---- a/drivers/char/agp/intel-agp.c -+++ b/drivers/char/agp/intel-agp.c -@@ -12,9 +12,6 @@ - #include - #include "agp.h" - #include "intel-agp.h" --#include -- --#include "intel-gtt.c" - - int intel_agp_enabled; - EXPORT_SYMBOL(intel_agp_enabled); -@@ -703,179 +700,37 @@ static const struct agp_bridge_driver intel_7505_driver = { - .agp_type_to_mask_type = agp_generic_type_to_mask_type, - }; - --static int find_gmch(u16 device) --{ -- struct pci_dev *gmch_device; -- -- gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); -- if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { -- gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, -- device, gmch_device); -- } -- -- if (!gmch_device) -- return 0; -- -- intel_private.pcidev = gmch_device; -- return 1; --} -- - /* 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 - * which one should be used if a gmch_chip_id is present. - */ --static const struct intel_driver_description { -+static const struct intel_agp_driver_description { - unsigned int chip_id; -- unsigned int gmch_chip_id; - char *name; - const struct agp_bridge_driver *driver; -- const struct agp_bridge_driver *gmch_driver; - } intel_agp_chipsets[] = { -- { PCI_DEVICE_ID_INTEL_82443LX_0, 0, "440LX", &intel_generic_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82443BX_0, 0, "440BX", &intel_generic_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82443GX_0, 0, "440GX", &intel_generic_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, "i810", -- NULL, &intel_810_driver }, -- { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, "i810", -- NULL, &intel_810_driver }, -- { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, "i810", -- NULL, &intel_810_driver }, -- { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, "i815", -- &intel_815_driver, &intel_810_driver }, -- { PCI_DEVICE_ID_INTEL_82820_HB, 0, "i820", &intel_820_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, "i820", &intel_820_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, "830M", -- &intel_830mp_driver, &intel_830_driver }, -- { PCI_DEVICE_ID_INTEL_82840_HB, 0, "i840", &intel_840_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82845_HB, 0, "845G", &intel_845_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, "830M", -- &intel_845_driver, &intel_830_driver }, -- { PCI_DEVICE_ID_INTEL_82850_HB, 0, "i850", &intel_850_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, "854", -- &intel_845_driver, &intel_830_driver }, -- { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, "855PM", &intel_845_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", -- &intel_845_driver, &intel_830_driver }, -- { PCI_DEVICE_ID_INTEL_82860_HB, 0, "i860", &intel_860_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, "865", -- &intel_845_driver, &intel_830_driver }, -- { PCI_DEVICE_ID_INTEL_82875_HB, 0, "i875", &intel_845_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", -- NULL, &intel_915_driver }, -- { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, "915G", -- NULL, &intel_915_driver }, -- { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", -- NULL, &intel_915_driver }, -- { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, "945G", -- NULL, &intel_915_driver }, -- { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", -- NULL, &intel_915_driver }, -- { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", -- NULL, &intel_915_driver }, -- { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", -- NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, "G35", -- NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", -- NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, "965G", -- NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", -- NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", -- NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_7505_0, 0, "E7505", &intel_7505_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_7205_0, 0, "E7205", &intel_7505_driver, NULL }, -- { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, "G33", -- NULL, &intel_g33_driver }, -- { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", -- NULL, &intel_g33_driver }, -- { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", -- NULL, &intel_g33_driver }, -- { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", -- NULL, &intel_g33_driver }, -- { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", -- NULL, &intel_g33_driver }, -- { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, -- "GM45", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, -- "Eaglelake", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, -- "Q45/Q43", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, -- "G45/G43", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, -- "B43", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG, -- "B43", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, -- "G41", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, -- "HD Graphics", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, -- "HD Graphics", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, -- "HD Graphics", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, -- "HD Graphics", NULL, &intel_i965_driver }, -- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, -- "Sandybridge", NULL, &intel_gen6_driver }, -- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, -- "Sandybridge", NULL, &intel_gen6_driver }, -- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, -- "Sandybridge", NULL, &intel_gen6_driver }, -- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, -- "Sandybridge", NULL, &intel_gen6_driver }, -- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, -- "Sandybridge", NULL, &intel_gen6_driver }, -- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, -- "Sandybridge", NULL, &intel_gen6_driver }, -- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, -- "Sandybridge", NULL, &intel_gen6_driver }, -- { 0, 0, NULL, NULL, NULL } -+ { PCI_DEVICE_ID_INTEL_82443LX_0, "440LX", &intel_generic_driver }, -+ { PCI_DEVICE_ID_INTEL_82443BX_0, "440BX", &intel_generic_driver }, -+ { PCI_DEVICE_ID_INTEL_82443GX_0, "440GX", &intel_generic_driver }, -+ { PCI_DEVICE_ID_INTEL_82815_MC, "i815", &intel_815_driver }, -+ { PCI_DEVICE_ID_INTEL_82820_HB, "i820", &intel_820_driver }, -+ { PCI_DEVICE_ID_INTEL_82820_UP_HB, "i820", &intel_820_driver }, -+ { PCI_DEVICE_ID_INTEL_82830_HB, "830M", &intel_830mp_driver }, -+ { PCI_DEVICE_ID_INTEL_82840_HB, "i840", &intel_840_driver }, -+ { PCI_DEVICE_ID_INTEL_82845_HB, "845G", &intel_845_driver }, -+ { PCI_DEVICE_ID_INTEL_82845G_HB, "830M", &intel_845_driver }, -+ { PCI_DEVICE_ID_INTEL_82850_HB, "i850", &intel_850_driver }, -+ { PCI_DEVICE_ID_INTEL_82854_HB, "854", &intel_845_driver }, -+ { PCI_DEVICE_ID_INTEL_82855PM_HB, "855PM", &intel_845_driver }, -+ { PCI_DEVICE_ID_INTEL_82855GM_HB, "855GM", &intel_845_driver }, -+ { PCI_DEVICE_ID_INTEL_82860_HB, "i860", &intel_860_driver }, -+ { PCI_DEVICE_ID_INTEL_82865_HB, "865", &intel_845_driver }, -+ { PCI_DEVICE_ID_INTEL_82875_HB, "i875", &intel_845_driver }, -+ { PCI_DEVICE_ID_INTEL_7505_0, "E7505", &intel_7505_driver }, -+ { PCI_DEVICE_ID_INTEL_7205_0, "E7205", &intel_7505_driver }, -+ { 0, NULL, NULL } - }; - --static int __devinit intel_gmch_probe(struct pci_dev *pdev, -- struct agp_bridge_data *bridge) --{ -- int i, mask; -- -- bridge->driver = NULL; -- -- for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { -- if ((intel_agp_chipsets[i].gmch_chip_id != 0) && -- find_gmch(intel_agp_chipsets[i].gmch_chip_id)) { -- bridge->driver = -- intel_agp_chipsets[i].gmch_driver; -- break; -- } -- } -- -- if (!bridge->driver) -- return 0; -- -- bridge->dev_private_data = &intel_private; -- bridge->dev = pdev; -- -- dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); -- -- if (bridge->driver->mask_memory == intel_gen6_mask_memory) -- mask = 40; -- else if (bridge->driver->mask_memory == intel_i965_mask_memory) -- mask = 36; -- else -- mask = 32; -- -- if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) -- dev_err(&intel_private.pcidev->dev, -- "set gfx device dma mask %d-bit failed!\n", mask); -- else -- pci_set_consistent_dma_mask(intel_private.pcidev, -- DMA_BIT_MASK(mask)); -- -- return 1; --} -- - static int __devinit agp_intel_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) - { -@@ -905,7 +760,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, - } - } - -- if (intel_agp_chipsets[i].name == NULL) { -+ if (!bridge->driver) { - if (cap_ptr) - dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n", - pdev->vendor, pdev->device); -@@ -913,14 +768,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, - return -ENODEV; - } - -- if (!bridge->driver) { -- if (cap_ptr) -- dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n", -- intel_agp_chipsets[i].gmch_chip_id); -- agp_put_bridge(bridge); -- return -ENODEV; -- } -- - bridge->dev = pdev; - bridge->dev_private_data = NULL; - -@@ -972,8 +819,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) - - agp_remove_bridge(bridge); - -- if (intel_private.pcidev) -- pci_dev_put(intel_private.pcidev); -+ intel_gmch_remove(pdev); - - agp_put_bridge(bridge); - } -@@ -1049,6 +895,7 @@ static struct pci_device_id agp_intel_pci_table[] = { - ID(PCI_DEVICE_ID_INTEL_G45_HB), - ID(PCI_DEVICE_ID_INTEL_G41_HB), - ID(PCI_DEVICE_ID_INTEL_B43_HB), -+ ID(PCI_DEVICE_ID_INTEL_B43_1_HB), - ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), - ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), - ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), -diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h -index d09b1ab..90539df 100644 ---- a/drivers/char/agp/intel-agp.h -+++ b/drivers/char/agp/intel-agp.h -@@ -215,44 +215,7 @@ - #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ - #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A - --/* cover 915 and 945 variants */ --#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB) -- --#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82G35_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB) -- --#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) -- --#define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) -- --#define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB) -- --#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \ -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \ -- IS_SNB) -- -+int intel_gmch_probe(struct pci_dev *pdev, -+ struct agp_bridge_data *bridge); -+void intel_gmch_remove(struct pci_dev *pdev); - #endif -diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c -index 75e0a34..9272c38 100644 ---- a/drivers/char/agp/intel-gtt.c -+++ b/drivers/char/agp/intel-gtt.c -@@ -15,6 +15,18 @@ - * /fairy-tale-mode off - */ - -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "agp.h" -+#include "intel-agp.h" -+#include -+#include -+ - /* - * If we have Intel graphics, we're not going to have anything other than - * an Intel IOMMU. So make the correct use of the PCI DMA API contingent -@@ -23,11 +35,12 @@ - */ - #ifdef CONFIG_DMAR - #define USE_PCI_DMA_API 1 -+#else -+#define USE_PCI_DMA_API 0 - #endif - - /* Max amount of stolen space, anything above will be returned to Linux */ - int intel_max_stolen = 32 * 1024 * 1024; --EXPORT_SYMBOL(intel_max_stolen); - - static const struct aper_size_info_fixed intel_i810_sizes[] = - { -@@ -55,32 +68,36 @@ static struct gatt_mask intel_i810_masks[] = - #define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 - #define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 - --static struct gatt_mask intel_gen6_masks[] = --{ -- {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED, -- .type = INTEL_AGP_UNCACHED_MEMORY }, -- {.mask = I810_PTE_VALID | GEN6_PTE_LLC, -- .type = INTEL_AGP_CACHED_MEMORY_LLC }, -- {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT, -- .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT }, -- {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC, -- .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC }, -- {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT, -- .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT }, -+struct intel_gtt_driver { -+ unsigned int gen : 8; -+ unsigned int is_g33 : 1; -+ unsigned int is_pineview : 1; -+ unsigned int is_ironlake : 1; -+ unsigned int dma_mask_size : 8; -+ /* Chipset specific GTT setup */ -+ int (*setup)(void); -+ /* This should undo anything done in ->setup() save the unmapping -+ * of the mmio register file, that's done in the generic code. */ -+ void (*cleanup)(void); -+ void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags); -+ /* Flags is a more or less chipset specific opaque value. -+ * For chipsets that need to support old ums (non-gem) code, this -+ * needs to be identical to the various supported agp memory types! */ -+ bool (*check_flags)(unsigned int flags); -+ void (*chipset_flush)(void); - }; - - static struct _intel_private { -+ struct intel_gtt base; -+ const struct intel_gtt_driver *driver; - struct pci_dev *pcidev; /* device one */ -+ struct pci_dev *bridge_dev; - u8 __iomem *registers; -+ phys_addr_t gtt_bus_addr; -+ phys_addr_t gma_bus_addr; -+ phys_addr_t pte_bus_addr; - u32 __iomem *gtt; /* I915G */ - int num_dcache_entries; -- /* gtt_entries is the number of gtt entries that are already mapped -- * to stolen memory. Stolen memory is larger than the memory mapped -- * through gtt_entries, as it includes some reserved space for the BIOS -- * popup and for the GTT. -- */ -- int gtt_entries; /* i830+ */ -- int gtt_total_size; - union { - void __iomem *i9xx_flush_page; - void *i8xx_flush_page; -@@ -88,23 +105,14 @@ static struct _intel_private { - struct page *i8xx_page; - struct resource ifp_resource; - int resource_valid; -+ struct page *scratch_page; -+ dma_addr_t scratch_page_dma; - } intel_private; - --#ifdef USE_PCI_DMA_API --static int intel_agp_map_page(struct page *page, dma_addr_t *ret) --{ -- *ret = pci_map_page(intel_private.pcidev, page, 0, -- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -- if (pci_dma_mapping_error(intel_private.pcidev, *ret)) -- return -EINVAL; -- return 0; --} -- --static void intel_agp_unmap_page(struct page *page, dma_addr_t dma) --{ -- pci_unmap_page(intel_private.pcidev, dma, -- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); --} -+#define INTEL_GTT_GEN intel_private.driver->gen -+#define IS_G33 intel_private.driver->is_g33 -+#define IS_PINEVIEW intel_private.driver->is_pineview -+#define IS_IRONLAKE intel_private.driver->is_ironlake - - static void intel_agp_free_sglist(struct agp_memory *mem) - { -@@ -125,6 +133,9 @@ static int intel_agp_map_memory(struct agp_memory *mem) - struct scatterlist *sg; - int i; - -+ if (mem->sg_list) -+ return 0; /* already mapped (for e.g. resume */ -+ - DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); - - if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) -@@ -156,70 +167,17 @@ static void intel_agp_unmap_memory(struct agp_memory *mem) - intel_agp_free_sglist(mem); - } - --static void intel_agp_insert_sg_entries(struct agp_memory *mem, -- off_t pg_start, int mask_type) --{ -- struct scatterlist *sg; -- int i, j; -- -- j = pg_start; -- -- WARN_ON(!mem->num_sg); -- -- if (mem->num_sg == mem->page_count) { -- for_each_sg(mem->sg_list, sg, mem->page_count, i) { -- writel(agp_bridge->driver->mask_memory(agp_bridge, -- sg_dma_address(sg), mask_type), -- intel_private.gtt+j); -- j++; -- } -- } else { -- /* sg may merge pages, but we have to separate -- * per-page addr for GTT */ -- unsigned int len, m; -- -- for_each_sg(mem->sg_list, sg, mem->num_sg, i) { -- len = sg_dma_len(sg) / PAGE_SIZE; -- for (m = 0; m < len; m++) { -- writel(agp_bridge->driver->mask_memory(agp_bridge, -- sg_dma_address(sg) + m * PAGE_SIZE, -- mask_type), -- intel_private.gtt+j); -- j++; -- } -- } -- } -- readl(intel_private.gtt+j-1); --} -- --#else -- --static void intel_agp_insert_sg_entries(struct agp_memory *mem, -- off_t pg_start, int mask_type) --{ -- int i, j; -- -- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { -- writel(agp_bridge->driver->mask_memory(agp_bridge, -- page_to_phys(mem->pages[i]), mask_type), -- intel_private.gtt+j); -- } -- -- readl(intel_private.gtt+j-1); --} -- --#endif -- - static int intel_i810_fetch_size(void) - { - u32 smram_miscc; - struct aper_size_info_fixed *values; - -- pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc); -+ pci_read_config_dword(intel_private.bridge_dev, -+ I810_SMRAM_MISCC, &smram_miscc); - values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); - - if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { -- dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n"); -+ dev_warn(&intel_private.bridge_dev->dev, "i810 is disabled\n"); - return 0; - } - if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { -@@ -284,7 +242,7 @@ static void intel_i810_cleanup(void) - iounmap(intel_private.registers); - } - --static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode) -+static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) - { - return; - } -@@ -319,34 +277,6 @@ static void i8xx_destroy_pages(struct page *page) - atomic_dec(&agp_bridge->current_memory_agp); - } - --static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, -- int type) --{ -- if (type < AGP_USER_TYPES) -- return type; -- else if (type == AGP_USER_CACHED_MEMORY) -- return INTEL_AGP_CACHED_MEMORY; -- else -- return 0; --} -- --static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge, -- int type) --{ -- unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT; -- unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT; -- -- if (type_mask == AGP_USER_UNCACHED_MEMORY) -- return INTEL_AGP_UNCACHED_MEMORY; -- else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) -- return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT : -- INTEL_AGP_CACHED_MEMORY_LLC_MLC; -- else /* set 'normal'/'cached' to LLC by default */ -- return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT : -- INTEL_AGP_CACHED_MEMORY_LLC; --} -- -- - static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, - int type) - { -@@ -514,8 +444,33 @@ static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, - return addr | bridge->driver->masks[type].mask; - } - --static struct aper_size_info_fixed intel_i830_sizes[] = -+static int intel_gtt_setup_scratch_page(void) - { -+ struct page *page; -+ dma_addr_t dma_addr; -+ -+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); -+ if (page == NULL) -+ return -ENOMEM; -+ get_page(page); -+ set_pages_uc(page, 1); -+ -+ if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { -+ dma_addr = pci_map_page(intel_private.pcidev, page, 0, -+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) -+ return -EINVAL; -+ -+ intel_private.scratch_page_dma = dma_addr; -+ } else -+ intel_private.scratch_page_dma = page_to_phys(page); -+ -+ intel_private.scratch_page = page; -+ -+ return 0; -+} -+ -+static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = { - {128, 32768, 5}, - /* The 64M mode still requires a 128k gatt */ - {64, 16384, 5}, -@@ -523,102 +478,49 @@ static struct aper_size_info_fixed intel_i830_sizes[] = - {512, 131072, 7}, - }; - --static void intel_i830_init_gtt_entries(void) -+static unsigned int intel_gtt_stolen_entries(void) - { - u16 gmch_ctrl; -- int gtt_entries = 0; - u8 rdct; - int local = 0; - static const int ddt[4] = { 0, 16, 32, 64 }; -- int size; /* reserved space (in kb) at the top of stolen memory */ -+ unsigned int overhead_entries, stolen_entries; -+ unsigned int stolen_size = 0; - -- pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); -+ pci_read_config_word(intel_private.bridge_dev, -+ I830_GMCH_CTRL, &gmch_ctrl); - -- if (IS_I965) { -- u32 pgetbl_ctl; -- pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); -+ if (INTEL_GTT_GEN > 4 || IS_PINEVIEW) -+ overhead_entries = 0; -+ else -+ overhead_entries = intel_private.base.gtt_mappable_entries -+ / 1024; - -- /* The 965 has a field telling us the size of the GTT, -- * which may be larger than what is necessary to map the -- * aperture. -- */ -- switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { -- case I965_PGETBL_SIZE_128KB: -- size = 128; -- break; -- case I965_PGETBL_SIZE_256KB: -- size = 256; -- break; -- case I965_PGETBL_SIZE_512KB: -- size = 512; -- break; -- case I965_PGETBL_SIZE_1MB: -- size = 1024; -- break; -- case I965_PGETBL_SIZE_2MB: -- size = 2048; -- break; -- case I965_PGETBL_SIZE_1_5MB: -- size = 1024 + 512; -- break; -- default: -- dev_info(&intel_private.pcidev->dev, -- "unknown page table size, assuming 512KB\n"); -- size = 512; -- } -- size += 4; /* add in BIOS popup space */ -- } else if (IS_G33 && !IS_PINEVIEW) { -- /* G33's GTT size defined in gmch_ctrl */ -- switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { -- case G33_PGETBL_SIZE_1M: -- size = 1024; -- break; -- case G33_PGETBL_SIZE_2M: -- size = 2048; -- break; -- default: -- dev_info(&agp_bridge->dev->dev, -- "unknown page table size 0x%x, assuming 512KB\n", -- (gmch_ctrl & G33_PGETBL_SIZE_MASK)); -- size = 512; -- } -- size += 4; -- } else if (IS_G4X || IS_PINEVIEW) { -- /* On 4 series hardware, GTT stolen is separate from graphics -- * stolen, ignore it in stolen gtt entries counting. However, -- * 4KB of the stolen memory doesn't get mapped to the GTT. -- */ -- size = 4; -- } else { -- /* On previous hardware, the GTT size was just what was -- * required to map the aperture. -- */ -- size = agp_bridge->driver->fetch_size() + 4; -- } -+ overhead_entries += 1; /* BIOS popup */ - -- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || -- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { -+ if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB || -+ intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I830_GMCH_GMS_STOLEN_512: -- gtt_entries = KB(512) - KB(size); -+ stolen_size = KB(512); - break; - case I830_GMCH_GMS_STOLEN_1024: -- gtt_entries = MB(1) - KB(size); -+ stolen_size = MB(1); - break; - case I830_GMCH_GMS_STOLEN_8192: -- gtt_entries = MB(8) - KB(size); -+ stolen_size = MB(8); - break; - case I830_GMCH_GMS_LOCAL: - rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); -- gtt_entries = (I830_RDRAM_ND(rdct) + 1) * -+ stolen_size = (I830_RDRAM_ND(rdct) + 1) * - MB(ddt[I830_RDRAM_DDT(rdct)]); - local = 1; - break; - default: -- gtt_entries = 0; -+ stolen_size = 0; - break; - } -- } else if (IS_SNB) { -+ } else if (INTEL_GTT_GEN == 6) { - /* - * SandyBridge has new memory control reg at 0x50.w - */ -@@ -626,149 +528,292 @@ static void intel_i830_init_gtt_entries(void) - pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); - switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { - case SNB_GMCH_GMS_STOLEN_32M: -- gtt_entries = MB(32) - KB(size); -+ stolen_size = MB(32); - break; - case SNB_GMCH_GMS_STOLEN_64M: -- gtt_entries = MB(64) - KB(size); -+ stolen_size = MB(64); - break; - case SNB_GMCH_GMS_STOLEN_96M: -- gtt_entries = MB(96) - KB(size); -+ stolen_size = MB(96); - break; - case SNB_GMCH_GMS_STOLEN_128M: -- gtt_entries = MB(128) - KB(size); -+ stolen_size = MB(128); - break; - case SNB_GMCH_GMS_STOLEN_160M: -- gtt_entries = MB(160) - KB(size); -+ stolen_size = MB(160); - break; - case SNB_GMCH_GMS_STOLEN_192M: -- gtt_entries = MB(192) - KB(size); -+ stolen_size = MB(192); - break; - case SNB_GMCH_GMS_STOLEN_224M: -- gtt_entries = MB(224) - KB(size); -+ stolen_size = MB(224); - break; - case SNB_GMCH_GMS_STOLEN_256M: -- gtt_entries = MB(256) - KB(size); -+ stolen_size = MB(256); - break; - case SNB_GMCH_GMS_STOLEN_288M: -- gtt_entries = MB(288) - KB(size); -+ stolen_size = MB(288); - break; - case SNB_GMCH_GMS_STOLEN_320M: -- gtt_entries = MB(320) - KB(size); -+ stolen_size = MB(320); - break; - case SNB_GMCH_GMS_STOLEN_352M: -- gtt_entries = MB(352) - KB(size); -+ stolen_size = MB(352); - break; - case SNB_GMCH_GMS_STOLEN_384M: -- gtt_entries = MB(384) - KB(size); -+ stolen_size = MB(384); - break; - case SNB_GMCH_GMS_STOLEN_416M: -- gtt_entries = MB(416) - KB(size); -+ stolen_size = MB(416); - break; - case SNB_GMCH_GMS_STOLEN_448M: -- gtt_entries = MB(448) - KB(size); -+ stolen_size = MB(448); - break; - case SNB_GMCH_GMS_STOLEN_480M: -- gtt_entries = MB(480) - KB(size); -+ stolen_size = MB(480); - break; - case SNB_GMCH_GMS_STOLEN_512M: -- gtt_entries = MB(512) - KB(size); -+ stolen_size = MB(512); - break; - } - } else { - switch (gmch_ctrl & I855_GMCH_GMS_MASK) { - case I855_GMCH_GMS_STOLEN_1M: -- gtt_entries = MB(1) - KB(size); -+ stolen_size = MB(1); - break; - case I855_GMCH_GMS_STOLEN_4M: -- gtt_entries = MB(4) - KB(size); -+ stolen_size = MB(4); - break; - case I855_GMCH_GMS_STOLEN_8M: -- gtt_entries = MB(8) - KB(size); -+ stolen_size = MB(8); - break; - case I855_GMCH_GMS_STOLEN_16M: -- gtt_entries = MB(16) - KB(size); -+ stolen_size = MB(16); - break; - case I855_GMCH_GMS_STOLEN_32M: -- gtt_entries = MB(32) - KB(size); -+ stolen_size = MB(32); - break; - case I915_GMCH_GMS_STOLEN_48M: -- /* Check it's really I915G */ -- if (IS_I915 || IS_I965 || IS_G33 || IS_G4X) -- gtt_entries = MB(48) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(48); - break; - case I915_GMCH_GMS_STOLEN_64M: -- /* Check it's really I915G */ -- if (IS_I915 || IS_I965 || IS_G33 || IS_G4X) -- gtt_entries = MB(64) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(64); - break; - case G33_GMCH_GMS_STOLEN_128M: -- if (IS_G33 || IS_I965 || IS_G4X) -- gtt_entries = MB(128) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(128); - break; - case G33_GMCH_GMS_STOLEN_256M: -- if (IS_G33 || IS_I965 || IS_G4X) -- gtt_entries = MB(256) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(256); - break; - case INTEL_GMCH_GMS_STOLEN_96M: -- if (IS_I965 || IS_G4X) -- gtt_entries = MB(96) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(96); - break; - case INTEL_GMCH_GMS_STOLEN_160M: -- if (IS_I965 || IS_G4X) -- gtt_entries = MB(160) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(160); - break; - case INTEL_GMCH_GMS_STOLEN_224M: -- if (IS_I965 || IS_G4X) -- gtt_entries = MB(224) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(224); - break; - case INTEL_GMCH_GMS_STOLEN_352M: -- if (IS_I965 || IS_G4X) -- gtt_entries = MB(352) - KB(size); -- else -- gtt_entries = 0; -+ stolen_size = MB(352); - break; - default: -- gtt_entries = 0; -+ stolen_size = 0; - break; - } - } -- if (!local && gtt_entries > intel_max_stolen) { -- dev_info(&agp_bridge->dev->dev, -+ -+ if (!local && stolen_size > intel_max_stolen) { -+ dev_info(&intel_private.bridge_dev->dev, - "detected %dK stolen memory, trimming to %dK\n", -- gtt_entries / KB(1), intel_max_stolen / KB(1)); -- gtt_entries = intel_max_stolen / KB(4); -- } else if (gtt_entries > 0) { -- dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", -- gtt_entries / KB(1), local ? "local" : "stolen"); -- gtt_entries /= KB(4); -+ stolen_size / KB(1), intel_max_stolen / KB(1)); -+ stolen_size = intel_max_stolen; -+ } else if (stolen_size > 0) { -+ dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", -+ stolen_size / KB(1), local ? "local" : "stolen"); - } else { -- dev_info(&agp_bridge->dev->dev, -+ dev_info(&intel_private.bridge_dev->dev, - "no pre-allocated video memory detected\n"); -- gtt_entries = 0; -+ stolen_size = 0; -+ } -+ -+ stolen_entries = stolen_size/KB(4) - overhead_entries; -+ -+ return stolen_entries; -+} -+ -+static unsigned int intel_gtt_total_entries(void) -+{ -+ int size; -+ -+ if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) { -+ u32 pgetbl_ctl; -+ pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); -+ -+ switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { -+ case I965_PGETBL_SIZE_128KB: -+ size = KB(128); -+ break; -+ case I965_PGETBL_SIZE_256KB: -+ size = KB(256); -+ break; -+ case I965_PGETBL_SIZE_512KB: -+ size = KB(512); -+ break; -+ case I965_PGETBL_SIZE_1MB: -+ size = KB(1024); -+ break; -+ case I965_PGETBL_SIZE_2MB: -+ size = KB(2048); -+ break; -+ case I965_PGETBL_SIZE_1_5MB: -+ size = KB(1024 + 512); -+ break; -+ default: -+ dev_info(&intel_private.pcidev->dev, -+ "unknown page table size, assuming 512KB\n"); -+ size = KB(512); -+ } -+ -+ return size/4; -+ } else if (INTEL_GTT_GEN == 6) { -+ u16 snb_gmch_ctl; -+ -+ pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); -+ switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { -+ default: -+ case SNB_GTT_SIZE_0M: -+ printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); -+ size = MB(0); -+ break; -+ case SNB_GTT_SIZE_1M: -+ size = MB(1); -+ break; -+ case SNB_GTT_SIZE_2M: -+ size = MB(2); -+ break; -+ } -+ return size/4; -+ } else { -+ /* On previous hardware, the GTT size was just what was -+ * required to map the aperture. -+ */ -+ return intel_private.base.gtt_mappable_entries; -+ } -+} -+ -+static unsigned int intel_gtt_mappable_entries(void) -+{ -+ unsigned int aperture_size; -+ -+ if (INTEL_GTT_GEN == 2) { -+ u16 gmch_ctrl; -+ -+ pci_read_config_word(intel_private.bridge_dev, -+ I830_GMCH_CTRL, &gmch_ctrl); -+ -+ if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_64M) -+ aperture_size = MB(64); -+ else -+ aperture_size = MB(128); -+ } else { -+ /* 9xx supports large sizes, just look at the length */ -+ aperture_size = pci_resource_len(intel_private.pcidev, 2); -+ } -+ -+ return aperture_size >> PAGE_SHIFT; -+} -+ -+static void intel_gtt_teardown_scratch_page(void) -+{ -+ set_pages_wb(intel_private.scratch_page, 1); -+ pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, -+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ put_page(intel_private.scratch_page); -+ __free_page(intel_private.scratch_page); -+} -+ -+static void intel_gtt_cleanup(void) -+{ -+ intel_private.driver->cleanup(); -+ -+ iounmap(intel_private.gtt); -+ iounmap(intel_private.registers); -+ -+ intel_gtt_teardown_scratch_page(); -+} -+ -+static int intel_gtt_init(void) -+{ -+ u32 gtt_map_size; -+ int ret; -+ -+ ret = intel_private.driver->setup(); -+ if (ret != 0) -+ return ret; -+ -+ intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); -+ intel_private.base.gtt_total_entries = intel_gtt_total_entries(); -+ -+ dev_info(&intel_private.bridge_dev->dev, -+ "detected gtt size: %dK total, %dK mappable\n", -+ intel_private.base.gtt_total_entries * 4, -+ intel_private.base.gtt_mappable_entries * 4); -+ -+ gtt_map_size = intel_private.base.gtt_total_entries * 4; -+ -+ intel_private.gtt = ioremap(intel_private.gtt_bus_addr, -+ gtt_map_size); -+ if (!intel_private.gtt) { -+ intel_private.driver->cleanup(); -+ iounmap(intel_private.registers); -+ return -ENOMEM; -+ } -+ -+ global_cache_flush(); /* FIXME: ? */ -+ -+ /* we have to call this as early as possible after the MMIO base address is known */ -+ intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries(); -+ if (intel_private.base.gtt_stolen_entries == 0) { -+ intel_private.driver->cleanup(); -+ iounmap(intel_private.registers); -+ iounmap(intel_private.gtt); -+ return -ENOMEM; -+ } -+ -+ ret = intel_gtt_setup_scratch_page(); -+ if (ret != 0) { -+ intel_gtt_cleanup(); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int intel_fake_agp_fetch_size(void) -+{ -+ int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes); -+ unsigned int aper_size; -+ int i; -+ -+ aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT) -+ / MB(1); -+ -+ for (i = 0; i < num_sizes; i++) { -+ if (aper_size == intel_fake_agp_sizes[i].size) { -+ agp_bridge->current_size = -+ (void *) (intel_fake_agp_sizes + i); -+ return aper_size; -+ } - } - -- intel_private.gtt_entries = gtt_entries; -+ return 0; - } - --static void intel_i830_fini_flush(void) -+static void i830_cleanup(void) - { - kunmap(intel_private.i8xx_page); - intel_private.i8xx_flush_page = NULL; -- unmap_page_from_agp(intel_private.i8xx_page); - - __free_page(intel_private.i8xx_page); - intel_private.i8xx_page = NULL; -@@ -780,13 +825,13 @@ static void intel_i830_setup_flush(void) - if (intel_private.i8xx_page) - return; - -- intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); -+ intel_private.i8xx_page = alloc_page(GFP_KERNEL); - if (!intel_private.i8xx_page) - return; - - intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); - if (!intel_private.i8xx_flush_page) -- intel_i830_fini_flush(); -+ i830_cleanup(); - } - - /* The chipset_flush interface needs to get data that has already been -@@ -799,7 +844,7 @@ static void intel_i830_setup_flush(void) - * that buffer out, we just fill 1KB and clflush it out, on the assumption - * that it'll push whatever was in there out. It appears to work. - */ --static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) -+static void i830_chipset_flush(void) - { - unsigned int *pg = intel_private.i8xx_flush_page; - -@@ -811,169 +856,184 @@ static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) - printk(KERN_ERR "Timed out waiting for cache flush.\n"); - } - --/* The intel i830 automatically initializes the agp aperture during POST. -- * Use the memory already set aside for in the GTT. -- */ --static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge) -+static void i830_write_entry(dma_addr_t addr, unsigned int entry, -+ unsigned int flags) - { -- int page_order; -- struct aper_size_info_fixed *size; -- int num_entries; -- u32 temp; -+ u32 pte_flags = I810_PTE_VALID; -+ -+ switch (flags) { -+ case AGP_DCACHE_MEMORY: -+ pte_flags |= I810_PTE_LOCAL; -+ break; -+ case AGP_USER_CACHED_MEMORY: -+ pte_flags |= I830_PTE_SYSTEM_CACHED; -+ break; -+ } - -- size = agp_bridge->current_size; -- page_order = size->page_order; -- num_entries = size->num_entries; -- agp_bridge->gatt_table_real = NULL; -+ writel(addr | pte_flags, intel_private.gtt + entry); -+} - -- pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); -- temp &= 0xfff80000; -+static void intel_enable_gtt(void) -+{ -+ u32 gma_addr; -+ u16 gmch_ctrl; - -- intel_private.registers = ioremap(temp, 128 * 4096); -- if (!intel_private.registers) -- return -ENOMEM; -+ if (INTEL_GTT_GEN == 2) -+ pci_read_config_dword(intel_private.pcidev, I810_GMADDR, -+ &gma_addr); -+ else -+ pci_read_config_dword(intel_private.pcidev, I915_GMADDR, -+ &gma_addr); - -- temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; -- global_cache_flush(); /* FIXME: ?? */ -+ intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); - -- /* we have to call this as early as possible after the MMIO base address is known */ -- intel_i830_init_gtt_entries(); -- if (intel_private.gtt_entries == 0) { -- iounmap(intel_private.registers); -+ pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl); -+ gmch_ctrl |= I830_GMCH_ENABLED; -+ pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl); -+ -+ writel(intel_private.pte_bus_addr|I810_PGETBL_ENABLED, -+ intel_private.registers+I810_PGETBL_CTL); -+ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ -+} -+ -+static int i830_setup(void) -+{ -+ u32 reg_addr; -+ -+ pci_read_config_dword(intel_private.pcidev, I810_MMADDR, ®_addr); -+ reg_addr &= 0xfff80000; -+ -+ intel_private.registers = ioremap(reg_addr, KB(64)); -+ if (!intel_private.registers) - return -ENOMEM; -- } - -- agp_bridge->gatt_table = NULL; -+ intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; -+ intel_private.pte_bus_addr = -+ readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; - -- agp_bridge->gatt_bus_addr = temp; -+ intel_i830_setup_flush(); - - return 0; - } - --/* Return the gatt table to a sane state. Use the top of stolen -- * memory for the GTT. -- */ --static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge) -+static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge) - { -+ agp_bridge->gatt_table_real = NULL; -+ agp_bridge->gatt_table = NULL; -+ agp_bridge->gatt_bus_addr = 0; -+ - return 0; - } - --static int intel_i830_fetch_size(void) -+static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge) - { -- u16 gmch_ctrl; -- struct aper_size_info_fixed *values; -+ return 0; -+} - -- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); -+static int intel_fake_agp_configure(void) -+{ -+ int i; - -- if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB && -- agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) { -- /* 855GM/852GM/865G has 128MB aperture size */ -- agp_bridge->current_size = (void *) values; -- agp_bridge->aperture_size_idx = 0; -- return values[0].size; -- } -+ intel_enable_gtt(); - -- pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); -+ agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; - -- if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { -- agp_bridge->current_size = (void *) values; -- agp_bridge->aperture_size_idx = 0; -- return values[0].size; -- } else { -- agp_bridge->current_size = (void *) (values + 1); -- agp_bridge->aperture_size_idx = 1; -- return values[1].size; -+ for (i = intel_private.base.gtt_stolen_entries; -+ i < intel_private.base.gtt_total_entries; i++) { -+ intel_private.driver->write_entry(intel_private.scratch_page_dma, -+ i, 0); - } -+ readl(intel_private.gtt+i-1); /* PCI Posting. */ -+ -+ global_cache_flush(); - - return 0; - } - --static int intel_i830_configure(void) -+static bool i830_check_flags(unsigned int flags) - { -- struct aper_size_info_fixed *current_size; -- u32 temp; -- u16 gmch_ctrl; -- int i; -+ switch (flags) { -+ case 0: -+ case AGP_PHYS_MEMORY: -+ case AGP_USER_CACHED_MEMORY: -+ case AGP_USER_MEMORY: -+ return true; -+ } - -- current_size = A_SIZE_FIX(agp_bridge->current_size); -+ return false; -+} - -- pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); -- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); -+static void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, -+ unsigned int sg_len, -+ unsigned int pg_start, -+ unsigned int flags) -+{ -+ struct scatterlist *sg; -+ unsigned int len, m; -+ int i, j; - -- pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); -- gmch_ctrl |= I830_GMCH_ENABLED; -- pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl); -- -- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); -- readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ -+ j = pg_start; - -- if (agp_bridge->driver->needs_scratch_page) { -- for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { -- writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); -+ /* sg may merge pages, but we have to separate -+ * per-page addr for GTT */ -+ for_each_sg(sg_list, sg, sg_len, i) { -+ len = sg_dma_len(sg) >> PAGE_SHIFT; -+ for (m = 0; m < len; m++) { -+ dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); -+ intel_private.driver->write_entry(addr, -+ j, flags); -+ j++; - } -- readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */ - } -- -- global_cache_flush(); -- -- intel_i830_setup_flush(); -- return 0; --} -- --static void intel_i830_cleanup(void) --{ -- iounmap(intel_private.registers); -+ readl(intel_private.gtt+j-1); - } - --static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start, -- int type) -+static int intel_fake_agp_insert_entries(struct agp_memory *mem, -+ off_t pg_start, int type) - { -- int i, j, num_entries; -- void *temp; -+ int i, j; - int ret = -EINVAL; -- int mask_type; - - if (mem->page_count == 0) - goto out; - -- temp = agp_bridge->current_size; -- num_entries = A_SIZE_FIX(temp)->num_entries; -- -- if (pg_start < intel_private.gtt_entries) { -+ if (pg_start < intel_private.base.gtt_stolen_entries) { - dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, -- "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", -- pg_start, intel_private.gtt_entries); -+ "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n", -+ pg_start, intel_private.base.gtt_stolen_entries); - - dev_info(&intel_private.pcidev->dev, - "trying to insert into local/stolen memory\n"); - goto out_err; - } - -- if ((pg_start + mem->page_count) > num_entries) -+ if ((pg_start + mem->page_count) > intel_private.base.gtt_total_entries) - goto out_err; - -- /* The i830 can't check the GTT for entries since its read only, -- * depend on the caller to make the correct offset decisions. -- */ -- - if (type != mem->type) - goto out_err; - -- mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); -- -- if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && -- mask_type != INTEL_AGP_CACHED_MEMORY) -+ if (!intel_private.driver->check_flags(type)) - goto out_err; - - if (!mem->is_flushed) - global_cache_flush(); - -- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { -- writel(agp_bridge->driver->mask_memory(agp_bridge, -- page_to_phys(mem->pages[i]), mask_type), -- intel_private.registers+I810_PTE_BASE+(j*4)); -+ if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { -+ ret = intel_agp_map_memory(mem); -+ if (ret != 0) -+ return ret; -+ -+ intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg, -+ pg_start, type); -+ } else { -+ for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { -+ dma_addr_t addr = page_to_phys(mem->pages[i]); -+ intel_private.driver->write_entry(addr, -+ j, type); -+ } -+ readl(intel_private.gtt+j-1); - } -- readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); - - out: - ret = 0; -@@ -982,29 +1042,39 @@ out_err: - return ret; - } - --static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start, -- int type) -+static int intel_fake_agp_remove_entries(struct agp_memory *mem, -+ off_t pg_start, int type) - { - int i; - - if (mem->page_count == 0) - return 0; - -- if (pg_start < intel_private.gtt_entries) { -+ if (pg_start < intel_private.base.gtt_stolen_entries) { - dev_info(&intel_private.pcidev->dev, - "trying to disable local/stolen memory\n"); - return -EINVAL; - } - -+ if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) -+ intel_agp_unmap_memory(mem); -+ - for (i = pg_start; i < (mem->page_count + pg_start); i++) { -- writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); -+ intel_private.driver->write_entry(intel_private.scratch_page_dma, -+ i, 0); - } -- readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); -+ readl(intel_private.gtt+i-1); - - return 0; - } - --static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type) -+static void intel_fake_agp_chipset_flush(struct agp_bridge_data *bridge) -+{ -+ intel_private.driver->chipset_flush(); -+} -+ -+static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, -+ int type) - { - if (type == AGP_PHYS_MEMORY) - return alloc_agpphysmem_i8xx(pg_count, type); -@@ -1015,9 +1085,9 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type) - static int intel_alloc_chipset_flush_resource(void) - { - int ret; -- ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE, -+ ret = pci_bus_alloc_resource(intel_private.bridge_dev->bus, &intel_private.ifp_resource, PAGE_SIZE, - PAGE_SIZE, PCIBIOS_MIN_MEM, 0, -- pcibios_align_resource, agp_bridge->dev); -+ pcibios_align_resource, intel_private.bridge_dev); - - return ret; - } -@@ -1027,11 +1097,11 @@ static void intel_i915_setup_chipset_flush(void) - int ret; - u32 temp; - -- pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp); -+ pci_read_config_dword(intel_private.bridge_dev, I915_IFPADDR, &temp); - if (!(temp & 0x1)) { - intel_alloc_chipset_flush_resource(); - intel_private.resource_valid = 1; -- pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); -+ pci_write_config_dword(intel_private.bridge_dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); - } else { - temp &= ~1; - -@@ -1050,17 +1120,17 @@ static void intel_i965_g33_setup_chipset_flush(void) - u32 temp_hi, temp_lo; - int ret; - -- pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi); -- pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo); -+ pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, &temp_hi); -+ pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR, &temp_lo); - - if (!(temp_lo & 0x1)) { - - intel_alloc_chipset_flush_resource(); - - intel_private.resource_valid = 1; -- pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, -+ pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, - upper_32_bits(intel_private.ifp_resource.start)); -- pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); -+ pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); - } else { - u64 l64; - -@@ -1083,7 +1153,7 @@ static void intel_i9xx_setup_flush(void) - if (intel_private.ifp_resource.start) - return; - -- if (IS_SNB) -+ if (INTEL_GTT_GEN == 6) - return; - - /* setup a resource for this object */ -@@ -1091,7 +1161,7 @@ static void intel_i9xx_setup_flush(void) - intel_private.ifp_resource.flags = IORESOURCE_MEM; - - /* Setup chipset flush for 915 */ -- if (IS_I965 || IS_G33 || IS_G4X) { -+ if (IS_G33 || INTEL_GTT_GEN >= 4) { - intel_i965_g33_setup_chipset_flush(); - } else { - intel_i915_setup_chipset_flush(); -@@ -1104,41 +1174,7 @@ static void intel_i9xx_setup_flush(void) - "can't ioremap flush page - no chipset flushing\n"); - } - --static int intel_i9xx_configure(void) --{ -- struct aper_size_info_fixed *current_size; -- u32 temp; -- u16 gmch_ctrl; -- int i; -- -- current_size = A_SIZE_FIX(agp_bridge->current_size); -- -- pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp); -- -- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); -- -- pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); -- gmch_ctrl |= I830_GMCH_ENABLED; -- pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl); -- -- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); -- readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ -- -- if (agp_bridge->driver->needs_scratch_page) { -- for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) { -- writel(agp_bridge->scratch_page, intel_private.gtt+i); -- } -- readl(intel_private.gtt+i-1); /* PCI Posting. */ -- } -- -- global_cache_flush(); -- -- intel_i9xx_setup_flush(); -- -- return 0; --} -- --static void intel_i915_cleanup(void) -+static void i9xx_cleanup(void) - { - if (intel_private.i9xx_flush_page) - iounmap(intel_private.i9xx_flush_page); -@@ -1146,320 +1182,93 @@ static void intel_i915_cleanup(void) - release_resource(&intel_private.ifp_resource); - intel_private.ifp_resource.start = 0; - intel_private.resource_valid = 0; -- iounmap(intel_private.gtt); -- iounmap(intel_private.registers); - } - --static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) -+static void i9xx_chipset_flush(void) - { - if (intel_private.i9xx_flush_page) - writel(1, intel_private.i9xx_flush_page); - } - --static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, -- int type) -+static void i965_write_entry(dma_addr_t addr, unsigned int entry, -+ unsigned int flags) - { -- int num_entries; -- void *temp; -- int ret = -EINVAL; -- int mask_type; -- -- if (mem->page_count == 0) -- goto out; -- -- temp = agp_bridge->current_size; -- num_entries = A_SIZE_FIX(temp)->num_entries; -- -- if (pg_start < intel_private.gtt_entries) { -- dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, -- "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", -- pg_start, intel_private.gtt_entries); -- -- dev_info(&intel_private.pcidev->dev, -- "trying to insert into local/stolen memory\n"); -- goto out_err; -- } -- -- if ((pg_start + mem->page_count) > num_entries) -- goto out_err; -- -- /* The i915 can't check the GTT for entries since it's read only; -- * depend on the caller to make the correct offset decisions. -- */ -- -- if (type != mem->type) -- goto out_err; -- -- mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); -- -- if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY && -- mask_type != INTEL_AGP_CACHED_MEMORY) -- goto out_err; -- -- if (!mem->is_flushed) -- global_cache_flush(); -- -- intel_agp_insert_sg_entries(mem, pg_start, mask_type); -- -- out: -- ret = 0; -- out_err: -- mem->is_flushed = true; -- return ret; -+ /* Shift high bits down */ -+ addr |= (addr >> 28) & 0xf0; -+ writel(addr | I810_PTE_VALID, intel_private.gtt + entry); - } - --static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start, -- int type) -+static bool gen6_check_flags(unsigned int flags) - { -- int i; -- -- if (mem->page_count == 0) -- return 0; -- -- if (pg_start < intel_private.gtt_entries) { -- dev_info(&intel_private.pcidev->dev, -- "trying to disable local/stolen memory\n"); -- return -EINVAL; -- } -- -- for (i = pg_start; i < (mem->page_count + pg_start); i++) -- writel(agp_bridge->scratch_page, intel_private.gtt+i); -- -- readl(intel_private.gtt+i-1); -- -- return 0; -+ return true; - } - --/* Return the aperture size by just checking the resource length. The effect -- * described in the spec of the MSAC registers is just changing of the -- * resource size. -- */ --static int intel_i9xx_fetch_size(void) -+static void gen6_write_entry(dma_addr_t addr, unsigned int entry, -+ unsigned int flags) - { -- int num_sizes = ARRAY_SIZE(intel_i830_sizes); -- int aper_size; /* size in megabytes */ -- int i; -- -- aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1); -- -- for (i = 0; i < num_sizes; i++) { -- if (aper_size == intel_i830_sizes[i].size) { -- agp_bridge->current_size = intel_i830_sizes + i; -- return aper_size; -- } -+ unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; -+ unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; -+ u32 pte_flags; -+ -+ if (type_mask == AGP_USER_MEMORY) -+ pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; -+ else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { -+ pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; -+ if (gfdt) -+ pte_flags |= GEN6_PTE_GFDT; -+ } else { /* set 'normal'/'cached' to LLC by default */ -+ pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; -+ if (gfdt) -+ pte_flags |= GEN6_PTE_GFDT; - } - -- return 0; -+ /* gen6 has bit11-4 for physical addr bit39-32 */ -+ addr |= (addr >> 28) & 0xff0; -+ writel(addr | pte_flags, intel_private.gtt + entry); - } - --static int intel_i915_get_gtt_size(void) -+static void gen6_cleanup(void) - { -- int size; -- -- if (IS_G33) { -- u16 gmch_ctrl; -- -- /* G33's GTT size defined in gmch_ctrl */ -- pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); -- switch (gmch_ctrl & I830_GMCH_GMS_MASK) { -- case I830_GMCH_GMS_STOLEN_512: -- size = 512; -- break; -- case I830_GMCH_GMS_STOLEN_1024: -- size = 1024; -- break; -- case I830_GMCH_GMS_STOLEN_8192: -- size = 8*1024; -- break; -- default: -- dev_info(&agp_bridge->dev->dev, -- "unknown page table size 0x%x, assuming 512KB\n", -- (gmch_ctrl & I830_GMCH_GMS_MASK)); -- size = 512; -- } -- } else { -- /* On previous hardware, the GTT size was just what was -- * required to map the aperture. -- */ -- size = agp_bridge->driver->fetch_size(); -- } -- -- return KB(size); - } - --/* The intel i915 automatically initializes the agp aperture during POST. -- * Use the memory already set aside for in the GTT. -- */ --static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) -+static int i9xx_setup(void) - { -- int page_order; -- struct aper_size_info_fixed *size; -- int num_entries; -- u32 temp, temp2; -- int gtt_map_size; -- -- size = agp_bridge->current_size; -- page_order = size->page_order; -- num_entries = size->num_entries; -- agp_bridge->gatt_table_real = NULL; -- -- pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); -- pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2); -- -- gtt_map_size = intel_i915_get_gtt_size(); -+ u32 reg_addr; - -- intel_private.gtt = ioremap(temp2, gtt_map_size); -- if (!intel_private.gtt) -- return -ENOMEM; -- -- intel_private.gtt_total_size = gtt_map_size / 4; -- -- temp &= 0xfff80000; -- -- intel_private.registers = ioremap(temp, 128 * 4096); -- if (!intel_private.registers) { -- iounmap(intel_private.gtt); -- return -ENOMEM; -- } -+ pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); - -- temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; -- global_cache_flush(); /* FIXME: ? */ -+ reg_addr &= 0xfff80000; - -- /* we have to call this as early as possible after the MMIO base address is known */ -- intel_i830_init_gtt_entries(); -- if (intel_private.gtt_entries == 0) { -- iounmap(intel_private.gtt); -- iounmap(intel_private.registers); -+ intel_private.registers = ioremap(reg_addr, 128 * 4096); -+ if (!intel_private.registers) - return -ENOMEM; -- } - -- agp_bridge->gatt_table = NULL; -- -- agp_bridge->gatt_bus_addr = temp; -+ if (INTEL_GTT_GEN == 3) { -+ u32 gtt_addr; - -- return 0; --} -- --/* -- * The i965 supports 36-bit physical addresses, but to keep -- * the format of the GTT the same, the bits that don't fit -- * in a 32-bit word are shifted down to bits 4..7. -- * -- * Gcc is smart enough to notice that "(addr >> 28) & 0xf0" -- * is always zero on 32-bit architectures, so no need to make -- * this conditional. -- */ --static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, -- dma_addr_t addr, int type) --{ -- /* Shift high bits down */ -- addr |= (addr >> 28) & 0xf0; -- -- /* Type checking must be done elsewhere */ -- return addr | bridge->driver->masks[type].mask; --} -- --static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, -- dma_addr_t addr, int type) --{ -- /* gen6 has bit11-4 for physical addr bit39-32 */ -- addr |= (addr >> 28) & 0xff0; -- -- /* Type checking must be done elsewhere */ -- return addr | bridge->driver->masks[type].mask; --} -- --static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) --{ -- u16 snb_gmch_ctl; -- -- switch (agp_bridge->dev->device) { -- case PCI_DEVICE_ID_INTEL_GM45_HB: -- case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB: -- case PCI_DEVICE_ID_INTEL_Q45_HB: -- case PCI_DEVICE_ID_INTEL_G45_HB: -- case PCI_DEVICE_ID_INTEL_G41_HB: -- case PCI_DEVICE_ID_INTEL_B43_HB: -- case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB: -- case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB: -- case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB: -- case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB: -- *gtt_offset = *gtt_size = MB(2); -- break; -- case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB: -- case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB: -- case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB: -- *gtt_offset = MB(2); -+ pci_read_config_dword(intel_private.pcidev, -+ I915_PTEADDR, >t_addr); -+ intel_private.gtt_bus_addr = gtt_addr; -+ } else { -+ u32 gtt_offset; - -- pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); -- switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { -- default: -- case SNB_GTT_SIZE_0M: -- printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); -- *gtt_size = MB(0); -- break; -- case SNB_GTT_SIZE_1M: -- *gtt_size = MB(1); -+ switch (INTEL_GTT_GEN) { -+ case 5: -+ case 6: -+ gtt_offset = MB(2); - break; -- case SNB_GTT_SIZE_2M: -- *gtt_size = MB(2); -+ case 4: -+ default: -+ gtt_offset = KB(512); - break; - } -- break; -- default: -- *gtt_offset = *gtt_size = KB(512); -- } --} -- --/* The intel i965 automatically initializes the agp aperture during POST. -- * Use the memory already set aside for in the GTT. -- */ --static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) --{ -- int page_order; -- struct aper_size_info_fixed *size; -- int num_entries; -- u32 temp; -- int gtt_offset, gtt_size; -- -- size = agp_bridge->current_size; -- page_order = size->page_order; -- num_entries = size->num_entries; -- agp_bridge->gatt_table_real = NULL; -- -- pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); -- -- temp &= 0xfff00000; -- -- intel_i965_get_gtt_range(>t_offset, >t_size); -- -- intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size); -- -- if (!intel_private.gtt) -- return -ENOMEM; -- -- intel_private.gtt_total_size = gtt_size / 4; -- -- intel_private.registers = ioremap(temp, 128 * 4096); -- if (!intel_private.registers) { -- iounmap(intel_private.gtt); -- return -ENOMEM; -- } -- -- temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; -- global_cache_flush(); /* FIXME: ? */ -- -- /* we have to call this as early as possible after the MMIO base address is known */ -- intel_i830_init_gtt_entries(); -- if (intel_private.gtt_entries == 0) { -- iounmap(intel_private.gtt); -- iounmap(intel_private.registers); -- return -ENOMEM; -+ intel_private.gtt_bus_addr = reg_addr + gtt_offset; - } - -- agp_bridge->gatt_table = NULL; -+ intel_private.pte_bus_addr = -+ readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; - -- agp_bridge->gatt_bus_addr = temp; -+ intel_i9xx_setup_flush(); - - return 0; - } -@@ -1475,7 +1284,7 @@ static const struct agp_bridge_driver intel_810_driver = { - .cleanup = intel_i810_cleanup, - .mask_memory = intel_i810_mask_memory, - .masks = intel_i810_masks, -- .agp_enable = intel_i810_agp_enable, -+ .agp_enable = intel_fake_agp_enable, - .cache_flush = global_cache_flush, - .create_gatt_table = agp_generic_create_gatt_table, - .free_gatt_table = agp_generic_free_gatt_table, -@@ -1490,161 +1299,282 @@ static const struct agp_bridge_driver intel_810_driver = { - .agp_type_to_mask_type = agp_generic_type_to_mask_type, - }; - --static const struct agp_bridge_driver intel_830_driver = { -+static const struct agp_bridge_driver intel_fake_agp_driver = { - .owner = THIS_MODULE, -- .aperture_sizes = intel_i830_sizes, - .size_type = FIXED_APER_SIZE, -- .num_aperture_sizes = 4, -- .needs_scratch_page = true, -- .configure = intel_i830_configure, -- .fetch_size = intel_i830_fetch_size, -- .cleanup = intel_i830_cleanup, -- .mask_memory = intel_i810_mask_memory, -- .masks = intel_i810_masks, -- .agp_enable = intel_i810_agp_enable, -+ .aperture_sizes = intel_fake_agp_sizes, -+ .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), -+ .configure = intel_fake_agp_configure, -+ .fetch_size = intel_fake_agp_fetch_size, -+ .cleanup = intel_gtt_cleanup, -+ .agp_enable = intel_fake_agp_enable, - .cache_flush = global_cache_flush, -- .create_gatt_table = intel_i830_create_gatt_table, -- .free_gatt_table = intel_i830_free_gatt_table, -- .insert_memory = intel_i830_insert_entries, -- .remove_memory = intel_i830_remove_entries, -- .alloc_by_type = intel_i830_alloc_by_type, -+ .create_gatt_table = intel_fake_agp_create_gatt_table, -+ .free_gatt_table = intel_fake_agp_free_gatt_table, -+ .insert_memory = intel_fake_agp_insert_entries, -+ .remove_memory = intel_fake_agp_remove_entries, -+ .alloc_by_type = intel_fake_agp_alloc_by_type, - .free_by_type = intel_i810_free_by_type, - .agp_alloc_page = agp_generic_alloc_page, - .agp_alloc_pages = agp_generic_alloc_pages, - .agp_destroy_page = agp_generic_destroy_page, - .agp_destroy_pages = agp_generic_destroy_pages, -- .agp_type_to_mask_type = intel_i830_type_to_mask_type, -- .chipset_flush = intel_i830_chipset_flush, -+ .chipset_flush = intel_fake_agp_chipset_flush, - }; - --static const struct agp_bridge_driver intel_915_driver = { -- .owner = THIS_MODULE, -- .aperture_sizes = intel_i830_sizes, -- .size_type = FIXED_APER_SIZE, -- .num_aperture_sizes = 4, -- .needs_scratch_page = true, -- .configure = intel_i9xx_configure, -- .fetch_size = intel_i9xx_fetch_size, -- .cleanup = intel_i915_cleanup, -- .mask_memory = intel_i810_mask_memory, -- .masks = intel_i810_masks, -- .agp_enable = intel_i810_agp_enable, -- .cache_flush = global_cache_flush, -- .create_gatt_table = intel_i915_create_gatt_table, -- .free_gatt_table = intel_i830_free_gatt_table, -- .insert_memory = intel_i915_insert_entries, -- .remove_memory = intel_i915_remove_entries, -- .alloc_by_type = intel_i830_alloc_by_type, -- .free_by_type = intel_i810_free_by_type, -- .agp_alloc_page = agp_generic_alloc_page, -- .agp_alloc_pages = agp_generic_alloc_pages, -- .agp_destroy_page = agp_generic_destroy_page, -- .agp_destroy_pages = agp_generic_destroy_pages, -- .agp_type_to_mask_type = intel_i830_type_to_mask_type, -- .chipset_flush = intel_i915_chipset_flush, --#ifdef USE_PCI_DMA_API -- .agp_map_page = intel_agp_map_page, -- .agp_unmap_page = intel_agp_unmap_page, -- .agp_map_memory = intel_agp_map_memory, -- .agp_unmap_memory = intel_agp_unmap_memory, --#endif -+static const struct intel_gtt_driver i81x_gtt_driver = { -+ .gen = 1, -+ .dma_mask_size = 32, - }; -- --static const struct agp_bridge_driver intel_i965_driver = { -- .owner = THIS_MODULE, -- .aperture_sizes = intel_i830_sizes, -- .size_type = FIXED_APER_SIZE, -- .num_aperture_sizes = 4, -- .needs_scratch_page = true, -- .configure = intel_i9xx_configure, -- .fetch_size = intel_i9xx_fetch_size, -- .cleanup = intel_i915_cleanup, -- .mask_memory = intel_i965_mask_memory, -- .masks = intel_i810_masks, -- .agp_enable = intel_i810_agp_enable, -- .cache_flush = global_cache_flush, -- .create_gatt_table = intel_i965_create_gatt_table, -- .free_gatt_table = intel_i830_free_gatt_table, -- .insert_memory = intel_i915_insert_entries, -- .remove_memory = intel_i915_remove_entries, -- .alloc_by_type = intel_i830_alloc_by_type, -- .free_by_type = intel_i810_free_by_type, -- .agp_alloc_page = agp_generic_alloc_page, -- .agp_alloc_pages = agp_generic_alloc_pages, -- .agp_destroy_page = agp_generic_destroy_page, -- .agp_destroy_pages = agp_generic_destroy_pages, -- .agp_type_to_mask_type = intel_i830_type_to_mask_type, -- .chipset_flush = intel_i915_chipset_flush, --#ifdef USE_PCI_DMA_API -- .agp_map_page = intel_agp_map_page, -- .agp_unmap_page = intel_agp_unmap_page, -- .agp_map_memory = intel_agp_map_memory, -- .agp_unmap_memory = intel_agp_unmap_memory, --#endif -+static const struct intel_gtt_driver i8xx_gtt_driver = { -+ .gen = 2, -+ .setup = i830_setup, -+ .cleanup = i830_cleanup, -+ .write_entry = i830_write_entry, -+ .dma_mask_size = 32, -+ .check_flags = i830_check_flags, -+ .chipset_flush = i830_chipset_flush, - }; -- --static const struct agp_bridge_driver intel_gen6_driver = { -- .owner = THIS_MODULE, -- .aperture_sizes = intel_i830_sizes, -- .size_type = FIXED_APER_SIZE, -- .num_aperture_sizes = 4, -- .needs_scratch_page = true, -- .configure = intel_i9xx_configure, -- .fetch_size = intel_i9xx_fetch_size, -- .cleanup = intel_i915_cleanup, -- .mask_memory = intel_gen6_mask_memory, -- .masks = intel_gen6_masks, -- .agp_enable = intel_i810_agp_enable, -- .cache_flush = global_cache_flush, -- .create_gatt_table = intel_i965_create_gatt_table, -- .free_gatt_table = intel_i830_free_gatt_table, -- .insert_memory = intel_i915_insert_entries, -- .remove_memory = intel_i915_remove_entries, -- .alloc_by_type = intel_i830_alloc_by_type, -- .free_by_type = intel_i810_free_by_type, -- .agp_alloc_page = agp_generic_alloc_page, -- .agp_alloc_pages = agp_generic_alloc_pages, -- .agp_destroy_page = agp_generic_destroy_page, -- .agp_destroy_pages = agp_generic_destroy_pages, -- .agp_type_to_mask_type = intel_gen6_type_to_mask_type, -- .chipset_flush = intel_i915_chipset_flush, --#ifdef USE_PCI_DMA_API -- .agp_map_page = intel_agp_map_page, -- .agp_unmap_page = intel_agp_unmap_page, -- .agp_map_memory = intel_agp_map_memory, -- .agp_unmap_memory = intel_agp_unmap_memory, --#endif -+static const struct intel_gtt_driver i915_gtt_driver = { -+ .gen = 3, -+ .setup = i9xx_setup, -+ .cleanup = i9xx_cleanup, -+ /* i945 is the last gpu to need phys mem (for overlay and cursors). */ -+ .write_entry = i830_write_entry, -+ .dma_mask_size = 32, -+ .check_flags = i830_check_flags, -+ .chipset_flush = i9xx_chipset_flush, -+}; -+static const struct intel_gtt_driver g33_gtt_driver = { -+ .gen = 3, -+ .is_g33 = 1, -+ .setup = i9xx_setup, -+ .cleanup = i9xx_cleanup, -+ .write_entry = i965_write_entry, -+ .dma_mask_size = 36, -+ .check_flags = i830_check_flags, -+ .chipset_flush = i9xx_chipset_flush, -+}; -+static const struct intel_gtt_driver pineview_gtt_driver = { -+ .gen = 3, -+ .is_pineview = 1, .is_g33 = 1, -+ .setup = i9xx_setup, -+ .cleanup = i9xx_cleanup, -+ .write_entry = i965_write_entry, -+ .dma_mask_size = 36, -+ .check_flags = i830_check_flags, -+ .chipset_flush = i9xx_chipset_flush, -+}; -+static const struct intel_gtt_driver i965_gtt_driver = { -+ .gen = 4, -+ .setup = i9xx_setup, -+ .cleanup = i9xx_cleanup, -+ .write_entry = i965_write_entry, -+ .dma_mask_size = 36, -+ .check_flags = i830_check_flags, -+ .chipset_flush = i9xx_chipset_flush, -+}; -+static const struct intel_gtt_driver g4x_gtt_driver = { -+ .gen = 5, -+ .setup = i9xx_setup, -+ .cleanup = i9xx_cleanup, -+ .write_entry = i965_write_entry, -+ .dma_mask_size = 36, -+ .check_flags = i830_check_flags, -+ .chipset_flush = i9xx_chipset_flush, -+}; -+static const struct intel_gtt_driver ironlake_gtt_driver = { -+ .gen = 5, -+ .is_ironlake = 1, -+ .setup = i9xx_setup, -+ .cleanup = i9xx_cleanup, -+ .write_entry = i965_write_entry, -+ .dma_mask_size = 36, -+ .check_flags = i830_check_flags, -+ .chipset_flush = i9xx_chipset_flush, -+}; -+static const struct intel_gtt_driver sandybridge_gtt_driver = { -+ .gen = 6, -+ .setup = i9xx_setup, -+ .cleanup = gen6_cleanup, -+ .write_entry = gen6_write_entry, -+ .dma_mask_size = 40, -+ .check_flags = gen6_check_flags, -+ .chipset_flush = i9xx_chipset_flush, - }; - --static const struct agp_bridge_driver intel_g33_driver = { -- .owner = THIS_MODULE, -- .aperture_sizes = intel_i830_sizes, -- .size_type = FIXED_APER_SIZE, -- .num_aperture_sizes = 4, -- .needs_scratch_page = true, -- .configure = intel_i9xx_configure, -- .fetch_size = intel_i9xx_fetch_size, -- .cleanup = intel_i915_cleanup, -- .mask_memory = intel_i965_mask_memory, -- .masks = intel_i810_masks, -- .agp_enable = intel_i810_agp_enable, -- .cache_flush = global_cache_flush, -- .create_gatt_table = intel_i915_create_gatt_table, -- .free_gatt_table = intel_i830_free_gatt_table, -- .insert_memory = intel_i915_insert_entries, -- .remove_memory = intel_i915_remove_entries, -- .alloc_by_type = intel_i830_alloc_by_type, -- .free_by_type = intel_i810_free_by_type, -- .agp_alloc_page = agp_generic_alloc_page, -- .agp_alloc_pages = agp_generic_alloc_pages, -- .agp_destroy_page = agp_generic_destroy_page, -- .agp_destroy_pages = agp_generic_destroy_pages, -- .agp_type_to_mask_type = intel_i830_type_to_mask_type, -- .chipset_flush = intel_i915_chipset_flush, --#ifdef USE_PCI_DMA_API -- .agp_map_page = intel_agp_map_page, -- .agp_unmap_page = intel_agp_unmap_page, -- .agp_map_memory = intel_agp_map_memory, -- .agp_unmap_memory = intel_agp_unmap_memory, --#endif -+/* 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 -+ * which one should be used if a gmch_chip_id is present. -+ */ -+static const struct intel_gtt_driver_description { -+ unsigned int gmch_chip_id; -+ char *name; -+ const struct agp_bridge_driver *gmch_driver; -+ const struct intel_gtt_driver *gtt_driver; -+} intel_gtt_chipsets[] = { -+ { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver, -+ &i81x_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver, -+ &i81x_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver, -+ &i81x_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver, -+ &i81x_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", -+ &intel_fake_agp_driver, &i8xx_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82845G_IG, "830M", -+ &intel_fake_agp_driver, &i8xx_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82854_IG, "854", -+ &intel_fake_agp_driver, &i8xx_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", -+ &intel_fake_agp_driver, &i8xx_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_82865_IG, "865", -+ &intel_fake_agp_driver, &i8xx_gtt_driver}, -+ { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", -+ &intel_fake_agp_driver, &i915_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", -+ &intel_fake_agp_driver, &i915_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", -+ &intel_fake_agp_driver, &i915_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", -+ &intel_fake_agp_driver, &i915_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", -+ &intel_fake_agp_driver, &i915_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", -+ &intel_fake_agp_driver, &i915_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", -+ &intel_fake_agp_driver, &i965_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", -+ &intel_fake_agp_driver, &i965_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", -+ &intel_fake_agp_driver, &i965_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", -+ &intel_fake_agp_driver, &i965_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", -+ &intel_fake_agp_driver, &i965_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", -+ &intel_fake_agp_driver, &i965_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_G33_IG, "G33", -+ &intel_fake_agp_driver, &g33_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", -+ &intel_fake_agp_driver, &g33_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", -+ &intel_fake_agp_driver, &g33_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", -+ &intel_fake_agp_driver, &pineview_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", -+ &intel_fake_agp_driver, &pineview_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", -+ &intel_fake_agp_driver, &g4x_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", -+ &intel_fake_agp_driver, &g4x_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", -+ &intel_fake_agp_driver, &g4x_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", -+ &intel_fake_agp_driver, &g4x_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_B43_IG, "B43", -+ &intel_fake_agp_driver, &g4x_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_B43_1_IG, "B43", -+ &intel_fake_agp_driver, &g4x_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_G41_IG, "G41", -+ &intel_fake_agp_driver, &g4x_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, -+ "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, -+ "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, -+ "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, -+ "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, -+ "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, -+ "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, -+ "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, -+ "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, -+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, -+ "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, -+ { 0, NULL, NULL } - }; -+ -+static int find_gmch(u16 device) -+{ -+ struct pci_dev *gmch_device; -+ -+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); -+ if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { -+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, -+ device, gmch_device); -+ } -+ -+ if (!gmch_device) -+ return 0; -+ -+ intel_private.pcidev = gmch_device; -+ return 1; -+} -+ -+int intel_gmch_probe(struct pci_dev *pdev, -+ struct agp_bridge_data *bridge) -+{ -+ int i, mask; -+ bridge->driver = NULL; -+ -+ for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { -+ if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { -+ bridge->driver = -+ intel_gtt_chipsets[i].gmch_driver; -+ intel_private.driver = -+ intel_gtt_chipsets[i].gtt_driver; -+ break; -+ } -+ } -+ -+ if (!bridge->driver) -+ return 0; -+ -+ bridge->dev_private_data = &intel_private; -+ bridge->dev = pdev; -+ -+ intel_private.bridge_dev = pci_dev_get(pdev); -+ -+ dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); -+ -+ mask = intel_private.driver->dma_mask_size; -+ if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) -+ dev_err(&intel_private.pcidev->dev, -+ "set gfx device dma mask %d-bit failed!\n", mask); -+ else -+ pci_set_consistent_dma_mask(intel_private.pcidev, -+ DMA_BIT_MASK(mask)); -+ -+ if (bridge->driver == &intel_810_driver) -+ return 1; -+ -+ if (intel_gtt_init() != 0) -+ return 0; -+ -+ return 1; -+} -+EXPORT_SYMBOL(intel_gmch_probe); -+ -+struct intel_gtt *intel_gtt_get(void) -+{ -+ return &intel_private.base; -+} -+EXPORT_SYMBOL(intel_gtt_get); -+ -+void intel_gmch_remove(struct pci_dev *pdev) -+{ -+ if (intel_private.pcidev) -+ pci_dev_put(intel_private.pcidev); -+ if (intel_private.bridge_dev) -+ pci_dev_put(intel_private.bridge_dev); -+} -+EXPORT_SYMBOL(intel_gmch_remove); -+ -+MODULE_AUTHOR("Dave Jones "); -+MODULE_LICENSE("GPL and additional rights"); -diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c -index 96e9631..7f356af 100644 ---- a/drivers/gpu/drm/drm_edid.c -+++ b/drivers/gpu/drm/drm_edid.c -@@ -1268,34 +1268,51 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, - } - - #define HDMI_IDENTIFIER 0x000C03 -+#define AUDIO_BLOCK 0x01 - #define VENDOR_BLOCK 0x03 -+#define EDID_BASIC_AUDIO (1 << 6) -+ - /** -- * drm_detect_hdmi_monitor - detect whether monitor is hdmi. -- * @edid: monitor EDID information -- * -- * Parse the CEA extension according to CEA-861-B. -- * Return true if HDMI, false if not or unknown. -+ * Search EDID for CEA extension block. - */ --bool drm_detect_hdmi_monitor(struct edid *edid) -+static u8 *drm_find_cea_extension(struct edid *edid) - { -- char *edid_ext = NULL; -- int i, hdmi_id; -- int start_offset, end_offset; -- bool is_hdmi = false; -+ u8 *edid_ext = NULL; -+ int i; - - /* No EDID or EDID extensions */ - if (edid == NULL || edid->extensions == 0) -- goto end; -+ return NULL; - - /* Find CEA extension */ - for (i = 0; i < edid->extensions; i++) { -- edid_ext = (char *)edid + EDID_LENGTH * (i + 1); -- /* This block is CEA extension */ -- if (edid_ext[0] == 0x02) -+ edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1); -+ if (edid_ext[0] == CEA_EXT) - break; - } - - if (i == edid->extensions) -+ return NULL; -+ -+ return edid_ext; -+} -+ -+/** -+ * drm_detect_hdmi_monitor - detect whether monitor is hdmi. -+ * @edid: monitor EDID information -+ * -+ * Parse the CEA extension according to CEA-861-B. -+ * Return true if HDMI, false if not or unknown. -+ */ -+bool drm_detect_hdmi_monitor(struct edid *edid) -+{ -+ u8 *edid_ext; -+ int i, hdmi_id; -+ int start_offset, end_offset; -+ bool is_hdmi = false; -+ -+ edid_ext = drm_find_cea_extension(edid); -+ if (!edid_ext) - goto end; - - /* Data block offset in CEA extension block */ -@@ -1326,6 +1343,53 @@ end: - EXPORT_SYMBOL(drm_detect_hdmi_monitor); - - /** -+ * drm_detect_monitor_audio - check monitor audio capability -+ * -+ * Monitor should have CEA extension block. -+ * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic -+ * audio' only. If there is any audio extension block and supported -+ * audio format, assume at least 'basic audio' support, even if 'basic -+ * audio' is not defined in EDID. -+ * -+ */ -+bool drm_detect_monitor_audio(struct edid *edid) -+{ -+ u8 *edid_ext; -+ int i, j; -+ bool has_audio = false; -+ int start_offset, end_offset; -+ -+ edid_ext = drm_find_cea_extension(edid); -+ if (!edid_ext) -+ goto end; -+ -+ has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0); -+ -+ if (has_audio) { -+ DRM_DEBUG_KMS("Monitor has basic audio support\n"); -+ goto end; -+ } -+ -+ /* Data block offset in CEA extension block */ -+ start_offset = 4; -+ end_offset = edid_ext[2]; -+ -+ for (i = start_offset; i < end_offset; -+ i += ((edid_ext[i] & 0x1f) + 1)) { -+ if ((edid_ext[i] >> 5) == AUDIO_BLOCK) { -+ has_audio = true; -+ for (j = 1; j < (edid_ext[i] & 0x1f); j += 3) -+ DRM_DEBUG_KMS("CEA audio format %d\n", -+ (edid_ext[i + j] >> 3) & 0xf); -+ goto end; -+ } -+ } -+end: -+ return has_audio; -+} -+EXPORT_SYMBOL(drm_detect_monitor_audio); -+ -+/** - * drm_add_edid_modes - add modes from EDID data, if available - * @connector: connector we're probing - * @edid: edid data -diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile -index 5c8e534..fdc833d 100644 ---- a/drivers/gpu/drm/i915/Makefile -+++ b/drivers/gpu/drm/i915/Makefile -@@ -26,15 +26,17 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ - intel_dvo.o \ - intel_ringbuffer.o \ - intel_overlay.o \ -+ intel_opregion.o \ - dvo_ch7xxx.o \ - dvo_ch7017.o \ - dvo_ivch.o \ - dvo_tfp410.o \ - dvo_sil164.o - --i915-$(CONFIG_ACPI) += i915_opregion.o - i915-$(CONFIG_COMPAT) += i915_ioc32.o - -+i915-$(CONFIG_ACPI) += intel_acpi.o -+ - obj-$(CONFIG_DRM_I915) += i915.o - - CFLAGS_i915_trace_points.o := -I$(src) -diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c -index 14d5980..af70337 100644 ---- a/drivers/gpu/drm/i915/dvo_ch7017.c -+++ b/drivers/gpu/drm/i915/dvo_ch7017.c -@@ -165,67 +165,44 @@ struct ch7017_priv { - static void ch7017_dump_regs(struct intel_dvo_device *dvo); - static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); - --static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) -+static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val) - { -- struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); -- u8 out_buf[2]; -- u8 in_buf[2]; -- - struct i2c_msg msgs[] = { - { - .addr = dvo->slave_addr, - .flags = 0, - .len = 1, -- .buf = out_buf, -+ .buf = &addr, - }, - { - .addr = dvo->slave_addr, - .flags = I2C_M_RD, - .len = 1, -- .buf = in_buf, -+ .buf = val, - } - }; -- -- out_buf[0] = addr; -- out_buf[1] = 0; -- -- if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { -- *val= in_buf[0]; -- return true; -- }; -- -- return false; -+ return i2c_transfer(dvo->i2c_bus, msgs, 2) == 2; - } - --static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) -+static bool ch7017_write(struct intel_dvo_device *dvo, u8 addr, u8 val) - { -- struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); -- uint8_t out_buf[2]; -+ uint8_t buf[2] = { addr, val }; - struct i2c_msg msg = { - .addr = dvo->slave_addr, - .flags = 0, - .len = 2, -- .buf = out_buf, -+ .buf = buf, - }; -- -- out_buf[0] = addr; -- out_buf[1] = val; -- -- if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) -- return true; -- -- return false; -+ return i2c_transfer(dvo->i2c_bus, &msg, 1) == 1; - } - - /** Probes for a CH7017 on the given bus and slave address. */ - static bool ch7017_init(struct intel_dvo_device *dvo, - struct i2c_adapter *adapter) - { -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - struct ch7017_priv *priv; -- uint8_t val; -+ const char *str; -+ u8 val; - - priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL); - if (priv == NULL) -@@ -237,16 +214,27 @@ static bool ch7017_init(struct intel_dvo_device *dvo, - if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) - goto fail; - -- if (val != CH7017_DEVICE_ID_VALUE && -- val != CH7018_DEVICE_ID_VALUE && -- val != CH7019_DEVICE_ID_VALUE) { -+ switch (val) { -+ case CH7017_DEVICE_ID_VALUE: -+ str = "ch7017"; -+ break; -+ case CH7018_DEVICE_ID_VALUE: -+ str = "ch7018"; -+ break; -+ case CH7019_DEVICE_ID_VALUE: -+ str = "ch7019"; -+ break; -+ default: - DRM_DEBUG_KMS("ch701x not detected, got %d: from %s " -- "Slave %d.\n", -- val, i2cbus->adapter.name,dvo->slave_addr); -+ "slave %d.\n", -+ val, adapter->name,dvo->slave_addr); - goto fail; - } - -+ DRM_DEBUG_KMS("%s detected on %s, addr %d\n", -+ str, adapter->name, dvo->slave_addr); - return true; -+ - fail: - kfree(priv); - return false; -@@ -368,7 +356,7 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode) - } - - /* XXX: Should actually wait for update power status somehow */ -- udelay(20000); -+ msleep(20); - } - - static void ch7017_dump_regs(struct intel_dvo_device *dvo) -diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c -index 6f1944b..7eaa94e 100644 ---- a/drivers/gpu/drm/i915/dvo_ch7xxx.c -+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c -@@ -113,7 +113,6 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) - { - struct ch7xxx_priv *ch7xxx= dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - u8 out_buf[2]; - u8 in_buf[2]; - -@@ -135,14 +134,14 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) - out_buf[0] = addr; - out_buf[1] = 0; - -- if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { -+ if (i2c_transfer(adapter, msgs, 2) == 2) { - *ch = in_buf[0]; - return true; - }; - - if (!ch7xxx->quiet) { - DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - return false; - } -@@ -152,7 +151,6 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) - { - struct ch7xxx_priv *ch7xxx = dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - uint8_t out_buf[2]; - struct i2c_msg msg = { - .addr = dvo->slave_addr, -@@ -164,12 +162,12 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) - out_buf[0] = addr; - out_buf[1] = ch; - -- if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) -+ if (i2c_transfer(adapter, &msg, 1) == 1) - return true; - - if (!ch7xxx->quiet) { - DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - - return false; -diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c -index a2ec3f4..a12ed94 100644 ---- a/drivers/gpu/drm/i915/dvo_ivch.c -+++ b/drivers/gpu/drm/i915/dvo_ivch.c -@@ -167,7 +167,6 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) - { - struct ivch_priv *priv = dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - u8 out_buf[1]; - u8 in_buf[2]; - -@@ -193,7 +192,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) - - out_buf[0] = addr; - -- if (i2c_transfer(&i2cbus->adapter, msgs, 3) == 3) { -+ if (i2c_transfer(adapter, msgs, 3) == 3) { - *data = (in_buf[1] << 8) | in_buf[0]; - return true; - }; -@@ -201,7 +200,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) - if (!priv->quiet) { - DRM_DEBUG_KMS("Unable to read register 0x%02x from " - "%s:%02x.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - return false; - } -@@ -211,7 +210,6 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) - { - struct ivch_priv *priv = dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - u8 out_buf[3]; - struct i2c_msg msg = { - .addr = dvo->slave_addr, -@@ -224,12 +222,12 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) - out_buf[1] = data & 0xff; - out_buf[2] = data >> 8; - -- if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) -+ if (i2c_transfer(adapter, &msg, 1) == 1) - return true; - - if (!priv->quiet) { - DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - - return false; -diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c -index 9b8e676..e4b4091 100644 ---- a/drivers/gpu/drm/i915/dvo_sil164.c -+++ b/drivers/gpu/drm/i915/dvo_sil164.c -@@ -69,7 +69,6 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) - { - struct sil164_priv *sil = dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - u8 out_buf[2]; - u8 in_buf[2]; - -@@ -91,14 +90,14 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) - out_buf[0] = addr; - out_buf[1] = 0; - -- if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { -+ if (i2c_transfer(adapter, msgs, 2) == 2) { - *ch = in_buf[0]; - return true; - }; - - if (!sil->quiet) { - DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - return false; - } -@@ -107,7 +106,6 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) - { - struct sil164_priv *sil= dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - uint8_t out_buf[2]; - struct i2c_msg msg = { - .addr = dvo->slave_addr, -@@ -119,12 +117,12 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) - out_buf[0] = addr; - out_buf[1] = ch; - -- if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) -+ if (i2c_transfer(adapter, &msg, 1) == 1) - return true; - - if (!sil->quiet) { - DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - - return false; -diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c -index 56f6642..8ab2855 100644 ---- a/drivers/gpu/drm/i915/dvo_tfp410.c -+++ b/drivers/gpu/drm/i915/dvo_tfp410.c -@@ -94,7 +94,6 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) - { - struct tfp410_priv *tfp = dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - u8 out_buf[2]; - u8 in_buf[2]; - -@@ -116,14 +115,14 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) - out_buf[0] = addr; - out_buf[1] = 0; - -- if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { -+ if (i2c_transfer(adapter, msgs, 2) == 2) { - *ch = in_buf[0]; - return true; - }; - - if (!tfp->quiet) { - DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - return false; - } -@@ -132,7 +131,6 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) - { - struct tfp410_priv *tfp = dvo->dev_priv; - struct i2c_adapter *adapter = dvo->i2c_bus; -- struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); - uint8_t out_buf[2]; - struct i2c_msg msg = { - .addr = dvo->slave_addr, -@@ -144,12 +142,12 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) - out_buf[0] = addr; - out_buf[1] = ch; - -- if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) -+ if (i2c_transfer(adapter, &msg, 1) == 1) - return true; - - if (!tfp->quiet) { - DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", -- addr, i2cbus->adapter.name, dvo->slave_addr); -+ addr, adapter->name, dvo->slave_addr); - } - - return false; -diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c -index 5e43d70..1f4f3ce 100644 ---- a/drivers/gpu/drm/i915/i915_debugfs.c -+++ b/drivers/gpu/drm/i915/i915_debugfs.c -@@ -40,9 +40,51 @@ - - #if defined(CONFIG_DEBUG_FS) - --#define ACTIVE_LIST 1 --#define FLUSHING_LIST 2 --#define INACTIVE_LIST 3 -+enum { -+ ACTIVE_LIST, -+ FLUSHING_LIST, -+ INACTIVE_LIST, -+ PINNED_LIST, -+ DEFERRED_FREE_LIST, -+}; -+ -+static const char *yesno(int v) -+{ -+ return v ? "yes" : "no"; -+} -+ -+static int i915_capabilities(struct seq_file *m, void *data) -+{ -+ struct drm_info_node *node = (struct drm_info_node *) m->private; -+ struct drm_device *dev = node->minor->dev; -+ const struct intel_device_info *info = INTEL_INFO(dev); -+ -+ seq_printf(m, "gen: %d\n", info->gen); -+#define B(x) seq_printf(m, #x ": %s\n", yesno(info->x)) -+ B(is_mobile); -+ B(is_i85x); -+ B(is_i915g); -+ B(is_i945gm); -+ B(is_g33); -+ B(need_gfx_hws); -+ B(is_g4x); -+ B(is_pineview); -+ B(is_broadwater); -+ B(is_crestline); -+ B(has_fbc); -+ B(has_rc6); -+ B(has_pipe_cxsr); -+ B(has_hotplug); -+ B(cursor_needs_physical); -+ B(has_overlay); -+ B(overlay_needs_physical); -+ B(supports_tv); -+ B(has_bsd_ring); -+ B(has_blt_ring); -+#undef B -+ -+ return 0; -+} - - static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv) - { -@@ -64,6 +106,29 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj_priv) - } - } - -+static void -+describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) -+{ -+ seq_printf(m, "%p: %s%s %8zd %08x %08x %d%s%s", -+ &obj->base, -+ get_pin_flag(obj), -+ get_tiling_flag(obj), -+ obj->base.size, -+ obj->base.read_domains, -+ obj->base.write_domain, -+ obj->last_rendering_seqno, -+ obj->dirty ? " dirty" : "", -+ obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); -+ if (obj->base.name) -+ seq_printf(m, " (name: %d)", obj->base.name); -+ if (obj->fence_reg != I915_FENCE_REG_NONE) -+ seq_printf(m, " (fence: %d)", obj->fence_reg); -+ if (obj->gtt_space != NULL) -+ seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset); -+ if (obj->ring != NULL) -+ seq_printf(m, " (%s)", obj->ring->name); -+} -+ - static int i915_gem_object_list_info(struct seq_file *m, void *data) - { - struct drm_info_node *node = (struct drm_info_node *) m->private; -@@ -72,56 +137,80 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; -- spinlock_t *lock = NULL; -+ size_t total_obj_size, total_gtt_size; -+ int count, ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - - switch (list) { - case ACTIVE_LIST: - seq_printf(m, "Active:\n"); -- lock = &dev_priv->mm.active_list_lock; -- head = &dev_priv->render_ring.active_list; -+ head = &dev_priv->mm.active_list; - break; - case INACTIVE_LIST: - seq_printf(m, "Inactive:\n"); - head = &dev_priv->mm.inactive_list; - break; -+ case PINNED_LIST: -+ seq_printf(m, "Pinned:\n"); -+ head = &dev_priv->mm.pinned_list; -+ break; - case FLUSHING_LIST: - seq_printf(m, "Flushing:\n"); - head = &dev_priv->mm.flushing_list; - break; -+ case DEFERRED_FREE_LIST: -+ seq_printf(m, "Deferred free:\n"); -+ head = &dev_priv->mm.deferred_free_list; -+ break; - default: -- DRM_INFO("Ooops, unexpected list\n"); -- return 0; -+ mutex_unlock(&dev->struct_mutex); -+ return -EINVAL; - } - -- if (lock) -- spin_lock(lock); -- list_for_each_entry(obj_priv, head, list) -- { -- seq_printf(m, " %p: %s %8zd %08x %08x %d%s%s", -- &obj_priv->base, -- get_pin_flag(obj_priv), -- obj_priv->base.size, -- obj_priv->base.read_domains, -- obj_priv->base.write_domain, -- obj_priv->last_rendering_seqno, -- obj_priv->dirty ? " dirty" : "", -- obj_priv->madv == I915_MADV_DONTNEED ? " purgeable" : ""); -- -- if (obj_priv->base.name) -- seq_printf(m, " (name: %d)", obj_priv->base.name); -- if (obj_priv->fence_reg != I915_FENCE_REG_NONE) -- seq_printf(m, " (fence: %d)", obj_priv->fence_reg); -- if (obj_priv->gtt_space != NULL) -- seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset); -- -+ total_obj_size = total_gtt_size = count = 0; -+ list_for_each_entry(obj_priv, head, mm_list) { -+ seq_printf(m, " "); -+ describe_obj(m, obj_priv); - seq_printf(m, "\n"); -+ total_obj_size += obj_priv->base.size; -+ total_gtt_size += obj_priv->gtt_space->size; -+ count++; - } -+ mutex_unlock(&dev->struct_mutex); - -- if (lock) -- spin_unlock(lock); -+ seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n", -+ count, total_obj_size, total_gtt_size); - return 0; - } - -+static int i915_gem_object_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; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; -+ -+ seq_printf(m, "%u objects\n", dev_priv->mm.object_count); -+ seq_printf(m, "%zu object bytes\n", dev_priv->mm.object_memory); -+ seq_printf(m, "%u pinned\n", dev_priv->mm.pin_count); -+ seq_printf(m, "%zu pin bytes\n", dev_priv->mm.pin_memory); -+ seq_printf(m, "%u objects in gtt\n", dev_priv->mm.gtt_count); -+ seq_printf(m, "%zu gtt bytes\n", dev_priv->mm.gtt_memory); -+ seq_printf(m, "%zu gtt total\n", dev_priv->mm.gtt_total); -+ -+ mutex_unlock(&dev->struct_mutex); -+ -+ return 0; -+} -+ -+ - static int i915_gem_pageflip_info(struct seq_file *m, void *data) - { - struct drm_info_node *node = (struct drm_info_node *) m->private; -@@ -176,6 +265,11 @@ static int i915_gem_request_info(struct seq_file *m, void *data) - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_request *gem_request; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - - seq_printf(m, "Request:\n"); - list_for_each_entry(gem_request, &dev_priv->render_ring.request_list, -@@ -184,6 +278,8 @@ static int i915_gem_request_info(struct seq_file *m, void *data) - gem_request->seqno, - (int) (jiffies - gem_request->emitted_jiffies)); - } -+ mutex_unlock(&dev->struct_mutex); -+ - return 0; - } - -@@ -192,16 +288,24 @@ static int i915_gem_seqno_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; - drm_i915_private_t *dev_priv = dev->dev_private; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - - if (dev_priv->render_ring.status_page.page_addr != NULL) { - seq_printf(m, "Current sequence: %d\n", -- i915_get_gem_seqno(dev, &dev_priv->render_ring)); -+ dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring)); - } else { - seq_printf(m, "Current sequence: hws uninitialized\n"); - } - seq_printf(m, "Waiter sequence: %d\n", - dev_priv->mm.waiting_gem_seqno); - seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); -+ -+ mutex_unlock(&dev->struct_mutex); -+ - return 0; - } - -@@ -211,6 +315,11 @@ static int i915_interrupt_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; - drm_i915_private_t *dev_priv = dev->dev_private; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - - if (!HAS_PCH_SPLIT(dev)) { - seq_printf(m, "Interrupt enable: %08x\n", -@@ -247,7 +356,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) - atomic_read(&dev_priv->irq_received)); - if (dev_priv->render_ring.status_page.page_addr != NULL) { - seq_printf(m, "Current sequence: %d\n", -- i915_get_gem_seqno(dev, &dev_priv->render_ring)); -+ dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring)); - } else { - seq_printf(m, "Current sequence: hws uninitialized\n"); - } -@@ -255,6 +364,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data) - dev_priv->mm.waiting_gem_seqno); - seq_printf(m, "IRQ sequence: %d\n", - dev_priv->mm.irq_gem_seqno); -+ mutex_unlock(&dev->struct_mutex); -+ - return 0; - } - -@@ -263,7 +374,11 @@ static int i915_gem_fence_regs_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; - drm_i915_private_t *dev_priv = dev->dev_private; -- int i; -+ int i, ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - - seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start); - seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); -@@ -289,6 +404,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) - seq_printf(m, "\n"); - } - } -+ mutex_unlock(&dev->struct_mutex); - - return 0; - } -@@ -313,16 +429,19 @@ static int i915_hws_info(struct seq_file *m, void *data) - return 0; - } - --static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_count) -+static void i915_dump_object(struct seq_file *m, -+ struct io_mapping *mapping, -+ struct drm_i915_gem_object *obj_priv) - { -- int page, i; -- uint32_t *mem; -+ int page, page_count, i; - -+ page_count = obj_priv->base.size / PAGE_SIZE; - for (page = 0; page < page_count; page++) { -- mem = kmap_atomic(pages[page], KM_USER0); -+ u32 *mem = io_mapping_map_wc(mapping, -+ obj_priv->gtt_offset + page * PAGE_SIZE); - for (i = 0; i < PAGE_SIZE; i += 4) - seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); -- kunmap_atomic(mem, KM_USER0); -+ io_mapping_unmap(mem); - } - } - -@@ -335,27 +454,20 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data) - struct drm_i915_gem_object *obj_priv; - int ret; - -- spin_lock(&dev_priv->mm.active_list_lock); -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - -- list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list, -- list) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - obj = &obj_priv->base; - if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { -- ret = i915_gem_object_get_pages(obj, 0); -- if (ret) { -- DRM_ERROR("Failed to get pages: %d\n", ret); -- spin_unlock(&dev_priv->mm.active_list_lock); -- return ret; -- } -- -- seq_printf(m, "--- gtt_offset = 0x%08x\n", obj_priv->gtt_offset); -- i915_dump_pages(m, obj_priv->pages, obj->size / PAGE_SIZE); -- -- i915_gem_object_put_pages(obj); -+ seq_printf(m, "--- gtt_offset = 0x%08x\n", -+ obj_priv->gtt_offset); -+ i915_dump_object(m, dev_priv->mm.gtt_mapping, obj_priv); - } - } - -- spin_unlock(&dev_priv->mm.active_list_lock); -+ mutex_unlock(&dev->struct_mutex); - - return 0; - } -@@ -365,20 +477,24 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data) - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; -- u8 *virt; -- uint32_t *ptr, off; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - - if (!dev_priv->render_ring.gem_object) { - seq_printf(m, "No ringbuffer setup\n"); -- return 0; -- } -- -- virt = dev_priv->render_ring.virtual_start; -+ } else { -+ u8 *virt = dev_priv->render_ring.virtual_start; -+ uint32_t off; - -- for (off = 0; off < dev_priv->render_ring.size; off += 4) { -- ptr = (uint32_t *)(virt + off); -- seq_printf(m, "%08x : %08x\n", off, *ptr); -+ for (off = 0; off < dev_priv->render_ring.size; off += 4) { -+ uint32_t *ptr = (uint32_t *)(virt + off); -+ seq_printf(m, "%08x : %08x\n", off, *ptr); -+ } - } -+ mutex_unlock(&dev->struct_mutex); - - return 0; - } -@@ -396,7 +512,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) - seq_printf(m, "RingHead : %08x\n", head); - seq_printf(m, "RingTail : %08x\n", tail); - seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size); -- seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD)); -+ seq_printf(m, "Acthd : %08x\n", I915_READ(INTEL_INFO(dev)->gen >= 4 ? ACTHD_I965 : ACTHD)); - - return 0; - } -@@ -458,7 +574,7 @@ static int i915_error_state(struct seq_file *m, void *unused) - seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); - seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); - seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - seq_printf(m, " INSTPS: 0x%08x\n", error->instps); - seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); - } -@@ -642,6 +758,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused) - } else { - seq_printf(m, "FBC disabled: "); - switch (dev_priv->no_fbc_reason) { -+ case FBC_NO_OUTPUT: -+ seq_printf(m, "no outputs"); -+ break; - case FBC_STOLEN_TOO_SMALL: - seq_printf(m, "not enough stolen memory"); - break; -@@ -675,15 +794,17 @@ static int i915_sr_status(struct seq_file *m, void *unused) - drm_i915_private_t *dev_priv = dev->dev_private; - bool sr_enabled = false; - -- if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev)) -+ if (IS_GEN5(dev)) -+ sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN; -+ else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev)) - sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN; - else if (IS_I915GM(dev)) - sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; - else if (IS_PINEVIEW(dev)) - sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN; - -- seq_printf(m, "self-refresh: %s\n", sr_enabled ? "enabled" : -- "disabled"); -+ seq_printf(m, "self-refresh: %s\n", -+ sr_enabled ? "enabled" : "disabled"); - - return 0; - } -@@ -694,10 +815,16 @@ static int i915_emon_status(struct seq_file *m, void *unused) - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - unsigned long temp, chipset, gfx; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; - - temp = i915_mch_val(dev_priv); - chipset = i915_chipset_val(dev_priv); - gfx = i915_gfx_val(dev_priv); -+ mutex_unlock(&dev->struct_mutex); - - seq_printf(m, "GMCH temp: %ld\n", temp); - seq_printf(m, "Chipset power: %ld\n", chipset); -@@ -718,6 +845,68 @@ static int i915_gfxec(struct seq_file *m, void *unused) - return 0; - } - -+static int i915_opregion(struct seq_file *m, void *unused) -+{ -+ struct drm_info_node *node = (struct drm_info_node *) m->private; -+ struct drm_device *dev = node->minor->dev; -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ struct intel_opregion *opregion = &dev_priv->opregion; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; -+ -+ if (opregion->header) -+ seq_write(m, opregion->header, OPREGION_SIZE); -+ -+ mutex_unlock(&dev->struct_mutex); -+ -+ return 0; -+} -+ -+static int i915_gem_framebuffer_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; -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ struct intel_fbdev *ifbdev; -+ struct intel_framebuffer *fb; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&dev->mode_config.mutex); -+ if (ret) -+ return ret; -+ -+ ifbdev = dev_priv->fbdev; -+ fb = to_intel_framebuffer(ifbdev->helper.fb); -+ -+ seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, obj ", -+ fb->base.width, -+ fb->base.height, -+ fb->base.depth, -+ fb->base.bits_per_pixel); -+ describe_obj(m, to_intel_bo(fb->obj)); -+ seq_printf(m, "\n"); -+ -+ list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { -+ if (&fb->base == ifbdev->helper.fb) -+ continue; -+ -+ seq_printf(m, "user size: %d x %d, depth %d, %d bpp, obj ", -+ fb->base.width, -+ fb->base.height, -+ fb->base.depth, -+ fb->base.bits_per_pixel); -+ describe_obj(m, to_intel_bo(fb->obj)); -+ seq_printf(m, "\n"); -+ } -+ -+ mutex_unlock(&dev->mode_config.mutex); -+ -+ return 0; -+} -+ - static int - i915_wedged_open(struct inode *inode, - struct file *filp) -@@ -741,6 +930,9 @@ i915_wedged_read(struct file *filp, - "wedged : %d\n", - atomic_read(&dev_priv->mm.wedged)); - -+ if (len > sizeof (buf)) -+ len = sizeof (buf); -+ - return simple_read_from_buffer(ubuf, max, ppos, buf, len); - } - -@@ -770,7 +962,7 @@ i915_wedged_write(struct file *filp, - - atomic_set(&dev_priv->mm.wedged, val); - if (val) { -- DRM_WAKEUP(&dev_priv->irq_queue); -+ wake_up_all(&dev_priv->irq_queue); - queue_work(dev_priv->wq, &dev_priv->error_work); - } - -@@ -782,6 +974,7 @@ static const struct file_operations i915_wedged_fops = { - .open = i915_wedged_open, - .read = i915_wedged_read, - .write = i915_wedged_write, -+ .llseek = default_llseek, - }; - - /* As the drm_debugfs_init() routines are called before dev->dev_private is -@@ -823,9 +1016,13 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) - } - - static struct drm_info_list i915_debugfs_list[] = { -+ {"i915_capabilities", i915_capabilities, 0, 0}, -+ {"i915_gem_objects", i915_gem_object_info, 0}, - {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, - {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, - {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, -+ {"i915_gem_pinned", i915_gem_object_list_info, 0, (void *) PINNED_LIST}, -+ {"i915_gem_deferred_free", i915_gem_object_list_info, 0, (void *) DEFERRED_FREE_LIST}, - {"i915_gem_pageflip", i915_gem_pageflip_info, 0}, - {"i915_gem_request", i915_gem_request_info, 0}, - {"i915_gem_seqno", i915_gem_seqno_info, 0}, -@@ -845,6 +1042,8 @@ static struct drm_info_list i915_debugfs_list[] = { - {"i915_gfxec", i915_gfxec, 0}, - {"i915_fbc_status", i915_fbc_status, 0}, - {"i915_sr_status", i915_sr_status, 0}, -+ {"i915_opregion", i915_opregion, 0}, -+ {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, - }; - #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) - -diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c -index 2dd2c93..7a26f4dd 100644 ---- a/drivers/gpu/drm/i915/i915_dma.c -+++ b/drivers/gpu/drm/i915/i915_dma.c -@@ -40,8 +40,7 @@ - #include - #include - #include -- --extern int intel_max_stolen; /* from AGP driver */ -+#include - - /** - * Sets up the hardware status page for devices that need a physical address -@@ -64,7 +63,7 @@ static int i915_init_phys_hws(struct drm_device *dev) - - memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE); - -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & - 0xf0; - -@@ -133,8 +132,8 @@ static int i915_dma_cleanup(struct drm_device * dev) - - mutex_lock(&dev->struct_mutex); - intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); -- if (HAS_BSD(dev)) -- intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); -+ intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); -+ intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring); - mutex_unlock(&dev->struct_mutex); - - /* Clear the HWS virtual address at teardown */ -@@ -222,7 +221,7 @@ static int i915_dma_resume(struct drm_device * dev) - DRM_DEBUG_DRIVER("hw status page @ %p\n", - ring->status_page.page_addr); - if (ring->status_page.gfx_addr != 0) -- ring->setup_status_page(dev, ring); -+ intel_ring_setup_status_page(dev, ring); - else - I915_WRITE(HWS_PGA, dev_priv->dma_status_page); - -@@ -377,7 +376,7 @@ i915_emit_box(struct drm_device *dev, - return -EINVAL; - } - -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - BEGIN_LP_RING(4); - OUT_RING(GFX_OP_DRAWRECT_INFO_I965); - OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); -@@ -481,7 +480,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, - - if (!IS_I830(dev) && !IS_845G(dev)) { - BEGIN_LP_RING(2); -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); - OUT_RING(batch->start); - } else { -@@ -500,7 +499,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, - } - - -- if (IS_G4X(dev) || IS_IRONLAKE(dev)) { -+ if (IS_G4X(dev) || IS_GEN5(dev)) { - BEGIN_LP_RING(2); - OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH | MI_INVALIDATE_ISP); - OUT_RING(MI_NOOP); -@@ -765,6 +764,9 @@ static int i915_getparam(struct drm_device *dev, void *data, - case I915_PARAM_HAS_BSD: - value = HAS_BSD(dev); - break; -+ case I915_PARAM_HAS_BLT: -+ value = HAS_BLT(dev); -+ break; - default: - DRM_DEBUG_DRIVER("Unknown parameter %d\n", - param->param); -@@ -888,12 +890,12 @@ static int - intel_alloc_mchbar_resource(struct drm_device *dev) - { - drm_i915_private_t *dev_priv = dev->dev_private; -- int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; -+ int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; - u32 temp_lo, temp_hi = 0; - u64 mchbar_addr; - int ret; - -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); - pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo); - mchbar_addr = ((u64)temp_hi << 32) | temp_lo; -@@ -920,7 +922,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) - return ret; - } - -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - pci_write_config_dword(dev_priv->bridge_dev, reg + 4, - upper_32_bits(dev_priv->mch_res.start)); - -@@ -934,7 +936,7 @@ static void - intel_setup_mchbar(struct drm_device *dev) - { - drm_i915_private_t *dev_priv = dev->dev_private; -- int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; -+ int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; - u32 temp; - bool enabled; - -@@ -971,7 +973,7 @@ static void - intel_teardown_mchbar(struct drm_device *dev) - { - drm_i915_private_t *dev_priv = dev->dev_private; -- int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; -+ int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; - u32 temp; - - if (dev_priv->mchbar_need_disable) { -@@ -990,174 +992,6 @@ intel_teardown_mchbar(struct drm_device *dev) - release_resource(&dev_priv->mch_res); - } - --/** -- * i915_probe_agp - get AGP bootup configuration -- * @pdev: PCI device -- * @aperture_size: returns AGP aperture configured size -- * @preallocated_size: returns size of BIOS preallocated AGP space -- * -- * Since Intel integrated graphics are UMA, the BIOS has to set aside -- * some RAM for the framebuffer at early boot. This code figures out -- * how much was set aside so we can use it for our own purposes. -- */ --static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, -- uint32_t *preallocated_size, -- uint32_t *start) --{ -- struct drm_i915_private *dev_priv = dev->dev_private; -- u16 tmp = 0; -- unsigned long overhead; -- unsigned long stolen; -- -- /* Get the fb aperture size and "stolen" memory amount. */ -- pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp); -- -- *aperture_size = 1024 * 1024; -- *preallocated_size = 1024 * 1024; -- -- switch (dev->pdev->device) { -- case PCI_DEVICE_ID_INTEL_82830_CGC: -- case PCI_DEVICE_ID_INTEL_82845G_IG: -- case PCI_DEVICE_ID_INTEL_82855GM_IG: -- case PCI_DEVICE_ID_INTEL_82865_IG: -- if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) -- *aperture_size *= 64; -- else -- *aperture_size *= 128; -- break; -- default: -- /* 9xx supports large sizes, just look at the length */ -- *aperture_size = pci_resource_len(dev->pdev, 2); -- break; -- } -- -- /* -- * Some of the preallocated space is taken by the GTT -- * and popup. GTT is 1K per MB of aperture size, and popup is 4K. -- */ -- if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) -- overhead = 4096; -- else -- overhead = (*aperture_size / 1024) + 4096; -- -- if (IS_GEN6(dev)) { -- /* SNB has memory control reg at 0x50.w */ -- pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &tmp); -- -- switch (tmp & SNB_GMCH_GMS_STOLEN_MASK) { -- case INTEL_855_GMCH_GMS_DISABLED: -- DRM_ERROR("video memory is disabled\n"); -- return -1; -- case SNB_GMCH_GMS_STOLEN_32M: -- stolen = 32 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_64M: -- stolen = 64 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_96M: -- stolen = 96 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_128M: -- stolen = 128 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_160M: -- stolen = 160 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_192M: -- stolen = 192 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_224M: -- stolen = 224 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_256M: -- stolen = 256 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_288M: -- stolen = 288 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_320M: -- stolen = 320 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_352M: -- stolen = 352 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_384M: -- stolen = 384 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_416M: -- stolen = 416 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_448M: -- stolen = 448 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_480M: -- stolen = 480 * 1024 * 1024; -- break; -- case SNB_GMCH_GMS_STOLEN_512M: -- stolen = 512 * 1024 * 1024; -- break; -- default: -- DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", -- tmp & SNB_GMCH_GMS_STOLEN_MASK); -- return -1; -- } -- } else { -- switch (tmp & INTEL_GMCH_GMS_MASK) { -- case INTEL_855_GMCH_GMS_DISABLED: -- DRM_ERROR("video memory is disabled\n"); -- return -1; -- case INTEL_855_GMCH_GMS_STOLEN_1M: -- stolen = 1 * 1024 * 1024; -- break; -- case INTEL_855_GMCH_GMS_STOLEN_4M: -- stolen = 4 * 1024 * 1024; -- break; -- case INTEL_855_GMCH_GMS_STOLEN_8M: -- stolen = 8 * 1024 * 1024; -- break; -- case INTEL_855_GMCH_GMS_STOLEN_16M: -- stolen = 16 * 1024 * 1024; -- break; -- case INTEL_855_GMCH_GMS_STOLEN_32M: -- stolen = 32 * 1024 * 1024; -- break; -- case INTEL_915G_GMCH_GMS_STOLEN_48M: -- stolen = 48 * 1024 * 1024; -- break; -- case INTEL_915G_GMCH_GMS_STOLEN_64M: -- stolen = 64 * 1024 * 1024; -- break; -- case INTEL_GMCH_GMS_STOLEN_128M: -- stolen = 128 * 1024 * 1024; -- break; -- case INTEL_GMCH_GMS_STOLEN_256M: -- stolen = 256 * 1024 * 1024; -- break; -- case INTEL_GMCH_GMS_STOLEN_96M: -- stolen = 96 * 1024 * 1024; -- break; -- case INTEL_GMCH_GMS_STOLEN_160M: -- stolen = 160 * 1024 * 1024; -- break; -- case INTEL_GMCH_GMS_STOLEN_224M: -- stolen = 224 * 1024 * 1024; -- break; -- case INTEL_GMCH_GMS_STOLEN_352M: -- stolen = 352 * 1024 * 1024; -- break; -- default: -- DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", -- tmp & INTEL_GMCH_GMS_MASK); -- return -1; -- } -- } -- -- *preallocated_size = stolen - overhead; -- *start = overhead; -- -- return 0; --} -- - #define PTE_ADDRESS_MASK 0xfffff000 - #define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */ - #define PTE_MAPPING_TYPE_UNCACHED (0 << 1) -@@ -1181,11 +1015,11 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, - { - unsigned long *gtt; - unsigned long entry, phys; -- int gtt_bar = IS_I9XX(dev) ? 0 : 1; -+ int gtt_bar = IS_GEN2(dev) ? 1 : 0; - int gtt_offset, gtt_size; - -- if (IS_I965G(dev)) { -- if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { -+ if (IS_G4X(dev) || INTEL_INFO(dev)->gen > 4) { - gtt_offset = 2*1024*1024; - gtt_size = 2*1024*1024; - } else { -@@ -1210,10 +1044,8 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, - DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry); - - /* Mask out these reserved bits on this hardware. */ -- if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) || -- IS_I945G(dev) || IS_I945GM(dev)) { -+ if (INTEL_INFO(dev)->gen < 4 && !IS_G33(dev)) - entry &= ~PTE_ADDRESS_MASK_HIGH; -- } - - /* If it's not a mapping type we know, then bail. */ - if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED && -@@ -1252,7 +1084,7 @@ static void i915_setup_compression(struct drm_device *dev, int size) - unsigned long ll_base = 0; - - /* Leave 1M for line length buffer & misc. */ -- compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0); -+ compressed_fb = drm_mm_search_free(&dev_priv->mm.vram, size, 4096, 0); - if (!compressed_fb) { - dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; - i915_warn_stolen(dev); -@@ -1273,7 +1105,7 @@ static void i915_setup_compression(struct drm_device *dev, int size) - } - - if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) { -- compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096, -+ compressed_llb = drm_mm_search_free(&dev_priv->mm.vram, 4096, - 4096, 0); - if (!compressed_llb) { - i915_warn_stolen(dev); -@@ -1343,10 +1175,8 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ - /* i915 resume handler doesn't set to D0 */ - pci_set_power_state(dev->pdev, PCI_D0); - i915_resume(dev); -- drm_kms_helper_poll_enable(dev); - } else { - printk(KERN_ERR "i915: switched off\n"); -- drm_kms_helper_poll_disable(dev); - i915_suspend(dev, pmm); - } - } -@@ -1363,23 +1193,14 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) - } - - static int i915_load_modeset_init(struct drm_device *dev, -- unsigned long prealloc_start, - unsigned long prealloc_size, - unsigned long agp_size) - { - struct drm_i915_private *dev_priv = dev->dev_private; -- int fb_bar = IS_I9XX(dev) ? 2 : 0; - int ret = 0; - -- dev->mode_config.fb_base = pci_resource_start(dev->pdev, fb_bar) & -- 0xff000000; -- -- /* Basic memrange allocator for stolen space (aka vram) */ -- drm_mm_init(&dev_priv->vram, 0, prealloc_size); -- DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024)); -- -- /* We're off and running w/KMS */ -- dev_priv->mm.suspended = 0; -+ /* Basic memrange allocator for stolen space (aka mm.vram) */ -+ drm_mm_init(&dev_priv->mm.vram, 0, prealloc_size); - - /* Let GEM Manage from end of prealloc space to end of aperture. - * -@@ -1414,7 +1235,7 @@ static int i915_load_modeset_init(struct drm_device *dev, - */ - dev_priv->allow_batchbuffer = 1; - -- ret = intel_init_bios(dev); -+ ret = intel_parse_bios(dev); - if (ret) - DRM_INFO("failed to find VBIOS tables\n"); - -@@ -1423,6 +1244,8 @@ static int i915_load_modeset_init(struct drm_device *dev, - if (ret) - goto cleanup_ringbuffer; - -+ intel_register_dsm_handler(); -+ - ret = vga_switcheroo_register_client(dev->pdev, - i915_switcheroo_set_state, - i915_switcheroo_can_switch); -@@ -1443,17 +1266,15 @@ static int i915_load_modeset_init(struct drm_device *dev, - /* FIXME: do pre/post-mode set stuff in core KMS code */ - dev->vblank_disable_allowed = 1; - -- /* -- * Initialize the hardware status page IRQ location. -- */ -- -- I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); -- - ret = intel_fbdev_init(dev); - if (ret) - goto cleanup_irq; - - drm_kms_helper_poll_init(dev); -+ -+ /* We're off and running w/KMS */ -+ dev_priv->mm.suspended = 0; -+ - return 0; - - cleanup_irq: -@@ -1907,7 +1728,7 @@ static struct drm_i915_private *i915_mch_dev; - * - dev_priv->fmax - * - dev_priv->gpu_busy - */ --DEFINE_SPINLOCK(mchdev_lock); -+static DEFINE_SPINLOCK(mchdev_lock); - - /** - * i915_read_mch_val - return value for IPS use -@@ -2062,7 +1883,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - struct drm_i915_private *dev_priv; - resource_size_t base, size; - int ret = 0, mmio_bar; -- uint32_t agp_size, prealloc_size, prealloc_start; -+ uint32_t agp_size, prealloc_size; - /* i915 has 4 more counters */ - dev->counters += 4; - dev->types[6] = _DRM_STAT_IRQ; -@@ -2079,7 +1900,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - dev_priv->info = (struct intel_device_info *) flags; - - /* Add register map (needed for suspend/resume) */ -- mmio_bar = IS_I9XX(dev) ? 0 : 1; -+ mmio_bar = IS_GEN2(dev) ? 1 : 0; - base = pci_resource_start(dev->pdev, mmio_bar); - size = pci_resource_len(dev->pdev, mmio_bar); - -@@ -2121,17 +1942,32 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - "performance may suffer.\n"); - } - -- ret = i915_probe_agp(dev, &agp_size, &prealloc_size, &prealloc_start); -- if (ret) -+ dev_priv->mm.gtt = intel_gtt_get(); -+ if (!dev_priv->mm.gtt) { -+ DRM_ERROR("Failed to initialize GTT\n"); -+ ret = -ENODEV; - goto out_iomapfree; -- -- if (prealloc_size > intel_max_stolen) { -- DRM_INFO("detected %dM stolen memory, trimming to %dM\n", -- prealloc_size >> 20, intel_max_stolen >> 20); -- prealloc_size = intel_max_stolen; - } - -- dev_priv->wq = create_singlethread_workqueue("i915"); -+ prealloc_size = dev_priv->mm.gtt->gtt_stolen_entries << PAGE_SHIFT; -+ agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; -+ -+ /* The i915 workqueue is primarily used for batched retirement of -+ * requests (and thus managing bo) once the task has been completed -+ * by the GPU. i915_gem_retire_requests() is called directly when we -+ * need high-priority retirement, such as waiting for an explicit -+ * bo. -+ * -+ * It is also used for periodic low-priority events, such as -+ * idle-timers and hangcheck. -+ * -+ * All tasks on the workqueue are expected to acquire the dev mutex -+ * so there is no point in running more than one instance of the -+ * workqueue at any time: max_active = 1 and NON_REENTRANT. -+ */ -+ dev_priv->wq = alloc_workqueue("i915", -+ WQ_UNBOUND | WQ_NON_REENTRANT, -+ 1); - if (dev_priv->wq == NULL) { - DRM_ERROR("Failed to create our workqueue.\n"); - ret = -ENOMEM; -@@ -2159,13 +1995,18 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - - dev->driver->get_vblank_counter = i915_get_vblank_counter; - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ -- if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) { -+ if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev)) { - dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ - dev->driver->get_vblank_counter = gm45_get_vblank_counter; - } - - /* Try to make sure MCHBAR is enabled before poking at it */ - intel_setup_mchbar(dev); -+ intel_setup_gmbus(dev); -+ intel_opregion_setup(dev); -+ -+ /* Make sure the bios did its job and set up vital registers */ -+ intel_setup_bios(dev); - - i915_gem_load(dev); - -@@ -2178,7 +2019,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - - if (IS_PINEVIEW(dev)) - i915_pineview_get_mem_freq(dev); -- else if (IS_IRONLAKE(dev)) -+ else if (IS_GEN5(dev)) - i915_ironlake_get_mem_freq(dev); - - /* On the 945G/GM, the chipset reports the MSI capability on the -@@ -2212,8 +2053,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - intel_detect_pch(dev); - - if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- ret = i915_load_modeset_init(dev, prealloc_start, -- prealloc_size, agp_size); -+ ret = i915_load_modeset_init(dev, prealloc_size, agp_size); - if (ret < 0) { - DRM_ERROR("failed to init modeset\n"); - goto out_workqueue_free; -@@ -2221,7 +2061,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - } - - /* Must be done after probing outputs */ -- intel_opregion_init(dev, 0); -+ intel_opregion_init(dev); -+ acpi_video_register(); - - setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, - (unsigned long) dev); -@@ -2231,9 +2072,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) - dev_priv->mchdev_lock = &mchdev_lock; - spin_unlock(&mchdev_lock); - -- /* XXX Prevent module unload due to memory corruption bugs. */ -- __module_get(THIS_MODULE); -- - return 0; - - out_workqueue_free: -@@ -2252,15 +2090,20 @@ free_priv: - int i915_driver_unload(struct drm_device *dev) - { - struct drm_i915_private *dev_priv = dev->dev_private; -- -- i915_destroy_error_state(dev); -+ int ret; - - spin_lock(&mchdev_lock); - i915_mch_dev = NULL; - spin_unlock(&mchdev_lock); - -- destroy_workqueue(dev_priv->wq); -- del_timer_sync(&dev_priv->hangcheck_timer); -+ mutex_lock(&dev->struct_mutex); -+ ret = i915_gpu_idle(dev); -+ if (ret) -+ DRM_ERROR("failed to idle hardware: %d\n", ret); -+ mutex_unlock(&dev->struct_mutex); -+ -+ /* Cancel the retire work handler, which should be idle now. */ -+ cancel_delayed_work_sync(&dev_priv->mm.retire_work); - - io_mapping_free(dev_priv->mm.gtt_mapping); - if (dev_priv->mm.gtt_mtrr >= 0) { -@@ -2269,7 +2112,10 @@ int i915_driver_unload(struct drm_device *dev) - dev_priv->mm.gtt_mtrr = -1; - } - -+ acpi_video_unregister(); -+ - if (drm_core_check_feature(dev, DRIVER_MODESET)) { -+ intel_fbdev_fini(dev); - intel_modeset_cleanup(dev); - - /* -@@ -2281,20 +2127,25 @@ int i915_driver_unload(struct drm_device *dev) - dev_priv->child_dev = NULL; - dev_priv->child_dev_num = 0; - } -- drm_irq_uninstall(dev); -+ - vga_switcheroo_unregister_client(dev->pdev); - vga_client_register(dev->pdev, NULL, NULL, NULL); - } - -+ /* Free error state after interrupts are fully disabled. */ -+ del_timer_sync(&dev_priv->hangcheck_timer); -+ cancel_work_sync(&dev_priv->error_work); -+ i915_destroy_error_state(dev); -+ - if (dev->pdev->msi_enabled) - pci_disable_msi(dev->pdev); - -- if (dev_priv->regs != NULL) -- iounmap(dev_priv->regs); -- -- intel_opregion_free(dev, 0); -+ intel_opregion_fini(dev); - - if (drm_core_check_feature(dev, DRIVER_MODESET)) { -+ /* Flush any outstanding unpin_work. */ -+ flush_workqueue(dev_priv->wq); -+ - i915_gem_free_all_phys_object(dev); - - mutex_lock(&dev->struct_mutex); -@@ -2302,34 +2153,41 @@ int i915_driver_unload(struct drm_device *dev) - mutex_unlock(&dev->struct_mutex); - if (I915_HAS_FBC(dev) && i915_powersave) - i915_cleanup_compression(dev); -- drm_mm_takedown(&dev_priv->vram); -- i915_gem_lastclose(dev); -+ drm_mm_takedown(&dev_priv->mm.vram); - - intel_cleanup_overlay(dev); -+ -+ if (!I915_NEED_GFX_HWS(dev)) -+ i915_free_hws(dev); - } - -+ if (dev_priv->regs != NULL) -+ iounmap(dev_priv->regs); -+ -+ intel_teardown_gmbus(dev); - intel_teardown_mchbar(dev); - -+ destroy_workqueue(dev_priv->wq); -+ - pci_dev_put(dev_priv->bridge_dev); - kfree(dev->dev_private); - - return 0; - } - --int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv) -+int i915_driver_open(struct drm_device *dev, struct drm_file *file) - { -- struct drm_i915_file_private *i915_file_priv; -+ struct drm_i915_file_private *file_priv; - - DRM_DEBUG_DRIVER("\n"); -- i915_file_priv = (struct drm_i915_file_private *) -- kmalloc(sizeof(*i915_file_priv), GFP_KERNEL); -- -- if (!i915_file_priv) -+ file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL); -+ if (!file_priv) - return -ENOMEM; - -- file_priv->driver_priv = i915_file_priv; -+ file->driver_priv = file_priv; - -- INIT_LIST_HEAD(&i915_file_priv->mm.request_list); -+ spin_lock_init(&file_priv->mm.lock); -+ INIT_LIST_HEAD(&file_priv->mm.request_list); - - return 0; - } -@@ -2372,11 +2230,11 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) - i915_mem_release(dev, file_priv, dev_priv->agp_heap); - } - --void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) -+void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) - { -- struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; -+ struct drm_i915_file_private *file_priv = file->driver_priv; - -- kfree(i915_file_priv); -+ kfree(file_priv); - } - - struct drm_ioctl_desc i915_ioctls[] = { -diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c -index 6dbe14c..027cbfc 100644 ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -32,6 +32,7 @@ - #include "drm.h" - #include "i915_drm.h" - #include "i915_drv.h" -+#include "intel_drv.h" - - #include - #include "drm_crtc_helper.h" -@@ -43,7 +44,7 @@ unsigned int i915_fbpercrtc = 0; - module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); - - unsigned int i915_powersave = 1; --module_param_named(powersave, i915_powersave, int, 0400); -+module_param_named(powersave, i915_powersave, int, 0600); - - unsigned int i915_lvds_downclock = 0; - module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); -@@ -61,86 +62,110 @@ extern int intel_agp_enabled; - .driver_data = (unsigned long) info } - - static const struct intel_device_info intel_i830_info = { -- .gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, -+ .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, -+ .has_overlay = 1, .overlay_needs_physical = 1, - }; - - static const struct intel_device_info intel_845g_info = { -- .gen = 2, .is_i8xx = 1, -+ .gen = 2, -+ .has_overlay = 1, .overlay_needs_physical = 1, - }; - - static const struct intel_device_info intel_i85x_info = { -- .gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, -+ .gen = 2, .is_i85x = 1, .is_mobile = 1, - .cursor_needs_physical = 1, -+ .has_overlay = 1, .overlay_needs_physical = 1, - }; - - static const struct intel_device_info intel_i865g_info = { -- .gen = 2, .is_i8xx = 1, -+ .gen = 2, -+ .has_overlay = 1, .overlay_needs_physical = 1, - }; - - static const struct intel_device_info intel_i915g_info = { -- .gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, -+ .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, -+ .has_overlay = 1, .overlay_needs_physical = 1, - }; - static const struct intel_device_info intel_i915gm_info = { -- .gen = 3, .is_i9xx = 1, .is_mobile = 1, -+ .gen = 3, .is_mobile = 1, - .cursor_needs_physical = 1, -+ .has_overlay = 1, .overlay_needs_physical = 1, -+ .supports_tv = 1, - }; - static const struct intel_device_info intel_i945g_info = { -- .gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, -+ .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, -+ .has_overlay = 1, .overlay_needs_physical = 1, - }; - static const struct intel_device_info intel_i945gm_info = { -- .gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, -+ .gen = 3, .is_i945gm = 1, .is_mobile = 1, - .has_hotplug = 1, .cursor_needs_physical = 1, -+ .has_overlay = 1, .overlay_needs_physical = 1, -+ .supports_tv = 1, - }; - - static const struct intel_device_info intel_i965g_info = { -- .gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, -+ .gen = 4, .is_broadwater = 1, - .has_hotplug = 1, -+ .has_overlay = 1, - }; - - static const struct intel_device_info intel_i965gm_info = { -- .gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, -+ .gen = 4, .is_crestline = 1, - .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, -+ .has_overlay = 1, -+ .supports_tv = 1, - }; - - static const struct intel_device_info intel_g33_info = { -- .gen = 3, .is_g33 = 1, .is_i9xx = 1, -+ .gen = 3, .is_g33 = 1, - .need_gfx_hws = 1, .has_hotplug = 1, -+ .has_overlay = 1, - }; - - static const struct intel_device_info intel_g45_info = { -- .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, -+ .gen = 4, .is_g4x = 1, .need_gfx_hws = 1, - .has_pipe_cxsr = 1, .has_hotplug = 1, -+ .has_bsd_ring = 1, - }; - - static const struct intel_device_info intel_gm45_info = { -- .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, -+ .gen = 4, .is_g4x = 1, - .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, - .has_pipe_cxsr = 1, .has_hotplug = 1, -+ .supports_tv = 1, -+ .has_bsd_ring = 1, - }; - - static const struct intel_device_info intel_pineview_info = { -- .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, -+ .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, - .need_gfx_hws = 1, .has_hotplug = 1, -+ .has_overlay = 1, - }; - - static const struct intel_device_info intel_ironlake_d_info = { -- .gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, -+ .gen = 5, - .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, -+ .has_bsd_ring = 1, - }; - - static const struct intel_device_info intel_ironlake_m_info = { -- .gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, -+ .gen = 5, .is_mobile = 1, - .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, -+ .has_bsd_ring = 1, - }; - - static const struct intel_device_info intel_sandybridge_d_info = { -- .gen = 6, .is_i965g = 1, .is_i9xx = 1, -+ .gen = 6, - .need_gfx_hws = 1, .has_hotplug = 1, -+ .has_bsd_ring = 1, -+ .has_blt_ring = 1, - }; - - static const struct intel_device_info intel_sandybridge_m_info = { -- .gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, -+ .gen = 6, .is_mobile = 1, - .need_gfx_hws = 1, .has_hotplug = 1, -+ .has_bsd_ring = 1, -+ .has_blt_ring = 1, - }; - - static const struct pci_device_id pciidlist[] = { /* aka */ -@@ -237,7 +262,7 @@ static int i915_drm_freeze(struct drm_device *dev) - - i915_save_state(dev); - -- intel_opregion_free(dev, 1); -+ intel_opregion_fini(dev); - - /* Modeset on resume, not lid events */ - dev_priv->modeset_on_lid = 0; -@@ -258,6 +283,8 @@ int i915_suspend(struct drm_device *dev, pm_message_t state) - if (state.event == PM_EVENT_PRETHAW) - return 0; - -+ drm_kms_helper_poll_disable(dev); -+ - error = i915_drm_freeze(dev); - if (error) - return error; -@@ -277,8 +304,7 @@ static int i915_drm_thaw(struct drm_device *dev) - int error = 0; - - i915_restore_state(dev); -- -- intel_opregion_init(dev, 1); -+ intel_opregion_setup(dev); - - /* KMS EnterVT equivalent */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) { -@@ -294,6 +320,8 @@ static int i915_drm_thaw(struct drm_device *dev) - drm_helper_resume_force_mode(dev); - } - -+ intel_opregion_init(dev); -+ - dev_priv->modeset_on_lid = 0; - - return error; -@@ -301,12 +329,79 @@ static int i915_drm_thaw(struct drm_device *dev) - - int i915_resume(struct drm_device *dev) - { -+ int ret; -+ - if (pci_enable_device(dev->pdev)) - return -EIO; - - pci_set_master(dev->pdev); - -- return i915_drm_thaw(dev); -+ ret = i915_drm_thaw(dev); -+ if (ret) -+ return ret; -+ -+ drm_kms_helper_poll_enable(dev); -+ return 0; -+} -+ -+static int i8xx_do_reset(struct drm_device *dev, u8 flags) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ -+ if (IS_I85X(dev)) -+ return -ENODEV; -+ -+ I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830); -+ POSTING_READ(D_STATE); -+ -+ if (IS_I830(dev) || IS_845G(dev)) { -+ I915_WRITE(DEBUG_RESET_I830, -+ DEBUG_RESET_DISPLAY | -+ DEBUG_RESET_RENDER | -+ DEBUG_RESET_FULL); -+ POSTING_READ(DEBUG_RESET_I830); -+ msleep(1); -+ -+ I915_WRITE(DEBUG_RESET_I830, 0); -+ POSTING_READ(DEBUG_RESET_I830); -+ } -+ -+ msleep(1); -+ -+ I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830); -+ POSTING_READ(D_STATE); -+ -+ return 0; -+} -+ -+static int i965_reset_complete(struct drm_device *dev) -+{ -+ u8 gdrst; -+ pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); -+ return gdrst & 0x1; -+} -+ -+static int i965_do_reset(struct drm_device *dev, u8 flags) -+{ -+ u8 gdrst; -+ -+ /* -+ * Set the domains we want to reset (GRDOM/bits 2 and 3) as -+ * well as the reset bit (GR/bit 0). Setting the GR bit -+ * triggers the reset; when done, the hardware will clear it. -+ */ -+ pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); -+ pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1); -+ -+ return wait_for(i965_reset_complete(dev), 500); -+} -+ -+static int ironlake_do_reset(struct drm_device *dev, u8 flags) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR); -+ I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1); -+ return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500); - } - - /** -@@ -325,54 +420,39 @@ int i915_resume(struct drm_device *dev) - * - re-init interrupt state - * - re-init display - */ --int i965_reset(struct drm_device *dev, u8 flags) -+int i915_reset(struct drm_device *dev, u8 flags) - { - drm_i915_private_t *dev_priv = dev->dev_private; -- unsigned long timeout; -- u8 gdrst; - /* - * We really should only reset the display subsystem if we actually - * need to - */ - bool need_display = true; -+ int ret; - - mutex_lock(&dev->struct_mutex); - -- /* -- * Clear request list -- */ -- i915_gem_retire_requests(dev); -- -- if (need_display) -- i915_save_display(dev); -- -- if (IS_I965G(dev) || IS_G4X(dev)) { -- /* -- * Set the domains we want to reset, then the reset bit (bit 0). -- * Clear the reset bit after a while and wait for hardware status -- * bit (bit 1) to be set -- */ -- pci_read_config_byte(dev->pdev, GDRST, &gdrst); -- pci_write_config_byte(dev->pdev, GDRST, gdrst | flags | ((flags == GDRST_FULL) ? 0x1 : 0x0)); -- udelay(50); -- pci_write_config_byte(dev->pdev, GDRST, gdrst & 0xfe); -- -- /* ...we don't want to loop forever though, 500ms should be plenty */ -- timeout = jiffies + msecs_to_jiffies(500); -- do { -- udelay(100); -- pci_read_config_byte(dev->pdev, GDRST, &gdrst); -- } while ((gdrst & 0x1) && time_after(timeout, jiffies)); -- -- if (gdrst & 0x1) { -- WARN(true, "i915: Failed to reset chip\n"); -- mutex_unlock(&dev->struct_mutex); -- return -EIO; -- } -- } else { -- DRM_ERROR("Error occurred. Don't know how to reset this chip.\n"); -+ i915_gem_reset(dev); -+ -+ ret = -ENODEV; -+ if (get_seconds() - dev_priv->last_gpu_reset < 5) { -+ DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); -+ } else switch (INTEL_INFO(dev)->gen) { -+ case 5: -+ ret = ironlake_do_reset(dev, flags); -+ break; -+ case 4: -+ ret = i965_do_reset(dev, flags); -+ break; -+ case 2: -+ ret = i8xx_do_reset(dev, flags); -+ break; -+ } -+ dev_priv->last_gpu_reset = get_seconds(); -+ if (ret) { -+ DRM_ERROR("Failed to reset chip.\n"); - mutex_unlock(&dev->struct_mutex); -- return -ENODEV; -+ return ret; - } - - /* Ok, now get things going again... */ -@@ -400,13 +480,19 @@ int i965_reset(struct drm_device *dev, u8 flags) - mutex_lock(&dev->struct_mutex); - } - -+ mutex_unlock(&dev->struct_mutex); -+ - /* -- * Display needs restore too... -+ * Perform a full modeset as on later generations, e.g. Ironlake, we may -+ * need to retrain the display link and cannot just restore the register -+ * values. - */ -- if (need_display) -- i915_restore_display(dev); -+ if (need_display) { -+ mutex_lock(&dev->mode_config.mutex); -+ drm_helper_resume_force_mode(dev); -+ mutex_unlock(&dev->mode_config.mutex); -+ } - -- mutex_unlock(&dev->struct_mutex); - return 0; - } - -@@ -422,6 +508,8 @@ i915_pci_remove(struct pci_dev *pdev) - { - struct drm_device *dev = pci_get_drvdata(pdev); - -+ pci_disable_device(pdev); /* core did previous enable */ -+ - drm_put_dev(dev); - } - -@@ -524,8 +612,6 @@ static struct drm_driver driver = { - .irq_uninstall = i915_driver_irq_uninstall, - .irq_handler = i915_driver_irq_handler, - .reclaim_buffers = drm_core_reclaim_buffers, -- .get_map_ofs = drm_core_get_map_ofs, -- .get_reg_ofs = drm_core_get_reg_ofs, - .master_create = i915_master_create, - .master_destroy = i915_master_destroy, - #if defined(CONFIG_DEBUG_FS) -@@ -548,6 +634,7 @@ static struct drm_driver driver = { - #ifdef CONFIG_COMPAT - .compat_ioctl = i915_compat_ioctl, - #endif -+ .llseek = noop_llseek, - }, - - .pci_driver = { -diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h -index af4a263..90414ae 100644 ---- a/drivers/gpu/drm/i915/i915_drv.h -+++ b/drivers/gpu/drm/i915/i915_drv.h -@@ -34,6 +34,8 @@ - #include "intel_bios.h" - #include "intel_ringbuffer.h" - #include -+#include -+#include - - /* General customization: - */ -@@ -73,11 +75,9 @@ enum plane { - #define DRIVER_PATCHLEVEL 0 - - #define WATCH_COHERENCY 0 --#define WATCH_BUF 0 - #define WATCH_EXEC 0 --#define WATCH_LRU 0 - #define WATCH_RELOC 0 --#define WATCH_INACTIVE 0 -+#define WATCH_LISTS 0 - #define WATCH_PWRITE 0 - - #define I915_GEM_PHYS_CURSOR_0 1 -@@ -110,8 +110,9 @@ struct intel_opregion { - struct opregion_acpi *acpi; - struct opregion_swsci *swsci; - struct opregion_asle *asle; -- int enabled; -+ void *vbt; - }; -+#define OPREGION_SIZE (8*1024) - - struct intel_overlay; - struct intel_overlay_error_state; -@@ -125,13 +126,16 @@ struct drm_i915_master_private { - struct drm_i915_fence_reg { - struct drm_gem_object *obj; - struct list_head lru_list; -+ bool gpu; - }; - - struct sdvo_device_mapping { -+ u8 initialized; - u8 dvo_port; - u8 slave_addr; - u8 dvo_wiring; -- u8 initialized; -+ u8 i2c_pin; -+ u8 i2c_speed; - u8 ddc_pin; - }; - -@@ -193,28 +197,29 @@ struct drm_i915_display_funcs { - struct intel_device_info { - u8 gen; - u8 is_mobile : 1; -- u8 is_i8xx : 1; - u8 is_i85x : 1; - u8 is_i915g : 1; -- u8 is_i9xx : 1; - u8 is_i945gm : 1; -- u8 is_i965g : 1; -- u8 is_i965gm : 1; - u8 is_g33 : 1; - u8 need_gfx_hws : 1; - u8 is_g4x : 1; - u8 is_pineview : 1; - u8 is_broadwater : 1; - u8 is_crestline : 1; -- u8 is_ironlake : 1; - u8 has_fbc : 1; - u8 has_rc6 : 1; - u8 has_pipe_cxsr : 1; - u8 has_hotplug : 1; - u8 cursor_needs_physical : 1; -+ u8 has_overlay : 1; -+ u8 overlay_needs_physical : 1; -+ u8 supports_tv : 1; -+ u8 has_bsd_ring : 1; -+ u8 has_blt_ring : 1; - }; - - enum no_fbc_reason { -+ FBC_NO_OUTPUT, /* no outputs enabled to compress */ - FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ - FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */ - FBC_MODE_TOO_LARGE, /* mode too large for compression */ -@@ -241,9 +246,16 @@ typedef struct drm_i915_private { - - void __iomem *regs; - -+ struct intel_gmbus { -+ struct i2c_adapter adapter; -+ struct i2c_adapter *force_bit; -+ u32 reg0; -+ } *gmbus; -+ - struct pci_dev *bridge_dev; - struct intel_ring_buffer render_ring; - struct intel_ring_buffer bsd_ring; -+ struct intel_ring_buffer blt_ring; - uint32_t next_seqno; - - drm_dma_handle_t *status_page_dmah; -@@ -263,6 +275,9 @@ typedef struct drm_i915_private { - int front_offset; - int current_page; - int page_flipping; -+#define I915_DEBUG_READ (1<<0) -+#define I915_DEBUG_WRITE (1<<1) -+ unsigned long debug_flags; - - wait_queue_head_t irq_queue; - atomic_t irq_received; -@@ -289,24 +304,21 @@ typedef struct drm_i915_private { - unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; - int vblank_pipe; - int num_pipe; -- u32 flush_rings; --#define FLUSH_RENDER_RING 0x1 --#define FLUSH_BSD_RING 0x2 - - /* For hangcheck timer */ --#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */ -+#define DRM_I915_HANGCHECK_PERIOD 250 /* in ms */ - struct timer_list hangcheck_timer; - int hangcheck_count; - uint32_t last_acthd; - uint32_t last_instdone; - uint32_t last_instdone1; - -- struct drm_mm vram; -- - unsigned long cfb_size; - unsigned long cfb_pitch; -+ unsigned long cfb_offset; - int cfb_fence; - int cfb_plane; -+ int cfb_y; - - int irq_enabled; - -@@ -316,8 +328,7 @@ typedef struct drm_i915_private { - struct intel_overlay *overlay; - - /* LVDS info */ -- int backlight_duty_cycle; /* restore backlight to this value */ -- bool panel_wants_dither; -+ int backlight_level; /* restore backlight to this value */ - struct drm_display_mode *panel_fixed_mode; - struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ - struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ -@@ -328,13 +339,23 @@ typedef struct drm_i915_private { - unsigned int lvds_vbt:1; - unsigned int int_crt_support:1; - unsigned int lvds_use_ssc:1; -- unsigned int edp_support:1; - int lvds_ssc_freq; -- int edp_bpp; -+ struct { -+ int rate; -+ int lanes; -+ int preemphasis; -+ int vswing; -+ -+ bool initialized; -+ bool support; -+ int bpp; -+ struct edp_power_seq pps; -+ } edp; -+ bool no_aux_handshake; - - struct notifier_block lid_notifier; - -- int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */ -+ int crt_ddc_pin; - struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ - int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ - int num_fence_regs; /* 8 on pre-965, 16 otherwise */ -@@ -344,6 +365,7 @@ typedef struct drm_i915_private { - spinlock_t error_lock; - struct drm_i915_error_state *first_error; - struct work_struct error_work; -+ struct completion error_completion; - struct workqueue_struct *wq; - - /* Display functions */ -@@ -507,6 +529,11 @@ typedef struct drm_i915_private { - u32 saveMCHBAR_RENDER_STANDBY; - - struct { -+ /** Bridge to intel-gtt-ko */ -+ struct intel_gtt *gtt; -+ /** Memory allocator for GTT stolen memory */ -+ struct drm_mm vram; -+ /** Memory allocator for GTT */ - struct drm_mm gtt_space; - - struct io_mapping *gtt_mapping; -@@ -521,7 +548,16 @@ typedef struct drm_i915_private { - */ - struct list_head shrink_list; - -- spinlock_t active_list_lock; -+ /** -+ * List of objects currently involved in rendering. -+ * -+ * Includes buffers having the contents of their GPU caches -+ * flushed, not necessarily primitives. last_rendering_seqno -+ * represents when the rendering involved will be completed. -+ * -+ * A reference is held on the buffer while on this list. -+ */ -+ struct list_head active_list; - - /** - * List of objects which are not in the ringbuffer but which -@@ -535,15 +571,6 @@ typedef struct drm_i915_private { - struct list_head flushing_list; - - /** -- * List of objects currently pending a GPU write flush. -- * -- * All elements on this list will belong to either the -- * active_list or flushing_list, last_rendering_seqno can -- * be used to differentiate between the two elements. -- */ -- struct list_head gpu_write_list; -- -- /** - * LRU list of objects which are not in the ringbuffer and - * are ready to unbind, but are still in the GTT. - * -@@ -555,6 +582,12 @@ typedef struct drm_i915_private { - */ - struct list_head inactive_list; - -+ /** -+ * LRU list of objects which are not in the ringbuffer but -+ * are still pinned in the GTT. -+ */ -+ struct list_head pinned_list; -+ - /** LRU list of objects with fence regs on them. */ - struct list_head fence_list; - -@@ -611,6 +644,17 @@ typedef struct drm_i915_private { - - /* storage for physical objects */ - struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; -+ -+ uint32_t flush_rings; -+ -+ /* accounting, useful for userland debugging */ -+ size_t object_memory; -+ size_t pin_memory; -+ size_t gtt_memory; -+ size_t gtt_total; -+ u32 object_count; -+ u32 pin_count; -+ u32 gtt_count; - } mm; - struct sdvo_device_mapping sdvo_mappings[2]; - /* indicate whether the LVDS_BORDER should be enabled or not */ -@@ -626,8 +670,6 @@ typedef struct drm_i915_private { - /* Reclocking support */ - bool render_reclock_avail; - bool lvds_downclock_avail; -- /* indicate whether the LVDS EDID is OK */ -- bool lvds_edid_good; - /* indicates the reduced downclock for LVDS*/ - int lvds_downclock; - struct work_struct idle_work; -@@ -661,6 +703,8 @@ typedef struct drm_i915_private { - struct drm_mm_node *compressed_fb; - struct drm_mm_node *compressed_llb; - -+ unsigned long last_gpu_reset; -+ - /* list of fbdev register on this device */ - struct intel_fbdev *fbdev; - } drm_i915_private_t; -@@ -673,7 +717,8 @@ struct drm_i915_gem_object { - struct drm_mm_node *gtt_space; - - /** This object's place on the active/flushing/inactive lists */ -- struct list_head list; -+ struct list_head ring_list; -+ struct list_head mm_list; - /** This object's place on GPU write list */ - struct list_head gpu_write_list; - /** This object's place on eviction list */ -@@ -816,12 +861,14 @@ struct drm_i915_gem_request { - /** global list entry for this request */ - struct list_head list; - -+ struct drm_i915_file_private *file_priv; - /** file_priv list entry for this request */ - struct list_head client_list; - }; - - struct drm_i915_file_private { - struct { -+ struct spinlock lock; - struct list_head request_list; - } mm; - }; -@@ -862,7 +909,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, - extern int i915_emit_box(struct drm_device *dev, - struct drm_clip_rect *boxes, - int i, int DR1, int DR4); --extern int i965_reset(struct drm_device *dev, u8 flags); -+extern int i915_reset(struct drm_device *dev, u8 flags); - extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); - extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); - extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); -@@ -871,7 +918,6 @@ extern void i915_update_gfx_val(struct drm_i915_private *dev_priv); - - /* i915_irq.c */ - void i915_hangcheck_elapsed(unsigned long data); --void i915_destroy_error_state(struct drm_device *dev); - extern int i915_irq_emit(struct drm_device *dev, void *data, - struct drm_file *file_priv); - extern int i915_irq_wait(struct drm_device *dev, void *data, -@@ -908,6 +954,12 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); - - void intel_enable_asle (struct drm_device *dev); - -+#ifdef CONFIG_DEBUG_FS -+extern void i915_destroy_error_state(struct drm_device *dev); -+#else -+#define i915_destroy_error_state(x) -+#endif -+ - - /* i915_mem.c */ - extern int i915_mem_alloc(struct drm_device *dev, void *data, -@@ -922,6 +974,7 @@ extern void i915_mem_takedown(struct mem_block **heap); - extern void i915_mem_release(struct drm_device * dev, - struct drm_file *file_priv, struct mem_block *heap); - /* i915_gem.c */ -+int i915_gem_check_is_wedged(struct drm_device *dev); - int i915_gem_init_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - int i915_gem_create_ioctl(struct drm_device *dev, void *data, -@@ -972,13 +1025,22 @@ void i915_gem_object_unpin(struct drm_gem_object *obj); - int i915_gem_object_unbind(struct drm_gem_object *obj); - void i915_gem_release_mmap(struct drm_gem_object *obj); - void i915_gem_lastclose(struct drm_device *dev); --uint32_t i915_get_gem_seqno(struct drm_device *dev, -- struct intel_ring_buffer *ring); --bool i915_seqno_passed(uint32_t seq1, uint32_t seq2); --int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); --int i915_gem_object_put_fence_reg(struct drm_gem_object *obj); -+ -+/** -+ * Returns true if seq1 is later than seq2. -+ */ -+static inline bool -+i915_seqno_passed(uint32_t seq1, uint32_t seq2) -+{ -+ return (int32_t)(seq1 - seq2) >= 0; -+} -+ -+int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, -+ bool interruptible); -+int i915_gem_object_put_fence_reg(struct drm_gem_object *obj, -+ bool interruptible); - void i915_gem_retire_requests(struct drm_device *dev); --void i915_gem_retire_work_handler(struct work_struct *work); -+void i915_gem_reset(struct drm_device *dev); - void i915_gem_clflush_object(struct drm_gem_object *obj); - int i915_gem_object_set_domain(struct drm_gem_object *obj, - uint32_t read_domains, -@@ -990,16 +1052,18 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start, - int i915_gpu_idle(struct drm_device *dev); - int i915_gem_idle(struct drm_device *dev); - uint32_t i915_add_request(struct drm_device *dev, -- struct drm_file *file_priv, -- uint32_t flush_domains, -- struct intel_ring_buffer *ring); -+ struct drm_file *file_priv, -+ struct drm_i915_gem_request *request, -+ struct intel_ring_buffer *ring); - int i915_do_wait_request(struct drm_device *dev, -- uint32_t seqno, int interruptible, -- struct intel_ring_buffer *ring); -+ uint32_t seqno, -+ bool interruptible, -+ struct intel_ring_buffer *ring); - int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); - int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, - int write); --int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj); -+int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, -+ bool pipelined); - int i915_gem_attach_phys_object(struct drm_device *dev, - struct drm_gem_object *obj, - int id, -@@ -1007,10 +1071,7 @@ int i915_gem_attach_phys_object(struct drm_device *dev, - void i915_gem_detach_phys_object(struct drm_device *dev, - struct drm_gem_object *obj); - void i915_gem_free_all_phys_object(struct drm_device *dev); --int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); --void i915_gem_object_put_pages(struct drm_gem_object *obj); - void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); --int i915_gem_object_flush_write_domain(struct drm_gem_object *obj); - - void i915_gem_shrinker_init(void); - void i915_gem_shrinker_exit(void); -@@ -1032,15 +1093,14 @@ bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, - /* i915_gem_debug.c */ - void i915_gem_dump_object(struct drm_gem_object *obj, int len, - const char *where, uint32_t mark); --#if WATCH_INACTIVE --void i915_verify_inactive(struct drm_device *dev, char *file, int line); -+#if WATCH_LISTS -+int i915_verify_lists(struct drm_device *dev); - #else --#define i915_verify_inactive(dev, file, line) -+#define i915_verify_lists(dev) 0 - #endif - void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle); - void i915_gem_dump_object(struct drm_gem_object *obj, int len, - const char *where, uint32_t mark); --void i915_dump_lru(struct drm_device *dev, const char *where); - - /* i915_debugfs.c */ - int i915_debugfs_init(struct drm_minor *minor); -@@ -1054,21 +1114,42 @@ extern int i915_restore_state(struct drm_device *dev); - extern int i915_save_state(struct drm_device *dev); - extern int i915_restore_state(struct drm_device *dev); - -+/* intel_i2c.c */ -+extern int intel_setup_gmbus(struct drm_device *dev); -+extern void intel_teardown_gmbus(struct drm_device *dev); -+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 inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) -+{ -+ return container_of(adapter, struct intel_gmbus, adapter)->force_bit; -+} -+extern void intel_i2c_reset(struct drm_device *dev); -+ -+/* intel_opregion.c */ -+extern int intel_opregion_setup(struct drm_device *dev); - #ifdef CONFIG_ACPI --/* i915_opregion.c */ --extern int intel_opregion_init(struct drm_device *dev, int resume); --extern void intel_opregion_free(struct drm_device *dev, int suspend); --extern void opregion_asle_intr(struct drm_device *dev); --extern void ironlake_opregion_gse_intr(struct drm_device *dev); --extern void opregion_enable_asle(struct drm_device *dev); -+extern void intel_opregion_init(struct drm_device *dev); -+extern void intel_opregion_fini(struct drm_device *dev); -+extern void intel_opregion_asle_intr(struct drm_device *dev); -+extern void intel_opregion_gse_intr(struct drm_device *dev); -+extern void intel_opregion_enable_asle(struct drm_device *dev); - #else --static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } --static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } --static inline void opregion_asle_intr(struct drm_device *dev) { return; } --static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; } --static inline void opregion_enable_asle(struct drm_device *dev) { return; } -+static inline void intel_opregion_init(struct drm_device *dev) { return; } -+static inline void intel_opregion_fini(struct drm_device *dev) { return; } -+static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; } -+static inline void intel_opregion_gse_intr(struct drm_device *dev) { return; } -+static inline void intel_opregion_enable_asle(struct drm_device *dev) { return; } - #endif - -+/* intel_acpi.c */ -+#ifdef CONFIG_ACPI -+extern void intel_register_dsm_handler(void); -+extern void intel_unregister_dsm_handler(void); -+#else -+static inline void intel_register_dsm_handler(void) { return; } -+static inline void intel_unregister_dsm_handler(void) { return; } -+#endif /* CONFIG_ACPI */ -+ - /* modesetting */ - extern void intel_modeset_init(struct drm_device *dev); - extern void intel_modeset_cleanup(struct drm_device *dev); -@@ -1084,8 +1165,10 @@ extern void intel_detect_pch (struct drm_device *dev); - extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); - - /* overlay */ -+#ifdef CONFIG_DEBUG_FS - extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); - extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); -+#endif - - /** - * Lock test for when it's just for synchronization of ring access. -@@ -1099,8 +1182,26 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove - LOCK_TEST_WITH_RETURN(dev, file_priv); \ - } while (0) - --#define I915_READ(reg) readl(dev_priv->regs + (reg)) --#define I915_WRITE(reg, val) writel(val, dev_priv->regs + (reg)) -+static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg) -+{ -+ u32 val; -+ -+ val = readl(dev_priv->regs + reg); -+ if (dev_priv->debug_flags & I915_DEBUG_READ) -+ printk(KERN_ERR "read 0x%08x from 0x%08x\n", val, reg); -+ return val; -+} -+ -+static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg, -+ u32 val) -+{ -+ writel(val, dev_priv->regs + reg); -+ if (dev_priv->debug_flags & I915_DEBUG_WRITE) -+ printk(KERN_ERR "wrote 0x%08x to 0x%08x\n", val, reg); -+} -+ -+#define I915_READ(reg) i915_read(dev_priv, (reg)) -+#define I915_WRITE(reg, val) i915_write(dev_priv, (reg), (val)) - #define I915_READ16(reg) readw(dev_priv->regs + (reg)) - #define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg)) - #define I915_READ8(reg) readb(dev_priv->regs + (reg)) -@@ -1110,6 +1211,11 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove - #define POSTING_READ(reg) (void)I915_READ(reg) - #define POSTING_READ16(reg) (void)I915_READ16(reg) - -+#define I915_DEBUG_ENABLE_IO() (dev_priv->debug_flags |= I915_DEBUG_READ | \ -+ I915_DEBUG_WRITE) -+#define I915_DEBUG_DISABLE_IO() (dev_priv->debug_flags &= ~(I915_DEBUG_READ | \ -+ I915_DEBUG_WRITE)) -+ - #define I915_VERBOSE 0 - - #define BEGIN_LP_RING(n) do { \ -@@ -1166,8 +1272,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove - #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) - #define IS_I945G(dev) ((dev)->pci_device == 0x2772) - #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) --#define IS_I965G(dev) (INTEL_INFO(dev)->is_i965g) --#define IS_I965GM(dev) (INTEL_INFO(dev)->is_i965gm) - #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) - #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) - #define IS_GM45(dev) ((dev)->pci_device == 0x2A42) -@@ -1178,8 +1282,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove - #define IS_G33(dev) (INTEL_INFO(dev)->is_g33) - #define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) - #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) --#define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) --#define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx) - #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) - - #define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) -@@ -1188,36 +1290,38 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove - #define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) - #define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) - --#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev)) -+#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) -+#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) - #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) - -+#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) -+#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) -+ - /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte - * rows, which changed the alignment requirements and fence programming. - */ --#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ -+#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \ - IS_I915GM(dev))) --#define SUPPORTS_DIGITAL_OUTPUTS(dev) (IS_I9XX(dev) && !IS_PINEVIEW(dev)) --#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) --#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) -+#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) -+#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev)) -+#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_GEN5(dev)) - #define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) --#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \ -- !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev) && \ -- !IS_GEN6(dev)) -+#define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) - #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) - /* dsparb controlled by hw only */ - #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) - --#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev)) -+#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2) - #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) - #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) - #define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) - --#define HAS_PCH_SPLIT(dev) (IS_IRONLAKE(dev) || \ -- IS_GEN6(dev)) --#define HAS_PIPE_CONTROL(dev) (IS_IRONLAKE(dev) || IS_GEN6(dev)) -+#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev)) -+#define HAS_PIPE_CONTROL(dev) (IS_GEN5(dev) || IS_GEN6(dev)) - - #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) - #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) -+#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) - - #define PRIMARY_RINGBUFFER_SIZE (128*1024) - -diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c -index 90b1d67..6da2c6d 100644 ---- a/drivers/gpu/drm/i915/i915_gem.c -+++ b/drivers/gpu/drm/i915/i915_gem.c -@@ -37,7 +37,9 @@ - #include - - static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); --static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); -+ -+static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, -+ bool pipelined); - static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); - static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); - static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, -@@ -46,7 +48,8 @@ static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, - uint64_t offset, - uint64_t size); - static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); --static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); -+static int i915_gem_object_wait_rendering(struct drm_gem_object *obj, -+ bool interruptible); - static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, - unsigned alignment); - static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); -@@ -55,9 +58,111 @@ static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *o - struct drm_file *file_priv); - static void i915_gem_free_object_tail(struct drm_gem_object *obj); - -+static int -+i915_gem_object_get_pages(struct drm_gem_object *obj, -+ gfp_t gfpmask); -+ -+static void -+i915_gem_object_put_pages(struct drm_gem_object *obj); -+ - static LIST_HEAD(shrink_list); - static DEFINE_SPINLOCK(shrink_list_lock); - -+/* some bookkeeping */ -+static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, -+ size_t size) -+{ -+ dev_priv->mm.object_count++; -+ dev_priv->mm.object_memory += size; -+} -+ -+static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, -+ size_t size) -+{ -+ dev_priv->mm.object_count--; -+ dev_priv->mm.object_memory -= size; -+} -+ -+static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv, -+ size_t size) -+{ -+ dev_priv->mm.gtt_count++; -+ dev_priv->mm.gtt_memory += size; -+} -+ -+static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv, -+ size_t size) -+{ -+ dev_priv->mm.gtt_count--; -+ dev_priv->mm.gtt_memory -= size; -+} -+ -+static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv, -+ size_t size) -+{ -+ dev_priv->mm.pin_count++; -+ dev_priv->mm.pin_memory += size; -+} -+ -+static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv, -+ size_t size) -+{ -+ dev_priv->mm.pin_count--; -+ dev_priv->mm.pin_memory -= size; -+} -+ -+int -+i915_gem_check_is_wedged(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct completion *x = &dev_priv->error_completion; -+ unsigned long flags; -+ int ret; -+ -+ if (!atomic_read(&dev_priv->mm.wedged)) -+ return 0; -+ -+ ret = wait_for_completion_interruptible(x); -+ if (ret) -+ return ret; -+ -+ /* Success, we reset the GPU! */ -+ if (!atomic_read(&dev_priv->mm.wedged)) -+ return 0; -+ -+ /* GPU is hung, bump the completion count to account for -+ * the token we just consumed so that we never hit zero and -+ * end up waiting upon a subsequent completion event that -+ * will never happen. -+ */ -+ spin_lock_irqsave(&x->wait.lock, flags); -+ x->done++; -+ spin_unlock_irqrestore(&x->wait.lock, flags); -+ return -EIO; -+} -+ -+static int i915_mutex_lock_interruptible(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ int ret; -+ -+ ret = i915_gem_check_is_wedged(dev); -+ if (ret) -+ return ret; -+ -+ ret = mutex_lock_interruptible(&dev->struct_mutex); -+ if (ret) -+ return ret; -+ -+ if (atomic_read(&dev_priv->mm.wedged)) { -+ mutex_unlock(&dev->struct_mutex); -+ return -EAGAIN; -+ } -+ -+ WARN_ON(i915_verify_lists(dev)); -+ return 0; -+} -+ - static inline bool - i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) - { -@@ -66,7 +171,8 @@ i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) - obj_priv->pin_count == 0; - } - --int i915_gem_do_init(struct drm_device *dev, unsigned long start, -+int i915_gem_do_init(struct drm_device *dev, -+ unsigned long start, - unsigned long end) - { - drm_i915_private_t *dev_priv = dev->dev_private; -@@ -80,7 +186,7 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start, - drm_mm_init(&dev_priv->mm.gtt_space, start, - end - start); - -- dev->gtt_total = (uint32_t) (end - start); -+ dev_priv->mm.gtt_total = end - start; - - return 0; - } -@@ -103,14 +209,16 @@ int - i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_get_aperture *args = data; - - if (!(dev->driver->driver_features & DRIVER_GEM)) - return -ENODEV; - -- args->aper_size = dev->gtt_total; -- args->aper_available_size = (args->aper_size - -- atomic_read(&dev->pin_memory)); -+ mutex_lock(&dev->struct_mutex); -+ args->aper_size = dev_priv->mm.gtt_total; -+ args->aper_available_size = args->aper_size - dev_priv->mm.pin_memory; -+ mutex_unlock(&dev->struct_mutex); - - return 0; - } -@@ -136,12 +244,17 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, - return -ENOMEM; - - ret = drm_gem_handle_create(file_priv, obj, &handle); -- /* drop reference from allocate - handle holds it now */ -- drm_gem_object_unreference_unlocked(obj); - if (ret) { -+ drm_gem_object_release(obj); -+ i915_gem_info_remove_obj(dev->dev_private, obj->size); -+ kfree(obj); - return ret; - } - -+ /* drop reference from allocate - handle holds it now */ -+ drm_gem_object_unreference(obj); -+ trace_i915_gem_object_create(obj); -+ - args->handle = handle; - return 0; - } -@@ -152,19 +265,14 @@ fast_shmem_read(struct page **pages, - char __user *data, - int length) - { -- char __iomem *vaddr; -- int unwritten; -+ char *vaddr; -+ int ret; - - vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); -- if (vaddr == NULL) -- return -ENOMEM; -- unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length); -+ ret = __copy_to_user_inatomic(data, vaddr + page_offset, length); - kunmap_atomic(vaddr, KM_USER0); - -- if (unwritten) -- return -EFAULT; -- -- return 0; -+ return ret; - } - - static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj) -@@ -258,22 +366,10 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, - loff_t offset, page_base; - char __user *user_data; - int page_offset, page_length; -- int ret; - - user_data = (char __user *) (uintptr_t) args->data_ptr; - remain = args->size; - -- mutex_lock(&dev->struct_mutex); -- -- ret = i915_gem_object_get_pages(obj, 0); -- if (ret != 0) -- goto fail_unlock; -- -- ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, -- args->size); -- if (ret != 0) -- goto fail_put_pages; -- - obj_priv = to_intel_bo(obj); - offset = args->offset; - -@@ -290,23 +386,17 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, - if ((page_offset + remain) > PAGE_SIZE) - page_length = PAGE_SIZE - page_offset; - -- ret = fast_shmem_read(obj_priv->pages, -- page_base, page_offset, -- user_data, page_length); -- if (ret) -- goto fail_put_pages; -+ if (fast_shmem_read(obj_priv->pages, -+ page_base, page_offset, -+ user_data, page_length)) -+ return -EFAULT; - - remain -= page_length; - user_data += page_length; - offset += page_length; - } - --fail_put_pages: -- i915_gem_object_put_pages(obj); --fail_unlock: -- mutex_unlock(&dev->struct_mutex); -- -- return ret; -+ return 0; - } - - static int -@@ -367,31 +457,28 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, - last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; - num_pages = last_data_page - first_data_page + 1; - -- user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); -+ user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); - if (user_pages == NULL) - return -ENOMEM; - -+ mutex_unlock(&dev->struct_mutex); - down_read(&mm->mmap_sem); - pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, - num_pages, 1, 0, user_pages, NULL); - up_read(&mm->mmap_sem); -+ mutex_lock(&dev->struct_mutex); - if (pinned_pages < num_pages) { - ret = -EFAULT; -- goto fail_put_user_pages; -+ goto out; - } - -- do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); -- -- mutex_lock(&dev->struct_mutex); -- -- ret = i915_gem_object_get_pages_or_evict(obj); -+ ret = i915_gem_object_set_cpu_read_domain_range(obj, -+ args->offset, -+ args->size); - if (ret) -- goto fail_unlock; -+ goto out; - -- ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, -- args->size); -- if (ret != 0) -- goto fail_put_pages; -+ do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); - - obj_priv = to_intel_bo(obj); - offset = args->offset; -@@ -436,11 +523,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, - offset += page_length; - } - --fail_put_pages: -- i915_gem_object_put_pages(obj); --fail_unlock: -- mutex_unlock(&dev->struct_mutex); --fail_put_user_pages: -+out: - for (i = 0; i < pinned_pages; i++) { - SetPageDirty(user_pages[i]); - page_cache_release(user_pages[i]); -@@ -462,37 +545,64 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, - struct drm_i915_gem_pread *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; -- int ret; -+ int ret = 0; -+ -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); -- if (obj == NULL) -- return -ENOENT; -+ if (obj == NULL) { -+ ret = -ENOENT; -+ goto unlock; -+ } - obj_priv = to_intel_bo(obj); - - /* Bounds check source. */ - if (args->offset > obj->size || args->size > obj->size - args->offset) { - ret = -EINVAL; -- goto err; -+ goto out; - } - -+ if (args->size == 0) -+ goto out; -+ - if (!access_ok(VERIFY_WRITE, - (char __user *)(uintptr_t)args->data_ptr, - args->size)) { - ret = -EFAULT; -- goto err; -+ goto out; - } - -- if (i915_gem_object_needs_bit17_swizzle(obj)) { -- ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); -- } else { -- ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv); -- if (ret != 0) -- ret = i915_gem_shmem_pread_slow(dev, obj, args, -- file_priv); -+ ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr, -+ args->size); -+ if (ret) { -+ ret = -EFAULT; -+ goto out; - } - --err: -- drm_gem_object_unreference_unlocked(obj); -+ ret = i915_gem_object_get_pages_or_evict(obj); -+ if (ret) -+ goto out; -+ -+ ret = i915_gem_object_set_cpu_read_domain_range(obj, -+ args->offset, -+ args->size); -+ if (ret) -+ goto out_put; -+ -+ ret = -EFAULT; -+ if (!i915_gem_object_needs_bit17_swizzle(obj)) -+ ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv); -+ if (ret == -EFAULT) -+ ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); -+ -+out_put: -+ i915_gem_object_put_pages(obj); -+out: -+ drm_gem_object_unreference(obj); -+unlock: -+ mutex_unlock(&dev->struct_mutex); - return ret; - } - -@@ -513,9 +623,7 @@ fast_user_write(struct io_mapping *mapping, - unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, - user_data, length); - io_mapping_unmap_atomic(vaddr_atomic, KM_USER0); -- if (unwritten) -- return -EFAULT; -- return 0; -+ return unwritten; - } - - /* Here's the write path which can sleep for -@@ -548,18 +656,14 @@ fast_shmem_write(struct page **pages, - char __user *data, - int length) - { -- char __iomem *vaddr; -- unsigned long unwritten; -+ char *vaddr; -+ int ret; - - vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); -- if (vaddr == NULL) -- return -ENOMEM; -- unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length); -+ ret = __copy_from_user_inatomic(vaddr + page_offset, data, length); - kunmap_atomic(vaddr, KM_USER0); - -- if (unwritten) -- return -EFAULT; -- return 0; -+ return ret; - } - - /** -@@ -577,22 +681,10 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, - loff_t offset, page_base; - char __user *user_data; - int page_offset, page_length; -- int ret; - - user_data = (char __user *) (uintptr_t) args->data_ptr; - remain = args->size; - -- -- mutex_lock(&dev->struct_mutex); -- ret = i915_gem_object_pin(obj, 0); -- if (ret) { -- mutex_unlock(&dev->struct_mutex); -- return ret; -- } -- ret = i915_gem_object_set_to_gtt_domain(obj, 1); -- if (ret) -- goto fail; -- - obj_priv = to_intel_bo(obj); - offset = obj_priv->gtt_offset + args->offset; - -@@ -609,26 +701,21 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, - if ((page_offset + remain) > PAGE_SIZE) - page_length = PAGE_SIZE - page_offset; - -- ret = fast_user_write (dev_priv->mm.gtt_mapping, page_base, -- page_offset, user_data, page_length); -- - /* If we get a fault while copying data, then (presumably) our - * source page isn't available. Return the error and we'll - * retry in the slow path. - */ -- if (ret) -- goto fail; -+ if (fast_user_write(dev_priv->mm.gtt_mapping, page_base, -+ page_offset, user_data, page_length)) -+ -+ return -EFAULT; - - remain -= page_length; - user_data += page_length; - offset += page_length; - } - --fail: -- i915_gem_object_unpin(obj); -- mutex_unlock(&dev->struct_mutex); -- -- return ret; -+ return 0; - } - - /** -@@ -665,27 +752,24 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, - last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; - num_pages = last_data_page - first_data_page + 1; - -- user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); -+ user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); - if (user_pages == NULL) - return -ENOMEM; - -+ mutex_unlock(&dev->struct_mutex); - down_read(&mm->mmap_sem); - pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, - num_pages, 0, 0, user_pages, NULL); - up_read(&mm->mmap_sem); -+ mutex_lock(&dev->struct_mutex); - if (pinned_pages < num_pages) { - ret = -EFAULT; - goto out_unpin_pages; - } - -- mutex_lock(&dev->struct_mutex); -- ret = i915_gem_object_pin(obj, 0); -- if (ret) -- goto out_unlock; -- - ret = i915_gem_object_set_to_gtt_domain(obj, 1); - if (ret) -- goto out_unpin_object; -+ goto out_unpin_pages; - - obj_priv = to_intel_bo(obj); - offset = obj_priv->gtt_offset + args->offset; -@@ -721,10 +805,6 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, - data_ptr += page_length; - } - --out_unpin_object: -- i915_gem_object_unpin(obj); --out_unlock: -- mutex_unlock(&dev->struct_mutex); - out_unpin_pages: - for (i = 0; i < pinned_pages; i++) - page_cache_release(user_pages[i]); -@@ -747,21 +827,10 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, - loff_t offset, page_base; - char __user *user_data; - int page_offset, page_length; -- int ret; - - user_data = (char __user *) (uintptr_t) args->data_ptr; - remain = args->size; - -- mutex_lock(&dev->struct_mutex); -- -- ret = i915_gem_object_get_pages(obj, 0); -- if (ret != 0) -- goto fail_unlock; -- -- ret = i915_gem_object_set_to_cpu_domain(obj, 1); -- if (ret != 0) -- goto fail_put_pages; -- - obj_priv = to_intel_bo(obj); - offset = args->offset; - obj_priv->dirty = 1; -@@ -779,23 +848,17 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, - if ((page_offset + remain) > PAGE_SIZE) - page_length = PAGE_SIZE - page_offset; - -- ret = fast_shmem_write(obj_priv->pages, -+ if (fast_shmem_write(obj_priv->pages, - page_base, page_offset, -- user_data, page_length); -- if (ret) -- goto fail_put_pages; -+ user_data, page_length)) -+ return -EFAULT; - - remain -= page_length; - user_data += page_length; - offset += page_length; - } - --fail_put_pages: -- i915_gem_object_put_pages(obj); --fail_unlock: -- mutex_unlock(&dev->struct_mutex); -- -- return ret; -+ return 0; - } - - /** -@@ -833,30 +896,26 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, - last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; - num_pages = last_data_page - first_data_page + 1; - -- user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); -+ user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); - if (user_pages == NULL) - return -ENOMEM; - -+ mutex_unlock(&dev->struct_mutex); - down_read(&mm->mmap_sem); - pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, - num_pages, 0, 0, user_pages, NULL); - up_read(&mm->mmap_sem); -+ mutex_lock(&dev->struct_mutex); - if (pinned_pages < num_pages) { - ret = -EFAULT; -- goto fail_put_user_pages; -+ goto out; - } - -- do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); -- -- mutex_lock(&dev->struct_mutex); -- -- ret = i915_gem_object_get_pages_or_evict(obj); -+ ret = i915_gem_object_set_to_cpu_domain(obj, 1); - if (ret) -- goto fail_unlock; -+ goto out; - -- ret = i915_gem_object_set_to_cpu_domain(obj, 1); -- if (ret != 0) -- goto fail_put_pages; -+ do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); - - obj_priv = to_intel_bo(obj); - offset = args->offset; -@@ -902,11 +961,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, - offset += page_length; - } - --fail_put_pages: -- i915_gem_object_put_pages(obj); --fail_unlock: -- mutex_unlock(&dev->struct_mutex); --fail_put_user_pages: -+out: - for (i = 0; i < pinned_pages; i++) - page_cache_release(user_pages[i]); - drm_free_large(user_pages); -@@ -921,29 +976,46 @@ fail_put_user_pages: - */ - int - i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, -- struct drm_file *file_priv) -+ struct drm_file *file) - { - struct drm_i915_gem_pwrite *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; - int ret = 0; - -- obj = drm_gem_object_lookup(dev, file_priv, args->handle); -- if (obj == NULL) -- return -ENOENT; -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; -+ -+ obj = drm_gem_object_lookup(dev, file, args->handle); -+ if (obj == NULL) { -+ ret = -ENOENT; -+ goto unlock; -+ } - obj_priv = to_intel_bo(obj); - -+ - /* Bounds check destination. */ - if (args->offset > obj->size || args->size > obj->size - args->offset) { - ret = -EINVAL; -- goto err; -+ goto out; - } - -+ if (args->size == 0) -+ goto out; -+ - if (!access_ok(VERIFY_READ, - (char __user *)(uintptr_t)args->data_ptr, - args->size)) { - ret = -EFAULT; -- goto err; -+ goto out; -+ } -+ -+ ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr, -+ args->size); -+ if (ret) { -+ ret = -EFAULT; -+ goto out; - } - - /* We can only do the GTT pwrite on untiled buffers, as otherwise -@@ -953,32 +1025,47 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, - * perspective, requiring manual detiling by the client. - */ - if (obj_priv->phys_obj) -- ret = i915_gem_phys_pwrite(dev, obj, args, file_priv); -+ ret = i915_gem_phys_pwrite(dev, obj, args, file); - else if (obj_priv->tiling_mode == I915_TILING_NONE && -- dev->gtt_total != 0 && -+ obj_priv->gtt_space && - obj->write_domain != I915_GEM_DOMAIN_CPU) { -- ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv); -- if (ret == -EFAULT) { -- ret = i915_gem_gtt_pwrite_slow(dev, obj, args, -- file_priv); -- } -- } else if (i915_gem_object_needs_bit17_swizzle(obj)) { -- ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file_priv); -+ ret = i915_gem_object_pin(obj, 0); -+ if (ret) -+ goto out; -+ -+ ret = i915_gem_object_set_to_gtt_domain(obj, 1); -+ if (ret) -+ goto out_unpin; -+ -+ ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file); -+ if (ret == -EFAULT) -+ ret = i915_gem_gtt_pwrite_slow(dev, obj, args, file); -+ -+out_unpin: -+ i915_gem_object_unpin(obj); - } else { -- ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file_priv); -- if (ret == -EFAULT) { -- ret = i915_gem_shmem_pwrite_slow(dev, obj, args, -- file_priv); -- } -- } -+ ret = i915_gem_object_get_pages_or_evict(obj); -+ if (ret) -+ goto out; - --#if WATCH_PWRITE -- if (ret) -- DRM_INFO("pwrite failed %d\n", ret); --#endif -+ ret = i915_gem_object_set_to_cpu_domain(obj, 1); -+ if (ret) -+ goto out_put; - --err: -- drm_gem_object_unreference_unlocked(obj); -+ ret = -EFAULT; -+ if (!i915_gem_object_needs_bit17_swizzle(obj)) -+ ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file); -+ if (ret == -EFAULT) -+ ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file); -+ -+out_put: -+ i915_gem_object_put_pages(obj); -+ } -+ -+out: -+ drm_gem_object_unreference(obj); -+unlock: -+ mutex_unlock(&dev->struct_mutex); - return ret; - } - -@@ -1014,19 +1101,19 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, - if (write_domain != 0 && read_domains != write_domain) - return -EINVAL; - -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; -+ - obj = drm_gem_object_lookup(dev, file_priv, args->handle); -- if (obj == NULL) -- return -ENOENT; -+ if (obj == NULL) { -+ ret = -ENOENT; -+ goto unlock; -+ } - obj_priv = to_intel_bo(obj); - -- mutex_lock(&dev->struct_mutex); -- - intel_mark_busy(dev, obj); - --#if WATCH_BUF -- DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n", -- obj, obj->size, read_domains, write_domain); --#endif - if (read_domains & I915_GEM_DOMAIN_GTT) { - ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); - -@@ -1050,12 +1137,12 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, - ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); - } - -- - /* Maintain LRU order of "inactive" objects */ - if (ret == 0 && i915_gem_object_is_inactive(obj_priv)) -- list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); -+ list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); - - drm_gem_object_unreference(obj); -+unlock: - mutex_unlock(&dev->struct_mutex); - return ret; - } -@@ -1069,30 +1156,27 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, - { - struct drm_i915_gem_sw_finish *args = data; - struct drm_gem_object *obj; -- struct drm_i915_gem_object *obj_priv; - int ret = 0; - - if (!(dev->driver->driver_features & DRIVER_GEM)) - return -ENODEV; - -- mutex_lock(&dev->struct_mutex); -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; -+ - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) { -- mutex_unlock(&dev->struct_mutex); -- return -ENOENT; -+ ret = -ENOENT; -+ goto unlock; - } - --#if WATCH_BUF -- DRM_INFO("%s: sw_finish %d (%p %zd)\n", -- __func__, args->handle, obj, obj->size); --#endif -- obj_priv = to_intel_bo(obj); -- - /* Pinned buffers may be scanout, so flush the cache */ -- if (obj_priv->pin_count) -+ if (to_intel_bo(obj)->pin_count) - i915_gem_object_flush_cpu_write_domain(obj); - - drm_gem_object_unreference(obj); -+unlock: - mutex_unlock(&dev->struct_mutex); - return ret; - } -@@ -1181,13 +1265,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) - - /* Need a new fence register? */ - if (obj_priv->tiling_mode != I915_TILING_NONE) { -- ret = i915_gem_object_get_fence_reg(obj); -+ ret = i915_gem_object_get_fence_reg(obj, true); - if (ret) - goto unlock; - } - - if (i915_gem_object_is_inactive(obj_priv)) -- list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); -+ list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); - - pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + - page_offset; -@@ -1246,7 +1330,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) - obj->size / PAGE_SIZE, 0, 0); - if (!list->file_offset_node) { - DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); -- ret = -ENOMEM; -+ ret = -ENOSPC; - goto out_free_list; - } - -@@ -1258,9 +1342,9 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) - } - - list->hash.key = list->file_offset_node->start; -- if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { -+ ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); -+ if (ret) { - DRM_ERROR("failed to add to map hash\n"); -- ret = -ENOMEM; - goto out_free_mm; - } - -@@ -1345,14 +1429,14 @@ i915_gem_get_gtt_alignment(struct drm_gem_object *obj) - * Minimum alignment is 4k (GTT page size), but might be greater - * if a fence register is needed for the object. - */ -- if (IS_I965G(dev) || obj_priv->tiling_mode == I915_TILING_NONE) -+ if (INTEL_INFO(dev)->gen >= 4 || obj_priv->tiling_mode == I915_TILING_NONE) - return 4096; - - /* - * Previous chips need to be aligned to the size of the smallest - * fence register that can contain the object. - */ -- if (IS_I9XX(dev)) -+ if (INTEL_INFO(dev)->gen == 3) - start = 1024*1024; - else - start = 512*1024; -@@ -1390,29 +1474,27 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, - if (!(dev->driver->driver_features & DRIVER_GEM)) - return -ENODEV; - -- obj = drm_gem_object_lookup(dev, file_priv, args->handle); -- if (obj == NULL) -- return -ENOENT; -- -- mutex_lock(&dev->struct_mutex); -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; - -+ obj = drm_gem_object_lookup(dev, file_priv, args->handle); -+ if (obj == NULL) { -+ ret = -ENOENT; -+ goto unlock; -+ } - obj_priv = to_intel_bo(obj); - - if (obj_priv->madv != I915_MADV_WILLNEED) { - DRM_ERROR("Attempting to mmap a purgeable buffer\n"); -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - -- - if (!obj_priv->mmap_offset) { - ret = i915_gem_create_mmap_offset(obj); -- if (ret) { -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- return ret; -- } -+ if (ret) -+ goto out; - } - - args->offset = obj_priv->mmap_offset; -@@ -1423,20 +1505,18 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, - */ - if (!obj_priv->agp_mem) { - ret = i915_gem_object_bind_to_gtt(obj, 0); -- if (ret) { -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- return ret; -- } -+ if (ret) -+ goto out; - } - -+out: - drm_gem_object_unreference(obj); -+unlock: - mutex_unlock(&dev->struct_mutex); -- -- return 0; -+ return ret; - } - --void -+static void - i915_gem_object_put_pages(struct drm_gem_object *obj) - { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -@@ -1470,13 +1550,25 @@ i915_gem_object_put_pages(struct drm_gem_object *obj) - obj_priv->pages = NULL; - } - -+static uint32_t -+i915_gem_next_request_seqno(struct drm_device *dev, -+ struct intel_ring_buffer *ring) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ -+ ring->outstanding_lazy_request = true; -+ return dev_priv->next_seqno; -+} -+ - static void --i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno, -+i915_gem_object_move_to_active(struct drm_gem_object *obj, - struct intel_ring_buffer *ring) - { - struct drm_device *dev = obj->dev; -- drm_i915_private_t *dev_priv = dev->dev_private; -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -+ uint32_t seqno = i915_gem_next_request_seqno(dev, ring); -+ - BUG_ON(ring == NULL); - obj_priv->ring = ring; - -@@ -1485,10 +1577,10 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno, - drm_gem_object_reference(obj); - obj_priv->active = 1; - } -+ - /* Move from whatever list we were on to the tail of execution. */ -- spin_lock(&dev_priv->mm.active_list_lock); -- list_move_tail(&obj_priv->list, &ring->active_list); -- spin_unlock(&dev_priv->mm.active_list_lock); -+ list_move_tail(&obj_priv->mm_list, &dev_priv->mm.active_list); -+ list_move_tail(&obj_priv->ring_list, &ring->active_list); - obj_priv->last_rendering_seqno = seqno; - } - -@@ -1500,7 +1592,8 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj) - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - - BUG_ON(!obj_priv->active); -- list_move_tail(&obj_priv->list, &dev_priv->mm.flushing_list); -+ list_move_tail(&obj_priv->mm_list, &dev_priv->mm.flushing_list); -+ list_del_init(&obj_priv->ring_list); - obj_priv->last_rendering_seqno = 0; - } - -@@ -1538,11 +1631,11 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - -- i915_verify_inactive(dev, __FILE__, __LINE__); - if (obj_priv->pin_count != 0) -- list_del_init(&obj_priv->list); -+ list_move_tail(&obj_priv->mm_list, &dev_priv->mm.pinned_list); - else -- list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); -+ list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); -+ list_del_init(&obj_priv->ring_list); - - BUG_ON(!list_empty(&obj_priv->gpu_write_list)); - -@@ -1552,30 +1645,28 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) - obj_priv->active = 0; - drm_gem_object_unreference(obj); - } -- i915_verify_inactive(dev, __FILE__, __LINE__); -+ WARN_ON(i915_verify_lists(dev)); - } - - static void - i915_gem_process_flushing_list(struct drm_device *dev, -- uint32_t flush_domains, uint32_t seqno, -+ uint32_t flush_domains, - struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv, *next; - - list_for_each_entry_safe(obj_priv, next, -- &dev_priv->mm.gpu_write_list, -+ &ring->gpu_write_list, - gpu_write_list) { - struct drm_gem_object *obj = &obj_priv->base; - -- if ((obj->write_domain & flush_domains) == -- obj->write_domain && -- obj_priv->ring->ring_flag == ring->ring_flag) { -+ if (obj->write_domain & flush_domains) { - uint32_t old_write_domain = obj->write_domain; - - obj->write_domain = 0; - list_del_init(&obj_priv->gpu_write_list); -- i915_gem_object_move_to_active(obj, seqno, ring); -+ i915_gem_object_move_to_active(obj, ring); - - /* update the fence lru list */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { -@@ -1593,23 +1684,27 @@ i915_gem_process_flushing_list(struct drm_device *dev, - } - - uint32_t --i915_add_request(struct drm_device *dev, struct drm_file *file_priv, -- uint32_t flush_domains, struct intel_ring_buffer *ring) -+i915_add_request(struct drm_device *dev, -+ struct drm_file *file, -+ struct drm_i915_gem_request *request, -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; -- struct drm_i915_file_private *i915_file_priv = NULL; -- struct drm_i915_gem_request *request; -+ struct drm_i915_file_private *file_priv = NULL; - uint32_t seqno; - int was_empty; - -- if (file_priv != NULL) -- i915_file_priv = file_priv->driver_priv; -+ if (file != NULL) -+ file_priv = file->driver_priv; - -- request = kzalloc(sizeof(*request), GFP_KERNEL); -- if (request == NULL) -- return 0; -+ if (request == NULL) { -+ request = kzalloc(sizeof(*request), GFP_KERNEL); -+ if (request == NULL) -+ return 0; -+ } - -- seqno = ring->add_request(dev, ring, file_priv, flush_domains); -+ seqno = ring->add_request(dev, ring, 0); -+ ring->outstanding_lazy_request = false; - - request->seqno = seqno; - request->ring = ring; -@@ -1617,23 +1712,20 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, - was_empty = list_empty(&ring->request_list); - list_add_tail(&request->list, &ring->request_list); - -- if (i915_file_priv) { -+ if (file_priv) { -+ spin_lock(&file_priv->mm.lock); -+ request->file_priv = file_priv; - list_add_tail(&request->client_list, -- &i915_file_priv->mm.request_list); -- } else { -- INIT_LIST_HEAD(&request->client_list); -+ &file_priv->mm.request_list); -+ spin_unlock(&file_priv->mm.lock); - } - -- /* Associate any objects on the flushing list matching the write -- * domain we're flushing with our flush. -- */ -- if (flush_domains != 0) -- i915_gem_process_flushing_list(dev, flush_domains, seqno, ring); -- - if (!dev_priv->mm.suspended) { -- mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); -+ mod_timer(&dev_priv->hangcheck_timer, -+ jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); - if (was_empty) -- queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); -+ queue_delayed_work(dev_priv->wq, -+ &dev_priv->mm.retire_work, HZ); - } - return seqno; - } -@@ -1644,91 +1736,105 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, - * Ensures that all commands in the ring are finished - * before signalling the CPU - */ --static uint32_t -+static void - i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) - { - uint32_t flush_domains = 0; - - /* The sampler always gets flushed on i965 (sigh) */ -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - flush_domains |= I915_GEM_DOMAIN_SAMPLER; - - ring->flush(dev, ring, - I915_GEM_DOMAIN_COMMAND, flush_domains); -- return flush_domains; - } - --/** -- * Moves buffers associated only with the given active seqno from the active -- * to inactive list, potentially freeing them. -- */ --static void --i915_gem_retire_request(struct drm_device *dev, -- struct drm_i915_gem_request *request) -+static inline void -+i915_gem_request_remove_from_client(struct drm_i915_gem_request *request) - { -- drm_i915_private_t *dev_priv = dev->dev_private; -+ struct drm_i915_file_private *file_priv = request->file_priv; - -- trace_i915_gem_request_retire(dev, request->seqno); -+ if (!file_priv) -+ return; - -- /* Move any buffers on the active list that are no longer referenced -- * by the ringbuffer to the flushing/inactive lists as appropriate. -- */ -- spin_lock(&dev_priv->mm.active_list_lock); -- while (!list_empty(&request->ring->active_list)) { -- struct drm_gem_object *obj; -- struct drm_i915_gem_object *obj_priv; -+ spin_lock(&file_priv->mm.lock); -+ list_del(&request->client_list); -+ request->file_priv = NULL; -+ spin_unlock(&file_priv->mm.lock); -+} - -- obj_priv = list_first_entry(&request->ring->active_list, -- struct drm_i915_gem_object, -- list); -- obj = &obj_priv->base; -+static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, -+ struct intel_ring_buffer *ring) -+{ -+ while (!list_empty(&ring->request_list)) { -+ struct drm_i915_gem_request *request; - -- /* If the seqno being retired doesn't match the oldest in the -- * list, then the oldest in the list must still be newer than -- * this seqno. -- */ -- if (obj_priv->last_rendering_seqno != request->seqno) -- goto out; -+ request = list_first_entry(&ring->request_list, -+ struct drm_i915_gem_request, -+ list); - --#if WATCH_LRU -- DRM_INFO("%s: retire %d moves to inactive list %p\n", -- __func__, request->seqno, obj); --#endif -+ list_del(&request->list); -+ i915_gem_request_remove_from_client(request); -+ kfree(request); -+ } - -- if (obj->write_domain != 0) -- i915_gem_object_move_to_flushing(obj); -- else { -- /* Take a reference on the object so it won't be -- * freed while the spinlock is held. The list -- * protection for this spinlock is safe when breaking -- * the lock like this since the next thing we do -- * is just get the head of the list again. -- */ -- drm_gem_object_reference(obj); -- i915_gem_object_move_to_inactive(obj); -- spin_unlock(&dev_priv->mm.active_list_lock); -- drm_gem_object_unreference(obj); -- spin_lock(&dev_priv->mm.active_list_lock); -- } -+ while (!list_empty(&ring->active_list)) { -+ struct drm_i915_gem_object *obj_priv; -+ -+ obj_priv = list_first_entry(&ring->active_list, -+ struct drm_i915_gem_object, -+ ring_list); -+ -+ obj_priv->base.write_domain = 0; -+ list_del_init(&obj_priv->gpu_write_list); -+ i915_gem_object_move_to_inactive(&obj_priv->base); - } --out: -- spin_unlock(&dev_priv->mm.active_list_lock); - } - --/** -- * Returns true if seq1 is later than seq2. -- */ --bool --i915_seqno_passed(uint32_t seq1, uint32_t seq2) -+void i915_gem_reset(struct drm_device *dev) - { -- return (int32_t)(seq1 - seq2) >= 0; --} -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct drm_i915_gem_object *obj_priv; -+ int i; - --uint32_t --i915_get_gem_seqno(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- return ring->get_gem_seqno(dev, ring); -+ i915_gem_reset_ring_lists(dev_priv, &dev_priv->render_ring); -+ i915_gem_reset_ring_lists(dev_priv, &dev_priv->bsd_ring); -+ i915_gem_reset_ring_lists(dev_priv, &dev_priv->blt_ring); -+ -+ /* Remove anything from the flushing lists. The GPU cache is likely -+ * to be lost on reset along with the data, so simply move the -+ * lost bo to the inactive list. -+ */ -+ while (!list_empty(&dev_priv->mm.flushing_list)) { -+ obj_priv = list_first_entry(&dev_priv->mm.flushing_list, -+ struct drm_i915_gem_object, -+ mm_list); -+ -+ obj_priv->base.write_domain = 0; -+ list_del_init(&obj_priv->gpu_write_list); -+ i915_gem_object_move_to_inactive(&obj_priv->base); -+ } -+ -+ /* Move everything out of the GPU domains to ensure we do any -+ * necessary invalidation upon reuse. -+ */ -+ list_for_each_entry(obj_priv, -+ &dev_priv->mm.inactive_list, -+ mm_list) -+ { -+ obj_priv->base.read_domains &= ~I915_GEM_GPU_DOMAINS; -+ } -+ -+ /* The fence registers are invalidated so clear them out */ -+ for (i = 0; i < 16; i++) { -+ struct drm_i915_fence_reg *reg; -+ -+ reg = &dev_priv->fence_regs[i]; -+ if (!reg->obj) -+ continue; -+ -+ i915_gem_clear_fence_reg(reg->obj); -+ } - } - - /** -@@ -1741,38 +1847,58 @@ i915_gem_retire_requests_ring(struct drm_device *dev, - drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t seqno; - -- if (!ring->status_page.page_addr -- || list_empty(&ring->request_list)) -+ if (!ring->status_page.page_addr || -+ list_empty(&ring->request_list)) - return; - -- seqno = i915_get_gem_seqno(dev, ring); -+ WARN_ON(i915_verify_lists(dev)); - -+ seqno = ring->get_seqno(dev, ring); - while (!list_empty(&ring->request_list)) { - struct drm_i915_gem_request *request; -- uint32_t retiring_seqno; - - request = list_first_entry(&ring->request_list, - struct drm_i915_gem_request, - list); -- retiring_seqno = request->seqno; - -- if (i915_seqno_passed(seqno, retiring_seqno) || -- atomic_read(&dev_priv->mm.wedged)) { -- i915_gem_retire_request(dev, request); -+ if (!i915_seqno_passed(seqno, request->seqno)) -+ break; -+ -+ trace_i915_gem_request_retire(dev, request->seqno); -+ -+ list_del(&request->list); -+ i915_gem_request_remove_from_client(request); -+ kfree(request); -+ } -+ -+ /* Move any buffers on the active list that are no longer referenced -+ * by the ringbuffer to the flushing/inactive lists as appropriate. -+ */ -+ while (!list_empty(&ring->active_list)) { -+ struct drm_gem_object *obj; -+ struct drm_i915_gem_object *obj_priv; -+ -+ obj_priv = list_first_entry(&ring->active_list, -+ struct drm_i915_gem_object, -+ ring_list); - -- list_del(&request->list); -- list_del(&request->client_list); -- kfree(request); -- } else -+ if (!i915_seqno_passed(seqno, obj_priv->last_rendering_seqno)) - break; -+ -+ obj = &obj_priv->base; -+ if (obj->write_domain != 0) -+ i915_gem_object_move_to_flushing(obj); -+ else -+ i915_gem_object_move_to_inactive(obj); - } - - if (unlikely (dev_priv->trace_irq_seqno && - i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { -- - ring->user_irq_put(dev, ring); - dev_priv->trace_irq_seqno = 0; - } -+ -+ WARN_ON(i915_verify_lists(dev)); - } - - void -@@ -1790,16 +1916,16 @@ i915_gem_retire_requests(struct drm_device *dev) - */ - list_for_each_entry_safe(obj_priv, tmp, - &dev_priv->mm.deferred_free_list, -- list) -+ mm_list) - i915_gem_free_object_tail(&obj_priv->base); - } - - i915_gem_retire_requests_ring(dev, &dev_priv->render_ring); -- if (HAS_BSD(dev)) -- i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); -+ i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); -+ i915_gem_retire_requests_ring(dev, &dev_priv->blt_ring); - } - --void -+static void - i915_gem_retire_work_handler(struct work_struct *work) - { - drm_i915_private_t *dev_priv; -@@ -1809,20 +1935,25 @@ i915_gem_retire_work_handler(struct work_struct *work) - mm.retire_work.work); - dev = dev_priv->dev; - -- mutex_lock(&dev->struct_mutex); -+ /* Come back later if the device is busy... */ -+ if (!mutex_trylock(&dev->struct_mutex)) { -+ queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); -+ return; -+ } -+ - i915_gem_retire_requests(dev); - - if (!dev_priv->mm.suspended && - (!list_empty(&dev_priv->render_ring.request_list) || -- (HAS_BSD(dev) && -- !list_empty(&dev_priv->bsd_ring.request_list)))) -+ !list_empty(&dev_priv->bsd_ring.request_list) || -+ !list_empty(&dev_priv->blt_ring.request_list))) - queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); - mutex_unlock(&dev->struct_mutex); - } - - int - i915_do_wait_request(struct drm_device *dev, uint32_t seqno, -- int interruptible, struct intel_ring_buffer *ring) -+ bool interruptible, struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; - u32 ier; -@@ -1831,9 +1962,16 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, - BUG_ON(seqno == 0); - - if (atomic_read(&dev_priv->mm.wedged)) -- return -EIO; -+ return -EAGAIN; - -- if (!i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)) { -+ if (ring->outstanding_lazy_request) { -+ seqno = i915_add_request(dev, NULL, NULL, ring); -+ if (seqno == 0) -+ return -ENOMEM; -+ } -+ BUG_ON(seqno == dev_priv->next_seqno); -+ -+ if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { - if (HAS_PCH_SPLIT(dev)) - ier = I915_READ(DEIER) | I915_READ(GTIER); - else -@@ -1852,12 +1990,12 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, - if (interruptible) - ret = wait_event_interruptible(ring->irq_queue, - i915_seqno_passed( -- ring->get_gem_seqno(dev, ring), seqno) -+ ring->get_seqno(dev, ring), seqno) - || atomic_read(&dev_priv->mm.wedged)); - else - wait_event(ring->irq_queue, - i915_seqno_passed( -- ring->get_gem_seqno(dev, ring), seqno) -+ ring->get_seqno(dev, ring), seqno) - || atomic_read(&dev_priv->mm.wedged)); - - ring->user_irq_put(dev, ring); -@@ -1866,11 +2004,12 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, - trace_i915_gem_request_wait_end(dev, seqno); - } - if (atomic_read(&dev_priv->mm.wedged)) -- ret = -EIO; -+ ret = -EAGAIN; - - if (ret && ret != -ERESTARTSYS) -- DRM_ERROR("%s returns %d (awaiting %d at %d)\n", -- __func__, ret, seqno, ring->get_gem_seqno(dev, ring)); -+ DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n", -+ __func__, ret, seqno, ring->get_seqno(dev, ring), -+ dev_priv->next_seqno); - - /* Directly dispatch request retiring. While we have the work queue - * to handle this, the waiter on a request often wants an associated -@@ -1889,27 +2028,48 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, - */ - static int - i915_wait_request(struct drm_device *dev, uint32_t seqno, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - return i915_do_wait_request(dev, seqno, 1, ring); - } - - static void -+i915_gem_flush_ring(struct drm_device *dev, -+ struct drm_file *file_priv, -+ struct intel_ring_buffer *ring, -+ uint32_t invalidate_domains, -+ uint32_t flush_domains) -+{ -+ ring->flush(dev, ring, invalidate_domains, flush_domains); -+ i915_gem_process_flushing_list(dev, flush_domains, ring); -+} -+ -+static void - i915_gem_flush(struct drm_device *dev, -+ struct drm_file *file_priv, - uint32_t invalidate_domains, -- uint32_t flush_domains) -+ uint32_t flush_domains, -+ uint32_t flush_rings) - { - drm_i915_private_t *dev_priv = dev->dev_private; -+ - if (flush_domains & I915_GEM_DOMAIN_CPU) - drm_agp_chipset_flush(dev); -- dev_priv->render_ring.flush(dev, &dev_priv->render_ring, -- invalidate_domains, -- flush_domains); -- -- if (HAS_BSD(dev)) -- dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring, -- invalidate_domains, -- flush_domains); -+ -+ if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { -+ if (flush_rings & RING_RENDER) -+ i915_gem_flush_ring(dev, file_priv, -+ &dev_priv->render_ring, -+ invalidate_domains, flush_domains); -+ if (flush_rings & RING_BSD) -+ i915_gem_flush_ring(dev, file_priv, -+ &dev_priv->bsd_ring, -+ invalidate_domains, flush_domains); -+ if (flush_rings & RING_BLT) -+ i915_gem_flush_ring(dev, file_priv, -+ &dev_priv->blt_ring, -+ invalidate_domains, flush_domains); -+ } - } - - /** -@@ -1917,7 +2077,8 @@ i915_gem_flush(struct drm_device *dev, - * safe to unbind from the GTT or access from the CPU. - */ - static int --i915_gem_object_wait_rendering(struct drm_gem_object *obj) -+i915_gem_object_wait_rendering(struct drm_gem_object *obj, -+ bool interruptible) - { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -@@ -1932,13 +2093,11 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) - * it. - */ - if (obj_priv->active) { --#if WATCH_BUF -- DRM_INFO("%s: object %p wait for seqno %08x\n", -- __func__, obj, obj_priv->last_rendering_seqno); --#endif -- ret = i915_wait_request(dev, -- obj_priv->last_rendering_seqno, obj_priv->ring); -- if (ret != 0) -+ ret = i915_do_wait_request(dev, -+ obj_priv->last_rendering_seqno, -+ interruptible, -+ obj_priv->ring); -+ if (ret) - return ret; - } - -@@ -1952,14 +2111,10 @@ int - i915_gem_object_unbind(struct drm_gem_object *obj) - { - struct drm_device *dev = obj->dev; -- drm_i915_private_t *dev_priv = dev->dev_private; -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int ret = 0; - --#if WATCH_BUF -- DRM_INFO("%s:%d %p\n", __func__, __LINE__, obj); -- DRM_INFO("gtt_space %p\n", obj_priv->gtt_space); --#endif - if (obj_priv->gtt_space == NULL) - return 0; - -@@ -1984,33 +2139,27 @@ i915_gem_object_unbind(struct drm_gem_object *obj) - * should be safe and we need to cleanup or else we might - * cause memory corruption through use-after-free. - */ -+ if (ret) { -+ i915_gem_clflush_object(obj); -+ obj->read_domains = obj->write_domain = I915_GEM_DOMAIN_CPU; -+ } - - /* release the fence reg _after_ flushing */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - i915_gem_clear_fence_reg(obj); - -- if (obj_priv->agp_mem != NULL) { -- drm_unbind_agp(obj_priv->agp_mem); -- drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); -- obj_priv->agp_mem = NULL; -- } -+ drm_unbind_agp(obj_priv->agp_mem); -+ drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); - - i915_gem_object_put_pages(obj); - BUG_ON(obj_priv->pages_refcount); - -- if (obj_priv->gtt_space) { -- atomic_dec(&dev->gtt_count); -- atomic_sub(obj->size, &dev->gtt_memory); -- -- drm_mm_put_block(obj_priv->gtt_space); -- obj_priv->gtt_space = NULL; -- } -+ i915_gem_info_remove_gtt(dev_priv, obj->size); -+ list_del_init(&obj_priv->mm_list); - -- /* Remove ourselves from the LRU list if present. */ -- spin_lock(&dev_priv->mm.active_list_lock); -- if (!list_empty(&obj_priv->list)) -- list_del_init(&obj_priv->list); -- spin_unlock(&dev_priv->mm.active_list_lock); -+ drm_mm_put_block(obj_priv->gtt_space); -+ obj_priv->gtt_space = NULL; -+ obj_priv->gtt_offset = 0; - - if (i915_gem_object_is_purgeable(obj_priv)) - i915_gem_object_truncate(obj); -@@ -2020,48 +2169,48 @@ i915_gem_object_unbind(struct drm_gem_object *obj) - return ret; - } - -+static int i915_ring_idle(struct drm_device *dev, -+ struct intel_ring_buffer *ring) -+{ -+ if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) -+ return 0; -+ -+ i915_gem_flush_ring(dev, NULL, ring, -+ I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); -+ return i915_wait_request(dev, -+ i915_gem_next_request_seqno(dev, ring), -+ ring); -+} -+ - int - i915_gpu_idle(struct drm_device *dev) - { - drm_i915_private_t *dev_priv = dev->dev_private; - bool lists_empty; -- uint32_t seqno1, seqno2; - int ret; - -- spin_lock(&dev_priv->mm.active_list_lock); - lists_empty = (list_empty(&dev_priv->mm.flushing_list) && -- list_empty(&dev_priv->render_ring.active_list) && -- (!HAS_BSD(dev) || -- list_empty(&dev_priv->bsd_ring.active_list))); -- spin_unlock(&dev_priv->mm.active_list_lock); -- -+ list_empty(&dev_priv->mm.active_list)); - if (lists_empty) - return 0; - - /* Flush everything onto the inactive list. */ -- i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); -- seqno1 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, -- &dev_priv->render_ring); -- if (seqno1 == 0) -- return -ENOMEM; -- ret = i915_wait_request(dev, seqno1, &dev_priv->render_ring); -- -- if (HAS_BSD(dev)) { -- seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, -- &dev_priv->bsd_ring); -- if (seqno2 == 0) -- return -ENOMEM; -+ ret = i915_ring_idle(dev, &dev_priv->render_ring); -+ if (ret) -+ return ret; - -- ret = i915_wait_request(dev, seqno2, &dev_priv->bsd_ring); -- if (ret) -- return ret; -- } -+ ret = i915_ring_idle(dev, &dev_priv->bsd_ring); -+ if (ret) -+ return ret; - -+ ret = i915_ring_idle(dev, &dev_priv->blt_ring); -+ if (ret) -+ return ret; - -- return ret; -+ return 0; - } - --int -+static int - i915_gem_object_get_pages(struct drm_gem_object *obj, - gfp_t gfpmask) - { -@@ -2241,7 +2390,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) - I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); - } - --static int i915_find_fence_reg(struct drm_device *dev) -+static int i915_find_fence_reg(struct drm_device *dev, -+ bool interruptible) - { - struct drm_i915_fence_reg *reg = NULL; - struct drm_i915_gem_object *obj_priv = NULL; -@@ -2286,7 +2436,7 @@ static int i915_find_fence_reg(struct drm_device *dev) - * private reference to obj like the other callers of put_fence_reg - * (set_tiling ioctl) do. */ - drm_gem_object_reference(obj); -- ret = i915_gem_object_put_fence_reg(obj); -+ ret = i915_gem_object_put_fence_reg(obj, interruptible); - drm_gem_object_unreference(obj); - if (ret != 0) - return ret; -@@ -2308,7 +2458,8 @@ static int i915_find_fence_reg(struct drm_device *dev) - * and tiling format. - */ - int --i915_gem_object_get_fence_reg(struct drm_gem_object *obj) -+i915_gem_object_get_fence_reg(struct drm_gem_object *obj, -+ bool interruptible) - { - struct drm_device *dev = obj->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -@@ -2343,7 +2494,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) - break; - } - -- ret = i915_find_fence_reg(dev); -+ ret = i915_find_fence_reg(dev, interruptible); - if (ret < 0) - return ret; - -@@ -2421,15 +2572,19 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) - * i915_gem_object_put_fence_reg - waits on outstanding fenced access - * to the buffer to finish, and then resets the fence register. - * @obj: tiled object holding a fence register. -+ * @bool: whether the wait upon the fence is interruptible - * - * Zeroes out the fence register itself and clears out the associated - * data structures in dev_priv and obj_priv. - */ - int --i915_gem_object_put_fence_reg(struct drm_gem_object *obj) -+i915_gem_object_put_fence_reg(struct drm_gem_object *obj, -+ bool interruptible) - { - struct drm_device *dev = obj->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -+ struct drm_i915_fence_reg *reg; - - if (obj_priv->fence_reg == I915_FENCE_REG_NONE) - return 0; -@@ -2444,20 +2599,23 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj) - * therefore we must wait for any outstanding access to complete - * before clearing the fence. - */ -- if (!IS_I965G(dev)) { -+ reg = &dev_priv->fence_regs[obj_priv->fence_reg]; -+ if (reg->gpu) { - int ret; - -- ret = i915_gem_object_flush_gpu_write_domain(obj); -- if (ret != 0) -+ ret = i915_gem_object_flush_gpu_write_domain(obj, true); -+ if (ret) - return ret; - -- ret = i915_gem_object_wait_rendering(obj); -- if (ret != 0) -+ ret = i915_gem_object_wait_rendering(obj, interruptible); -+ if (ret) - return ret; -+ -+ reg->gpu = false; - } - - i915_gem_object_flush_gtt_write_domain(obj); -- i915_gem_clear_fence_reg (obj); -+ i915_gem_clear_fence_reg(obj); - - return 0; - } -@@ -2490,7 +2648,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) - /* If the object is bigger than the entire aperture, reject it early - * before evicting everything in a vain attempt to find space. - */ -- if (obj->size > dev->gtt_total) { -+ if (obj->size > dev_priv->mm.gtt_total) { - DRM_ERROR("Attempting to bind an object larger than the aperture\n"); - return -E2BIG; - } -@@ -2498,19 +2656,13 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) - search_free: - free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, - obj->size, alignment, 0); -- if (free_space != NULL) { -+ if (free_space != NULL) - obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size, - alignment); -- if (obj_priv->gtt_space != NULL) -- obj_priv->gtt_offset = obj_priv->gtt_space->start; -- } - if (obj_priv->gtt_space == NULL) { - /* If the gtt is empty and we're still having trouble - * fitting our object in, we're out of memory. - */ --#if WATCH_LRU -- DRM_INFO("%s: GTT full, evicting something\n", __func__); --#endif - ret = i915_gem_evict_something(dev, obj->size, alignment); - if (ret) - return ret; -@@ -2518,10 +2670,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) - goto search_free; - } - --#if WATCH_BUF -- DRM_INFO("Binding object of size %zd at 0x%08x\n", -- obj->size, obj_priv->gtt_offset); --#endif - ret = i915_gem_object_get_pages(obj, gfpmask); - if (ret) { - drm_mm_put_block(obj_priv->gtt_space); -@@ -2553,7 +2701,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) - obj_priv->agp_mem = drm_agp_bind_pages(dev, - obj_priv->pages, - obj->size >> PAGE_SHIFT, -- obj_priv->gtt_offset, -+ obj_priv->gtt_space->start, - obj_priv->agp_type); - if (obj_priv->agp_mem == NULL) { - i915_gem_object_put_pages(obj); -@@ -2566,11 +2714,10 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) - - goto search_free; - } -- atomic_inc(&dev->gtt_count); -- atomic_add(obj->size, &dev->gtt_memory); - - /* keep track of bounds object by adding it to the inactive list */ -- list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); -+ list_add_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); -+ i915_gem_info_add_gtt(dev_priv, obj->size); - - /* Assert that the object is not currently in any GPU domain. As it - * wasn't in the GTT, there shouldn't be any way it could have been in -@@ -2579,6 +2726,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) - BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); - BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); - -+ obj_priv->gtt_offset = obj_priv->gtt_space->start; - trace_i915_gem_object_bind(obj, obj_priv->gtt_offset); - - return 0; -@@ -2603,25 +2751,30 @@ i915_gem_clflush_object(struct drm_gem_object *obj) - - /** Flushes any GPU write domain for the object if it's dirty. */ - static int --i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) -+i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, -+ bool pipelined) - { - struct drm_device *dev = obj->dev; - uint32_t old_write_domain; -- struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - - if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) - return 0; - - /* Queue the GPU write cache flushing we need. */ - old_write_domain = obj->write_domain; -- i915_gem_flush(dev, 0, obj->write_domain); -- if (i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring) == 0) -- return -ENOMEM; -+ i915_gem_flush_ring(dev, NULL, -+ to_intel_bo(obj)->ring, -+ 0, obj->write_domain); -+ BUG_ON(obj->write_domain); - - trace_i915_gem_object_change_domain(obj, - obj->read_domains, - old_write_domain); -- return 0; -+ -+ if (pipelined) -+ return 0; -+ -+ return i915_gem_object_wait_rendering(obj, true); - } - - /** Flushes the GTT write domain for the object if it's dirty. */ -@@ -2665,26 +2818,6 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) - old_write_domain); - } - --int --i915_gem_object_flush_write_domain(struct drm_gem_object *obj) --{ -- int ret = 0; -- -- switch (obj->write_domain) { -- case I915_GEM_DOMAIN_GTT: -- i915_gem_object_flush_gtt_write_domain(obj); -- break; -- case I915_GEM_DOMAIN_CPU: -- i915_gem_object_flush_cpu_write_domain(obj); -- break; -- default: -- ret = i915_gem_object_flush_gpu_write_domain(obj); -- break; -- } -- -- return ret; --} -- - /** - * Moves a single object to the GTT read, and possibly write domain. - * -@@ -2702,32 +2835,28 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) - if (obj_priv->gtt_space == NULL) - return -EINVAL; - -- ret = i915_gem_object_flush_gpu_write_domain(obj); -+ ret = i915_gem_object_flush_gpu_write_domain(obj, false); - if (ret != 0) - return ret; - -- /* Wait on any GPU rendering and flushing to occur. */ -- ret = i915_gem_object_wait_rendering(obj); -- if (ret != 0) -- return ret; -+ i915_gem_object_flush_cpu_write_domain(obj); -+ -+ if (write) { -+ ret = i915_gem_object_wait_rendering(obj, true); -+ if (ret) -+ return ret; -+ } - - old_write_domain = obj->write_domain; - old_read_domains = obj->read_domains; - -- /* If we're writing through the GTT domain, then CPU and GPU caches -- * will need to be invalidated at next use. -- */ -- if (write) -- obj->read_domains &= I915_GEM_DOMAIN_GTT; -- -- i915_gem_object_flush_cpu_write_domain(obj); -- - /* It should now be out of any other write domains, and we can update - * the domain values for our changes. - */ - BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); - obj->read_domains |= I915_GEM_DOMAIN_GTT; - if (write) { -+ obj->read_domains = I915_GEM_DOMAIN_GTT; - obj->write_domain = I915_GEM_DOMAIN_GTT; - obj_priv->dirty = 1; - } -@@ -2744,51 +2873,36 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) - * wait, as in modesetting process we're not supposed to be interrupted. - */ - int --i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) -+i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, -+ bool pipelined) - { -- struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -- uint32_t old_write_domain, old_read_domains; -+ uint32_t old_read_domains; - int ret; - - /* Not valid to be called on unbound objects. */ - if (obj_priv->gtt_space == NULL) - return -EINVAL; - -- ret = i915_gem_object_flush_gpu_write_domain(obj); -+ ret = i915_gem_object_flush_gpu_write_domain(obj, true); - if (ret) - return ret; - -- /* Wait on any GPU rendering and flushing to occur. */ -- if (obj_priv->active) { --#if WATCH_BUF -- DRM_INFO("%s: object %p wait for seqno %08x\n", -- __func__, obj, obj_priv->last_rendering_seqno); --#endif -- ret = i915_do_wait_request(dev, -- obj_priv->last_rendering_seqno, -- 0, -- obj_priv->ring); -- if (ret != 0) -+ /* Currently, we are always called from an non-interruptible context. */ -+ if (!pipelined) { -+ ret = i915_gem_object_wait_rendering(obj, false); -+ if (ret) - return ret; - } - - i915_gem_object_flush_cpu_write_domain(obj); - -- old_write_domain = obj->write_domain; - old_read_domains = obj->read_domains; -- -- /* It should now be out of any other write domains, and we can update -- * the domain values for our changes. -- */ -- BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); -- obj->read_domains = I915_GEM_DOMAIN_GTT; -- obj->write_domain = I915_GEM_DOMAIN_GTT; -- obj_priv->dirty = 1; -+ obj->read_domains |= I915_GEM_DOMAIN_GTT; - - trace_i915_gem_object_change_domain(obj, - old_read_domains, -- old_write_domain); -+ obj->write_domain); - - return 0; - } -@@ -2805,12 +2919,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) - uint32_t old_write_domain, old_read_domains; - int ret; - -- ret = i915_gem_object_flush_gpu_write_domain(obj); -- if (ret) -- return ret; -- -- /* Wait on any GPU rendering and flushing to occur. */ -- ret = i915_gem_object_wait_rendering(obj); -+ ret = i915_gem_object_flush_gpu_write_domain(obj, false); - if (ret != 0) - return ret; - -@@ -2821,6 +2930,12 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) - */ - i915_gem_object_set_to_full_cpu_read_domain(obj); - -+ if (write) { -+ ret = i915_gem_object_wait_rendering(obj, true); -+ if (ret) -+ return ret; -+ } -+ - old_write_domain = obj->write_domain; - old_read_domains = obj->read_domains; - -@@ -2840,7 +2955,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) - * need to be invalidated at next use. - */ - if (write) { -- obj->read_domains &= I915_GEM_DOMAIN_CPU; -+ obj->read_domains = I915_GEM_DOMAIN_CPU; - obj->write_domain = I915_GEM_DOMAIN_CPU; - } - -@@ -2963,26 +3078,18 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) - * drm_agp_chipset_flush - */ - static void --i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) -+i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, -+ struct intel_ring_buffer *ring) - { - struct drm_device *dev = obj->dev; -- drm_i915_private_t *dev_priv = dev->dev_private; -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - uint32_t invalidate_domains = 0; - uint32_t flush_domains = 0; - uint32_t old_read_domains; - -- BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU); -- BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU); -- - intel_mark_busy(dev, obj); - --#if WATCH_BUF -- DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", -- __func__, obj, -- obj->read_domains, obj->pending_read_domains, -- obj->write_domain, obj->pending_write_domain); --#endif - /* - * If the object isn't moving to a new write domain, - * let the object stay in multiple read domains -@@ -2999,7 +3106,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) - * write domain - */ - if (obj->write_domain && -- obj->write_domain != obj->pending_read_domains) { -+ (obj->write_domain != obj->pending_read_domains || -+ obj_priv->ring != ring)) { - flush_domains |= obj->write_domain; - invalidate_domains |= - obj->pending_read_domains & ~obj->write_domain; -@@ -3009,13 +3117,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) - * stale data. That is, any new read domains. - */ - invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; -- if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { --#if WATCH_BUF -- DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", -- __func__, flush_domains, invalidate_domains); --#endif -+ if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) - i915_gem_clflush_object(obj); -- } - - old_read_domains = obj->read_domains; - -@@ -3029,21 +3132,12 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) - obj->pending_write_domain = obj->write_domain; - obj->read_domains = obj->pending_read_domains; - -- if (flush_domains & I915_GEM_GPU_DOMAINS) { -- if (obj_priv->ring == &dev_priv->render_ring) -- dev_priv->flush_rings |= FLUSH_RENDER_RING; -- else if (obj_priv->ring == &dev_priv->bsd_ring) -- dev_priv->flush_rings |= FLUSH_BSD_RING; -- } -- - dev->invalidate_domains |= invalidate_domains; - dev->flush_domains |= flush_domains; --#if WATCH_BUF -- DRM_INFO("%s: read %08x write %08x invalidate %08x flush %08x\n", -- __func__, -- obj->read_domains, obj->write_domain, -- dev->invalidate_domains, dev->flush_domains); --#endif -+ if (flush_domains & I915_GEM_GPU_DOMAINS) -+ dev_priv->mm.flush_rings |= obj_priv->ring->id; -+ if (invalidate_domains & I915_GEM_GPU_DOMAINS) -+ dev_priv->mm.flush_rings |= ring->id; - - trace_i915_gem_object_change_domain(obj, - old_read_domains, -@@ -3106,12 +3200,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, - if (offset == 0 && size == obj->size) - return i915_gem_object_set_to_cpu_domain(obj, 0); - -- ret = i915_gem_object_flush_gpu_write_domain(obj); -- if (ret) -- return ret; -- -- /* Wait on any GPU rendering and flushing to occur. */ -- ret = i915_gem_object_wait_rendering(obj); -+ ret = i915_gem_object_flush_gpu_write_domain(obj, false); - if (ret != 0) - return ret; - i915_gem_object_flush_gtt_write_domain(obj); -@@ -3164,66 +3253,42 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, - * Pin an object to the GTT and evaluate the relocations landing in it. - */ - static int --i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, -- struct drm_file *file_priv, -- struct drm_i915_gem_exec_object2 *entry, -- struct drm_i915_gem_relocation_entry *relocs) -+i915_gem_execbuffer_relocate(struct drm_i915_gem_object *obj, -+ struct drm_file *file_priv, -+ struct drm_i915_gem_exec_object2 *entry) - { -- struct drm_device *dev = obj->dev; -+ struct drm_device *dev = obj->base.dev; - drm_i915_private_t *dev_priv = dev->dev_private; -- struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -- int i, ret; -- void __iomem *reloc_page; -- bool need_fence; -- -- need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE && -- obj_priv->tiling_mode != I915_TILING_NONE; -- -- /* Check fence reg constraints and rebind if necessary */ -- if (need_fence && -- !i915_gem_object_fence_offset_ok(obj, -- obj_priv->tiling_mode)) { -- ret = i915_gem_object_unbind(obj); -- if (ret) -- return ret; -- } -+ struct drm_i915_gem_relocation_entry __user *user_relocs; -+ struct drm_gem_object *target_obj = NULL; -+ uint32_t target_handle = 0; -+ int i, ret = 0; - -- /* Choose the GTT offset for our buffer and put it there. */ -- ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); -- if (ret) -- return ret; -+ user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; -+ for (i = 0; i < entry->relocation_count; i++) { -+ struct drm_i915_gem_relocation_entry reloc; -+ uint32_t target_offset; - -- /* -- * Pre-965 chips need a fence register set up in order to -- * properly handle blits to/from tiled surfaces. -- */ -- if (need_fence) { -- ret = i915_gem_object_get_fence_reg(obj); -- if (ret != 0) { -- i915_gem_object_unpin(obj); -- return ret; -+ if (__copy_from_user_inatomic(&reloc, -+ user_relocs+i, -+ sizeof(reloc))) { -+ ret = -EFAULT; -+ break; - } -- } - -- entry->offset = obj_priv->gtt_offset; -+ if (reloc.target_handle != target_handle) { -+ drm_gem_object_unreference(target_obj); - -- /* Apply the relocations, using the GTT aperture to avoid cache -- * flushing requirements. -- */ -- for (i = 0; i < entry->relocation_count; i++) { -- struct drm_i915_gem_relocation_entry *reloc= &relocs[i]; -- struct drm_gem_object *target_obj; -- struct drm_i915_gem_object *target_obj_priv; -- uint32_t reloc_val, reloc_offset; -- uint32_t __iomem *reloc_entry; -- -- target_obj = drm_gem_object_lookup(obj->dev, file_priv, -- reloc->target_handle); -- if (target_obj == NULL) { -- i915_gem_object_unpin(obj); -- return -ENOENT; -+ target_obj = drm_gem_object_lookup(dev, file_priv, -+ reloc.target_handle); -+ if (target_obj == NULL) { -+ ret = -ENOENT; -+ break; -+ } -+ -+ target_handle = reloc.target_handle; - } -- target_obj_priv = to_intel_bo(target_obj); -+ target_offset = to_intel_bo(target_obj)->gtt_offset; - - #if WATCH_RELOC - DRM_INFO("%s: obj %p offset %08x target %d " -@@ -3231,268 +3296,313 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, - "presumed %08x delta %08x\n", - __func__, - obj, -- (int) reloc->offset, -- (int) reloc->target_handle, -- (int) reloc->read_domains, -- (int) reloc->write_domain, -- (int) target_obj_priv->gtt_offset, -- (int) reloc->presumed_offset, -- reloc->delta); -+ (int) reloc.offset, -+ (int) reloc.target_handle, -+ (int) reloc.read_domains, -+ (int) reloc.write_domain, -+ (int) target_offset, -+ (int) reloc.presumed_offset, -+ reloc.delta); - #endif - - /* The target buffer should have appeared before us in the - * exec_object list, so it should have a GTT space bound by now. - */ -- if (target_obj_priv->gtt_space == NULL) { -+ if (target_offset == 0) { - DRM_ERROR("No GTT space found for object %d\n", -- reloc->target_handle); -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -+ reloc.target_handle); -+ ret = -EINVAL; -+ break; - } - - /* Validate that the target is in a valid r/w GPU domain */ -- if (reloc->write_domain & (reloc->write_domain - 1)) { -+ if (reloc.write_domain & (reloc.write_domain - 1)) { - DRM_ERROR("reloc with multiple write domains: " - "obj %p target %d offset %d " - "read %08x write %08x", -- obj, reloc->target_handle, -- (int) reloc->offset, -- reloc->read_domains, -- reloc->write_domain); -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -+ obj, reloc.target_handle, -+ (int) reloc.offset, -+ reloc.read_domains, -+ reloc.write_domain); -+ ret = -EINVAL; -+ break; - } -- if (reloc->write_domain & I915_GEM_DOMAIN_CPU || -- reloc->read_domains & I915_GEM_DOMAIN_CPU) { -+ if (reloc.write_domain & I915_GEM_DOMAIN_CPU || -+ reloc.read_domains & I915_GEM_DOMAIN_CPU) { - DRM_ERROR("reloc with read/write CPU domains: " - "obj %p target %d offset %d " - "read %08x write %08x", -- obj, reloc->target_handle, -- (int) reloc->offset, -- reloc->read_domains, -- reloc->write_domain); -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -+ obj, reloc.target_handle, -+ (int) reloc.offset, -+ reloc.read_domains, -+ reloc.write_domain); -+ ret = -EINVAL; -+ break; - } -- if (reloc->write_domain && target_obj->pending_write_domain && -- reloc->write_domain != target_obj->pending_write_domain) { -+ if (reloc.write_domain && target_obj->pending_write_domain && -+ reloc.write_domain != target_obj->pending_write_domain) { - DRM_ERROR("Write domain conflict: " - "obj %p target %d offset %d " - "new %08x old %08x\n", -- obj, reloc->target_handle, -- (int) reloc->offset, -- reloc->write_domain, -+ obj, reloc.target_handle, -+ (int) reloc.offset, -+ reloc.write_domain, - target_obj->pending_write_domain); -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -+ ret = -EINVAL; -+ break; - } - -- target_obj->pending_read_domains |= reloc->read_domains; -- target_obj->pending_write_domain |= reloc->write_domain; -+ target_obj->pending_read_domains |= reloc.read_domains; -+ target_obj->pending_write_domain |= reloc.write_domain; - - /* If the relocation already has the right value in it, no - * more work needs to be done. - */ -- if (target_obj_priv->gtt_offset == reloc->presumed_offset) { -- drm_gem_object_unreference(target_obj); -+ if (target_offset == reloc.presumed_offset) - continue; -- } - - /* Check that the relocation address is valid... */ -- if (reloc->offset > obj->size - 4) { -+ if (reloc.offset > obj->base.size - 4) { - DRM_ERROR("Relocation beyond object bounds: " - "obj %p target %d offset %d size %d.\n", -- obj, reloc->target_handle, -- (int) reloc->offset, (int) obj->size); -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -+ obj, reloc.target_handle, -+ (int) reloc.offset, (int) obj->base.size); -+ ret = -EINVAL; -+ break; - } -- if (reloc->offset & 3) { -+ if (reloc.offset & 3) { - DRM_ERROR("Relocation not 4-byte aligned: " - "obj %p target %d offset %d.\n", -- obj, reloc->target_handle, -- (int) reloc->offset); -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -+ obj, reloc.target_handle, -+ (int) reloc.offset); -+ ret = -EINVAL; -+ break; - } - - /* and points to somewhere within the target object. */ -- if (reloc->delta >= target_obj->size) { -+ if (reloc.delta >= target_obj->size) { - DRM_ERROR("Relocation beyond target object bounds: " - "obj %p target %d delta %d size %d.\n", -- obj, reloc->target_handle, -- (int) reloc->delta, (int) target_obj->size); -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -+ obj, reloc.target_handle, -+ (int) reloc.delta, (int) target_obj->size); -+ ret = -EINVAL; -+ break; - } - -- ret = i915_gem_object_set_to_gtt_domain(obj, 1); -- if (ret != 0) { -- drm_gem_object_unreference(target_obj); -- i915_gem_object_unpin(obj); -- return -EINVAL; -- } -+ reloc.delta += target_offset; -+ if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { -+ uint32_t page_offset = reloc.offset & ~PAGE_MASK; -+ char *vaddr; - -- /* Map the page containing the relocation we're going to -- * perform. -- */ -- reloc_offset = obj_priv->gtt_offset + reloc->offset; -- reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, -- (reloc_offset & -- ~(PAGE_SIZE - 1)), -- KM_USER0); -- reloc_entry = (uint32_t __iomem *)(reloc_page + -- (reloc_offset & (PAGE_SIZE - 1))); -- reloc_val = target_obj_priv->gtt_offset + reloc->delta; -- --#if WATCH_BUF -- DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n", -- obj, (unsigned int) reloc->offset, -- readl(reloc_entry), reloc_val); --#endif -- writel(reloc_val, reloc_entry); -- io_mapping_unmap_atomic(reloc_page, KM_USER0); -+ vaddr = kmap_atomic(obj->pages[reloc.offset >> PAGE_SHIFT], KM_USER0); -+ *(uint32_t *)(vaddr + page_offset) = reloc.delta; -+ kunmap_atomic(vaddr, KM_USER0); -+ } else { -+ uint32_t __iomem *reloc_entry; -+ void __iomem *reloc_page; - -- /* The updated presumed offset for this entry will be -- * copied back out to the user. -- */ -- reloc->presumed_offset = target_obj_priv->gtt_offset; -+ ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1); -+ if (ret) -+ break; -+ -+ /* Map the page containing the relocation we're going to perform. */ -+ reloc.offset += obj->gtt_offset; -+ reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, -+ reloc.offset & PAGE_MASK, -+ KM_USER0); -+ reloc_entry = (uint32_t __iomem *) -+ (reloc_page + (reloc.offset & ~PAGE_MASK)); -+ iowrite32(reloc.delta, reloc_entry); -+ io_mapping_unmap_atomic(reloc_page, KM_USER0); -+ } - -- drm_gem_object_unreference(target_obj); -+ /* and update the user's relocation entry */ -+ reloc.presumed_offset = target_offset; -+ if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, -+ &reloc.presumed_offset, -+ sizeof(reloc.presumed_offset))) { -+ ret = -EFAULT; -+ break; -+ } - } - --#if WATCH_BUF -- if (0) -- i915_gem_dump_object(obj, 128, __func__, ~0); --#endif -- return 0; -+ drm_gem_object_unreference(target_obj); -+ return ret; - } - --/* Throttle our rendering by waiting until the ring has completed our requests -- * emitted over 20 msec ago. -- * -- * Note that if we were to use the current jiffies each time around the loop, -- * we wouldn't escape the function with any frames outstanding if the time to -- * render a frame was over 20ms. -- * -- * This should get us reasonable parallelism between CPU and GPU but also -- * relatively low latency when blocking on a particular request to finish. -- */ - static int --i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) -+i915_gem_execbuffer_pin(struct drm_device *dev, -+ struct drm_file *file, -+ struct drm_gem_object **object_list, -+ struct drm_i915_gem_exec_object2 *exec_list, -+ int count) - { -- struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; -- int ret = 0; -- unsigned long recent_enough = jiffies - msecs_to_jiffies(20); -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ int ret, i, retry; - -- mutex_lock(&dev->struct_mutex); -- while (!list_empty(&i915_file_priv->mm.request_list)) { -- struct drm_i915_gem_request *request; -+ /* attempt to pin all of the buffers into the GTT */ -+ for (retry = 0; retry < 2; retry++) { -+ ret = 0; -+ for (i = 0; i < count; i++) { -+ struct drm_i915_gem_exec_object2 *entry = &exec_list[i]; -+ struct drm_i915_gem_object *obj= to_intel_bo(object_list[i]); -+ bool need_fence = -+ entry->flags & EXEC_OBJECT_NEEDS_FENCE && -+ obj->tiling_mode != I915_TILING_NONE; -+ -+ /* Check fence reg constraints and rebind if necessary */ -+ if (need_fence && -+ !i915_gem_object_fence_offset_ok(&obj->base, -+ obj->tiling_mode)) { -+ ret = i915_gem_object_unbind(&obj->base); -+ if (ret) -+ break; -+ } - -- request = list_first_entry(&i915_file_priv->mm.request_list, -- struct drm_i915_gem_request, -- client_list); -+ ret = i915_gem_object_pin(&obj->base, entry->alignment); -+ if (ret) -+ break; - -- if (time_after_eq(request->emitted_jiffies, recent_enough)) -- break; -+ /* -+ * Pre-965 chips need a fence register set up in order -+ * to properly handle blits to/from tiled surfaces. -+ */ -+ if (need_fence) { -+ ret = i915_gem_object_get_fence_reg(&obj->base, true); -+ if (ret) { -+ i915_gem_object_unpin(&obj->base); -+ break; -+ } -+ -+ dev_priv->fence_regs[obj->fence_reg].gpu = true; -+ } -+ -+ entry->offset = obj->gtt_offset; -+ } - -- ret = i915_wait_request(dev, request->seqno, request->ring); -- if (ret != 0) -+ while (i--) -+ i915_gem_object_unpin(object_list[i]); -+ -+ if (ret == 0) - break; -+ -+ if (ret != -ENOSPC || retry) -+ return ret; -+ -+ ret = i915_gem_evict_everything(dev); -+ if (ret) -+ return ret; - } -- mutex_unlock(&dev->struct_mutex); - -- return ret; -+ return 0; - } - - static int --i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list, -- uint32_t buffer_count, -- struct drm_i915_gem_relocation_entry **relocs) -+i915_gem_execbuffer_move_to_gpu(struct drm_device *dev, -+ struct drm_file *file, -+ struct intel_ring_buffer *ring, -+ struct drm_gem_object **objects, -+ int count) - { -- uint32_t reloc_count = 0, reloc_index = 0, i; -- int ret; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ int ret, i; - -- *relocs = NULL; -- for (i = 0; i < buffer_count; i++) { -- if (reloc_count + exec_list[i].relocation_count < reloc_count) -- return -EINVAL; -- reloc_count += exec_list[i].relocation_count; -- } -+ /* Zero the global flush/invalidate flags. These -+ * will be modified as new domains are computed -+ * for each object -+ */ -+ dev->invalidate_domains = 0; -+ dev->flush_domains = 0; -+ dev_priv->mm.flush_rings = 0; -+ for (i = 0; i < count; i++) -+ i915_gem_object_set_to_gpu_domain(objects[i], ring); - -- *relocs = drm_calloc_large(reloc_count, sizeof(**relocs)); -- if (*relocs == NULL) { -- DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count); -- return -ENOMEM; -+ if (dev->invalidate_domains | dev->flush_domains) { -+#if WATCH_EXEC -+ DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", -+ __func__, -+ dev->invalidate_domains, -+ dev->flush_domains); -+#endif -+ i915_gem_flush(dev, file, -+ dev->invalidate_domains, -+ dev->flush_domains, -+ dev_priv->mm.flush_rings); - } - -- for (i = 0; i < buffer_count; i++) { -- struct drm_i915_gem_relocation_entry __user *user_relocs; -- -- user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; -- -- ret = copy_from_user(&(*relocs)[reloc_index], -- user_relocs, -- exec_list[i].relocation_count * -- sizeof(**relocs)); -- if (ret != 0) { -- drm_free_large(*relocs); -- *relocs = NULL; -- return -EFAULT; -+ for (i = 0; i < count; i++) { -+ struct drm_i915_gem_object *obj = to_intel_bo(objects[i]); -+ /* XXX replace with semaphores */ -+ if (obj->ring && ring != obj->ring) { -+ ret = i915_gem_object_wait_rendering(&obj->base, true); -+ if (ret) -+ return ret; - } -- -- reloc_index += exec_list[i].relocation_count; - } - - return 0; - } - -+/* Throttle our rendering by waiting until the ring has completed our requests -+ * emitted over 20 msec ago. -+ * -+ * Note that if we were to use the current jiffies each time around the loop, -+ * we wouldn't escape the function with any frames outstanding if the time to -+ * render a frame was over 20ms. -+ * -+ * This should get us reasonable parallelism between CPU and GPU but also -+ * relatively low latency when blocking on a particular request to finish. -+ */ - static int --i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list, -- uint32_t buffer_count, -- struct drm_i915_gem_relocation_entry *relocs) -+i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) - { -- uint32_t reloc_count = 0, i; -- int ret = 0; -- -- if (relocs == NULL) -- return 0; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct drm_i915_file_private *file_priv = file->driver_priv; -+ unsigned long recent_enough = jiffies - msecs_to_jiffies(20); -+ struct drm_i915_gem_request *request; -+ struct intel_ring_buffer *ring = NULL; -+ u32 seqno = 0; -+ int ret; - -- for (i = 0; i < buffer_count; i++) { -- struct drm_i915_gem_relocation_entry __user *user_relocs; -- int unwritten; -+ spin_lock(&file_priv->mm.lock); -+ list_for_each_entry(request, &file_priv->mm.request_list, client_list) { -+ if (time_after_eq(request->emitted_jiffies, recent_enough)) -+ break; - -- user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; -+ ring = request->ring; -+ seqno = request->seqno; -+ } -+ spin_unlock(&file_priv->mm.lock); - -- unwritten = copy_to_user(user_relocs, -- &relocs[reloc_count], -- exec_list[i].relocation_count * -- sizeof(*relocs)); -+ if (seqno == 0) -+ return 0; - -- if (unwritten) { -- ret = -EFAULT; -- goto err; -- } -+ ret = 0; -+ if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { -+ /* And wait for the seqno passing without holding any locks and -+ * causing extra latency for others. This is safe as the irq -+ * generation is designed to be run atomically and so is -+ * lockless. -+ */ -+ ring->user_irq_get(dev, ring); -+ ret = wait_event_interruptible(ring->irq_queue, -+ i915_seqno_passed(ring->get_seqno(dev, ring), seqno) -+ || atomic_read(&dev_priv->mm.wedged)); -+ ring->user_irq_put(dev, ring); - -- reloc_count += exec_list[i].relocation_count; -+ if (ret == 0 && atomic_read(&dev_priv->mm.wedged)) -+ ret = -EIO; - } - --err: -- drm_free_large(relocs); -+ if (ret == 0) -+ queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); - - return ret; - } - - static int --i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, -- uint64_t exec_offset) -+i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec, -+ uint64_t exec_offset) - { - uint32_t exec_start, exec_len; - -@@ -3509,44 +3619,32 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, - } - - static int --i915_gem_wait_for_pending_flip(struct drm_device *dev, -- struct drm_gem_object **object_list, -- int count) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- struct drm_i915_gem_object *obj_priv; -- DEFINE_WAIT(wait); -- int i, ret = 0; -+validate_exec_list(struct drm_i915_gem_exec_object2 *exec, -+ int count) -+{ -+ int i; - -- for (;;) { -- prepare_to_wait(&dev_priv->pending_flip_queue, -- &wait, TASK_INTERRUPTIBLE); -- for (i = 0; i < count; i++) { -- obj_priv = to_intel_bo(object_list[i]); -- if (atomic_read(&obj_priv->pending_flip) > 0) -- break; -- } -- if (i == count) -- break; -+ for (i = 0; i < count; i++) { -+ char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; -+ size_t length = exec[i].relocation_count * sizeof(struct drm_i915_gem_relocation_entry); - -- if (!signal_pending(current)) { -- mutex_unlock(&dev->struct_mutex); -- schedule(); -- mutex_lock(&dev->struct_mutex); -- continue; -- } -- ret = -ERESTARTSYS; -- break; -+ if (!access_ok(VERIFY_READ, ptr, length)) -+ return -EFAULT; -+ -+ /* we may also need to update the presumed offsets */ -+ if (!access_ok(VERIFY_WRITE, ptr, length)) -+ return -EFAULT; -+ -+ if (fault_in_pages_readable(ptr, length)) -+ return -EFAULT; - } -- finish_wait(&dev_priv->pending_flip_queue, &wait); - -- return ret; -+ return 0; - } - -- --int -+static int - i915_gem_do_execbuffer(struct drm_device *dev, void *data, -- struct drm_file *file_priv, -+ struct drm_file *file, - struct drm_i915_gem_execbuffer2 *args, - struct drm_i915_gem_exec_object2 *exec_list) - { -@@ -3555,26 +3653,47 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - struct drm_gem_object *batch_obj; - struct drm_i915_gem_object *obj_priv; - struct drm_clip_rect *cliprects = NULL; -- struct drm_i915_gem_relocation_entry *relocs = NULL; -- int ret = 0, ret2, i, pinned = 0; -+ struct drm_i915_gem_request *request = NULL; -+ int ret, i, flips; - uint64_t exec_offset; -- uint32_t seqno, flush_domains, reloc_index; -- int pin_tries, flips; - - struct intel_ring_buffer *ring = NULL; - -+ ret = i915_gem_check_is_wedged(dev); -+ if (ret) -+ return ret; -+ -+ ret = validate_exec_list(exec_list, args->buffer_count); -+ if (ret) -+ return ret; -+ - #if WATCH_EXEC - DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", - (int) args->buffers_ptr, args->buffer_count, args->batch_len); - #endif -- if (args->flags & I915_EXEC_BSD) { -+ switch (args->flags & I915_EXEC_RING_MASK) { -+ case I915_EXEC_DEFAULT: -+ case I915_EXEC_RENDER: -+ ring = &dev_priv->render_ring; -+ break; -+ case I915_EXEC_BSD: - if (!HAS_BSD(dev)) { -- DRM_ERROR("execbuf with wrong flag\n"); -+ DRM_ERROR("execbuf with invalid ring (BSD)\n"); - return -EINVAL; - } - ring = &dev_priv->bsd_ring; -- } else { -- ring = &dev_priv->render_ring; -+ break; -+ case I915_EXEC_BLT: -+ if (!HAS_BLT(dev)) { -+ DRM_ERROR("execbuf with invalid ring (BLT)\n"); -+ return -EINVAL; -+ } -+ ring = &dev_priv->blt_ring; -+ break; -+ default: -+ DRM_ERROR("execbuf with unknown ring: %d\n", -+ (int)(args->flags & I915_EXEC_RING_MASK)); -+ return -EINVAL; - } - - if (args->buffer_count < 1) { -@@ -3609,20 +3728,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - } - } - -- ret = i915_gem_get_relocs_from_user(exec_list, args->buffer_count, -- &relocs); -- if (ret != 0) -+ request = kzalloc(sizeof(*request), GFP_KERNEL); -+ if (request == NULL) { -+ ret = -ENOMEM; - goto pre_mutex_err; -+ } - -- mutex_lock(&dev->struct_mutex); -- -- i915_verify_inactive(dev, __FILE__, __LINE__); -- -- if (atomic_read(&dev_priv->mm.wedged)) { -- mutex_unlock(&dev->struct_mutex); -- ret = -EIO; -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) - goto pre_mutex_err; -- } - - if (dev_priv->mm.suspended) { - mutex_unlock(&dev->struct_mutex); -@@ -3631,9 +3745,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - } - - /* Look up object handles */ -- flips = 0; - for (i = 0; i < args->buffer_count; i++) { -- object_list[i] = drm_gem_object_lookup(dev, file_priv, -+ object_list[i] = drm_gem_object_lookup(dev, file, - exec_list[i].handle); - if (object_list[i] == NULL) { - DRM_ERROR("Invalid object handle %d at index %d\n", -@@ -3654,75 +3767,22 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - goto err; - } - obj_priv->in_execbuffer = true; -- flips += atomic_read(&obj_priv->pending_flip); -- } -- -- if (flips > 0) { -- ret = i915_gem_wait_for_pending_flip(dev, object_list, -- args->buffer_count); -- if (ret) -- goto err; - } - -- /* Pin and relocate */ -- for (pin_tries = 0; ; pin_tries++) { -- ret = 0; -- reloc_index = 0; -- -- for (i = 0; i < args->buffer_count; i++) { -- object_list[i]->pending_read_domains = 0; -- object_list[i]->pending_write_domain = 0; -- ret = i915_gem_object_pin_and_relocate(object_list[i], -- file_priv, -- &exec_list[i], -- &relocs[reloc_index]); -- if (ret) -- break; -- pinned = i + 1; -- reloc_index += exec_list[i].relocation_count; -- } -- /* success */ -- if (ret == 0) -- break; -- -- /* error other than GTT full, or we've already tried again */ -- if (ret != -ENOSPC || pin_tries >= 1) { -- if (ret != -ERESTARTSYS) { -- unsigned long long total_size = 0; -- int num_fences = 0; -- for (i = 0; i < args->buffer_count; i++) { -- obj_priv = to_intel_bo(object_list[i]); -- -- total_size += object_list[i]->size; -- num_fences += -- exec_list[i].flags & EXEC_OBJECT_NEEDS_FENCE && -- obj_priv->tiling_mode != I915_TILING_NONE; -- } -- DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes, %d fences: %d\n", -- pinned+1, args->buffer_count, -- total_size, num_fences, -- ret); -- DRM_ERROR("%d objects [%d pinned], " -- "%d object bytes [%d pinned], " -- "%d/%d gtt bytes\n", -- atomic_read(&dev->object_count), -- atomic_read(&dev->pin_count), -- atomic_read(&dev->object_memory), -- atomic_read(&dev->pin_memory), -- atomic_read(&dev->gtt_memory), -- dev->gtt_total); -- } -- goto err; -- } -- -- /* unpin all of our buffers */ -- for (i = 0; i < pinned; i++) -- i915_gem_object_unpin(object_list[i]); -- pinned = 0; -+ /* Move the objects en-masse into the GTT, evicting if necessary. */ -+ ret = i915_gem_execbuffer_pin(dev, file, -+ object_list, exec_list, -+ args->buffer_count); -+ if (ret) -+ goto err; - -- /* evict everyone we can from the aperture */ -- ret = i915_gem_evict_everything(dev); -- if (ret && ret != -ENOSPC) -+ /* The objects are in their final locations, apply the relocations. */ -+ for (i = 0; i < args->buffer_count; i++) { -+ struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); -+ obj->base.pending_read_domains = 0; -+ obj->base.pending_write_domain = 0; -+ ret = i915_gem_execbuffer_relocate(obj, file, &exec_list[i]); -+ if (ret) - goto err; - } - -@@ -3735,72 +3795,28 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - } - batch_obj->pending_read_domains |= I915_GEM_DOMAIN_COMMAND; - -- /* Sanity check the batch buffer, prior to moving objects */ -- exec_offset = exec_list[args->buffer_count - 1].offset; -- ret = i915_gem_check_execbuffer (args, exec_offset); -+ /* Sanity check the batch buffer */ -+ exec_offset = to_intel_bo(batch_obj)->gtt_offset; -+ ret = i915_gem_check_execbuffer(args, exec_offset); - if (ret != 0) { - DRM_ERROR("execbuf with invalid offset/length\n"); - goto err; - } - -- i915_verify_inactive(dev, __FILE__, __LINE__); -- -- /* Zero the global flush/invalidate flags. These -- * will be modified as new domains are computed -- * for each object -- */ -- dev->invalidate_domains = 0; -- dev->flush_domains = 0; -- dev_priv->flush_rings = 0; -- -- for (i = 0; i < args->buffer_count; i++) { -- struct drm_gem_object *obj = object_list[i]; -- -- /* Compute new gpu domains and update invalidate/flush */ -- i915_gem_object_set_to_gpu_domain(obj); -- } -- -- i915_verify_inactive(dev, __FILE__, __LINE__); -- -- if (dev->invalidate_domains | dev->flush_domains) { --#if WATCH_EXEC -- DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", -- __func__, -- dev->invalidate_domains, -- dev->flush_domains); --#endif -- i915_gem_flush(dev, -- dev->invalidate_domains, -- dev->flush_domains); -- if (dev_priv->flush_rings & FLUSH_RENDER_RING) -- (void)i915_add_request(dev, file_priv, -- dev->flush_domains, -- &dev_priv->render_ring); -- if (dev_priv->flush_rings & FLUSH_BSD_RING) -- (void)i915_add_request(dev, file_priv, -- dev->flush_domains, -- &dev_priv->bsd_ring); -- } -+ ret = i915_gem_execbuffer_move_to_gpu(dev, file, ring, -+ object_list, args->buffer_count); -+ if (ret) -+ goto err; - - for (i = 0; i < args->buffer_count; i++) { - struct drm_gem_object *obj = object_list[i]; -- struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - uint32_t old_write_domain = obj->write_domain; -- - obj->write_domain = obj->pending_write_domain; -- if (obj->write_domain) -- list_move_tail(&obj_priv->gpu_write_list, -- &dev_priv->mm.gpu_write_list); -- else -- list_del_init(&obj_priv->gpu_write_list); -- - trace_i915_gem_object_change_domain(obj, - obj->read_domains, - old_write_domain); - } - -- i915_verify_inactive(dev, __FILE__, __LINE__); -- - #if WATCH_COHERENCY - for (i = 0; i < args->buffer_count; i++) { - i915_gem_object_check_coherency(object_list[i], -@@ -3815,9 +3831,38 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - ~0); - #endif - -+ /* Check for any pending flips. As we only maintain a flip queue depth -+ * of 1, we can simply insert a WAIT for the next display flip prior -+ * to executing the batch and avoid stalling the CPU. -+ */ -+ flips = 0; -+ for (i = 0; i < args->buffer_count; i++) { -+ if (object_list[i]->write_domain) -+ flips |= atomic_read(&to_intel_bo(object_list[i])->pending_flip); -+ } -+ if (flips) { -+ int plane, flip_mask; -+ -+ for (plane = 0; flips >> plane; plane++) { -+ if (((flips >> plane) & 1) == 0) -+ continue; -+ -+ if (plane) -+ flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; -+ else -+ flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; -+ -+ intel_ring_begin(dev, ring, 2); -+ intel_ring_emit(dev, ring, -+ MI_WAIT_FOR_EVENT | flip_mask); -+ intel_ring_emit(dev, ring, MI_NOOP); -+ intel_ring_advance(dev, ring); -+ } -+ } -+ - /* Exec the batchbuffer */ - ret = ring->dispatch_gem_execbuffer(dev, ring, args, -- cliprects, exec_offset); -+ cliprects, exec_offset); - if (ret) { - DRM_ERROR("dispatch failed %d\n", ret); - goto err; -@@ -3827,38 +3872,21 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - * Ensure that the commands in the batch buffer are - * finished before the interrupt fires - */ -- flush_domains = i915_retire_commands(dev, ring); -- -- i915_verify_inactive(dev, __FILE__, __LINE__); -+ i915_retire_commands(dev, ring); - -- /* -- * Get a seqno representing the execution of the current buffer, -- * which we can wait on. We would like to mitigate these interrupts, -- * likely by only creating seqnos occasionally (so that we have -- * *some* interrupts representing completion of buffers that we can -- * wait on when trying to clear up gtt space). -- */ -- seqno = i915_add_request(dev, file_priv, flush_domains, ring); -- BUG_ON(seqno == 0); - for (i = 0; i < args->buffer_count; i++) { - struct drm_gem_object *obj = object_list[i]; -- obj_priv = to_intel_bo(obj); - -- i915_gem_object_move_to_active(obj, seqno, ring); --#if WATCH_LRU -- DRM_INFO("%s: move to exec list %p\n", __func__, obj); --#endif -+ i915_gem_object_move_to_active(obj, ring); -+ if (obj->write_domain) -+ list_move_tail(&to_intel_bo(obj)->gpu_write_list, -+ &ring->gpu_write_list); - } --#if WATCH_LRU -- i915_dump_lru(dev, __func__); --#endif - -- i915_verify_inactive(dev, __FILE__, __LINE__); -+ i915_add_request(dev, file, request, ring); -+ request = NULL; - - err: -- for (i = 0; i < pinned; i++) -- i915_gem_object_unpin(object_list[i]); -- - for (i = 0; i < args->buffer_count; i++) { - if (object_list[i]) { - obj_priv = to_intel_bo(object_list[i]); -@@ -3870,22 +3898,9 @@ err: - mutex_unlock(&dev->struct_mutex); - - pre_mutex_err: -- /* Copy the updated relocations out regardless of current error -- * state. Failure to update the relocs would mean that the next -- * time userland calls execbuf, it would do so with presumed offset -- * state that didn't match the actual object state. -- */ -- ret2 = i915_gem_put_relocs_to_user(exec_list, args->buffer_count, -- relocs); -- if (ret2 != 0) { -- DRM_ERROR("Failed to copy relocations back out: %d\n", ret2); -- -- if (ret == 0) -- ret = ret2; -- } -- - drm_free_large(object_list); - kfree(cliprects); -+ kfree(request); - - return ret; - } -@@ -3942,7 +3957,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, - exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; - exec2_list[i].alignment = exec_list[i].alignment; - exec2_list[i].offset = exec_list[i].offset; -- if (!IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen < 4) - exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; - else - exec2_list[i].flags = 0; -@@ -4039,12 +4054,12 @@ int - i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) - { - struct drm_device *dev = obj->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int ret; - - BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); -- -- i915_verify_inactive(dev, __FILE__, __LINE__); -+ WARN_ON(i915_verify_lists(dev)); - - if (obj_priv->gtt_space != NULL) { - if (alignment == 0) -@@ -4072,14 +4087,13 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) - * remove it from the inactive list - */ - if (obj_priv->pin_count == 1) { -- atomic_inc(&dev->pin_count); -- atomic_add(obj->size, &dev->pin_memory); -- if (!obj_priv->active && -- (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) -- list_del_init(&obj_priv->list); -+ i915_gem_info_add_pin(dev_priv, obj->size); -+ if (!obj_priv->active) -+ list_move_tail(&obj_priv->mm_list, -+ &dev_priv->mm.pinned_list); - } -- i915_verify_inactive(dev, __FILE__, __LINE__); - -+ WARN_ON(i915_verify_lists(dev)); - return 0; - } - -@@ -4090,7 +4104,7 @@ i915_gem_object_unpin(struct drm_gem_object *obj) - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - -- i915_verify_inactive(dev, __FILE__, __LINE__); -+ WARN_ON(i915_verify_lists(dev)); - obj_priv->pin_count--; - BUG_ON(obj_priv->pin_count < 0); - BUG_ON(obj_priv->gtt_space == NULL); -@@ -4100,14 +4114,12 @@ i915_gem_object_unpin(struct drm_gem_object *obj) - * the inactive list - */ - if (obj_priv->pin_count == 0) { -- if (!obj_priv->active && -- (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) -- list_move_tail(&obj_priv->list, -+ if (!obj_priv->active) -+ list_move_tail(&obj_priv->mm_list, - &dev_priv->mm.inactive_list); -- atomic_dec(&dev->pin_count); -- atomic_sub(obj->size, &dev->pin_memory); -+ i915_gem_info_remove_pin(dev_priv, obj->size); - } -- i915_verify_inactive(dev, __FILE__, __LINE__); -+ WARN_ON(i915_verify_lists(dev)); - } - - int -@@ -4119,41 +4131,36 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, - struct drm_i915_gem_object *obj_priv; - int ret; - -- mutex_lock(&dev->struct_mutex); -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) { -- DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", -- args->handle); -- mutex_unlock(&dev->struct_mutex); -- return -ENOENT; -+ ret = -ENOENT; -+ goto unlock; - } - obj_priv = to_intel_bo(obj); - - if (obj_priv->madv != I915_MADV_WILLNEED) { - DRM_ERROR("Attempting to pin a purgeable buffer\n"); -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - - if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { - DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", - args->handle); -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - - obj_priv->user_pin_count++; - obj_priv->pin_filp = file_priv; - if (obj_priv->user_pin_count == 1) { - ret = i915_gem_object_pin(obj, args->alignment); -- if (ret != 0) { -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- return ret; -- } -+ if (ret) -+ goto out; - } - - /* XXX - flush the CPU caches for pinned objects -@@ -4161,10 +4168,11 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, - */ - i915_gem_object_flush_cpu_write_domain(obj); - args->offset = obj_priv->gtt_offset; -+out: - drm_gem_object_unreference(obj); -+unlock: - mutex_unlock(&dev->struct_mutex); -- -- return 0; -+ return ret; - } - - int -@@ -4174,24 +4182,24 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, - struct drm_i915_gem_pin *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; -+ int ret; - -- mutex_lock(&dev->struct_mutex); -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) { -- DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", -- args->handle); -- mutex_unlock(&dev->struct_mutex); -- return -ENOENT; -+ ret = -ENOENT; -+ goto unlock; - } -- - obj_priv = to_intel_bo(obj); -+ - if (obj_priv->pin_filp != file_priv) { - DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", - args->handle); -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - obj_priv->user_pin_count--; - if (obj_priv->user_pin_count == 0) { -@@ -4199,9 +4207,11 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, - i915_gem_object_unpin(obj); - } - -+out: - drm_gem_object_unreference(obj); -+unlock: - mutex_unlock(&dev->struct_mutex); -- return 0; -+ return ret; - } - - int -@@ -4211,22 +4221,24 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, - struct drm_i915_gem_busy *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; -+ int ret; -+ -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) { -- DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", -- args->handle); -- return -ENOENT; -+ ret = -ENOENT; -+ goto unlock; - } -- -- mutex_lock(&dev->struct_mutex); -+ obj_priv = to_intel_bo(obj); - - /* Count all active objects as busy, even if they are currently not used - * by the gpu. Users of this interface expect objects to eventually - * become non-busy without any further actions, therefore emit any - * necessary flushes here. - */ -- obj_priv = to_intel_bo(obj); - args->busy = obj_priv->active; - if (args->busy) { - /* Unconditionally flush objects, even when the gpu still uses this -@@ -4234,10 +4246,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, - * use this buffer rather sooner than later, so issuing the required - * flush earlier is beneficial. - */ -- if (obj->write_domain) { -- i915_gem_flush(dev, 0, obj->write_domain); -- (void)i915_add_request(dev, file_priv, obj->write_domain, obj_priv->ring); -- } -+ if (obj->write_domain & I915_GEM_GPU_DOMAINS) -+ i915_gem_flush_ring(dev, file_priv, -+ obj_priv->ring, -+ 0, obj->write_domain); - - /* Update the active list for the hardware's current position. - * Otherwise this only updates on a delayed timer or when irqs -@@ -4250,8 +4262,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, - } - - drm_gem_object_unreference(obj); -+unlock: - mutex_unlock(&dev->struct_mutex); -- return 0; -+ return ret; - } - - int -@@ -4268,6 +4281,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, - struct drm_i915_gem_madvise *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; -+ int ret; - - switch (args->madv) { - case I915_MADV_DONTNEED: -@@ -4277,22 +4291,20 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, - return -EINVAL; - } - -+ ret = i915_mutex_lock_interruptible(dev); -+ if (ret) -+ return ret; -+ - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) { -- DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n", -- args->handle); -- return -ENOENT; -+ ret = -ENOENT; -+ goto unlock; - } -- -- mutex_lock(&dev->struct_mutex); - obj_priv = to_intel_bo(obj); - - if (obj_priv->pin_count) { -- drm_gem_object_unreference(obj); -- mutex_unlock(&dev->struct_mutex); -- -- DRM_ERROR("Attempted i915_gem_madvise_ioctl() on a pinned object\n"); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - - if (obj_priv->madv != __I915_MADV_PURGED) -@@ -4305,15 +4317,17 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, - - args->retained = obj_priv->madv != __I915_MADV_PURGED; - -+out: - drm_gem_object_unreference(obj); -+unlock: - mutex_unlock(&dev->struct_mutex); -- -- return 0; -+ return ret; - } - - struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, - size_t size) - { -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj; - - obj = kzalloc(sizeof(*obj), GFP_KERNEL); -@@ -4325,18 +4339,19 @@ struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, - return NULL; - } - -+ i915_gem_info_add_obj(dev_priv, size); -+ - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - - obj->agp_type = AGP_USER_MEMORY; - obj->base.driver_private = NULL; - obj->fence_reg = I915_FENCE_REG_NONE; -- INIT_LIST_HEAD(&obj->list); -+ INIT_LIST_HEAD(&obj->mm_list); -+ INIT_LIST_HEAD(&obj->ring_list); - INIT_LIST_HEAD(&obj->gpu_write_list); - obj->madv = I915_MADV_WILLNEED; - -- trace_i915_gem_object_create(&obj->base); -- - return &obj->base; - } - -@@ -4356,7 +4371,7 @@ static void i915_gem_free_object_tail(struct drm_gem_object *obj) - - ret = i915_gem_object_unbind(obj); - if (ret == -ERESTARTSYS) { -- list_move(&obj_priv->list, -+ list_move(&obj_priv->mm_list, - &dev_priv->mm.deferred_free_list); - return; - } -@@ -4365,6 +4380,7 @@ static void i915_gem_free_object_tail(struct drm_gem_object *obj) - i915_gem_free_mmap_offset(obj); - - drm_gem_object_release(obj); -+ i915_gem_info_remove_obj(dev_priv, obj->size); - - kfree(obj_priv->page_cpu_valid); - kfree(obj_priv->bit_17); -@@ -4395,10 +4411,7 @@ i915_gem_idle(struct drm_device *dev) - - mutex_lock(&dev->struct_mutex); - -- if (dev_priv->mm.suspended || -- (dev_priv->render_ring.gem_object == NULL) || -- (HAS_BSD(dev) && -- dev_priv->bsd_ring.gem_object == NULL)) { -+ if (dev_priv->mm.suspended) { - mutex_unlock(&dev->struct_mutex); - return 0; - } -@@ -4423,7 +4436,7 @@ i915_gem_idle(struct drm_device *dev) - * And not confound mm.suspended! - */ - dev_priv->mm.suspended = 1; -- del_timer(&dev_priv->hangcheck_timer); -+ del_timer_sync(&dev_priv->hangcheck_timer); - - i915_kernel_lost_context(dev); - i915_gem_cleanup_ringbuffer(dev); -@@ -4503,36 +4516,34 @@ i915_gem_init_ringbuffer(struct drm_device *dev) - drm_i915_private_t *dev_priv = dev->dev_private; - int ret; - -- dev_priv->render_ring = render_ring; -- -- if (!I915_NEED_GFX_HWS(dev)) { -- dev_priv->render_ring.status_page.page_addr -- = dev_priv->status_page_dmah->vaddr; -- memset(dev_priv->render_ring.status_page.page_addr, -- 0, PAGE_SIZE); -- } -- - if (HAS_PIPE_CONTROL(dev)) { - ret = i915_gem_init_pipe_control(dev); - if (ret) - return ret; - } - -- ret = intel_init_ring_buffer(dev, &dev_priv->render_ring); -+ ret = intel_init_render_ring_buffer(dev); - if (ret) - goto cleanup_pipe_control; - - if (HAS_BSD(dev)) { -- dev_priv->bsd_ring = bsd_ring; -- ret = intel_init_ring_buffer(dev, &dev_priv->bsd_ring); -+ ret = intel_init_bsd_ring_buffer(dev); - if (ret) - goto cleanup_render_ring; - } - -+ if (HAS_BLT(dev)) { -+ ret = intel_init_blt_ring_buffer(dev); -+ if (ret) -+ goto cleanup_bsd_ring; -+ } -+ - dev_priv->next_seqno = 1; - - return 0; - -+cleanup_bsd_ring: -+ intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); - cleanup_render_ring: - intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); - cleanup_pipe_control: -@@ -4547,8 +4558,8 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) - drm_i915_private_t *dev_priv = dev->dev_private; - - intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); -- if (HAS_BSD(dev)) -- intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); -+ intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); -+ intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring); - if (HAS_PIPE_CONTROL(dev)) - i915_gem_cleanup_pipe_control(dev); - } -@@ -4577,15 +4588,15 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, - return ret; - } - -- spin_lock(&dev_priv->mm.active_list_lock); -+ BUG_ON(!list_empty(&dev_priv->mm.active_list)); - BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); -- BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list)); -- spin_unlock(&dev_priv->mm.active_list_lock); -- -+ BUG_ON(!list_empty(&dev_priv->bsd_ring.active_list)); -+ BUG_ON(!list_empty(&dev_priv->blt_ring.active_list)); - BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); - BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); - BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); -- BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list)); -+ BUG_ON(!list_empty(&dev_priv->bsd_ring.request_list)); -+ BUG_ON(!list_empty(&dev_priv->blt_ring.request_list)); - mutex_unlock(&dev->struct_mutex); - - ret = drm_irq_install(dev); -@@ -4627,28 +4638,34 @@ i915_gem_lastclose(struct drm_device *dev) - DRM_ERROR("failed to idle hardware: %d\n", ret); - } - -+static void -+init_ring_lists(struct intel_ring_buffer *ring) -+{ -+ INIT_LIST_HEAD(&ring->active_list); -+ INIT_LIST_HEAD(&ring->request_list); -+ INIT_LIST_HEAD(&ring->gpu_write_list); -+} -+ - void - i915_gem_load(struct drm_device *dev) - { - int i; - drm_i915_private_t *dev_priv = dev->dev_private; - -- spin_lock_init(&dev_priv->mm.active_list_lock); -+ INIT_LIST_HEAD(&dev_priv->mm.active_list); - INIT_LIST_HEAD(&dev_priv->mm.flushing_list); -- INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); - INIT_LIST_HEAD(&dev_priv->mm.inactive_list); -+ INIT_LIST_HEAD(&dev_priv->mm.pinned_list); - INIT_LIST_HEAD(&dev_priv->mm.fence_list); - INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list); -- INIT_LIST_HEAD(&dev_priv->render_ring.active_list); -- INIT_LIST_HEAD(&dev_priv->render_ring.request_list); -- if (HAS_BSD(dev)) { -- INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list); -- INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list); -- } -+ init_ring_lists(&dev_priv->render_ring); -+ init_ring_lists(&dev_priv->bsd_ring); -+ init_ring_lists(&dev_priv->blt_ring); - for (i = 0; i < 16; i++) - INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); - INIT_DELAYED_WORK(&dev_priv->mm.retire_work, - i915_gem_retire_work_handler); -+ init_completion(&dev_priv->error_completion); - spin_lock(&shrink_list_lock); - list_add(&dev_priv->mm.shrink_list, &shrink_list); - spin_unlock(&shrink_list_lock); -@@ -4667,21 +4684,30 @@ i915_gem_load(struct drm_device *dev) - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - dev_priv->fence_reg_start = 3; - -- if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) -+ if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) - dev_priv->num_fence_regs = 16; - else - dev_priv->num_fence_regs = 8; - - /* Initialize fence registers to zero */ -- if (IS_I965G(dev)) { -+ switch (INTEL_INFO(dev)->gen) { -+ case 6: -+ for (i = 0; i < 16; i++) -+ I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), 0); -+ break; -+ case 5: -+ case 4: - for (i = 0; i < 16; i++) - I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); -- } else { -- for (i = 0; i < 8; i++) -- I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); -+ break; -+ case 3: - if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) - for (i = 0; i < 8; i++) - I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); -+ case 2: -+ for (i = 0; i < 8; i++) -+ I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); -+ break; - } - i915_gem_detect_bit_6_swizzle(dev); - init_waitqueue_head(&dev_priv->pending_flip_queue); -@@ -4691,8 +4717,8 @@ i915_gem_load(struct drm_device *dev) - * Create a physically contiguous memory object for this object - * e.g. for cursor + overlay regs - */ --int i915_gem_init_phys_object(struct drm_device *dev, -- int id, int size, int align) -+static int i915_gem_init_phys_object(struct drm_device *dev, -+ int id, int size, int align) - { - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_phys_object *phys_obj; -@@ -4724,7 +4750,7 @@ kfree_obj: - return ret; - } - --void i915_gem_free_phys_object(struct drm_device *dev, int id) -+static void i915_gem_free_phys_object(struct drm_device *dev, int id) - { - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_phys_object *phys_obj; -@@ -4853,34 +4879,48 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, - struct drm_file *file_priv) - { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -- void *obj_addr; -- int ret; -- char __user *user_data; -+ void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset; -+ char __user *user_data = (char __user *) (uintptr_t) args->data_ptr; - -- user_data = (char __user *) (uintptr_t) args->data_ptr; -- obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; -+ DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size); - -- DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size); -- ret = copy_from_user(obj_addr, user_data, args->size); -- if (ret) -- return -EFAULT; -+ if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { -+ unsigned long unwritten; -+ -+ /* The physical object once assigned is fixed for the lifetime -+ * of the obj, so we can safely drop the lock and continue -+ * to access vaddr. -+ */ -+ mutex_unlock(&dev->struct_mutex); -+ unwritten = copy_from_user(vaddr, user_data, args->size); -+ mutex_lock(&dev->struct_mutex); -+ if (unwritten) -+ return -EFAULT; -+ } - - drm_agp_chipset_flush(dev); - return 0; - } - --void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv) -+void i915_gem_release(struct drm_device *dev, struct drm_file *file) - { -- struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; -+ struct drm_i915_file_private *file_priv = file->driver_priv; - - /* Clean up our request list when the client is going away, so that - * later retire_requests won't dereference our soon-to-be-gone - * file_priv. - */ -- mutex_lock(&dev->struct_mutex); -- while (!list_empty(&i915_file_priv->mm.request_list)) -- list_del_init(i915_file_priv->mm.request_list.next); -- mutex_unlock(&dev->struct_mutex); -+ spin_lock(&file_priv->mm.lock); -+ while (!list_empty(&file_priv->mm.request_list)) { -+ struct drm_i915_gem_request *request; -+ -+ request = list_first_entry(&file_priv->mm.request_list, -+ struct drm_i915_gem_request, -+ client_list); -+ list_del(&request->client_list); -+ request->file_priv = NULL; -+ } -+ spin_unlock(&file_priv->mm.lock); - } - - static int -@@ -4889,12 +4929,8 @@ i915_gpu_is_active(struct drm_device *dev) - drm_i915_private_t *dev_priv = dev->dev_private; - int lists_empty; - -- spin_lock(&dev_priv->mm.active_list_lock); - lists_empty = list_empty(&dev_priv->mm.flushing_list) && -- list_empty(&dev_priv->render_ring.active_list); -- if (HAS_BSD(dev)) -- lists_empty &= list_empty(&dev_priv->bsd_ring.active_list); -- spin_unlock(&dev_priv->mm.active_list_lock); -+ list_empty(&dev_priv->mm.active_list); - - return !lists_empty; - } -@@ -4916,7 +4952,7 @@ i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) - if (mutex_trylock(&dev->struct_mutex)) { - list_for_each_entry(obj_priv, - &dev_priv->mm.inactive_list, -- list) -+ mm_list) - cnt++; - mutex_unlock(&dev->struct_mutex); - } -@@ -4942,7 +4978,7 @@ rescan: - - list_for_each_entry_safe(obj_priv, next_obj, - &dev_priv->mm.inactive_list, -- list) { -+ mm_list) { - if (i915_gem_object_is_purgeable(obj_priv)) { - i915_gem_object_unbind(&obj_priv->base); - if (--nr_to_scan <= 0) -@@ -4971,7 +5007,7 @@ rescan: - - list_for_each_entry_safe(obj_priv, next_obj, - &dev_priv->mm.inactive_list, -- list) { -+ mm_list) { - if (nr_to_scan > 0) { - i915_gem_object_unbind(&obj_priv->base); - nr_to_scan--; -diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c -index 80f380b..48644b8 100644 ---- a/drivers/gpu/drm/i915/i915_gem_debug.c -+++ b/drivers/gpu/drm/i915/i915_gem_debug.c -@@ -30,29 +30,112 @@ - #include "i915_drm.h" - #include "i915_drv.h" - --#if WATCH_INACTIVE --void --i915_verify_inactive(struct drm_device *dev, char *file, int line) -+#if WATCH_LISTS -+int -+i915_verify_lists(struct drm_device *dev) - { -+ static int warned; - drm_i915_private_t *dev_priv = dev->dev_private; -- struct drm_gem_object *obj; -- struct drm_i915_gem_object *obj_priv; -- -- list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { -- obj = &obj_priv->base; -- if (obj_priv->pin_count || obj_priv->active || -- (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | -- I915_GEM_DOMAIN_GTT))) -- DRM_ERROR("inactive %p (p %d a %d w %x) %s:%d\n", -+ struct drm_i915_gem_object *obj; -+ int err = 0; -+ -+ if (warned) -+ return 0; -+ -+ list_for_each_entry(obj, &dev_priv->render_ring.active_list, list) { -+ if (obj->base.dev != dev || -+ !atomic_read(&obj->base.refcount.refcount)) { -+ DRM_ERROR("freed render active %p\n", obj); -+ err++; -+ break; -+ } else if (!obj->active || -+ (obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0) { -+ DRM_ERROR("invalid render active %p (a %d r %x)\n", -+ obj, -+ obj->active, -+ obj->base.read_domains); -+ err++; -+ } else if (obj->base.write_domain && list_empty(&obj->gpu_write_list)) { -+ DRM_ERROR("invalid render active %p (w %x, gwl %d)\n", -+ obj, -+ obj->base.write_domain, -+ !list_empty(&obj->gpu_write_list)); -+ err++; -+ } -+ } -+ -+ list_for_each_entry(obj, &dev_priv->mm.flushing_list, list) { -+ if (obj->base.dev != dev || -+ !atomic_read(&obj->base.refcount.refcount)) { -+ DRM_ERROR("freed flushing %p\n", obj); -+ err++; -+ break; -+ } else if (!obj->active || -+ (obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0 || -+ list_empty(&obj->gpu_write_list)){ -+ DRM_ERROR("invalid flushing %p (a %d w %x gwl %d)\n", - obj, -- obj_priv->pin_count, obj_priv->active, -- obj->write_domain, file, line); -+ obj->active, -+ obj->base.write_domain, -+ !list_empty(&obj->gpu_write_list)); -+ err++; -+ } -+ } -+ -+ list_for_each_entry(obj, &dev_priv->mm.gpu_write_list, gpu_write_list) { -+ if (obj->base.dev != dev || -+ !atomic_read(&obj->base.refcount.refcount)) { -+ DRM_ERROR("freed gpu write %p\n", obj); -+ err++; -+ break; -+ } else if (!obj->active || -+ (obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) { -+ DRM_ERROR("invalid gpu write %p (a %d w %x)\n", -+ obj, -+ obj->active, -+ obj->base.write_domain); -+ err++; -+ } -+ } -+ -+ list_for_each_entry(obj, &dev_priv->mm.inactive_list, list) { -+ if (obj->base.dev != dev || -+ !atomic_read(&obj->base.refcount.refcount)) { -+ DRM_ERROR("freed inactive %p\n", obj); -+ err++; -+ break; -+ } else if (obj->pin_count || obj->active || -+ (obj->base.write_domain & I915_GEM_GPU_DOMAINS)) { -+ DRM_ERROR("invalid inactive %p (p %d a %d w %x)\n", -+ obj, -+ obj->pin_count, obj->active, -+ obj->base.write_domain); -+ err++; -+ } - } -+ -+ list_for_each_entry(obj, &dev_priv->mm.pinned_list, list) { -+ if (obj->base.dev != dev || -+ !atomic_read(&obj->base.refcount.refcount)) { -+ DRM_ERROR("freed pinned %p\n", obj); -+ err++; -+ break; -+ } else if (!obj->pin_count || obj->active || -+ (obj->base.write_domain & I915_GEM_GPU_DOMAINS)) { -+ DRM_ERROR("invalid pinned %p (p %d a %d w %x)\n", -+ obj, -+ obj->pin_count, obj->active, -+ obj->base.write_domain); -+ err++; -+ } -+ } -+ -+ return warned = err; - } - #endif /* WATCH_INACTIVE */ - - --#if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE -+#if WATCH_EXEC | WATCH_PWRITE - static void - i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end, - uint32_t bias, uint32_t mark) -@@ -97,41 +180,6 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len, - } - #endif - --#if WATCH_LRU --void --i915_dump_lru(struct drm_device *dev, const char *where) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- struct drm_i915_gem_object *obj_priv; -- -- DRM_INFO("active list %s {\n", where); -- spin_lock(&dev_priv->mm.active_list_lock); -- list_for_each_entry(obj_priv, &dev_priv->mm.active_list, -- list) -- { -- DRM_INFO(" %p: %08x\n", obj_priv, -- obj_priv->last_rendering_seqno); -- } -- spin_unlock(&dev_priv->mm.active_list_lock); -- DRM_INFO("}\n"); -- DRM_INFO("flushing list %s {\n", where); -- list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, -- list) -- { -- DRM_INFO(" %p: %08x\n", obj_priv, -- obj_priv->last_rendering_seqno); -- } -- DRM_INFO("}\n"); -- DRM_INFO("inactive %s {\n", where); -- list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { -- DRM_INFO(" %p: %08x\n", obj_priv, -- obj_priv->last_rendering_seqno); -- } -- DRM_INFO("}\n"); --} --#endif -- -- - #if WATCH_COHERENCY - void - i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) -diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c -index 5c428fa..d8ae7d1 100644 ---- a/drivers/gpu/drm/i915/i915_gem_evict.c -+++ b/drivers/gpu/drm/i915/i915_gem_evict.c -@@ -31,49 +31,6 @@ - #include "i915_drv.h" - #include "i915_drm.h" - --static struct drm_i915_gem_object * --i915_gem_next_active_object(struct drm_device *dev, -- struct list_head **render_iter, -- struct list_head **bsd_iter) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- struct drm_i915_gem_object *render_obj = NULL, *bsd_obj = NULL; -- -- if (*render_iter != &dev_priv->render_ring.active_list) -- render_obj = list_entry(*render_iter, -- struct drm_i915_gem_object, -- list); -- -- if (HAS_BSD(dev)) { -- if (*bsd_iter != &dev_priv->bsd_ring.active_list) -- bsd_obj = list_entry(*bsd_iter, -- struct drm_i915_gem_object, -- list); -- -- if (render_obj == NULL) { -- *bsd_iter = (*bsd_iter)->next; -- return bsd_obj; -- } -- -- if (bsd_obj == NULL) { -- *render_iter = (*render_iter)->next; -- return render_obj; -- } -- -- /* XXX can we handle seqno wrapping? */ -- if (render_obj->last_rendering_seqno < bsd_obj->last_rendering_seqno) { -- *render_iter = (*render_iter)->next; -- return render_obj; -- } else { -- *bsd_iter = (*bsd_iter)->next; -- return bsd_obj; -- } -- } else { -- *render_iter = (*render_iter)->next; -- return render_obj; -- } --} -- - static bool - mark_free(struct drm_i915_gem_object *obj_priv, - struct list_head *unwind) -@@ -83,18 +40,12 @@ mark_free(struct drm_i915_gem_object *obj_priv, - return drm_mm_scan_add_block(obj_priv->gtt_space); - } - --#define i915_for_each_active_object(OBJ, R, B) \ -- *(R) = dev_priv->render_ring.active_list.next; \ -- *(B) = dev_priv->bsd_ring.active_list.next; \ -- while (((OBJ) = i915_gem_next_active_object(dev, (R), (B))) != NULL) -- - int - i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment) - { - drm_i915_private_t *dev_priv = dev->dev_private; - struct list_head eviction_list, unwind_list; - struct drm_i915_gem_object *obj_priv; -- struct list_head *render_iter, *bsd_iter; - int ret = 0; - - i915_gem_retire_requests(dev); -@@ -131,13 +82,13 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen - drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment); - - /* First see if there is a large enough contiguous idle region... */ -- list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, mm_list) { - if (mark_free(obj_priv, &unwind_list)) - goto found; - } - - /* Now merge in the soon-to-be-expired objects... */ -- i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - /* Does the object require an outstanding flush? */ - if (obj_priv->base.write_domain || obj_priv->pin_count) - continue; -@@ -147,14 +98,14 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen - } - - /* Finally add anything with a pending flush (in order of retirement) */ -- list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, list) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, mm_list) { - if (obj_priv->pin_count) - continue; - - if (mark_free(obj_priv, &unwind_list)) - goto found; - } -- i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - if (! obj_priv->base.write_domain || obj_priv->pin_count) - continue; - -@@ -212,14 +163,9 @@ i915_gem_evict_everything(struct drm_device *dev) - int ret; - bool lists_empty; - -- spin_lock(&dev_priv->mm.active_list_lock); - lists_empty = (list_empty(&dev_priv->mm.inactive_list) && - list_empty(&dev_priv->mm.flushing_list) && -- list_empty(&dev_priv->render_ring.active_list) && -- (!HAS_BSD(dev) -- || list_empty(&dev_priv->bsd_ring.active_list))); -- spin_unlock(&dev_priv->mm.active_list_lock); -- -+ list_empty(&dev_priv->mm.active_list)); - if (lists_empty) - return -ENOSPC; - -@@ -234,13 +180,9 @@ i915_gem_evict_everything(struct drm_device *dev) - if (ret) - return ret; - -- spin_lock(&dev_priv->mm.active_list_lock); - lists_empty = (list_empty(&dev_priv->mm.inactive_list) && - list_empty(&dev_priv->mm.flushing_list) && -- list_empty(&dev_priv->render_ring.active_list) && -- (!HAS_BSD(dev) -- || list_empty(&dev_priv->bsd_ring.active_list))); -- spin_unlock(&dev_priv->mm.active_list_lock); -+ list_empty(&dev_priv->mm.active_list)); - BUG_ON(!lists_empty); - - return 0; -@@ -258,7 +200,7 @@ i915_gem_evict_inactive(struct drm_device *dev) - - obj = &list_first_entry(&dev_priv->mm.inactive_list, - struct drm_i915_gem_object, -- list)->base; -+ mm_list)->base; - - ret = i915_gem_object_unbind(obj); - if (ret != 0) { -diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c -index 710eca7..af352de 100644 ---- a/drivers/gpu/drm/i915/i915_gem_tiling.c -+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c -@@ -92,13 +92,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) - uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; - uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; - -- if (IS_IRONLAKE(dev) || IS_GEN6(dev)) { -+ if (IS_GEN5(dev) || IS_GEN6(dev)) { - /* On Ironlake whatever DRAM config, GPU always do - * same swizzling setup. - */ - swizzle_x = I915_BIT_6_SWIZZLE_9_10; - swizzle_y = I915_BIT_6_SWIZZLE_9; -- } else if (!IS_I9XX(dev)) { -+ } else if (IS_GEN2(dev)) { - /* As far as we know, the 865 doesn't have these bit 6 - * swizzling issues. - */ -@@ -190,19 +190,19 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) - if (tiling_mode == I915_TILING_NONE) - return true; - -- if (!IS_I9XX(dev) || -+ if (IS_GEN2(dev) || - (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) - tile_width = 128; - else - tile_width = 512; - - /* check maximum stride & object size */ -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - /* i965 stores the end address of the gtt mapping in the fence - * reg, so dont bother to check the size */ - if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) - return false; -- } else if (IS_GEN3(dev) || IS_GEN2(dev)) { -+ } else { - if (stride > 8192) - return false; - -@@ -216,7 +216,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) - } - - /* 965+ just needs multiples of tile width */ -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - if (stride & (tile_width - 1)) - return false; - return true; -@@ -244,16 +244,18 @@ i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode) - if (tiling_mode == I915_TILING_NONE) - return true; - -- if (!IS_I965G(dev)) { -- if (obj_priv->gtt_offset & (obj->size - 1)) -+ if (INTEL_INFO(dev)->gen >= 4) -+ return true; -+ -+ if (obj_priv->gtt_offset & (obj->size - 1)) -+ return false; -+ -+ if (IS_GEN3(dev)) { -+ if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK) -+ return false; -+ } else { -+ if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK) - return false; -- if (IS_I9XX(dev)) { -- if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK) -- return false; -- } else { -- if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK) -- return false; -- } - } - - return true; -@@ -271,7 +273,11 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; -- int ret = 0; -+ int ret; -+ -+ ret = i915_gem_check_is_wedged(dev); -+ if (ret) -+ return ret; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) -@@ -328,7 +334,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, - if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode)) - ret = i915_gem_object_unbind(obj); - else if (obj_priv->fence_reg != I915_FENCE_REG_NONE) -- ret = i915_gem_object_put_fence_reg(obj); -+ ret = i915_gem_object_put_fence_reg(obj, true); - else - i915_gem_release_mmap(obj); - -@@ -399,16 +405,14 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, - * bit 17 of its physical address and therefore being interpreted differently - * by the GPU. - */ --static int -+static void - i915_gem_swizzle_page(struct page *page) - { -+ char temp[64]; - char *vaddr; - int i; -- char temp[64]; - - vaddr = kmap(page); -- if (vaddr == NULL) -- return -ENOMEM; - - for (i = 0; i < PAGE_SIZE; i += 128) { - memcpy(temp, &vaddr[i], 64); -@@ -417,8 +421,6 @@ i915_gem_swizzle_page(struct page *page) - } - - kunmap(page); -- -- return 0; - } - - void -@@ -440,11 +442,7 @@ i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj) - char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17; - if ((new_bit_17 & 0x1) != - (test_bit(i, obj_priv->bit_17) != 0)) { -- int ret = i915_gem_swizzle_page(obj_priv->pages[i]); -- if (ret != 0) { -- DRM_ERROR("Failed to swizzle page\n"); -- return; -- } -+ i915_gem_swizzle_page(obj_priv->pages[i]); - set_page_dirty(obj_priv->pages[i]); - } - } -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index 744225e..237b8bd 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -85,7 +85,7 @@ ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) - } - - /* For display hotplug interrupt */ --void -+static void - ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) - { - if ((dev_priv->irq_mask_reg & mask) != 0) { -@@ -172,7 +172,7 @@ void intel_enable_asle (struct drm_device *dev) - else { - i915_enable_pipestat(dev_priv, 1, - PIPE_LEGACY_BLC_EVENT_ENABLE); -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - i915_enable_pipestat(dev_priv, 0, - PIPE_LEGACY_BLC_EVENT_ENABLE); - } -@@ -191,12 +191,7 @@ static int - i915_pipe_enabled(struct drm_device *dev, int pipe) - { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; -- unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; -- -- if (I915_READ(pipeconf) & PIPEACONF_ENABLE) -- return 1; -- -- return 0; -+ return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE; - } - - /* Called from drm generic code, passed a 'crtc', which -@@ -207,10 +202,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long high_frame; - unsigned long low_frame; -- u32 high1, high2, low, count; -- -- high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; -- low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; -+ u32 high1, high2, low; - - if (!i915_pipe_enabled(dev, pipe)) { - DRM_DEBUG_DRIVER("trying to get vblank count for disabled " -@@ -218,23 +210,23 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) - return 0; - } - -+ high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; -+ low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; -+ - /* - * High & low register fields aren't synchronized, so make sure - * we get a low value that's stable across two reads of the high - * register. - */ - do { -- high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> -- PIPE_FRAME_HIGH_SHIFT); -- low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> -- PIPE_FRAME_LOW_SHIFT); -- high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> -- PIPE_FRAME_HIGH_SHIFT); -+ high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; -+ low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK; -+ high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; - } while (high1 != high2); - -- count = (high1 << 8) | low; -- -- return count; -+ high1 >>= PIPE_FRAME_HIGH_SHIFT; -+ low >>= PIPE_FRAME_LOW_SHIFT; -+ return (high1 << 8) | low; - } - - u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) -@@ -260,16 +252,12 @@ static void i915_hotplug_work_func(struct work_struct *work) - hotplug_work); - struct drm_device *dev = dev_priv->dev; - struct drm_mode_config *mode_config = &dev->mode_config; -- struct drm_encoder *encoder; -- -- if (mode_config->num_encoder) { -- list_for_each_entry(encoder, &mode_config->encoder_list, head) { -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -- -- if (intel_encoder->hot_plug) -- (*intel_encoder->hot_plug) (intel_encoder); -- } -- } -+ struct intel_encoder *encoder; -+ -+ list_for_each_entry(encoder, &mode_config->encoder_list, base.head) -+ if (encoder->hot_plug) -+ encoder->hot_plug(encoder); -+ - /* Just fire off a uevent and let userspace tell us what to do */ - drm_helper_hpd_irq_event(dev); - } -@@ -305,13 +293,30 @@ static void i915_handle_rps_change(struct drm_device *dev) - return; - } - --irqreturn_t ironlake_irq_handler(struct drm_device *dev) -+static void notify_ring(struct drm_device *dev, -+ struct intel_ring_buffer *ring) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 seqno = ring->get_seqno(dev, ring); -+ ring->irq_gem_seqno = seqno; -+ trace_i915_gem_request_complete(dev, seqno); -+ wake_up_all(&ring->irq_queue); -+ dev_priv->hangcheck_count = 0; -+ mod_timer(&dev_priv->hangcheck_timer, -+ jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); -+} -+ -+static irqreturn_t ironlake_irq_handler(struct drm_device *dev) - { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - int ret = IRQ_NONE; - u32 de_iir, gt_iir, de_ier, pch_iir; -+ u32 hotplug_mask; - struct drm_i915_master_private *master_priv; -- struct intel_ring_buffer *render_ring = &dev_priv->render_ring; -+ u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; -+ -+ if (IS_GEN6(dev)) -+ bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; - - /* disable master interrupt before clearing iir */ - de_ier = I915_READ(DEIER); -@@ -325,6 +330,11 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) - if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) - goto done; - -+ if (HAS_PCH_CPT(dev)) -+ hotplug_mask = SDE_HOTPLUG_MASK_CPT; -+ else -+ hotplug_mask = SDE_HOTPLUG_MASK; -+ - ret = IRQ_HANDLED; - - if (dev->primary->master) { -@@ -334,29 +344,24 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) - READ_BREADCRUMB(dev_priv); - } - -- if (gt_iir & GT_PIPE_NOTIFY) { -- u32 seqno = render_ring->get_gem_seqno(dev, render_ring); -- render_ring->irq_gem_seqno = seqno; -- trace_i915_gem_request_complete(dev, seqno); -- DRM_WAKEUP(&dev_priv->render_ring.irq_queue); -- dev_priv->hangcheck_count = 0; -- mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); -- } -- if (gt_iir & GT_BSD_USER_INTERRUPT) -- DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); -- -+ if (gt_iir & GT_PIPE_NOTIFY) -+ notify_ring(dev, &dev_priv->render_ring); -+ if (gt_iir & bsd_usr_interrupt) -+ notify_ring(dev, &dev_priv->bsd_ring); -+ if (HAS_BLT(dev) && gt_iir & GT_BLT_USER_INTERRUPT) -+ notify_ring(dev, &dev_priv->blt_ring); - - if (de_iir & DE_GSE) -- ironlake_opregion_gse_intr(dev); -+ intel_opregion_gse_intr(dev); - - if (de_iir & DE_PLANEA_FLIP_DONE) { - intel_prepare_page_flip(dev, 0); -- intel_finish_page_flip(dev, 0); -+ intel_finish_page_flip_plane(dev, 0); - } - - if (de_iir & DE_PLANEB_FLIP_DONE) { - intel_prepare_page_flip(dev, 1); -- intel_finish_page_flip(dev, 1); -+ intel_finish_page_flip_plane(dev, 1); - } - - if (de_iir & DE_PIPEA_VBLANK) -@@ -366,10 +371,8 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) - drm_handle_vblank(dev, 1); - - /* check event from PCH */ -- if ((de_iir & DE_PCH_EVENT) && -- (pch_iir & SDE_HOTPLUG_MASK)) { -+ if ((de_iir & DE_PCH_EVENT) && (pch_iir & hotplug_mask)) - queue_work(dev_priv->wq, &dev_priv->hotplug_work); -- } - - if (de_iir & DE_PCU_EVENT) { - I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); -@@ -404,23 +407,20 @@ static void i915_error_work_func(struct work_struct *work) - char *reset_event[] = { "RESET=1", NULL }; - char *reset_done_event[] = { "ERROR=0", NULL }; - -- DRM_DEBUG_DRIVER("generating error event\n"); - kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); - - if (atomic_read(&dev_priv->mm.wedged)) { -- if (IS_I965G(dev)) { -- DRM_DEBUG_DRIVER("resetting chip\n"); -- kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); -- if (!i965_reset(dev, GDRST_RENDER)) { -- atomic_set(&dev_priv->mm.wedged, 0); -- kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); -- } -- } else { -- DRM_DEBUG_DRIVER("reboot required\n"); -+ DRM_DEBUG_DRIVER("resetting chip\n"); -+ kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); -+ if (!i915_reset(dev, GRDOM_RENDER)) { -+ atomic_set(&dev_priv->mm.wedged, 0); -+ kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); - } -+ complete_all(&dev_priv->error_completion); - } - } - -+#ifdef CONFIG_DEBUG_FS - static struct drm_i915_error_object * - i915_error_object_create(struct drm_device *dev, - struct drm_gem_object *src) -@@ -511,7 +511,7 @@ i915_get_bbaddr(struct drm_device *dev, u32 *ring) - - if (IS_I830(dev) || IS_845G(dev)) - cmd = MI_BATCH_BUFFER; -- else if (IS_I965G(dev)) -+ else if (INTEL_INFO(dev)->gen >= 4) - cmd = (MI_BATCH_BUFFER_START | (2 << 6) | - MI_BATCH_NON_SECURE_I965); - else -@@ -584,13 +584,16 @@ static void i915_capture_error_state(struct drm_device *dev) - return; - } - -- error->seqno = i915_get_gem_seqno(dev, &dev_priv->render_ring); -+ DRM_DEBUG_DRIVER("generating error event\n"); -+ -+ error->seqno = -+ dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring); - error->eir = I915_READ(EIR); - error->pgtbl_er = I915_READ(PGTBL_ER); - error->pipeastat = I915_READ(PIPEASTAT); - error->pipebstat = I915_READ(PIPEBSTAT); - error->instpm = I915_READ(INSTPM); -- if (!IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen < 4) { - error->ipeir = I915_READ(IPEIR); - error->ipehr = I915_READ(IPEHR); - error->instdone = I915_READ(INSTDONE); -@@ -612,9 +615,7 @@ static void i915_capture_error_state(struct drm_device *dev) - batchbuffer[0] = NULL; - batchbuffer[1] = NULL; - count = 0; -- list_for_each_entry(obj_priv, -- &dev_priv->render_ring.active_list, list) { -- -+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - - if (batchbuffer[0] == NULL && -@@ -631,7 +632,7 @@ static void i915_capture_error_state(struct drm_device *dev) - } - /* Scan the other lists for completeness for those bizarre errors. */ - if (batchbuffer[0] == NULL || batchbuffer[1] == NULL) { -- list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, list) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - - if (batchbuffer[0] == NULL && -@@ -649,7 +650,7 @@ static void i915_capture_error_state(struct drm_device *dev) - } - } - if (batchbuffer[0] == NULL || batchbuffer[1] == NULL) { -- list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - - if (batchbuffer[0] == NULL && -@@ -668,7 +669,7 @@ static void i915_capture_error_state(struct drm_device *dev) - } - - /* We need to copy these to an anonymous buffer as the simplest -- * method to avoid being overwritten by userpace. -+ * method to avoid being overwritten by userspace. - */ - error->batchbuffer[0] = i915_error_object_create(dev, batchbuffer[0]); - if (batchbuffer[1] != batchbuffer[0]) -@@ -690,8 +691,7 @@ static void i915_capture_error_state(struct drm_device *dev) - - if (error->active_bo) { - int i = 0; -- list_for_each_entry(obj_priv, -- &dev_priv->render_ring.active_list, list) { -+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - - error->active_bo[i].size = obj->size; -@@ -744,6 +744,9 @@ void i915_destroy_error_state(struct drm_device *dev) - if (error) - i915_error_state_free(dev, error); - } -+#else -+#define i915_capture_error_state(x) -+#endif - - static void i915_report_and_clear_eir(struct drm_device *dev) - { -@@ -785,7 +788,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) - } - } - -- if (IS_I9XX(dev)) { -+ if (!IS_GEN2(dev)) { - if (eir & I915_ERROR_PAGE_TABLE) { - u32 pgtbl_err = I915_READ(PGTBL_ER); - printk(KERN_ERR "page table error\n"); -@@ -811,7 +814,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) - printk(KERN_ERR "instruction error\n"); - printk(KERN_ERR " INSTPM: 0x%08x\n", - I915_READ(INSTPM)); -- if (!IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen < 4) { - u32 ipeir = I915_READ(IPEIR); - - printk(KERN_ERR " IPEIR: 0x%08x\n", -@@ -876,12 +879,17 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) - i915_report_and_clear_eir(dev); - - if (wedged) { -+ INIT_COMPLETION(dev_priv->error_completion); - atomic_set(&dev_priv->mm.wedged, 1); - - /* - * Wakeup waiting processes so they don't hang - */ -- DRM_WAKEUP(&dev_priv->render_ring.irq_queue); -+ wake_up_all(&dev_priv->render_ring.irq_queue); -+ if (HAS_BSD(dev)) -+ wake_up_all(&dev_priv->bsd_ring.irq_queue); -+ if (HAS_BLT(dev)) -+ wake_up_all(&dev_priv->blt_ring.irq_queue); - } - - queue_work(dev_priv->wq, &dev_priv->error_work); -@@ -912,7 +920,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) - - /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ - obj_priv = to_intel_bo(work->pending_flip_obj); -- if(IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; - stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset; - } else { -@@ -942,7 +950,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) - unsigned long irqflags; - int irq_received; - int ret = IRQ_NONE; -- struct intel_ring_buffer *render_ring = &dev_priv->render_ring; - - atomic_inc(&dev_priv->irq_received); - -@@ -951,7 +958,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) - - iir = I915_READ(IIR); - -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS; - else - vblank_status = PIPE_VBLANK_INTERRUPT_STATUS; -@@ -1019,18 +1026,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) - READ_BREADCRUMB(dev_priv); - } - -- if (iir & I915_USER_INTERRUPT) { -- u32 seqno = -- render_ring->get_gem_seqno(dev, render_ring); -- render_ring->irq_gem_seqno = seqno; -- trace_i915_gem_request_complete(dev, seqno); -- DRM_WAKEUP(&dev_priv->render_ring.irq_queue); -- dev_priv->hangcheck_count = 0; -- mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); -- } -- -+ if (iir & I915_USER_INTERRUPT) -+ notify_ring(dev, &dev_priv->render_ring); - if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) -- DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); -+ notify_ring(dev, &dev_priv->bsd_ring); - - if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { - intel_prepare_page_flip(dev, 0); -@@ -1065,7 +1064,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) - if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || - (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || - (iir & I915_ASLE_INTERRUPT)) -- opregion_asle_intr(dev); -+ intel_opregion_asle_intr(dev); - - /* With MSI, interrupts are only generated when iir - * transitions from zero to nonzero. If another bit got -@@ -1207,18 +1206,15 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) - { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; -- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -- u32 pipeconf; - -- pipeconf = I915_READ(pipeconf_reg); -- if (!(pipeconf & PIPEACONF_ENABLE)) -+ if (!i915_pipe_enabled(dev, pipe)) - return -EINVAL; - - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - if (HAS_PCH_SPLIT(dev)) - ironlake_enable_display_irq(dev_priv, (pipe == 0) ? - DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); -- else if (IS_I965G(dev)) -+ else if (INTEL_INFO(dev)->gen >= 4) - i915_enable_pipestat(dev_priv, pipe, - PIPE_START_VBLANK_INTERRUPT_ENABLE); - else -@@ -1252,7 +1248,7 @@ void i915_enable_interrupt (struct drm_device *dev) - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!HAS_PCH_SPLIT(dev)) -- opregion_enable_asle(dev); -+ intel_opregion_enable_asle(dev); - dev_priv->irq_enabled = 1; - } - -@@ -1311,7 +1307,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, - return -EINVAL; - } - --struct drm_i915_gem_request * -+static struct drm_i915_gem_request * - i915_get_tail_request(struct drm_device *dev) - { - drm_i915_private_t *dev_priv = dev->dev_private; -@@ -1331,11 +1327,7 @@ void i915_hangcheck_elapsed(unsigned long data) - drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t acthd, instdone, instdone1; - -- /* No reset support on this chip yet. */ -- if (IS_GEN6(dev)) -- return; -- -- if (!IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen < 4) { - acthd = I915_READ(ACTHD); - instdone = I915_READ(INSTDONE); - instdone1 = 0; -@@ -1347,9 +1339,8 @@ void i915_hangcheck_elapsed(unsigned long data) - - /* If all work is done then ACTHD clearly hasn't advanced. */ - if (list_empty(&dev_priv->render_ring.request_list) || -- i915_seqno_passed(i915_get_gem_seqno(dev, -- &dev_priv->render_ring), -- i915_get_tail_request(dev)->seqno)) { -+ i915_seqno_passed(dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring), -+ i915_get_tail_request(dev)->seqno)) { - bool missed_wakeup = false; - - dev_priv->hangcheck_count = 0; -@@ -1357,13 +1348,19 @@ void i915_hangcheck_elapsed(unsigned long data) - /* Issue a wake-up to catch stuck h/w. */ - if (dev_priv->render_ring.waiting_gem_seqno && - waitqueue_active(&dev_priv->render_ring.irq_queue)) { -- DRM_WAKEUP(&dev_priv->render_ring.irq_queue); -+ wake_up_all(&dev_priv->render_ring.irq_queue); - missed_wakeup = true; - } - - if (dev_priv->bsd_ring.waiting_gem_seqno && - waitqueue_active(&dev_priv->bsd_ring.irq_queue)) { -- DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); -+ wake_up_all(&dev_priv->bsd_ring.irq_queue); -+ missed_wakeup = true; -+ } -+ -+ if (dev_priv->blt_ring.waiting_gem_seqno && -+ waitqueue_active(&dev_priv->blt_ring.irq_queue)) { -+ wake_up_all(&dev_priv->blt_ring.irq_queue); - missed_wakeup = true; - } - -@@ -1377,6 +1374,21 @@ void i915_hangcheck_elapsed(unsigned long data) - dev_priv->last_instdone1 == instdone1) { - if (dev_priv->hangcheck_count++ > 1) { - DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); -+ -+ if (!IS_GEN2(dev)) { -+ /* Is the chip hanging on a WAIT_FOR_EVENT? -+ * If so we can simply poke the RB_WAIT bit -+ * and break the hang. This should work on -+ * all but the second generation chipsets. -+ */ -+ u32 tmp = I915_READ(PRB0_CTL); -+ if (tmp & RING_WAIT) { -+ I915_WRITE(PRB0_CTL, tmp); -+ POSTING_READ(PRB0_CTL); -+ goto out; -+ } -+ } -+ - i915_handle_error(dev, true); - return; - } -@@ -1388,8 +1400,10 @@ void i915_hangcheck_elapsed(unsigned long data) - dev_priv->last_instdone1 = instdone1; - } - -+out: - /* Reset timer case chip hangs without another request being added */ -- mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); -+ mod_timer(&dev_priv->hangcheck_timer, -+ jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); - } - - /* drm_dma.h hooks -@@ -1424,8 +1438,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) - u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | - DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE; - u32 render_mask = GT_PIPE_NOTIFY | GT_BSD_USER_INTERRUPT; -- u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | -- SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; -+ u32 hotplug_mask; - - dev_priv->irq_mask_reg = ~display_mask; - dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK; -@@ -1436,20 +1449,35 @@ static int ironlake_irq_postinstall(struct drm_device *dev) - I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); - (void) I915_READ(DEIER); - -- /* Gen6 only needs render pipe_control now */ -- if (IS_GEN6(dev)) -- render_mask = GT_PIPE_NOTIFY; -+ if (IS_GEN6(dev)) { -+ render_mask = -+ GT_PIPE_NOTIFY | -+ GT_GEN6_BSD_USER_INTERRUPT | -+ GT_BLT_USER_INTERRUPT; -+ } - - dev_priv->gt_irq_mask_reg = ~render_mask; - dev_priv->gt_irq_enable_reg = render_mask; - - I915_WRITE(GTIIR, I915_READ(GTIIR)); - I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); -- if (IS_GEN6(dev)) -+ if (IS_GEN6(dev)) { - I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); -+ I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT); -+ I915_WRITE(GEN6_BLITTER_IMR, ~GEN6_BLITTER_USER_INTERRUPT); -+ } -+ - I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); - (void) I915_READ(GTIER); - -+ if (HAS_PCH_CPT(dev)) { -+ hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT | -+ SDE_PORTC_HOTPLUG_CPT | SDE_PORTD_HOTPLUG_CPT ; -+ } else { -+ hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | -+ SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; -+ } -+ - dev_priv->pch_irq_mask_reg = ~hotplug_mask; - dev_priv->pch_irq_enable_reg = hotplug_mask; - -@@ -1506,9 +1534,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev) - u32 error_mask; - - DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue); -- - if (HAS_BSD(dev)) - DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue); -+ if (HAS_BLT(dev)) -+ DRM_INIT_WAITQUEUE(&dev_priv->blt_ring.irq_queue); - - dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; - -@@ -1578,7 +1607,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - } - -- opregion_enable_asle(dev); -+ intel_opregion_enable_asle(dev); - - return 0; - } -diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h -index 4f5e155..25ed911 100644 ---- a/drivers/gpu/drm/i915/i915_reg.h -+++ b/drivers/gpu/drm/i915/i915_reg.h -@@ -25,52 +25,16 @@ - #ifndef _I915_REG_H_ - #define _I915_REG_H_ - -+#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) -+ - /* - * The Bridge device's PCI config space has information about the - * fb aperture size and the amount of pre-reserved memory. -+ * This is all handled in the intel-gtt.ko module. i915.ko only -+ * cares about the vga bit for the vga rbiter. - */ - #define INTEL_GMCH_CTRL 0x52 - #define INTEL_GMCH_VGA_DISABLE (1 << 1) --#define INTEL_GMCH_ENABLED 0x4 --#define INTEL_GMCH_MEM_MASK 0x1 --#define INTEL_GMCH_MEM_64M 0x1 --#define INTEL_GMCH_MEM_128M 0 -- --#define INTEL_GMCH_GMS_MASK (0xf << 4) --#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4) --#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4) --#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4) --#define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4) --#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4) --#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4) -- --#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4) --#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4) --#define INTEL_GMCH_GMS_STOLEN_128M (0x8 << 4) --#define INTEL_GMCH_GMS_STOLEN_256M (0x9 << 4) --#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) --#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) --#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) --#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) -- --#define SNB_GMCH_CTRL 0x50 --#define SNB_GMCH_GMS_STOLEN_MASK 0xF8 --#define SNB_GMCH_GMS_STOLEN_32M (1 << 3) --#define SNB_GMCH_GMS_STOLEN_64M (2 << 3) --#define SNB_GMCH_GMS_STOLEN_96M (3 << 3) --#define SNB_GMCH_GMS_STOLEN_128M (4 << 3) --#define SNB_GMCH_GMS_STOLEN_160M (5 << 3) --#define SNB_GMCH_GMS_STOLEN_192M (6 << 3) --#define SNB_GMCH_GMS_STOLEN_224M (7 << 3) --#define SNB_GMCH_GMS_STOLEN_256M (8 << 3) --#define SNB_GMCH_GMS_STOLEN_288M (9 << 3) --#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3) --#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3) --#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3) --#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3) --#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3) --#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3) --#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3) - - /* PCI config space */ - -@@ -106,10 +70,13 @@ - #define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0) - #define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0) - #define LBB 0xf4 --#define GDRST 0xc0 --#define GDRST_FULL (0<<2) --#define GDRST_RENDER (1<<2) --#define GDRST_MEDIA (3<<2) -+ -+/* Graphics reset regs */ -+#define I965_GDRST 0xc0 /* PCI config register */ -+#define ILK_GDSR 0x2ca4 /* MCHBAR offset */ -+#define GRDOM_FULL (0<<2) -+#define GRDOM_RENDER (1<<2) -+#define GRDOM_MEDIA (3<<2) - - /* VGA stuff */ - -@@ -192,11 +159,11 @@ - #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) - #define MI_STORE_DWORD_INDEX_SHIFT 2 - #define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) -+#define MI_FLUSH_DW MI_INSTR(0x26, 2) /* for GEN6 */ - #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) - #define MI_BATCH_NON_SECURE (1) - #define MI_BATCH_NON_SECURE_I965 (1<<8) - #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) -- - /* - * 3D instructions used by the kernel - */ -@@ -249,6 +216,16 @@ - #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ - #define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */ - -+ -+/* -+ * Reset registers -+ */ -+#define DEBUG_RESET_I830 0x6070 -+#define DEBUG_RESET_FULL (1<<7) -+#define DEBUG_RESET_RENDER (1<<8) -+#define DEBUG_RESET_DISPLAY (1<<9) -+ -+ - /* - * Fence registers - */ -@@ -283,6 +260,17 @@ - #define PRB0_HEAD 0x02034 - #define PRB0_START 0x02038 - #define PRB0_CTL 0x0203c -+#define RENDER_RING_BASE 0x02000 -+#define BSD_RING_BASE 0x04000 -+#define GEN6_BSD_RING_BASE 0x12000 -+#define BLT_RING_BASE 0x22000 -+#define RING_TAIL(base) ((base)+0x30) -+#define RING_HEAD(base) ((base)+0x34) -+#define RING_START(base) ((base)+0x38) -+#define RING_CTL(base) ((base)+0x3c) -+#define RING_HWS_PGA(base) ((base)+0x80) -+#define RING_HWS_PGA_GEN6(base) ((base)+0x2080) -+#define RING_ACTHD(base) ((base)+0x74) - #define TAIL_ADDR 0x001FFFF8 - #define HEAD_WRAP_COUNT 0xFFE00000 - #define HEAD_WRAP_ONE 0x00200000 -@@ -295,6 +283,8 @@ - #define RING_VALID_MASK 0x00000001 - #define RING_VALID 0x00000001 - #define RING_INVALID 0x00000000 -+#define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */ -+#define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */ - #define PRB1_TAIL 0x02040 /* 915+ only */ - #define PRB1_HEAD 0x02044 /* 915+ only */ - #define PRB1_START 0x02048 /* 915+ only */ -@@ -306,7 +296,6 @@ - #define INSTDONE1 0x0207c /* 965+ only */ - #define ACTHD_I965 0x02074 - #define HWS_PGA 0x02080 --#define HWS_PGA_GEN6 0x04080 - #define HWS_ADDRESS_MASK 0xfffff000 - #define HWS_START_ADDRESS_SHIFT 4 - #define PWRCTXA 0x2088 /* 965GM+ only */ -@@ -464,17 +453,17 @@ - #define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25) - #define GEN6_BLITTER_SYNC_STATUS (1 << 24) - #define GEN6_BLITTER_USER_INTERRUPT (1 << 22) --/* -- * BSD (bit stream decoder instruction and interrupt control register defines -- * (G4X and Ironlake only) -- */ - --#define BSD_RING_TAIL 0x04030 --#define BSD_RING_HEAD 0x04034 --#define BSD_RING_START 0x04038 --#define BSD_RING_CTL 0x0403c --#define BSD_RING_ACTHD 0x04074 --#define BSD_HWS_PGA 0x04080 -+#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 -+#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16) -+#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0) -+#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 -+#define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) -+ -+#define GEN6_BSD_IMR 0x120a8 -+#define GEN6_BSD_IMR_USER_INTERRUPT (1 << 12) -+ -+#define GEN6_BSD_RNCID 0x12198 - - /* - * Framebuffer compression (915+ only) -@@ -579,12 +568,51 @@ - # define GPIO_DATA_VAL_IN (1 << 12) - # define GPIO_DATA_PULLUP_DISABLE (1 << 13) - --#define GMBUS0 0x5100 --#define GMBUS1 0x5104 --#define GMBUS2 0x5108 --#define GMBUS3 0x510c --#define GMBUS4 0x5110 --#define GMBUS5 0x5120 -+#define GMBUS0 0x5100 /* clock/port select */ -+#define GMBUS_RATE_100KHZ (0<<8) -+#define GMBUS_RATE_50KHZ (1<<8) -+#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ -+#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */ -+#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */ -+#define GMBUS_PORT_DISABLED 0 -+#define GMBUS_PORT_SSC 1 -+#define GMBUS_PORT_VGADDC 2 -+#define GMBUS_PORT_PANEL 3 -+#define GMBUS_PORT_DPC 4 /* HDMIC */ -+#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ -+ /* 6 reserved */ -+#define GMBUS_PORT_DPD 7 /* HDMID */ -+#define GMBUS_NUM_PORTS 8 -+#define GMBUS1 0x5104 /* command/status */ -+#define GMBUS_SW_CLR_INT (1<<31) -+#define GMBUS_SW_RDY (1<<30) -+#define GMBUS_ENT (1<<29) /* enable timeout */ -+#define GMBUS_CYCLE_NONE (0<<25) -+#define GMBUS_CYCLE_WAIT (1<<25) -+#define GMBUS_CYCLE_INDEX (2<<25) -+#define GMBUS_CYCLE_STOP (4<<25) -+#define GMBUS_BYTE_COUNT_SHIFT 16 -+#define GMBUS_SLAVE_INDEX_SHIFT 8 -+#define GMBUS_SLAVE_ADDR_SHIFT 1 -+#define GMBUS_SLAVE_READ (1<<0) -+#define GMBUS_SLAVE_WRITE (0<<0) -+#define GMBUS2 0x5108 /* status */ -+#define GMBUS_INUSE (1<<15) -+#define GMBUS_HW_WAIT_PHASE (1<<14) -+#define GMBUS_STALL_TIMEOUT (1<<13) -+#define GMBUS_INT (1<<12) -+#define GMBUS_HW_RDY (1<<11) -+#define GMBUS_SATOER (1<<10) -+#define GMBUS_ACTIVE (1<<9) -+#define GMBUS3 0x510c /* data buffer bytes 3-0 */ -+#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */ -+#define GMBUS_SLAVE_TIMEOUT_EN (1<<4) -+#define GMBUS_NAK_EN (1<<3) -+#define GMBUS_IDLE_EN (1<<2) -+#define GMBUS_HW_WAIT_EN (1<<1) -+#define GMBUS_HW_RDY_EN (1<<0) -+#define GMBUS5 0x5120 /* byte index */ -+#define GMBUS_2BYTE_INDEX_EN (1<<31) - - /* - * Clock control & power management -@@ -603,6 +631,7 @@ - #define VGA1_PD_P1_MASK (0x1f << 8) - #define DPLL_A 0x06014 - #define DPLL_B 0x06018 -+#define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B) - #define DPLL_VCO_ENABLE (1 << 31) - #define DPLL_DVO_HIGH_SPEED (1 << 30) - #define DPLL_SYNCLOCK_ENABLE (1 << 29) -@@ -633,31 +662,6 @@ - #define LVDS 0x61180 - #define LVDS_ON (1<<31) - --#define ADPA 0x61100 --#define ADPA_DPMS_MASK (~(3<<10)) --#define ADPA_DPMS_ON (0<<10) --#define ADPA_DPMS_SUSPEND (1<<10) --#define ADPA_DPMS_STANDBY (2<<10) --#define ADPA_DPMS_OFF (3<<10) -- --#define RING_TAIL 0x00 --#define TAIL_ADDR 0x001FFFF8 --#define RING_HEAD 0x04 --#define HEAD_WRAP_COUNT 0xFFE00000 --#define HEAD_WRAP_ONE 0x00200000 --#define HEAD_ADDR 0x001FFFFC --#define RING_START 0x08 --#define START_ADDR 0xFFFFF000 --#define RING_LEN 0x0C --#define RING_NR_PAGES 0x001FF000 --#define RING_REPORT_MASK 0x00000006 --#define RING_REPORT_64K 0x00000002 --#define RING_REPORT_128K 0x00000004 --#define RING_NO_REPORT 0x00000000 --#define RING_VALID_MASK 0x00000001 --#define RING_VALID 0x00000001 --#define RING_INVALID 0x00000000 -- - /* Scratch pad debug 0 reg: - */ - #define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 -@@ -736,10 +740,13 @@ - #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f - #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 - #define DPLL_B_MD 0x06020 /* 965+ only */ -+#define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD) - #define FPA0 0x06040 - #define FPA1 0x06044 - #define FPB0 0x06048 - #define FPB1 0x0604c -+#define FP0(pipe) _PIPE(pipe, FPA0, FPB0) -+#define FP1(pipe) _PIPE(pipe, FPA1, FPB1) - #define FP_N_DIV_MASK 0x003f0000 - #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 - #define FP_N_DIV_SHIFT 16 -@@ -760,6 +767,7 @@ - #define DPLLA_TEST_M_BYPASS (1 << 2) - #define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) - #define D_STATE 0x6104 -+#define DSTATE_GFX_RESET_I830 (1<<6) - #define DSTATE_PLL_D3_OFF (1<<3) - #define DSTATE_GFX_CLOCK_GATING (1<<1) - #define DSTATE_DOT_CLOCK_GATING (1<<0) -@@ -926,6 +934,8 @@ - #define CLKCFG_MEM_800 (3 << 4) - #define CLKCFG_MEM_MASK (7 << 4) - -+#define TSC1 0x11001 -+#define TSE (1<<0) - #define TR1 0x11006 - #define TSFS 0x11020 - #define TSFS_SLOPE_MASK 0x0000ff00 -@@ -1070,6 +1080,8 @@ - #define MEMSTAT_SRC_CTL_STDBY 3 - #define RCPREVBSYTUPAVG 0x113b8 - #define RCPREVBSYTDNAVG 0x113bc -+#define PMMISC 0x11214 -+#define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */ - #define SDEW 0x1124c - #define CSIEW0 0x11250 - #define CSIEW1 0x11254 -@@ -1150,6 +1162,15 @@ - #define PIPEBSRC 0x6101c - #define BCLRPAT_B 0x61020 - -+#define HTOTAL(pipe) _PIPE(pipe, HTOTAL_A, HTOTAL_B) -+#define HBLANK(pipe) _PIPE(pipe, HBLANK_A, HBLANK_B) -+#define HSYNC(pipe) _PIPE(pipe, HSYNC_A, HSYNC_B) -+#define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B) -+#define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B) -+#define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B) -+#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC) -+#define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B) -+ - /* VGA port control */ - #define ADPA 0x61100 - #define ADPA_DAC_ENABLE (1<<31) -@@ -1173,6 +1194,7 @@ - #define ADPA_DPMS_STANDBY (2<<10) - #define ADPA_DPMS_OFF (3<<10) - -+ - /* Hotplug control (945+ only) */ - #define PORT_HOTPLUG_EN 0x61110 - #define HDMIB_HOTPLUG_INT_EN (1 << 29) -@@ -1331,6 +1353,22 @@ - #define LVDS_B0B3_POWER_DOWN (0 << 2) - #define LVDS_B0B3_POWER_UP (3 << 2) - -+/* Video Data Island Packet control */ -+#define VIDEO_DIP_DATA 0x61178 -+#define VIDEO_DIP_CTL 0x61170 -+#define VIDEO_DIP_ENABLE (1 << 31) -+#define VIDEO_DIP_PORT_B (1 << 29) -+#define VIDEO_DIP_PORT_C (2 << 29) -+#define VIDEO_DIP_ENABLE_AVI (1 << 21) -+#define VIDEO_DIP_ENABLE_VENDOR (2 << 21) -+#define VIDEO_DIP_ENABLE_SPD (8 << 21) -+#define VIDEO_DIP_SELECT_AVI (0 << 19) -+#define VIDEO_DIP_SELECT_VENDOR (1 << 19) -+#define VIDEO_DIP_SELECT_SPD (3 << 19) -+#define VIDEO_DIP_FREQ_ONCE (0 << 16) -+#define VIDEO_DIP_FREQ_VSYNC (1 << 16) -+#define VIDEO_DIP_FREQ_2VSYNC (2 << 16) -+ - /* Panel power sequencing */ - #define PP_STATUS 0x61200 - #define PP_ON (1 << 31) -@@ -1346,6 +1384,9 @@ - #define PP_SEQUENCE_ON (1 << 28) - #define PP_SEQUENCE_OFF (2 << 28) - #define PP_SEQUENCE_MASK 0x30000000 -+#define PP_CYCLE_DELAY_ACTIVE (1 << 27) -+#define PP_SEQUENCE_STATE_ON_IDLE (1 << 3) -+#define PP_SEQUENCE_STATE_MASK 0x0000000f - #define PP_CONTROL 0x61204 - #define POWER_TARGET_ON (1 << 0) - #define PP_ON_DELAYS 0x61208 -@@ -1481,6 +1522,7 @@ - # define TV_TEST_MODE_MASK (7 << 0) - - #define TV_DAC 0x68004 -+# define TV_DAC_SAVE 0x00ffff00 - /** - * Reports that DAC state change logic has reported change (RO). - * -@@ -2075,29 +2117,35 @@ - - /* Display & cursor control */ - --/* dithering flag on Ironlake */ --#define PIPE_ENABLE_DITHER (1 << 4) --#define PIPE_DITHER_TYPE_MASK (3 << 2) --#define PIPE_DITHER_TYPE_SPATIAL (0 << 2) --#define PIPE_DITHER_TYPE_ST01 (1 << 2) - /* Pipe A */ - #define PIPEADSL 0x70000 --#define DSL_LINEMASK 0x00000fff -+#define DSL_LINEMASK 0x00000fff - #define PIPEACONF 0x70008 --#define PIPEACONF_ENABLE (1<<31) --#define PIPEACONF_DISABLE 0 --#define PIPEACONF_DOUBLE_WIDE (1<<30) -+#define PIPECONF_ENABLE (1<<31) -+#define PIPECONF_DISABLE 0 -+#define PIPECONF_DOUBLE_WIDE (1<<30) - #define I965_PIPECONF_ACTIVE (1<<30) --#define PIPEACONF_SINGLE_WIDE 0 --#define PIPEACONF_PIPE_UNLOCKED 0 --#define PIPEACONF_PIPE_LOCKED (1<<25) --#define PIPEACONF_PALETTE 0 --#define PIPEACONF_GAMMA (1<<24) -+#define PIPECONF_SINGLE_WIDE 0 -+#define PIPECONF_PIPE_UNLOCKED 0 -+#define PIPECONF_PIPE_LOCKED (1<<25) -+#define PIPECONF_PALETTE 0 -+#define PIPECONF_GAMMA (1<<24) - #define PIPECONF_FORCE_BORDER (1<<25) - #define PIPECONF_PROGRESSIVE (0 << 21) - #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) - #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) - #define PIPECONF_CXSR_DOWNCLOCK (1<<16) -+#define PIPECONF_BPP_MASK (0x000000e0) -+#define PIPECONF_BPP_8 (0<<5) -+#define PIPECONF_BPP_10 (1<<5) -+#define PIPECONF_BPP_6 (2<<5) -+#define PIPECONF_BPP_12 (3<<5) -+#define PIPECONF_DITHER_EN (1<<4) -+#define PIPECONF_DITHER_TYPE_MASK (0x0000000c) -+#define PIPECONF_DITHER_TYPE_SP (0<<2) -+#define PIPECONF_DITHER_TYPE_ST1 (1<<2) -+#define PIPECONF_DITHER_TYPE_ST2 (2<<2) -+#define PIPECONF_DITHER_TYPE_TEMP (3<<2) - #define PIPEASTAT 0x70024 - #define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) - #define PIPE_CRC_ERROR_ENABLE (1UL<<29) -@@ -2128,12 +2176,15 @@ - #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ - #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) - #define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) --#define PIPE_BPC_MASK (7 << 5) /* Ironlake */ -+#define PIPE_BPC_MASK (7 << 5) /* Ironlake */ - #define PIPE_8BPC (0 << 5) - #define PIPE_10BPC (1 << 5) - #define PIPE_6BPC (2 << 5) - #define PIPE_12BPC (3 << 5) - -+#define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) -+#define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) -+ - #define DSPARB 0x70030 - #define DSPARB_CSTART_MASK (0x7f << 7) - #define DSPARB_CSTART_SHIFT 7 -@@ -2206,8 +2257,8 @@ - #define WM1_LP_SR_EN (1<<31) - #define WM1_LP_LATENCY_SHIFT 24 - #define WM1_LP_LATENCY_MASK (0x7f<<24) --#define WM1_LP_FBC_LP1_MASK (0xf<<20) --#define WM1_LP_FBC_LP1_SHIFT 20 -+#define WM1_LP_FBC_MASK (0xf<<20) -+#define WM1_LP_FBC_SHIFT 20 - #define WM1_LP_SR_MASK (0x1ff<<8) - #define WM1_LP_SR_SHIFT 8 - #define WM1_LP_CURSOR_MASK (0x3f) -@@ -2333,6 +2384,14 @@ - #define DSPASURF 0x7019C /* 965+ only */ - #define DSPATILEOFF 0x701A4 /* 965+ only */ - -+#define DSPCNTR(plane) _PIPE(plane, DSPACNTR, DSPBCNTR) -+#define DSPADDR(plane) _PIPE(plane, DSPAADDR, DSPBADDR) -+#define DSPSTRIDE(plane) _PIPE(plane, DSPASTRIDE, DSPBSTRIDE) -+#define DSPPOS(plane) _PIPE(plane, DSPAPOS, DSPBPOS) -+#define DSPSIZE(plane) _PIPE(plane, DSPASIZE, DSPBSIZE) -+#define DSPSURF(plane) _PIPE(plane, DSPASURF, DSPBSURF) -+#define DSPTILEOFF(plane) _PIPE(plane, DSPATILEOFF, DSPBTILEOFF) -+ - /* VBIOS flags */ - #define SWF00 0x71410 - #define SWF01 0x71414 -@@ -2397,6 +2456,7 @@ - #define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 - - #define FDI_PLL_BIOS_0 0x46000 -+#define FDI_PLL_FB_CLOCK_MASK 0xff - #define FDI_PLL_BIOS_1 0x46004 - #define FDI_PLL_BIOS_2 0x46008 - #define DISPLAY_PORT_PLL_BIOS_0 0x4600c -@@ -2420,46 +2480,47 @@ - #define PIPEA_DATA_M1 0x60030 - #define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ - #define TU_SIZE_MASK 0x7e000000 --#define PIPEA_DATA_M1_OFFSET 0 -+#define PIPE_DATA_M1_OFFSET 0 - #define PIPEA_DATA_N1 0x60034 --#define PIPEA_DATA_N1_OFFSET 0 -+#define PIPE_DATA_N1_OFFSET 0 - - #define PIPEA_DATA_M2 0x60038 --#define PIPEA_DATA_M2_OFFSET 0 -+#define PIPE_DATA_M2_OFFSET 0 - #define PIPEA_DATA_N2 0x6003c --#define PIPEA_DATA_N2_OFFSET 0 -+#define PIPE_DATA_N2_OFFSET 0 - - #define PIPEA_LINK_M1 0x60040 --#define PIPEA_LINK_M1_OFFSET 0 -+#define PIPE_LINK_M1_OFFSET 0 - #define PIPEA_LINK_N1 0x60044 --#define PIPEA_LINK_N1_OFFSET 0 -+#define PIPE_LINK_N1_OFFSET 0 - - #define PIPEA_LINK_M2 0x60048 --#define PIPEA_LINK_M2_OFFSET 0 -+#define PIPE_LINK_M2_OFFSET 0 - #define PIPEA_LINK_N2 0x6004c --#define PIPEA_LINK_N2_OFFSET 0 -+#define PIPE_LINK_N2_OFFSET 0 - - /* PIPEB timing regs are same start from 0x61000 */ - - #define PIPEB_DATA_M1 0x61030 --#define PIPEB_DATA_M1_OFFSET 0 - #define PIPEB_DATA_N1 0x61034 --#define PIPEB_DATA_N1_OFFSET 0 - - #define PIPEB_DATA_M2 0x61038 --#define PIPEB_DATA_M2_OFFSET 0 - #define PIPEB_DATA_N2 0x6103c --#define PIPEB_DATA_N2_OFFSET 0 - - #define PIPEB_LINK_M1 0x61040 --#define PIPEB_LINK_M1_OFFSET 0 - #define PIPEB_LINK_N1 0x61044 --#define PIPEB_LINK_N1_OFFSET 0 - - #define PIPEB_LINK_M2 0x61048 --#define PIPEB_LINK_M2_OFFSET 0 - #define PIPEB_LINK_N2 0x6104c --#define PIPEB_LINK_N2_OFFSET 0 -+ -+#define PIPE_DATA_M1(pipe) _PIPE(pipe, PIPEA_DATA_M1, PIPEB_DATA_M1) -+#define PIPE_DATA_N1(pipe) _PIPE(pipe, PIPEA_DATA_N1, PIPEB_DATA_N1) -+#define PIPE_DATA_M2(pipe) _PIPE(pipe, PIPEA_DATA_M2, PIPEB_DATA_M2) -+#define PIPE_DATA_N2(pipe) _PIPE(pipe, PIPEA_DATA_N2, PIPEB_DATA_N2) -+#define PIPE_LINK_M1(pipe) _PIPE(pipe, PIPEA_LINK_M1, PIPEB_LINK_M1) -+#define PIPE_LINK_N1(pipe) _PIPE(pipe, PIPEA_LINK_N1, PIPEB_LINK_N1) -+#define PIPE_LINK_M2(pipe) _PIPE(pipe, PIPEA_LINK_M2, PIPEB_LINK_M2) -+#define PIPE_LINK_N2(pipe) _PIPE(pipe, PIPEA_LINK_N2, PIPEB_LINK_N2) - - /* CPU panel fitter */ - #define PFA_CTL_1 0x68080 -@@ -2516,7 +2577,8 @@ - #define GT_SYNC_STATUS (1 << 2) - #define GT_USER_INTERRUPT (1 << 0) - #define GT_BSD_USER_INTERRUPT (1 << 5) -- -+#define GT_GEN6_BSD_USER_INTERRUPT (1 << 12) -+#define GT_BLT_USER_INTERRUPT (1 << 22) - - #define GTISR 0x44010 - #define GTIMR 0x44014 -@@ -2551,6 +2613,10 @@ - #define SDE_PORTD_HOTPLUG_CPT (1 << 23) - #define SDE_PORTC_HOTPLUG_CPT (1 << 22) - #define SDE_PORTB_HOTPLUG_CPT (1 << 21) -+#define SDE_HOTPLUG_MASK_CPT (SDE_CRT_HOTPLUG_CPT | \ -+ SDE_PORTD_HOTPLUG_CPT | \ -+ SDE_PORTC_HOTPLUG_CPT | \ -+ SDE_PORTB_HOTPLUG_CPT) - - #define SDEISR 0xc4000 - #define SDEIMR 0xc4004 -@@ -2600,11 +2666,14 @@ - - #define PCH_DPLL_A 0xc6014 - #define PCH_DPLL_B 0xc6018 -+#define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B) - - #define PCH_FPA0 0xc6040 - #define PCH_FPA1 0xc6044 - #define PCH_FPB0 0xc6048 - #define PCH_FPB1 0xc604c -+#define PCH_FP0(pipe) _PIPE(pipe, PCH_FPA0, PCH_FPB0) -+#define PCH_FP1(pipe) _PIPE(pipe, PCH_FPA1, PCH_FPB1) - - #define PCH_DPLL_TEST 0xc606c - -@@ -2690,6 +2759,13 @@ - #define TRANS_VBLANK_B 0xe1010 - #define TRANS_VSYNC_B 0xe1014 - -+#define TRANS_HTOTAL(pipe) _PIPE(pipe, TRANS_HTOTAL_A, TRANS_HTOTAL_B) -+#define TRANS_HBLANK(pipe) _PIPE(pipe, TRANS_HBLANK_A, TRANS_HBLANK_B) -+#define TRANS_HSYNC(pipe) _PIPE(pipe, TRANS_HSYNC_A, TRANS_HSYNC_B) -+#define TRANS_VTOTAL(pipe) _PIPE(pipe, TRANS_VTOTAL_A, TRANS_VTOTAL_B) -+#define TRANS_VBLANK(pipe) _PIPE(pipe, TRANS_VBLANK_A, TRANS_VBLANK_B) -+#define TRANS_VSYNC(pipe) _PIPE(pipe, TRANS_VSYNC_A, TRANS_VSYNC_B) -+ - #define TRANSB_DATA_M1 0xe1030 - #define TRANSB_DATA_N1 0xe1034 - #define TRANSB_DATA_M2 0xe1038 -@@ -2701,6 +2777,7 @@ - - #define TRANSACONF 0xf0008 - #define TRANSBCONF 0xf1008 -+#define TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF) - #define TRANS_DISABLE (0<<31) - #define TRANS_ENABLE (1<<31) - #define TRANS_STATE_MASK (1<<30) -@@ -2721,10 +2798,15 @@ - #define FDI_RXA_CHICKEN 0xc200c - #define FDI_RXB_CHICKEN 0xc2010 - #define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1) -+#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, FDI_RXA_CHICKEN, FDI_RXB_CHICKEN) -+ -+#define SOUTH_DSPCLK_GATE_D 0xc2020 -+#define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) - - /* CPU: FDI_TX */ - #define FDI_TXA_CTL 0x60100 - #define FDI_TXB_CTL 0x61100 -+#define FDI_TX_CTL(pipe) _PIPE(pipe, FDI_TXA_CTL, FDI_TXB_CTL) - #define FDI_TX_DISABLE (0<<31) - #define FDI_TX_ENABLE (1<<31) - #define FDI_LINK_TRAIN_PATTERN_1 (0<<28) -@@ -2766,8 +2848,8 @@ - /* FDI_RX, FDI_X is hard-wired to Transcoder_X */ - #define FDI_RXA_CTL 0xf000c - #define FDI_RXB_CTL 0xf100c -+#define FDI_RX_CTL(pipe) _PIPE(pipe, FDI_RXA_CTL, FDI_RXB_CTL) - #define FDI_RX_ENABLE (1<<31) --#define FDI_RX_DISABLE (0<<31) - /* train, dp width same as FDI_TX */ - #define FDI_DP_PORT_WIDTH_X8 (7<<19) - #define FDI_8BPC (0<<16) -@@ -2782,8 +2864,7 @@ - #define FDI_FS_ERR_REPORT_ENABLE (1<<9) - #define FDI_FE_ERR_REPORT_ENABLE (1<<8) - #define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6) --#define FDI_SEL_RAWCLK (0<<4) --#define FDI_SEL_PCDCLK (1<<4) -+#define FDI_PCDCLK (1<<4) - /* CPT */ - #define FDI_AUTO_TRAINING (1<<10) - #define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8) -@@ -2798,6 +2879,9 @@ - #define FDI_RXA_TUSIZE2 0xf0038 - #define FDI_RXB_TUSIZE1 0xf1030 - #define FDI_RXB_TUSIZE2 0xf1038 -+#define FDI_RX_MISC(pipe) _PIPE(pipe, FDI_RXA_MISC, FDI_RXB_MISC) -+#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, FDI_RXA_TUSIZE1, FDI_RXB_TUSIZE1) -+#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, FDI_RXA_TUSIZE2, FDI_RXB_TUSIZE2) - - /* FDI_RX interrupt register format */ - #define FDI_RX_INTER_LANE_ALIGN (1<<10) -@@ -2816,6 +2900,8 @@ - #define FDI_RXA_IMR 0xf0018 - #define FDI_RXB_IIR 0xf1014 - #define FDI_RXB_IMR 0xf1018 -+#define FDI_RX_IIR(pipe) _PIPE(pipe, FDI_RXA_IIR, FDI_RXB_IIR) -+#define FDI_RX_IMR(pipe) _PIPE(pipe, FDI_RXA_IMR, FDI_RXB_IMR) - - #define FDI_PLL_CTL_1 0xfe000 - #define FDI_PLL_CTL_2 0xfe004 -@@ -2935,6 +3021,7 @@ - #define TRANS_DP_CTL_A 0xe0300 - #define TRANS_DP_CTL_B 0xe1300 - #define TRANS_DP_CTL_C 0xe2300 -+#define TRANS_DP_CTL(pipe) (TRANS_DP_CTL_A + (pipe) * 0x01000) - #define TRANS_DP_OUTPUT_ENABLE (1<<31) - #define TRANS_DP_PORT_SEL_B (0<<29) - #define TRANS_DP_PORT_SEL_C (1<<29) -diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c -index 31f0858..454c064 100644 ---- a/drivers/gpu/drm/i915/i915_suspend.c -+++ b/drivers/gpu/drm/i915/i915_suspend.c -@@ -256,7 +256,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) - dev_priv->saveFPA1 = I915_READ(FPA1); - dev_priv->saveDPLL_A = I915_READ(DPLL_A); - } -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) - dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); - dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); - dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); -@@ -294,7 +294,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) - dev_priv->saveDSPASIZE = I915_READ(DSPASIZE); - dev_priv->saveDSPAPOS = I915_READ(DSPAPOS); - dev_priv->saveDSPAADDR = I915_READ(DSPAADDR); -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - dev_priv->saveDSPASURF = I915_READ(DSPASURF); - dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); - } -@@ -313,7 +313,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) - dev_priv->saveFPB1 = I915_READ(FPB1); - dev_priv->saveDPLL_B = I915_READ(DPLL_B); - } -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) - dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); - dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); - dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); -@@ -351,7 +351,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) - dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); - dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); - dev_priv->saveDSPBADDR = I915_READ(DSPBADDR); -- if (IS_I965GM(dev) || IS_GM45(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); - dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); - } -@@ -404,7 +404,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) - I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A); - POSTING_READ(dpll_a_reg); - udelay(150); -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { - I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); - POSTING_READ(DPLL_A_MD); - } -@@ -448,7 +448,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) - I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); - I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); - I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); - I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); - } -@@ -473,7 +473,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) - I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); - POSTING_READ(dpll_b_reg); - udelay(150); -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { - I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); - POSTING_READ(DPLL_B_MD); - } -@@ -517,7 +517,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) - I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); - I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); - I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); - I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); - } -@@ -550,7 +550,7 @@ void i915_save_display(struct drm_device *dev) - dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); - dev_priv->saveCURBPOS = I915_READ(CURBPOS); - dev_priv->saveCURBBASE = I915_READ(CURBBASE); -- if (!IS_I9XX(dev)) -+ if (IS_GEN2(dev)) - dev_priv->saveCURSIZE = I915_READ(CURSIZE); - - /* CRT state */ -@@ -573,7 +573,7 @@ void i915_save_display(struct drm_device *dev) - dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); - dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); - if (IS_MOBILE(dev) && !IS_I830(dev)) - dev_priv->saveLVDS = I915_READ(LVDS); -@@ -664,7 +664,7 @@ void i915_restore_display(struct drm_device *dev) - I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); - I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); - I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); -- if (!IS_I9XX(dev)) -+ if (IS_GEN2(dev)) - I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); - - /* CRT state */ -@@ -674,7 +674,7 @@ void i915_restore_display(struct drm_device *dev) - I915_WRITE(ADPA, dev_priv->saveADPA); - - /* LVDS state */ -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) - I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); - - if (HAS_PCH_SPLIT(dev)) { -@@ -862,8 +862,10 @@ int i915_restore_state(struct drm_device *dev) - /* Clock gating state */ - intel_init_clock_gating(dev); - -- if (HAS_PCH_SPLIT(dev)) -+ if (HAS_PCH_SPLIT(dev)) { - ironlake_enable_drps(dev); -+ intel_init_emon(dev); -+ } - - /* Cache mode state */ - I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); -@@ -878,9 +880,7 @@ int i915_restore_state(struct drm_device *dev) - for (i = 0; i < 3; i++) - I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); - -- /* I2C state */ -- intel_i2c_reset_gmbus(dev); -+ intel_i2c_reset(dev); - - return 0; - } -- -diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c -new file mode 100644 -index 0000000..65c88f9 ---- /dev/null -+++ b/drivers/gpu/drm/i915/intel_acpi.c -@@ -0,0 +1,286 @@ -+/* -+ * Intel ACPI functions -+ * -+ * _DSM related code stolen from nouveau_acpi.c. -+ */ -+#include -+#include -+#include -+#include -+ -+#include "drmP.h" -+ -+#define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */ -+ -+#define INTEL_DSM_FN_SUPPORTED_FUNCTIONS 0 /* No args */ -+#define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */ -+ -+static struct intel_dsm_priv { -+ acpi_handle dhandle; -+} intel_dsm_priv; -+ -+static const u8 intel_dsm_guid[] = { -+ 0xd3, 0x73, 0xd8, 0x7e, -+ 0xd0, 0xc2, -+ 0x4f, 0x4e, -+ 0xa8, 0x54, -+ 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c -+}; -+ -+static int intel_dsm(acpi_handle handle, int func, int arg) -+{ -+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; -+ struct acpi_object_list input; -+ union acpi_object params[4]; -+ union acpi_object *obj; -+ u32 result; -+ int ret = 0; -+ -+ input.count = 4; -+ input.pointer = params; -+ params[0].type = ACPI_TYPE_BUFFER; -+ params[0].buffer.length = sizeof(intel_dsm_guid); -+ params[0].buffer.pointer = (char *)intel_dsm_guid; -+ params[1].type = ACPI_TYPE_INTEGER; -+ params[1].integer.value = INTEL_DSM_REVISION_ID; -+ params[2].type = ACPI_TYPE_INTEGER; -+ params[2].integer.value = func; -+ params[3].type = ACPI_TYPE_INTEGER; -+ params[3].integer.value = arg; -+ -+ ret = acpi_evaluate_object(handle, "_DSM", &input, &output); -+ if (ret) { -+ DRM_DEBUG_DRIVER("failed to evaluate _DSM: %d\n", ret); -+ return ret; -+ } -+ -+ obj = (union acpi_object *)output.pointer; -+ -+ result = 0; -+ switch (obj->type) { -+ case ACPI_TYPE_INTEGER: -+ result = obj->integer.value; -+ break; -+ -+ case ACPI_TYPE_BUFFER: -+ if (obj->buffer.length == 4) { -+ result =(obj->buffer.pointer[0] | -+ (obj->buffer.pointer[1] << 8) | -+ (obj->buffer.pointer[2] << 16) | -+ (obj->buffer.pointer[3] << 24)); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ if (result == 0x80000002) -+ ret = -ENODEV; -+ -+ kfree(output.pointer); -+ return ret; -+} -+ -+static char *intel_dsm_port_name(u8 id) -+{ -+ switch (id) { -+ case 0: -+ return "Reserved"; -+ case 1: -+ return "Analog VGA"; -+ case 2: -+ return "LVDS"; -+ case 3: -+ return "Reserved"; -+ case 4: -+ return "HDMI/DVI_B"; -+ case 5: -+ return "HDMI/DVI_C"; -+ case 6: -+ return "HDMI/DVI_D"; -+ case 7: -+ return "DisplayPort_A"; -+ case 8: -+ return "DisplayPort_B"; -+ case 9: -+ return "DisplayPort_C"; -+ case 0xa: -+ return "DisplayPort_D"; -+ case 0xb: -+ case 0xc: -+ case 0xd: -+ return "Reserved"; -+ case 0xe: -+ return "WiDi"; -+ default: -+ return "bad type"; -+ } -+} -+ -+static char *intel_dsm_mux_type(u8 type) -+{ -+ switch (type) { -+ case 0: -+ return "unknown"; -+ case 1: -+ return "No MUX, iGPU only"; -+ case 2: -+ return "No MUX, dGPU only"; -+ case 3: -+ return "MUXed between iGPU and dGPU"; -+ default: -+ return "bad type"; -+ } -+} -+ -+static void intel_dsm_platform_mux_info(void) -+{ -+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; -+ struct acpi_object_list input; -+ union acpi_object params[4]; -+ union acpi_object *pkg; -+ int i, ret; -+ -+ input.count = 4; -+ input.pointer = params; -+ params[0].type = ACPI_TYPE_BUFFER; -+ params[0].buffer.length = sizeof(intel_dsm_guid); -+ params[0].buffer.pointer = (char *)intel_dsm_guid; -+ params[1].type = ACPI_TYPE_INTEGER; -+ params[1].integer.value = INTEL_DSM_REVISION_ID; -+ params[2].type = ACPI_TYPE_INTEGER; -+ params[2].integer.value = INTEL_DSM_FN_PLATFORM_MUX_INFO; -+ params[3].type = ACPI_TYPE_INTEGER; -+ params[3].integer.value = 0; -+ -+ ret = acpi_evaluate_object(intel_dsm_priv.dhandle, "_DSM", &input, -+ &output); -+ if (ret) { -+ DRM_DEBUG_DRIVER("failed to evaluate _DSM: %d\n", ret); -+ goto out; -+ } -+ -+ pkg = (union acpi_object *)output.pointer; -+ -+ if (pkg->type == ACPI_TYPE_PACKAGE) { -+ union acpi_object *connector_count = &pkg->package.elements[0]; -+ DRM_DEBUG_DRIVER("MUX info connectors: %lld\n", -+ (unsigned long long)connector_count->integer.value); -+ for (i = 1; i < pkg->package.count; i++) { -+ union acpi_object *obj = &pkg->package.elements[i]; -+ union acpi_object *connector_id = -+ &obj->package.elements[0]; -+ union acpi_object *info = &obj->package.elements[1]; -+ DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n", -+ (unsigned long long)connector_id->integer.value); -+ DRM_DEBUG_DRIVER(" port id: %s\n", -+ intel_dsm_port_name(info->buffer.pointer[0])); -+ DRM_DEBUG_DRIVER(" display mux info: %s\n", -+ intel_dsm_mux_type(info->buffer.pointer[1])); -+ DRM_DEBUG_DRIVER(" aux/dc mux info: %s\n", -+ intel_dsm_mux_type(info->buffer.pointer[2])); -+ DRM_DEBUG_DRIVER(" hpd mux info: %s\n", -+ intel_dsm_mux_type(info->buffer.pointer[3])); -+ } -+ } else { -+ DRM_ERROR("MUX INFO call failed\n"); -+ } -+ -+out: -+ kfree(output.pointer); -+} -+ -+static int intel_dsm_switchto(enum vga_switcheroo_client_id id) -+{ -+ return 0; -+} -+ -+static int intel_dsm_power_state(enum vga_switcheroo_client_id id, -+ enum vga_switcheroo_state state) -+{ -+ return 0; -+} -+ -+static int intel_dsm_init(void) -+{ -+ return 0; -+} -+ -+static int intel_dsm_get_client_id(struct pci_dev *pdev) -+{ -+ if (intel_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) -+ return VGA_SWITCHEROO_IGD; -+ else -+ return VGA_SWITCHEROO_DIS; -+} -+ -+static struct vga_switcheroo_handler intel_dsm_handler = { -+ .switchto = intel_dsm_switchto, -+ .power_state = intel_dsm_power_state, -+ .init = intel_dsm_init, -+ .get_client_id = intel_dsm_get_client_id, -+}; -+ -+static bool intel_dsm_pci_probe(struct pci_dev *pdev) -+{ -+ acpi_handle dhandle, intel_handle; -+ acpi_status status; -+ int ret; -+ -+ dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); -+ if (!dhandle) -+ return false; -+ -+ status = acpi_get_handle(dhandle, "_DSM", &intel_handle); -+ if (ACPI_FAILURE(status)) { -+ DRM_DEBUG_KMS("no _DSM method for intel device\n"); -+ return false; -+ } -+ -+ ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS, 0); -+ if (ret < 0) { -+ DRM_ERROR("failed to get supported _DSM functions\n"); -+ return false; -+ } -+ -+ intel_dsm_priv.dhandle = dhandle; -+ -+ intel_dsm_platform_mux_info(); -+ return true; -+} -+ -+static bool intel_dsm_detect(void) -+{ -+ char acpi_method_name[255] = { 0 }; -+ struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; -+ struct pci_dev *pdev = NULL; -+ bool has_dsm = false; -+ int vga_count = 0; -+ -+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { -+ vga_count++; -+ has_dsm |= intel_dsm_pci_probe(pdev); -+ } -+ -+ if (vga_count == 2 && has_dsm) { -+ acpi_get_name(intel_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); -+ DRM_DEBUG_DRIVER("VGA switcheroo: detected DSM switching method %s handle\n", -+ acpi_method_name); -+ return true; -+ } -+ -+ return false; -+} -+ -+void intel_register_dsm_handler(void) -+{ -+ if (!intel_dsm_detect()) -+ return; -+ -+ vga_switcheroo_register_handler(&intel_dsm_handler); -+} -+ -+void intel_unregister_dsm_handler(void) -+{ -+ vga_switcheroo_unregister_handler(); -+} -diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c -index 96f75d7..b0b1200 100644 ---- a/drivers/gpu/drm/i915/intel_bios.c -+++ b/drivers/gpu/drm/i915/intel_bios.c -@@ -24,6 +24,7 @@ - * Eric Anholt - * - */ -+#include - #include "drmP.h" - #include "drm.h" - #include "i915_drm.h" -@@ -129,10 +130,6 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, - int i, temp_downclock; - struct drm_display_mode *temp_mode; - -- /* Defaults if we can't find VBT info */ -- dev_priv->lvds_dither = 0; -- dev_priv->lvds_vbt = 0; -- - lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); - if (!lvds_options) - return; -@@ -140,6 +137,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, - dev_priv->lvds_dither = lvds_options->pixel_dither; - if (lvds_options->panel_type == 0xff) - return; -+ - panel_type = lvds_options->panel_type; - - lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); -@@ -169,6 +167,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, - ((unsigned char *)entry + dvo_timing_offset); - - panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); -+ if (!panel_fixed_mode) -+ return; - - fill_detail_timing_data(panel_fixed_mode, dvo_timing); - -@@ -230,8 +230,6 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, - struct lvds_dvo_timing *dvo_timing; - struct drm_display_mode *panel_fixed_mode; - -- dev_priv->sdvo_lvds_vbt_mode = NULL; -- - sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); - if (!sdvo_lvds_options) - return; -@@ -260,10 +258,6 @@ parse_general_features(struct drm_i915_private *dev_priv, - struct drm_device *dev = dev_priv->dev; - struct bdb_general_features *general; - -- /* Set sensible defaults in case we can't find the general block */ -- dev_priv->int_tv_support = 1; -- dev_priv->int_crt_support = 1; -- - general = find_section(bdb, BDB_GENERAL_FEATURES); - if (general) { - dev_priv->int_tv_support = general->int_tv_support; -@@ -271,10 +265,10 @@ parse_general_features(struct drm_i915_private *dev_priv, - dev_priv->lvds_use_ssc = general->enable_ssc; - - if (dev_priv->lvds_use_ssc) { -- if (IS_I85X(dev_priv->dev)) -+ if (IS_I85X(dev)) - dev_priv->lvds_ssc_freq = - general->ssc_freq ? 66 : 48; -- else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev)) -+ else if (IS_GEN5(dev) || IS_GEN6(dev)) - dev_priv->lvds_ssc_freq = - general->ssc_freq ? 100 : 120; - else -@@ -289,14 +283,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) - { - struct bdb_general_definitions *general; -- const int crt_bus_map_table[] = { -- GPIOB, -- GPIOA, -- GPIOC, -- GPIOD, -- GPIOE, -- GPIOF, -- }; - - general = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (general) { -@@ -304,10 +290,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv, - if (block_size >= sizeof(*general)) { - int bus_pin = general->crt_ddc_gmbus_pin; - DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); -- if ((bus_pin >= 1) && (bus_pin <= 6)) { -- dev_priv->crt_ddc_bus = -- crt_bus_map_table[bus_pin-1]; -- } -+ if (bus_pin >= 1 && bus_pin <= 6) -+ dev_priv->crt_ddc_pin = bus_pin; - } else { - DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", - block_size); -@@ -317,7 +301,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, - - static void - parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, -- struct bdb_header *bdb) -+ struct bdb_header *bdb) - { - struct sdvo_device_mapping *p_mapping; - struct bdb_general_definitions *p_defs; -@@ -327,7 +311,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, - - p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (!p_defs) { -- DRM_DEBUG_KMS("No general definition block is found\n"); -+ DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); - return; - } - /* judge whether the size of child device meets the requirements. -@@ -377,7 +361,16 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, - p_mapping->slave_addr = p_child->slave_addr; - p_mapping->dvo_wiring = p_child->dvo_wiring; - p_mapping->ddc_pin = p_child->ddc_pin; -+ p_mapping->i2c_pin = p_child->i2c_pin; -+ p_mapping->i2c_speed = p_child->i2c_speed; - p_mapping->initialized = 1; -+ DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n", -+ p_mapping->dvo_port, -+ p_mapping->slave_addr, -+ p_mapping->dvo_wiring, -+ p_mapping->ddc_pin, -+ p_mapping->i2c_pin, -+ p_mapping->i2c_speed); - } else { - DRM_DEBUG_KMS("Maybe one SDVO port is shared by " - "two SDVO device.\n"); -@@ -409,14 +402,11 @@ parse_driver_features(struct drm_i915_private *dev_priv, - if (!driver) - return; - -- if (driver && SUPPORTS_EDP(dev) && -- driver->lvds_config == BDB_DRIVER_FEATURE_EDP) { -- dev_priv->edp_support = 1; -- } else { -- dev_priv->edp_support = 0; -- } -+ if (SUPPORTS_EDP(dev) && -+ driver->lvds_config == BDB_DRIVER_FEATURE_EDP) -+ dev_priv->edp.support = 1; - -- if (driver && driver->dual_frequency) -+ if (driver->dual_frequency) - dev_priv->render_reclock_avail = true; - } - -@@ -424,27 +414,78 @@ static void - parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) - { - struct bdb_edp *edp; -+ struct edp_power_seq *edp_pps; -+ struct edp_link_params *edp_link_params; - - edp = find_section(bdb, BDB_EDP); - if (!edp) { -- if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { -+ if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { - DRM_DEBUG_KMS("No eDP BDB found but eDP panel " -- "supported, assume 18bpp panel color " -- "depth.\n"); -- dev_priv->edp_bpp = 18; -+ "supported, assume %dbpp panel color " -+ "depth.\n", -+ dev_priv->edp.bpp); - } - return; - } - - switch ((edp->color_depth >> (panel_type * 2)) & 3) { - case EDP_18BPP: -- dev_priv->edp_bpp = 18; -+ dev_priv->edp.bpp = 18; - break; - case EDP_24BPP: -- dev_priv->edp_bpp = 24; -+ dev_priv->edp.bpp = 24; - break; - case EDP_30BPP: -- dev_priv->edp_bpp = 30; -+ dev_priv->edp.bpp = 30; -+ break; -+ } -+ -+ /* Get the eDP sequencing and link info */ -+ edp_pps = &edp->power_seqs[panel_type]; -+ edp_link_params = &edp->link_params[panel_type]; -+ -+ dev_priv->edp.pps = *edp_pps; -+ -+ dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 : -+ DP_LINK_BW_1_62; -+ switch (edp_link_params->lanes) { -+ case 0: -+ dev_priv->edp.lanes = 1; -+ break; -+ case 1: -+ dev_priv->edp.lanes = 2; -+ break; -+ case 3: -+ default: -+ dev_priv->edp.lanes = 4; -+ break; -+ } -+ switch (edp_link_params->preemphasis) { -+ case 0: -+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0; -+ break; -+ case 1: -+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5; -+ break; -+ case 2: -+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6; -+ break; -+ case 3: -+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5; -+ break; -+ } -+ switch (edp_link_params->vswing) { -+ case 0: -+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400; -+ break; -+ case 1: -+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600; -+ break; -+ case 2: -+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800; -+ break; -+ case 3: -+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200; - break; - } - } -@@ -460,7 +501,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, - - p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (!p_defs) { -- DRM_DEBUG_KMS("No general definition block is found\n"); -+ DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); - return; - } - /* judge whether the size of child device meets the requirements. -@@ -513,50 +554,83 @@ parse_device_mapping(struct drm_i915_private *dev_priv, - } - return; - } -+ -+static void -+init_vbt_defaults(struct drm_i915_private *dev_priv) -+{ -+ dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC; -+ -+ /* LFP panel data */ -+ dev_priv->lvds_dither = 1; -+ dev_priv->lvds_vbt = 0; -+ -+ /* SDVO panel data */ -+ dev_priv->sdvo_lvds_vbt_mode = NULL; -+ -+ /* general features */ -+ dev_priv->int_tv_support = 1; -+ dev_priv->int_crt_support = 1; -+ dev_priv->lvds_use_ssc = 0; -+ -+ /* eDP data */ -+ dev_priv->edp.bpp = 18; -+} -+ - /** -- * intel_init_bios - initialize VBIOS settings & find VBT -+ * intel_parse_bios - find VBT and initialize settings from the BIOS - * @dev: DRM device - * - * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers - * to appropriate values. - * -- * VBT existence is a sanity check that is relied on by other i830_bios.c code. -- * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may -- * feed an updated VBT back through that, compared to what we'll fetch using -- * this method of groping around in the BIOS data. -- * - * Returns 0 on success, nonzero on failure. - */ - bool --intel_init_bios(struct drm_device *dev) -+intel_parse_bios(struct drm_device *dev) - { - struct drm_i915_private *dev_priv = dev->dev_private; - struct pci_dev *pdev = dev->pdev; -- struct vbt_header *vbt = NULL; -- struct bdb_header *bdb; -- u8 __iomem *bios; -- size_t size; -- int i; -- -- bios = pci_map_rom(pdev, &size); -- if (!bios) -- return -1; -- -- /* Scour memory looking for the VBT signature */ -- for (i = 0; i + 4 < size; i++) { -- if (!memcmp(bios + i, "$VBT", 4)) { -- vbt = (struct vbt_header *)(bios + i); -- break; -- } -+ struct bdb_header *bdb = NULL; -+ u8 __iomem *bios = NULL; -+ -+ init_vbt_defaults(dev_priv); -+ -+ /* XXX Should this validation be moved to intel_opregion.c? */ -+ if (dev_priv->opregion.vbt) { -+ struct vbt_header *vbt = dev_priv->opregion.vbt; -+ if (memcmp(vbt->signature, "$VBT", 4) == 0) { -+ DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n", -+ vbt->signature); -+ bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); -+ } else -+ dev_priv->opregion.vbt = NULL; - } - -- if (!vbt) { -- DRM_ERROR("VBT signature missing\n"); -- pci_unmap_rom(pdev, bios); -- return -1; -- } -+ if (bdb == NULL) { -+ struct vbt_header *vbt = NULL; -+ size_t size; -+ int i; - -- bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); -+ bios = pci_map_rom(pdev, &size); -+ if (!bios) -+ return -1; -+ -+ /* Scour memory looking for the VBT signature */ -+ for (i = 0; i + 4 < size; i++) { -+ if (!memcmp(bios + i, "$VBT", 4)) { -+ vbt = (struct vbt_header *)(bios + i); -+ break; -+ } -+ } -+ -+ if (!vbt) { -+ DRM_ERROR("VBT signature missing\n"); -+ pci_unmap_rom(pdev, bios); -+ return -1; -+ } -+ -+ bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); -+ } - - /* Grab useful general definitions */ - parse_general_features(dev_priv, bdb); -@@ -568,7 +642,25 @@ intel_init_bios(struct drm_device *dev) - parse_driver_features(dev_priv, bdb); - parse_edp(dev_priv, bdb); - -- pci_unmap_rom(pdev, bios); -+ if (bios) -+ pci_unmap_rom(pdev, bios); - - return 0; - } -+ -+/* Ensure that vital registers have been initialised, even if the BIOS -+ * is absent or just failing to do its job. -+ */ -+void intel_setup_bios(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ -+ /* Set the Panel Power On/Off timings if uninitialized. */ -+ if ((I915_READ(PP_ON_DELAYS) == 0) && (I915_READ(PP_OFF_DELAYS) == 0)) { -+ /* Set T2 to 40ms and T5 to 200ms */ -+ I915_WRITE(PP_ON_DELAYS, 0x019007d0); -+ -+ /* Set T3 to 35ms and Tx to 200ms */ -+ I915_WRITE(PP_OFF_DELAYS, 0x015e07d0); -+ } -+} -diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h -index 4c18514..5f8e4ed 100644 ---- a/drivers/gpu/drm/i915/intel_bios.h -+++ b/drivers/gpu/drm/i915/intel_bios.h -@@ -197,7 +197,8 @@ struct bdb_general_features { - struct child_device_config { - u16 handle; - u16 device_type; -- u8 device_id[10]; /* See DEVICE_TYPE_* above */ -+ u8 i2c_speed; -+ u8 rsvd[9]; - u16 addin_offset; - u8 dvo_port; /* See Device_PORT_* above */ - u8 i2c_pin; -@@ -466,7 +467,8 @@ struct bdb_edp { - struct edp_link_params link_params[16]; - } __attribute__ ((packed)); - --bool intel_init_bios(struct drm_device *dev); -+void intel_setup_bios(struct drm_device *dev); -+bool intel_parse_bios(struct drm_device *dev); - - /* - * Driver<->VBIOS interaction occurs through scratch bits in -diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c -index 197d4f3..c55c770 100644 ---- a/drivers/gpu/drm/i915/intel_crt.c -+++ b/drivers/gpu/drm/i915/intel_crt.c -@@ -79,7 +79,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector, - if (mode->clock < 25000) - return MODE_CLOCK_LOW; - -- if (!IS_I9XX(dev)) -+ if (IS_GEN2(dev)) - max_clock = 350000; - else - max_clock = 400000; -@@ -123,7 +123,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, - * Disable separate mode multiplier used when cloning SDVO to CRT - * XXX this needs to be adjusted when we really are cloning - */ -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { - dpll_md = I915_READ(dpll_md_reg); - I915_WRITE(dpll_md_reg, - dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); -@@ -187,11 +187,12 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) - I915_WRITE(PCH_ADPA, adpa); - - if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, -- 1000, 1)) -+ 1000)) - DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); - - if (turn_off_dac) { -- I915_WRITE(PCH_ADPA, temp); -+ /* Make sure hotplug is enabled */ -+ I915_WRITE(PCH_ADPA, temp | ADPA_CRT_HOTPLUG_ENABLE); - (void)I915_READ(PCH_ADPA); - } - -@@ -244,7 +245,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) - /* wait for FORCE_DETECT to go off */ - if (wait_for((I915_READ(PORT_HOTPLUG_EN) & - CRT_HOTPLUG_FORCE_DETECT) == 0, -- 1000, 1)) -+ 1000)) - DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); - } - -@@ -261,21 +262,47 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) - return ret; - } - -+static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus) -+{ -+ u8 buf; -+ struct i2c_msg msgs[] = { -+ { -+ .addr = 0xA0, -+ .flags = 0, -+ .len = 1, -+ .buf = &buf, -+ }, -+ }; -+ /* DDC monitor detect: Does it ACK a write to 0xA0? */ -+ return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1; -+} -+ - static bool intel_crt_detect_ddc(struct drm_encoder *encoder) - { -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -+ struct intel_encoder *intel_encoder = to_intel_encoder(encoder); -+ struct drm_i915_private *dev_priv = encoder->dev->dev_private; - - /* CRT should always be at 0, but check anyway */ - if (intel_encoder->type != INTEL_OUTPUT_ANALOG) - return false; - -- return intel_ddc_probe(intel_encoder); -+ if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) { -+ DRM_DEBUG_KMS("CRT detected via DDC:0xa0\n"); -+ return true; -+ } -+ -+ if (intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin)) { -+ DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); -+ return true; -+ } -+ -+ return false; - } - - static enum drm_connector_status - intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder) - { -- struct drm_encoder *encoder = &intel_encoder->enc; -+ struct drm_encoder *encoder = &intel_encoder->base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -@@ -295,6 +322,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder - uint8_t st00; - enum drm_connector_status status; - -+ DRM_DEBUG_KMS("starting load-detect on CRT\n"); -+ - if (pipe == 0) { - bclrpat_reg = BCLRPAT_A; - vtotal_reg = VTOTAL_A; -@@ -324,9 +353,10 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder - /* Set the border color to purple. */ - I915_WRITE(bclrpat_reg, 0x500050); - -- if (IS_I9XX(dev)) { -+ if (!IS_GEN2(dev)) { - uint32_t pipeconf = I915_READ(pipeconf_reg); - I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); -+ POSTING_READ(pipeconf_reg); - /* Wait for next Vblank to substitue - * border color for Color info */ - intel_wait_for_vblank(dev, pipe); -@@ -404,34 +434,37 @@ static enum drm_connector_status - intel_crt_detect(struct drm_connector *connector, bool force) - { - struct drm_device *dev = connector->dev; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -+ struct intel_encoder *encoder = intel_attached_encoder(connector); - struct drm_crtc *crtc; - int dpms_mode; - enum drm_connector_status status; - -- if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { -- if (intel_crt_detect_hotplug(connector)) -+ if (I915_HAS_HOTPLUG(dev)) { -+ if (intel_crt_detect_hotplug(connector)) { -+ DRM_DEBUG_KMS("CRT detected via hotplug\n"); - return connector_status_connected; -- else -+ } else - return connector_status_disconnected; - } - -- if (intel_crt_detect_ddc(encoder)) -+ if (intel_crt_detect_ddc(&encoder->base)) - return connector_status_connected; - - if (!force) - return connector->status; - - /* for pre-945g platforms use load detect */ -- if (encoder->crtc && encoder->crtc->enabled) { -- status = intel_crt_load_detect(encoder->crtc, intel_encoder); -+ if (encoder->base.crtc && encoder->base.crtc->enabled) { -+ status = intel_crt_load_detect(encoder->base.crtc, encoder); - } else { -- crtc = intel_get_load_detect_pipe(intel_encoder, connector, -+ crtc = intel_get_load_detect_pipe(encoder, connector, - NULL, &dpms_mode); - if (crtc) { -- status = intel_crt_load_detect(crtc, intel_encoder); -- intel_release_load_detect_pipe(intel_encoder, -+ if (intel_crt_detect_ddc(&encoder->base)) -+ status = connector_status_connected; -+ else -+ status = intel_crt_load_detect(crtc, encoder); -+ intel_release_load_detect_pipe(encoder, - connector, dpms_mode); - } else - status = connector_status_unknown; -@@ -449,32 +482,18 @@ static void intel_crt_destroy(struct drm_connector *connector) - - static int intel_crt_get_modes(struct drm_connector *connector) - { -- int ret; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -- struct i2c_adapter *ddc_bus; - struct drm_device *dev = connector->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ int ret; - -- -- ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); -+ ret = intel_ddc_get_modes(connector, -+ &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); - if (ret || !IS_G4X(dev)) -- goto end; -+ return ret; - - /* Try to probe digital port for output in DVI-I -> VGA mode. */ -- ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); -- -- if (!ddc_bus) { -- dev_printk(KERN_ERR, &connector->dev->pdev->dev, -- "DDC bus registration failed for CRTDDC_D.\n"); -- goto end; -- } -- /* Try to get modes by GPIOD port */ -- ret = intel_ddc_get_modes(connector, ddc_bus); -- intel_i2c_destroy(ddc_bus); -- --end: -- return ret; -- -+ return intel_ddc_get_modes(connector, -+ &dev_priv->gmbus[GMBUS_PORT_DPB].adapter); - } - - static int intel_crt_set_property(struct drm_connector *connector, -@@ -507,7 +526,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = { - static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { - .mode_valid = intel_crt_mode_valid, - .get_modes = intel_crt_get_modes, -- .best_encoder = intel_attached_encoder, -+ .best_encoder = intel_best_encoder, - }; - - static const struct drm_encoder_funcs intel_crt_enc_funcs = { -@@ -520,7 +539,6 @@ void intel_crt_init(struct drm_device *dev) - struct intel_encoder *intel_encoder; - struct intel_connector *intel_connector; - struct drm_i915_private *dev_priv = dev->dev_private; -- u32 i2c_reg; - - intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); - if (!intel_encoder) -@@ -536,27 +554,10 @@ void intel_crt_init(struct drm_device *dev) - drm_connector_init(dev, &intel_connector->base, - &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); - -- drm_encoder_init(dev, &intel_encoder->enc, &intel_crt_enc_funcs, -+ drm_encoder_init(dev, &intel_encoder->base, &intel_crt_enc_funcs, - DRM_MODE_ENCODER_DAC); - -- drm_mode_connector_attach_encoder(&intel_connector->base, -- &intel_encoder->enc); -- -- /* Set up the DDC bus. */ -- if (HAS_PCH_SPLIT(dev)) -- i2c_reg = PCH_GPIOA; -- else { -- i2c_reg = GPIOA; -- /* Use VBT information for CRT DDC if available */ -- if (dev_priv->crt_ddc_bus != 0) -- i2c_reg = dev_priv->crt_ddc_bus; -- } -- intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); -- if (!intel_encoder->ddc_bus) { -- dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " -- "failed.\n"); -- return; -- } -+ intel_connector_attach_encoder(intel_connector, intel_encoder); - - intel_encoder->type = INTEL_OUTPUT_ANALOG; - intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | -@@ -566,7 +567,7 @@ void intel_crt_init(struct drm_device *dev) - connector->interlace_allowed = 1; - connector->doublescan_allowed = 0; - -- drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs); -+ drm_encoder_helper_add(&intel_encoder->base, &intel_crt_helper_funcs); - drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); - - drm_sysfs_connector_add(connector); -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 9792285..0cece04 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -43,8 +43,8 @@ - - bool intel_pipe_has_type (struct drm_crtc *crtc, int type); - static void intel_update_watermarks(struct drm_device *dev); --static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule); --static void intel_crtc_update_cursor(struct drm_crtc *crtc); -+static void intel_increase_pllclock(struct drm_crtc *crtc); -+static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); - - typedef struct { - /* given values */ -@@ -342,6 +342,16 @@ static bool - intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); - -+static inline u32 /* units of 100MHz */ -+intel_fdi_link_freq(struct drm_device *dev) -+{ -+ if (IS_GEN5(dev)) { -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2; -+ } else -+ return 27; -+} -+ - static const intel_limit_t intel_limits_i8xx_dvo = { - .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, - .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, -@@ -701,16 +711,16 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) - limit = intel_ironlake_limit(crtc); - else if (IS_G4X(dev)) { - limit = intel_g4x_limit(crtc); -- } else if (IS_I9XX(dev) && !IS_PINEVIEW(dev)) { -- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) -- limit = &intel_limits_i9xx_lvds; -- else -- limit = &intel_limits_i9xx_sdvo; - } else if (IS_PINEVIEW(dev)) { - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits_pineview_lvds; - else - limit = &intel_limits_pineview_sdvo; -+ } else if (!IS_GEN2(dev)) { -+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) -+ limit = &intel_limits_i9xx_lvds; -+ else -+ limit = &intel_limits_i9xx_sdvo; - } else { - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits_i8xx_lvds; -@@ -744,20 +754,17 @@ static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock - /** - * Returns whether any output on the specified pipe is of the specified type - */ --bool intel_pipe_has_type (struct drm_crtc *crtc, int type) -+bool intel_pipe_has_type(struct drm_crtc *crtc, int type) - { -- struct drm_device *dev = crtc->dev; -- struct drm_mode_config *mode_config = &dev->mode_config; -- struct drm_encoder *l_entry; -+ struct drm_device *dev = crtc->dev; -+ struct drm_mode_config *mode_config = &dev->mode_config; -+ struct intel_encoder *encoder; - -- list_for_each_entry(l_entry, &mode_config->encoder_list, head) { -- if (l_entry && l_entry->crtc == crtc) { -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(l_entry); -- if (intel_encoder->type == type) -- return true; -- } -- } -- return false; -+ list_for_each_entry(encoder, &mode_config->encoder_list, base.head) -+ if (encoder->base.crtc == crtc && encoder->type == type) -+ return true; -+ -+ return false; - } - - #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) -@@ -928,10 +935,6 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, - struct drm_device *dev = crtc->dev; - intel_clock_t clock; - -- /* return directly when it is eDP */ -- if (HAS_eDP) -- return true; -- - if (target < 200000) { - clock.n = 1; - clock.p1 = 2; -@@ -955,26 +958,26 @@ static bool - intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) - { -- intel_clock_t clock; -- if (target < 200000) { -- clock.p1 = 2; -- clock.p2 = 10; -- clock.n = 2; -- clock.m1 = 23; -- clock.m2 = 8; -- } else { -- clock.p1 = 1; -- clock.p2 = 10; -- clock.n = 1; -- clock.m1 = 14; -- clock.m2 = 2; -- } -- clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); -- clock.p = (clock.p1 * clock.p2); -- clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; -- clock.vco = 0; -- memcpy(best_clock, &clock, sizeof(intel_clock_t)); -- return true; -+ intel_clock_t clock; -+ if (target < 200000) { -+ clock.p1 = 2; -+ clock.p2 = 10; -+ clock.n = 2; -+ clock.m1 = 23; -+ clock.m2 = 8; -+ } else { -+ clock.p1 = 1; -+ clock.p2 = 10; -+ clock.n = 1; -+ clock.m1 = 14; -+ clock.m2 = 2; -+ } -+ clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); -+ clock.p = (clock.p1 * clock.p2); -+ clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; -+ clock.vco = 0; -+ memcpy(best_clock, &clock, sizeof(intel_clock_t)); -+ return true; - } - - /** -@@ -1007,9 +1010,9 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) - I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS); - - /* Wait for vblank interrupt bit to set */ -- if (wait_for((I915_READ(pipestat_reg) & -- PIPE_VBLANK_INTERRUPT_STATUS), -- 50, 0)) -+ if (wait_for(I915_READ(pipestat_reg) & -+ PIPE_VBLANK_INTERRUPT_STATUS, -+ 50)) - DRM_DEBUG_KMS("vblank wait timed out\n"); - } - -@@ -1028,36 +1031,35 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) - * Otherwise: - * wait for the display line value to settle (it usually - * ends up stopping at the start of the next frame). -- * -+ * - */ --static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) -+void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) - { - struct drm_i915_private *dev_priv = dev->dev_private; - - if (INTEL_INFO(dev)->gen >= 4) { -- int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF); -+ int reg = PIPECONF(pipe); - - /* Wait for the Pipe State to go off */ -- if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, -- 100, 0)) -+ if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, -+ 100)) - DRM_DEBUG_KMS("pipe_off wait timed out\n"); - } else { - u32 last_line; -- int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); -+ int reg = PIPEDSL(pipe); - unsigned long timeout = jiffies + msecs_to_jiffies(100); - - /* Wait for the display line to settle */ - do { -- last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; -+ last_line = I915_READ(reg) & DSL_LINEMASK; - mdelay(5); -- } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && -+ } while (((I915_READ(reg) & DSL_LINEMASK) != last_line) && - time_after(timeout, jiffies)); - if (time_after(jiffies, timeout)) - DRM_DEBUG_KMS("pipe_off wait timed out\n"); - } - } - --/* Parameters have changed, update FBC info */ - static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - { - struct drm_device *dev = crtc->dev; -@@ -1069,6 +1071,14 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - int plane, i; - u32 fbc_ctl, fbc_ctl2; - -+ if (fb->pitch == dev_priv->cfb_pitch && -+ obj_priv->fence_reg == dev_priv->cfb_fence && -+ intel_crtc->plane == dev_priv->cfb_plane && -+ I915_READ(FBC_CONTROL) & FBC_CTL_EN) -+ return; -+ -+ i8xx_disable_fbc(dev); -+ - dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; - - if (fb->pitch < dev_priv->cfb_pitch) -@@ -1102,7 +1112,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - I915_WRITE(FBC_CONTROL, fbc_ctl); - - DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ", -- dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); -+ dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); - } - - void i8xx_disable_fbc(struct drm_device *dev) -@@ -1110,19 +1120,16 @@ void i8xx_disable_fbc(struct drm_device *dev) - struct drm_i915_private *dev_priv = dev->dev_private; - u32 fbc_ctl; - -- if (!I915_HAS_FBC(dev)) -- return; -- -- if (!(I915_READ(FBC_CONTROL) & FBC_CTL_EN)) -- return; /* Already off, just return */ -- - /* Disable compression */ - fbc_ctl = I915_READ(FBC_CONTROL); -+ if ((fbc_ctl & FBC_CTL_EN) == 0) -+ return; -+ - fbc_ctl &= ~FBC_CTL_EN; - I915_WRITE(FBC_CONTROL, fbc_ctl); - - /* Wait for compressing bit to clear */ -- if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10, 0)) { -+ if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) { - DRM_DEBUG_KMS("FBC idle timed out\n"); - return; - } -@@ -1145,14 +1152,27 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : -- DPFC_CTL_PLANEB); -+ int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; - unsigned long stall_watermark = 200; - u32 dpfc_ctl; - -+ dpfc_ctl = I915_READ(DPFC_CONTROL); -+ if (dpfc_ctl & DPFC_CTL_EN) { -+ if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 && -+ dev_priv->cfb_fence == obj_priv->fence_reg && -+ dev_priv->cfb_plane == intel_crtc->plane && -+ dev_priv->cfb_y == crtc->y) -+ return; -+ -+ I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN); -+ POSTING_READ(DPFC_CONTROL); -+ intel_wait_for_vblank(dev, intel_crtc->pipe); -+ } -+ - dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; - dev_priv->cfb_fence = obj_priv->fence_reg; - dev_priv->cfb_plane = intel_crtc->plane; -+ dev_priv->cfb_y = crtc->y; - - dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; - if (obj_priv->tiling_mode != I915_TILING_NONE) { -@@ -1162,7 +1182,6 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY); - } - -- I915_WRITE(DPFC_CONTROL, dpfc_ctl); - I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | - (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | - (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); -@@ -1181,10 +1200,12 @@ void g4x_disable_fbc(struct drm_device *dev) - - /* Disable compression */ - dpfc_ctl = I915_READ(DPFC_CONTROL); -- dpfc_ctl &= ~DPFC_CTL_EN; -- I915_WRITE(DPFC_CONTROL, dpfc_ctl); -+ if (dpfc_ctl & DPFC_CTL_EN) { -+ dpfc_ctl &= ~DPFC_CTL_EN; -+ I915_WRITE(DPFC_CONTROL, dpfc_ctl); - -- DRM_DEBUG_KMS("disabled FBC\n"); -+ DRM_DEBUG_KMS("disabled FBC\n"); -+ } - } - - static bool g4x_fbc_enabled(struct drm_device *dev) -@@ -1202,16 +1223,30 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- int plane = (intel_crtc->plane == 0) ? DPFC_CTL_PLANEA : -- DPFC_CTL_PLANEB; -+ int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; - unsigned long stall_watermark = 200; - u32 dpfc_ctl; - -+ dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); -+ if (dpfc_ctl & DPFC_CTL_EN) { -+ if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 && -+ dev_priv->cfb_fence == obj_priv->fence_reg && -+ dev_priv->cfb_plane == intel_crtc->plane && -+ dev_priv->cfb_offset == obj_priv->gtt_offset && -+ dev_priv->cfb_y == crtc->y) -+ return; -+ -+ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN); -+ POSTING_READ(ILK_DPFC_CONTROL); -+ intel_wait_for_vblank(dev, intel_crtc->pipe); -+ } -+ - dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; - dev_priv->cfb_fence = obj_priv->fence_reg; - dev_priv->cfb_plane = intel_crtc->plane; -+ dev_priv->cfb_offset = obj_priv->gtt_offset; -+ dev_priv->cfb_y = crtc->y; - -- dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); - dpfc_ctl &= DPFC_RESERVED; - dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); - if (obj_priv->tiling_mode != I915_TILING_NONE) { -@@ -1221,15 +1256,13 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY); - } - -- I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | - (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | - (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); - I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); - I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID); - /* enable it... */ -- I915_WRITE(ILK_DPFC_CONTROL, I915_READ(ILK_DPFC_CONTROL) | -- DPFC_CTL_EN); -+ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); - - DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); - } -@@ -1241,10 +1274,12 @@ void ironlake_disable_fbc(struct drm_device *dev) - - /* Disable compression */ - dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); -- dpfc_ctl &= ~DPFC_CTL_EN; -- I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); -+ if (dpfc_ctl & DPFC_CTL_EN) { -+ dpfc_ctl &= ~DPFC_CTL_EN; -+ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - -- DRM_DEBUG_KMS("disabled FBC\n"); -+ DRM_DEBUG_KMS("disabled FBC\n"); -+ } - } - - static bool ironlake_fbc_enabled(struct drm_device *dev) -@@ -1286,8 +1321,7 @@ void intel_disable_fbc(struct drm_device *dev) - - /** - * intel_update_fbc - enable/disable FBC as needed -- * @crtc: CRTC to point the compressor at -- * @mode: mode in use -+ * @dev: the drm_device - * - * Set up the framebuffer compression hardware at mode set time. We - * enable it if possible: -@@ -1304,18 +1338,14 @@ void intel_disable_fbc(struct drm_device *dev) - * - * We need to enable/disable FBC on a global basis. - */ --static void intel_update_fbc(struct drm_crtc *crtc, -- struct drm_display_mode *mode) -+static void intel_update_fbc(struct drm_device *dev) - { -- struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- struct drm_framebuffer *fb = crtc->fb; -+ struct drm_crtc *crtc = NULL, *tmp_crtc; -+ struct intel_crtc *intel_crtc; -+ struct drm_framebuffer *fb; - struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj_priv; -- struct drm_crtc *tmp_crtc; -- struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- int plane = intel_crtc->plane; -- int crtcs_enabled = 0; - - DRM_DEBUG_KMS("\n"); - -@@ -1325,12 +1355,6 @@ static void intel_update_fbc(struct drm_crtc *crtc, - if (!I915_HAS_FBC(dev)) - return; - -- if (!crtc->fb) -- return; -- -- intel_fb = to_intel_framebuffer(fb); -- obj_priv = to_intel_bo(intel_fb->obj); -- - /* - * If FBC is already on, we just have to verify that we can - * keep it that way... -@@ -1341,35 +1365,47 @@ static void intel_update_fbc(struct drm_crtc *crtc, - * - going to an unsupported config (interlace, pixel multiply, etc.) - */ - list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { -- if (tmp_crtc->enabled) -- crtcs_enabled++; -+ if (tmp_crtc->enabled) { -+ if (crtc) { -+ DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); -+ dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; -+ goto out_disable; -+ } -+ crtc = tmp_crtc; -+ } - } -- DRM_DEBUG_KMS("%d pipes active\n", crtcs_enabled); -- if (crtcs_enabled > 1) { -- DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); -- dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; -+ -+ if (!crtc || crtc->fb == NULL) { -+ DRM_DEBUG_KMS("no output, disabling\n"); -+ dev_priv->no_fbc_reason = FBC_NO_OUTPUT; - goto out_disable; - } -+ -+ intel_crtc = to_intel_crtc(crtc); -+ fb = crtc->fb; -+ intel_fb = to_intel_framebuffer(fb); -+ obj_priv = to_intel_bo(intel_fb->obj); -+ - if (intel_fb->obj->size > dev_priv->cfb_size) { - DRM_DEBUG_KMS("framebuffer too large, disabling " -- "compression\n"); -+ "compression\n"); - dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; - goto out_disable; - } -- if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || -- (mode->flags & DRM_MODE_FLAG_DBLSCAN)) { -+ if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || -+ (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { - DRM_DEBUG_KMS("mode incompatible with compression, " -- "disabling\n"); -+ "disabling\n"); - dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; - goto out_disable; - } -- if ((mode->hdisplay > 2048) || -- (mode->vdisplay > 1536)) { -+ if ((crtc->mode.hdisplay > 2048) || -+ (crtc->mode.vdisplay > 1536)) { - DRM_DEBUG_KMS("mode too large for compression, disabling\n"); - dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE; - goto out_disable; - } -- if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) { -+ if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) { - DRM_DEBUG_KMS("plane not 0, disabling compression\n"); - dev_priv->no_fbc_reason = FBC_BAD_PLANE; - goto out_disable; -@@ -1384,18 +1420,7 @@ static void intel_update_fbc(struct drm_crtc *crtc, - if (in_dbg_master()) - goto out_disable; - -- if (intel_fbc_enabled(dev)) { -- /* We can re-enable it in this case, but need to update pitch */ -- if ((fb->pitch > dev_priv->cfb_pitch) || -- (obj_priv->fence_reg != dev_priv->cfb_fence) || -- (plane != dev_priv->cfb_plane)) -- intel_disable_fbc(dev); -- } -- -- /* Now try to turn it back on if possible */ -- if (!intel_fbc_enabled(dev)) -- intel_enable_fbc(crtc, 500); -- -+ intel_enable_fbc(crtc, 500); - return; - - out_disable: -@@ -1407,7 +1432,9 @@ out_disable: - } - - int --intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) -+intel_pin_and_fence_fb_obj(struct drm_device *dev, -+ struct drm_gem_object *obj, -+ bool pipelined) - { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - u32 alignment; -@@ -1417,7 +1444,7 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) - case I915_TILING_NONE: - if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) - alignment = 128 * 1024; -- else if (IS_I965G(dev)) -+ else if (INTEL_INFO(dev)->gen >= 4) - alignment = 4 * 1024; - else - alignment = 64 * 1024; -@@ -1435,9 +1462,13 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) - } - - ret = i915_gem_object_pin(obj, alignment); -- if (ret != 0) -+ if (ret) - return ret; - -+ ret = i915_gem_object_set_to_display_plane(obj, pipelined); -+ if (ret) -+ goto err_unpin; -+ - /* Install a fence for tiled scan-out. Pre-i965 always needs a - * fence, whereas 965+ only requires a fence if using - * framebuffer compression. For simplicity, we always install -@@ -1445,14 +1476,16 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) - */ - if (obj_priv->fence_reg == I915_FENCE_REG_NONE && - obj_priv->tiling_mode != I915_TILING_NONE) { -- ret = i915_gem_object_get_fence_reg(obj); -- if (ret != 0) { -- i915_gem_object_unpin(obj); -- return ret; -- } -+ ret = i915_gem_object_get_fence_reg(obj, false); -+ if (ret) -+ goto err_unpin; - } - - return 0; -+ -+err_unpin: -+ i915_gem_object_unpin(obj); -+ return ret; - } - - /* Assume fb object is pinned & idle & fenced and just update base pointers */ -@@ -1468,12 +1501,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_gem_object *obj; - int plane = intel_crtc->plane; - unsigned long Start, Offset; -- int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR); -- int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF); -- int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; -- int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); -- int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr; -+ u32 reg; - - switch (plane) { - case 0: -@@ -1488,7 +1517,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - obj = intel_fb->obj; - obj_priv = to_intel_bo(obj); - -- dspcntr = I915_READ(dspcntr_reg); -+ reg = DSPCNTR(plane); -+ dspcntr = I915_READ(reg); - /* Mask out pixel format bits in case we change it */ - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - switch (fb->bits_per_pixel) { -@@ -1509,7 +1539,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - DRM_ERROR("Unknown color depth\n"); - return -EINVAL; - } -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - if (obj_priv->tiling_mode != I915_TILING_NONE) - dspcntr |= DISPPLANE_TILED; - else -@@ -1520,28 +1550,24 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - /* must disable */ - dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - -- I915_WRITE(dspcntr_reg, dspcntr); -+ I915_WRITE(reg, dspcntr); - - Start = obj_priv->gtt_offset; - Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); - - DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", - Start, Offset, x, y, fb->pitch); -- I915_WRITE(dspstride, fb->pitch); -- if (IS_I965G(dev)) { -- I915_WRITE(dspsurf, Start); -- I915_WRITE(dsptileoff, (y << 16) | x); -- I915_WRITE(dspbase, Offset); -- } else { -- I915_WRITE(dspbase, Start + Offset); -- } -- POSTING_READ(dspbase); -- -- if (IS_I965G(dev) || plane == 0) -- intel_update_fbc(crtc, &crtc->mode); -+ I915_WRITE(DSPSTRIDE(plane), fb->pitch); -+ if (INTEL_INFO(dev)->gen >= 4) { -+ I915_WRITE(DSPSURF(plane), Start); -+ I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); -+ I915_WRITE(DSPADDR(plane), Offset); -+ } else -+ I915_WRITE(DSPADDR(plane), Start + Offset); -+ POSTING_READ(reg); - -- intel_wait_for_vblank(dev, intel_crtc->pipe); -- intel_increase_pllclock(crtc, true); -+ intel_update_fbc(dev); -+ intel_increase_pllclock(crtc); - - return 0; - } -@@ -1553,11 +1579,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_device *dev = crtc->dev; - struct drm_i915_master_private *master_priv; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- struct intel_framebuffer *intel_fb; -- struct drm_i915_gem_object *obj_priv; -- struct drm_gem_object *obj; -- int pipe = intel_crtc->pipe; -- int plane = intel_crtc->plane; - int ret; - - /* no fb bound */ -@@ -1566,45 +1587,41 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, - return 0; - } - -- switch (plane) { -+ switch (intel_crtc->plane) { - case 0: - case 1: - break; - default: -- DRM_ERROR("Can't update plane %d in SAREA\n", plane); - return -EINVAL; - } - -- intel_fb = to_intel_framebuffer(crtc->fb); -- obj = intel_fb->obj; -- obj_priv = to_intel_bo(obj); -- - mutex_lock(&dev->struct_mutex); -- ret = intel_pin_and_fence_fb_obj(dev, obj); -+ ret = intel_pin_and_fence_fb_obj(dev, -+ to_intel_framebuffer(crtc->fb)->obj, -+ false); - if (ret != 0) { - mutex_unlock(&dev->struct_mutex); - return ret; - } - -- ret = i915_gem_object_set_to_display_plane(obj); -- if (ret != 0) { -- i915_gem_object_unpin(obj); -- mutex_unlock(&dev->struct_mutex); -- return ret; -+ if (old_fb) { -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct drm_gem_object *obj = to_intel_framebuffer(old_fb)->obj; -+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); -+ -+ wait_event(dev_priv->pending_flip_queue, -+ atomic_read(&obj_priv->pending_flip) == 0); - } - - ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y); - if (ret) { -- i915_gem_object_unpin(obj); -+ i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); - mutex_unlock(&dev->struct_mutex); - return ret; - } - -- if (old_fb) { -- intel_fb = to_intel_framebuffer(old_fb); -- obj_priv = to_intel_bo(intel_fb->obj); -- i915_gem_object_unpin(intel_fb->obj); -- } -+ if (old_fb) -+ i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj); - - mutex_unlock(&dev->struct_mutex); - -@@ -1615,7 +1632,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, - if (!master_priv->sarea_priv) - return 0; - -- if (pipe) { -+ if (intel_crtc->pipe) { - master_priv->sarea_priv->pipeB_x = x; - master_priv->sarea_priv->pipeB_y = y; - } else { -@@ -1626,7 +1643,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, - return 0; - } - --static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) -+static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) - { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -@@ -1659,9 +1676,41 @@ static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) - } - I915_WRITE(DP_A, dpa_ctl); - -+ POSTING_READ(DP_A); - udelay(500); - } - -+static void intel_fdi_normal_train(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ u32 reg, temp; -+ -+ /* enable normal train */ -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); -+ temp &= ~FDI_LINK_TRAIN_NONE; -+ temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; -+ I915_WRITE(reg, temp); -+ -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); -+ if (HAS_PCH_CPT(dev)) { -+ temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; -+ temp |= FDI_LINK_TRAIN_NORMAL_CPT; -+ } else { -+ temp &= ~FDI_LINK_TRAIN_NONE; -+ temp |= FDI_LINK_TRAIN_NONE; -+ } -+ I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); -+ -+ /* wait one idle pattern time */ -+ POSTING_READ(reg); -+ udelay(1000); -+} -+ - /* The FDI link training functions for ILK/Ibexpeak. */ - static void ironlake_fdi_link_train(struct drm_crtc *crtc) - { -@@ -1669,84 +1718,88 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; -- int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; -- int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; -- int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR; -- int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR; -- u32 temp, tries = 0; -+ u32 reg, temp, tries; - - /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit - for train result */ -- temp = I915_READ(fdi_rx_imr_reg); -+ reg = FDI_RX_IMR(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_RX_SYMBOL_LOCK; - temp &= ~FDI_RX_BIT_LOCK; -- I915_WRITE(fdi_rx_imr_reg, temp); -- I915_READ(fdi_rx_imr_reg); -+ I915_WRITE(reg, temp); -+ I915_READ(reg); - udelay(150); - - /* enable CPU FDI TX and PCH FDI RX */ -- temp = I915_READ(fdi_tx_reg); -- temp |= FDI_TX_ENABLE; -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~(7 << 19); - temp |= (intel_crtc->fdi_lanes - 1) << 19; - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_1; -- I915_WRITE(fdi_tx_reg, temp); -- I915_READ(fdi_tx_reg); -+ I915_WRITE(reg, temp | FDI_TX_ENABLE); - -- temp = I915_READ(fdi_rx_reg); -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_1; -- I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE); -- I915_READ(fdi_rx_reg); -+ I915_WRITE(reg, temp | FDI_RX_ENABLE); -+ -+ POSTING_READ(reg); - udelay(150); - -+ /* Ironlake workaround, enable clock pointer after FDI enable*/ -+ I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_ENABLE); -+ -+ reg = FDI_RX_IIR(pipe); - for (tries = 0; tries < 5; tries++) { -- temp = I915_READ(fdi_rx_iir_reg); -+ temp = I915_READ(reg); - DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); - - if ((temp & FDI_RX_BIT_LOCK)) { - DRM_DEBUG_KMS("FDI train 1 done.\n"); -- I915_WRITE(fdi_rx_iir_reg, -- temp | FDI_RX_BIT_LOCK); -+ I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); - break; - } - } - if (tries == 5) -- DRM_DEBUG_KMS("FDI train 1 fail!\n"); -+ DRM_ERROR("FDI train 1 fail!\n"); - - /* Train 2 */ -- temp = I915_READ(fdi_tx_reg); -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_2; -- I915_WRITE(fdi_tx_reg, temp); -+ I915_WRITE(reg, temp); - -- temp = I915_READ(fdi_rx_reg); -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_2; -- I915_WRITE(fdi_rx_reg, temp); -- udelay(150); -+ I915_WRITE(reg, temp); - -- tries = 0; -+ POSTING_READ(reg); -+ udelay(150); - -+ reg = FDI_RX_IIR(pipe); - for (tries = 0; tries < 5; tries++) { -- temp = I915_READ(fdi_rx_iir_reg); -+ temp = I915_READ(reg); - DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); - - if (temp & FDI_RX_SYMBOL_LOCK) { -- I915_WRITE(fdi_rx_iir_reg, -- temp | FDI_RX_SYMBOL_LOCK); -+ I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); - DRM_DEBUG_KMS("FDI train 2 done.\n"); - break; - } - } - if (tries == 5) -- DRM_DEBUG_KMS("FDI train 2 fail!\n"); -+ DRM_ERROR("FDI train 2 fail!\n"); - - DRM_DEBUG_KMS("FDI train done\n"); -+ - } - --static int snb_b_fdi_train_param [] = { -+static const int const snb_b_fdi_train_param [] = { - FDI_LINK_TRAIN_400MV_0DB_SNB_B, - FDI_LINK_TRAIN_400MV_6DB_SNB_B, - FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, -@@ -1760,24 +1813,22 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; -- int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; -- int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; -- int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR; -- int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR; -- u32 temp, i; -+ u32 reg, temp, i; - - /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit - for train result */ -- temp = I915_READ(fdi_rx_imr_reg); -+ reg = FDI_RX_IMR(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_RX_SYMBOL_LOCK; - temp &= ~FDI_RX_BIT_LOCK; -- I915_WRITE(fdi_rx_imr_reg, temp); -- I915_READ(fdi_rx_imr_reg); -+ I915_WRITE(reg, temp); -+ -+ POSTING_READ(reg); - udelay(150); - - /* enable CPU FDI TX and PCH FDI RX */ -- temp = I915_READ(fdi_tx_reg); -- temp |= FDI_TX_ENABLE; -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~(7 << 19); - temp |= (intel_crtc->fdi_lanes - 1) << 19; - temp &= ~FDI_LINK_TRAIN_NONE; -@@ -1785,10 +1836,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) - temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; - /* SNB-B */ - temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; -- I915_WRITE(fdi_tx_reg, temp); -- I915_READ(fdi_tx_reg); -+ I915_WRITE(reg, temp | FDI_TX_ENABLE); - -- temp = I915_READ(fdi_rx_reg); -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); - if (HAS_PCH_CPT(dev)) { - temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; - temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; -@@ -1796,32 +1847,37 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_1; - } -- I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE); -- I915_READ(fdi_rx_reg); -+ I915_WRITE(reg, temp | FDI_RX_ENABLE); -+ -+ POSTING_READ(reg); - udelay(150); - - for (i = 0; i < 4; i++ ) { -- temp = I915_READ(fdi_tx_reg); -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; - temp |= snb_b_fdi_train_param[i]; -- I915_WRITE(fdi_tx_reg, temp); -+ I915_WRITE(reg, temp); -+ -+ POSTING_READ(reg); - udelay(500); - -- temp = I915_READ(fdi_rx_iir_reg); -+ reg = FDI_RX_IIR(pipe); -+ temp = I915_READ(reg); - DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); - - if (temp & FDI_RX_BIT_LOCK) { -- I915_WRITE(fdi_rx_iir_reg, -- temp | FDI_RX_BIT_LOCK); -+ I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); - DRM_DEBUG_KMS("FDI train 1 done.\n"); - break; - } - } - if (i == 4) -- DRM_DEBUG_KMS("FDI train 1 fail!\n"); -+ DRM_ERROR("FDI train 1 fail!\n"); - - /* Train 2 */ -- temp = I915_READ(fdi_tx_reg); -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_2; - if (IS_GEN6(dev)) { -@@ -1829,9 +1885,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) - /* SNB-B */ - temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; - } -- I915_WRITE(fdi_tx_reg, temp); -+ I915_WRITE(reg, temp); - -- temp = I915_READ(fdi_rx_reg); -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); - if (HAS_PCH_CPT(dev)) { - temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; - temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; -@@ -1839,535 +1896,596 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_2; - } -- I915_WRITE(fdi_rx_reg, temp); -+ I915_WRITE(reg, temp); -+ -+ POSTING_READ(reg); - udelay(150); - - for (i = 0; i < 4; i++ ) { -- temp = I915_READ(fdi_tx_reg); -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; - temp |= snb_b_fdi_train_param[i]; -- I915_WRITE(fdi_tx_reg, temp); -+ I915_WRITE(reg, temp); -+ -+ POSTING_READ(reg); - udelay(500); - -- temp = I915_READ(fdi_rx_iir_reg); -+ reg = FDI_RX_IIR(pipe); -+ temp = I915_READ(reg); - DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); - - if (temp & FDI_RX_SYMBOL_LOCK) { -- I915_WRITE(fdi_rx_iir_reg, -- temp | FDI_RX_SYMBOL_LOCK); -+ I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); - DRM_DEBUG_KMS("FDI train 2 done.\n"); - break; - } - } - if (i == 4) -- DRM_DEBUG_KMS("FDI train 2 fail!\n"); -+ DRM_ERROR("FDI train 2 fail!\n"); - - DRM_DEBUG_KMS("FDI train done.\n"); - } - --static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) -+static void ironlake_fdi_enable(struct drm_crtc *crtc) - { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; -- int plane = intel_crtc->plane; -- int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; -- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -- int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; -- int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR; -- int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; -- int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; -- int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF; -- int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -- int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -- int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -- int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -- int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -- int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -- int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B; -- int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B; -- int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B; -- int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B; -- int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B; -- int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B; -- int trans_dpll_sel = (pipe == 0) ? 0 : 1; -- u32 temp; -- u32 pipe_bpc; -- -- temp = I915_READ(pipeconf_reg); -- pipe_bpc = temp & PIPE_BPC_MASK; -+ u32 reg, temp; - -- /* XXX: When our outputs are all unaware of DPMS modes other than off -- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -- */ -- switch (mode) { -- case DRM_MODE_DPMS_ON: -- case DRM_MODE_DPMS_STANDBY: -- case DRM_MODE_DPMS_SUSPEND: -- DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane); -+ /* Write the TU size bits so error detection works */ -+ I915_WRITE(FDI_RX_TUSIZE1(pipe), -+ I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK); - -- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -- temp = I915_READ(PCH_LVDS); -- if ((temp & LVDS_PORT_EN) == 0) { -- I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); -- POSTING_READ(PCH_LVDS); -- } -- } -+ /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); -+ temp &= ~((0x7 << 19) | (0x7 << 16)); -+ temp |= (intel_crtc->fdi_lanes - 1) << 19; -+ temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; -+ I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE); - -- if (!HAS_eDP) { -+ POSTING_READ(reg); -+ udelay(200); - -- /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ -- temp = I915_READ(fdi_rx_reg); -- /* -- * make the BPC in FDI Rx be consistent with that in -- * pipeconf reg. -- */ -- temp &= ~(0x7 << 16); -- temp |= (pipe_bpc << 11); -- temp &= ~(7 << 19); -- temp |= (intel_crtc->fdi_lanes - 1) << 19; -- I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); -- I915_READ(fdi_rx_reg); -- udelay(200); -+ /* Switch from Rawclk to PCDclk */ -+ temp = I915_READ(reg); -+ I915_WRITE(reg, temp | FDI_PCDCLK); - -- /* Switch from Rawclk to PCDclk */ -- temp = I915_READ(fdi_rx_reg); -- I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK); -- I915_READ(fdi_rx_reg); -- udelay(200); -+ POSTING_READ(reg); -+ udelay(200); - -- /* Enable CPU FDI TX PLL, always on for Ironlake */ -- temp = I915_READ(fdi_tx_reg); -- if ((temp & FDI_TX_PLL_ENABLE) == 0) { -- I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); -- I915_READ(fdi_tx_reg); -- udelay(100); -- } -- } -+ /* Enable CPU FDI TX PLL, always on for Ironlake */ -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); -+ if ((temp & FDI_TX_PLL_ENABLE) == 0) { -+ I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE); - -- /* Enable panel fitting for LVDS */ -- if (dev_priv->pch_pf_size && -- (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) -- || HAS_eDP || intel_pch_has_edp(crtc))) { -- /* Force use of hard-coded filter coefficients -- * as some pre-programmed values are broken, -- * e.g. x201. -- */ -- I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, -- PF_ENABLE | PF_FILTER_MED_3x3); -- I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS, -- dev_priv->pch_pf_pos); -- I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, -- dev_priv->pch_pf_size); -- } -+ POSTING_READ(reg); -+ udelay(100); -+ } -+} - -- /* Enable CPU pipe */ -- temp = I915_READ(pipeconf_reg); -- if ((temp & PIPEACONF_ENABLE) == 0) { -- I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); -- I915_READ(pipeconf_reg); -- udelay(100); -- } -+static void intel_flush_display_plane(struct drm_device *dev, -+ int plane) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 reg = DSPADDR(plane); -+ I915_WRITE(reg, I915_READ(reg)); -+} - -- /* configure and enable CPU plane */ -- temp = I915_READ(dspcntr_reg); -- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -- I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); -- /* Flush the plane changes */ -- I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); -- } -+/* -+ * When we disable a pipe, we need to clear any pending scanline wait events -+ * to avoid hanging the ring, which we assume we are waiting on. -+ */ -+static void intel_clear_scanline_wait(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 tmp; - -- if (!HAS_eDP) { -- /* For PCH output, training FDI link */ -- if (IS_GEN6(dev)) -- gen6_fdi_link_train(crtc); -- else -- ironlake_fdi_link_train(crtc); -+ if (IS_GEN2(dev)) -+ /* Can't break the hang on i8xx */ -+ return; - -- /* enable PCH DPLL */ -- temp = I915_READ(pch_dpll_reg); -- if ((temp & DPLL_VCO_ENABLE) == 0) { -- I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE); -- I915_READ(pch_dpll_reg); -- } -- udelay(200); -+ tmp = I915_READ(PRB0_CTL); -+ if (tmp & RING_WAIT) { -+ I915_WRITE(PRB0_CTL, tmp); -+ POSTING_READ(PRB0_CTL); -+ } -+} - -- if (HAS_PCH_CPT(dev)) { -- /* Be sure PCH DPLL SEL is set */ -- temp = I915_READ(PCH_DPLL_SEL); -- if (trans_dpll_sel == 0 && -- (temp & TRANSA_DPLL_ENABLE) == 0) -- temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); -- else if (trans_dpll_sel == 1 && -- (temp & TRANSB_DPLL_ENABLE) == 0) -- temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); -- I915_WRITE(PCH_DPLL_SEL, temp); -- I915_READ(PCH_DPLL_SEL); -- } -+static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) -+{ -+ struct drm_i915_gem_object *obj_priv; -+ struct drm_i915_private *dev_priv; - -- /* set transcoder timing */ -- I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg)); -- I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg)); -- I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg)); -- -- I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg)); -- I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg)); -- I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg)); -- -- /* enable normal train */ -- temp = I915_READ(fdi_tx_reg); -- temp &= ~FDI_LINK_TRAIN_NONE; -- I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE | -- FDI_TX_ENHANCE_FRAME_ENABLE); -- I915_READ(fdi_tx_reg); -- -- temp = I915_READ(fdi_rx_reg); -- if (HAS_PCH_CPT(dev)) { -- temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; -- temp |= FDI_LINK_TRAIN_NORMAL_CPT; -- } else { -- temp &= ~FDI_LINK_TRAIN_NONE; -- temp |= FDI_LINK_TRAIN_NONE; -- } -- I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); -- I915_READ(fdi_rx_reg); -+ if (crtc->fb == NULL) -+ return; - -- /* wait one idle pattern time */ -- udelay(100); -+ obj_priv = to_intel_bo(to_intel_framebuffer(crtc->fb)->obj); -+ dev_priv = crtc->dev->dev_private; -+ wait_event(dev_priv->pending_flip_queue, -+ atomic_read(&obj_priv->pending_flip) == 0); -+} - -- /* For PCH DP, enable TRANS_DP_CTL */ -- if (HAS_PCH_CPT(dev) && -- intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { -- int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; -- int reg; -- -- reg = I915_READ(trans_dp_ctl); -- reg &= ~(TRANS_DP_PORT_SEL_MASK | -- TRANS_DP_SYNC_MASK); -- reg |= (TRANS_DP_OUTPUT_ENABLE | -- TRANS_DP_ENH_FRAMING); -- -- if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) -- reg |= TRANS_DP_HSYNC_ACTIVE_HIGH; -- if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) -- reg |= TRANS_DP_VSYNC_ACTIVE_HIGH; -- -- switch (intel_trans_dp_port_sel(crtc)) { -- case PCH_DP_B: -- reg |= TRANS_DP_PORT_SEL_B; -- break; -- case PCH_DP_C: -- reg |= TRANS_DP_PORT_SEL_C; -- break; -- case PCH_DP_D: -- reg |= TRANS_DP_PORT_SEL_D; -- break; -- default: -- DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n"); -- reg |= TRANS_DP_PORT_SEL_B; -- break; -- } -+static void ironlake_crtc_enable(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int plane = intel_crtc->plane; -+ u32 reg, temp; - -- I915_WRITE(trans_dp_ctl, reg); -- POSTING_READ(trans_dp_ctl); -- } -+ if (intel_crtc->active) -+ return; - -- /* enable PCH transcoder */ -- temp = I915_READ(transconf_reg); -- /* -- * make the BPC in transcoder be consistent with -- * that in pipeconf reg. -- */ -- temp &= ~PIPE_BPC_MASK; -- temp |= pipe_bpc; -- I915_WRITE(transconf_reg, temp | TRANS_ENABLE); -- I915_READ(transconf_reg); -+ intel_crtc->active = true; -+ intel_update_watermarks(dev); - -- if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100, 1)) -- DRM_ERROR("failed to enable transcoder\n"); -- } -+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -+ temp = I915_READ(PCH_LVDS); -+ if ((temp & LVDS_PORT_EN) == 0) -+ I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); -+ } - -- intel_crtc_load_lut(crtc); -+ ironlake_fdi_enable(crtc); - -- intel_update_fbc(crtc, &crtc->mode); -- break; -+ /* Enable panel fitting for LVDS */ -+ if (dev_priv->pch_pf_size && -+ (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) { -+ /* Force use of hard-coded filter coefficients -+ * as some pre-programmed values are broken, -+ * e.g. x201. -+ */ -+ I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, -+ PF_ENABLE | PF_FILTER_MED_3x3); -+ I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS, -+ dev_priv->pch_pf_pos); -+ I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, -+ dev_priv->pch_pf_size); -+ } -+ -+ /* Enable CPU pipe */ -+ reg = PIPECONF(pipe); -+ temp = I915_READ(reg); -+ if ((temp & PIPECONF_ENABLE) == 0) { -+ I915_WRITE(reg, temp | PIPECONF_ENABLE); -+ POSTING_READ(reg); -+ intel_wait_for_vblank(dev, intel_crtc->pipe); -+ } -+ -+ /* configure and enable CPU plane */ -+ reg = DSPCNTR(plane); -+ temp = I915_READ(reg); -+ if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -+ I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); -+ intel_flush_display_plane(dev, plane); -+ } -+ -+ /* For PCH output, training FDI link */ -+ if (IS_GEN6(dev)) -+ gen6_fdi_link_train(crtc); -+ else -+ ironlake_fdi_link_train(crtc); -+ -+ /* enable PCH DPLL */ -+ reg = PCH_DPLL(pipe); -+ temp = I915_READ(reg); -+ if ((temp & DPLL_VCO_ENABLE) == 0) { -+ I915_WRITE(reg, temp | DPLL_VCO_ENABLE); -+ POSTING_READ(reg); -+ udelay(200); -+ } - -- case DRM_MODE_DPMS_OFF: -- DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane); -+ if (HAS_PCH_CPT(dev)) { -+ /* Be sure PCH DPLL SEL is set */ -+ temp = I915_READ(PCH_DPLL_SEL); -+ if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0) -+ temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); -+ else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0) -+ temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); -+ I915_WRITE(PCH_DPLL_SEL, temp); -+ } -+ -+ /* set transcoder timing */ -+ I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe))); -+ I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe))); -+ I915_WRITE(TRANS_HSYNC(pipe), I915_READ(HSYNC(pipe))); -+ -+ I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe))); -+ I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe))); -+ I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe))); -+ -+ intel_fdi_normal_train(crtc); -+ -+ /* For PCH DP, enable TRANS_DP_CTL */ -+ if (HAS_PCH_CPT(dev) && -+ intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { -+ reg = TRANS_DP_CTL(pipe); -+ temp = I915_READ(reg); -+ temp &= ~(TRANS_DP_PORT_SEL_MASK | -+ TRANS_DP_SYNC_MASK); -+ temp |= (TRANS_DP_OUTPUT_ENABLE | -+ TRANS_DP_ENH_FRAMING); - -- drm_vblank_off(dev, pipe); -- /* Disable display plane */ -- temp = I915_READ(dspcntr_reg); -- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -- I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); -- /* Flush the plane changes */ -- I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); -- I915_READ(dspbase_reg); -+ if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) -+ temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; -+ if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) -+ temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; -+ -+ switch (intel_trans_dp_port_sel(crtc)) { -+ case PCH_DP_B: -+ temp |= TRANS_DP_PORT_SEL_B; -+ break; -+ case PCH_DP_C: -+ temp |= TRANS_DP_PORT_SEL_C; -+ break; -+ case PCH_DP_D: -+ temp |= TRANS_DP_PORT_SEL_D; -+ break; -+ default: -+ DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n"); -+ temp |= TRANS_DP_PORT_SEL_B; -+ break; - } - -- if (dev_priv->cfb_plane == plane && -- dev_priv->display.disable_fbc) -- dev_priv->display.disable_fbc(dev); -+ I915_WRITE(reg, temp); -+ } - -- /* disable cpu pipe, disable after all planes disabled */ -- temp = I915_READ(pipeconf_reg); -- if ((temp & PIPEACONF_ENABLE) != 0) { -- I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); -+ /* enable PCH transcoder */ -+ reg = TRANSCONF(pipe); -+ temp = I915_READ(reg); -+ /* -+ * make the BPC in transcoder be consistent with -+ * that in pipeconf reg. -+ */ -+ temp &= ~PIPE_BPC_MASK; -+ temp |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK; -+ I915_WRITE(reg, temp | TRANS_ENABLE); -+ if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) -+ DRM_ERROR("failed to enable transcoder %d\n", pipe); - -- /* wait for cpu pipe off, pipe state */ -- if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, 50, 1)) -- DRM_ERROR("failed to turn off cpu pipe\n"); -- } else -- DRM_DEBUG_KMS("crtc %d is disabled\n", pipe); -+ intel_crtc_load_lut(crtc); -+ intel_update_fbc(dev); -+ intel_crtc_update_cursor(crtc, true); -+} - -- udelay(100); -+static void ironlake_crtc_disable(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int plane = intel_crtc->plane; -+ u32 reg, temp; - -- /* Disable PF */ -- I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); -- I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); -+ if (!intel_crtc->active) -+ return; - -- /* disable CPU FDI tx and PCH FDI rx */ -- temp = I915_READ(fdi_tx_reg); -- I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE); -- I915_READ(fdi_tx_reg); -+ intel_crtc_wait_for_pending_flips(crtc); -+ drm_vblank_off(dev, pipe); -+ intel_crtc_update_cursor(crtc, false); - -- temp = I915_READ(fdi_rx_reg); -- /* BPC in FDI rx is consistent with that in pipeconf */ -- temp &= ~(0x07 << 16); -- temp |= (pipe_bpc << 11); -- I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE); -- I915_READ(fdi_rx_reg); -+ /* Disable display plane */ -+ reg = DSPCNTR(plane); -+ temp = I915_READ(reg); -+ if (temp & DISPLAY_PLANE_ENABLE) { -+ I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); -+ intel_flush_display_plane(dev, plane); -+ } - -- udelay(100); -+ if (dev_priv->cfb_plane == plane && -+ dev_priv->display.disable_fbc) -+ dev_priv->display.disable_fbc(dev); - -- /* still set train pattern 1 */ -- temp = I915_READ(fdi_tx_reg); -+ /* disable cpu pipe, disable after all planes disabled */ -+ reg = PIPECONF(pipe); -+ temp = I915_READ(reg); -+ if (temp & PIPECONF_ENABLE) { -+ I915_WRITE(reg, temp & ~PIPECONF_ENABLE); -+ POSTING_READ(reg); -+ /* wait for cpu pipe off, pipe state */ -+ intel_wait_for_pipe_off(dev, intel_crtc->pipe); -+ } -+ -+ /* Disable PF */ -+ I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); -+ I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); -+ -+ /* disable CPU FDI tx and PCH FDI rx */ -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); -+ I915_WRITE(reg, temp & ~FDI_TX_ENABLE); -+ POSTING_READ(reg); -+ -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); -+ temp &= ~(0x7 << 16); -+ temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; -+ I915_WRITE(reg, temp & ~FDI_RX_ENABLE); -+ -+ POSTING_READ(reg); -+ udelay(100); -+ -+ /* Ironlake workaround, disable clock pointer after downing FDI */ -+ if (HAS_PCH_IBX(dev)) -+ I915_WRITE(FDI_RX_CHICKEN(pipe), -+ I915_READ(FDI_RX_CHICKEN(pipe) & -+ ~FDI_RX_PHASE_SYNC_POINTER_ENABLE)); -+ -+ /* still set train pattern 1 */ -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); -+ temp &= ~FDI_LINK_TRAIN_NONE; -+ temp |= FDI_LINK_TRAIN_PATTERN_1; -+ I915_WRITE(reg, temp); -+ -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); -+ if (HAS_PCH_CPT(dev)) { -+ temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; -+ temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; -+ } else { - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_PATTERN_1; -- I915_WRITE(fdi_tx_reg, temp); -- POSTING_READ(fdi_tx_reg); -- -- temp = I915_READ(fdi_rx_reg); -- if (HAS_PCH_CPT(dev)) { -- temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; -- temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; -- } else { -- temp &= ~FDI_LINK_TRAIN_NONE; -- temp |= FDI_LINK_TRAIN_PATTERN_1; -- } -- I915_WRITE(fdi_rx_reg, temp); -- POSTING_READ(fdi_rx_reg); -+ } -+ /* BPC in FDI rx is consistent with that in PIPECONF */ -+ temp &= ~(0x07 << 16); -+ temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; -+ I915_WRITE(reg, temp); - -- udelay(100); -+ POSTING_READ(reg); -+ udelay(100); - -- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -- temp = I915_READ(PCH_LVDS); -+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -+ temp = I915_READ(PCH_LVDS); -+ if (temp & LVDS_PORT_EN) { - I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); -- I915_READ(PCH_LVDS); -+ POSTING_READ(PCH_LVDS); - udelay(100); - } -+ } - -- /* disable PCH transcoder */ -- temp = I915_READ(transconf_reg); -- if ((temp & TRANS_ENABLE) != 0) { -- I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE); -+ /* disable PCH transcoder */ -+ reg = TRANSCONF(plane); -+ temp = I915_READ(reg); -+ if (temp & TRANS_ENABLE) { -+ I915_WRITE(reg, temp & ~TRANS_ENABLE); -+ /* wait for PCH transcoder off, transcoder state */ -+ if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) -+ DRM_ERROR("failed to disable transcoder\n"); -+ } - -- /* wait for PCH transcoder off, transcoder state */ -- if (wait_for((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0, 50, 1)) -- DRM_ERROR("failed to disable transcoder\n"); -- } -+ if (HAS_PCH_CPT(dev)) { -+ /* disable TRANS_DP_CTL */ -+ reg = TRANS_DP_CTL(pipe); -+ temp = I915_READ(reg); -+ temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); -+ I915_WRITE(reg, temp); - -- temp = I915_READ(transconf_reg); -- /* BPC in transcoder is consistent with that in pipeconf */ -- temp &= ~PIPE_BPC_MASK; -- temp |= pipe_bpc; -- I915_WRITE(transconf_reg, temp); -- I915_READ(transconf_reg); -- udelay(100); -+ /* disable DPLL_SEL */ -+ temp = I915_READ(PCH_DPLL_SEL); -+ if (pipe == 0) -+ temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL); -+ else -+ temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); -+ I915_WRITE(PCH_DPLL_SEL, temp); -+ } - -- if (HAS_PCH_CPT(dev)) { -- /* disable TRANS_DP_CTL */ -- int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; -- int reg; -+ /* disable PCH DPLL */ -+ reg = PCH_DPLL(pipe); -+ temp = I915_READ(reg); -+ I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE); - -- reg = I915_READ(trans_dp_ctl); -- reg &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); -- I915_WRITE(trans_dp_ctl, reg); -- POSTING_READ(trans_dp_ctl); -+ /* Switch from PCDclk to Rawclk */ -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); -+ I915_WRITE(reg, temp & ~FDI_PCDCLK); - -- /* disable DPLL_SEL */ -- temp = I915_READ(PCH_DPLL_SEL); -- if (trans_dpll_sel == 0) -- temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL); -- else -- temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); -- I915_WRITE(PCH_DPLL_SEL, temp); -- I915_READ(PCH_DPLL_SEL); -+ /* Disable CPU FDI TX PLL */ -+ reg = FDI_TX_CTL(pipe); -+ temp = I915_READ(reg); -+ I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE); - -- } -+ POSTING_READ(reg); -+ udelay(100); - -- /* disable PCH DPLL */ -- temp = I915_READ(pch_dpll_reg); -- I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE); -- I915_READ(pch_dpll_reg); -- -- /* Switch from PCDclk to Rawclk */ -- temp = I915_READ(fdi_rx_reg); -- temp &= ~FDI_SEL_PCDCLK; -- I915_WRITE(fdi_rx_reg, temp); -- I915_READ(fdi_rx_reg); -- -- /* Disable CPU FDI TX PLL */ -- temp = I915_READ(fdi_tx_reg); -- I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE); -- I915_READ(fdi_tx_reg); -- udelay(100); -+ reg = FDI_RX_CTL(pipe); -+ temp = I915_READ(reg); -+ I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE); - -- temp = I915_READ(fdi_rx_reg); -- temp &= ~FDI_RX_PLL_ENABLE; -- I915_WRITE(fdi_rx_reg, temp); -- I915_READ(fdi_rx_reg); -+ /* Wait for the clocks to turn off. */ -+ POSTING_READ(reg); -+ udelay(100); - -- /* Wait for the clocks to turn off. */ -- udelay(100); -+ intel_crtc->active = false; -+ intel_update_watermarks(dev); -+ intel_update_fbc(dev); -+ intel_clear_scanline_wait(dev); -+} -+ -+static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) -+{ -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int plane = intel_crtc->plane; -+ -+ /* XXX: When our outputs are all unaware of DPMS modes other than off -+ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -+ */ -+ switch (mode) { -+ case DRM_MODE_DPMS_ON: -+ case DRM_MODE_DPMS_STANDBY: -+ case DRM_MODE_DPMS_SUSPEND: -+ DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane); -+ ironlake_crtc_enable(crtc); -+ break; -+ -+ case DRM_MODE_DPMS_OFF: -+ DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane); -+ ironlake_crtc_disable(crtc); - break; - } - } - - static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) - { -- struct intel_overlay *overlay; -- int ret; -- - if (!enable && intel_crtc->overlay) { -- overlay = intel_crtc->overlay; -- mutex_lock(&overlay->dev->struct_mutex); -- for (;;) { -- ret = intel_overlay_switch_off(overlay); -- if (ret == 0) -- break; -+ struct drm_device *dev = intel_crtc->base.dev; - -- ret = intel_overlay_recover_from_interrupt(overlay, 0); -- if (ret != 0) { -- /* overlay doesn't react anymore. Usually -- * results in a black screen and an unkillable -- * X server. */ -- BUG(); -- overlay->hw_wedged = HW_WEDGED; -- break; -- } -- } -- mutex_unlock(&overlay->dev->struct_mutex); -+ mutex_lock(&dev->struct_mutex); -+ (void) intel_overlay_switch_off(intel_crtc->overlay, false); -+ mutex_unlock(&dev->struct_mutex); - } -- /* Let userspace switch the overlay on again. In most cases userspace -- * has to recompute where to put it anyway. */ - -- return; -+ /* Let userspace switch the overlay on again. In most cases userspace -+ * has to recompute where to put it anyway. -+ */ - } - --static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) -+static void i9xx_crtc_enable(struct drm_crtc *crtc) - { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - int plane = intel_crtc->plane; -- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -- int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; -- int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR; -- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -- u32 temp; -+ u32 reg, temp; - -- /* XXX: When our outputs are all unaware of DPMS modes other than off -- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -- */ -- switch (mode) { -- case DRM_MODE_DPMS_ON: -- case DRM_MODE_DPMS_STANDBY: -- case DRM_MODE_DPMS_SUSPEND: -- /* Enable the DPLL */ -- temp = I915_READ(dpll_reg); -- if ((temp & DPLL_VCO_ENABLE) == 0) { -- I915_WRITE(dpll_reg, temp); -- I915_READ(dpll_reg); -- /* Wait for the clocks to stabilize. */ -- udelay(150); -- I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -- I915_READ(dpll_reg); -- /* Wait for the clocks to stabilize. */ -- udelay(150); -- I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -- I915_READ(dpll_reg); -- /* Wait for the clocks to stabilize. */ -- udelay(150); -- } -+ if (intel_crtc->active) -+ return; - -- /* Enable the pipe */ -- temp = I915_READ(pipeconf_reg); -- if ((temp & PIPEACONF_ENABLE) == 0) -- I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); -- -- /* Enable the plane */ -- temp = I915_READ(dspcntr_reg); -- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -- I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); -- /* Flush the plane changes */ -- I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); -- } -+ intel_crtc->active = true; -+ intel_update_watermarks(dev); - -- intel_crtc_load_lut(crtc); -+ /* Enable the DPLL */ -+ reg = DPLL(pipe); -+ temp = I915_READ(reg); -+ if ((temp & DPLL_VCO_ENABLE) == 0) { -+ I915_WRITE(reg, temp); - -- if ((IS_I965G(dev) || plane == 0)) -- intel_update_fbc(crtc, &crtc->mode); -+ /* Wait for the clocks to stabilize. */ -+ POSTING_READ(reg); -+ udelay(150); - -- /* Give the overlay scaler a chance to enable if it's on this pipe */ -- intel_crtc_dpms_overlay(intel_crtc, true); -- break; -- case DRM_MODE_DPMS_OFF: -- /* Give the overlay scaler a chance to disable if it's on this pipe */ -- intel_crtc_dpms_overlay(intel_crtc, false); -- drm_vblank_off(dev, pipe); -- -- if (dev_priv->cfb_plane == plane && -- dev_priv->display.disable_fbc) -- dev_priv->display.disable_fbc(dev); -- -- /* Disable display plane */ -- temp = I915_READ(dspcntr_reg); -- if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -- I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); -- /* Flush the plane changes */ -- I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); -- I915_READ(dspbase_reg); -- } -+ I915_WRITE(reg, temp | DPLL_VCO_ENABLE); -+ -+ /* Wait for the clocks to stabilize. */ -+ POSTING_READ(reg); -+ udelay(150); -+ -+ I915_WRITE(reg, temp | DPLL_VCO_ENABLE); - -- /* Don't disable pipe A or pipe A PLLs if needed */ -- if (pipeconf_reg == PIPEACONF && -- (dev_priv->quirks & QUIRK_PIPEA_FORCE)) { -- /* Wait for vblank for the disable to take effect */ -+ /* Wait for the clocks to stabilize. */ -+ POSTING_READ(reg); -+ udelay(150); -+ } -+ -+ /* Enable the pipe */ -+ reg = PIPECONF(pipe); -+ temp = I915_READ(reg); -+ if ((temp & PIPECONF_ENABLE) == 0) -+ I915_WRITE(reg, temp | PIPECONF_ENABLE); -+ -+ /* Enable the plane */ -+ reg = DSPCNTR(plane); -+ temp = I915_READ(reg); -+ if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -+ I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); -+ intel_flush_display_plane(dev, plane); -+ } -+ -+ intel_crtc_load_lut(crtc); -+ intel_update_fbc(dev); -+ -+ /* Give the overlay scaler a chance to enable if it's on this pipe */ -+ intel_crtc_dpms_overlay(intel_crtc, true); -+ intel_crtc_update_cursor(crtc, true); -+} -+ -+static void i9xx_crtc_disable(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int plane = intel_crtc->plane; -+ u32 reg, temp; -+ -+ if (!intel_crtc->active) -+ return; -+ -+ /* Give the overlay scaler a chance to disable if it's on this pipe */ -+ intel_crtc_wait_for_pending_flips(crtc); -+ drm_vblank_off(dev, pipe); -+ intel_crtc_dpms_overlay(intel_crtc, false); -+ intel_crtc_update_cursor(crtc, false); -+ -+ if (dev_priv->cfb_plane == plane && -+ dev_priv->display.disable_fbc) -+ dev_priv->display.disable_fbc(dev); -+ -+ /* Disable display plane */ -+ reg = DSPCNTR(plane); -+ temp = I915_READ(reg); -+ if (temp & DISPLAY_PLANE_ENABLE) { -+ I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); -+ /* Flush the plane changes */ -+ intel_flush_display_plane(dev, plane); -+ -+ /* Wait for vblank for the disable to take effect */ -+ if (IS_GEN2(dev)) - intel_wait_for_vblank(dev, pipe); -- goto skip_pipe_off; -- } -+ } - -- /* Next, disable display pipes */ -- temp = I915_READ(pipeconf_reg); -- if ((temp & PIPEACONF_ENABLE) != 0) { -- I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); -- I915_READ(pipeconf_reg); -- } -+ /* Don't disable pipe A or pipe A PLLs if needed */ -+ if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) -+ goto done; -+ -+ /* Next, disable display pipes */ -+ reg = PIPECONF(pipe); -+ temp = I915_READ(reg); -+ if (temp & PIPECONF_ENABLE) { -+ I915_WRITE(reg, temp & ~PIPECONF_ENABLE); - - /* Wait for the pipe to turn off */ -+ POSTING_READ(reg); - intel_wait_for_pipe_off(dev, pipe); -+ } -+ -+ reg = DPLL(pipe); -+ temp = I915_READ(reg); -+ if (temp & DPLL_VCO_ENABLE) { -+ I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE); - -- temp = I915_READ(dpll_reg); -- if ((temp & DPLL_VCO_ENABLE) != 0) { -- I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); -- I915_READ(dpll_reg); -- } -- skip_pipe_off: - /* Wait for the clocks to turn off. */ -+ POSTING_READ(reg); - udelay(150); -+ } -+ -+done: -+ intel_crtc->active = false; -+ intel_update_fbc(dev); -+ intel_update_watermarks(dev); -+ intel_clear_scanline_wait(dev); -+} -+ -+static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) -+{ -+ /* XXX: When our outputs are all unaware of DPMS modes other than off -+ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -+ */ -+ switch (mode) { -+ case DRM_MODE_DPMS_ON: -+ case DRM_MODE_DPMS_STANDBY: -+ case DRM_MODE_DPMS_SUSPEND: -+ i9xx_crtc_enable(crtc); -+ break; -+ case DRM_MODE_DPMS_OFF: -+ i9xx_crtc_disable(crtc); - break; - } - } -@@ -2388,26 +2506,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) - return; - - intel_crtc->dpms_mode = mode; -- intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON; -- -- /* When switching on the display, ensure that SR is disabled -- * with multiple pipes prior to enabling to new pipe. -- * -- * When switching off the display, make sure the cursor is -- * properly hidden prior to disabling the pipe. -- */ -- if (mode == DRM_MODE_DPMS_ON) -- intel_update_watermarks(dev); -- else -- intel_crtc_update_cursor(crtc); - - dev_priv->display.dpms(crtc, mode); - -- if (mode == DRM_MODE_DPMS_ON) -- intel_crtc_update_cursor(crtc); -- else -- intel_update_watermarks(dev); -- - if (!dev->primary->master) - return; - -@@ -2432,16 +2533,46 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) - } - } - --static void intel_crtc_prepare (struct drm_crtc *crtc) -+static void intel_crtc_disable(struct drm_crtc *crtc) - { - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -+ struct drm_device *dev = crtc->dev; -+ - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -+ -+ if (crtc->fb) { -+ mutex_lock(&dev->struct_mutex); -+ i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); -+ mutex_unlock(&dev->struct_mutex); -+ } -+} -+ -+/* Prepare for a mode set. -+ * -+ * Note we could be a lot smarter here. We need to figure out which outputs -+ * will be enabled, which disabled (in short, how the config will changes) -+ * and perform the minimum necessary steps to accomplish that, e.g. updating -+ * watermarks, FBC configuration, making sure PLLs are programmed correctly, -+ * panel fitting is in the proper state, etc. -+ */ -+static void i9xx_crtc_prepare(struct drm_crtc *crtc) -+{ -+ i9xx_crtc_disable(crtc); - } - --static void intel_crtc_commit (struct drm_crtc *crtc) -+static void i9xx_crtc_commit(struct drm_crtc *crtc) - { -- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -+ i9xx_crtc_enable(crtc); -+} -+ -+static void ironlake_crtc_prepare(struct drm_crtc *crtc) -+{ -+ ironlake_crtc_disable(crtc); -+} -+ -+static void ironlake_crtc_commit(struct drm_crtc *crtc) -+{ -+ ironlake_crtc_enable(crtc); - } - - void intel_encoder_prepare (struct drm_encoder *encoder) -@@ -2460,13 +2591,7 @@ void intel_encoder_commit (struct drm_encoder *encoder) - - void intel_encoder_destroy(struct drm_encoder *encoder) - { -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -- -- if (intel_encoder->ddc_bus) -- intel_i2c_destroy(intel_encoder->ddc_bus); -- -- if (intel_encoder->i2c_bus) -- intel_i2c_destroy(intel_encoder->i2c_bus); -+ struct intel_encoder *intel_encoder = to_intel_encoder(encoder); - - drm_encoder_cleanup(encoder); - kfree(intel_encoder); -@@ -2557,33 +2682,6 @@ static int i830_get_display_clock_speed(struct drm_device *dev) - return 133000; - } - --/** -- * Return the pipe currently connected to the panel fitter, -- * or -1 if the panel fitter is not present or not in use -- */ --int intel_panel_fitter_pipe (struct drm_device *dev) --{ -- struct drm_i915_private *dev_priv = dev->dev_private; -- u32 pfit_control; -- -- /* i830 doesn't have a panel fitter */ -- if (IS_I830(dev)) -- return -1; -- -- pfit_control = I915_READ(PFIT_CONTROL); -- -- /* See if the panel fitter is in use */ -- if ((pfit_control & PFIT_ENABLE) == 0) -- return -1; -- -- /* 965 can place panel fitter on either pipe */ -- if (IS_I965G(dev)) -- return (pfit_control >> 29) & 0x3; -- -- /* older chips can only use pipe 1 */ -- return 1; --} -- - struct fdi_m_n { - u32 tu; - u32 gmch_m; -@@ -2902,7 +3000,7 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane) - size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; - - DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, -- plane ? "B" : "A", size); -+ plane ? "B" : "A", size); - - return size; - } -@@ -2919,7 +3017,7 @@ static int i85x_get_fifo_size(struct drm_device *dev, int plane) - size >>= 1; /* Convert to cachelines */ - - DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, -- plane ? "B" : "A", size); -+ plane ? "B" : "A", size); - - return size; - } -@@ -2934,8 +3032,8 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane) - size >>= 2; /* Convert to cachelines */ - - DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, -- plane ? "B" : "A", -- size); -+ plane ? "B" : "A", -+ size); - - return size; - } -@@ -2950,14 +3048,14 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) - size >>= 1; /* Convert to cachelines */ - - DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, -- plane ? "B" : "A", size); -+ plane ? "B" : "A", size); - - return size; - } - - static void pineview_update_wm(struct drm_device *dev, int planea_clock, -- int planeb_clock, int sr_hdisplay, int unused, -- int pixel_size) -+ int planeb_clock, int sr_hdisplay, int unused, -+ int pixel_size) - { - struct drm_i915_private *dev_priv = dev->dev_private; - const struct cxsr_latency *latency; -@@ -3069,13 +3167,13 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, - - /* Use ns/us then divide to preserve precision */ - sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * -- pixel_size * sr_hdisplay; -+ pixel_size * sr_hdisplay; - sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); - - entries_required = (((sr_latency_ns / line_time_us) + - 1000) / 1000) * pixel_size * 64; - entries_required = DIV_ROUND_UP(entries_required, -- g4x_cursor_wm_info.cacheline_size); -+ g4x_cursor_wm_info.cacheline_size); - cursor_sr = entries_required + g4x_cursor_wm_info.guard_size; - - if (cursor_sr > g4x_cursor_wm_info.max_wm) -@@ -3087,7 +3185,7 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, - } else { - /* Turn off self refresh if both pipes are enabled */ - I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) -- & ~FW_BLC_SELF_EN); -+ & ~FW_BLC_SELF_EN); - } - - DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", -@@ -3125,7 +3223,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, - - /* Use ns/us then divide to preserve precision */ - sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * -- pixel_size * sr_hdisplay; -+ pixel_size * sr_hdisplay; - sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE); - DRM_DEBUG("self-refresh entries: %d\n", sr_entries); - srwm = I965_FIFO_SIZE - sr_entries; -@@ -3134,11 +3232,11 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, - srwm &= 0x1ff; - - sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * -- pixel_size * 64; -+ pixel_size * 64; - sr_entries = DIV_ROUND_UP(sr_entries, - i965_cursor_wm_info.cacheline_size); - cursor_sr = i965_cursor_wm_info.fifo_size - -- (sr_entries + i965_cursor_wm_info.guard_size); -+ (sr_entries + i965_cursor_wm_info.guard_size); - - if (cursor_sr > i965_cursor_wm_info.max_wm) - cursor_sr = i965_cursor_wm_info.max_wm; -@@ -3146,11 +3244,11 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, - DRM_DEBUG_KMS("self-refresh watermark: display plane %d " - "cursor %d\n", srwm, cursor_sr); - -- if (IS_I965GM(dev)) -+ if (IS_CRESTLINE(dev)) - I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); - } else { - /* Turn off self refresh if both pipes are enabled */ -- if (IS_I965GM(dev)) -+ if (IS_CRESTLINE(dev)) - I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) - & ~FW_BLC_SELF_EN); - } -@@ -3180,9 +3278,9 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, - int sr_clock, sr_entries = 0; - - /* Create copies of the base settings for each pipe */ -- if (IS_I965GM(dev) || IS_I945GM(dev)) -+ if (IS_CRESTLINE(dev) || IS_I945GM(dev)) - planea_params = planeb_params = i945_wm_info; -- else if (IS_I9XX(dev)) -+ else if (!IS_GEN2(dev)) - planea_params = planeb_params = i915_wm_info; - else - planea_params = planeb_params = i855_wm_info; -@@ -3217,7 +3315,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, - - /* Use ns/us then divide to preserve precision */ - sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * -- pixel_size * sr_hdisplay; -+ pixel_size * sr_hdisplay; - sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); - DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries); - srwm = total_size - sr_entries; -@@ -3242,7 +3340,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, - } - - DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", -- planea_wm, planeb_wm, cwm, srwm); -+ planea_wm, planeb_wm, cwm, srwm); - - fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f); - fwater_hi = (cwm & 0x1f); -@@ -3276,146 +3374,130 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, - #define ILK_LP0_PLANE_LATENCY 700 - #define ILK_LP0_CURSOR_LATENCY 1300 - --static void ironlake_update_wm(struct drm_device *dev, int planea_clock, -- int planeb_clock, int sr_hdisplay, int sr_htotal, -- int pixel_size) -+static bool ironlake_compute_wm0(struct drm_device *dev, -+ int pipe, -+ int *plane_wm, -+ int *cursor_wm) - { -- struct drm_i915_private *dev_priv = dev->dev_private; -- int planea_wm, planeb_wm, cursora_wm, cursorb_wm; -- int sr_wm, cursor_wm; -- unsigned long line_time_us; -- int sr_clock, entries_required; -- u32 reg_value; -- int line_count; -- int planea_htotal = 0, planeb_htotal = 0; - struct drm_crtc *crtc; -+ int htotal, hdisplay, clock, pixel_size = 0; -+ int line_time_us, line_count, entries; - -- /* Need htotal for all active display plane */ -- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -- struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- if (intel_crtc->dpms_mode == DRM_MODE_DPMS_ON) { -- if (intel_crtc->plane == 0) -- planea_htotal = crtc->mode.htotal; -- else -- planeb_htotal = crtc->mode.htotal; -- } -- } -- -- /* Calculate and update the watermark for plane A */ -- if (planea_clock) { -- entries_required = ((planea_clock / 1000) * pixel_size * -- ILK_LP0_PLANE_LATENCY) / 1000; -- entries_required = DIV_ROUND_UP(entries_required, -- ironlake_display_wm_info.cacheline_size); -- planea_wm = entries_required + -- ironlake_display_wm_info.guard_size; -- -- if (planea_wm > (int)ironlake_display_wm_info.max_wm) -- planea_wm = ironlake_display_wm_info.max_wm; -- -- /* Use the large buffer method to calculate cursor watermark */ -- line_time_us = (planea_htotal * 1000) / planea_clock; -- -- /* Use ns/us then divide to preserve precision */ -- line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; -- -- /* calculate the cursor watermark for cursor A */ -- entries_required = line_count * 64 * pixel_size; -- entries_required = DIV_ROUND_UP(entries_required, -- ironlake_cursor_wm_info.cacheline_size); -- cursora_wm = entries_required + ironlake_cursor_wm_info.guard_size; -- if (cursora_wm > ironlake_cursor_wm_info.max_wm) -- cursora_wm = ironlake_cursor_wm_info.max_wm; -- -- reg_value = I915_READ(WM0_PIPEA_ILK); -- reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); -- reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) | -- (cursora_wm & WM0_PIPE_CURSOR_MASK); -- I915_WRITE(WM0_PIPEA_ILK, reg_value); -- DRM_DEBUG_KMS("FIFO watermarks For pipe A - plane %d, " -- "cursor: %d\n", planea_wm, cursora_wm); -- } -- /* Calculate and update the watermark for plane B */ -- if (planeb_clock) { -- entries_required = ((planeb_clock / 1000) * pixel_size * -- ILK_LP0_PLANE_LATENCY) / 1000; -- entries_required = DIV_ROUND_UP(entries_required, -- ironlake_display_wm_info.cacheline_size); -- planeb_wm = entries_required + -- ironlake_display_wm_info.guard_size; -- -- if (planeb_wm > (int)ironlake_display_wm_info.max_wm) -- planeb_wm = ironlake_display_wm_info.max_wm; -+ crtc = intel_get_crtc_for_pipe(dev, pipe); -+ if (crtc->fb == NULL || !crtc->enabled) -+ return false; - -- /* Use the large buffer method to calculate cursor watermark */ -- line_time_us = (planeb_htotal * 1000) / planeb_clock; -+ htotal = crtc->mode.htotal; -+ hdisplay = crtc->mode.hdisplay; -+ clock = crtc->mode.clock; -+ pixel_size = crtc->fb->bits_per_pixel / 8; -+ -+ /* Use the small buffer method to calculate plane watermark */ -+ entries = ((clock * pixel_size / 1000) * ILK_LP0_PLANE_LATENCY) / 1000; -+ entries = DIV_ROUND_UP(entries, -+ ironlake_display_wm_info.cacheline_size); -+ *plane_wm = entries + ironlake_display_wm_info.guard_size; -+ if (*plane_wm > (int)ironlake_display_wm_info.max_wm) -+ *plane_wm = ironlake_display_wm_info.max_wm; -+ -+ /* Use the large buffer method to calculate cursor watermark */ -+ line_time_us = ((htotal * 1000) / clock); -+ line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; -+ entries = line_count * 64 * pixel_size; -+ entries = DIV_ROUND_UP(entries, -+ ironlake_cursor_wm_info.cacheline_size); -+ *cursor_wm = entries + ironlake_cursor_wm_info.guard_size; -+ if (*cursor_wm > ironlake_cursor_wm_info.max_wm) -+ *cursor_wm = ironlake_cursor_wm_info.max_wm; - -- /* Use ns/us then divide to preserve precision */ -- line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; -+ return true; -+} - -- /* calculate the cursor watermark for cursor B */ -- entries_required = line_count * 64 * pixel_size; -- entries_required = DIV_ROUND_UP(entries_required, -- ironlake_cursor_wm_info.cacheline_size); -- cursorb_wm = entries_required + ironlake_cursor_wm_info.guard_size; -- if (cursorb_wm > ironlake_cursor_wm_info.max_wm) -- cursorb_wm = ironlake_cursor_wm_info.max_wm; -+static void ironlake_update_wm(struct drm_device *dev, -+ int planea_clock, int planeb_clock, -+ int sr_hdisplay, int sr_htotal, -+ int pixel_size) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ int plane_wm, cursor_wm, enabled; -+ int tmp; -+ -+ enabled = 0; -+ if (ironlake_compute_wm0(dev, 0, &plane_wm, &cursor_wm)) { -+ I915_WRITE(WM0_PIPEA_ILK, -+ (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); -+ DRM_DEBUG_KMS("FIFO watermarks For pipe A -" -+ " plane %d, " "cursor: %d\n", -+ plane_wm, cursor_wm); -+ enabled++; -+ } - -- reg_value = I915_READ(WM0_PIPEB_ILK); -- reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); -- reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) | -- (cursorb_wm & WM0_PIPE_CURSOR_MASK); -- I915_WRITE(WM0_PIPEB_ILK, reg_value); -- DRM_DEBUG_KMS("FIFO watermarks For pipe B - plane %d, " -- "cursor: %d\n", planeb_wm, cursorb_wm); -+ if (ironlake_compute_wm0(dev, 1, &plane_wm, &cursor_wm)) { -+ I915_WRITE(WM0_PIPEB_ILK, -+ (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); -+ DRM_DEBUG_KMS("FIFO watermarks For pipe B -" -+ " plane %d, cursor: %d\n", -+ plane_wm, cursor_wm); -+ enabled++; - } - - /* - * Calculate and update the self-refresh watermark only when one - * display plane is used. - */ -- if (!planea_clock || !planeb_clock) { -- -+ tmp = 0; -+ if (enabled == 1 && /* XXX disabled due to buggy implmentation? */ 0) { -+ unsigned long line_time_us; -+ int small, large, plane_fbc; -+ int sr_clock, entries; -+ int line_count, line_size; - /* Read the self-refresh latency. The unit is 0.5us */ - int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; - - sr_clock = planea_clock ? planea_clock : planeb_clock; -- line_time_us = ((sr_htotal * 1000) / sr_clock); -+ line_time_us = (sr_htotal * 1000) / sr_clock; - - /* Use ns/us then divide to preserve precision */ - line_count = ((ilk_sr_latency * 500) / line_time_us + 1000) -- / 1000; -+ / 1000; -+ line_size = sr_hdisplay * pixel_size; - -- /* calculate the self-refresh watermark for display plane */ -- entries_required = line_count * sr_hdisplay * pixel_size; -- entries_required = DIV_ROUND_UP(entries_required, -- ironlake_display_srwm_info.cacheline_size); -- sr_wm = entries_required + -- ironlake_display_srwm_info.guard_size; -+ /* Use the minimum of the small and large buffer method for primary */ -+ small = ((sr_clock * pixel_size / 1000) * (ilk_sr_latency * 500)) / 1000; -+ large = line_count * line_size; - -- /* calculate the self-refresh watermark for display cursor */ -- entries_required = line_count * pixel_size * 64; -- entries_required = DIV_ROUND_UP(entries_required, -- ironlake_cursor_srwm_info.cacheline_size); -- cursor_wm = entries_required + -- ironlake_cursor_srwm_info.guard_size; -+ entries = DIV_ROUND_UP(min(small, large), -+ ironlake_display_srwm_info.cacheline_size); - -- /* configure watermark and enable self-refresh */ -- reg_value = I915_READ(WM1_LP_ILK); -- reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK | -- WM1_LP_CURSOR_MASK); -- reg_value |= (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | -- (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm; -+ plane_fbc = entries * 64; -+ plane_fbc = DIV_ROUND_UP(plane_fbc, line_size); - -- I915_WRITE(WM1_LP_ILK, reg_value); -- DRM_DEBUG_KMS("self-refresh watermark: display plane %d " -- "cursor %d\n", sr_wm, cursor_wm); -+ plane_wm = entries + ironlake_display_srwm_info.guard_size; -+ if (plane_wm > (int)ironlake_display_srwm_info.max_wm) -+ plane_wm = ironlake_display_srwm_info.max_wm; - -- } else { -- /* Turn off self refresh if both pipes are enabled */ -- I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); -- } -+ /* calculate the self-refresh watermark for display cursor */ -+ entries = line_count * pixel_size * 64; -+ entries = DIV_ROUND_UP(entries, -+ ironlake_cursor_srwm_info.cacheline_size); -+ -+ cursor_wm = entries + ironlake_cursor_srwm_info.guard_size; -+ if (cursor_wm > (int)ironlake_cursor_srwm_info.max_wm) -+ cursor_wm = ironlake_cursor_srwm_info.max_wm; -+ -+ /* configure watermark and enable self-refresh */ -+ tmp = (WM1_LP_SR_EN | -+ (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | -+ (plane_fbc << WM1_LP_FBC_SHIFT) | -+ (plane_wm << WM1_LP_SR_SHIFT) | -+ cursor_wm); -+ DRM_DEBUG_KMS("self-refresh watermark: display plane %d, fbc lines %d," -+ " cursor %d\n", plane_wm, plane_fbc, cursor_wm); -+ } -+ I915_WRITE(WM1_LP_ILK, tmp); -+ /* XXX setup WM2 and WM3 */ - } -+ - /** - * intel_update_watermarks - update FIFO watermark values based on current modes - * -@@ -3447,7 +3529,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, - * - * We don't use the sprite, so we can ignore that. And on Crestline we have - * to set the non-SR watermarks to 8. -- */ -+ */ - static void intel_update_watermarks(struct drm_device *dev) - { - struct drm_i915_private *dev_priv = dev->dev_private; -@@ -3463,15 +3545,15 @@ static void intel_update_watermarks(struct drm_device *dev) - /* Get the clock config from both planes */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- if (intel_crtc->dpms_mode == DRM_MODE_DPMS_ON) { -+ if (intel_crtc->active) { - enabled++; - if (intel_crtc->plane == 0) { - DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n", -- intel_crtc->pipe, crtc->mode.clock); -+ intel_crtc->pipe, crtc->mode.clock); - planea_clock = crtc->mode.clock; - } else { - DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n", -- intel_crtc->pipe, crtc->mode.clock); -+ intel_crtc->pipe, crtc->mode.clock); - planeb_clock = crtc->mode.clock; - } - sr_hdisplay = crtc->mode.hdisplay; -@@ -3502,62 +3584,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - int plane = intel_crtc->plane; -- int fp_reg = (pipe == 0) ? FPA0 : FPB0; -- int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -- int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; -- int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; -- int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -- int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -- int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -- int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -- int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -- int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -- int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -- int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE; -- int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS; -- int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -+ u32 fp_reg, dpll_reg; - int refclk, num_connectors = 0; - intel_clock_t clock, reduced_clock; -- u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf; -+ u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; - bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; - bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; - struct intel_encoder *has_edp_encoder = NULL; - struct drm_mode_config *mode_config = &dev->mode_config; -- struct drm_encoder *encoder; -+ struct intel_encoder *encoder; - const intel_limit_t *limit; - int ret; - struct fdi_m_n m_n = {0}; -- int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1; -- int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1; -- int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1; -- int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1; -- int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0; -- int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; -- int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; -- int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; -- int trans_dpll_sel = (pipe == 0) ? 0 : 1; -- int lvds_reg = LVDS; -- u32 temp; -- int sdvo_pixel_multiply; -+ u32 reg, temp; - int target_clock; - - drm_vblank_pre_modeset(dev, pipe); - -- list_for_each_entry(encoder, &mode_config->encoder_list, head) { -- struct intel_encoder *intel_encoder; -- -- if (encoder->crtc != crtc) -+ list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { -+ if (encoder->base.crtc != crtc) - continue; - -- intel_encoder = enc_to_intel_encoder(encoder); -- switch (intel_encoder->type) { -+ switch (encoder->type) { - case INTEL_OUTPUT_LVDS: - is_lvds = true; - break; - case INTEL_OUTPUT_SDVO: - case INTEL_OUTPUT_HDMI: - is_sdvo = true; -- if (intel_encoder->needs_tv_clock) -+ if (encoder->needs_tv_clock) - is_tv = true; - break; - case INTEL_OUTPUT_DVO: -@@ -3573,7 +3628,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - is_dp = true; - break; - case INTEL_OUTPUT_EDP: -- has_edp_encoder = intel_encoder; -+ has_edp_encoder = encoder; - break; - } - -@@ -3583,15 +3638,15 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2) { - refclk = dev_priv->lvds_ssc_freq * 1000; - DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", -- refclk / 1000); -- } else if (IS_I9XX(dev)) { -+ refclk / 1000); -+ } else if (!IS_GEN2(dev)) { - refclk = 96000; -- if (HAS_PCH_SPLIT(dev)) -+ if (HAS_PCH_SPLIT(dev) && -+ (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base))) - refclk = 120000; /* 120Mhz refclk */ - } else { - refclk = 48000; - } -- - - /* - * Returns a set of divisors for the desired target clock with the given -@@ -3607,13 +3662,13 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - } - - /* Ensure that the cursor is valid for the new mode before changing... */ -- intel_crtc_update_cursor(crtc); -+ intel_crtc_update_cursor(crtc, true); - - if (is_lvds && dev_priv->lvds_downclock_avail) { - has_reduced_clock = limit->find_pll(limit, crtc, -- dev_priv->lvds_downclock, -- refclk, -- &reduced_clock); -+ dev_priv->lvds_downclock, -+ refclk, -+ &reduced_clock); - if (has_reduced_clock && (clock.p != reduced_clock.p)) { - /* - * If the different P is found, it means that we can't -@@ -3622,7 +3677,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - * feature. - */ - DRM_DEBUG_KMS("Different P is found for " -- "LVDS clock/downclock\n"); -+ "LVDS clock/downclock\n"); - has_reduced_clock = 0; - } - } -@@ -3630,14 +3685,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - this mirrors vbios setting. */ - if (is_sdvo && is_tv) { - if (adjusted_mode->clock >= 100000 -- && adjusted_mode->clock < 140500) { -+ && adjusted_mode->clock < 140500) { - clock.p1 = 2; - clock.p2 = 10; - clock.n = 3; - clock.m1 = 16; - clock.m2 = 8; - } else if (adjusted_mode->clock >= 140500 -- && adjusted_mode->clock <= 200000) { -+ && adjusted_mode->clock <= 200000) { - clock.p1 = 1; - clock.p2 = 10; - clock.n = 6; -@@ -3649,34 +3704,41 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - /* FDI link */ - if (HAS_PCH_SPLIT(dev)) { - int lane = 0, link_bw, bpp; -- /* eDP doesn't require FDI link, so just set DP M/N -+ /* CPU eDP doesn't require FDI link, so just set DP M/N - according to current link config */ -- if (has_edp_encoder) { -+ if (has_edp_encoder && !intel_encoder_is_pch_edp(&encoder->base)) { - target_clock = mode->clock; - intel_edp_link_config(has_edp_encoder, - &lane, &link_bw); - } else { -- /* DP over FDI requires target mode clock -+ /* [e]DP over FDI requires target mode clock - instead of link clock */ -- if (is_dp) -+ if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) - target_clock = mode->clock; - else - target_clock = adjusted_mode->clock; -- link_bw = 270000; -+ -+ /* FDI is a binary signal running at ~2.7GHz, encoding -+ * each output octet as 10 bits. The actual frequency -+ * is stored as a divider into a 100MHz clock, and the -+ * mode pixel clock is stored in units of 1KHz. -+ * Hence the bw of each lane in terms of the mode signal -+ * is: -+ */ -+ link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; - } - - /* determine panel color depth */ -- temp = I915_READ(pipeconf_reg); -+ temp = I915_READ(PIPECONF(pipe)); - temp &= ~PIPE_BPC_MASK; - if (is_lvds) { -- int lvds_reg = I915_READ(PCH_LVDS); - /* the BPC will be 6 if it is 18-bit LVDS panel */ -- if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) -+ if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) - temp |= PIPE_8BPC; - else - temp |= PIPE_6BPC; -- } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) { -- switch (dev_priv->edp_bpp/3) { -+ } else if (has_edp_encoder) { -+ switch (dev_priv->edp.bpp/3) { - case 8: - temp |= PIPE_8BPC; - break; -@@ -3692,8 +3754,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - } - } else - temp |= PIPE_8BPC; -- I915_WRITE(pipeconf_reg, temp); -- I915_READ(pipeconf_reg); -+ I915_WRITE(PIPECONF(pipe), temp); - - switch (temp & PIPE_BPC_MASK) { - case PIPE_8BPC: -@@ -3738,33 +3799,39 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - /* Always enable nonspread source */ - temp &= ~DREF_NONSPREAD_SOURCE_MASK; - temp |= DREF_NONSPREAD_SOURCE_ENABLE; -- I915_WRITE(PCH_DREF_CONTROL, temp); -- POSTING_READ(PCH_DREF_CONTROL); -- - temp &= ~DREF_SSC_SOURCE_MASK; - temp |= DREF_SSC_SOURCE_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); -- POSTING_READ(PCH_DREF_CONTROL); - -+ POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - - if (has_edp_encoder) { - if (dev_priv->lvds_use_ssc) { - temp |= DREF_SSC1_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); -- POSTING_READ(PCH_DREF_CONTROL); -- -- udelay(200); - -- temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; -- temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; -- I915_WRITE(PCH_DREF_CONTROL, temp); - POSTING_READ(PCH_DREF_CONTROL); -+ udelay(200); -+ } -+ temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; -+ -+ /* Enable CPU source on CPU attached eDP */ -+ if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { -+ if (dev_priv->lvds_use_ssc) -+ temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; -+ else -+ temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; - } else { -- temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; -- I915_WRITE(PCH_DREF_CONTROL, temp); -- POSTING_READ(PCH_DREF_CONTROL); -+ /* Enable SSC on PCH eDP if needed */ -+ if (dev_priv->lvds_use_ssc) { -+ DRM_ERROR("enabling SSC on PCH\n"); -+ temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; -+ } - } -+ I915_WRITE(PCH_DREF_CONTROL, temp); -+ POSTING_READ(PCH_DREF_CONTROL); -+ udelay(200); - } - } - -@@ -3780,23 +3847,26 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - reduced_clock.m2; - } - -+ dpll = 0; - if (!HAS_PCH_SPLIT(dev)) - dpll = DPLL_VGA_MODE_DIS; - -- if (IS_I9XX(dev)) { -+ if (!IS_GEN2(dev)) { - if (is_lvds) - dpll |= DPLLB_MODE_LVDS; - else - dpll |= DPLLB_MODE_DAC_SERIAL; - if (is_sdvo) { -+ int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); -+ if (pixel_multiplier > 1) { -+ if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) -+ dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; -+ else if (HAS_PCH_SPLIT(dev)) -+ dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; -+ } - dpll |= DPLL_DVO_HIGH_SPEED; -- sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; -- if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) -- dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; -- else if (HAS_PCH_SPLIT(dev)) -- dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; - } -- if (is_dp) -+ if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) - dpll |= DPLL_DVO_HIGH_SPEED; - - /* compute bitmask from p1 value */ -@@ -3824,7 +3894,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; - break; - } -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) - dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); - } else { - if (is_lvds) { -@@ -3851,7 +3921,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - dpll |= PLL_REF_INPUT_DREFCLK; - - /* setup pipeconf */ -- pipeconf = I915_READ(pipeconf_reg); -+ pipeconf = I915_READ(PIPECONF(pipe)); - - /* Set up the display plane register */ - dspcntr = DISPPLANE_GAMMA_ENABLE; -@@ -3865,7 +3935,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - dspcntr |= DISPPLANE_SEL_PIPE_B; - } - -- if (pipe == 0 && !IS_I965G(dev)) { -+ if (pipe == 0 && INTEL_INFO(dev)->gen < 4) { - /* Enable pixel doubling when the dot clock is > 90% of the (display) - * core speed. - * -@@ -3874,51 +3944,47 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - */ - if (mode->clock > - dev_priv->display.get_display_clock_speed(dev) * 9 / 10) -- pipeconf |= PIPEACONF_DOUBLE_WIDE; -+ pipeconf |= PIPECONF_DOUBLE_WIDE; - else -- pipeconf &= ~PIPEACONF_DOUBLE_WIDE; -+ pipeconf &= ~PIPECONF_DOUBLE_WIDE; - } - - dspcntr |= DISPLAY_PLANE_ENABLE; -- pipeconf |= PIPEACONF_ENABLE; -+ pipeconf |= PIPECONF_ENABLE; - dpll |= DPLL_VCO_ENABLE; - -- -- /* Disable the panel fitter if it was on our pipe */ -- if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe) -- I915_WRITE(PFIT_CONTROL, 0); -- - DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); - drm_mode_debug_printmodeline(mode); - - /* assign to Ironlake registers */ - if (HAS_PCH_SPLIT(dev)) { -- fp_reg = pch_fp_reg; -- dpll_reg = pch_dpll_reg; -+ fp_reg = PCH_FP0(pipe); -+ dpll_reg = PCH_DPLL(pipe); -+ } else { -+ fp_reg = FP0(pipe); -+ dpll_reg = DPLL(pipe); - } - -- if (!has_edp_encoder) { -+ /* PCH eDP needs FDI, but CPU eDP does not */ -+ if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - I915_WRITE(fp_reg, fp); - I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); -- I915_READ(dpll_reg); -+ -+ POSTING_READ(dpll_reg); - udelay(150); - } - - /* enable transcoder DPLL */ - if (HAS_PCH_CPT(dev)) { - temp = I915_READ(PCH_DPLL_SEL); -- if (trans_dpll_sel == 0) -- temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); -+ if (pipe == 0) -+ temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; - else -- temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); -+ temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; - I915_WRITE(PCH_DPLL_SEL, temp); -- I915_READ(PCH_DPLL_SEL); -- udelay(150); -- } - -- if (HAS_PCH_SPLIT(dev)) { -- pipeconf &= ~PIPE_ENABLE_DITHER; -- pipeconf &= ~PIPE_DITHER_TYPE_MASK; -+ POSTING_READ(PCH_DPLL_SEL); -+ udelay(150); - } - - /* The LVDS pin pair needs to be on before the DPLLs are enabled. -@@ -3926,58 +3992,60 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - * things on. - */ - if (is_lvds) { -- u32 lvds; -- -+ reg = LVDS; - if (HAS_PCH_SPLIT(dev)) -- lvds_reg = PCH_LVDS; -+ reg = PCH_LVDS; - -- lvds = I915_READ(lvds_reg); -- lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; -+ temp = I915_READ(reg); -+ temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; - if (pipe == 1) { - if (HAS_PCH_CPT(dev)) -- lvds |= PORT_TRANS_B_SEL_CPT; -+ temp |= PORT_TRANS_B_SEL_CPT; - else -- lvds |= LVDS_PIPEB_SELECT; -+ temp |= LVDS_PIPEB_SELECT; - } else { - if (HAS_PCH_CPT(dev)) -- lvds &= ~PORT_TRANS_SEL_MASK; -+ temp &= ~PORT_TRANS_SEL_MASK; - else -- lvds &= ~LVDS_PIPEB_SELECT; -+ temp &= ~LVDS_PIPEB_SELECT; - } - /* set the corresponsding LVDS_BORDER bit */ -- lvds |= dev_priv->lvds_border_bits; -+ temp |= dev_priv->lvds_border_bits; - /* Set the B0-B3 data pairs corresponding to whether we're going to - * set the DPLLs for dual-channel mode or not. - */ - if (clock.p2 == 7) -- lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; -+ temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; - else -- lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); -+ temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); - - /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) - * appropriately here, but we need to look more thoroughly into how - * panels behave in the two modes. - */ -- /* set the dithering flag */ -- if (IS_I965G(dev)) { -- if (dev_priv->lvds_dither) { -- if (HAS_PCH_SPLIT(dev)) { -- pipeconf |= PIPE_ENABLE_DITHER; -- pipeconf |= PIPE_DITHER_TYPE_ST01; -- } else -- lvds |= LVDS_ENABLE_DITHER; -- } else { -- if (!HAS_PCH_SPLIT(dev)) { -- lvds &= ~LVDS_ENABLE_DITHER; -- } -- } -+ /* set the dithering flag on non-PCH LVDS as needed */ -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { -+ if (dev_priv->lvds_dither) -+ temp |= LVDS_ENABLE_DITHER; -+ else -+ temp &= ~LVDS_ENABLE_DITHER; -+ } -+ I915_WRITE(reg, temp); -+ } -+ -+ /* set the dithering flag and clear for anything other than a panel. */ -+ if (HAS_PCH_SPLIT(dev)) { -+ pipeconf &= ~PIPECONF_DITHER_EN; -+ pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; -+ if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { -+ pipeconf |= PIPECONF_DITHER_EN; -+ pipeconf |= PIPECONF_DITHER_TYPE_ST1; - } -- I915_WRITE(lvds_reg, lvds); -- I915_READ(lvds_reg); - } -- if (is_dp) -+ -+ if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - intel_dp_set_m_n(crtc, mode, adjusted_mode); -- else if (HAS_PCH_SPLIT(dev)) { -+ } else if (HAS_PCH_SPLIT(dev)) { - /* For non-DP output, clear any trans DP clock recovery setting.*/ - if (pipe == 0) { - I915_WRITE(TRANSA_DATA_M1, 0); -@@ -3992,29 +4060,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - } - } - -- if (!has_edp_encoder) { -+ if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - I915_WRITE(fp_reg, fp); - I915_WRITE(dpll_reg, dpll); -- I915_READ(dpll_reg); -+ - /* Wait for the clocks to stabilize. */ -+ POSTING_READ(dpll_reg); - udelay(150); - -- if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { -+ temp = 0; - if (is_sdvo) { -- sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; -- I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | -- ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); -- } else -- I915_WRITE(dpll_md_reg, 0); -+ temp = intel_mode_get_pixel_multiplier(adjusted_mode); -+ if (temp > 1) -+ temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; -+ else -+ temp = 0; -+ } -+ I915_WRITE(DPLL_MD(pipe), temp); - } else { - /* write it again -- the BIOS does, after all */ - I915_WRITE(dpll_reg, dpll); - } -- I915_READ(dpll_reg); -+ - /* Wait for the clocks to stabilize. */ -+ POSTING_READ(dpll_reg); - udelay(150); - } - -+ intel_crtc->lowfreq_avail = false; - if (is_lvds && has_reduced_clock && i915_powersave) { - I915_WRITE(fp_reg + 4, fp2); - intel_crtc->lowfreq_avail = true; -@@ -4024,7 +4098,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - } - } else { - I915_WRITE(fp_reg + 4, fp); -- intel_crtc->lowfreq_avail = false; - if (HAS_PIPE_CXSR(dev)) { - DRM_DEBUG_KMS("disabling CxSR downclocking\n"); - pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; -@@ -4043,70 +4116,62 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, - } else - pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ - -- I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | -+ I915_WRITE(HTOTAL(pipe), -+ (adjusted_mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); -- I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | -+ I915_WRITE(HBLANK(pipe), -+ (adjusted_mode->crtc_hblank_start - 1) | - ((adjusted_mode->crtc_hblank_end - 1) << 16)); -- I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | -+ I915_WRITE(HSYNC(pipe), -+ (adjusted_mode->crtc_hsync_start - 1) | - ((adjusted_mode->crtc_hsync_end - 1) << 16)); -- I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | -+ -+ I915_WRITE(VTOTAL(pipe), -+ (adjusted_mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); -- I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | -+ I915_WRITE(VBLANK(pipe), -+ (adjusted_mode->crtc_vblank_start - 1) | - ((adjusted_mode->crtc_vblank_end - 1) << 16)); -- I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | -+ I915_WRITE(VSYNC(pipe), -+ (adjusted_mode->crtc_vsync_start - 1) | - ((adjusted_mode->crtc_vsync_end - 1) << 16)); -- /* pipesrc and dspsize control the size that is scaled from, which should -- * always be the user's requested size. -+ -+ /* pipesrc and dspsize control the size that is scaled from, -+ * which should always be the user's requested size. - */ - if (!HAS_PCH_SPLIT(dev)) { -- I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | -- (mode->hdisplay - 1)); -- I915_WRITE(dsppos_reg, 0); -+ I915_WRITE(DSPSIZE(plane), -+ ((mode->vdisplay - 1) << 16) | -+ (mode->hdisplay - 1)); -+ I915_WRITE(DSPPOS(plane), 0); - } -- I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); -+ I915_WRITE(PIPESRC(pipe), -+ ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); - - if (HAS_PCH_SPLIT(dev)) { -- I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m); -- I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n); -- I915_WRITE(link_m1_reg, m_n.link_m); -- I915_WRITE(link_n1_reg, m_n.link_n); -+ I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); -+ I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); -+ I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); -+ I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); - -- if (has_edp_encoder) { -+ if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - ironlake_set_pll_edp(crtc, adjusted_mode->clock); -- } else { -- /* enable FDI RX PLL too */ -- temp = I915_READ(fdi_rx_reg); -- I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); -- I915_READ(fdi_rx_reg); -- udelay(200); -- -- /* enable FDI TX PLL too */ -- temp = I915_READ(fdi_tx_reg); -- I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); -- I915_READ(fdi_tx_reg); -- -- /* enable FDI RX PCDCLK */ -- temp = I915_READ(fdi_rx_reg); -- I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK); -- I915_READ(fdi_rx_reg); -- udelay(200); - } - } - -- I915_WRITE(pipeconf_reg, pipeconf); -- I915_READ(pipeconf_reg); -+ I915_WRITE(PIPECONF(pipe), pipeconf); -+ POSTING_READ(PIPECONF(pipe)); - - intel_wait_for_vblank(dev, pipe); - -- if (IS_IRONLAKE(dev)) { -+ if (IS_GEN5(dev)) { - /* enable address swizzle for tiling buffer */ - temp = I915_READ(DISP_ARB_CTL); - I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); - } - -- I915_WRITE(dspcntr_reg, dspcntr); -+ I915_WRITE(DSPCNTR(plane), dspcntr); - -- /* Flush the plane changes */ - ret = intel_pipe_set_base(crtc, x, y, old_fb); - - intel_update_watermarks(dev); -@@ -4199,7 +4264,8 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) - } - - /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ --static void intel_crtc_update_cursor(struct drm_crtc *crtc) -+static void intel_crtc_update_cursor(struct drm_crtc *crtc, -+ bool on) - { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -@@ -4212,7 +4278,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc) - - pos = 0; - -- if (intel_crtc->cursor_on && crtc->fb) { -+ if (on && crtc->enabled && crtc->fb) { - base = intel_crtc->cursor_addr; - if (x > (int) crtc->fb->width) - base = 0; -@@ -4324,7 +4390,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, - addr = obj_priv->phys_obj->handle->busaddr; - } - -- if (!IS_I9XX(dev)) -+ if (IS_GEN2(dev)) - I915_WRITE(CURSIZE, (height << 12) | width); - - finish: -@@ -4344,7 +4410,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, - intel_crtc->cursor_width = width; - intel_crtc->cursor_height = height; - -- intel_crtc_update_cursor(crtc); -+ intel_crtc_update_cursor(crtc, true); - - return 0; - fail_unpin: -@@ -4363,7 +4429,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) - intel_crtc->cursor_x = x; - intel_crtc->cursor_y = y; - -- intel_crtc_update_cursor(crtc); -+ intel_crtc_update_cursor(crtc, true); - - return 0; - } -@@ -4432,7 +4498,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, - struct intel_crtc *intel_crtc; - struct drm_crtc *possible_crtc; - struct drm_crtc *supported_crtc =NULL; -- struct drm_encoder *encoder = &intel_encoder->enc; -+ struct drm_encoder *encoder = &intel_encoder->base; - struct drm_crtc *crtc = NULL; - struct drm_device *dev = encoder->dev; - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; -@@ -4513,7 +4579,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, - void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - struct drm_connector *connector, int dpms_mode) - { -- struct drm_encoder *encoder = &intel_encoder->enc; -+ struct drm_encoder *encoder = &intel_encoder->base; - struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc = encoder->crtc; - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; -@@ -4559,7 +4625,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) - clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; - } - -- if (IS_I9XX(dev)) { -+ if (!IS_GEN2(dev)) { - if (IS_PINEVIEW(dev)) - clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> - DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); -@@ -4663,8 +4729,6 @@ static void intel_gpu_idle_timer(unsigned long arg) - struct drm_device *dev = (struct drm_device *)arg; - drm_i915_private_t *dev_priv = dev->dev_private; - -- DRM_DEBUG_DRIVER("idle timer fired, downclocking\n"); -- - dev_priv->busy = false; - - queue_work(dev_priv->wq, &dev_priv->idle_work); -@@ -4678,14 +4742,12 @@ static void intel_crtc_idle_timer(unsigned long arg) - struct drm_crtc *crtc = &intel_crtc->base; - drm_i915_private_t *dev_priv = crtc->dev->dev_private; - -- DRM_DEBUG_DRIVER("idle timer fired, downclocking\n"); -- - intel_crtc->busy = false; - - queue_work(dev_priv->wq, &dev_priv->idle_work); - } - --static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) -+static void intel_increase_pllclock(struct drm_crtc *crtc) - { - struct drm_device *dev = crtc->dev; - drm_i915_private_t *dev_priv = dev->dev_private; -@@ -4720,9 +4782,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) - } - - /* Schedule downclock */ -- if (schedule) -- mod_timer(&intel_crtc->idle_timer, jiffies + -- msecs_to_jiffies(CRTC_IDLE_TIMEOUT)); -+ mod_timer(&intel_crtc->idle_timer, jiffies + -+ msecs_to_jiffies(CRTC_IDLE_TIMEOUT)); - } - - static void intel_decrease_pllclock(struct drm_crtc *crtc) -@@ -4858,7 +4919,7 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) - I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK); - } - /* Non-busy -> busy, upclock */ -- intel_increase_pllclock(crtc, true); -+ intel_increase_pllclock(crtc); - intel_crtc->busy = true; - } else { - /* Busy -> busy, put off timer */ -@@ -4872,8 +4933,22 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) - static void intel_crtc_destroy(struct drm_crtc *crtc) - { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ struct intel_unpin_work *work; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ work = intel_crtc->unpin_work; -+ intel_crtc->unpin_work = NULL; -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ -+ if (work) { -+ cancel_work_sync(&work->work); -+ kfree(work); -+ } - - drm_crtc_cleanup(crtc); -+ - kfree(intel_crtc); - } - -@@ -4928,12 +5003,11 @@ static void do_intel_finish_page_flip(struct drm_device *dev, - - spin_unlock_irqrestore(&dev->event_lock, flags); - -- obj_priv = to_intel_bo(work->pending_flip_obj); -- -- /* Initial scanout buffer will have a 0 pending flip count */ -- if ((atomic_read(&obj_priv->pending_flip) == 0) || -- atomic_dec_and_test(&obj_priv->pending_flip)) -- DRM_WAKEUP(&dev_priv->pending_flip_queue); -+ obj_priv = to_intel_bo(work->old_fb_obj); -+ atomic_clear_mask(1 << intel_crtc->plane, -+ &obj_priv->pending_flip.counter); -+ if (atomic_read(&obj_priv->pending_flip) == 0) -+ wake_up(&dev_priv->pending_flip_queue); - schedule_work(&work->work); - - trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); -@@ -5014,7 +5088,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, - obj = intel_fb->obj; - - mutex_lock(&dev->struct_mutex); -- ret = intel_pin_and_fence_fb_obj(dev, obj); -+ ret = intel_pin_and_fence_fb_obj(dev, obj, true); - if (ret) - goto cleanup_work; - -@@ -5023,29 +5097,33 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, - drm_gem_object_reference(obj); - - crtc->fb = fb; -- ret = i915_gem_object_flush_write_domain(obj); -- if (ret) -- goto cleanup_objs; - - ret = drm_vblank_get(dev, intel_crtc->pipe); - if (ret) - goto cleanup_objs; - -- obj_priv = to_intel_bo(obj); -- atomic_inc(&obj_priv->pending_flip); -+ /* Block clients from rendering to the new back buffer until -+ * the flip occurs and the object is no longer visible. -+ */ -+ atomic_add(1 << intel_crtc->plane, -+ &to_intel_bo(work->old_fb_obj)->pending_flip); -+ - work->pending_flip_obj = obj; -+ obj_priv = to_intel_bo(obj); - - if (IS_GEN3(dev) || IS_GEN2(dev)) { - u32 flip_mask; - -+ /* Can't queue multiple flips, so wait for the previous -+ * one to finish before executing the next. -+ */ -+ BEGIN_LP_RING(2); - if (intel_crtc->plane) - flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; - else - flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; -- -- BEGIN_LP_RING(2); - OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); -- OUT_RING(0); -+ OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - } - -@@ -5126,15 +5204,14 @@ cleanup_work: - return ret; - } - --static const struct drm_crtc_helper_funcs intel_helper_funcs = { -+static struct drm_crtc_helper_funcs intel_helper_funcs = { - .dpms = intel_crtc_dpms, - .mode_fixup = intel_crtc_mode_fixup, - .mode_set = intel_crtc_mode_set, - .mode_set_base = intel_pipe_set_base, - .mode_set_base_atomic = intel_pipe_set_base_atomic, -- .prepare = intel_crtc_prepare, -- .commit = intel_crtc_commit, - .load_lut = intel_crtc_load_lut, -+ .disable = intel_crtc_disable, - }; - - static const struct drm_crtc_funcs intel_crtc_funcs = { -@@ -5160,8 +5237,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) - drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); - - drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); -- intel_crtc->pipe = pipe; -- intel_crtc->plane = pipe; - for (i = 0; i < 256; i++) { - intel_crtc->lut_r[i] = i; - intel_crtc->lut_g[i] = i; -@@ -5171,9 +5246,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) - /* Swap pipes & planes for FBC on pre-965 */ - intel_crtc->pipe = pipe; - intel_crtc->plane = pipe; -- if (IS_MOBILE(dev) && (IS_I9XX(dev) && !IS_I965G(dev))) { -+ if (IS_MOBILE(dev) && IS_GEN3(dev)) { - DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); -- intel_crtc->plane = ((pipe == 0) ? 1 : 0); -+ intel_crtc->plane = !pipe; - } - - BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || -@@ -5183,6 +5258,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) - - intel_crtc->cursor_addr = 0; - intel_crtc->dpms_mode = -1; -+ intel_crtc->active = true; /* force the pipe off on setup_init_config */ -+ -+ if (HAS_PCH_SPLIT(dev)) { -+ intel_helper_funcs.prepare = ironlake_crtc_prepare; -+ intel_helper_funcs.commit = ironlake_crtc_commit; -+ } else { -+ intel_helper_funcs.prepare = i9xx_crtc_prepare; -+ intel_helper_funcs.commit = i9xx_crtc_commit; -+ } -+ - drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); - - intel_crtc->busy = false; -@@ -5218,38 +5303,25 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - return 0; - } - --struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) --{ -- struct drm_crtc *crtc = NULL; -- -- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -- struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- if (intel_crtc->pipe == pipe) -- break; -- } -- return crtc; --} -- - static int intel_encoder_clones(struct drm_device *dev, int type_mask) - { -+ struct intel_encoder *encoder; - int index_mask = 0; -- struct drm_encoder *encoder; - int entry = 0; - -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -- if (type_mask & intel_encoder->clone_mask) -+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { -+ if (type_mask & encoder->clone_mask) - index_mask |= (1 << entry); - entry++; - } -+ - return index_mask; - } - -- - static void intel_setup_outputs(struct drm_device *dev) - { - struct drm_i915_private *dev_priv = dev->dev_private; -- struct drm_encoder *encoder; -+ struct intel_encoder *encoder; - bool dpd_is_edp = false; - - if (IS_MOBILE(dev) && !IS_I830(dev)) -@@ -5338,12 +5410,10 @@ static void intel_setup_outputs(struct drm_device *dev) - if (SUPPORTS_TV(dev)) - intel_tv_init(dev); - -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -- -- encoder->possible_crtcs = intel_encoder->crtc_mask; -- encoder->possible_clones = intel_encoder_clones(dev, -- intel_encoder->clone_mask); -+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { -+ encoder->base.possible_crtcs = encoder->crtc_mask; -+ encoder->base.possible_clones = -+ intel_encoder_clones(dev, encoder->clone_mask); - } - } - -@@ -5377,8 +5447,25 @@ int intel_framebuffer_init(struct drm_device *dev, - struct drm_mode_fb_cmd *mode_cmd, - struct drm_gem_object *obj) - { -+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int ret; - -+ if (obj_priv->tiling_mode == I915_TILING_Y) -+ return -EINVAL; -+ -+ if (mode_cmd->pitch & 63) -+ return -EINVAL; -+ -+ switch (mode_cmd->bpp) { -+ case 8: -+ case 16: -+ case 24: -+ case 32: -+ break; -+ default: -+ return -EINVAL; -+ } -+ - ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); - if (ret) { - DRM_ERROR("framebuffer init failed %d\n", ret); -@@ -5487,6 +5574,10 @@ void ironlake_enable_drps(struct drm_device *dev) - u32 rgvmodectl = I915_READ(MEMMODECTL); - u8 fmax, fmin, fstart, vstart; - -+ /* Enable temp reporting */ -+ I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN); -+ I915_WRITE16(TSC1, I915_READ(TSC1) | TSE); -+ - /* 100ms RC evaluation intervals */ - I915_WRITE(RCUPEI, 100000); - I915_WRITE(RCDNEI, 100000); -@@ -5502,20 +5593,19 @@ void ironlake_enable_drps(struct drm_device *dev) - fmin = (rgvmodectl & MEMMODE_FMIN_MASK); - fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> - MEMMODE_FSTART_SHIFT; -- fstart = fmax; - - vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> - PXVFREQ_PX_SHIFT; - -- dev_priv->fmax = fstart; /* IPS callback will increase this */ -+ dev_priv->fmax = fmax; /* IPS callback will increase this */ - dev_priv->fstart = fstart; - -- dev_priv->max_delay = fmax; -+ dev_priv->max_delay = fstart; - dev_priv->min_delay = fmin; - dev_priv->cur_delay = fstart; - -- DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin, -- fstart); -+ DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", -+ fmax, fmin, fstart); - - I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); - -@@ -5529,7 +5619,7 @@ void ironlake_enable_drps(struct drm_device *dev) - rgvmodectl |= MEMMODE_SWMODE_EN; - I915_WRITE(MEMMODECTL, rgvmodectl); - -- if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 1, 0)) -+ if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) - DRM_ERROR("stuck trying to change perf mode\n"); - msleep(1); - -@@ -5660,7 +5750,7 @@ void intel_init_clock_gating(struct drm_device *dev) - if (HAS_PCH_SPLIT(dev)) { - uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; - -- if (IS_IRONLAKE(dev)) { -+ if (IS_GEN5(dev)) { - /* Required for FBC */ - dspclk_gate |= DPFDUNIT_CLOCK_GATE_DISABLE; - /* Required for CxSR */ -@@ -5674,13 +5764,20 @@ void intel_init_clock_gating(struct drm_device *dev) - I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); - - /* -+ * On Ibex Peak and Cougar Point, we need to disable clock -+ * gating for the panel power sequencer or it will fail to -+ * start up when no ports are active. -+ */ -+ I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); -+ -+ /* - * According to the spec the following bits should be set in - * order to enable memory self-refresh - * The bit 22/21 of 0x42004 - * The bit 5 of 0x42020 - * The bit 15 of 0x45000 - */ -- if (IS_IRONLAKE(dev)) { -+ if (IS_GEN5(dev)) { - I915_WRITE(ILK_DISPLAY_CHICKEN2, - (I915_READ(ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE | ILK_VSDPFD_FULL)); -@@ -5728,20 +5825,20 @@ void intel_init_clock_gating(struct drm_device *dev) - if (IS_GM45(dev)) - dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; - I915_WRITE(DSPCLK_GATE_D, dspclk_gate); -- } else if (IS_I965GM(dev)) { -+ } else if (IS_CRESTLINE(dev)) { - I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); - I915_WRITE(RENCLK_GATE_D2, 0); - I915_WRITE(DSPCLK_GATE_D, 0); - I915_WRITE(RAMCLK_GATE_D, 0); - I915_WRITE16(DEUC, 0); -- } else if (IS_I965G(dev)) { -+ } else if (IS_BROADWATER(dev)) { - I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | - I965_RCC_CLOCK_GATE_DISABLE | - I965_RCPB_CLOCK_GATE_DISABLE | - I965_ISC_CLOCK_GATE_DISABLE | - I965_FBC_CLOCK_GATE_DISABLE); - I915_WRITE(RENCLK_GATE_D2, 0); -- } else if (IS_I9XX(dev)) { -+ } else if (IS_GEN3(dev)) { - u32 dstate = I915_READ(D_STATE); - - dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | -@@ -5823,7 +5920,7 @@ static void intel_init_display(struct drm_device *dev) - dev_priv->display.fbc_enabled = g4x_fbc_enabled; - dev_priv->display.enable_fbc = g4x_enable_fbc; - dev_priv->display.disable_fbc = g4x_disable_fbc; -- } else if (IS_I965GM(dev)) { -+ } else if (IS_CRESTLINE(dev)) { - dev_priv->display.fbc_enabled = i8xx_fbc_enabled; - dev_priv->display.enable_fbc = i8xx_enable_fbc; - dev_priv->display.disable_fbc = i8xx_disable_fbc; -@@ -5856,7 +5953,7 @@ static void intel_init_display(struct drm_device *dev) - - /* For FIFO watermark updates */ - if (HAS_PCH_SPLIT(dev)) { -- if (IS_IRONLAKE(dev)) { -+ if (IS_GEN5(dev)) { - if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK) - dev_priv->display.update_wm = ironlake_update_wm; - else { -@@ -5883,9 +5980,9 @@ static void intel_init_display(struct drm_device *dev) - dev_priv->display.update_wm = pineview_update_wm; - } else if (IS_G4X(dev)) - dev_priv->display.update_wm = g4x_update_wm; -- else if (IS_I965G(dev)) -+ else if (IS_GEN4(dev)) - dev_priv->display.update_wm = i965_update_wm; -- else if (IS_I9XX(dev)) { -+ else if (IS_GEN3(dev)) { - dev_priv->display.update_wm = i9xx_update_wm; - dev_priv->display.get_fifo_size = i9xx_get_fifo_size; - } else if (IS_I85X(dev)) { -@@ -5999,24 +6096,24 @@ void intel_modeset_init(struct drm_device *dev) - - intel_init_display(dev); - -- if (IS_I965G(dev)) { -- dev->mode_config.max_width = 8192; -- dev->mode_config.max_height = 8192; -- } else if (IS_I9XX(dev)) { -+ if (IS_GEN2(dev)) { -+ dev->mode_config.max_width = 2048; -+ dev->mode_config.max_height = 2048; -+ } else if (IS_GEN3(dev)) { - dev->mode_config.max_width = 4096; - dev->mode_config.max_height = 4096; - } else { -- dev->mode_config.max_width = 2048; -- dev->mode_config.max_height = 2048; -+ dev->mode_config.max_width = 8192; -+ dev->mode_config.max_height = 8192; - } - - /* set memory base */ -- if (IS_I9XX(dev)) -- dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); -- else -+ if (IS_GEN2(dev)) - dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); -+ else -+ dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); - -- if (IS_MOBILE(dev) || IS_I9XX(dev)) -+ if (IS_MOBILE(dev) || !IS_GEN2(dev)) - dev_priv->num_pipe = 2; - else - dev_priv->num_pipe = 1; -@@ -6052,10 +6149,11 @@ void intel_modeset_cleanup(struct drm_device *dev) - struct drm_crtc *crtc; - struct intel_crtc *intel_crtc; - -+ drm_kms_helper_poll_fini(dev); - mutex_lock(&dev->struct_mutex); - -- drm_kms_helper_poll_fini(dev); -- intel_fbdev_fini(dev); -+ intel_unregister_dsm_handler(); -+ - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - /* Skip inactive CRTCs */ -@@ -6063,12 +6161,9 @@ void intel_modeset_cleanup(struct drm_device *dev) - continue; - - intel_crtc = to_intel_crtc(crtc); -- intel_increase_pllclock(crtc, false); -- del_timer_sync(&intel_crtc->idle_timer); -+ intel_increase_pllclock(crtc); - } - -- del_timer_sync(&dev_priv->idle_timer); -- - if (dev_priv->display.disable_fbc) - dev_priv->display.disable_fbc(dev); - -@@ -6097,33 +6192,36 @@ void intel_modeset_cleanup(struct drm_device *dev) - - mutex_unlock(&dev->struct_mutex); - -+ /* Disable the irq before mode object teardown, for the irq might -+ * enqueue unpin/hotplug work. */ -+ drm_irq_uninstall(dev); -+ cancel_work_sync(&dev_priv->hotplug_work); -+ -+ /* Shut off idle work before the crtcs get freed. */ -+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -+ intel_crtc = to_intel_crtc(crtc); -+ del_timer_sync(&intel_crtc->idle_timer); -+ } -+ del_timer_sync(&dev_priv->idle_timer); -+ cancel_work_sync(&dev_priv->idle_work); -+ - drm_mode_config_cleanup(dev); - } - -- - /* - * Return which encoder is currently attached for connector. - */ --struct drm_encoder *intel_attached_encoder (struct drm_connector *connector) -+struct drm_encoder *intel_best_encoder(struct drm_connector *connector) - { -- struct drm_mode_object *obj; -- struct drm_encoder *encoder; -- int i; -- -- for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { -- if (connector->encoder_ids[i] == 0) -- break; -- -- obj = drm_mode_object_find(connector->dev, -- connector->encoder_ids[i], -- DRM_MODE_OBJECT_ENCODER); -- if (!obj) -- continue; -+ return &intel_attached_encoder(connector)->base; -+} - -- encoder = obj_to_encoder(obj); -- return encoder; -- } -- return NULL; -+void intel_connector_attach_encoder(struct intel_connector *connector, -+ struct intel_encoder *encoder) -+{ -+ connector->encoder = encoder; -+ drm_mode_connector_attach_encoder(&connector->base, -+ &encoder->base); - } - - /* -diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index 9ab8708..2d3dee9 100644 ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -42,15 +42,13 @@ - - #define DP_LINK_CONFIGURATION_SIZE 9 - --#define IS_eDP(i) ((i)->base.type == INTEL_OUTPUT_EDP) --#define IS_PCH_eDP(i) ((i)->is_pch_edp) -- - struct intel_dp { - struct intel_encoder base; - uint32_t output_reg; - uint32_t DP; - uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; - bool has_audio; -+ int force_audio; - int dpms_mode; - uint8_t link_bw; - uint8_t lane_count; -@@ -58,14 +56,69 @@ struct intel_dp { - struct i2c_adapter adapter; - struct i2c_algo_dp_aux_data algo; - bool is_pch_edp; -+ uint8_t train_set[4]; -+ uint8_t link_status[DP_LINK_STATUS_SIZE]; -+ -+ struct drm_property *force_audio_property; - }; - -+/** -+ * is_edp - is the given port attached to an eDP panel (either CPU or PCH) -+ * @intel_dp: DP struct -+ * -+ * If a CPU or PCH DP output is attached to an eDP panel, this function -+ * will return true, and false otherwise. -+ */ -+static bool is_edp(struct intel_dp *intel_dp) -+{ -+ return intel_dp->base.type == INTEL_OUTPUT_EDP; -+} -+ -+/** -+ * is_pch_edp - is the port on the PCH and attached to an eDP panel? -+ * @intel_dp: DP struct -+ * -+ * Returns true if the given DP struct corresponds to a PCH DP port attached -+ * to an eDP panel, false otherwise. Helpful for determining whether we -+ * may need FDI resources for a given DP output or not. -+ */ -+static bool is_pch_edp(struct intel_dp *intel_dp) -+{ -+ return intel_dp->is_pch_edp; -+} -+ - static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder) - { -- return container_of(enc_to_intel_encoder(encoder), struct intel_dp, base); -+ return container_of(encoder, struct intel_dp, base.base); -+} -+ -+static struct intel_dp *intel_attached_dp(struct drm_connector *connector) -+{ -+ return container_of(intel_attached_encoder(connector), -+ struct intel_dp, base); -+} -+ -+/** -+ * intel_encoder_is_pch_edp - is the given encoder a PCH attached eDP? -+ * @encoder: DRM encoder -+ * -+ * Return true if @encoder corresponds to a PCH attached eDP panel. Needed -+ * by intel_display.c. -+ */ -+bool intel_encoder_is_pch_edp(struct drm_encoder *encoder) -+{ -+ struct intel_dp *intel_dp; -+ -+ if (!encoder) -+ return false; -+ -+ intel_dp = enc_to_intel_dp(encoder); -+ -+ return is_pch_edp(intel_dp); - } - --static void intel_dp_link_train(struct intel_dp *intel_dp); -+static void intel_dp_start_link_train(struct intel_dp *intel_dp); -+static void intel_dp_complete_link_train(struct intel_dp *intel_dp); - static void intel_dp_link_down(struct intel_dp *intel_dp); - - void -@@ -129,8 +182,8 @@ intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pi - { - struct drm_i915_private *dev_priv = dev->dev_private; - -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) -- return (pixel_clock * dev_priv->edp_bpp) / 8; -+ if (is_edp(intel_dp)) -+ return (pixel_clock * dev_priv->edp.bpp + 7) / 8; - else - return pixel_clock * 3; - } -@@ -145,15 +198,13 @@ static int - intel_dp_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dp *intel_dp = enc_to_intel_dp(encoder); -+ struct intel_dp *intel_dp = intel_attached_dp(connector); - struct drm_device *dev = connector->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); - int max_lanes = intel_dp_max_lane_count(intel_dp); - -- if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) && -- dev_priv->panel_fixed_mode) { -+ if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) { - if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) - return MODE_PANEL; - -@@ -163,7 +214,7 @@ intel_dp_mode_valid(struct drm_connector *connector, - - /* only refuse the mode on non eDP since we have seen some wierd eDP panels - which are outside spec tolerances but somehow work by magic */ -- if (!IS_eDP(intel_dp) && -+ if (!is_edp(intel_dp) && - (intel_dp_link_required(connector->dev, intel_dp, mode->clock) - > intel_dp_max_data_rate(max_link_clock, max_lanes))) - return MODE_CLOCK_HIGH; -@@ -233,7 +284,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, - uint8_t *recv, int recv_size) - { - uint32_t output_reg = intel_dp->output_reg; -- struct drm_device *dev = intel_dp->base.enc.dev; -+ struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t ch_ctl = output_reg + 0x10; - uint32_t ch_data = ch_ctl + 4; -@@ -246,8 +297,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, - /* The clock divider is based off the hrawclk, - * and would like to run at 2MHz. So, take the - * hrawclk value and divide by 2 and use that -+ * -+ * Note that PCH attached eDP panels should use a 125MHz input -+ * clock divider. - */ -- if (IS_eDP(intel_dp)) { -+ if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) { - if (IS_GEN6(dev)) - aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ - else -@@ -519,8 +573,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, - int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; - static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; - -- if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) && -- dev_priv->panel_fixed_mode) { -+ if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) { - intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode); - intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, - mode, adjusted_mode); -@@ -531,6 +584,17 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, - mode->clock = dev_priv->panel_fixed_mode->clock; - } - -+ /* Just use VBT values for eDP */ -+ if (is_edp(intel_dp)) { -+ intel_dp->lane_count = dev_priv->edp.lanes; -+ intel_dp->link_bw = dev_priv->edp.rate; -+ adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); -+ DRM_DEBUG_KMS("eDP link bw %02x lane count %d clock %d\n", -+ intel_dp->link_bw, intel_dp->lane_count, -+ adjusted_mode->clock); -+ return true; -+ } -+ - for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { - for (clock = 0; clock <= max_clock; clock++) { - int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); -@@ -549,19 +613,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, - } - } - -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) { -- /* okay we failed just pick the highest */ -- intel_dp->lane_count = max_lane_count; -- intel_dp->link_bw = bws[max_clock]; -- adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); -- DRM_DEBUG_KMS("Force picking display port link bw %02x lane " -- "count %d clock %d\n", -- intel_dp->link_bw, intel_dp->lane_count, -- adjusted_mode->clock); -- -- return true; -- } -- - return false; - } - -@@ -598,25 +649,6 @@ intel_dp_compute_m_n(int bpp, - intel_reduce_ratio(&m_n->link_m, &m_n->link_n); - } - --bool intel_pch_has_edp(struct drm_crtc *crtc) --{ -- struct drm_device *dev = crtc->dev; -- struct drm_mode_config *mode_config = &dev->mode_config; -- struct drm_encoder *encoder; -- -- list_for_each_entry(encoder, &mode_config->encoder_list, head) { -- struct intel_dp *intel_dp; -- -- if (encoder->crtc != crtc) -- continue; -- -- intel_dp = enc_to_intel_dp(encoder); -- if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) -- return intel_dp->is_pch_edp; -- } -- return false; --} -- - void - intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -@@ -641,8 +673,10 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, - intel_dp = enc_to_intel_dp(encoder); - if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) { - lane_count = intel_dp->lane_count; -- if (IS_PCH_eDP(intel_dp)) -- bpp = dev_priv->edp_bpp; -+ break; -+ } else if (is_edp(intel_dp)) { -+ lane_count = dev_priv->edp.lanes; -+ bpp = dev_priv->edp.bpp; - break; - } - } -@@ -698,7 +732,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - { - struct drm_device *dev = encoder->dev; - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); -- struct drm_crtc *crtc = intel_dp->base.enc.crtc; -+ struct drm_crtc *crtc = intel_dp->base.base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - intel_dp->DP = (DP_VOLTAGE_0_4 | -@@ -709,7 +743,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - intel_dp->DP |= DP_SYNC_VS_HIGH; - -- if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) -+ if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) - intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; - else - intel_dp->DP |= DP_LINK_TRAIN_OFF; -@@ -744,7 +778,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev)) - intel_dp->DP |= DP_PIPEB_SELECT; - -- if (IS_eDP(intel_dp)) { -+ if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) { - /* don't miss out required setting for eDP */ - intel_dp->DP |= DP_PLL_ENABLE; - if (adjusted_mode->clock < 200000) -@@ -754,13 +788,16 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - } - } - --static void ironlake_edp_panel_on (struct drm_device *dev) -+/* Returns true if the panel was already on when called */ -+static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) - { -+ struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- u32 pp; -+ u32 pp, idle_on = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; -+ u32 idle_on_mask = PP_ON | PP_SEQUENCE_STATE_MASK; - - if (I915_READ(PCH_PP_STATUS) & PP_ON) -- return; -+ return true; - - pp = I915_READ(PCH_PP_CONTROL); - -@@ -771,21 +808,30 @@ static void ironlake_edp_panel_on (struct drm_device *dev) - - pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON; - I915_WRITE(PCH_PP_CONTROL, pp); -+ POSTING_READ(PCH_PP_CONTROL); - -- if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000, 10)) -+ /* Ouch. We need to wait here for some panels, like Dell e6510 -+ * https://bugs.freedesktop.org/show_bug.cgi?id=29278i -+ */ -+ msleep(300); -+ -+ if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on, -+ 5000)) - DRM_ERROR("panel on wait timed out: 0x%08x\n", - I915_READ(PCH_PP_STATUS)); - -- pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD); - pp |= PANEL_POWER_RESET; /* restore panel reset bit */ - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); -+ -+ return false; - } - - static void ironlake_edp_panel_off (struct drm_device *dev) - { - struct drm_i915_private *dev_priv = dev->dev_private; -- u32 pp; -+ u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | -+ PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; - - pp = I915_READ(PCH_PP_CONTROL); - -@@ -796,15 +842,20 @@ static void ironlake_edp_panel_off (struct drm_device *dev) - - pp &= ~POWER_TARGET_ON; - I915_WRITE(PCH_PP_CONTROL, pp); -+ POSTING_READ(PCH_PP_CONTROL); - -- if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000, 10)) -+ if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) - DRM_ERROR("panel off wait timed out: 0x%08x\n", - I915_READ(PCH_PP_STATUS)); - -- /* Make sure VDD is enabled so DP AUX will work */ -- pp |= EDP_FORCE_VDD | PANEL_POWER_RESET; /* restore panel reset bit */ -+ pp |= PANEL_POWER_RESET; /* restore panel reset bit */ - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); -+ -+ /* Ouch. We need to wait here for some panels, like Dell e6510 -+ * https://bugs.freedesktop.org/show_bug.cgi?id=29278i -+ */ -+ msleep(300); - } - - static void ironlake_edp_backlight_on (struct drm_device *dev) -@@ -813,6 +864,13 @@ static void ironlake_edp_backlight_on (struct drm_device *dev) - u32 pp; - - DRM_DEBUG_KMS("\n"); -+ /* -+ * If we enable the backlight right away following a panel power -+ * on, we may see slight flicker as the panel syncs with the eDP -+ * link. So delay a bit to make sure the image is solid before -+ * allowing it to appear. -+ */ -+ msleep(300); - pp = I915_READ(PCH_PP_CONTROL); - pp |= EDP_BLC_ENABLE; - I915_WRITE(PCH_PP_CONTROL, pp); -@@ -837,8 +895,10 @@ static void ironlake_edp_pll_on(struct drm_encoder *encoder) - - DRM_DEBUG_KMS("\n"); - dpa_ctl = I915_READ(DP_A); -- dpa_ctl &= ~DP_PLL_ENABLE; -+ dpa_ctl |= DP_PLL_ENABLE; - I915_WRITE(DP_A, dpa_ctl); -+ POSTING_READ(DP_A); -+ udelay(200); - } - - static void ironlake_edp_pll_off(struct drm_encoder *encoder) -@@ -848,8 +908,9 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder) - u32 dpa_ctl; - - dpa_ctl = I915_READ(DP_A); -- dpa_ctl |= DP_PLL_ENABLE; -+ dpa_ctl &= ~DP_PLL_ENABLE; - I915_WRITE(DP_A, dpa_ctl); -+ POSTING_READ(DP_A); - udelay(200); - } - -@@ -857,29 +918,32 @@ static void intel_dp_prepare(struct drm_encoder *encoder) - { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct drm_device *dev = encoder->dev; -- struct drm_i915_private *dev_priv = dev->dev_private; -- uint32_t dp_reg = I915_READ(intel_dp->output_reg); - -- if (IS_eDP(intel_dp)) { -+ if (is_edp(intel_dp)) { - ironlake_edp_backlight_off(dev); -- ironlake_edp_panel_on(dev); -- ironlake_edp_pll_on(encoder); -+ ironlake_edp_panel_off(dev); -+ ironlake_edp_panel_on(intel_dp); -+ if (!is_pch_edp(intel_dp)) -+ ironlake_edp_pll_on(encoder); -+ else -+ ironlake_edp_pll_off(encoder); - } -- if (dp_reg & DP_PORT_EN) -- intel_dp_link_down(intel_dp); -+ intel_dp_link_down(intel_dp); - } - - static void intel_dp_commit(struct drm_encoder *encoder) - { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct drm_device *dev = encoder->dev; -- struct drm_i915_private *dev_priv = dev->dev_private; -- uint32_t dp_reg = I915_READ(intel_dp->output_reg); - -- if (!(dp_reg & DP_PORT_EN)) { -- intel_dp_link_train(intel_dp); -- } -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) -+ intel_dp_start_link_train(intel_dp); -+ -+ if (is_edp(intel_dp)) -+ ironlake_edp_panel_on(intel_dp); -+ -+ intel_dp_complete_link_train(intel_dp); -+ -+ if (is_edp(intel_dp)) - ironlake_edp_backlight_on(dev); - } - -@@ -892,22 +956,22 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) - uint32_t dp_reg = I915_READ(intel_dp->output_reg); - - if (mode != DRM_MODE_DPMS_ON) { -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) { -+ if (is_edp(intel_dp)) - ironlake_edp_backlight_off(dev); -+ intel_dp_link_down(intel_dp); -+ if (is_edp(intel_dp)) - ironlake_edp_panel_off(dev); -- } -- if (dp_reg & DP_PORT_EN) -- intel_dp_link_down(intel_dp); -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) -+ if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) - ironlake_edp_pll_off(encoder); - } else { -+ if (is_edp(intel_dp)) -+ ironlake_edp_panel_on(intel_dp); - if (!(dp_reg & DP_PORT_EN)) { -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) -- ironlake_edp_panel_on(dev); -- intel_dp_link_train(intel_dp); -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) -- ironlake_edp_backlight_on(dev); -+ intel_dp_start_link_train(intel_dp); -+ intel_dp_complete_link_train(intel_dp); - } -+ if (is_edp(intel_dp)) -+ ironlake_edp_backlight_on(dev); - } - intel_dp->dpms_mode = mode; - } -@@ -917,14 +981,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) - * link status information - */ - static bool --intel_dp_get_link_status(struct intel_dp *intel_dp, -- uint8_t link_status[DP_LINK_STATUS_SIZE]) -+intel_dp_get_link_status(struct intel_dp *intel_dp) - { - int ret; - - ret = intel_dp_aux_native_read(intel_dp, - DP_LANE0_1_STATUS, -- link_status, DP_LINK_STATUS_SIZE); -+ intel_dp->link_status, DP_LINK_STATUS_SIZE); - if (ret != DP_LINK_STATUS_SIZE) - return false; - return true; -@@ -999,18 +1062,15 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing) - } - - static void --intel_get_adjust_train(struct intel_dp *intel_dp, -- uint8_t link_status[DP_LINK_STATUS_SIZE], -- int lane_count, -- uint8_t train_set[4]) -+intel_get_adjust_train(struct intel_dp *intel_dp) - { - uint8_t v = 0; - uint8_t p = 0; - int lane; - -- for (lane = 0; lane < lane_count; lane++) { -- uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane); -- uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane); -+ for (lane = 0; lane < intel_dp->lane_count; lane++) { -+ uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane); -+ uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane); - - if (this_v > v) - v = this_v; -@@ -1025,15 +1085,25 @@ intel_get_adjust_train(struct intel_dp *intel_dp, - p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; - - for (lane = 0; lane < 4; lane++) -- train_set[lane] = v | p; -+ intel_dp->train_set[lane] = v | p; - } - - static uint32_t --intel_dp_signal_levels(uint8_t train_set, int lane_count) -+intel_dp_signal_levels(struct intel_dp *intel_dp) - { -- uint32_t signal_levels = 0; -+ struct drm_device *dev = intel_dp->base.base.dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ uint32_t signal_levels = 0; -+ u8 train_set = intel_dp->train_set[0]; -+ u32 vswing = train_set & DP_TRAIN_VOLTAGE_SWING_MASK; -+ u32 preemphasis = train_set & DP_TRAIN_PRE_EMPHASIS_MASK; -+ -+ if (is_edp(intel_dp)) { -+ vswing = dev_priv->edp.vswing; -+ preemphasis = dev_priv->edp.preemphasis; -+ } - -- switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { -+ switch (vswing) { - case DP_TRAIN_VOLTAGE_SWING_400: - default: - signal_levels |= DP_VOLTAGE_0_4; -@@ -1048,7 +1118,7 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count) - signal_levels |= DP_VOLTAGE_1_2; - break; - } -- switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { -+ switch (preemphasis) { - case DP_TRAIN_PRE_EMPHASIS_0: - default: - signal_levels |= DP_PRE_EMPHASIS_0; -@@ -1116,18 +1186,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count - DP_LANE_CHANNEL_EQ_DONE|\ - DP_LANE_SYMBOL_LOCKED) - static bool --intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) -+intel_channel_eq_ok(struct intel_dp *intel_dp) - { - uint8_t lane_align; - uint8_t lane_status; - int lane; - -- lane_align = intel_dp_link_status(link_status, -+ lane_align = intel_dp_link_status(intel_dp->link_status, - DP_LANE_ALIGN_STATUS_UPDATED); - if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) - return false; -- for (lane = 0; lane < lane_count; lane++) { -- lane_status = intel_get_lane_status(link_status, lane); -+ for (lane = 0; lane < intel_dp->lane_count; lane++) { -+ lane_status = intel_get_lane_status(intel_dp->link_status, lane); - if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) - return false; - } -@@ -1135,159 +1205,194 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) - } - - static bool -+intel_dp_aux_handshake_required(struct intel_dp *intel_dp) -+{ -+ struct drm_device *dev = intel_dp->base.base.dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ -+ if (is_edp(intel_dp) && dev_priv->no_aux_handshake) -+ return false; -+ -+ return true; -+} -+ -+static bool - intel_dp_set_link_train(struct intel_dp *intel_dp, - uint32_t dp_reg_value, -- uint8_t dp_train_pat, -- uint8_t train_set[4]) -+ uint8_t dp_train_pat) - { -- struct drm_device *dev = intel_dp->base.enc.dev; -+ struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - I915_WRITE(intel_dp->output_reg, dp_reg_value); - POSTING_READ(intel_dp->output_reg); - -+ if (!intel_dp_aux_handshake_required(intel_dp)) -+ return true; -+ - intel_dp_aux_native_write_1(intel_dp, - DP_TRAINING_PATTERN_SET, - dp_train_pat); - - ret = intel_dp_aux_native_write(intel_dp, -- DP_TRAINING_LANE0_SET, train_set, 4); -+ DP_TRAINING_LANE0_SET, -+ intel_dp->train_set, 4); - if (ret != 4) - return false; - - return true; - } - -+/* Enable corresponding port and start training pattern 1 */ - static void --intel_dp_link_train(struct intel_dp *intel_dp) -+intel_dp_start_link_train(struct intel_dp *intel_dp) - { -- struct drm_device *dev = intel_dp->base.enc.dev; -+ struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- uint8_t train_set[4]; -- uint8_t link_status[DP_LINK_STATUS_SIZE]; -+ struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc); - int i; - uint8_t voltage; - bool clock_recovery = false; -- bool channel_eq = false; - int tries; - u32 reg; - uint32_t DP = intel_dp->DP; -- struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); - - /* Enable output, wait for it to become active */ - I915_WRITE(intel_dp->output_reg, intel_dp->DP); - POSTING_READ(intel_dp->output_reg); - intel_wait_for_vblank(dev, intel_crtc->pipe); - -- /* Write the link configuration data */ -- intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, -- intel_dp->link_configuration, -- DP_LINK_CONFIGURATION_SIZE); -+ if (intel_dp_aux_handshake_required(intel_dp)) -+ /* Write the link configuration data */ -+ intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, -+ intel_dp->link_configuration, -+ DP_LINK_CONFIGURATION_SIZE); - - DP |= DP_PORT_EN; -- if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) -+ if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) - DP &= ~DP_LINK_TRAIN_MASK_CPT; - else - DP &= ~DP_LINK_TRAIN_MASK; -- memset(train_set, 0, 4); -+ memset(intel_dp->train_set, 0, 4); - voltage = 0xff; - tries = 0; - clock_recovery = false; - for (;;) { -- /* Use train_set[0] to set the voltage and pre emphasis values */ -+ /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ - uint32_t signal_levels; -- if (IS_GEN6(dev) && IS_eDP(intel_dp)) { -- signal_levels = intel_gen6_edp_signal_levels(train_set[0]); -+ if (IS_GEN6(dev) && is_edp(intel_dp)) { -+ signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); - DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; - } else { -- signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count); -+ signal_levels = intel_dp_signal_levels(intel_dp); - DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; - } - -- if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) -+ if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) - reg = DP | DP_LINK_TRAIN_PAT_1_CPT; - else - reg = DP | DP_LINK_TRAIN_PAT_1; - - if (!intel_dp_set_link_train(intel_dp, reg, -- DP_TRAINING_PATTERN_1, train_set)) -+ DP_TRAINING_PATTERN_1)) - break; - /* Set training pattern 1 */ - -- udelay(100); -- if (!intel_dp_get_link_status(intel_dp, link_status)) -+ udelay(500); -+ if (intel_dp_aux_handshake_required(intel_dp)) { - break; -+ } else { -+ if (!intel_dp_get_link_status(intel_dp)) -+ break; - -- if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) { -- clock_recovery = true; -- break; -- } -- -- /* Check to see if we've tried the max voltage */ -- for (i = 0; i < intel_dp->lane_count; i++) -- if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) -+ if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { -+ clock_recovery = true; - break; -- if (i == intel_dp->lane_count) -- break; -+ } - -- /* Check to see if we've tried the same voltage 5 times */ -- if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { -- ++tries; -- if (tries == 5) -+ /* Check to see if we've tried the max voltage */ -+ for (i = 0; i < intel_dp->lane_count; i++) -+ if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) -+ break; -+ if (i == intel_dp->lane_count) - break; -- } else -- tries = 0; -- voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; - -- /* Compute new train_set as requested by target */ -- intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set); -+ /* Check to see if we've tried the same voltage 5 times */ -+ if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { -+ ++tries; -+ if (tries == 5) -+ break; -+ } else -+ tries = 0; -+ voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; -+ -+ /* Compute new intel_dp->train_set as requested by target */ -+ intel_get_adjust_train(intel_dp); -+ } - } - -+ intel_dp->DP = DP; -+} -+ -+static void -+intel_dp_complete_link_train(struct intel_dp *intel_dp) -+{ -+ struct drm_device *dev = intel_dp->base.base.dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ bool channel_eq = false; -+ int tries; -+ u32 reg; -+ uint32_t DP = intel_dp->DP; -+ - /* channel equalization */ - tries = 0; - channel_eq = false; - for (;;) { -- /* Use train_set[0] to set the voltage and pre emphasis values */ -+ /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ - uint32_t signal_levels; - -- if (IS_GEN6(dev) && IS_eDP(intel_dp)) { -- signal_levels = intel_gen6_edp_signal_levels(train_set[0]); -+ if (IS_GEN6(dev) && is_edp(intel_dp)) { -+ signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); - DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; - } else { -- signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count); -+ signal_levels = intel_dp_signal_levels(intel_dp); - DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; - } - -- if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) -+ if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) - reg = DP | DP_LINK_TRAIN_PAT_2_CPT; - else - reg = DP | DP_LINK_TRAIN_PAT_2; - - /* channel eq pattern */ - if (!intel_dp_set_link_train(intel_dp, reg, -- DP_TRAINING_PATTERN_2, train_set)) -+ DP_TRAINING_PATTERN_2)) - break; - -- udelay(400); -- if (!intel_dp_get_link_status(intel_dp, link_status)) -- break; -+ udelay(500); - -- if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) { -- channel_eq = true; -+ if (!intel_dp_aux_handshake_required(intel_dp)) { - break; -- } -+ } else { -+ if (!intel_dp_get_link_status(intel_dp)) -+ break; - -- /* Try 5 times */ -- if (tries > 5) -- break; -+ if (intel_channel_eq_ok(intel_dp)) { -+ channel_eq = true; -+ break; -+ } - -- /* Compute new train_set as requested by target */ -- intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set); -- ++tries; -- } -+ /* Try 5 times */ -+ if (tries > 5) -+ break; - -- if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) -+ /* Compute new intel_dp->train_set as requested by target */ -+ intel_get_adjust_train(intel_dp); -+ ++tries; -+ } -+ } -+ if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) - reg = DP | DP_LINK_TRAIN_OFF_CPT; - else - reg = DP | DP_LINK_TRAIN_OFF; -@@ -1301,32 +1406,31 @@ intel_dp_link_train(struct intel_dp *intel_dp) - static void - intel_dp_link_down(struct intel_dp *intel_dp) - { -- struct drm_device *dev = intel_dp->base.enc.dev; -+ struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t DP = intel_dp->DP; - - DRM_DEBUG_KMS("\n"); - -- if (IS_eDP(intel_dp)) { -+ if (is_edp(intel_dp)) { - DP &= ~DP_PLL_ENABLE; - I915_WRITE(intel_dp->output_reg, DP); - POSTING_READ(intel_dp->output_reg); - udelay(100); - } - -- if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) { -+ if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) { - DP &= ~DP_LINK_TRAIN_MASK_CPT; - I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); -- POSTING_READ(intel_dp->output_reg); - } else { - DP &= ~DP_LINK_TRAIN_MASK; - I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); -- POSTING_READ(intel_dp->output_reg); - } -+ POSTING_READ(intel_dp->output_reg); - -- udelay(17000); -+ msleep(17); - -- if (IS_eDP(intel_dp)) -+ if (is_edp(intel_dp)) - DP |= DP_LINK_TRAIN_OFF; - I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); - POSTING_READ(intel_dp->output_reg); -@@ -1344,32 +1448,34 @@ intel_dp_link_down(struct intel_dp *intel_dp) - static void - intel_dp_check_link_status(struct intel_dp *intel_dp) - { -- uint8_t link_status[DP_LINK_STATUS_SIZE]; -- -- if (!intel_dp->base.enc.crtc) -+ if (!intel_dp->base.base.crtc) - return; - -- if (!intel_dp_get_link_status(intel_dp, link_status)) { -+ if (!intel_dp_get_link_status(intel_dp)) { - intel_dp_link_down(intel_dp); - return; - } - -- if (!intel_channel_eq_ok(link_status, intel_dp->lane_count)) -- intel_dp_link_train(intel_dp); -+ if (!intel_channel_eq_ok(intel_dp)) { -+ intel_dp_start_link_train(intel_dp); -+ intel_dp_complete_link_train(intel_dp); -+ } - } - - static enum drm_connector_status --ironlake_dp_detect(struct drm_connector *connector) -+ironlake_dp_detect(struct intel_dp *intel_dp) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - enum drm_connector_status status; - -+ /* Can't disconnect eDP */ -+ if (is_edp(intel_dp)) -+ return connector_status_connected; -+ - status = connector_status_disconnected; - if (intel_dp_aux_native_read(intel_dp, - 0x000, intel_dp->dpcd, -- sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd)) -- { -+ sizeof (intel_dp->dpcd)) -+ == sizeof(intel_dp->dpcd)) { - if (intel_dp->dpcd[0] != 0) - status = connector_status_connected; - } -@@ -1378,26 +1484,13 @@ ironlake_dp_detect(struct drm_connector *connector) - return status; - } - --/** -- * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. -- * -- * \return true if DP port is connected. -- * \return false if DP port is disconnected. -- */ - static enum drm_connector_status --intel_dp_detect(struct drm_connector *connector, bool force) -+g4x_dp_detect(struct intel_dp *intel_dp) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dp *intel_dp = enc_to_intel_dp(encoder); -- struct drm_device *dev = intel_dp->base.enc.dev; -+ struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- uint32_t temp, bit; - enum drm_connector_status status; -- -- intel_dp->has_audio = false; -- -- if (HAS_PCH_SPLIT(dev)) -- return ironlake_dp_detect(connector); -+ uint32_t temp, bit; - - switch (intel_dp->output_reg) { - case DP_B: -@@ -1419,31 +1512,66 @@ intel_dp_detect(struct drm_connector *connector, bool force) - return connector_status_disconnected; - - status = connector_status_disconnected; -- if (intel_dp_aux_native_read(intel_dp, -- 0x000, intel_dp->dpcd, -+ if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd, - sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd)) - { - if (intel_dp->dpcd[0] != 0) - status = connector_status_connected; - } -+ - return status; - } - -+/** -+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. -+ * -+ * \return true if DP port is connected. -+ * \return false if DP port is disconnected. -+ */ -+static enum drm_connector_status -+intel_dp_detect(struct drm_connector *connector, bool force) -+{ -+ struct intel_dp *intel_dp = intel_attached_dp(connector); -+ struct drm_device *dev = intel_dp->base.base.dev; -+ enum drm_connector_status status; -+ struct edid *edid = NULL; -+ -+ intel_dp->has_audio = false; -+ -+ if (HAS_PCH_SPLIT(dev)) -+ status = ironlake_dp_detect(intel_dp); -+ else -+ status = g4x_dp_detect(intel_dp); -+ if (status != connector_status_connected) -+ return status; -+ -+ if (intel_dp->force_audio) { -+ intel_dp->has_audio = intel_dp->force_audio > 0; -+ } else { -+ edid = drm_get_edid(connector, &intel_dp->adapter); -+ if (edid) { -+ intel_dp->has_audio = drm_detect_monitor_audio(edid); -+ connector->display_info.raw_edid = NULL; -+ kfree(edid); -+ } -+ } -+ -+ return connector_status_connected; -+} -+ - static int intel_dp_get_modes(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dp *intel_dp = enc_to_intel_dp(encoder); -- struct drm_device *dev = intel_dp->base.enc.dev; -+ struct intel_dp *intel_dp = intel_attached_dp(connector); -+ struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - /* We should parse the EDID data and find out if it has an audio sink - */ - -- ret = intel_ddc_get_modes(connector, intel_dp->base.ddc_bus); -+ ret = intel_ddc_get_modes(connector, &intel_dp->adapter); - if (ret) { -- if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) && -- !dev_priv->panel_fixed_mode) { -+ if (is_edp(intel_dp) && !dev_priv->panel_fixed_mode) { - struct drm_display_mode *newmode; - list_for_each_entry(newmode, &connector->probed_modes, - head) { -@@ -1459,7 +1587,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) - } - - /* if eDP has no EDID, try to use fixed panel mode from VBT */ -- if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) { -+ if (is_edp(intel_dp)) { - if (dev_priv->panel_fixed_mode != NULL) { - struct drm_display_mode *mode; - mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); -@@ -1470,6 +1598,46 @@ static int intel_dp_get_modes(struct drm_connector *connector) - return 0; - } - -+static int -+intel_dp_set_property(struct drm_connector *connector, -+ struct drm_property *property, -+ uint64_t val) -+{ -+ struct intel_dp *intel_dp = intel_attached_dp(connector); -+ int ret; -+ -+ ret = drm_connector_property_set_value(connector, property, val); -+ if (ret) -+ return ret; -+ -+ if (property == intel_dp->force_audio_property) { -+ if (val == intel_dp->force_audio) -+ return 0; -+ -+ intel_dp->force_audio = val; -+ -+ if (val > 0 && intel_dp->has_audio) -+ return 0; -+ if (val < 0 && !intel_dp->has_audio) -+ return 0; -+ -+ intel_dp->has_audio = val > 0; -+ goto done; -+ } -+ -+ return -EINVAL; -+ -+done: -+ if (intel_dp->base.base.crtc) { -+ struct drm_crtc *crtc = intel_dp->base.base.crtc; -+ drm_crtc_helper_set_mode(crtc, &crtc->mode, -+ crtc->x, crtc->y, -+ crtc->fb); -+ } -+ -+ return 0; -+} -+ - static void - intel_dp_destroy (struct drm_connector *connector) - { -@@ -1478,6 +1646,15 @@ intel_dp_destroy (struct drm_connector *connector) - kfree(connector); - } - -+static void intel_dp_encoder_destroy(struct drm_encoder *encoder) -+{ -+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder); -+ -+ i2c_del_adapter(&intel_dp->adapter); -+ drm_encoder_cleanup(encoder); -+ kfree(intel_dp); -+} -+ - static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { - .dpms = intel_dp_dpms, - .mode_fixup = intel_dp_mode_fixup, -@@ -1490,20 +1667,21 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .detect = intel_dp_detect, - .fill_modes = drm_helper_probe_single_connector_modes, -+ .set_property = intel_dp_set_property, - .destroy = intel_dp_destroy, - }; - - static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { - .get_modes = intel_dp_get_modes, - .mode_valid = intel_dp_mode_valid, -- .best_encoder = intel_attached_encoder, -+ .best_encoder = intel_best_encoder, - }; - - static const struct drm_encoder_funcs intel_dp_enc_funcs = { -- .destroy = intel_encoder_destroy, -+ .destroy = intel_dp_encoder_destroy, - }; - --void -+static void - intel_dp_hot_plug(struct intel_encoder *intel_encoder) - { - struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); -@@ -1554,6 +1732,20 @@ bool intel_dpd_is_edp(struct drm_device *dev) - return false; - } - -+static void -+intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) -+{ -+ struct drm_device *dev = connector->dev; -+ -+ intel_dp->force_audio_property = -+ drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2); -+ if (intel_dp->force_audio_property) { -+ intel_dp->force_audio_property->values[0] = -1; -+ intel_dp->force_audio_property->values[1] = 1; -+ drm_connector_attach_property(connector, intel_dp->force_audio_property, 0); -+ } -+} -+ - void - intel_dp_init(struct drm_device *dev, int output_reg) - { -@@ -1580,7 +1772,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) - if (intel_dpd_is_edp(dev)) - intel_dp->is_pch_edp = true; - -- if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) { -+ if (output_reg == DP_A || is_pch_edp(intel_dp)) { - type = DRM_MODE_CONNECTOR_eDP; - intel_encoder->type = INTEL_OUTPUT_EDP; - } else { -@@ -1601,7 +1793,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) - else if (output_reg == DP_D || output_reg == PCH_DP_D) - intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); - -- if (IS_eDP(intel_dp)) -+ if (is_edp(intel_dp)) - intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT); - - intel_encoder->crtc_mask = (1 << 0) | (1 << 1); -@@ -1612,12 +1804,11 @@ intel_dp_init(struct drm_device *dev, int output_reg) - intel_dp->has_audio = false; - intel_dp->dpms_mode = DRM_MODE_DPMS_ON; - -- drm_encoder_init(dev, &intel_encoder->enc, &intel_dp_enc_funcs, -+ drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs, - DRM_MODE_ENCODER_TMDS); -- drm_encoder_helper_add(&intel_encoder->enc, &intel_dp_helper_funcs); -+ drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs); - -- drm_mode_connector_attach_encoder(&intel_connector->base, -- &intel_encoder->enc); -+ intel_connector_attach_encoder(intel_connector, intel_encoder); - drm_sysfs_connector_add(connector); - - /* Set up the DDC bus. */ -@@ -1647,10 +1838,29 @@ intel_dp_init(struct drm_device *dev, int output_reg) - - intel_dp_i2c_init(intel_dp, intel_connector, name); - -- intel_encoder->ddc_bus = &intel_dp->adapter; -+ /* Cache some DPCD data in the eDP case */ -+ if (is_edp(intel_dp)) { -+ int ret; -+ bool was_on; -+ -+ was_on = ironlake_edp_panel_on(intel_dp); -+ ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV, -+ intel_dp->dpcd, -+ sizeof(intel_dp->dpcd)); -+ if (ret == sizeof(intel_dp->dpcd)) { -+ if (intel_dp->dpcd[0] >= 0x11) -+ dev_priv->no_aux_handshake = intel_dp->dpcd[3] & -+ DP_NO_AUX_HANDSHAKE_LINK_TRAINING; -+ } else { -+ DRM_ERROR("failed to retrieve link info\n"); -+ } -+ if (!was_on) -+ ironlake_edp_panel_off(dev); -+ } -+ - intel_encoder->hot_plug = intel_dp_hot_plug; - -- if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) { -+ if (is_edp(intel_dp)) { - /* initialize panel mode from VBT if available for eDP */ - if (dev_priv->lfp_lvds_vbt_mode) { - dev_priv->panel_fixed_mode = -@@ -1662,6 +1872,8 @@ intel_dp_init(struct drm_device *dev, int output_reg) - } - } - -+ intel_dp_add_properties(intel_dp, connector); -+ - /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written - * 0xd. Failure to do so will result in spurious interrupts being - * generated on the port when a cable is not attached. -diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h -index 8828b3a..21551fe 100644 ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -26,14 +26,12 @@ - #define __INTEL_DRV_H__ - - #include --#include --#include - #include "i915_drv.h" - #include "drm_crtc.h" -- - #include "drm_crtc_helper.h" -+#include "drm_fb_helper.h" - --#define wait_for(COND, MS, W) ({ \ -+#define _wait_for(COND, MS, W) ({ \ - unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ - int ret__ = 0; \ - while (! (COND)) { \ -@@ -41,11 +39,24 @@ - ret__ = -ETIMEDOUT; \ - break; \ - } \ -- if (W) msleep(W); \ -+ if (W && !in_dbg_master()) msleep(W); \ - } \ - ret__; \ - }) - -+#define wait_for(COND, MS) _wait_for(COND, MS, 1) -+#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) -+ -+#define MSLEEP(x) do { \ -+ if (in_dbg_master()) \ -+ mdelay(x); \ -+ else \ -+ msleep(x); \ -+} while(0) -+ -+#define KHz(x) (1000*x) -+#define MHz(x) KHz(1000*x) -+ - /* - * Display related stuff - */ -@@ -96,24 +107,39 @@ - #define INTEL_DVO_CHIP_TMDS 2 - #define INTEL_DVO_CHIP_TVOUT 4 - --struct intel_i2c_chan { -- struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */ -- u32 reg; /* GPIO reg */ -- struct i2c_adapter adapter; -- struct i2c_algo_bit_data algo; --}; -+/* drm_display_mode->private_flags */ -+#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) -+#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) -+ -+static inline void -+intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, -+ int multiplier) -+{ -+ mode->clock *= multiplier; -+ mode->private_flags |= multiplier; -+} -+ -+static inline int -+intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode) -+{ -+ return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT; -+} - - struct intel_framebuffer { - struct drm_framebuffer base; - struct drm_gem_object *obj; - }; - -+struct intel_fbdev { -+ struct drm_fb_helper helper; -+ struct intel_framebuffer ifb; -+ struct list_head fbdev_list; -+ struct drm_display_mode *our_mode; -+}; - - struct intel_encoder { -- struct drm_encoder enc; -+ struct drm_encoder base; - int type; -- struct i2c_adapter *i2c_bus; -- struct i2c_adapter *ddc_bus; - bool load_detect_temp; - bool needs_tv_clock; - void (*hot_plug)(struct intel_encoder *); -@@ -123,32 +149,7 @@ struct intel_encoder { - - struct intel_connector { - struct drm_connector base; --}; -- --struct intel_crtc; --struct intel_overlay { -- struct drm_device *dev; -- struct intel_crtc *crtc; -- struct drm_i915_gem_object *vid_bo; -- struct drm_i915_gem_object *old_vid_bo; -- int active; -- int pfit_active; -- u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ -- u32 color_key; -- u32 brightness, contrast, saturation; -- u32 old_xscale, old_yscale; -- /* register access */ -- u32 flip_addr; -- struct drm_i915_gem_object *reg_bo; -- void *virt_addr; -- /* flip handling */ -- uint32_t last_flip_req; -- int hw_wedged; --#define HW_WEDGED 1 --#define NEEDS_WAIT_FOR_FLIP 2 --#define RELEASE_OLD_VID 3 --#define SWITCH_OFF_STAGE_1 4 --#define SWITCH_OFF_STAGE_2 5 -+ struct intel_encoder *encoder; - }; - - struct intel_crtc { -@@ -157,6 +158,7 @@ struct intel_crtc { - enum plane plane; - u8 lut_r[256], lut_g[256], lut_b[256]; - int dpms_mode; -+ bool active; /* is the crtc on? independent of the dpms mode */ - bool busy; /* is scanout buffer being updated frequently? */ - struct timer_list idle_timer; - bool lowfreq_avail; -@@ -168,14 +170,53 @@ struct intel_crtc { - uint32_t cursor_addr; - int16_t cursor_x, cursor_y; - int16_t cursor_width, cursor_height; -- bool cursor_visible, cursor_on; -+ bool cursor_visible; - }; - - #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) - #define to_intel_connector(x) container_of(x, struct intel_connector, base) --#define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc) -+#define to_intel_encoder(x) container_of(x, struct intel_encoder, base) - #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) - -+#define DIP_TYPE_AVI 0x82 -+#define DIP_VERSION_AVI 0x2 -+#define DIP_LEN_AVI 13 -+ -+struct dip_infoframe { -+ uint8_t type; /* HB0 */ -+ uint8_t ver; /* HB1 */ -+ uint8_t len; /* HB2 - body len, not including checksum */ -+ uint8_t ecc; /* Header ECC */ -+ uint8_t checksum; /* PB0 */ -+ union { -+ struct { -+ /* PB1 - Y 6:5, A 4:4, B 3:2, S 1:0 */ -+ uint8_t Y_A_B_S; -+ /* PB2 - C 7:6, M 5:4, R 3:0 */ -+ uint8_t C_M_R; -+ /* PB3 - ITC 7:7, EC 6:4, Q 3:2, SC 1:0 */ -+ uint8_t ITC_EC_Q_SC; -+ /* PB4 - VIC 6:0 */ -+ uint8_t VIC; -+ /* PB5 - PR 3:0 */ -+ uint8_t PR; -+ /* PB6 to PB13 */ -+ uint16_t top_bar_end; -+ uint16_t bottom_bar_start; -+ uint16_t left_bar_end; -+ uint16_t right_bar_start; -+ } avi; -+ uint8_t payload[27]; -+ } __attribute__ ((packed)) body; -+} __attribute__((packed)); -+ -+static inline struct drm_crtc * -+intel_get_crtc_for_pipe(struct drm_device *dev, int pipe) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ return dev_priv->pipe_to_crtc_mapping[pipe]; -+} -+ - struct intel_unpin_work { - struct work_struct work; - struct drm_device *dev; -@@ -186,16 +227,12 @@ struct intel_unpin_work { - bool enable_stall_check; - }; - --struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, -- const char *name); --void intel_i2c_destroy(struct i2c_adapter *adapter); - int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); --extern bool intel_ddc_probe(struct intel_encoder *intel_encoder); --void intel_i2c_quirk_set(struct drm_device *dev, bool enable); --void intel_i2c_reset_gmbus(struct drm_device *dev); -+extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); - - extern void intel_crt_init(struct drm_device *dev); - extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); -+void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); - extern bool intel_sdvo_init(struct drm_device *dev, int output_device); - extern void intel_dvo_init(struct drm_device *dev); - extern void intel_tv_init(struct drm_device *dev); -@@ -205,32 +242,41 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg); - void - intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); --extern bool intel_pch_has_edp(struct drm_crtc *crtc); - extern bool intel_dpd_is_edp(struct drm_device *dev); - extern void intel_edp_link_config (struct intel_encoder *, int *, int *); -+extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); - -- -+/* intel_panel.c */ - extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, - struct drm_display_mode *adjusted_mode); - extern void intel_pch_panel_fitting(struct drm_device *dev, - int fitting_mode, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); -+extern u32 intel_panel_get_max_backlight(struct drm_device *dev); -+extern u32 intel_panel_get_backlight(struct drm_device *dev); -+extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); - --extern int intel_panel_fitter_pipe (struct drm_device *dev); - extern void intel_crtc_load_lut(struct drm_crtc *crtc); - extern void intel_encoder_prepare (struct drm_encoder *encoder); - extern void intel_encoder_commit (struct drm_encoder *encoder); - extern void intel_encoder_destroy(struct drm_encoder *encoder); - --extern struct drm_encoder *intel_attached_encoder(struct drm_connector *connector); -+static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) -+{ -+ return to_intel_connector(connector)->encoder; -+} -+ -+extern void intel_connector_attach_encoder(struct intel_connector *connector, -+ struct intel_encoder *encoder); -+extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector); - - extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc); - int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file_priv); - extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); --extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); -+extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); - extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, - struct drm_connector *connector, - struct drm_display_mode *mode, -@@ -250,9 +296,11 @@ extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - extern void intel_init_clock_gating(struct drm_device *dev); - extern void ironlake_enable_drps(struct drm_device *dev); - extern void ironlake_disable_drps(struct drm_device *dev); -+extern void intel_init_emon(struct drm_device *dev); - - extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, -- struct drm_gem_object *obj); -+ struct drm_gem_object *obj, -+ bool pipelined); - - extern int intel_framebuffer_init(struct drm_device *dev, - struct intel_framebuffer *ifb, -@@ -267,9 +315,8 @@ extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); - - extern void intel_setup_overlay(struct drm_device *dev); - extern void intel_cleanup_overlay(struct drm_device *dev); --extern int intel_overlay_switch_off(struct intel_overlay *overlay); --extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, -- int interruptible); -+extern int intel_overlay_switch_off(struct intel_overlay *overlay, -+ bool interruptible); - extern int intel_overlay_put_image(struct drm_device *dev, void *data, - struct drm_file *file_priv); - extern int intel_overlay_attrs(struct drm_device *dev, void *data, -diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c -index 7c9ec14..ea37328 100644 ---- a/drivers/gpu/drm/i915/intel_dvo.c -+++ b/drivers/gpu/drm/i915/intel_dvo.c -@@ -72,7 +72,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { - .name = "ch7017", - .dvo_reg = DVOC, - .slave_addr = 0x75, -- .gpio = GPIOE, -+ .gpio = GMBUS_PORT_DPB, - .dev_ops = &ch7017_ops, - } - }; -@@ -88,7 +88,13 @@ struct intel_dvo { - - static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder) - { -- return container_of(enc_to_intel_encoder(encoder), struct intel_dvo, base); -+ return container_of(encoder, struct intel_dvo, base.base); -+} -+ -+static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector) -+{ -+ return container_of(intel_attached_encoder(connector), -+ struct intel_dvo, base); - } - - static void intel_dvo_dpms(struct drm_encoder *encoder, int mode) -@@ -112,8 +118,7 @@ static void intel_dvo_dpms(struct drm_encoder *encoder, int mode) - static int intel_dvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); -+ struct intel_dvo *intel_dvo = intel_attached_dvo(connector); - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; -@@ -224,23 +229,22 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, - static enum drm_connector_status - intel_dvo_detect(struct drm_connector *connector, bool force) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); -- -+ struct intel_dvo *intel_dvo = intel_attached_dvo(connector); - return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); - } - - static int intel_dvo_get_modes(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); -+ struct intel_dvo *intel_dvo = intel_attached_dvo(connector); -+ struct drm_i915_private *dev_priv = connector->dev->dev_private; - - /* We should probably have an i2c driver get_modes function for those - * devices which will have a fixed set of modes determined by the chip - * (TV-out, for example), but for now with just TMDS and LVDS, - * that's not the case. - */ -- intel_ddc_get_modes(connector, intel_dvo->base.ddc_bus); -+ intel_ddc_get_modes(connector, -+ &dev_priv->gmbus[GMBUS_PORT_DPC].adapter); - if (!list_empty(&connector->probed_modes)) - return 1; - -@@ -281,7 +285,7 @@ static const struct drm_connector_funcs intel_dvo_connector_funcs = { - static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = { - .mode_valid = intel_dvo_mode_valid, - .get_modes = intel_dvo_get_modes, -- .best_encoder = intel_attached_encoder, -+ .best_encoder = intel_best_encoder, - }; - - static void intel_dvo_enc_destroy(struct drm_encoder *encoder) -@@ -311,8 +315,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector) - { - struct drm_device *dev = connector->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); -+ struct intel_dvo *intel_dvo = intel_attached_dvo(connector); - uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); - struct drm_display_mode *mode = NULL; - -@@ -323,7 +326,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector) - struct drm_crtc *crtc; - int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; - -- crtc = intel_get_crtc_from_pipe(dev, pipe); -+ crtc = intel_get_crtc_for_pipe(dev, pipe); - if (crtc) { - mode = intel_crtc_mode_get(dev, crtc); - if (mode) { -@@ -341,11 +344,10 @@ intel_dvo_get_current_mode(struct drm_connector *connector) - - void intel_dvo_init(struct drm_device *dev) - { -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *intel_encoder; - struct intel_dvo *intel_dvo; - struct intel_connector *intel_connector; -- struct i2c_adapter *i2cbus = NULL; -- int ret = 0; - int i; - int encoder_type = DRM_MODE_ENCODER_NONE; - -@@ -360,16 +362,14 @@ void intel_dvo_init(struct drm_device *dev) - } - - intel_encoder = &intel_dvo->base; -- -- /* Set up the DDC bus */ -- intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D"); -- if (!intel_encoder->ddc_bus) -- goto free_intel; -+ drm_encoder_init(dev, &intel_encoder->base, -+ &intel_dvo_enc_funcs, encoder_type); - - /* Now, try to find a controller */ - for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { - struct drm_connector *connector = &intel_connector->base; - const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; -+ struct i2c_adapter *i2c; - int gpio; - - /* Allow the I2C driver info to specify the GPIO to be used in -@@ -379,24 +379,18 @@ void intel_dvo_init(struct drm_device *dev) - if (dvo->gpio != 0) - gpio = dvo->gpio; - else if (dvo->type == INTEL_DVO_CHIP_LVDS) -- gpio = GPIOB; -+ gpio = GMBUS_PORT_SSC; - else -- gpio = GPIOE; -+ gpio = GMBUS_PORT_DPB; - - /* Set up the I2C bus necessary for the chip we're probing. - * It appears that everything is on GPIOE except for panels - * on i830 laptops, which are on GPIOB (DVOA). - */ -- if (i2cbus != NULL) -- intel_i2c_destroy(i2cbus); -- if (!(i2cbus = intel_i2c_create(dev, gpio, -- gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { -- continue; -- } -+ i2c = &dev_priv->gmbus[gpio].adapter; - - intel_dvo->dev = *dvo; -- ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus); -- if (!ret) -+ if (!dvo->dev_ops->init(&intel_dvo->dev, i2c)) - continue; - - intel_encoder->type = INTEL_OUTPUT_DVO; -@@ -427,13 +421,10 @@ void intel_dvo_init(struct drm_device *dev) - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - -- drm_encoder_init(dev, &intel_encoder->enc, -- &intel_dvo_enc_funcs, encoder_type); -- drm_encoder_helper_add(&intel_encoder->enc, -+ drm_encoder_helper_add(&intel_encoder->base, - &intel_dvo_helper_funcs); - -- drm_mode_connector_attach_encoder(&intel_connector->base, -- &intel_encoder->enc); -+ intel_connector_attach_encoder(intel_connector, intel_encoder); - if (dvo->type == INTEL_DVO_CHIP_LVDS) { - /* For our LVDS chipsets, we should hopefully be able - * to dig the fixed panel mode out of the BIOS data. -@@ -451,11 +442,7 @@ void intel_dvo_init(struct drm_device *dev) - return; - } - -- intel_i2c_destroy(intel_encoder->ddc_bus); -- /* Didn't find a chip, so tear down. */ -- if (i2cbus != NULL) -- intel_i2c_destroy(i2cbus); --free_intel: -+ drm_encoder_cleanup(&intel_encoder->base); - kfree(intel_dvo); - kfree(intel_connector); - } -diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c -index b61966c..af2a1dd 100644 ---- a/drivers/gpu/drm/i915/intel_fb.c -+++ b/drivers/gpu/drm/i915/intel_fb.c -@@ -44,13 +44,6 @@ - #include "i915_drm.h" - #include "i915_drv.h" - --struct intel_fbdev { -- struct drm_fb_helper helper; -- struct intel_framebuffer ifb; -- struct list_head fbdev_list; -- struct drm_display_mode *our_mode; --}; -- - static struct fb_ops intelfb_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, -@@ -75,7 +68,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, - struct drm_gem_object *fbo = NULL; - struct drm_i915_gem_object *obj_priv; - struct device *device = &dev->pdev->dev; -- int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; -+ int size, ret, mmio_bar = IS_GEN2(dev) ? 1 : 0; - - /* we don't do packed 24bpp */ - if (sizes->surface_bpp == 24) -@@ -100,19 +93,13 @@ static int intelfb_create(struct intel_fbdev *ifbdev, - - mutex_lock(&dev->struct_mutex); - -- ret = intel_pin_and_fence_fb_obj(dev, fbo); -+ /* Flush everything out, we'll be doing GTT only from now on */ -+ ret = intel_pin_and_fence_fb_obj(dev, fbo, false); - if (ret) { - DRM_ERROR("failed to pin fb: %d\n", ret); - goto out_unref; - } - -- /* Flush everything out, we'll be doing GTT only from now on */ -- ret = i915_gem_object_set_to_gtt_domain(fbo, 1); -- if (ret) { -- DRM_ERROR("failed to bind fb: %d.\n", ret); -- goto out_unpin; -- } -- - info = framebuffer_alloc(0, device); - if (!info) { - ret = -ENOMEM; -@@ -142,7 +129,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, - goto out_unpin; - } - info->apertures->ranges[0].base = dev->mode_config.fb_base; -- if (IS_I9XX(dev)) -+ if (!IS_GEN2(dev)) - info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2); - else - info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); -@@ -219,8 +206,8 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = { - .fb_probe = intel_fb_find_or_create_single, - }; - --int intel_fbdev_destroy(struct drm_device *dev, -- struct intel_fbdev *ifbdev) -+static void intel_fbdev_destroy(struct drm_device *dev, -+ struct intel_fbdev *ifbdev) - { - struct fb_info *info; - struct intel_framebuffer *ifb = &ifbdev->ifb; -@@ -238,11 +225,9 @@ int intel_fbdev_destroy(struct drm_device *dev, - - drm_framebuffer_cleanup(&ifb->base); - if (ifb->obj) { -- drm_gem_object_unreference(ifb->obj); -+ drm_gem_object_unreference_unlocked(ifb->obj); - ifb->obj = NULL; - } -- -- return 0; - } - - int intel_fbdev_init(struct drm_device *dev) -diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c -index 926934a..0d0273e 100644 ---- a/drivers/gpu/drm/i915/intel_hdmi.c -+++ b/drivers/gpu/drm/i915/intel_hdmi.c -@@ -40,12 +40,76 @@ - struct intel_hdmi { - struct intel_encoder base; - u32 sdvox_reg; -+ int ddc_bus; - bool has_hdmi_sink; -+ bool has_audio; -+ int force_audio; -+ struct drm_property *force_audio_property; - }; - - static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) - { -- return container_of(enc_to_intel_encoder(encoder), struct intel_hdmi, base); -+ return container_of(encoder, struct intel_hdmi, base.base); -+} -+ -+static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) -+{ -+ return container_of(intel_attached_encoder(connector), -+ struct intel_hdmi, base); -+} -+ -+void intel_dip_infoframe_csum(struct dip_infoframe *avi_if) -+{ -+ uint8_t *data = (uint8_t *)avi_if; -+ uint8_t sum = 0; -+ unsigned i; -+ -+ avi_if->checksum = 0; -+ avi_if->ecc = 0; -+ -+ for (i = 0; i < sizeof(*avi_if); i++) -+ sum += data[i]; -+ -+ avi_if->checksum = 0x100 - sum; -+} -+ -+static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder) -+{ -+ struct dip_infoframe avi_if = { -+ .type = DIP_TYPE_AVI, -+ .ver = DIP_VERSION_AVI, -+ .len = DIP_LEN_AVI, -+ }; -+ uint32_t *data = (uint32_t *)&avi_if; -+ struct drm_device *dev = encoder->dev; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); -+ u32 port; -+ unsigned i; -+ -+ if (!intel_hdmi->has_hdmi_sink) -+ return; -+ -+ /* XXX first guess at handling video port, is this corrent? */ -+ if (intel_hdmi->sdvox_reg == SDVOB) -+ port = VIDEO_DIP_PORT_B; -+ else if (intel_hdmi->sdvox_reg == SDVOC) -+ port = VIDEO_DIP_PORT_C; -+ else -+ return; -+ -+ I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port | -+ VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC); -+ -+ intel_dip_infoframe_csum(&avi_if); -+ for (i = 0; i < sizeof(avi_if); i += 4) { -+ I915_WRITE(VIDEO_DIP_DATA, *data); -+ data++; -+ } -+ -+ I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port | -+ VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC | -+ VIDEO_DIP_ENABLE_AVI); - } - - static void intel_hdmi_mode_set(struct drm_encoder *encoder, -@@ -65,10 +129,13 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - sdvox |= SDVO_HSYNC_ACTIVE_HIGH; - -- if (intel_hdmi->has_hdmi_sink) { -+ /* Required on CPT */ -+ if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) -+ sdvox |= HDMI_MODE_SELECT; -+ -+ if (intel_hdmi->has_audio) { - sdvox |= SDVO_AUDIO_ENABLE; -- if (HAS_PCH_CPT(dev)) -- sdvox |= HDMI_MODE_SELECT; -+ sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC; - } - - if (intel_crtc->pipe == 1) { -@@ -80,6 +147,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, - - I915_WRITE(intel_hdmi->sdvox_reg, sdvox); - POSTING_READ(intel_hdmi->sdvox_reg); -+ -+ intel_hdmi_set_avi_infoframe(encoder); - } - - static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) -@@ -141,36 +210,85 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, - static enum drm_connector_status - intel_hdmi_detect(struct drm_connector *connector, bool force) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); -- struct edid *edid = NULL; -+ struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); -+ struct drm_i915_private *dev_priv = connector->dev->dev_private; -+ struct edid *edid; - enum drm_connector_status status = connector_status_disconnected; - - intel_hdmi->has_hdmi_sink = false; -- edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus); -+ intel_hdmi->has_audio = false; -+ edid = drm_get_edid(connector, -+ &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); - - if (edid) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) { - status = connector_status_connected; - intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); -+ intel_hdmi->has_audio = drm_detect_monitor_audio(edid); - } - connector->display_info.raw_edid = NULL; - kfree(edid); - } - -+ if (status == connector_status_connected) { -+ if (intel_hdmi->force_audio) -+ intel_hdmi->has_audio = intel_hdmi->force_audio > 0; -+ } -+ - return status; - } - - static int intel_hdmi_get_modes(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); -+ struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); -+ struct drm_i915_private *dev_priv = connector->dev->dev_private; - - /* We should parse the EDID data and find out if it's an HDMI sink so - * we can send audio to it. - */ - -- return intel_ddc_get_modes(connector, intel_hdmi->base.ddc_bus); -+ return intel_ddc_get_modes(connector, -+ &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); -+} -+ -+static int -+intel_hdmi_set_property(struct drm_connector *connector, -+ struct drm_property *property, -+ uint64_t val) -+{ -+ struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); -+ int ret; -+ -+ ret = drm_connector_property_set_value(connector, property, val); -+ if (ret) -+ return ret; -+ -+ if (property == intel_hdmi->force_audio_property) { -+ if (val == intel_hdmi->force_audio) -+ return 0; -+ -+ intel_hdmi->force_audio = val; -+ -+ if (val > 0 && intel_hdmi->has_audio) -+ return 0; -+ if (val < 0 && !intel_hdmi->has_audio) -+ return 0; -+ -+ intel_hdmi->has_audio = val > 0; -+ goto done; -+ } -+ -+ return -EINVAL; -+ -+done: -+ if (intel_hdmi->base.base.crtc) { -+ struct drm_crtc *crtc = intel_hdmi->base.base.crtc; -+ drm_crtc_helper_set_mode(crtc, &crtc->mode, -+ crtc->x, crtc->y, -+ crtc->fb); -+ } -+ -+ return 0; - } - - static void intel_hdmi_destroy(struct drm_connector *connector) -@@ -192,19 +310,34 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .detect = intel_hdmi_detect, - .fill_modes = drm_helper_probe_single_connector_modes, -+ .set_property = intel_hdmi_set_property, - .destroy = intel_hdmi_destroy, - }; - - static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { - .get_modes = intel_hdmi_get_modes, - .mode_valid = intel_hdmi_mode_valid, -- .best_encoder = intel_attached_encoder, -+ .best_encoder = intel_best_encoder, - }; - - static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { - .destroy = intel_encoder_destroy, - }; - -+static void -+intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) -+{ -+ struct drm_device *dev = connector->dev; -+ -+ intel_hdmi->force_audio_property = -+ drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2); -+ if (intel_hdmi->force_audio_property) { -+ intel_hdmi->force_audio_property->values[0] = -1; -+ intel_hdmi->force_audio_property->values[1] = 1; -+ drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0); -+ } -+} -+ - void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) - { - struct drm_i915_private *dev_priv = dev->dev_private; -@@ -224,6 +357,9 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) - } - - intel_encoder = &intel_hdmi->base; -+ drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, -+ DRM_MODE_ENCODER_TMDS); -+ - connector = &intel_connector->base; - drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA); -@@ -239,39 +375,33 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) - /* Set up the DDC bus. */ - if (sdvox_reg == SDVOB) { - intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); -- intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); -+ intel_hdmi->ddc_bus = GMBUS_PORT_DPB; - dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; - } else if (sdvox_reg == SDVOC) { - intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); -- intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); -+ intel_hdmi->ddc_bus = GMBUS_PORT_DPC; - dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; - } else if (sdvox_reg == HDMIB) { - intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); -- intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, -- "HDMIB"); -+ intel_hdmi->ddc_bus = GMBUS_PORT_DPB; - dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; - } else if (sdvox_reg == HDMIC) { - intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); -- intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, -- "HDMIC"); -+ intel_hdmi->ddc_bus = GMBUS_PORT_DPC; - dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; - } else if (sdvox_reg == HDMID) { - intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); -- intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, -- "HDMID"); -+ intel_hdmi->ddc_bus = GMBUS_PORT_DPD; - dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; - } -- if (!intel_encoder->ddc_bus) -- goto err_connector; - - intel_hdmi->sdvox_reg = sdvox_reg; - -- drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs, -- DRM_MODE_ENCODER_TMDS); -- drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs); -+ drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); -+ -+ intel_hdmi_add_properties(intel_hdmi, connector); - -- drm_mode_connector_attach_encoder(&intel_connector->base, -- &intel_encoder->enc); -+ intel_connector_attach_encoder(intel_connector, intel_encoder); - drm_sysfs_connector_add(connector); - - /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written -@@ -282,13 +412,4 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) - u32 temp = I915_READ(PEG_BAND_GAP_DATA); - I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); - } -- -- return; -- --err_connector: -- drm_connector_cleanup(connector); -- kfree(intel_hdmi); -- kfree(intel_connector); -- -- return; - } -diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c -index c2649c7..2be4f72 100644 ---- a/drivers/gpu/drm/i915/intel_i2c.c -+++ b/drivers/gpu/drm/i915/intel_i2c.c -@@ -1,6 +1,6 @@ - /* - * Copyright (c) 2006 Dave Airlie -- * Copyright © 2006-2008 Intel Corporation -+ * Copyright © 2006-2008,2010 Intel Corporation - * Jesse Barnes - * - * Permission is hereby granted, free of charge, to any person obtaining a -@@ -24,10 +24,9 @@ - * - * Authors: - * Eric Anholt -+ * Chris Wilson - */ - #include --#include --#include - #include - #include "drmP.h" - #include "drm.h" -@@ -35,79 +34,106 @@ - #include "i915_drm.h" - #include "i915_drv.h" - --void intel_i2c_quirk_set(struct drm_device *dev, bool enable) -+/* Intel GPIO access functions */ -+ -+#define I2C_RISEFALL_TIME 20 -+ -+static inline struct intel_gmbus * -+to_intel_gmbus(struct i2c_adapter *i2c) -+{ -+ return container_of(i2c, struct intel_gmbus, adapter); -+} -+ -+struct intel_gpio { -+ struct i2c_adapter adapter; -+ struct i2c_algo_bit_data algo; -+ struct drm_i915_private *dev_priv; -+ u32 reg; -+}; -+ -+void -+intel_i2c_reset(struct drm_device *dev) - { - struct drm_i915_private *dev_priv = dev->dev_private; -+ if (HAS_PCH_SPLIT(dev)) -+ I915_WRITE(PCH_GMBUS0, 0); -+ else -+ I915_WRITE(GMBUS0, 0); -+} -+ -+static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) -+{ -+ u32 val; - - /* When using bit bashing for I2C, this bit needs to be set to 1 */ -- if (!IS_PINEVIEW(dev)) -+ if (!IS_PINEVIEW(dev_priv->dev)) - return; -+ -+ val = I915_READ(DSPCLK_GATE_D); - if (enable) -- I915_WRITE(DSPCLK_GATE_D, -- I915_READ(DSPCLK_GATE_D) | DPCUNIT_CLOCK_GATE_DISABLE); -+ val |= DPCUNIT_CLOCK_GATE_DISABLE; - else -- I915_WRITE(DSPCLK_GATE_D, -- I915_READ(DSPCLK_GATE_D) & (~DPCUNIT_CLOCK_GATE_DISABLE)); -+ val &= ~DPCUNIT_CLOCK_GATE_DISABLE; -+ I915_WRITE(DSPCLK_GATE_D, val); - } - --/* -- * Intel GPIO access functions -- */ -+static u32 get_reserved(struct intel_gpio *gpio) -+{ -+ struct drm_i915_private *dev_priv = gpio->dev_priv; -+ struct drm_device *dev = dev_priv->dev; -+ u32 reserved = 0; - --#define I2C_RISEFALL_TIME 20 -+ /* On most chips, these bits must be preserved in software. */ -+ if (!IS_I830(dev) && !IS_845G(dev)) -+ reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE | -+ GPIO_CLOCK_PULLUP_DISABLE); -+ -+ return reserved; -+} - - static int get_clock(void *data) - { -- struct intel_i2c_chan *chan = data; -- struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; -- u32 val; -- -- val = I915_READ(chan->reg); -- return ((val & GPIO_CLOCK_VAL_IN) != 0); -+ struct intel_gpio *gpio = data; -+ struct drm_i915_private *dev_priv = gpio->dev_priv; -+ u32 reserved = get_reserved(gpio); -+ I915_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); -+ I915_WRITE(gpio->reg, reserved); -+ return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; - } - - static int get_data(void *data) - { -- struct intel_i2c_chan *chan = data; -- struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; -- u32 val; -- -- val = I915_READ(chan->reg); -- return ((val & GPIO_DATA_VAL_IN) != 0); -+ struct intel_gpio *gpio = data; -+ struct drm_i915_private *dev_priv = gpio->dev_priv; -+ u32 reserved = get_reserved(gpio); -+ I915_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); -+ I915_WRITE(gpio->reg, reserved); -+ return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0; - } - - static void set_clock(void *data, int state_high) - { -- struct intel_i2c_chan *chan = data; -- struct drm_device *dev = chan->drm_dev; -- struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; -- u32 reserved = 0, clock_bits; -- -- /* On most chips, these bits must be preserved in software. */ -- if (!IS_I830(dev) && !IS_845G(dev)) -- reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | -- GPIO_CLOCK_PULLUP_DISABLE); -+ struct intel_gpio *gpio = data; -+ struct drm_i915_private *dev_priv = gpio->dev_priv; -+ u32 reserved = get_reserved(gpio); -+ u32 clock_bits; - - if (state_high) - clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; - else - clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | - GPIO_CLOCK_VAL_MASK; -- I915_WRITE(chan->reg, reserved | clock_bits); -- udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ -+ -+ I915_WRITE(gpio->reg, reserved | clock_bits); -+ POSTING_READ(gpio->reg); - } - - static void set_data(void *data, int state_high) - { -- struct intel_i2c_chan *chan = data; -- struct drm_device *dev = chan->drm_dev; -- struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; -- u32 reserved = 0, data_bits; -- -- /* On most chips, these bits must be preserved in software. */ -- if (!IS_I830(dev) && !IS_845G(dev)) -- reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | -- GPIO_CLOCK_PULLUP_DISABLE); -+ struct intel_gpio *gpio = data; -+ struct drm_i915_private *dev_priv = gpio->dev_priv; -+ u32 reserved = get_reserved(gpio); -+ u32 data_bits; - - if (state_high) - data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; -@@ -115,109 +141,313 @@ static void set_data(void *data, int state_high) - data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | - GPIO_DATA_VAL_MASK; - -- I915_WRITE(chan->reg, reserved | data_bits); -- udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ -+ I915_WRITE(gpio->reg, reserved | data_bits); -+ POSTING_READ(gpio->reg); - } - --/* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C -- * engine, but if the BIOS leaves it enabled, then that can break our use -- * of the bit-banging I2C interfaces. This is notably the case with the -- * Mac Mini in EFI mode. -- */ --void --intel_i2c_reset_gmbus(struct drm_device *dev) -+static struct i2c_adapter * -+intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin) - { -- struct drm_i915_private *dev_priv = dev->dev_private; -+ static const int map_pin_to_reg[] = { -+ 0, -+ GPIOB, -+ GPIOA, -+ GPIOC, -+ GPIOD, -+ GPIOE, -+ 0, -+ GPIOF, -+ }; -+ struct intel_gpio *gpio; - -- if (HAS_PCH_SPLIT(dev)) { -- I915_WRITE(PCH_GMBUS0, 0); -- } else { -- I915_WRITE(GMBUS0, 0); -+ if (pin < 1 || pin > 7) -+ return NULL; -+ -+ gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); -+ if (gpio == NULL) -+ return NULL; -+ -+ gpio->reg = map_pin_to_reg[pin]; -+ if (HAS_PCH_SPLIT(dev_priv->dev)) -+ gpio->reg += PCH_GPIOA - GPIOA; -+ gpio->dev_priv = dev_priv; -+ -+ snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO%c", "?BACDEF?"[pin]); -+ gpio->adapter.owner = THIS_MODULE; -+ gpio->adapter.algo_data = &gpio->algo; -+ gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; -+ gpio->algo.setsda = set_data; -+ gpio->algo.setscl = set_clock; -+ gpio->algo.getsda = get_data; -+ gpio->algo.getscl = get_clock; -+ gpio->algo.udelay = I2C_RISEFALL_TIME; -+ gpio->algo.timeout = usecs_to_jiffies(2200); -+ gpio->algo.data = gpio; -+ -+ if (i2c_bit_add_bus(&gpio->adapter)) -+ goto out_free; -+ -+ return &gpio->adapter; -+ -+out_free: -+ kfree(gpio); -+ return NULL; -+} -+ -+static int -+intel_i2c_quirk_xfer(struct drm_i915_private *dev_priv, -+ struct i2c_adapter *adapter, -+ struct i2c_msg *msgs, -+ int num) -+{ -+ struct intel_gpio *gpio = container_of(adapter, -+ struct intel_gpio, -+ adapter); -+ int ret; -+ -+ intel_i2c_reset(dev_priv->dev); -+ -+ intel_i2c_quirk_set(dev_priv, true); -+ set_data(gpio, 1); -+ set_clock(gpio, 1); -+ udelay(I2C_RISEFALL_TIME); -+ -+ ret = adapter->algo->master_xfer(adapter, msgs, num); -+ -+ set_data(gpio, 1); -+ set_clock(gpio, 1); -+ intel_i2c_quirk_set(dev_priv, false); -+ -+ return ret; -+} -+ -+static int -+gmbus_xfer(struct i2c_adapter *adapter, -+ struct i2c_msg *msgs, -+ int num) -+{ -+ struct intel_gmbus *bus = container_of(adapter, -+ struct intel_gmbus, -+ adapter); -+ struct drm_i915_private *dev_priv = adapter->algo_data; -+ int i, reg_offset; -+ -+ if (bus->force_bit) -+ return intel_i2c_quirk_xfer(dev_priv, -+ bus->force_bit, msgs, num); -+ -+ reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0; -+ -+ I915_WRITE(GMBUS0 + reg_offset, bus->reg0); -+ -+ for (i = 0; i < num; i++) { -+ u16 len = msgs[i].len; -+ u8 *buf = msgs[i].buf; -+ -+ if (msgs[i].flags & I2C_M_RD) { -+ I915_WRITE(GMBUS1 + reg_offset, -+ GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | -+ (len << GMBUS_BYTE_COUNT_SHIFT) | -+ (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | -+ GMBUS_SLAVE_READ | GMBUS_SW_RDY); -+ POSTING_READ(GMBUS2+reg_offset); -+ do { -+ u32 val, loop = 0; -+ -+ if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) -+ goto timeout; -+ if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) -+ return 0; -+ -+ val = I915_READ(GMBUS3 + reg_offset); -+ do { -+ *buf++ = val & 0xff; -+ val >>= 8; -+ } while (--len && ++loop < 4); -+ } while (len); -+ } else { -+ u32 val, loop; -+ -+ val = loop = 0; -+ do { -+ val |= *buf++ << (8 * loop); -+ } while (--len && ++loop < 4); -+ -+ I915_WRITE(GMBUS3 + reg_offset, val); -+ I915_WRITE(GMBUS1 + reg_offset, -+ (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | -+ (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | -+ (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | -+ GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); -+ POSTING_READ(GMBUS2+reg_offset); -+ -+ while (len) { -+ if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) -+ goto timeout; -+ if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) -+ return 0; -+ -+ val = loop = 0; -+ do { -+ val |= *buf++ << (8 * loop); -+ } while (--len && ++loop < 4); -+ -+ I915_WRITE(GMBUS3 + reg_offset, val); -+ POSTING_READ(GMBUS2+reg_offset); -+ } -+ } -+ -+ if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) -+ goto timeout; -+ if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) -+ return 0; - } -+ -+ return num; -+ -+timeout: -+ DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", -+ bus->reg0 & 0xff, bus->adapter.name); -+ /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ -+ bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); -+ if (!bus->force_bit) -+ return -ENOMEM; -+ -+ return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); - } - -+static u32 gmbus_func(struct i2c_adapter *adapter) -+{ -+ struct intel_gmbus *bus = container_of(adapter, -+ struct intel_gmbus, -+ adapter); -+ -+ if (bus->force_bit) -+ bus->force_bit->algo->functionality(bus->force_bit); -+ -+ return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | -+ /* I2C_FUNC_10BIT_ADDR | */ -+ I2C_FUNC_SMBUS_READ_BLOCK_DATA | -+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL); -+} -+ -+static const struct i2c_algorithm gmbus_algorithm = { -+ .master_xfer = gmbus_xfer, -+ .functionality = gmbus_func -+}; -+ - /** -- * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg -+ * intel_gmbus_setup - instantiate all Intel i2c GMBuses - * @dev: DRM device -- * @output: driver specific output device -- * @reg: GPIO reg to use -- * @name: name for this bus -- * @slave_addr: slave address (if fixed) -- * -- * Creates and registers a new i2c bus with the Linux i2c layer, for use -- * in output probing and control (e.g. DDC or SDVO control functions). -- * -- * Possible values for @reg include: -- * %GPIOA -- * %GPIOB -- * %GPIOC -- * %GPIOD -- * %GPIOE -- * %GPIOF -- * %GPIOG -- * %GPIOH -- * see PRM for details on how these different busses are used. - */ --struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, -- const char *name) -+int intel_setup_gmbus(struct drm_device *dev) - { -- struct intel_i2c_chan *chan; -+ static const char *names[GMBUS_NUM_PORTS] = { -+ "disabled", -+ "ssc", -+ "vga", -+ "panel", -+ "dpc", -+ "dpb", -+ "reserved" -+ "dpd", -+ }; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ int ret, i; - -- chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL); -- if (!chan) -- goto out_free; -+ dev_priv->gmbus = kcalloc(sizeof(struct intel_gmbus), GMBUS_NUM_PORTS, -+ GFP_KERNEL); -+ if (dev_priv->gmbus == NULL) -+ return -ENOMEM; - -- chan->drm_dev = dev; -- chan->reg = reg; -- snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); -- chan->adapter.owner = THIS_MODULE; -- chan->adapter.algo_data = &chan->algo; -- chan->adapter.dev.parent = &dev->pdev->dev; -- chan->algo.setsda = set_data; -- chan->algo.setscl = set_clock; -- chan->algo.getsda = get_data; -- chan->algo.getscl = get_clock; -- chan->algo.udelay = 20; -- chan->algo.timeout = usecs_to_jiffies(2200); -- chan->algo.data = chan; -- -- i2c_set_adapdata(&chan->adapter, chan); -- -- if(i2c_bit_add_bus(&chan->adapter)) -- goto out_free; -+ for (i = 0; i < GMBUS_NUM_PORTS; i++) { -+ struct intel_gmbus *bus = &dev_priv->gmbus[i]; - -- intel_i2c_reset_gmbus(dev); -+ bus->adapter.owner = THIS_MODULE; -+ bus->adapter.class = I2C_CLASS_DDC; -+ snprintf(bus->adapter.name, -+ I2C_NAME_SIZE, -+ "gmbus %s", -+ names[i]); - -- /* JJJ: raise SCL and SDA? */ -- intel_i2c_quirk_set(dev, true); -- set_data(chan, 1); -- set_clock(chan, 1); -- intel_i2c_quirk_set(dev, false); -- udelay(20); -+ bus->adapter.dev.parent = &dev->pdev->dev; -+ bus->adapter.algo_data = dev_priv; - -- return &chan->adapter; -+ bus->adapter.algo = &gmbus_algorithm; -+ ret = i2c_add_adapter(&bus->adapter); -+ if (ret) -+ goto err; - --out_free: -- kfree(chan); -- return NULL; -+ /* By default use a conservative clock rate */ -+ bus->reg0 = i | GMBUS_RATE_100KHZ; -+ -+ /* XXX force bit banging until GMBUS is fully debugged */ -+ bus->force_bit = intel_gpio_create(dev_priv, i); -+ } -+ -+ intel_i2c_reset(dev_priv->dev); -+ -+ return 0; -+ -+err: -+ while (--i) { -+ struct intel_gmbus *bus = &dev_priv->gmbus[i]; -+ i2c_del_adapter(&bus->adapter); -+ } -+ kfree(dev_priv->gmbus); -+ dev_priv->gmbus = NULL; -+ return ret; - } - --/** -- * intel_i2c_destroy - unregister and free i2c bus resources -- * @output: channel to free -- * -- * Unregister the adapter from the i2c layer, then free the structure. -- */ --void intel_i2c_destroy(struct i2c_adapter *adapter) -+void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) -+{ -+ struct intel_gmbus *bus = to_intel_gmbus(adapter); -+ -+ /* speed: -+ * 0x0 = 100 KHz -+ * 0x1 = 50 KHz -+ * 0x2 = 400 KHz -+ * 0x3 = 1000 Khz -+ */ -+ bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8); -+} -+ -+void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) -+{ -+ struct intel_gmbus *bus = to_intel_gmbus(adapter); -+ -+ if (force_bit) { -+ if (bus->force_bit == NULL) { -+ struct drm_i915_private *dev_priv = adapter->algo_data; -+ bus->force_bit = intel_gpio_create(dev_priv, -+ bus->reg0 & 0xff); -+ } -+ } else { -+ if (bus->force_bit) { -+ i2c_del_adapter(bus->force_bit); -+ kfree(bus->force_bit); -+ bus->force_bit = NULL; -+ } -+ } -+} -+ -+void intel_teardown_gmbus(struct drm_device *dev) - { -- struct intel_i2c_chan *chan; -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ int i; - -- if (!adapter) -+ if (dev_priv->gmbus == NULL) - return; - -- chan = container_of(adapter, -- struct intel_i2c_chan, -- adapter); -- i2c_del_adapter(&chan->adapter); -- kfree(chan); -+ for (i = 0; i < GMBUS_NUM_PORTS; i++) { -+ struct intel_gmbus *bus = &dev_priv->gmbus[i]; -+ if (bus->force_bit) { -+ i2c_del_adapter(bus->force_bit); -+ kfree(bus->force_bit); -+ } -+ i2c_del_adapter(&bus->adapter); -+ } -+ -+ kfree(dev_priv->gmbus); -+ dev_priv->gmbus = NULL; - } -diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c -index 6ec39a8..4324a32 100644 ---- a/drivers/gpu/drm/i915/intel_lvds.c -+++ b/drivers/gpu/drm/i915/intel_lvds.c -@@ -43,102 +43,76 @@ - /* Private structure for the integrated LVDS support */ - struct intel_lvds { - struct intel_encoder base; -+ -+ struct edid *edid; -+ - int fitting_mode; - u32 pfit_control; - u32 pfit_pgm_ratios; -+ bool pfit_dirty; -+ -+ struct drm_display_mode *fixed_mode; - }; - --static struct intel_lvds *enc_to_intel_lvds(struct drm_encoder *encoder) -+static struct intel_lvds *to_intel_lvds(struct drm_encoder *encoder) - { -- return container_of(enc_to_intel_encoder(encoder), struct intel_lvds, base); -+ return container_of(encoder, struct intel_lvds, base.base); - } - --/** -- * Sets the backlight level. -- * -- * \param level backlight level, from 0 to intel_lvds_get_max_backlight(). -- */ --static void intel_lvds_set_backlight(struct drm_device *dev, int level) -+static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) - { -- struct drm_i915_private *dev_priv = dev->dev_private; -- u32 blc_pwm_ctl, reg; -- -- if (HAS_PCH_SPLIT(dev)) -- reg = BLC_PWM_CPU_CTL; -- else -- reg = BLC_PWM_CTL; -- -- blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK; -- I915_WRITE(reg, (blc_pwm_ctl | -- (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); --} -- --/** -- * Returns the maximum level of the backlight duty cycle field. -- */ --static u32 intel_lvds_get_max_backlight(struct drm_device *dev) --{ -- struct drm_i915_private *dev_priv = dev->dev_private; -- u32 reg; -- -- if (HAS_PCH_SPLIT(dev)) -- reg = BLC_PWM_PCH_CTL2; -- else -- reg = BLC_PWM_CTL; -- -- return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >> -- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; -+ return container_of(intel_attached_encoder(connector), -+ struct intel_lvds, base); - } - - /** - * Sets the power state for the panel. - */ --static void intel_lvds_set_power(struct drm_device *dev, bool on) -+static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on) - { -+ struct drm_device *dev = intel_lvds->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- u32 ctl_reg, status_reg, lvds_reg; -+ u32 ctl_reg, lvds_reg; - - if (HAS_PCH_SPLIT(dev)) { - ctl_reg = PCH_PP_CONTROL; -- status_reg = PCH_PP_STATUS; - lvds_reg = PCH_LVDS; - } else { - ctl_reg = PP_CONTROL; -- status_reg = PP_STATUS; - lvds_reg = LVDS; - } - - if (on) { - I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); -- POSTING_READ(lvds_reg); -- -- I915_WRITE(ctl_reg, I915_READ(ctl_reg) | -- POWER_TARGET_ON); -- if (wait_for(I915_READ(status_reg) & PP_ON, 1000, 0)) -- DRM_ERROR("timed out waiting to enable LVDS pipe"); -- -- intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); -+ I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON); -+ intel_panel_set_backlight(dev, dev_priv->backlight_level); - } else { -- intel_lvds_set_backlight(dev, 0); -+ dev_priv->backlight_level = intel_panel_get_backlight(dev); - -- I915_WRITE(ctl_reg, I915_READ(ctl_reg) & -- ~POWER_TARGET_ON); -- if (wait_for((I915_READ(status_reg) & PP_ON) == 0, 1000, 0)) -- DRM_ERROR("timed out waiting for LVDS pipe to turn off"); -+ intel_panel_set_backlight(dev, 0); -+ I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); -+ -+ if (intel_lvds->pfit_control) { -+ if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) -+ DRM_ERROR("timed out waiting for panel to power off\n"); -+ I915_WRITE(PFIT_CONTROL, 0); -+ intel_lvds->pfit_control = 0; -+ intel_lvds->pfit_dirty = false; -+ } - - I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); -- POSTING_READ(lvds_reg); - } -+ POSTING_READ(lvds_reg); - } - - static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) - { -- struct drm_device *dev = encoder->dev; -+ struct intel_lvds *intel_lvds = to_intel_lvds(encoder); - - if (mode == DRM_MODE_DPMS_ON) -- intel_lvds_set_power(dev, true); -+ intel_lvds_set_power(intel_lvds, true); - else -- intel_lvds_set_power(dev, false); -+ intel_lvds_set_power(intel_lvds, false); - - /* XXX: We never power down the LVDS pairs. */ - } -@@ -146,16 +120,13 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) - static int intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { -- struct drm_device *dev = connector->dev; -- struct drm_i915_private *dev_priv = dev->dev_private; -- struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode; -+ struct intel_lvds *intel_lvds = intel_attached_lvds(connector); -+ struct drm_display_mode *fixed_mode = intel_lvds->fixed_mode; - -- if (fixed_mode) { -- if (mode->hdisplay > fixed_mode->hdisplay) -- return MODE_PANEL; -- if (mode->vdisplay > fixed_mode->vdisplay) -- return MODE_PANEL; -- } -+ if (mode->hdisplay > fixed_mode->hdisplay) -+ return MODE_PANEL; -+ if (mode->vdisplay > fixed_mode->vdisplay) -+ return MODE_PANEL; - - return MODE_OK; - } -@@ -223,12 +194,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); -- struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); -+ struct intel_lvds *intel_lvds = to_intel_lvds(encoder); - struct drm_encoder *tmp_encoder; - u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; - - /* Should never happen!! */ -- if (!IS_I965G(dev) && intel_crtc->pipe == 0) { -+ if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { - DRM_ERROR("Can't support LVDS on pipe A\n"); - return false; - } -@@ -241,9 +212,6 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - return false; - } - } -- /* If we don't have a panel mode, there is nothing we can do */ -- if (dev_priv->panel_fixed_mode == NULL) -- return true; - - /* - * We have timings from the BIOS for the panel, put them in -@@ -251,7 +219,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - * with the panel scaling set up to source from the H/VDisplay - * of the original mode. - */ -- intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode); -+ intel_fixed_panel_mode(intel_lvds->fixed_mode, adjusted_mode); - - if (HAS_PCH_SPLIT(dev)) { - intel_pch_panel_fitting(dev, intel_lvds->fitting_mode, -@@ -260,8 +228,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - } - - /* Make sure pre-965s set dither correctly */ -- if (!IS_I965G(dev)) { -- if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) -+ if (INTEL_INFO(dev)->gen < 4) { -+ if (dev_priv->lvds_dither) - pfit_control |= PANEL_8TO6_DITHER_ENABLE; - } - -@@ -271,7 +239,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - goto out; - - /* 965+ wants fuzzy fitting */ -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | - PFIT_FILTER_FUZZY); - -@@ -297,7 +265,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - - case DRM_MODE_SCALE_ASPECT: - /* Scale but preserve the aspect ratio */ -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; - u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; - -@@ -356,7 +324,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - * Fortunately this is all done for us in hw. - */ - pfit_control |= PFIT_ENABLE; -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - pfit_control |= PFIT_SCALING_AUTO; - else - pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | -@@ -369,8 +337,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - } - - out: -- intel_lvds->pfit_control = pfit_control; -- intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios; -+ if (pfit_control != intel_lvds->pfit_control || -+ pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) { -+ intel_lvds->pfit_control = pfit_control; -+ intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios; -+ intel_lvds->pfit_dirty = true; -+ } - dev_priv->lvds_border_bits = border; - - /* -@@ -386,30 +358,60 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) - { - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- u32 reg; -- -- if (HAS_PCH_SPLIT(dev)) -- reg = BLC_PWM_CPU_CTL; -- else -- reg = BLC_PWM_CTL; -- -- dev_priv->saveBLC_PWM_CTL = I915_READ(reg); -- dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & -- BACKLIGHT_DUTY_CYCLE_MASK); -+ struct intel_lvds *intel_lvds = to_intel_lvds(encoder); -+ -+ dev_priv->backlight_level = intel_panel_get_backlight(dev); -+ -+ /* We try to do the minimum that is necessary in order to unlock -+ * the registers for mode setting. -+ * -+ * On Ironlake, this is quite simple as we just set the unlock key -+ * and ignore all subtleties. (This may cause some issues...) -+ * -+ * Prior to Ironlake, we must disable the pipe if we want to adjust -+ * the panel fitter. However at all other times we can just reset -+ * the registers regardless. -+ */ - -- intel_lvds_set_power(dev, false); -+ if (HAS_PCH_SPLIT(dev)) { -+ I915_WRITE(PCH_PP_CONTROL, -+ I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); -+ } else if (intel_lvds->pfit_dirty) { -+ I915_WRITE(PP_CONTROL, -+ (I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS) -+ & ~POWER_TARGET_ON); -+ } else { -+ I915_WRITE(PP_CONTROL, -+ I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); -+ } - } - --static void intel_lvds_commit( struct drm_encoder *encoder) -+static void intel_lvds_commit(struct drm_encoder *encoder) - { - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_lvds *intel_lvds = to_intel_lvds(encoder); - -- if (dev_priv->backlight_duty_cycle == 0) -- dev_priv->backlight_duty_cycle = -- intel_lvds_get_max_backlight(dev); -+ if (dev_priv->backlight_level == 0) -+ dev_priv->backlight_level = intel_panel_get_max_backlight(dev); - -- intel_lvds_set_power(dev, true); -+ /* Undo any unlocking done in prepare to prevent accidental -+ * adjustment of the registers. -+ */ -+ if (HAS_PCH_SPLIT(dev)) { -+ u32 val = I915_READ(PCH_PP_CONTROL); -+ if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS) -+ I915_WRITE(PCH_PP_CONTROL, val & 0x3); -+ } else { -+ u32 val = I915_READ(PP_CONTROL); -+ if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS) -+ I915_WRITE(PP_CONTROL, val & 0x3); -+ } -+ -+ /* Always do a full power on as we do not know what state -+ * we were left in. -+ */ -+ intel_lvds_set_power(intel_lvds, true); - } - - static void intel_lvds_mode_set(struct drm_encoder *encoder, -@@ -418,7 +420,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, - { - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); -+ struct intel_lvds *intel_lvds = to_intel_lvds(encoder); - - /* - * The LVDS pin pair will already have been turned on in the -@@ -429,13 +431,23 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, - if (HAS_PCH_SPLIT(dev)) - return; - -+ if (!intel_lvds->pfit_dirty) -+ return; -+ - /* - * Enable automatic panel scaling so that non-native modes fill the - * screen. Should be enabled before the pipe is enabled, according to - * register description and PRM. - */ -+ DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n", -+ intel_lvds->pfit_control, -+ intel_lvds->pfit_pgm_ratios); -+ if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) -+ DRM_ERROR("timed out waiting for panel to power off\n"); -+ - I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios); - I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control); -+ intel_lvds->pfit_dirty = false; - } - - /** -@@ -465,38 +477,19 @@ intel_lvds_detect(struct drm_connector *connector, bool force) - */ - static int intel_lvds_get_modes(struct drm_connector *connector) - { -+ struct intel_lvds *intel_lvds = intel_attached_lvds(connector); - struct drm_device *dev = connector->dev; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); -- struct drm_i915_private *dev_priv = dev->dev_private; -- int ret = 0; -- -- if (dev_priv->lvds_edid_good) { -- ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); -- -- if (ret) -- return ret; -- } -+ struct drm_display_mode *mode; - -- /* Didn't get an EDID, so -- * Set wide sync ranges so we get all modes -- * handed to valid_mode for checking -- */ -- connector->display_info.min_vfreq = 0; -- connector->display_info.max_vfreq = 200; -- connector->display_info.min_hfreq = 0; -- connector->display_info.max_hfreq = 200; -- -- if (dev_priv->panel_fixed_mode != NULL) { -- struct drm_display_mode *mode; -- -- mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); -- drm_mode_probed_add(connector, mode); -+ if (intel_lvds->edid) -+ return drm_add_edid_modes(connector, intel_lvds->edid); - -- return 1; -- } -+ mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode); -+ if (mode == 0) -+ return 0; - -- return 0; -+ drm_mode_probed_add(connector, mode); -+ return 1; - } - - static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id) -@@ -587,18 +580,17 @@ static int intel_lvds_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t value) - { -+ struct intel_lvds *intel_lvds = intel_attached_lvds(connector); - struct drm_device *dev = connector->dev; - -- if (property == dev->mode_config.scaling_mode_property && -- connector->encoder) { -- struct drm_crtc *crtc = connector->encoder->crtc; -- struct drm_encoder *encoder = connector->encoder; -- struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); -+ if (property == dev->mode_config.scaling_mode_property) { -+ struct drm_crtc *crtc = intel_lvds->base.base.crtc; - - if (value == DRM_MODE_SCALE_NONE) { - DRM_DEBUG_KMS("no scaling not supported\n"); -- return 0; -+ return -EINVAL; - } -+ - if (intel_lvds->fitting_mode == value) { - /* the LVDS scaling property is not changed */ - return 0; -@@ -628,7 +620,7 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = { - static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { - .get_modes = intel_lvds_get_modes, - .mode_valid = intel_lvds_mode_valid, -- .best_encoder = intel_attached_encoder, -+ .best_encoder = intel_best_encoder, - }; - - static const struct drm_connector_funcs intel_lvds_connector_funcs = { -@@ -726,16 +718,14 @@ static const struct dmi_system_id intel_no_lvds[] = { - * Find the reduced downclock for LVDS in EDID. - */ - static void intel_find_lvds_downclock(struct drm_device *dev, -- struct drm_connector *connector) -+ struct drm_display_mode *fixed_mode, -+ struct drm_connector *connector) - { - struct drm_i915_private *dev_priv = dev->dev_private; -- struct drm_display_mode *scan, *panel_fixed_mode; -+ struct drm_display_mode *scan; - int temp_downclock; - -- panel_fixed_mode = dev_priv->panel_fixed_mode; -- temp_downclock = panel_fixed_mode->clock; -- -- mutex_lock(&dev->mode_config.mutex); -+ temp_downclock = fixed_mode->clock; - list_for_each_entry(scan, &connector->probed_modes, head) { - /* - * If one mode has the same resolution with the fixed_panel -@@ -744,14 +734,14 @@ static void intel_find_lvds_downclock(struct drm_device *dev, - * case we can set the different FPx0/1 to dynamically select - * between low and high frequency. - */ -- if (scan->hdisplay == panel_fixed_mode->hdisplay && -- scan->hsync_start == panel_fixed_mode->hsync_start && -- scan->hsync_end == panel_fixed_mode->hsync_end && -- scan->htotal == panel_fixed_mode->htotal && -- scan->vdisplay == panel_fixed_mode->vdisplay && -- scan->vsync_start == panel_fixed_mode->vsync_start && -- scan->vsync_end == panel_fixed_mode->vsync_end && -- scan->vtotal == panel_fixed_mode->vtotal) { -+ if (scan->hdisplay == fixed_mode->hdisplay && -+ scan->hsync_start == fixed_mode->hsync_start && -+ scan->hsync_end == fixed_mode->hsync_end && -+ scan->htotal == fixed_mode->htotal && -+ scan->vdisplay == fixed_mode->vdisplay && -+ scan->vsync_start == fixed_mode->vsync_start && -+ scan->vsync_end == fixed_mode->vsync_end && -+ scan->vtotal == fixed_mode->vtotal) { - if (scan->clock < temp_downclock) { - /* - * The downclock is already found. But we -@@ -761,17 +751,14 @@ static void intel_find_lvds_downclock(struct drm_device *dev, - } - } - } -- mutex_unlock(&dev->mode_config.mutex); -- if (temp_downclock < panel_fixed_mode->clock && -- i915_lvds_downclock) { -+ if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) { - /* We found the downclock for LVDS. */ - dev_priv->lvds_downclock_avail = 1; - dev_priv->lvds_downclock = temp_downclock; - DRM_DEBUG_KMS("LVDS downclock is found in EDID. " -- "Normal clock %dKhz, downclock %dKhz\n", -- panel_fixed_mode->clock, temp_downclock); -+ "Normal clock %dKhz, downclock %dKhz\n", -+ fixed_mode->clock, temp_downclock); - } -- return; - } - - /* -@@ -780,38 +767,67 @@ static void intel_find_lvds_downclock(struct drm_device *dev, - * If it is present, return 1. - * If it is not present, return false. - * If no child dev is parsed from VBT, it assumes that the LVDS is present. -- * Note: The addin_offset should also be checked for LVDS panel. -- * Only when it is non-zero, it is assumed that it is present. - */ --static int lvds_is_present_in_vbt(struct drm_device *dev) -+static bool lvds_is_present_in_vbt(struct drm_device *dev, -+ u8 *i2c_pin) - { - struct drm_i915_private *dev_priv = dev->dev_private; -- struct child_device_config *p_child; -- int i, ret; -+ int i; - - if (!dev_priv->child_dev_num) -- return 1; -+ return true; - -- ret = 0; - for (i = 0; i < dev_priv->child_dev_num; i++) { -- p_child = dev_priv->child_dev + i; -- /* -- * If the device type is not LFP, continue. -- * If the device type is 0x22, it is also regarded as LFP. -+ struct child_device_config *child = dev_priv->child_dev + i; -+ -+ /* If the device type is not LFP, continue. -+ * We have to check both the new identifiers as well as the -+ * old for compatibility with some BIOSes. - */ -- if (p_child->device_type != DEVICE_TYPE_INT_LFP && -- p_child->device_type != DEVICE_TYPE_LFP) -+ if (child->device_type != DEVICE_TYPE_INT_LFP && -+ child->device_type != DEVICE_TYPE_LFP) - continue; - -- /* The addin_offset should be checked. Only when it is -- * non-zero, it is regarded as present. -+ if (child->i2c_pin) -+ *i2c_pin = child->i2c_pin; -+ -+ /* However, we cannot trust the BIOS writers to populate -+ * the VBT correctly. Since LVDS requires additional -+ * information from AIM blocks, a non-zero addin offset is -+ * a good indicator that the LVDS is actually present. - */ -- if (p_child->addin_offset) { -- ret = 1; -- break; -- } -+ if (child->addin_offset) -+ return true; -+ -+ /* But even then some BIOS writers perform some black magic -+ * and instantiate the device without reference to any -+ * additional data. Trust that if the VBT was written into -+ * the OpRegion then they have validated the LVDS's existence. -+ */ -+ if (dev_priv->opregion.vbt) -+ return true; - } -- return ret; -+ -+ return false; -+} -+ -+static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u8 buf = 0; -+ struct i2c_msg msgs[] = { -+ { -+ .addr = 0xA0, -+ .flags = 0, -+ .len = 1, -+ .buf = &buf, -+ }, -+ }; -+ struct i2c_adapter *i2c = &dev_priv->gmbus[pin].adapter; -+ /* XXX this only appears to work when using GMBUS */ -+ if (intel_gmbus_is_forced_bit(i2c)) -+ return true; -+ return i2c_transfer(i2c, msgs, 1) == 1; - } - - /** -@@ -832,13 +848,15 @@ void intel_lvds_init(struct drm_device *dev) - struct drm_display_mode *scan; /* *modes, *bios_mode; */ - struct drm_crtc *crtc; - u32 lvds; -- int pipe, gpio = GPIOC; -+ int pipe; -+ u8 pin; - - /* Skip init on machines we know falsely report LVDS */ - if (dmi_check_system(intel_no_lvds)) - return; - -- if (!lvds_is_present_in_vbt(dev)) { -+ pin = GMBUS_PORT_PANEL; -+ if (!lvds_is_present_in_vbt(dev, &pin)) { - DRM_DEBUG_KMS("LVDS is not present in VBT\n"); - return; - } -@@ -846,11 +864,15 @@ void intel_lvds_init(struct drm_device *dev) - if (HAS_PCH_SPLIT(dev)) { - if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) - return; -- if (dev_priv->edp_support) { -+ if (dev_priv->edp.support) { - DRM_DEBUG_KMS("disable LVDS for eDP support\n"); - return; - } -- gpio = PCH_GPIOC; -+ } -+ -+ if (!intel_lvds_ddc_probe(dev, pin)) { -+ DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n"); -+ return; - } - - intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); -@@ -864,16 +886,20 @@ void intel_lvds_init(struct drm_device *dev) - return; - } - -+ if (!HAS_PCH_SPLIT(dev)) { -+ intel_lvds->pfit_control = I915_READ(PFIT_CONTROL); -+ } -+ - intel_encoder = &intel_lvds->base; -- encoder = &intel_encoder->enc; -+ encoder = &intel_encoder->base; - connector = &intel_connector->base; - drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - -- drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs, -+ drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs, - DRM_MODE_ENCODER_LVDS); - -- drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc); -+ intel_connector_attach_encoder(intel_connector, intel_encoder); - intel_encoder->type = INTEL_OUTPUT_LVDS; - - intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); -@@ -904,43 +930,50 @@ void intel_lvds_init(struct drm_device *dev) - * if closed, act like it's not there for now - */ - -- /* Set up the DDC bus. */ -- intel_encoder->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C"); -- if (!intel_encoder->ddc_bus) { -- dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " -- "failed.\n"); -- goto failed; -- } -- - /* - * Attempt to get the fixed panel mode from DDC. Assume that the - * preferred mode is the right one. - */ -- dev_priv->lvds_edid_good = true; -- -- if (!intel_ddc_get_modes(connector, intel_encoder->ddc_bus)) -- dev_priv->lvds_edid_good = false; -+ intel_lvds->edid = drm_get_edid(connector, -+ &dev_priv->gmbus[pin].adapter); -+ if (intel_lvds->edid) { -+ if (drm_add_edid_modes(connector, -+ intel_lvds->edid)) { -+ drm_mode_connector_update_edid_property(connector, -+ intel_lvds->edid); -+ } else { -+ kfree(intel_lvds->edid); -+ intel_lvds->edid = NULL; -+ } -+ } -+ if (!intel_lvds->edid) { -+ /* Didn't get an EDID, so -+ * Set wide sync ranges so we get all modes -+ * handed to valid_mode for checking -+ */ -+ connector->display_info.min_vfreq = 0; -+ connector->display_info.max_vfreq = 200; -+ connector->display_info.min_hfreq = 0; -+ connector->display_info.max_hfreq = 200; -+ } - - list_for_each_entry(scan, &connector->probed_modes, head) { -- mutex_lock(&dev->mode_config.mutex); - if (scan->type & DRM_MODE_TYPE_PREFERRED) { -- dev_priv->panel_fixed_mode = -+ intel_lvds->fixed_mode = - drm_mode_duplicate(dev, scan); -- mutex_unlock(&dev->mode_config.mutex); -- intel_find_lvds_downclock(dev, connector); -+ intel_find_lvds_downclock(dev, -+ intel_lvds->fixed_mode, -+ connector); - goto out; - } -- mutex_unlock(&dev->mode_config.mutex); - } - - /* Failed to get EDID, what about VBT? */ - if (dev_priv->lfp_lvds_vbt_mode) { -- mutex_lock(&dev->mode_config.mutex); -- dev_priv->panel_fixed_mode = -+ intel_lvds->fixed_mode = - drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); -- mutex_unlock(&dev->mode_config.mutex); -- if (dev_priv->panel_fixed_mode) { -- dev_priv->panel_fixed_mode->type |= -+ if (intel_lvds->fixed_mode) { -+ intel_lvds->fixed_mode->type |= - DRM_MODE_TYPE_PREFERRED; - goto out; - } -@@ -958,19 +991,19 @@ void intel_lvds_init(struct drm_device *dev) - - lvds = I915_READ(LVDS); - pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; -- crtc = intel_get_crtc_from_pipe(dev, pipe); -+ crtc = intel_get_crtc_for_pipe(dev, pipe); - - if (crtc && (lvds & LVDS_PORT_EN)) { -- dev_priv->panel_fixed_mode = intel_crtc_mode_get(dev, crtc); -- if (dev_priv->panel_fixed_mode) { -- dev_priv->panel_fixed_mode->type |= -+ intel_lvds->fixed_mode = intel_crtc_mode_get(dev, crtc); -+ if (intel_lvds->fixed_mode) { -+ intel_lvds->fixed_mode->type |= - DRM_MODE_TYPE_PREFERRED; - goto out; - } - } - - /* If we still don't have a mode after all that, give up. */ -- if (!dev_priv->panel_fixed_mode) -+ if (!intel_lvds->fixed_mode) - goto failed; - - out: -@@ -997,8 +1030,6 @@ out: - - failed: - DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); -- if (intel_encoder->ddc_bus) -- intel_i2c_destroy(intel_encoder->ddc_bus); - drm_connector_cleanup(connector); - drm_encoder_cleanup(encoder); - kfree(intel_lvds); -diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c -index 4b1fd3d..f70b7cf 100644 ---- a/drivers/gpu/drm/i915/intel_modes.c -+++ b/drivers/gpu/drm/i915/intel_modes.c -@@ -1,6 +1,6 @@ - /* - * Copyright (c) 2007 Dave Airlie -- * Copyright (c) 2007 Intel Corporation -+ * Copyright (c) 2007, 2010 Intel Corporation - * Jesse Barnes - * - * Permission is hereby granted, free of charge, to any person obtaining a -@@ -34,11 +34,11 @@ - * intel_ddc_probe - * - */ --bool intel_ddc_probe(struct intel_encoder *intel_encoder) -+bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) - { -+ struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; - u8 out_buf[] = { 0x0, 0x0}; - u8 buf[2]; -- int ret; - struct i2c_msg msgs[] = { - { - .addr = 0x50, -@@ -54,13 +54,7 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder) - } - }; - -- intel_i2c_quirk_set(intel_encoder->enc.dev, true); -- ret = i2c_transfer(intel_encoder->ddc_bus, msgs, 2); -- intel_i2c_quirk_set(intel_encoder->enc.dev, false); -- if (ret == 2) -- return true; -- -- return false; -+ return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2; - } - - /** -@@ -76,9 +70,7 @@ int intel_ddc_get_modes(struct drm_connector *connector, - struct edid *edid; - int ret = 0; - -- intel_i2c_quirk_set(connector->dev, true); - edid = drm_get_edid(connector, adapter); -- intel_i2c_quirk_set(connector->dev, false); - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); -diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c -new file mode 100644 -index 0000000..9b0d9a8 ---- /dev/null -+++ b/drivers/gpu/drm/i915/intel_opregion.c -@@ -0,0 +1,517 @@ -+/* -+ * Copyright 2008 Intel Corporation -+ * Copyright 2008 Red Hat -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sub license, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NON-INFRINGEMENT. IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ * -+ */ -+ -+#include -+#include -+ -+#include "drmP.h" -+#include "i915_drm.h" -+#include "i915_drv.h" -+#include "intel_drv.h" -+ -+#define PCI_ASLE 0xe4 -+#define PCI_ASLS 0xfc -+ -+#define OPREGION_HEADER_OFFSET 0 -+#define OPREGION_ACPI_OFFSET 0x100 -+#define OPREGION_SWSCI_OFFSET 0x200 -+#define OPREGION_ASLE_OFFSET 0x300 -+#define OPREGION_VBT_OFFSET 0x400 -+ -+#define OPREGION_SIGNATURE "IntelGraphicsMem" -+#define MBOX_ACPI (1<<0) -+#define MBOX_SWSCI (1<<1) -+#define MBOX_ASLE (1<<2) -+ -+struct opregion_header { -+ u8 signature[16]; -+ u32 size; -+ u32 opregion_ver; -+ u8 bios_ver[32]; -+ u8 vbios_ver[16]; -+ u8 driver_ver[16]; -+ u32 mboxes; -+ u8 reserved[164]; -+} __attribute__((packed)); -+ -+/* OpRegion mailbox #1: public ACPI methods */ -+struct opregion_acpi { -+ u32 drdy; /* driver readiness */ -+ u32 csts; /* notification status */ -+ u32 cevt; /* current event */ -+ u8 rsvd1[20]; -+ u32 didl[8]; /* supported display devices ID list */ -+ u32 cpdl[8]; /* currently presented display list */ -+ u32 cadl[8]; /* currently active display list */ -+ u32 nadl[8]; /* next active devices list */ -+ u32 aslp; /* ASL sleep time-out */ -+ u32 tidx; /* toggle table index */ -+ u32 chpd; /* current hotplug enable indicator */ -+ u32 clid; /* current lid state*/ -+ u32 cdck; /* current docking state */ -+ u32 sxsw; /* Sx state resume */ -+ u32 evts; /* ASL supported events */ -+ u32 cnot; /* current OS notification */ -+ u32 nrdy; /* driver status */ -+ u8 rsvd2[60]; -+} __attribute__((packed)); -+ -+/* OpRegion mailbox #2: SWSCI */ -+struct opregion_swsci { -+ u32 scic; /* SWSCI command|status|data */ -+ u32 parm; /* command parameters */ -+ u32 dslp; /* driver sleep time-out */ -+ u8 rsvd[244]; -+} __attribute__((packed)); -+ -+/* OpRegion mailbox #3: ASLE */ -+struct opregion_asle { -+ u32 ardy; /* driver readiness */ -+ u32 aslc; /* ASLE interrupt command */ -+ u32 tche; /* technology enabled indicator */ -+ u32 alsi; /* current ALS illuminance reading */ -+ u32 bclp; /* backlight brightness to set */ -+ u32 pfit; /* panel fitting state */ -+ u32 cblv; /* current brightness level */ -+ u16 bclm[20]; /* backlight level duty cycle mapping table */ -+ u32 cpfm; /* current panel fitting mode */ -+ u32 epfm; /* enabled panel fitting modes */ -+ u8 plut[74]; /* panel LUT and identifier */ -+ u32 pfmb; /* PWM freq and min brightness */ -+ u8 rsvd[102]; -+} __attribute__((packed)); -+ -+/* ASLE irq request bits */ -+#define ASLE_SET_ALS_ILLUM (1 << 0) -+#define ASLE_SET_BACKLIGHT (1 << 1) -+#define ASLE_SET_PFIT (1 << 2) -+#define ASLE_SET_PWM_FREQ (1 << 3) -+#define ASLE_REQ_MSK 0xf -+ -+/* response bits of ASLE irq request */ -+#define ASLE_ALS_ILLUM_FAILED (1<<10) -+#define ASLE_BACKLIGHT_FAILED (1<<12) -+#define ASLE_PFIT_FAILED (1<<14) -+#define ASLE_PWM_FREQ_FAILED (1<<16) -+ -+/* ASLE backlight brightness to set */ -+#define ASLE_BCLP_VALID (1<<31) -+#define ASLE_BCLP_MSK (~(1<<31)) -+ -+/* ASLE panel fitting request */ -+#define ASLE_PFIT_VALID (1<<31) -+#define ASLE_PFIT_CENTER (1<<0) -+#define ASLE_PFIT_STRETCH_TEXT (1<<1) -+#define ASLE_PFIT_STRETCH_GFX (1<<2) -+ -+/* PWM frequency and minimum brightness */ -+#define ASLE_PFMB_BRIGHTNESS_MASK (0xff) -+#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8) -+#define ASLE_PFMB_PWM_MASK (0x7ffffe00) -+#define ASLE_PFMB_PWM_VALID (1<<31) -+ -+#define ASLE_CBLV_VALID (1<<31) -+ -+#define ACPI_OTHER_OUTPUT (0<<8) -+#define ACPI_VGA_OUTPUT (1<<8) -+#define ACPI_TV_OUTPUT (2<<8) -+#define ACPI_DIGITAL_OUTPUT (3<<8) -+#define ACPI_LVDS_OUTPUT (4<<8) -+ -+#ifdef CONFIG_ACPI -+static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct opregion_asle *asle = dev_priv->opregion.asle; -+ u32 max; -+ -+ if (!(bclp & ASLE_BCLP_VALID)) -+ return ASLE_BACKLIGHT_FAILED; -+ -+ bclp &= ASLE_BCLP_MSK; -+ if (bclp > 255) -+ return ASLE_BACKLIGHT_FAILED; -+ -+ max = intel_panel_get_max_backlight(dev); -+ intel_panel_set_backlight(dev, bclp * max / 255); -+ asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; -+ -+ return 0; -+} -+ -+static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) -+{ -+ /* alsi is the current ALS reading in lux. 0 indicates below sensor -+ range, 0xffff indicates above sensor range. 1-0xfffe are valid */ -+ return 0; -+} -+ -+static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ if (pfmb & ASLE_PFMB_PWM_VALID) { -+ u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL); -+ u32 pwm = pfmb & ASLE_PFMB_PWM_MASK; -+ blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK; -+ pwm = pwm >> 9; -+ /* FIXME - what do we do with the PWM? */ -+ } -+ return 0; -+} -+ -+static u32 asle_set_pfit(struct drm_device *dev, u32 pfit) -+{ -+ /* Panel fitting is currently controlled by the X code, so this is a -+ noop until modesetting support works fully */ -+ if (!(pfit & ASLE_PFIT_VALID)) -+ return ASLE_PFIT_FAILED; -+ return 0; -+} -+ -+void intel_opregion_asle_intr(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct opregion_asle *asle = dev_priv->opregion.asle; -+ u32 asle_stat = 0; -+ u32 asle_req; -+ -+ if (!asle) -+ return; -+ -+ asle_req = asle->aslc & ASLE_REQ_MSK; -+ -+ if (!asle_req) { -+ DRM_DEBUG_DRIVER("non asle set request??\n"); -+ return; -+ } -+ -+ if (asle_req & ASLE_SET_ALS_ILLUM) -+ asle_stat |= asle_set_als_illum(dev, asle->alsi); -+ -+ if (asle_req & ASLE_SET_BACKLIGHT) -+ asle_stat |= asle_set_backlight(dev, asle->bclp); -+ -+ if (asle_req & ASLE_SET_PFIT) -+ asle_stat |= asle_set_pfit(dev, asle->pfit); -+ -+ if (asle_req & ASLE_SET_PWM_FREQ) -+ asle_stat |= asle_set_pwm_freq(dev, asle->pfmb); -+ -+ asle->aslc = asle_stat; -+} -+ -+/* Only present on Ironlake+ */ -+void intel_opregion_gse_intr(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct opregion_asle *asle = dev_priv->opregion.asle; -+ u32 asle_stat = 0; -+ u32 asle_req; -+ -+ if (!asle) -+ return; -+ -+ asle_req = asle->aslc & ASLE_REQ_MSK; -+ -+ if (!asle_req) { -+ DRM_DEBUG_DRIVER("non asle set request??\n"); -+ return; -+ } -+ -+ if (asle_req & ASLE_SET_ALS_ILLUM) { -+ DRM_DEBUG_DRIVER("Illum is not supported\n"); -+ asle_stat |= ASLE_ALS_ILLUM_FAILED; -+ } -+ -+ if (asle_req & ASLE_SET_BACKLIGHT) -+ asle_stat |= asle_set_backlight(dev, asle->bclp); -+ -+ if (asle_req & ASLE_SET_PFIT) { -+ DRM_DEBUG_DRIVER("Pfit is not supported\n"); -+ asle_stat |= ASLE_PFIT_FAILED; -+ } -+ -+ if (asle_req & ASLE_SET_PWM_FREQ) { -+ DRM_DEBUG_DRIVER("PWM freq is not supported\n"); -+ asle_stat |= ASLE_PWM_FREQ_FAILED; -+ } -+ -+ asle->aslc = asle_stat; -+} -+#define ASLE_ALS_EN (1<<0) -+#define ASLE_BLC_EN (1<<1) -+#define ASLE_PFIT_EN (1<<2) -+#define ASLE_PFMB_EN (1<<3) -+ -+void intel_opregion_enable_asle(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct opregion_asle *asle = dev_priv->opregion.asle; -+ -+ if (asle) { -+ if (IS_MOBILE(dev)) { -+ unsigned long irqflags; -+ -+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); -+ intel_enable_asle(dev); -+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, -+ irqflags); -+ } -+ -+ asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN | -+ ASLE_PFMB_EN; -+ asle->ardy = 1; -+ } -+} -+ -+#define ACPI_EV_DISPLAY_SWITCH (1<<0) -+#define ACPI_EV_LID (1<<1) -+#define ACPI_EV_DOCK (1<<2) -+ -+static struct intel_opregion *system_opregion; -+ -+static int intel_opregion_video_event(struct notifier_block *nb, -+ unsigned long val, void *data) -+{ -+ /* The only video events relevant to opregion are 0x80. These indicate -+ either a docking event, lid switch or display switch request. In -+ Linux, these are handled by the dock, button and video drivers. -+ We might want to fix the video driver to be opregion-aware in -+ future, but right now we just indicate to the firmware that the -+ request has been handled */ -+ -+ struct opregion_acpi *acpi; -+ -+ if (!system_opregion) -+ return NOTIFY_DONE; -+ -+ acpi = system_opregion->acpi; -+ acpi->csts = 0; -+ -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block intel_opregion_notifier = { -+ .notifier_call = intel_opregion_video_event, -+}; -+ -+/* -+ * Initialise the DIDL field in opregion. This passes a list of devices to -+ * the firmware. Values are defined by section B.4.2 of the ACPI specification -+ * (version 3) -+ */ -+ -+static void intel_didl_outputs(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_opregion *opregion = &dev_priv->opregion; -+ struct drm_connector *connector; -+ acpi_handle handle; -+ struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL; -+ unsigned long long device_id; -+ acpi_status status; -+ int i = 0; -+ -+ handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); -+ if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) -+ return; -+ -+ if (acpi_is_video_device(acpi_dev)) -+ acpi_video_bus = acpi_dev; -+ else { -+ list_for_each_entry(acpi_cdev, &acpi_dev->children, node) { -+ if (acpi_is_video_device(acpi_cdev)) { -+ acpi_video_bus = acpi_cdev; -+ break; -+ } -+ } -+ } -+ -+ if (!acpi_video_bus) { -+ printk(KERN_WARNING "No ACPI video bus found\n"); -+ return; -+ } -+ -+ list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) { -+ if (i >= 8) { -+ dev_printk (KERN_ERR, &dev->pdev->dev, -+ "More than 8 outputs detected\n"); -+ return; -+ } -+ status = -+ acpi_evaluate_integer(acpi_cdev->handle, "_ADR", -+ NULL, &device_id); -+ if (ACPI_SUCCESS(status)) { -+ if (!device_id) -+ goto blind_set; -+ opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f); -+ i++; -+ } -+ } -+ -+end: -+ /* If fewer than 8 outputs, the list must be null terminated */ -+ if (i < 8) -+ opregion->acpi->didl[i] = 0; -+ return; -+ -+blind_set: -+ i = 0; -+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -+ int output_type = ACPI_OTHER_OUTPUT; -+ if (i >= 8) { -+ dev_printk (KERN_ERR, &dev->pdev->dev, -+ "More than 8 outputs detected\n"); -+ return; -+ } -+ switch (connector->connector_type) { -+ case DRM_MODE_CONNECTOR_VGA: -+ case DRM_MODE_CONNECTOR_DVIA: -+ output_type = ACPI_VGA_OUTPUT; -+ break; -+ case DRM_MODE_CONNECTOR_Composite: -+ case DRM_MODE_CONNECTOR_SVIDEO: -+ case DRM_MODE_CONNECTOR_Component: -+ case DRM_MODE_CONNECTOR_9PinDIN: -+ output_type = ACPI_TV_OUTPUT; -+ break; -+ case DRM_MODE_CONNECTOR_DVII: -+ case DRM_MODE_CONNECTOR_DVID: -+ case DRM_MODE_CONNECTOR_DisplayPort: -+ case DRM_MODE_CONNECTOR_HDMIA: -+ case DRM_MODE_CONNECTOR_HDMIB: -+ output_type = ACPI_DIGITAL_OUTPUT; -+ break; -+ case DRM_MODE_CONNECTOR_LVDS: -+ output_type = ACPI_LVDS_OUTPUT; -+ break; -+ } -+ opregion->acpi->didl[i] |= (1<<31) | output_type | i; -+ i++; -+ } -+ goto end; -+} -+ -+void intel_opregion_init(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_opregion *opregion = &dev_priv->opregion; -+ -+ if (!opregion->header) -+ return; -+ -+ if (opregion->acpi) { -+ if (drm_core_check_feature(dev, DRIVER_MODESET)) -+ intel_didl_outputs(dev); -+ -+ /* Notify BIOS we are ready to handle ACPI video ext notifs. -+ * Right now, all the events are handled by the ACPI video module. -+ * We don't actually need to do anything with them. */ -+ opregion->acpi->csts = 0; -+ opregion->acpi->drdy = 1; -+ -+ system_opregion = opregion; -+ register_acpi_notifier(&intel_opregion_notifier); -+ } -+ -+ if (opregion->asle) -+ intel_opregion_enable_asle(dev); -+} -+ -+void intel_opregion_fini(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_opregion *opregion = &dev_priv->opregion; -+ -+ if (!opregion->header) -+ return; -+ -+ if (opregion->acpi) { -+ opregion->acpi->drdy = 0; -+ -+ system_opregion = NULL; -+ unregister_acpi_notifier(&intel_opregion_notifier); -+ } -+ -+ /* just clear all opregion memory pointers now */ -+ iounmap(opregion->header); -+ opregion->header = NULL; -+ opregion->acpi = NULL; -+ opregion->swsci = NULL; -+ opregion->asle = NULL; -+ opregion->vbt = NULL; -+} -+#endif -+ -+int intel_opregion_setup(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct intel_opregion *opregion = &dev_priv->opregion; -+ void *base; -+ u32 asls, mboxes; -+ int err = 0; -+ -+ pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); -+ DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls); -+ if (asls == 0) { -+ DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n"); -+ return -ENOTSUPP; -+ } -+ -+ base = ioremap(asls, OPREGION_SIZE); -+ if (!base) -+ return -ENOMEM; -+ -+ if (memcmp(base, OPREGION_SIGNATURE, 16)) { -+ DRM_DEBUG_DRIVER("opregion signature mismatch\n"); -+ err = -EINVAL; -+ goto err_out; -+ } -+ opregion->header = base; -+ opregion->vbt = base + OPREGION_VBT_OFFSET; -+ -+ mboxes = opregion->header->mboxes; -+ if (mboxes & MBOX_ACPI) { -+ DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); -+ opregion->acpi = base + OPREGION_ACPI_OFFSET; -+ } -+ -+ if (mboxes & MBOX_SWSCI) { -+ DRM_DEBUG_DRIVER("SWSCI supported\n"); -+ opregion->swsci = base + OPREGION_SWSCI_OFFSET; -+ } -+ if (mboxes & MBOX_ASLE) { -+ DRM_DEBUG_DRIVER("ASLE supported\n"); -+ opregion->asle = base + OPREGION_ASLE_OFFSET; -+ } -+ -+ return 0; -+ -+err_out: -+ iounmap(base); -+ return err; -+} -diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c -index 1d306a4..5b513ea 100644 ---- a/drivers/gpu/drm/i915/intel_overlay.c -+++ b/drivers/gpu/drm/i915/intel_overlay.c -@@ -170,57 +170,143 @@ struct overlay_registers { - u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; - }; - --/* overlay flip addr flag */ --#define OFC_UPDATE 0x1 -- --#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev)) --#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev)) -- -+struct intel_overlay { -+ struct drm_device *dev; -+ struct intel_crtc *crtc; -+ struct drm_i915_gem_object *vid_bo; -+ struct drm_i915_gem_object *old_vid_bo; -+ int active; -+ int pfit_active; -+ u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ -+ u32 color_key; -+ u32 brightness, contrast, saturation; -+ u32 old_xscale, old_yscale; -+ /* register access */ -+ u32 flip_addr; -+ struct drm_i915_gem_object *reg_bo; -+ /* flip handling */ -+ uint32_t last_flip_req; -+ void (*flip_tail)(struct intel_overlay *); -+}; - --static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay) -+static struct overlay_registers * -+intel_overlay_map_regs(struct intel_overlay *overlay) - { - drm_i915_private_t *dev_priv = overlay->dev->dev_private; - struct overlay_registers *regs; - -- /* no recursive mappings */ -- BUG_ON(overlay->virt_addr); -+ if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) -+ regs = overlay->reg_bo->phys_obj->handle->vaddr; -+ else -+ regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping, -+ overlay->reg_bo->gtt_offset); - -- if (OVERLAY_NONPHYSICAL(overlay->dev)) { -- regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, -- overlay->reg_bo->gtt_offset, -- KM_USER0); -+ return regs; -+} - -- if (!regs) { -- DRM_ERROR("failed to map overlay regs in GTT\n"); -- return NULL; -- } -- } else -- regs = overlay->reg_bo->phys_obj->handle->vaddr; -+static void intel_overlay_unmap_regs(struct intel_overlay *overlay, -+ struct overlay_registers *regs) -+{ -+ if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev)) -+ io_mapping_unmap(regs); -+} - -- return overlay->virt_addr = regs; -+static int intel_overlay_do_wait_request(struct intel_overlay *overlay, -+ struct drm_i915_gem_request *request, -+ bool interruptible, -+ void (*tail)(struct intel_overlay *)) -+{ -+ struct drm_device *dev = overlay->dev; -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ int ret; -+ -+ BUG_ON(overlay->last_flip_req); -+ overlay->last_flip_req = -+ i915_add_request(dev, NULL, request, &dev_priv->render_ring); -+ if (overlay->last_flip_req == 0) -+ return -ENOMEM; -+ -+ overlay->flip_tail = tail; -+ ret = i915_do_wait_request(dev, -+ overlay->last_flip_req, true, -+ &dev_priv->render_ring); -+ if (ret) -+ return ret; -+ -+ overlay->last_flip_req = 0; -+ return 0; - } - --static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay) -+/* Workaround for i830 bug where pipe a must be enable to change control regs */ -+static int -+i830_activate_pipe_a(struct drm_device *dev) - { -- if (OVERLAY_NONPHYSICAL(overlay->dev)) -- io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0); -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ struct intel_crtc *crtc; -+ struct drm_crtc_helper_funcs *crtc_funcs; -+ struct drm_display_mode vesa_640x480 = { -+ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, -+ 752, 800, 0, 480, 489, 492, 525, 0, -+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) -+ }, *mode; -+ -+ crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]); -+ if (crtc->dpms_mode == DRM_MODE_DPMS_ON) -+ return 0; - -- overlay->virt_addr = NULL; -+ /* most i8xx have pipe a forced on, so don't trust dpms mode */ -+ if (I915_READ(PIPEACONF) & PIPECONF_ENABLE) -+ return 0; - -- return; -+ crtc_funcs = crtc->base.helper_private; -+ if (crtc_funcs->dpms == NULL) -+ return 0; -+ -+ DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n"); -+ -+ mode = drm_mode_duplicate(dev, &vesa_640x480); -+ drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); -+ if(!drm_crtc_helper_set_mode(&crtc->base, mode, -+ crtc->base.x, crtc->base.y, -+ crtc->base.fb)) -+ return 0; -+ -+ crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON); -+ return 1; -+} -+ -+static void -+i830_deactivate_pipe_a(struct drm_device *dev) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; -+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -+ -+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); - } - - /* overlay needs to be disable in OCMD reg */ - static int intel_overlay_on(struct intel_overlay *overlay) - { - struct drm_device *dev = overlay->dev; -+ struct drm_i915_gem_request *request; -+ int pipe_a_quirk = 0; - int ret; -- drm_i915_private_t *dev_priv = dev->dev_private; - - BUG_ON(overlay->active); -- - overlay->active = 1; -- overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP; -+ -+ if (IS_I830(dev)) { -+ pipe_a_quirk = i830_activate_pipe_a(dev); -+ if (pipe_a_quirk < 0) -+ return pipe_a_quirk; -+ } -+ -+ request = kzalloc(sizeof(*request), GFP_KERNEL); -+ if (request == NULL) { -+ ret = -ENOMEM; -+ goto out; -+ } - - BEGIN_LP_RING(4); - OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); -@@ -229,32 +315,30 @@ static int intel_overlay_on(struct intel_overlay *overlay) - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - -- overlay->last_flip_req = -- i915_add_request(dev, NULL, 0, &dev_priv->render_ring); -- if (overlay->last_flip_req == 0) -- return -ENOMEM; -- -- ret = i915_do_wait_request(dev, -- overlay->last_flip_req, 1, &dev_priv->render_ring); -- if (ret != 0) -- return ret; -+ ret = intel_overlay_do_wait_request(overlay, request, true, NULL); -+out: -+ if (pipe_a_quirk) -+ i830_deactivate_pipe_a(dev); - -- overlay->hw_wedged = 0; -- overlay->last_flip_req = 0; -- return 0; -+ return ret; - } - - /* overlay needs to be enabled in OCMD reg */ --static void intel_overlay_continue(struct intel_overlay *overlay, -- bool load_polyphase_filter) -+static int intel_overlay_continue(struct intel_overlay *overlay, -+ bool load_polyphase_filter) - { - struct drm_device *dev = overlay->dev; - drm_i915_private_t *dev_priv = dev->dev_private; -+ struct drm_i915_gem_request *request; - u32 flip_addr = overlay->flip_addr; - u32 tmp; - - BUG_ON(!overlay->active); - -+ request = kzalloc(sizeof(*request), GFP_KERNEL); -+ if (request == NULL) -+ return -ENOMEM; -+ - if (load_polyphase_filter) - flip_addr |= OFC_UPDATE; - -@@ -269,220 +353,132 @@ static void intel_overlay_continue(struct intel_overlay *overlay, - ADVANCE_LP_RING(); - - overlay->last_flip_req = -- i915_add_request(dev, NULL, 0, &dev_priv->render_ring); -+ i915_add_request(dev, NULL, request, &dev_priv->render_ring); -+ return 0; - } - --static int intel_overlay_wait_flip(struct intel_overlay *overlay) -+static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) - { -- struct drm_device *dev = overlay->dev; -- drm_i915_private_t *dev_priv = dev->dev_private; -- int ret; -- u32 tmp; -- -- if (overlay->last_flip_req != 0) { -- ret = i915_do_wait_request(dev, overlay->last_flip_req, -- 1, &dev_priv->render_ring); -- if (ret == 0) { -- overlay->last_flip_req = 0; -- -- tmp = I915_READ(ISR); -+ struct drm_gem_object *obj = &overlay->old_vid_bo->base; - -- if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) -- return 0; -- } -- } -+ i915_gem_object_unpin(obj); -+ drm_gem_object_unreference(obj); - -- /* synchronous slowpath */ -- overlay->hw_wedged = RELEASE_OLD_VID; -+ overlay->old_vid_bo = NULL; -+} - -- BEGIN_LP_RING(2); -- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); -- OUT_RING(MI_NOOP); -- ADVANCE_LP_RING(); -+static void intel_overlay_off_tail(struct intel_overlay *overlay) -+{ -+ struct drm_gem_object *obj; - -- overlay->last_flip_req = -- i915_add_request(dev, NULL, 0, &dev_priv->render_ring); -- if (overlay->last_flip_req == 0) -- return -ENOMEM; -+ /* never have the overlay hw on without showing a frame */ -+ BUG_ON(!overlay->vid_bo); -+ obj = &overlay->vid_bo->base; - -- ret = i915_do_wait_request(dev, overlay->last_flip_req, -- 1, &dev_priv->render_ring); -- if (ret != 0) -- return ret; -+ i915_gem_object_unpin(obj); -+ drm_gem_object_unreference(obj); -+ overlay->vid_bo = NULL; - -- overlay->hw_wedged = 0; -- overlay->last_flip_req = 0; -- return 0; -+ overlay->crtc->overlay = NULL; -+ overlay->crtc = NULL; -+ overlay->active = 0; - } - - /* overlay needs to be disabled in OCMD reg */ --static int intel_overlay_off(struct intel_overlay *overlay) -+static int intel_overlay_off(struct intel_overlay *overlay, -+ bool interruptible) - { -- u32 flip_addr = overlay->flip_addr; - struct drm_device *dev = overlay->dev; -- drm_i915_private_t *dev_priv = dev->dev_private; -- int ret; -+ u32 flip_addr = overlay->flip_addr; -+ struct drm_i915_gem_request *request; - - BUG_ON(!overlay->active); - -+ request = kzalloc(sizeof(*request), GFP_KERNEL); -+ if (request == NULL) -+ return -ENOMEM; -+ - /* According to intel docs the overlay hw may hang (when switching - * off) without loading the filter coeffs. It is however unclear whether - * this applies to the disabling of the overlay or to the switching off - * of the hw. Do it in both cases */ - flip_addr |= OFC_UPDATE; - -+ BEGIN_LP_RING(6); - /* wait for overlay to go idle */ -- overlay->hw_wedged = SWITCH_OFF_STAGE_1; -- -- BEGIN_LP_RING(4); - OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); - OUT_RING(flip_addr); -- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); -- OUT_RING(MI_NOOP); -- ADVANCE_LP_RING(); -- -- overlay->last_flip_req = -- i915_add_request(dev, NULL, 0, &dev_priv->render_ring); -- if (overlay->last_flip_req == 0) -- return -ENOMEM; -- -- ret = i915_do_wait_request(dev, overlay->last_flip_req, -- 1, &dev_priv->render_ring); -- if (ret != 0) -- return ret; -- -+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); - /* turn overlay off */ -- overlay->hw_wedged = SWITCH_OFF_STAGE_2; -- -- BEGIN_LP_RING(4); -- OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); -+ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); - OUT_RING(flip_addr); -- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); -- OUT_RING(MI_NOOP); -+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); - ADVANCE_LP_RING(); - -- overlay->last_flip_req = -- i915_add_request(dev, NULL, 0, &dev_priv->render_ring); -- if (overlay->last_flip_req == 0) -- return -ENOMEM; -- -- ret = i915_do_wait_request(dev, overlay->last_flip_req, -- 1, &dev_priv->render_ring); -- if (ret != 0) -- return ret; -- -- overlay->hw_wedged = 0; -- overlay->last_flip_req = 0; -- return ret; --} -- --static void intel_overlay_off_tail(struct intel_overlay *overlay) --{ -- struct drm_gem_object *obj; -- -- /* never have the overlay hw on without showing a frame */ -- BUG_ON(!overlay->vid_bo); -- obj = &overlay->vid_bo->base; -- -- i915_gem_object_unpin(obj); -- drm_gem_object_unreference(obj); -- overlay->vid_bo = NULL; -- -- overlay->crtc->overlay = NULL; -- overlay->crtc = NULL; -- overlay->active = 0; -+ return intel_overlay_do_wait_request(overlay, request, interruptible, -+ intel_overlay_off_tail); - } - - /* recover from an interruption due to a signal - * We have to be careful not to repeat work forever an make forward progess. */ --int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, -- int interruptible) -+static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, -+ bool interruptible) - { - struct drm_device *dev = overlay->dev; -- struct drm_gem_object *obj; - drm_i915_private_t *dev_priv = dev->dev_private; -- u32 flip_addr; - int ret; - -- if (overlay->hw_wedged == HW_WEDGED) -- return -EIO; -- -- if (overlay->last_flip_req == 0) { -- overlay->last_flip_req = -- i915_add_request(dev, NULL, 0, &dev_priv->render_ring); -- if (overlay->last_flip_req == 0) -- return -ENOMEM; -- } -+ if (overlay->last_flip_req == 0) -+ return 0; - - ret = i915_do_wait_request(dev, overlay->last_flip_req, -- interruptible, &dev_priv->render_ring); -- if (ret != 0) -+ interruptible, &dev_priv->render_ring); -+ if (ret) - return ret; - -- switch (overlay->hw_wedged) { -- case RELEASE_OLD_VID: -- obj = &overlay->old_vid_bo->base; -- i915_gem_object_unpin(obj); -- drm_gem_object_unreference(obj); -- overlay->old_vid_bo = NULL; -- break; -- case SWITCH_OFF_STAGE_1: -- flip_addr = overlay->flip_addr; -- flip_addr |= OFC_UPDATE; -- -- overlay->hw_wedged = SWITCH_OFF_STAGE_2; -- -- BEGIN_LP_RING(4); -- OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); -- OUT_RING(flip_addr); -- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); -- OUT_RING(MI_NOOP); -- ADVANCE_LP_RING(); -- -- overlay->last_flip_req = i915_add_request(dev, NULL, -- 0, &dev_priv->render_ring); -- if (overlay->last_flip_req == 0) -- return -ENOMEM; -- -- ret = i915_do_wait_request(dev, overlay->last_flip_req, -- interruptible, &dev_priv->render_ring); -- if (ret != 0) -- return ret; -- -- case SWITCH_OFF_STAGE_2: -- intel_overlay_off_tail(overlay); -- break; -- default: -- BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP); -- } -+ if (overlay->flip_tail) -+ overlay->flip_tail(overlay); - -- overlay->hw_wedged = 0; - overlay->last_flip_req = 0; - return 0; - } - - /* Wait for pending overlay flip and release old frame. - * Needs to be called before the overlay register are changed -- * via intel_overlay_(un)map_regs_atomic */ -+ * via intel_overlay_(un)map_regs -+ */ - static int intel_overlay_release_old_vid(struct intel_overlay *overlay) - { -+ struct drm_device *dev = overlay->dev; -+ drm_i915_private_t *dev_priv = dev->dev_private; - int ret; -- struct drm_gem_object *obj; - -- /* only wait if there is actually an old frame to release to -- * guarantee forward progress */ -+ /* Only wait if there is actually an old frame to release to -+ * guarantee forward progress. -+ */ - if (!overlay->old_vid_bo) - return 0; - -- ret = intel_overlay_wait_flip(overlay); -- if (ret != 0) -- return ret; -+ if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { -+ struct drm_i915_gem_request *request; - -- obj = &overlay->old_vid_bo->base; -- i915_gem_object_unpin(obj); -- drm_gem_object_unreference(obj); -- overlay->old_vid_bo = NULL; -+ /* synchronous slowpath */ -+ request = kzalloc(sizeof(*request), GFP_KERNEL); -+ if (request == NULL) -+ return -ENOMEM; -+ -+ BEGIN_LP_RING(2); -+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); -+ OUT_RING(MI_NOOP); -+ ADVANCE_LP_RING(); -+ -+ ret = intel_overlay_do_wait_request(overlay, request, true, -+ intel_overlay_release_old_vid_tail); -+ if (ret) -+ return ret; -+ } - -+ intel_overlay_release_old_vid_tail(overlay); - return 0; - } - -@@ -506,65 +502,65 @@ struct put_image_params { - static int packed_depth_bytes(u32 format) - { - switch (format & I915_OVERLAY_DEPTH_MASK) { -- case I915_OVERLAY_YUV422: -- return 4; -- case I915_OVERLAY_YUV411: -- /* return 6; not implemented */ -- default: -- return -EINVAL; -+ case I915_OVERLAY_YUV422: -+ return 4; -+ case I915_OVERLAY_YUV411: -+ /* return 6; not implemented */ -+ default: -+ return -EINVAL; - } - } - - static int packed_width_bytes(u32 format, short width) - { - switch (format & I915_OVERLAY_DEPTH_MASK) { -- case I915_OVERLAY_YUV422: -- return width << 1; -- default: -- return -EINVAL; -+ case I915_OVERLAY_YUV422: -+ return width << 1; -+ default: -+ return -EINVAL; - } - } - - static int uv_hsubsampling(u32 format) - { - switch (format & I915_OVERLAY_DEPTH_MASK) { -- case I915_OVERLAY_YUV422: -- case I915_OVERLAY_YUV420: -- return 2; -- case I915_OVERLAY_YUV411: -- case I915_OVERLAY_YUV410: -- return 4; -- default: -- return -EINVAL; -+ case I915_OVERLAY_YUV422: -+ case I915_OVERLAY_YUV420: -+ return 2; -+ case I915_OVERLAY_YUV411: -+ case I915_OVERLAY_YUV410: -+ return 4; -+ default: -+ return -EINVAL; - } - } - - static int uv_vsubsampling(u32 format) - { - switch (format & I915_OVERLAY_DEPTH_MASK) { -- case I915_OVERLAY_YUV420: -- case I915_OVERLAY_YUV410: -- return 2; -- case I915_OVERLAY_YUV422: -- case I915_OVERLAY_YUV411: -- return 1; -- default: -- return -EINVAL; -+ case I915_OVERLAY_YUV420: -+ case I915_OVERLAY_YUV410: -+ return 2; -+ case I915_OVERLAY_YUV422: -+ case I915_OVERLAY_YUV411: -+ return 1; -+ default: -+ return -EINVAL; - } - } - - static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) - { - u32 mask, shift, ret; -- if (IS_I9XX(dev)) { -- mask = 0x3f; -- shift = 6; -- } else { -+ if (IS_GEN2(dev)) { - mask = 0x1f; - shift = 5; -+ } else { -+ mask = 0x3f; -+ shift = 6; - } - ret = ((offset + width + mask) >> shift) - (offset >> shift); -- if (IS_I9XX(dev)) -+ if (!IS_GEN2(dev)) - ret <<= 1; - ret -=1; - return ret << 2; -@@ -587,7 +583,9 @@ static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = { - 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, - 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, - 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, -- 0xb000, 0x3000, 0x0800, 0x3000, 0xb000}; -+ 0xb000, 0x3000, 0x0800, 0x3000, 0xb000 -+}; -+ - static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { - 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, - 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, -@@ -597,7 +595,8 @@ static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { - 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, - 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, - 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, -- 0x3000, 0x0800, 0x3000}; -+ 0x3000, 0x0800, 0x3000 -+}; - - static void update_polyphase_filter(struct overlay_registers *regs) - { -@@ -630,29 +629,31 @@ static bool update_scaling_factors(struct intel_overlay *overlay, - yscale = 1 << FP_SHIFT; - - /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ -- xscale_UV = xscale/uv_hscale; -- yscale_UV = yscale/uv_vscale; -- /* make the Y scale to UV scale ratio an exact multiply */ -- xscale = xscale_UV * uv_hscale; -- yscale = yscale_UV * uv_vscale; -+ xscale_UV = xscale/uv_hscale; -+ yscale_UV = yscale/uv_vscale; -+ /* make the Y scale to UV scale ratio an exact multiply */ -+ xscale = xscale_UV * uv_hscale; -+ yscale = yscale_UV * uv_vscale; - /*} else { -- xscale_UV = 0; -- yscale_UV = 0; -- }*/ -+ xscale_UV = 0; -+ yscale_UV = 0; -+ }*/ - - if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) - scale_changed = true; - overlay->old_xscale = xscale; - overlay->old_yscale = yscale; - -- regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20) -- | ((xscale >> FP_SHIFT) << 16) -- | ((xscale & FRACT_MASK) << 3); -- regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20) -- | ((xscale_UV >> FP_SHIFT) << 16) -- | ((xscale_UV & FRACT_MASK) << 3); -- regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16) -- | ((yscale_UV >> FP_SHIFT) << 0); -+ regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) | -+ ((xscale >> FP_SHIFT) << 16) | -+ ((xscale & FRACT_MASK) << 3)); -+ -+ regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) | -+ ((xscale_UV >> FP_SHIFT) << 16) | -+ ((xscale_UV & FRACT_MASK) << 3)); -+ -+ regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) | -+ ((yscale_UV >> FP_SHIFT) << 0))); - - if (scale_changed) - update_polyphase_filter(regs); -@@ -664,22 +665,28 @@ static void update_colorkey(struct intel_overlay *overlay, - struct overlay_registers *regs) - { - u32 key = overlay->color_key; -+ - switch (overlay->crtc->base.fb->bits_per_pixel) { -- case 8: -- regs->DCLRKV = 0; -- regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; -- case 16: -- if (overlay->crtc->base.fb->depth == 15) { -- regs->DCLRKV = RGB15_TO_COLORKEY(key); -- regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; -- } else { -- regs->DCLRKV = RGB16_TO_COLORKEY(key); -- regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; -- } -- case 24: -- case 32: -- regs->DCLRKV = key; -- regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; -+ case 8: -+ regs->DCLRKV = 0; -+ regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; -+ break; -+ -+ case 16: -+ if (overlay->crtc->base.fb->depth == 15) { -+ regs->DCLRKV = RGB15_TO_COLORKEY(key); -+ regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; -+ } else { -+ regs->DCLRKV = RGB16_TO_COLORKEY(key); -+ regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; -+ } -+ break; -+ -+ case 24: -+ case 32: -+ regs->DCLRKV = key; -+ regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; -+ break; - } - } - -@@ -689,48 +696,48 @@ static u32 overlay_cmd_reg(struct put_image_params *params) - - if (params->format & I915_OVERLAY_YUV_PLANAR) { - switch (params->format & I915_OVERLAY_DEPTH_MASK) { -- case I915_OVERLAY_YUV422: -- cmd |= OCMD_YUV_422_PLANAR; -- break; -- case I915_OVERLAY_YUV420: -- cmd |= OCMD_YUV_420_PLANAR; -- break; -- case I915_OVERLAY_YUV411: -- case I915_OVERLAY_YUV410: -- cmd |= OCMD_YUV_410_PLANAR; -- break; -+ case I915_OVERLAY_YUV422: -+ cmd |= OCMD_YUV_422_PLANAR; -+ break; -+ case I915_OVERLAY_YUV420: -+ cmd |= OCMD_YUV_420_PLANAR; -+ break; -+ case I915_OVERLAY_YUV411: -+ case I915_OVERLAY_YUV410: -+ cmd |= OCMD_YUV_410_PLANAR; -+ break; - } - } else { /* YUV packed */ - switch (params->format & I915_OVERLAY_DEPTH_MASK) { -- case I915_OVERLAY_YUV422: -- cmd |= OCMD_YUV_422_PACKED; -- break; -- case I915_OVERLAY_YUV411: -- cmd |= OCMD_YUV_411_PACKED; -- break; -+ case I915_OVERLAY_YUV422: -+ cmd |= OCMD_YUV_422_PACKED; -+ break; -+ case I915_OVERLAY_YUV411: -+ cmd |= OCMD_YUV_411_PACKED; -+ break; - } - - switch (params->format & I915_OVERLAY_SWAP_MASK) { -- case I915_OVERLAY_NO_SWAP: -- break; -- case I915_OVERLAY_UV_SWAP: -- cmd |= OCMD_UV_SWAP; -- break; -- case I915_OVERLAY_Y_SWAP: -- cmd |= OCMD_Y_SWAP; -- break; -- case I915_OVERLAY_Y_AND_UV_SWAP: -- cmd |= OCMD_Y_AND_UV_SWAP; -- break; -+ case I915_OVERLAY_NO_SWAP: -+ break; -+ case I915_OVERLAY_UV_SWAP: -+ cmd |= OCMD_UV_SWAP; -+ break; -+ case I915_OVERLAY_Y_SWAP: -+ cmd |= OCMD_Y_SWAP; -+ break; -+ case I915_OVERLAY_Y_AND_UV_SWAP: -+ cmd |= OCMD_Y_AND_UV_SWAP; -+ break; - } - } - - return cmd; - } - --int intel_overlay_do_put_image(struct intel_overlay *overlay, -- struct drm_gem_object *new_bo, -- struct put_image_params *params) -+static int intel_overlay_do_put_image(struct intel_overlay *overlay, -+ struct drm_gem_object *new_bo, -+ struct put_image_params *params) - { - int ret, tmp_width; - struct overlay_registers *regs; -@@ -755,24 +762,24 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, - goto out_unpin; - - if (!overlay->active) { -- regs = intel_overlay_map_regs_atomic(overlay); -+ regs = intel_overlay_map_regs(overlay); - if (!regs) { - ret = -ENOMEM; - goto out_unpin; - } - regs->OCONFIG = OCONF_CC_OUT_8BIT; -- if (IS_I965GM(overlay->dev)) -+ if (IS_GEN4(overlay->dev)) - regs->OCONFIG |= OCONF_CSC_MODE_BT709; - regs->OCONFIG |= overlay->crtc->pipe == 0 ? - OCONF_PIPE_A : OCONF_PIPE_B; -- intel_overlay_unmap_regs_atomic(overlay); -+ intel_overlay_unmap_regs(overlay, regs); - - ret = intel_overlay_on(overlay); - if (ret != 0) - goto out_unpin; - } - -- regs = intel_overlay_map_regs_atomic(overlay); -+ regs = intel_overlay_map_regs(overlay); - if (!regs) { - ret = -ENOMEM; - goto out_unpin; -@@ -788,7 +795,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, - - regs->SWIDTH = params->src_w; - regs->SWIDTHSW = calc_swidthsw(overlay->dev, -- params->offset_Y, tmp_width); -+ params->offset_Y, tmp_width); - regs->SHEIGHT = params->src_h; - regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y; - regs->OSTRIDE = params->stride_Y; -@@ -799,9 +806,9 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, - u32 tmp_U, tmp_V; - regs->SWIDTH |= (params->src_w/uv_hscale) << 16; - tmp_U = calc_swidthsw(overlay->dev, params->offset_U, -- params->src_w/uv_hscale); -+ params->src_w/uv_hscale); - tmp_V = calc_swidthsw(overlay->dev, params->offset_V, -- params->src_w/uv_hscale); -+ params->src_w/uv_hscale); - regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; - regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; - regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U; -@@ -815,9 +822,11 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, - - regs->OCMD = overlay_cmd_reg(params); - -- intel_overlay_unmap_regs_atomic(overlay); -+ intel_overlay_unmap_regs(overlay, regs); - -- intel_overlay_continue(overlay, scale_changed); -+ ret = intel_overlay_continue(overlay, scale_changed); -+ if (ret) -+ goto out_unpin; - - overlay->old_vid_bo = overlay->vid_bo; - overlay->vid_bo = to_intel_bo(new_bo); -@@ -829,20 +838,19 @@ out_unpin: - return ret; - } - --int intel_overlay_switch_off(struct intel_overlay *overlay) -+int intel_overlay_switch_off(struct intel_overlay *overlay, -+ bool interruptible) - { -- int ret; - struct overlay_registers *regs; - struct drm_device *dev = overlay->dev; -+ int ret; - - BUG_ON(!mutex_is_locked(&dev->struct_mutex)); - BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); - -- if (overlay->hw_wedged) { -- ret = intel_overlay_recover_from_interrupt(overlay, 1); -- if (ret != 0) -- return ret; -- } -+ ret = intel_overlay_recover_from_interrupt(overlay, interruptible); -+ if (ret != 0) -+ return ret; - - if (!overlay->active) - return 0; -@@ -851,33 +859,29 @@ int intel_overlay_switch_off(struct intel_overlay *overlay) - if (ret != 0) - return ret; - -- regs = intel_overlay_map_regs_atomic(overlay); -+ regs = intel_overlay_map_regs(overlay); - regs->OCMD = 0; -- intel_overlay_unmap_regs_atomic(overlay); -+ intel_overlay_unmap_regs(overlay, regs); - -- ret = intel_overlay_off(overlay); -+ ret = intel_overlay_off(overlay, interruptible); - if (ret != 0) - return ret; - - intel_overlay_off_tail(overlay); -- - return 0; - } - - static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, - struct intel_crtc *crtc) - { -- drm_i915_private_t *dev_priv = overlay->dev->dev_private; -- u32 pipeconf; -- int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF; -+ drm_i915_private_t *dev_priv = overlay->dev->dev_private; - -- if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON) -+ if (!crtc->active) - return -EINVAL; - -- pipeconf = I915_READ(pipeconf_reg); -- - /* can't use the overlay with double wide pipe */ -- if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE) -+ if (INTEL_INFO(overlay->dev)->gen < 4 && -+ (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE) - return -EINVAL; - - return 0; -@@ -886,20 +890,22 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, - static void update_pfit_vscale_ratio(struct intel_overlay *overlay) - { - struct drm_device *dev = overlay->dev; -- drm_i915_private_t *dev_priv = dev->dev_private; -- u32 ratio; -+ drm_i915_private_t *dev_priv = dev->dev_private; - u32 pfit_control = I915_READ(PFIT_CONTROL); -+ u32 ratio; - - /* XXX: This is not the same logic as in the xorg driver, but more in -- * line with the intel documentation for the i965 */ -- if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) { -- ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT; -- } else { /* on i965 use the PGM reg to read out the autoscaler values */ -- ratio = I915_READ(PFIT_PGM_RATIOS); -- if (IS_I965G(dev)) -- ratio >>= PFIT_VERT_SCALE_SHIFT_965; -+ * line with the intel documentation for the i965 -+ */ -+ if (INTEL_INFO(dev)->gen >= 4) { -+ /* on i965 use the PGM reg to read out the autoscaler values */ -+ ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965; -+ } else { -+ if (pfit_control & VERT_AUTO_SCALE) -+ ratio = I915_READ(PFIT_AUTO_RATIOS); - else -- ratio >>= PFIT_VERT_SCALE_SHIFT; -+ ratio = I915_READ(PFIT_PGM_RATIOS); -+ ratio >>= PFIT_VERT_SCALE_SHIFT; - } - - overlay->pfit_vscale_ratio = ratio; -@@ -910,12 +916,10 @@ static int check_overlay_dst(struct intel_overlay *overlay, - { - struct drm_display_mode *mode = &overlay->crtc->base.mode; - -- if ((rec->dst_x < mode->crtc_hdisplay) -- && (rec->dst_x + rec->dst_width -- <= mode->crtc_hdisplay) -- && (rec->dst_y < mode->crtc_vdisplay) -- && (rec->dst_y + rec->dst_height -- <= mode->crtc_vdisplay)) -+ if (rec->dst_x < mode->crtc_hdisplay && -+ rec->dst_x + rec->dst_width <= mode->crtc_hdisplay && -+ rec->dst_y < mode->crtc_vdisplay && -+ rec->dst_y + rec->dst_height <= mode->crtc_vdisplay) - return 0; - else - return -EINVAL; -@@ -940,53 +944,59 @@ static int check_overlay_src(struct drm_device *dev, - struct drm_intel_overlay_put_image *rec, - struct drm_gem_object *new_bo) - { -- u32 stride_mask; -- int depth; - int uv_hscale = uv_hsubsampling(rec->flags); - int uv_vscale = uv_vsubsampling(rec->flags); -- size_t tmp; -+ u32 stride_mask; -+ int depth; -+ u32 tmp; - - /* check src dimensions */ - if (IS_845G(dev) || IS_I830(dev)) { -- if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY -- || rec->src_width > IMAGE_MAX_WIDTH_LEGACY) -+ if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY || -+ rec->src_width > IMAGE_MAX_WIDTH_LEGACY) - return -EINVAL; - } else { -- if (rec->src_height > IMAGE_MAX_HEIGHT -- || rec->src_width > IMAGE_MAX_WIDTH) -+ if (rec->src_height > IMAGE_MAX_HEIGHT || -+ rec->src_width > IMAGE_MAX_WIDTH) - return -EINVAL; - } -+ - /* better safe than sorry, use 4 as the maximal subsampling ratio */ -- if (rec->src_height < N_VERT_Y_TAPS*4 -- || rec->src_width < N_HORIZ_Y_TAPS*4) -+ if (rec->src_height < N_VERT_Y_TAPS*4 || -+ rec->src_width < N_HORIZ_Y_TAPS*4) - return -EINVAL; - - /* check alignment constraints */ - switch (rec->flags & I915_OVERLAY_TYPE_MASK) { -- case I915_OVERLAY_RGB: -- /* not implemented */ -+ case I915_OVERLAY_RGB: -+ /* not implemented */ -+ return -EINVAL; -+ -+ case I915_OVERLAY_YUV_PACKED: -+ if (uv_vscale != 1) - return -EINVAL; -- case I915_OVERLAY_YUV_PACKED: -- depth = packed_depth_bytes(rec->flags); -- if (uv_vscale != 1) -- return -EINVAL; -- if (depth < 0) -- return depth; -- /* ignore UV planes */ -- rec->stride_UV = 0; -- rec->offset_U = 0; -- rec->offset_V = 0; -- /* check pixel alignment */ -- if (rec->offset_Y % depth) -- return -EINVAL; -- break; -- case I915_OVERLAY_YUV_PLANAR: -- if (uv_vscale < 0 || uv_hscale < 0) -- return -EINVAL; -- /* no offset restrictions for planar formats */ -- break; -- default: -+ -+ depth = packed_depth_bytes(rec->flags); -+ if (depth < 0) -+ return depth; -+ -+ /* ignore UV planes */ -+ rec->stride_UV = 0; -+ rec->offset_U = 0; -+ rec->offset_V = 0; -+ /* check pixel alignment */ -+ if (rec->offset_Y % depth) - return -EINVAL; -+ break; -+ -+ case I915_OVERLAY_YUV_PLANAR: -+ if (uv_vscale < 0 || uv_hscale < 0) -+ return -EINVAL; -+ /* no offset restrictions for planar formats */ -+ break; -+ -+ default: -+ return -EINVAL; - } - - if (rec->src_width % uv_hscale) -@@ -1000,47 +1010,74 @@ static int check_overlay_src(struct drm_device *dev, - - if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) - return -EINVAL; -- if (IS_I965G(dev) && rec->stride_Y < 512) -+ if (IS_GEN4(dev) && rec->stride_Y < 512) - return -EINVAL; - - tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? -- 4 : 8; -- if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024) -+ 4096 : 8192; -+ if (rec->stride_Y > tmp || rec->stride_UV > 2*1024) - return -EINVAL; - - /* check buffer dimensions */ - switch (rec->flags & I915_OVERLAY_TYPE_MASK) { -- case I915_OVERLAY_RGB: -- case I915_OVERLAY_YUV_PACKED: -- /* always 4 Y values per depth pixels */ -- if (packed_width_bytes(rec->flags, rec->src_width) -- > rec->stride_Y) -- return -EINVAL; -- -- tmp = rec->stride_Y*rec->src_height; -- if (rec->offset_Y + tmp > new_bo->size) -- return -EINVAL; -- break; -- case I915_OVERLAY_YUV_PLANAR: -- if (rec->src_width > rec->stride_Y) -- return -EINVAL; -- if (rec->src_width/uv_hscale > rec->stride_UV) -- return -EINVAL; -- -- tmp = rec->stride_Y*rec->src_height; -- if (rec->offset_Y + tmp > new_bo->size) -- return -EINVAL; -- tmp = rec->stride_UV*rec->src_height; -- tmp /= uv_vscale; -- if (rec->offset_U + tmp > new_bo->size -- || rec->offset_V + tmp > new_bo->size) -- return -EINVAL; -- break; -+ case I915_OVERLAY_RGB: -+ case I915_OVERLAY_YUV_PACKED: -+ /* always 4 Y values per depth pixels */ -+ if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y) -+ return -EINVAL; -+ -+ tmp = rec->stride_Y*rec->src_height; -+ if (rec->offset_Y + tmp > new_bo->size) -+ return -EINVAL; -+ break; -+ -+ case I915_OVERLAY_YUV_PLANAR: -+ if (rec->src_width > rec->stride_Y) -+ return -EINVAL; -+ if (rec->src_width/uv_hscale > rec->stride_UV) -+ return -EINVAL; -+ -+ tmp = rec->stride_Y * rec->src_height; -+ if (rec->offset_Y + tmp > new_bo->size) -+ return -EINVAL; -+ -+ tmp = rec->stride_UV * (rec->src_height / uv_vscale); -+ if (rec->offset_U + tmp > new_bo->size || -+ rec->offset_V + tmp > new_bo->size) -+ return -EINVAL; -+ break; - } - - return 0; - } - -+/** -+ * Return the pipe currently connected to the panel fitter, -+ * or -1 if the panel fitter is not present or not in use -+ */ -+static int intel_panel_fitter_pipe(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 pfit_control; -+ -+ /* i830 doesn't have a panel fitter */ -+ if (IS_I830(dev)) -+ return -1; -+ -+ pfit_control = I915_READ(PFIT_CONTROL); -+ -+ /* See if the panel fitter is in use */ -+ if ((pfit_control & PFIT_ENABLE) == 0) -+ return -1; -+ -+ /* 965 can place panel fitter on either pipe */ -+ if (IS_GEN4(dev)) -+ return (pfit_control >> 29) & 0x3; -+ -+ /* older chips can only use pipe 1 */ -+ return 1; -+} -+ - int intel_overlay_put_image(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -@@ -1068,7 +1105,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, - mutex_lock(&dev->mode_config.mutex); - mutex_lock(&dev->struct_mutex); - -- ret = intel_overlay_switch_off(overlay); -+ ret = intel_overlay_switch_off(overlay, true); - - mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->mode_config.mutex); -@@ -1081,7 +1118,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, - return -ENOMEM; - - drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, -- DRM_MODE_OBJECT_CRTC); -+ DRM_MODE_OBJECT_CRTC); - if (!drmmode_obj) { - ret = -ENOENT; - goto out_free; -@@ -1089,7 +1126,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, - crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); - - new_bo = drm_gem_object_lookup(dev, file_priv, -- put_image_rec->bo_handle); -+ put_image_rec->bo_handle); - if (!new_bo) { - ret = -ENOENT; - goto out_free; -@@ -1098,15 +1135,13 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, - mutex_lock(&dev->mode_config.mutex); - mutex_lock(&dev->struct_mutex); - -- if (overlay->hw_wedged) { -- ret = intel_overlay_recover_from_interrupt(overlay, 1); -- if (ret != 0) -- goto out_unlock; -- } -+ ret = intel_overlay_recover_from_interrupt(overlay, true); -+ if (ret != 0) -+ goto out_unlock; - - if (overlay->crtc != crtc) { - struct drm_display_mode *mode = &crtc->base.mode; -- ret = intel_overlay_switch_off(overlay); -+ ret = intel_overlay_switch_off(overlay, true); - if (ret != 0) - goto out_unlock; - -@@ -1117,9 +1152,9 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, - overlay->crtc = crtc; - crtc->overlay = overlay; - -- if (intel_panel_fitter_pipe(dev) == crtc->pipe -- /* and line to wide, i.e. one-line-mode */ -- && mode->hdisplay > 1024) { -+ /* line too wide, i.e. one-line-mode */ -+ if (mode->hdisplay > 1024 && -+ intel_panel_fitter_pipe(dev) == crtc->pipe) { - overlay->pfit_active = 1; - update_pfit_vscale_ratio(overlay); - } else -@@ -1132,10 +1167,10 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, - - if (overlay->pfit_active) { - params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / -- overlay->pfit_vscale_ratio); -+ overlay->pfit_vscale_ratio); - /* shifting right rounds downwards, so add 1 */ - params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / -- overlay->pfit_vscale_ratio) + 1; -+ overlay->pfit_vscale_ratio) + 1; - } else { - params->dst_y = put_image_rec->dst_y; - params->dst_h = put_image_rec->dst_height; -@@ -1147,8 +1182,8 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, - params->src_h = put_image_rec->src_height; - params->src_scan_w = put_image_rec->src_scan_width; - params->src_scan_h = put_image_rec->src_scan_height; -- if (params->src_scan_h > params->src_h -- || params->src_scan_w > params->src_w) { -+ if (params->src_scan_h > params->src_h || -+ params->src_scan_w > params->src_w) { - ret = -EINVAL; - goto out_unlock; - } -@@ -1204,7 +1239,7 @@ static bool check_gamma_bounds(u32 gamma1, u32 gamma2) - return false; - - for (i = 0; i < 3; i++) { -- if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) -+ if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) - return false; - } - -@@ -1225,16 +1260,18 @@ static bool check_gamma5_errata(u32 gamma5) - - static int check_gamma(struct drm_intel_overlay_attrs *attrs) - { -- if (!check_gamma_bounds(0, attrs->gamma0) -- || !check_gamma_bounds(attrs->gamma0, attrs->gamma1) -- || !check_gamma_bounds(attrs->gamma1, attrs->gamma2) -- || !check_gamma_bounds(attrs->gamma2, attrs->gamma3) -- || !check_gamma_bounds(attrs->gamma3, attrs->gamma4) -- || !check_gamma_bounds(attrs->gamma4, attrs->gamma5) -- || !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) -+ if (!check_gamma_bounds(0, attrs->gamma0) || -+ !check_gamma_bounds(attrs->gamma0, attrs->gamma1) || -+ !check_gamma_bounds(attrs->gamma1, attrs->gamma2) || -+ !check_gamma_bounds(attrs->gamma2, attrs->gamma3) || -+ !check_gamma_bounds(attrs->gamma3, attrs->gamma4) || -+ !check_gamma_bounds(attrs->gamma4, attrs->gamma5) || -+ !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) - return -EINVAL; -+ - if (!check_gamma5_errata(attrs->gamma5)) - return -EINVAL; -+ - return 0; - } - -@@ -1261,13 +1298,14 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, - mutex_lock(&dev->mode_config.mutex); - mutex_lock(&dev->struct_mutex); - -+ ret = -EINVAL; - if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { -- attrs->color_key = overlay->color_key; -+ attrs->color_key = overlay->color_key; - attrs->brightness = overlay->brightness; -- attrs->contrast = overlay->contrast; -+ attrs->contrast = overlay->contrast; - attrs->saturation = overlay->saturation; - -- if (IS_I9XX(dev)) { -+ if (!IS_GEN2(dev)) { - attrs->gamma0 = I915_READ(OGAMC0); - attrs->gamma1 = I915_READ(OGAMC1); - attrs->gamma2 = I915_READ(OGAMC2); -@@ -1275,29 +1313,20 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, - attrs->gamma4 = I915_READ(OGAMC4); - attrs->gamma5 = I915_READ(OGAMC5); - } -- ret = 0; - } else { -- overlay->color_key = attrs->color_key; -- if (attrs->brightness >= -128 && attrs->brightness <= 127) { -- overlay->brightness = attrs->brightness; -- } else { -- ret = -EINVAL; -+ if (attrs->brightness < -128 || attrs->brightness > 127) - goto out_unlock; -- } -- if (attrs->contrast <= 255) { -- overlay->contrast = attrs->contrast; -- } else { -- ret = -EINVAL; -+ if (attrs->contrast > 255) - goto out_unlock; -- } -- if (attrs->saturation <= 1023) { -- overlay->saturation = attrs->saturation; -- } else { -- ret = -EINVAL; -+ if (attrs->saturation > 1023) - goto out_unlock; -- } - -- regs = intel_overlay_map_regs_atomic(overlay); -+ overlay->color_key = attrs->color_key; -+ overlay->brightness = attrs->brightness; -+ overlay->contrast = attrs->contrast; -+ overlay->saturation = attrs->saturation; -+ -+ regs = intel_overlay_map_regs(overlay); - if (!regs) { - ret = -ENOMEM; - goto out_unlock; -@@ -1305,13 +1334,11 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, - - update_reg_attrs(overlay, regs); - -- intel_overlay_unmap_regs_atomic(overlay); -+ intel_overlay_unmap_regs(overlay, regs); - - if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { -- if (!IS_I9XX(dev)) { -- ret = -EINVAL; -+ if (IS_GEN2(dev)) - goto out_unlock; -- } - - if (overlay->active) { - ret = -EBUSY; -@@ -1319,7 +1346,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, - } - - ret = check_gamma(attrs); -- if (ret != 0) -+ if (ret) - goto out_unlock; - - I915_WRITE(OGAMC0, attrs->gamma0); -@@ -1329,9 +1356,9 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, - I915_WRITE(OGAMC4, attrs->gamma4); - I915_WRITE(OGAMC5, attrs->gamma5); - } -- ret = 0; - } - -+ ret = 0; - out_unlock: - mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->mode_config.mutex); -@@ -1347,7 +1374,7 @@ void intel_setup_overlay(struct drm_device *dev) - struct overlay_registers *regs; - int ret; - -- if (!OVERLAY_EXISTS(dev)) -+ if (!HAS_OVERLAY(dev)) - return; - - overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); -@@ -1360,22 +1387,28 @@ void intel_setup_overlay(struct drm_device *dev) - goto out_free; - overlay->reg_bo = to_intel_bo(reg_bo); - -- if (OVERLAY_NONPHYSICAL(dev)) { -- ret = i915_gem_object_pin(reg_bo, PAGE_SIZE); -- if (ret) { -- DRM_ERROR("failed to pin overlay register bo\n"); -- goto out_free_bo; -- } -- overlay->flip_addr = overlay->reg_bo->gtt_offset; -- } else { -+ if (OVERLAY_NEEDS_PHYSICAL(dev)) { - ret = i915_gem_attach_phys_object(dev, reg_bo, - I915_GEM_PHYS_OVERLAY_REGS, -- 0); -+ PAGE_SIZE); - if (ret) { - DRM_ERROR("failed to attach phys overlay regs\n"); - goto out_free_bo; - } - overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr; -+ } else { -+ ret = i915_gem_object_pin(reg_bo, PAGE_SIZE); -+ if (ret) { -+ DRM_ERROR("failed to pin overlay register bo\n"); -+ goto out_free_bo; -+ } -+ overlay->flip_addr = overlay->reg_bo->gtt_offset; -+ -+ ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); -+ if (ret) { -+ DRM_ERROR("failed to move overlay register bo into the GTT\n"); -+ goto out_unpin_bo; -+ } - } - - /* init all values */ -@@ -1384,21 +1417,22 @@ void intel_setup_overlay(struct drm_device *dev) - overlay->contrast = 75; - overlay->saturation = 146; - -- regs = intel_overlay_map_regs_atomic(overlay); -+ regs = intel_overlay_map_regs(overlay); - if (!regs) - goto out_free_bo; - - memset(regs, 0, sizeof(struct overlay_registers)); - update_polyphase_filter(regs); -- - update_reg_attrs(overlay, regs); - -- intel_overlay_unmap_regs_atomic(overlay); -+ intel_overlay_unmap_regs(overlay, regs); - - dev_priv->overlay = overlay; - DRM_INFO("initialized overlay support\n"); - return; - -+out_unpin_bo: -+ i915_gem_object_unpin(reg_bo); - out_free_bo: - drm_gem_object_unreference(reg_bo); - out_free: -@@ -1408,18 +1442,23 @@ out_free: - - void intel_cleanup_overlay(struct drm_device *dev) - { -- drm_i915_private_t *dev_priv = dev->dev_private; -+ drm_i915_private_t *dev_priv = dev->dev_private; - -- if (dev_priv->overlay) { -- /* The bo's should be free'd by the generic code already. -- * Furthermore modesetting teardown happens beforehand so the -- * hardware should be off already */ -- BUG_ON(dev_priv->overlay->active); -+ if (!dev_priv->overlay) -+ return; - -- kfree(dev_priv->overlay); -- } -+ /* The bo's should be free'd by the generic code already. -+ * Furthermore modesetting teardown happens beforehand so the -+ * hardware should be off already */ -+ BUG_ON(dev_priv->overlay->active); -+ -+ drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base); -+ kfree(dev_priv->overlay); - } - -+#ifdef CONFIG_DEBUG_FS -+#include -+ - struct intel_overlay_error_state { - struct overlay_registers regs; - unsigned long base; -@@ -1427,6 +1466,30 @@ struct intel_overlay_error_state { - u32 isr; - }; - -+static struct overlay_registers * -+intel_overlay_map_regs_atomic(struct intel_overlay *overlay) -+{ -+ drm_i915_private_t *dev_priv = overlay->dev->dev_private; -+ struct overlay_registers *regs; -+ -+ if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) -+ regs = overlay->reg_bo->phys_obj->handle->vaddr; -+ else -+ regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, -+ overlay->reg_bo->gtt_offset, -+ KM_USER0); -+ -+ return regs; -+} -+ -+static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay, -+ struct overlay_registers *regs) -+{ -+ if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev)) -+ io_mapping_unmap_atomic(regs, KM_USER0); -+} -+ -+ - struct intel_overlay_error_state * - intel_overlay_capture_error_state(struct drm_device *dev) - { -@@ -1444,17 +1507,17 @@ intel_overlay_capture_error_state(struct drm_device *dev) - - error->dovsta = I915_READ(DOVSTA); - error->isr = I915_READ(ISR); -- if (OVERLAY_NONPHYSICAL(overlay->dev)) -- error->base = (long) overlay->reg_bo->gtt_offset; -- else -+ if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) - error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; -+ else -+ error->base = (long) overlay->reg_bo->gtt_offset; - - regs = intel_overlay_map_regs_atomic(overlay); - if (!regs) - goto err; - - memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers)); -- intel_overlay_unmap_regs_atomic(overlay); -+ intel_overlay_unmap_regs_atomic(overlay, regs); - - return error; - -@@ -1515,3 +1578,4 @@ intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_s - P(UVSCALEV); - #undef P - } -+#endif -diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c -index e7f5299..92ff8f3 100644 ---- a/drivers/gpu/drm/i915/intel_panel.c -+++ b/drivers/gpu/drm/i915/intel_panel.c -@@ -30,6 +30,8 @@ - - #include "intel_drv.h" - -+#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ -+ - void - intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, - struct drm_display_mode *adjusted_mode) -@@ -109,3 +111,110 @@ done: - dev_priv->pch_pf_pos = (x << 16) | y; - dev_priv->pch_pf_size = (width << 16) | height; - } -+ -+static int is_backlight_combination_mode(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ -+ if (INTEL_INFO(dev)->gen >= 4) -+ return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; -+ -+ if (IS_GEN2(dev)) -+ return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; -+ -+ return 0; -+} -+ -+u32 intel_panel_get_max_backlight(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 max; -+ -+ if (HAS_PCH_SPLIT(dev)) { -+ max = I915_READ(BLC_PWM_PCH_CTL2) >> 16; -+ } else { -+ max = I915_READ(BLC_PWM_CTL); -+ if (IS_PINEVIEW(dev)) { -+ max >>= 17; -+ } else { -+ max >>= 16; -+ if (INTEL_INFO(dev)->gen < 4) -+ max &= ~1; -+ } -+ -+ if (is_backlight_combination_mode(dev)) -+ max *= 0xff; -+ } -+ -+ if (max == 0) { -+ /* XXX add code here to query mode clock or hardware clock -+ * and program max PWM appropriately. -+ */ -+ DRM_ERROR("fixme: max PWM is zero.\n"); -+ max = 1; -+ } -+ -+ DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); -+ return max; -+} -+ -+u32 intel_panel_get_backlight(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 val; -+ -+ if (HAS_PCH_SPLIT(dev)) { -+ val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; -+ } else { -+ val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; -+ if (IS_PINEVIEW(dev)) -+ val >>= 1; -+ -+ if (is_backlight_combination_mode(dev)){ -+ u8 lbpc; -+ -+ val &= ~1; -+ pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); -+ val *= lbpc; -+ val >>= 1; -+ } -+ } -+ -+ DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); -+ return val; -+} -+ -+static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; -+ I915_WRITE(BLC_PWM_CPU_CTL, val | level); -+} -+ -+void intel_panel_set_backlight(struct drm_device *dev, u32 level) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ u32 tmp; -+ -+ DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); -+ -+ if (HAS_PCH_SPLIT(dev)) -+ return intel_pch_panel_set_backlight(dev, level); -+ -+ if (is_backlight_combination_mode(dev)){ -+ u32 max = intel_panel_get_max_backlight(dev); -+ u8 lpbc; -+ -+ lpbc = level * 0xfe / max + 1; -+ level /= lpbc; -+ pci_write_config_byte(dev->pdev, PCI_LBPC, lpbc); -+ } -+ -+ tmp = I915_READ(BLC_PWM_CTL); -+ if (IS_PINEVIEW(dev)) { -+ tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); -+ level <<= 1; -+ } else -+ tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; -+ I915_WRITE(BLC_PWM_CTL, tmp | level); -+} -diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c -index cb3508f..b83306f 100644 ---- a/drivers/gpu/drm/i915/intel_ringbuffer.c -+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c -@@ -32,6 +32,7 @@ - #include "i915_drv.h" - #include "i915_drm.h" - #include "i915_trace.h" -+#include "intel_drv.h" - - static u32 i915_gem_get_seqno(struct drm_device *dev) - { -@@ -49,9 +50,9 @@ static u32 i915_gem_get_seqno(struct drm_device *dev) - - static void - render_ring_flush(struct drm_device *dev, -- struct intel_ring_buffer *ring, -- u32 invalidate_domains, -- u32 flush_domains) -+ struct intel_ring_buffer *ring, -+ u32 invalidate_domains, -+ u32 flush_domains) - { - drm_i915_private_t *dev_priv = dev->dev_private; - u32 cmd; -@@ -97,7 +98,7 @@ render_ring_flush(struct drm_device *dev, - if ((invalidate_domains|flush_domains) & - I915_GEM_DOMAIN_RENDER) - cmd &= ~MI_NO_WRITE_FLUSH; -- if (!IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen < 4) { - /* - * On the 965, the sampler cache always gets flushed - * and this bit is reserved. -@@ -118,38 +119,26 @@ render_ring_flush(struct drm_device *dev, - } - } - --static unsigned int render_ring_get_head(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- return I915_READ(PRB0_HEAD) & HEAD_ADDR; --} -- --static unsigned int render_ring_get_tail(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+static void ring_write_tail(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ u32 value) - { - drm_i915_private_t *dev_priv = dev->dev_private; -- return I915_READ(PRB0_TAIL) & TAIL_ADDR; -+ I915_WRITE_TAIL(ring, value); - } - --static unsigned int render_ring_get_active_head(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+u32 intel_ring_get_active_head(struct drm_device *dev, -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; -- u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; -+ u32 acthd_reg = INTEL_INFO(dev)->gen >= 4 ? -+ RING_ACTHD(ring->mmio_base) : ACTHD; - - return I915_READ(acthd_reg); - } - --static void render_ring_advance_ring(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- I915_WRITE(PRB0_TAIL, ring->tail); --} -- - static int init_ring_common(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - u32 head; - drm_i915_private_t *dev_priv = dev->dev_private; -@@ -157,57 +146,57 @@ static int init_ring_common(struct drm_device *dev, - obj_priv = to_intel_bo(ring->gem_object); - - /* Stop the ring if it's running. */ -- I915_WRITE(ring->regs.ctl, 0); -- I915_WRITE(ring->regs.head, 0); -- I915_WRITE(ring->regs.tail, 0); -+ I915_WRITE_CTL(ring, 0); -+ I915_WRITE_HEAD(ring, 0); -+ ring->write_tail(dev, ring, 0); - - /* Initialize the ring. */ -- I915_WRITE(ring->regs.start, obj_priv->gtt_offset); -- head = ring->get_head(dev, ring); -+ I915_WRITE_START(ring, obj_priv->gtt_offset); -+ head = I915_READ_HEAD(ring) & HEAD_ADDR; - - /* G45 ring initialization fails to reset head to zero */ - if (head != 0) { - DRM_ERROR("%s head not reset to zero " - "ctl %08x head %08x tail %08x start %08x\n", - ring->name, -- I915_READ(ring->regs.ctl), -- I915_READ(ring->regs.head), -- I915_READ(ring->regs.tail), -- I915_READ(ring->regs.start)); -+ I915_READ_CTL(ring), -+ I915_READ_HEAD(ring), -+ I915_READ_TAIL(ring), -+ I915_READ_START(ring)); - -- I915_WRITE(ring->regs.head, 0); -+ I915_WRITE_HEAD(ring, 0); - - DRM_ERROR("%s head forced to zero " - "ctl %08x head %08x tail %08x start %08x\n", - ring->name, -- I915_READ(ring->regs.ctl), -- I915_READ(ring->regs.head), -- I915_READ(ring->regs.tail), -- I915_READ(ring->regs.start)); -+ I915_READ_CTL(ring), -+ I915_READ_HEAD(ring), -+ I915_READ_TAIL(ring), -+ I915_READ_START(ring)); - } - -- I915_WRITE(ring->regs.ctl, -+ I915_WRITE_CTL(ring, - ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) -- | RING_NO_REPORT | RING_VALID); -+ | RING_REPORT_64K | RING_VALID); - -- head = I915_READ(ring->regs.head) & HEAD_ADDR; -+ head = I915_READ_HEAD(ring) & HEAD_ADDR; - /* If the head is still not zero, the ring is dead */ - if (head != 0) { - DRM_ERROR("%s initialization failed " - "ctl %08x head %08x tail %08x start %08x\n", - ring->name, -- I915_READ(ring->regs.ctl), -- I915_READ(ring->regs.head), -- I915_READ(ring->regs.tail), -- I915_READ(ring->regs.start)); -+ I915_READ_CTL(ring), -+ I915_READ_HEAD(ring), -+ I915_READ_TAIL(ring), -+ I915_READ_START(ring)); - return -EIO; - } - - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - i915_kernel_lost_context(dev); - else { -- ring->head = ring->get_head(dev, ring); -- ring->tail = ring->get_tail(dev, ring); -+ ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; -+ ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->size; -@@ -216,13 +205,13 @@ static int init_ring_common(struct drm_device *dev, - } - - static int init_render_ring(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; - int ret = init_ring_common(dev, ring); - int mode; - -- if (IS_I9XX(dev) && !IS_GEN3(dev)) { -+ if (INTEL_INFO(dev)->gen > 3) { - mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; - if (IS_GEN6(dev)) - mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; -@@ -250,9 +239,8 @@ do { \ - */ - static u32 - render_ring_add_request(struct drm_device *dev, -- struct intel_ring_buffer *ring, -- struct drm_file *file_priv, -- u32 flush_domains) -+ struct intel_ring_buffer *ring, -+ u32 flush_domains) - { - drm_i915_private_t *dev_priv = dev->dev_private; - u32 seqno; -@@ -315,8 +303,8 @@ render_ring_add_request(struct drm_device *dev, - } - - static u32 --render_ring_get_gem_seqno(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+render_ring_get_seqno(struct drm_device *dev, -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - if (HAS_PIPE_CONTROL(dev)) -@@ -327,7 +315,7 @@ render_ring_get_gem_seqno(struct drm_device *dev, - - static void - render_ring_get_user_irq(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; -@@ -344,7 +332,7 @@ render_ring_get_user_irq(struct drm_device *dev, - - static void - render_ring_put_user_irq(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; -@@ -360,21 +348,23 @@ render_ring_put_user_irq(struct drm_device *dev, - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); - } - --static void render_setup_status_page(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+void intel_ring_setup_status_page(struct drm_device *dev, -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; - if (IS_GEN6(dev)) { -- I915_WRITE(HWS_PGA_GEN6, ring->status_page.gfx_addr); -- I915_READ(HWS_PGA_GEN6); /* posting read */ -+ I915_WRITE(RING_HWS_PGA_GEN6(ring->mmio_base), -+ ring->status_page.gfx_addr); -+ I915_READ(RING_HWS_PGA_GEN6(ring->mmio_base)); /* posting read */ - } else { -- I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); -- I915_READ(HWS_PGA); /* posting read */ -+ I915_WRITE(RING_HWS_PGA(ring->mmio_base), -+ ring->status_page.gfx_addr); -+ I915_READ(RING_HWS_PGA(ring->mmio_base)); /* posting read */ - } - - } - --void -+static void - bsd_ring_flush(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 invalidate_domains, -@@ -386,45 +376,16 @@ bsd_ring_flush(struct drm_device *dev, - intel_ring_advance(dev, ring); - } - --static inline unsigned int bsd_ring_get_head(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- return I915_READ(BSD_RING_HEAD) & HEAD_ADDR; --} -- --static inline unsigned int bsd_ring_get_tail(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- return I915_READ(BSD_RING_TAIL) & TAIL_ADDR; --} -- --static inline unsigned int bsd_ring_get_active_head(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- return I915_READ(BSD_RING_ACTHD); --} -- --static inline void bsd_ring_advance_ring(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- I915_WRITE(BSD_RING_TAIL, ring->tail); --} -- - static int init_bsd_ring(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - return init_ring_common(dev, ring); - } - - static u32 --bsd_ring_add_request(struct drm_device *dev, -- struct intel_ring_buffer *ring, -- struct drm_file *file_priv, -- u32 flush_domains) -+ring_add_request(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ u32 flush_domains) - { - u32 seqno; - -@@ -443,40 +404,32 @@ bsd_ring_add_request(struct drm_device *dev, - return seqno; - } - --static void bsd_setup_status_page(struct drm_device *dev, -- struct intel_ring_buffer *ring) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- I915_WRITE(BSD_HWS_PGA, ring->status_page.gfx_addr); -- I915_READ(BSD_HWS_PGA); --} -- - static void - bsd_ring_get_user_irq(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - /* do nothing */ - } - static void - bsd_ring_put_user_irq(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - /* do nothing */ - } - - static u32 --bsd_ring_get_gem_seqno(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ring_status_page_get_seqno(struct drm_device *dev, -+ struct intel_ring_buffer *ring) - { - return intel_read_status_page(ring, I915_GEM_HWS_INDEX); - } - - static int --bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, -- struct intel_ring_buffer *ring, -- struct drm_i915_gem_execbuffer2 *exec, -- struct drm_clip_rect *cliprects, -- uint64_t exec_offset) -+ring_dispatch_gem_execbuffer(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ struct drm_i915_gem_execbuffer2 *exec, -+ struct drm_clip_rect *cliprects, -+ uint64_t exec_offset) - { - uint32_t exec_start; - exec_start = (uint32_t) exec_offset + exec->batch_start_offset; -@@ -488,13 +441,12 @@ bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, - return 0; - } - -- - static int - render_ring_dispatch_gem_execbuffer(struct drm_device *dev, -- struct intel_ring_buffer *ring, -- struct drm_i915_gem_execbuffer2 *exec, -- struct drm_clip_rect *cliprects, -- uint64_t exec_offset) -+ struct intel_ring_buffer *ring, -+ struct drm_i915_gem_execbuffer2 *exec, -+ struct drm_clip_rect *cliprects, -+ uint64_t exec_offset) - { - drm_i915_private_t *dev_priv = dev->dev_private; - int nbox = exec->num_cliprects; -@@ -523,8 +475,8 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev, - intel_ring_emit(dev, ring, exec_start + exec_len - 4); - intel_ring_emit(dev, ring, 0); - } else { -- intel_ring_begin(dev, ring, 4); -- if (IS_I965G(dev)) { -+ intel_ring_begin(dev, ring, 2); -+ if (INTEL_INFO(dev)->gen >= 4) { - intel_ring_emit(dev, ring, - MI_BATCH_BUFFER_START | (2 << 6) - | MI_BATCH_NON_SECURE_I965); -@@ -539,7 +491,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev, - intel_ring_advance(dev, ring); - } - -- if (IS_G4X(dev) || IS_IRONLAKE(dev)) { -+ if (IS_G4X(dev) || IS_GEN5(dev)) { - intel_ring_begin(dev, ring, 2); - intel_ring_emit(dev, ring, MI_FLUSH | - MI_NO_WRITE_FLUSH | -@@ -553,7 +505,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev, - } - - static void cleanup_status_page(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; -@@ -573,7 +525,7 @@ static void cleanup_status_page(struct drm_device *dev, - } - - static int init_status_page(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; -@@ -603,7 +555,7 @@ static int init_status_page(struct drm_device *dev, - ring->status_page.obj = obj; - memset(ring->status_page.page_addr, 0, PAGE_SIZE); - -- ring->setup_status_page(dev, ring); -+ intel_ring_setup_status_page(dev, ring); - DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", - ring->name, ring->status_page.gfx_addr); - -@@ -617,15 +569,18 @@ err: - return ret; - } - -- - int intel_init_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { -+ struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - struct drm_gem_object *obj; - int ret; - - ring->dev = dev; -+ INIT_LIST_HEAD(&ring->active_list); -+ INIT_LIST_HEAD(&ring->request_list); -+ INIT_LIST_HEAD(&ring->gpu_write_list); - - if (I915_NEED_GFX_HWS(dev)) { - ret = init_status_page(dev, ring); -@@ -642,7 +597,7 @@ int intel_init_ring_buffer(struct drm_device *dev, - - ring->gem_object = obj; - -- ret = i915_gem_object_pin(obj, ring->alignment); -+ ret = i915_gem_object_pin(obj, PAGE_SIZE); - if (ret) - goto err_unref; - -@@ -668,14 +623,12 @@ int intel_init_ring_buffer(struct drm_device *dev, - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - i915_kernel_lost_context(dev); - else { -- ring->head = ring->get_head(dev, ring); -- ring->tail = ring->get_tail(dev, ring); -+ ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; -+ ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->size; - } -- INIT_LIST_HEAD(&ring->active_list); -- INIT_LIST_HEAD(&ring->request_list); - return ret; - - err_unmap: -@@ -691,7 +644,7 @@ err_hws: - } - - void intel_cleanup_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - if (ring->gem_object == NULL) - return; -@@ -701,11 +654,15 @@ void intel_cleanup_ring_buffer(struct drm_device *dev, - i915_gem_object_unpin(ring->gem_object); - drm_gem_object_unreference(ring->gem_object); - ring->gem_object = NULL; -+ -+ if (ring->cleanup) -+ ring->cleanup(ring); -+ - cleanup_status_page(dev, ring); - } - --int intel_wrap_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+static int intel_wrap_ring_buffer(struct drm_device *dev, -+ struct intel_ring_buffer *ring) - { - unsigned int *virt; - int rem; -@@ -731,14 +688,26 @@ int intel_wrap_ring_buffer(struct drm_device *dev, - } - - int intel_wait_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring, int n) -+ struct intel_ring_buffer *ring, int n) - { - unsigned long end; -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ u32 head; -+ -+ head = intel_read_status_page(ring, 4); -+ if (head) { -+ ring->head = head & HEAD_ADDR; -+ ring->space = ring->head - (ring->tail + 8); -+ if (ring->space < 0) -+ ring->space += ring->size; -+ if (ring->space >= n) -+ return 0; -+ } - - trace_i915_ring_wait_begin (dev); - end = jiffies + 3 * HZ; - do { -- ring->head = ring->get_head(dev, ring); -+ ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->size; -@@ -753,14 +722,15 @@ int intel_wait_ring_buffer(struct drm_device *dev, - master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; - } - -- yield(); -+ msleep(1); - } while (!time_after(jiffies, end)); - trace_i915_ring_wait_end (dev); - return -EBUSY; - } - - void intel_ring_begin(struct drm_device *dev, -- struct intel_ring_buffer *ring, int num_dwords) -+ struct intel_ring_buffer *ring, -+ int num_dwords) - { - int n = 4*num_dwords; - if (unlikely(ring->tail + n > ring->size)) -@@ -772,97 +742,287 @@ void intel_ring_begin(struct drm_device *dev, - } - - void intel_ring_advance(struct drm_device *dev, -- struct intel_ring_buffer *ring) -+ struct intel_ring_buffer *ring) - { - ring->tail &= ring->size - 1; -- ring->advance_ring(dev, ring); -+ ring->write_tail(dev, ring, ring->tail); - } - --void intel_fill_struct(struct drm_device *dev, -- struct intel_ring_buffer *ring, -- void *data, -- unsigned int len) --{ -- unsigned int *virt = ring->virtual_start + ring->tail; -- BUG_ON((len&~(4-1)) != 0); -- intel_ring_begin(dev, ring, len/4); -- memcpy(virt, data, len); -- ring->tail += len; -- ring->tail &= ring->size - 1; -- ring->space -= len; -- intel_ring_advance(dev, ring); --} -- --struct intel_ring_buffer render_ring = { -+static const struct intel_ring_buffer render_ring = { - .name = "render ring", -- .regs = { -- .ctl = PRB0_CTL, -- .head = PRB0_HEAD, -- .tail = PRB0_TAIL, -- .start = PRB0_START -- }, -- .ring_flag = I915_EXEC_RENDER, -+ .id = RING_RENDER, -+ .mmio_base = RENDER_RING_BASE, - .size = 32 * PAGE_SIZE, -- .alignment = PAGE_SIZE, -- .virtual_start = NULL, -- .dev = NULL, -- .gem_object = NULL, -- .head = 0, -- .tail = 0, -- .space = 0, -- .user_irq_refcount = 0, -- .irq_gem_seqno = 0, -- .waiting_gem_seqno = 0, -- .setup_status_page = render_setup_status_page, - .init = init_render_ring, -- .get_head = render_ring_get_head, -- .get_tail = render_ring_get_tail, -- .get_active_head = render_ring_get_active_head, -- .advance_ring = render_ring_advance_ring, -+ .write_tail = ring_write_tail, - .flush = render_ring_flush, - .add_request = render_ring_add_request, -- .get_gem_seqno = render_ring_get_gem_seqno, -+ .get_seqno = render_ring_get_seqno, - .user_irq_get = render_ring_get_user_irq, - .user_irq_put = render_ring_put_user_irq, - .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer, -- .status_page = {NULL, 0, NULL}, -- .map = {0,} - }; - - /* ring buffer for bit-stream decoder */ - --struct intel_ring_buffer bsd_ring = { -+static const struct intel_ring_buffer bsd_ring = { - .name = "bsd ring", -- .regs = { -- .ctl = BSD_RING_CTL, -- .head = BSD_RING_HEAD, -- .tail = BSD_RING_TAIL, -- .start = BSD_RING_START -- }, -- .ring_flag = I915_EXEC_BSD, -+ .id = RING_BSD, -+ .mmio_base = BSD_RING_BASE, - .size = 32 * PAGE_SIZE, -- .alignment = PAGE_SIZE, -- .virtual_start = NULL, -- .dev = NULL, -- .gem_object = NULL, -- .head = 0, -- .tail = 0, -- .space = 0, -- .user_irq_refcount = 0, -- .irq_gem_seqno = 0, -- .waiting_gem_seqno = 0, -- .setup_status_page = bsd_setup_status_page, - .init = init_bsd_ring, -- .get_head = bsd_ring_get_head, -- .get_tail = bsd_ring_get_tail, -- .get_active_head = bsd_ring_get_active_head, -- .advance_ring = bsd_ring_advance_ring, -+ .write_tail = ring_write_tail, - .flush = bsd_ring_flush, -- .add_request = bsd_ring_add_request, -- .get_gem_seqno = bsd_ring_get_gem_seqno, -+ .add_request = ring_add_request, -+ .get_seqno = ring_status_page_get_seqno, - .user_irq_get = bsd_ring_get_user_irq, - .user_irq_put = bsd_ring_put_user_irq, -- .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer, -- .status_page = {NULL, 0, NULL}, -- .map = {0,} -+ .dispatch_gem_execbuffer = ring_dispatch_gem_execbuffer, -+}; -+ -+ -+static void gen6_bsd_ring_write_tail(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ u32 value) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ -+ /* Every tail move must follow the sequence below */ -+ I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, -+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | -+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE); -+ I915_WRITE(GEN6_BSD_RNCID, 0x0); -+ -+ if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & -+ GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, -+ 50)) -+ DRM_ERROR("timed out waiting for IDLE Indicator\n"); -+ -+ I915_WRITE_TAIL(ring, value); -+ I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, -+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | -+ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); -+} -+ -+static void gen6_ring_flush(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ u32 invalidate_domains, -+ u32 flush_domains) -+{ -+ intel_ring_begin(dev, ring, 4); -+ intel_ring_emit(dev, ring, MI_FLUSH_DW); -+ intel_ring_emit(dev, ring, 0); -+ intel_ring_emit(dev, ring, 0); -+ intel_ring_emit(dev, ring, 0); -+ intel_ring_advance(dev, ring); -+} -+ -+static int -+gen6_ring_dispatch_gem_execbuffer(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ struct drm_i915_gem_execbuffer2 *exec, -+ struct drm_clip_rect *cliprects, -+ uint64_t exec_offset) -+{ -+ uint32_t exec_start; -+ -+ exec_start = (uint32_t) exec_offset + exec->batch_start_offset; -+ -+ intel_ring_begin(dev, ring, 2); -+ intel_ring_emit(dev, ring, -+ MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); -+ /* bit0-7 is the length on GEN6+ */ -+ intel_ring_emit(dev, ring, exec_start); -+ intel_ring_advance(dev, ring); -+ -+ return 0; -+} -+ -+/* ring buffer for Video Codec for Gen6+ */ -+static const struct intel_ring_buffer gen6_bsd_ring = { -+ .name = "gen6 bsd ring", -+ .id = RING_BSD, -+ .mmio_base = GEN6_BSD_RING_BASE, -+ .size = 32 * PAGE_SIZE, -+ .init = init_bsd_ring, -+ .write_tail = gen6_bsd_ring_write_tail, -+ .flush = gen6_ring_flush, -+ .add_request = ring_add_request, -+ .get_seqno = ring_status_page_get_seqno, -+ .user_irq_get = bsd_ring_get_user_irq, -+ .user_irq_put = bsd_ring_put_user_irq, -+ .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, -+}; -+ -+/* Blitter support (SandyBridge+) */ -+ -+static void -+blt_ring_get_user_irq(struct drm_device *dev, -+ struct intel_ring_buffer *ring) -+{ -+ /* do nothing */ -+} -+static void -+blt_ring_put_user_irq(struct drm_device *dev, -+ struct intel_ring_buffer *ring) -+{ -+ /* do nothing */ -+} -+ -+ -+/* Workaround for some stepping of SNB, -+ * each time when BLT engine ring tail moved, -+ * the first command in the ring to be parsed -+ * should be MI_BATCH_BUFFER_START -+ */ -+#define NEED_BLT_WORKAROUND(dev) \ -+ (IS_GEN6(dev) && (dev->pdev->revision < 8)) -+ -+static inline struct drm_i915_gem_object * -+to_blt_workaround(struct intel_ring_buffer *ring) -+{ -+ return ring->private; -+} -+ -+static int blt_ring_init(struct drm_device *dev, -+ struct intel_ring_buffer *ring) -+{ -+ if (NEED_BLT_WORKAROUND(dev)) { -+ struct drm_i915_gem_object *obj; -+ u32 __iomem *ptr; -+ int ret; -+ -+ obj = to_intel_bo(i915_gem_alloc_object(dev, 4096)); -+ if (obj == NULL) -+ return -ENOMEM; -+ -+ ret = i915_gem_object_pin(&obj->base, 4096); -+ if (ret) { -+ drm_gem_object_unreference(&obj->base); -+ return ret; -+ } -+ -+ ptr = kmap(obj->pages[0]); -+ iowrite32(MI_BATCH_BUFFER_END, ptr); -+ iowrite32(MI_NOOP, ptr+1); -+ kunmap(obj->pages[0]); -+ -+ ret = i915_gem_object_set_to_gtt_domain(&obj->base, false); -+ if (ret) { -+ i915_gem_object_unpin(&obj->base); -+ drm_gem_object_unreference(&obj->base); -+ return ret; -+ } -+ -+ ring->private = obj; -+ } -+ -+ return init_ring_common(dev, ring); -+} -+ -+static void blt_ring_begin(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ int num_dwords) -+{ -+ if (ring->private) { -+ intel_ring_begin(dev, ring, num_dwords+2); -+ intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START); -+ intel_ring_emit(dev, ring, to_blt_workaround(ring)->gtt_offset); -+ } else -+ intel_ring_begin(dev, ring, 4); -+} -+ -+static void blt_ring_flush(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ u32 invalidate_domains, -+ u32 flush_domains) -+{ -+ blt_ring_begin(dev, ring, 4); -+ intel_ring_emit(dev, ring, MI_FLUSH_DW); -+ intel_ring_emit(dev, ring, 0); -+ intel_ring_emit(dev, ring, 0); -+ intel_ring_emit(dev, ring, 0); -+ intel_ring_advance(dev, ring); -+} -+ -+static u32 -+blt_ring_add_request(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ u32 flush_domains) -+{ -+ u32 seqno = i915_gem_get_seqno(dev); -+ -+ blt_ring_begin(dev, ring, 4); -+ intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX); -+ intel_ring_emit(dev, ring, -+ I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); -+ intel_ring_emit(dev, ring, seqno); -+ intel_ring_emit(dev, ring, MI_USER_INTERRUPT); -+ intel_ring_advance(dev, ring); -+ -+ DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno); -+ return seqno; -+} -+ -+static void blt_ring_cleanup(struct intel_ring_buffer *ring) -+{ -+ if (!ring->private) -+ return; -+ -+ i915_gem_object_unpin(ring->private); -+ drm_gem_object_unreference(ring->private); -+ ring->private = NULL; -+} -+ -+static const struct intel_ring_buffer gen6_blt_ring = { -+ .name = "blt ring", -+ .id = RING_BLT, -+ .mmio_base = BLT_RING_BASE, -+ .size = 32 * PAGE_SIZE, -+ .init = blt_ring_init, -+ .write_tail = ring_write_tail, -+ .flush = blt_ring_flush, -+ .add_request = blt_ring_add_request, -+ .get_seqno = ring_status_page_get_seqno, -+ .user_irq_get = blt_ring_get_user_irq, -+ .user_irq_put = blt_ring_put_user_irq, -+ .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, -+ .cleanup = blt_ring_cleanup, - }; -+ -+int intel_init_render_ring_buffer(struct drm_device *dev) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ -+ dev_priv->render_ring = render_ring; -+ -+ if (!I915_NEED_GFX_HWS(dev)) { -+ dev_priv->render_ring.status_page.page_addr -+ = dev_priv->status_page_dmah->vaddr; -+ memset(dev_priv->render_ring.status_page.page_addr, -+ 0, PAGE_SIZE); -+ } -+ -+ return intel_init_ring_buffer(dev, &dev_priv->render_ring); -+} -+ -+int intel_init_bsd_ring_buffer(struct drm_device *dev) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ -+ if (IS_GEN6(dev)) -+ dev_priv->bsd_ring = gen6_bsd_ring; -+ else -+ dev_priv->bsd_ring = bsd_ring; -+ -+ return intel_init_ring_buffer(dev, &dev_priv->bsd_ring); -+} -+ -+int intel_init_blt_ring_buffer(struct drm_device *dev) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ -+ dev_priv->blt_ring = gen6_blt_ring; -+ -+ return intel_init_ring_buffer(dev, &dev_priv->blt_ring); -+} -diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h -index 525e7d3..3126c26 100644 ---- a/drivers/gpu/drm/i915/intel_ringbuffer.h -+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h -@@ -7,25 +7,32 @@ struct intel_hw_status_page { - struct drm_gem_object *obj; - }; - -+#define I915_READ_TAIL(ring) I915_READ(RING_TAIL(ring->mmio_base)) -+#define I915_WRITE_TAIL(ring, val) I915_WRITE(RING_TAIL(ring->mmio_base), val) -+#define I915_READ_START(ring) I915_READ(RING_START(ring->mmio_base)) -+#define I915_WRITE_START(ring, val) I915_WRITE(RING_START(ring->mmio_base), val) -+#define I915_READ_HEAD(ring) I915_READ(RING_HEAD(ring->mmio_base)) -+#define I915_WRITE_HEAD(ring, val) I915_WRITE(RING_HEAD(ring->mmio_base), val) -+#define I915_READ_CTL(ring) I915_READ(RING_CTL(ring->mmio_base)) -+#define I915_WRITE_CTL(ring, val) I915_WRITE(RING_CTL(ring->mmio_base), val) -+ - struct drm_i915_gem_execbuffer2; - struct intel_ring_buffer { - const char *name; -- struct ring_regs { -- u32 ctl; -- u32 head; -- u32 tail; -- u32 start; -- } regs; -- unsigned int ring_flag; -+ enum intel_ring_id { -+ RING_RENDER = 0x1, -+ RING_BSD = 0x2, -+ RING_BLT = 0x4, -+ } id; -+ u32 mmio_base; - unsigned long size; -- unsigned int alignment; - void *virtual_start; - struct drm_device *dev; - struct drm_gem_object *gem_object; - - unsigned int head; - unsigned int tail; -- unsigned int space; -+ int space; - struct intel_hw_status_page status_page; - - u32 irq_gem_seqno; /* last seq seem at irq time */ -@@ -35,35 +42,28 @@ struct intel_ring_buffer { - struct intel_ring_buffer *ring); - void (*user_irq_put)(struct drm_device *dev, - struct intel_ring_buffer *ring); -- void (*setup_status_page)(struct drm_device *dev, -- struct intel_ring_buffer *ring); - - int (*init)(struct drm_device *dev, - struct intel_ring_buffer *ring); - -- unsigned int (*get_head)(struct drm_device *dev, -- struct intel_ring_buffer *ring); -- unsigned int (*get_tail)(struct drm_device *dev, -- struct intel_ring_buffer *ring); -- unsigned int (*get_active_head)(struct drm_device *dev, -- struct intel_ring_buffer *ring); -- void (*advance_ring)(struct drm_device *dev, -- struct intel_ring_buffer *ring); -+ void (*write_tail)(struct drm_device *dev, -+ struct intel_ring_buffer *ring, -+ u32 value); - void (*flush)(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 invalidate_domains, - u32 flush_domains); - u32 (*add_request)(struct drm_device *dev, - struct intel_ring_buffer *ring, -- struct drm_file *file_priv, - u32 flush_domains); -- u32 (*get_gem_seqno)(struct drm_device *dev, -- struct intel_ring_buffer *ring); -+ u32 (*get_seqno)(struct drm_device *dev, -+ struct intel_ring_buffer *ring); - int (*dispatch_gem_execbuffer)(struct drm_device *dev, - struct intel_ring_buffer *ring, - struct drm_i915_gem_execbuffer2 *exec, - struct drm_clip_rect *cliprects, - uint64_t exec_offset); -+ void (*cleanup)(struct intel_ring_buffer *ring); - - /** - * List of objects currently involved in rendering from the -@@ -83,8 +83,24 @@ struct intel_ring_buffer { - */ - struct list_head request_list; - -+ /** -+ * List of objects currently pending a GPU write flush. -+ * -+ * All elements on this list will belong to either the -+ * active_list or flushing_list, last_rendering_seqno can -+ * be used to differentiate between the two elements. -+ */ -+ struct list_head gpu_write_list; -+ -+ /** -+ * Do we have some not yet emitted requests outstanding? -+ */ -+ bool outstanding_lazy_request; -+ - wait_queue_head_t irq_queue; - drm_local_map_t map; -+ -+ void *private; - }; - - static inline u32 -@@ -96,15 +112,13 @@ intel_read_status_page(struct intel_ring_buffer *ring, - } - - int intel_init_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring); -+ struct intel_ring_buffer *ring); - void intel_cleanup_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring); -+ struct intel_ring_buffer *ring); - int intel_wait_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring, int n); --int intel_wrap_ring_buffer(struct drm_device *dev, -- struct intel_ring_buffer *ring); -+ struct intel_ring_buffer *ring, int n); - void intel_ring_begin(struct drm_device *dev, -- struct intel_ring_buffer *ring, int n); -+ struct intel_ring_buffer *ring, int n); - - static inline void intel_ring_emit(struct drm_device *dev, - struct intel_ring_buffer *ring, -@@ -115,17 +129,19 @@ static inline void intel_ring_emit(struct drm_device *dev, - ring->tail += 4; - } - --void intel_fill_struct(struct drm_device *dev, -- struct intel_ring_buffer *ring, -- void *data, -- unsigned int len); - void intel_ring_advance(struct drm_device *dev, - struct intel_ring_buffer *ring); - - u32 intel_ring_get_seqno(struct drm_device *dev, - struct intel_ring_buffer *ring); - --extern struct intel_ring_buffer render_ring; --extern struct intel_ring_buffer bsd_ring; -+int intel_init_render_ring_buffer(struct drm_device *dev); -+int intel_init_bsd_ring_buffer(struct drm_device *dev); -+int intel_init_blt_ring_buffer(struct drm_device *dev); -+ -+u32 intel_ring_get_active_head(struct drm_device *dev, -+ struct intel_ring_buffer *ring); -+void intel_ring_setup_status_page(struct drm_device *dev, -+ struct intel_ring_buffer *ring); - - #endif /* _INTEL_RINGBUFFER_H_ */ -diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c -index ee73e42..de158b7 100644 ---- a/drivers/gpu/drm/i915/intel_sdvo.c -+++ b/drivers/gpu/drm/i915/intel_sdvo.c -@@ -65,8 +65,11 @@ static const char *tv_format_names[] = { - struct intel_sdvo { - struct intel_encoder base; - -+ struct i2c_adapter *i2c; - u8 slave_addr; - -+ struct i2c_adapter ddc; -+ - /* Register for the SDVO device: SDVOB or SDVOC */ - int sdvo_reg; - -@@ -104,34 +107,24 @@ struct intel_sdvo { - * This is set if we treat the device as HDMI, instead of DVI. - */ - bool is_hdmi; -+ bool has_audio; - - /** -- * This is set if we detect output of sdvo device as LVDS. -+ * This is set if we detect output of sdvo device as LVDS and -+ * have a valid fixed mode to use with the panel. - */ - bool is_lvds; - - /** -- * This is sdvo flags for input timing. -- */ -- uint8_t sdvo_flags; -- -- /** - * This is sdvo fixed pannel mode pointer - */ - struct drm_display_mode *sdvo_lvds_fixed_mode; - -- /* -- * supported encoding mode, used to determine whether HDMI is -- * supported -- */ -- struct intel_sdvo_encode encode; -- - /* DDC bus used by this SDVO encoder */ - uint8_t ddc_bus; - -- /* Mac mini hack -- use the same DDC as the analog connector */ -- struct i2c_adapter *analog_ddc_bus; -- -+ /* Input timings for adjusted_mode */ -+ struct intel_sdvo_dtd input_dtd; - }; - - struct intel_sdvo_connector { -@@ -140,11 +133,15 @@ struct intel_sdvo_connector { - /* Mark the type of connector */ - uint16_t output_flag; - -+ int force_audio; -+ - /* This contains all current supported TV format */ - u8 tv_format_supported[TV_FORMAT_NUM]; - int format_supported_num; - struct drm_property *tv_format; - -+ struct drm_property *force_audio_property; -+ - /* add the property for the SDVO-TV */ - struct drm_property *left; - struct drm_property *right; -@@ -186,9 +183,15 @@ struct intel_sdvo_connector { - u32 cur_dot_crawl, max_dot_crawl; - }; - --static struct intel_sdvo *enc_to_intel_sdvo(struct drm_encoder *encoder) -+static struct intel_sdvo *to_intel_sdvo(struct drm_encoder *encoder) -+{ -+ return container_of(encoder, struct intel_sdvo, base.base); -+} -+ -+static struct intel_sdvo *intel_attached_sdvo(struct drm_connector *connector) - { -- return container_of(enc_to_intel_encoder(encoder), struct intel_sdvo, base); -+ return container_of(intel_attached_encoder(connector), -+ struct intel_sdvo, base); - } - - static struct intel_sdvo_connector *to_intel_sdvo_connector(struct drm_connector *connector) -@@ -213,7 +216,7 @@ intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, - */ - static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) - { -- struct drm_device *dev = intel_sdvo->base.enc.dev; -+ struct drm_device *dev = intel_sdvo->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 bval = val, cval = val; - int i; -@@ -245,49 +248,29 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) - - static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) - { -- u8 out_buf[2] = { addr, 0 }; -- u8 buf[2]; - struct i2c_msg msgs[] = { - { -- .addr = intel_sdvo->slave_addr >> 1, -+ .addr = intel_sdvo->slave_addr, - .flags = 0, - .len = 1, -- .buf = out_buf, -+ .buf = &addr, - }, - { -- .addr = intel_sdvo->slave_addr >> 1, -+ .addr = intel_sdvo->slave_addr, - .flags = I2C_M_RD, - .len = 1, -- .buf = buf, -+ .buf = ch, - } - }; - int ret; - -- if ((ret = i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 2)) == 2) -- { -- *ch = buf[0]; -+ if ((ret = i2c_transfer(intel_sdvo->i2c, msgs, 2)) == 2) - return true; -- } - - DRM_DEBUG_KMS("i2c transfer returned %d\n", ret); - return false; - } - --static bool intel_sdvo_write_byte(struct intel_sdvo *intel_sdvo, int addr, u8 ch) --{ -- u8 out_buf[2] = { addr, ch }; -- struct i2c_msg msgs[] = { -- { -- .addr = intel_sdvo->slave_addr >> 1, -- .flags = 0, -- .len = 2, -- .buf = out_buf, -- } -- }; -- -- return i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 1) == 1; --} -- - #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} - /** Mapping of command numbers to names, for debug output */ - static const struct _sdvo_cmd_name { -@@ -432,22 +415,6 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, - DRM_LOG_KMS("\n"); - } - --static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, -- const void *args, int args_len) --{ -- int i; -- -- intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len); -- -- for (i = 0; i < args_len; i++) { -- if (!intel_sdvo_write_byte(intel_sdvo, SDVO_I2C_ARG_0 - i, -- ((u8*)args)[i])) -- return false; -- } -- -- return intel_sdvo_write_byte(intel_sdvo, SDVO_I2C_OPCODE, cmd); --} -- - static const char *cmd_status_names[] = { - "Power on", - "Success", -@@ -458,54 +425,115 @@ static const char *cmd_status_names[] = { - "Scaling not supported" - }; - --static void intel_sdvo_debug_response(struct intel_sdvo *intel_sdvo, -- void *response, int response_len, -- u8 status) -+static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, -+ const void *args, int args_len) - { -- int i; -+ u8 buf[args_len*2 + 2], status; -+ struct i2c_msg msgs[args_len + 3]; -+ int i, ret; - -- DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); -- for (i = 0; i < response_len; i++) -- DRM_LOG_KMS("%02X ", ((u8 *)response)[i]); -- for (; i < 8; i++) -- DRM_LOG_KMS(" "); -- if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) -- DRM_LOG_KMS("(%s)", cmd_status_names[status]); -- else -- DRM_LOG_KMS("(??? %d)", status); -- DRM_LOG_KMS("\n"); -+ intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len); -+ -+ for (i = 0; i < args_len; i++) { -+ msgs[i].addr = intel_sdvo->slave_addr; -+ msgs[i].flags = 0; -+ msgs[i].len = 2; -+ msgs[i].buf = buf + 2 *i; -+ buf[2*i + 0] = SDVO_I2C_ARG_0 - i; -+ buf[2*i + 1] = ((u8*)args)[i]; -+ } -+ msgs[i].addr = intel_sdvo->slave_addr; -+ msgs[i].flags = 0; -+ msgs[i].len = 2; -+ msgs[i].buf = buf + 2*i; -+ buf[2*i + 0] = SDVO_I2C_OPCODE; -+ buf[2*i + 1] = cmd; -+ -+ /* the following two are to read the response */ -+ status = SDVO_I2C_CMD_STATUS; -+ msgs[i+1].addr = intel_sdvo->slave_addr; -+ msgs[i+1].flags = 0; -+ msgs[i+1].len = 1; -+ msgs[i+1].buf = &status; -+ -+ msgs[i+2].addr = intel_sdvo->slave_addr; -+ msgs[i+2].flags = I2C_M_RD; -+ msgs[i+2].len = 1; -+ msgs[i+2].buf = &status; -+ -+ ret = i2c_transfer(intel_sdvo->i2c, msgs, i+3); -+ if (ret < 0) { -+ DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); -+ return false; -+ } -+ if (ret != i+3) { -+ /* failure in I2C transfer */ -+ DRM_DEBUG_KMS("I2c transfer returned %d/%d\n", ret, i+3); -+ return false; -+ } -+ -+ i = 3; -+ while (status == SDVO_CMD_STATUS_PENDING && i--) { -+ if (!intel_sdvo_read_byte(intel_sdvo, -+ SDVO_I2C_CMD_STATUS, -+ &status)) -+ return false; -+ } -+ if (status != SDVO_CMD_STATUS_SUCCESS) { -+ DRM_DEBUG_KMS("command returns response %s [%d]\n", -+ status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP ? cmd_status_names[status] : "???", -+ status); -+ return false; -+ } -+ -+ return true; - } - - static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, - void *response, int response_len) - { -- int i; -+ u8 retry = 5; - u8 status; -- u8 retry = 50; -- -- while (retry--) { -- /* Read the command response */ -- for (i = 0; i < response_len; i++) { -- if (!intel_sdvo_read_byte(intel_sdvo, -- SDVO_I2C_RETURN_0 + i, -- &((u8 *)response)[i])) -- return false; -- } -+ int i; - -- /* read the return status */ -- if (!intel_sdvo_read_byte(intel_sdvo, SDVO_I2C_CMD_STATUS, -+ /* -+ * The documentation states that all commands will be -+ * processed within 15µs, and that we need only poll -+ * the status byte a maximum of 3 times in order for the -+ * command to be complete. -+ * -+ * Check 5 times in case the hardware failed to read the docs. -+ */ -+ do { -+ if (!intel_sdvo_read_byte(intel_sdvo, -+ SDVO_I2C_CMD_STATUS, - &status)) - return false; -+ } while (status == SDVO_CMD_STATUS_PENDING && --retry); - -- intel_sdvo_debug_response(intel_sdvo, response, response_len, -- status); -- if (status != SDVO_CMD_STATUS_PENDING) -- break; -+ DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); -+ if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) -+ DRM_LOG_KMS("(%s)", cmd_status_names[status]); -+ else -+ DRM_LOG_KMS("(??? %d)", status); - -- mdelay(50); -+ if (status != SDVO_CMD_STATUS_SUCCESS) -+ goto log_fail; -+ -+ /* Read the command response */ -+ for (i = 0; i < response_len; i++) { -+ if (!intel_sdvo_read_byte(intel_sdvo, -+ SDVO_I2C_RETURN_0 + i, -+ &((u8 *)response)[i])) -+ goto log_fail; -+ DRM_LOG_KMS(" %02X", ((u8 *)response)[i]); - } -+ DRM_LOG_KMS("\n"); -+ return true; - -- return status == SDVO_CMD_STATUS_SUCCESS; -+log_fail: -+ DRM_LOG_KMS("\n"); -+ return false; - } - - static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) -@@ -518,71 +546,17 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) - return 4; - } - --/** -- * Try to read the response after issuie the DDC switch command. But it -- * is noted that we must do the action of reading response and issuing DDC -- * switch command in one I2C transaction. Otherwise when we try to start -- * another I2C transaction after issuing the DDC bus switch, it will be -- * switched to the internal SDVO register. -- */ --static void intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo, -- u8 target) -+static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo, -+ u8 ddc_bus) - { -- u8 out_buf[2], cmd_buf[2], ret_value[2], ret; -- struct i2c_msg msgs[] = { -- { -- .addr = intel_sdvo->slave_addr >> 1, -- .flags = 0, -- .len = 2, -- .buf = out_buf, -- }, -- /* the following two are to read the response */ -- { -- .addr = intel_sdvo->slave_addr >> 1, -- .flags = 0, -- .len = 1, -- .buf = cmd_buf, -- }, -- { -- .addr = intel_sdvo->slave_addr >> 1, -- .flags = I2C_M_RD, -- .len = 1, -- .buf = ret_value, -- }, -- }; -- -- intel_sdvo_debug_write(intel_sdvo, SDVO_CMD_SET_CONTROL_BUS_SWITCH, -- &target, 1); -- /* write the DDC switch command argument */ -- intel_sdvo_write_byte(intel_sdvo, SDVO_I2C_ARG_0, target); -- -- out_buf[0] = SDVO_I2C_OPCODE; -- out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; -- cmd_buf[0] = SDVO_I2C_CMD_STATUS; -- cmd_buf[1] = 0; -- ret_value[0] = 0; -- ret_value[1] = 0; -- -- ret = i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 3); -- if (ret != 3) { -- /* failure in I2C transfer */ -- DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); -- return; -- } -- if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) { -- DRM_DEBUG_KMS("DDC switch command returns response %d\n", -- ret_value[0]); -- return; -- } -- return; -+ return intel_sdvo_write_cmd(intel_sdvo, -+ SDVO_CMD_SET_CONTROL_BUS_SWITCH, -+ &ddc_bus, 1); - } - - static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len) - { -- if (!intel_sdvo_write_cmd(intel_sdvo, cmd, data, len)) -- return false; -- -- return intel_sdvo_read_response(intel_sdvo, NULL, 0); -+ return intel_sdvo_write_cmd(intel_sdvo, cmd, data, len); - } - - static bool -@@ -819,17 +793,13 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, - mode->flags |= DRM_MODE_FLAG_PVSYNC; - } - --static bool intel_sdvo_get_supp_encode(struct intel_sdvo *intel_sdvo, -- struct intel_sdvo_encode *encode) -+static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo) - { -- if (intel_sdvo_get_value(intel_sdvo, -- SDVO_CMD_GET_SUPP_ENCODE, -- encode, sizeof(*encode))) -- return true; -+ struct intel_sdvo_encode encode; - -- /* non-support means DVI */ -- memset(encode, 0, sizeof(*encode)); -- return false; -+ return intel_sdvo_get_value(intel_sdvo, -+ SDVO_CMD_GET_SUPP_ENCODE, -+ &encode, sizeof(encode)); - } - - static bool intel_sdvo_set_encode(struct intel_sdvo *intel_sdvo, -@@ -874,115 +844,33 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) - } - #endif - --static bool intel_sdvo_set_hdmi_buf(struct intel_sdvo *intel_sdvo, -- int index, -- uint8_t *data, int8_t size, uint8_t tx_rate) --{ -- uint8_t set_buf_index[2]; -- -- set_buf_index[0] = index; -- set_buf_index[1] = 0; -- -- if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX, -- set_buf_index, 2)) -- return false; -- -- for (; size > 0; size -= 8) { -- if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA, data, 8)) -- return false; -- -- data += 8; -- } -- -- return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1); --} -- --static uint8_t intel_sdvo_calc_hbuf_csum(uint8_t *data, uint8_t size) --{ -- uint8_t csum = 0; -- int i; -- -- for (i = 0; i < size; i++) -- csum += data[i]; -- -- return 0x100 - csum; --} -- --#define DIP_TYPE_AVI 0x82 --#define DIP_VERSION_AVI 0x2 --#define DIP_LEN_AVI 13 -- --struct dip_infoframe { -- uint8_t type; -- uint8_t version; -- uint8_t len; -- uint8_t checksum; -- union { -- struct { -- /* Packet Byte #1 */ -- uint8_t S:2; -- uint8_t B:2; -- uint8_t A:1; -- uint8_t Y:2; -- uint8_t rsvd1:1; -- /* Packet Byte #2 */ -- uint8_t R:4; -- uint8_t M:2; -- uint8_t C:2; -- /* Packet Byte #3 */ -- uint8_t SC:2; -- uint8_t Q:2; -- uint8_t EC:3; -- uint8_t ITC:1; -- /* Packet Byte #4 */ -- uint8_t VIC:7; -- uint8_t rsvd2:1; -- /* Packet Byte #5 */ -- uint8_t PR:4; -- uint8_t rsvd3:4; -- /* Packet Byte #6~13 */ -- uint16_t top_bar_end; -- uint16_t bottom_bar_start; -- uint16_t left_bar_end; -- uint16_t right_bar_start; -- } avi; -- struct { -- /* Packet Byte #1 */ -- uint8_t channel_count:3; -- uint8_t rsvd1:1; -- uint8_t coding_type:4; -- /* Packet Byte #2 */ -- uint8_t sample_size:2; /* SS0, SS1 */ -- uint8_t sample_frequency:3; -- uint8_t rsvd2:3; -- /* Packet Byte #3 */ -- uint8_t coding_type_private:5; -- uint8_t rsvd3:3; -- /* Packet Byte #4 */ -- uint8_t channel_allocation; -- /* Packet Byte #5 */ -- uint8_t rsvd4:3; -- uint8_t level_shift:4; -- uint8_t downmix_inhibit:1; -- } audio; -- uint8_t payload[28]; -- } __attribute__ ((packed)) u; --} __attribute__((packed)); -- --static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, -- struct drm_display_mode * mode) -+static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) - { - struct dip_infoframe avi_if = { - .type = DIP_TYPE_AVI, -- .version = DIP_VERSION_AVI, -+ .ver = DIP_VERSION_AVI, - .len = DIP_LEN_AVI, - }; -+ uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; -+ uint8_t set_buf_index[2] = { 1, 0 }; -+ uint64_t *data = (uint64_t *)&avi_if; -+ unsigned i; -+ -+ intel_dip_infoframe_csum(&avi_if); -+ -+ if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX, -+ set_buf_index, 2)) -+ return false; - -- avi_if.checksum = intel_sdvo_calc_hbuf_csum((uint8_t *)&avi_if, -- 4 + avi_if.len); -- return intel_sdvo_set_hdmi_buf(intel_sdvo, 1, (uint8_t *)&avi_if, -- 4 + avi_if.len, -- SDVO_HBUF_TX_VSYNC); -+ for (i = 0; i < sizeof(avi_if); i += 8) { -+ if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA, -+ data, 8)) -+ return false; -+ data++; -+ } -+ -+ return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE, -+ &tx_rate, 1); - } - - static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) -@@ -1022,8 +910,6 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - { -- struct intel_sdvo_dtd input_dtd; -- - /* Reset the input timing to the screen. Assume always input 0. */ - if (!intel_sdvo_set_target_input(intel_sdvo)) - return false; -@@ -1035,14 +921,12 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, - return false; - - if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, -- &input_dtd)) -+ &intel_sdvo->input_dtd)) - return false; - -- intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); -- intel_sdvo->sdvo_flags = input_dtd.part2.sdvo_flags; -+ intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); - - drm_mode_set_crtcinfo(adjusted_mode, 0); -- mode->clock = adjusted_mode->clock; - return true; - } - -@@ -1050,7 +934,8 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - { -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -+ struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); -+ int multiplier; - - /* We need to construct preferred input timings based on our - * output timings. To do that, we have to set the output -@@ -1065,10 +950,8 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, - mode, - adjusted_mode); - } else if (intel_sdvo->is_lvds) { -- drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, 0); -- - if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, -- intel_sdvo->sdvo_lvds_fixed_mode)) -+ intel_sdvo->sdvo_lvds_fixed_mode)) - return false; - - (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, -@@ -1077,9 +960,10 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, - } - - /* Make the CRTC code factor in the SDVO pixel multiplier. The -- * SDVO device will be told of the multiplier during mode_set. -+ * SDVO device will factor out the multiplier during mode_set. - */ -- adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); -+ multiplier = intel_sdvo_get_pixel_multiplier(adjusted_mode); -+ intel_mode_set_pixel_multiplier(adjusted_mode, multiplier); - - return true; - } -@@ -1092,11 +976,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = encoder->crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -- u32 sdvox = 0; -- int sdvo_pixel_multiply, rate; -+ struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); -+ u32 sdvox; - struct intel_sdvo_in_out_map in_out; - struct intel_sdvo_dtd input_dtd; -+ int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); -+ int rate; - - if (!mode) - return; -@@ -1114,28 +999,23 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, - SDVO_CMD_SET_IN_OUT_MAP, - &in_out, sizeof(in_out)); - -- if (intel_sdvo->is_hdmi) { -- if (!intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) -- return; -- -- sdvox |= SDVO_AUDIO_ENABLE; -- } -+ /* Set the output timings to the screen */ -+ if (!intel_sdvo_set_target_output(intel_sdvo, -+ intel_sdvo->attached_output)) -+ return; - - /* We have tried to get input timing in mode_fixup, and filled into -- adjusted_mode */ -- intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); -- if (intel_sdvo->is_tv || intel_sdvo->is_lvds) -- input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags; -- -- /* If it's a TV, we already set the output timing in mode_fixup. -- * Otherwise, the output timing is equal to the input timing. -+ * adjusted_mode. - */ -- if (!intel_sdvo->is_tv && !intel_sdvo->is_lvds) { -+ if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { -+ input_dtd = intel_sdvo->input_dtd; -+ } else { - /* Set the output timing to the screen */ - if (!intel_sdvo_set_target_output(intel_sdvo, - intel_sdvo->attached_output)) - return; - -+ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); - (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd); - } - -@@ -1143,31 +1023,18 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, - if (!intel_sdvo_set_target_input(intel_sdvo)) - return; - -- if (intel_sdvo->is_tv) { -- if (!intel_sdvo_set_tv_format(intel_sdvo)) -- return; -- } -+ if (intel_sdvo->is_hdmi && -+ !intel_sdvo_set_avi_infoframe(intel_sdvo)) -+ return; - -- /* We would like to use intel_sdvo_create_preferred_input_timing() to -- * provide the device with a timing it can support, if it supports that -- * feature. However, presumably we would need to adjust the CRTC to -- * output the preferred timing, and we don't support that currently. -- */ --#if 0 -- success = intel_sdvo_create_preferred_input_timing(encoder, clock, -- width, height); -- if (success) { -- struct intel_sdvo_dtd *input_dtd; -+ if (intel_sdvo->is_tv && -+ !intel_sdvo_set_tv_format(intel_sdvo)) -+ return; - -- intel_sdvo_get_preferred_input_timing(encoder, &input_dtd); -- intel_sdvo_set_input_timing(encoder, &input_dtd); -- } --#else - (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); --#endif - -- sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); -- switch (sdvo_pixel_multiply) { -+ switch (pixel_multiplier) { -+ default: - case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; - case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break; - case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break; -@@ -1176,14 +1043,14 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, - return; - - /* Set the SDVO control regs. */ -- if (IS_I965G(dev)) { -- sdvox |= SDVO_BORDER_ENABLE; -+ if (INTEL_INFO(dev)->gen >= 4) { -+ sdvox = SDVO_BORDER_ENABLE; - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - sdvox |= SDVO_VSYNC_ACTIVE_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - sdvox |= SDVO_HSYNC_ACTIVE_HIGH; - } else { -- sdvox |= I915_READ(intel_sdvo->sdvo_reg); -+ sdvox = I915_READ(intel_sdvo->sdvo_reg); - switch (intel_sdvo->sdvo_reg) { - case SDVOB: - sdvox &= SDVOB_PRESERVE_MASK; -@@ -1196,16 +1063,18 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, - } - if (intel_crtc->pipe == 1) - sdvox |= SDVO_PIPE_B_SELECT; -+ if (intel_sdvo->has_audio) -+ sdvox |= SDVO_AUDIO_ENABLE; - -- if (IS_I965G(dev)) { -+ if (INTEL_INFO(dev)->gen >= 4) { - /* done in crtc_mode_set as the dpll_md reg must be written early */ - } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { - /* done in crtc_mode_set as it lives inside the dpll register */ - } else { -- sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; -+ sdvox |= (pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT; - } - -- if (intel_sdvo->sdvo_flags & SDVO_NEED_TO_STALL) -+ if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL) - sdvox |= SDVO_STALL_SELECT; - intel_sdvo_write_sdvox(intel_sdvo, sdvox); - } -@@ -1214,7 +1083,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) - { - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -+ struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - u32 temp; - -@@ -1260,8 +1129,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) - static int intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -+ struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; -@@ -1285,7 +1153,38 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, - - static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps) - { -- return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_DEVICE_CAPS, caps, sizeof(*caps)); -+ if (!intel_sdvo_get_value(intel_sdvo, -+ SDVO_CMD_GET_DEVICE_CAPS, -+ caps, sizeof(*caps))) -+ return false; -+ -+ DRM_DEBUG_KMS("SDVO capabilities:\n" -+ " vendor_id: %d\n" -+ " device_id: %d\n" -+ " device_rev_id: %d\n" -+ " sdvo_version_major: %d\n" -+ " sdvo_version_minor: %d\n" -+ " sdvo_inputs_mask: %d\n" -+ " smooth_scaling: %d\n" -+ " sharp_scaling: %d\n" -+ " up_scaling: %d\n" -+ " down_scaling: %d\n" -+ " stall_support: %d\n" -+ " output_flags: %d\n", -+ caps->vendor_id, -+ caps->device_id, -+ caps->device_rev_id, -+ caps->sdvo_version_major, -+ caps->sdvo_version_minor, -+ caps->sdvo_inputs_mask, -+ caps->smooth_scaling, -+ caps->sharp_scaling, -+ caps->up_scaling, -+ caps->down_scaling, -+ caps->stall_support, -+ caps->output_flags); -+ -+ return true; - } - - /* No use! */ -@@ -1389,22 +1288,33 @@ intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) - return (caps > 1); - } - -+static struct edid * -+intel_sdvo_get_edid(struct drm_connector *connector) -+{ -+ struct intel_sdvo *sdvo = intel_attached_sdvo(connector); -+ return drm_get_edid(connector, &sdvo->ddc); -+} -+ - static struct drm_connector * - intel_find_analog_connector(struct drm_device *dev) - { - struct drm_connector *connector; -- struct drm_encoder *encoder; -- struct intel_sdvo *intel_sdvo; -- -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- intel_sdvo = enc_to_intel_sdvo(encoder); -- if (intel_sdvo->base.type == INTEL_OUTPUT_ANALOG) { -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- if (encoder == intel_attached_encoder(connector)) -+ struct intel_sdvo *encoder; -+ -+ list_for_each_entry(encoder, -+ &dev->mode_config.encoder_list, -+ base.base.head) { -+ if (encoder->base.type == INTEL_OUTPUT_ANALOG) { -+ list_for_each_entry(connector, -+ &dev->mode_config.connector_list, -+ head) { -+ if (&encoder->base == -+ intel_attached_encoder(connector)) - return connector; - } - } - } -+ - return NULL; - } - -@@ -1424,64 +1334,72 @@ intel_analog_is_connected(struct drm_device *dev) - return true; - } - -+/* Mac mini hack -- use the same DDC as the analog connector */ -+static struct edid * -+intel_sdvo_get_analog_edid(struct drm_connector *connector) -+{ -+ struct drm_i915_private *dev_priv = connector->dev->dev_private; -+ -+ if (!intel_analog_is_connected(connector->dev)) -+ return NULL; -+ -+ return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); -+} -+ - enum drm_connector_status - intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -- struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); -- enum drm_connector_status status = connector_status_connected; -- struct edid *edid = NULL; -+ struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); -+ enum drm_connector_status status; -+ struct edid *edid; - -- edid = drm_get_edid(connector, intel_sdvo->base.ddc_bus); -+ edid = intel_sdvo_get_edid(connector); - -- /* This is only applied to SDVO cards with multiple outputs */ - if (edid == NULL && intel_sdvo_multifunc_encoder(intel_sdvo)) { -- uint8_t saved_ddc, temp_ddc; -- saved_ddc = intel_sdvo->ddc_bus; -- temp_ddc = intel_sdvo->ddc_bus >> 1; -+ u8 ddc, saved_ddc = intel_sdvo->ddc_bus; -+ - /* - * Don't use the 1 as the argument of DDC bus switch to get - * the EDID. It is used for SDVO SPD ROM. - */ -- while(temp_ddc > 1) { -- intel_sdvo->ddc_bus = temp_ddc; -- edid = drm_get_edid(connector, intel_sdvo->base.ddc_bus); -- if (edid) { -- /* -- * When we can get the EDID, maybe it is the -- * correct DDC bus. Update it. -- */ -- intel_sdvo->ddc_bus = temp_ddc; -+ for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) { -+ intel_sdvo->ddc_bus = ddc; -+ edid = intel_sdvo_get_edid(connector); -+ if (edid) - break; -- } -- temp_ddc >>= 1; - } -+ /* -+ * If we found the EDID on the other bus, -+ * assume that is the correct DDC bus. -+ */ - if (edid == NULL) - intel_sdvo->ddc_bus = saved_ddc; - } -- /* when there is no edid and no monitor is connected with VGA -- * port, try to use the CRT ddc to read the EDID for DVI-connector -+ -+ /* -+ * When there is no edid and no monitor is connected with VGA -+ * port, try to use the CRT ddc to read the EDID for DVI-connector. - */ -- if (edid == NULL && intel_sdvo->analog_ddc_bus && -- !intel_analog_is_connected(connector->dev)) -- edid = drm_get_edid(connector, intel_sdvo->analog_ddc_bus); -+ if (edid == NULL) -+ edid = intel_sdvo_get_analog_edid(connector); - -+ status = connector_status_unknown; - if (edid != NULL) { -- bool is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); -- bool need_digital = !!(intel_sdvo_connector->output_flag & SDVO_TMDS_MASK); -- - /* DDC bus is shared, match EDID to connector type */ -- if (is_digital && need_digital) -+ if (edid->input & DRM_EDID_INPUT_DIGITAL) { -+ status = connector_status_connected; - intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid); -- else if (is_digital != need_digital) -- status = connector_status_disconnected; -- -+ intel_sdvo->has_audio = drm_detect_monitor_audio(edid); -+ } - connector->display_info.raw_edid = NULL; -- } else -- status = connector_status_disconnected; -- -- kfree(edid); -+ kfree(edid); -+ } -+ -+ if (status == connector_status_connected) { -+ struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); -+ if (intel_sdvo_connector->force_audio) -+ intel_sdvo->has_audio = intel_sdvo_connector->force_audio > 0; -+ } - - return status; - } -@@ -1490,13 +1408,12 @@ static enum drm_connector_status - intel_sdvo_detect(struct drm_connector *connector, bool force) - { - uint16_t response; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -+ struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); - struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); - enum drm_connector_status ret; - - if (!intel_sdvo_write_cmd(intel_sdvo, -- SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) -+ SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) - return connector_status_unknown; - if (intel_sdvo->is_tv) { - /* add 30ms delay when the output type is SDVO-TV */ -@@ -1505,7 +1422,9 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) - if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) - return connector_status_unknown; - -- DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8); -+ DRM_DEBUG_KMS("SDVO response %d %d [%x]\n", -+ response & 0xff, response >> 8, -+ intel_sdvo_connector->output_flag); - - if (response == 0) - return connector_status_disconnected; -@@ -1538,12 +1457,10 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) - - static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -- int num_modes; -+ struct edid *edid; - - /* set the bus switch and get the modes */ -- num_modes = intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus); -+ edid = intel_sdvo_get_edid(connector); - - /* - * Mac mini hack. On this device, the DVI-I connector shares one DDC -@@ -1551,12 +1468,14 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) - * DDC fails, check to see if the analog output is disconnected, in - * which case we'll look there for the digital DDC data. - */ -- if (num_modes == 0 && -- intel_sdvo->analog_ddc_bus && -- !intel_analog_is_connected(connector->dev)) { -- /* Switch to the analog ddc bus and try that -- */ -- (void) intel_ddc_get_modes(connector, intel_sdvo->analog_ddc_bus); -+ if (edid == NULL) -+ edid = intel_sdvo_get_analog_edid(connector); -+ -+ if (edid != NULL) { -+ drm_mode_connector_update_edid_property(connector, edid); -+ drm_add_edid_modes(connector, edid); -+ connector->display_info.raw_edid = NULL; -+ kfree(edid); - } - } - -@@ -1627,8 +1546,7 @@ struct drm_display_mode sdvo_tv_modes[] = { - - static void intel_sdvo_get_tv_modes(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -+ struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); - struct intel_sdvo_sdtv_resolution_request tv_res; - uint32_t reply = 0, format_map = 0; - int i; -@@ -1644,7 +1562,8 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) - return; - - BUILD_BUG_ON(sizeof(tv_res) != 3); -- if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, -+ if (!intel_sdvo_write_cmd(intel_sdvo, -+ SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, - &tv_res, sizeof(tv_res))) - return; - if (!intel_sdvo_read_response(intel_sdvo, &reply, 3)) -@@ -1662,8 +1581,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) - - static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -+ struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); - struct drm_i915_private *dev_priv = connector->dev->dev_private; - struct drm_display_mode *newmode; - -@@ -1672,7 +1590,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) - * Assume that the preferred modes are - * arranged in priority order. - */ -- intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus); -+ intel_ddc_get_modes(connector, intel_sdvo->i2c); - if (list_empty(&connector->probed_modes) == false) - goto end; - -@@ -1693,6 +1611,10 @@ end: - if (newmode->type & DRM_MODE_TYPE_PREFERRED) { - intel_sdvo->sdvo_lvds_fixed_mode = - drm_mode_duplicate(connector->dev, newmode); -+ -+ drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, -+ 0); -+ - intel_sdvo->is_lvds = true; - break; - } -@@ -1775,8 +1697,7 @@ intel_sdvo_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t val) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -+ struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); - struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); - uint16_t temp_value; - uint8_t cmd; -@@ -1786,6 +1707,21 @@ intel_sdvo_set_property(struct drm_connector *connector, - if (ret) - return ret; - -+ if (property == intel_sdvo_connector->force_audio_property) { -+ if (val == intel_sdvo_connector->force_audio) -+ return 0; -+ -+ intel_sdvo_connector->force_audio = val; -+ -+ if (val > 0 && intel_sdvo->has_audio) -+ return 0; -+ if (val < 0 && !intel_sdvo->has_audio) -+ return 0; -+ -+ intel_sdvo->has_audio = val > 0; -+ goto done; -+ } -+ - #define CHECK_PROPERTY(name, NAME) \ - if (intel_sdvo_connector->name == property) { \ - if (intel_sdvo_connector->cur_##name == temp_value) return 0; \ -@@ -1879,9 +1815,8 @@ set_value: - - - done: -- if (encoder->crtc) { -- struct drm_crtc *crtc = encoder->crtc; -- -+ if (intel_sdvo->base.base.crtc) { -+ struct drm_crtc *crtc = intel_sdvo->base.base.crtc; - drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, - crtc->y, crtc->fb); - } -@@ -1909,20 +1844,18 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = { - static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = { - .get_modes = intel_sdvo_get_modes, - .mode_valid = intel_sdvo_mode_valid, -- .best_encoder = intel_attached_encoder, -+ .best_encoder = intel_best_encoder, - }; - - static void intel_sdvo_enc_destroy(struct drm_encoder *encoder) - { -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -- -- if (intel_sdvo->analog_ddc_bus) -- intel_i2c_destroy(intel_sdvo->analog_ddc_bus); -+ struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); - - if (intel_sdvo->sdvo_lvds_fixed_mode != NULL) - drm_mode_destroy(encoder->dev, - intel_sdvo->sdvo_lvds_fixed_mode); - -+ i2c_del_adapter(&intel_sdvo->ddc); - intel_encoder_destroy(encoder); - } - -@@ -1990,53 +1923,48 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, - intel_sdvo_guess_ddc_bus(sdvo); - } - --static bool --intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device) -+static void -+intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, -+ struct intel_sdvo *sdvo, u32 reg) - { -- return intel_sdvo_set_target_output(intel_sdvo, -- device == 0 ? SDVO_OUTPUT_TMDS0 : SDVO_OUTPUT_TMDS1) && -- intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, -- &intel_sdvo->is_hdmi, 1); --} -+ struct sdvo_device_mapping *mapping; -+ u8 pin, speed; - --static struct intel_sdvo * --intel_sdvo_chan_to_intel_sdvo(struct intel_i2c_chan *chan) --{ -- struct drm_device *dev = chan->drm_dev; -- struct drm_encoder *encoder; -+ if (IS_SDVOB(reg)) -+ mapping = &dev_priv->sdvo_mappings[0]; -+ else -+ mapping = &dev_priv->sdvo_mappings[1]; - -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); -- if (intel_sdvo->base.ddc_bus == &chan->adapter) -- return intel_sdvo; -+ pin = GMBUS_PORT_DPB; -+ speed = GMBUS_RATE_1MHZ >> 8; -+ if (mapping->initialized) { -+ pin = mapping->i2c_pin; -+ speed = mapping->i2c_speed; - } - -- return NULL; -+ sdvo->i2c = &dev_priv->gmbus[pin].adapter; -+ intel_gmbus_set_speed(sdvo->i2c, speed); -+ intel_gmbus_force_bit(sdvo->i2c, true); - } - --static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, -- struct i2c_msg msgs[], int num) -+static bool -+intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device) - { -- struct intel_sdvo *intel_sdvo; -- struct i2c_algo_bit_data *algo_data; -- const struct i2c_algorithm *algo; -+ int is_hdmi; - -- algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; -- intel_sdvo = -- intel_sdvo_chan_to_intel_sdvo((struct intel_i2c_chan *) -- (algo_data->data)); -- if (intel_sdvo == NULL) -- return -EINVAL; -+ if (!intel_sdvo_check_supp_encode(intel_sdvo)) -+ return false; - -- algo = intel_sdvo->base.i2c_bus->algo; -+ if (!intel_sdvo_set_target_output(intel_sdvo, -+ device == 0 ? SDVO_OUTPUT_TMDS0 : SDVO_OUTPUT_TMDS1)) -+ return false; - -- intel_sdvo_set_control_bus_switch(intel_sdvo, intel_sdvo->ddc_bus); -- return algo->master_xfer(i2c_adap, msgs, num); --} -+ is_hdmi = 0; -+ if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, &is_hdmi, 1)) -+ return false; - --static struct i2c_algorithm intel_sdvo_i2c_bit_algo = { -- .master_xfer = intel_sdvo_master_xfer, --}; -+ return !!is_hdmi; -+} - - static u8 - intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) -@@ -2076,26 +2004,44 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) - } - - static void --intel_sdvo_connector_init(struct drm_encoder *encoder, -- struct drm_connector *connector) -+intel_sdvo_connector_init(struct intel_sdvo_connector *connector, -+ struct intel_sdvo *encoder) - { -- drm_connector_init(encoder->dev, connector, &intel_sdvo_connector_funcs, -- connector->connector_type); -+ drm_connector_init(encoder->base.base.dev, -+ &connector->base.base, -+ &intel_sdvo_connector_funcs, -+ connector->base.base.connector_type); -+ -+ drm_connector_helper_add(&connector->base.base, -+ &intel_sdvo_connector_helper_funcs); -+ -+ connector->base.base.interlace_allowed = 0; -+ connector->base.base.doublescan_allowed = 0; -+ connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB; - -- drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); -+ intel_connector_attach_encoder(&connector->base, &encoder->base); -+ drm_sysfs_connector_add(&connector->base.base); -+} - -- connector->interlace_allowed = 0; -- connector->doublescan_allowed = 0; -- connector->display_info.subpixel_order = SubPixelHorizontalRGB; -+static void -+intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector) -+{ -+ struct drm_device *dev = connector->base.base.dev; - -- drm_mode_connector_attach_encoder(connector, encoder); -- drm_sysfs_connector_add(connector); -+ connector->force_audio_property = -+ drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2); -+ if (connector->force_audio_property) { -+ connector->force_audio_property->values[0] = -1; -+ connector->force_audio_property->values[1] = 1; -+ drm_connector_attach_property(&connector->base.base, -+ connector->force_audio_property, 0); -+ } - } - - static bool - intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) - { -- struct drm_encoder *encoder = &intel_sdvo->base.enc; -+ struct drm_encoder *encoder = &intel_sdvo->base.base; - struct drm_connector *connector; - struct intel_connector *intel_connector; - struct intel_sdvo_connector *intel_sdvo_connector; -@@ -2118,19 +2064,20 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) - encoder->encoder_type = DRM_MODE_ENCODER_TMDS; - connector->connector_type = DRM_MODE_CONNECTOR_DVID; - -- if (intel_sdvo_get_supp_encode(intel_sdvo, &intel_sdvo->encode) -- && intel_sdvo_get_digital_encoding_mode(intel_sdvo, device) -- && intel_sdvo->is_hdmi) { -+ if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) { - /* enable hdmi encoding mode if supported */ - intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI); - intel_sdvo_set_colorimetry(intel_sdvo, - SDVO_COLORIMETRY_RGB256); - connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; -+ intel_sdvo->is_hdmi = true; - } - intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT)); - -- intel_sdvo_connector_init(encoder, connector); -+ intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); -+ -+ intel_sdvo_add_hdmi_properties(intel_sdvo_connector); - - return true; - } -@@ -2138,36 +2085,36 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) - static bool - intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) - { -- struct drm_encoder *encoder = &intel_sdvo->base.enc; -- struct drm_connector *connector; -- struct intel_connector *intel_connector; -- struct intel_sdvo_connector *intel_sdvo_connector; -+ struct drm_encoder *encoder = &intel_sdvo->base.base; -+ struct drm_connector *connector; -+ struct intel_connector *intel_connector; -+ struct intel_sdvo_connector *intel_sdvo_connector; - - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); - if (!intel_sdvo_connector) - return false; - - intel_connector = &intel_sdvo_connector->base; -- connector = &intel_connector->base; -- encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; -- connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; -+ connector = &intel_connector->base; -+ encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; -+ connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; - -- intel_sdvo->controlled_output |= type; -- intel_sdvo_connector->output_flag = type; -+ intel_sdvo->controlled_output |= type; -+ intel_sdvo_connector->output_flag = type; - -- intel_sdvo->is_tv = true; -- intel_sdvo->base.needs_tv_clock = true; -- intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT; -+ intel_sdvo->is_tv = true; -+ intel_sdvo->base.needs_tv_clock = true; -+ intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT; - -- intel_sdvo_connector_init(encoder, connector); -+ intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); - -- if (!intel_sdvo_tv_create_property(intel_sdvo, intel_sdvo_connector, type)) -+ if (!intel_sdvo_tv_create_property(intel_sdvo, intel_sdvo_connector, type)) - goto err; - -- if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) -+ if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) - goto err; - -- return true; -+ return true; - - err: - intel_sdvo_destroy(connector); -@@ -2177,43 +2124,44 @@ err: - static bool - intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) - { -- struct drm_encoder *encoder = &intel_sdvo->base.enc; -- struct drm_connector *connector; -- struct intel_connector *intel_connector; -- struct intel_sdvo_connector *intel_sdvo_connector; -+ struct drm_encoder *encoder = &intel_sdvo->base.base; -+ struct drm_connector *connector; -+ struct intel_connector *intel_connector; -+ struct intel_sdvo_connector *intel_sdvo_connector; - - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); - if (!intel_sdvo_connector) - return false; - - intel_connector = &intel_sdvo_connector->base; -- connector = &intel_connector->base; -+ connector = &intel_connector->base; - connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- encoder->encoder_type = DRM_MODE_ENCODER_DAC; -- connector->connector_type = DRM_MODE_CONNECTOR_VGA; -- -- if (device == 0) { -- intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; -- intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; -- } else if (device == 1) { -- intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; -- intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; -- } -- -- intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | -+ encoder->encoder_type = DRM_MODE_ENCODER_DAC; -+ connector->connector_type = DRM_MODE_CONNECTOR_VGA; -+ -+ if (device == 0) { -+ intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; -+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; -+ } else if (device == 1) { -+ intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; -+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; -+ } -+ -+ intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT)); - -- intel_sdvo_connector_init(encoder, connector); -- return true; -+ intel_sdvo_connector_init(intel_sdvo_connector, -+ intel_sdvo); -+ return true; - } - - static bool - intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) - { -- struct drm_encoder *encoder = &intel_sdvo->base.enc; -- struct drm_connector *connector; -- struct intel_connector *intel_connector; -- struct intel_sdvo_connector *intel_sdvo_connector; -+ struct drm_encoder *encoder = &intel_sdvo->base.base; -+ struct drm_connector *connector; -+ struct intel_connector *intel_connector; -+ struct intel_sdvo_connector *intel_sdvo_connector; - - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); - if (!intel_sdvo_connector) -@@ -2221,22 +2169,22 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) - - intel_connector = &intel_sdvo_connector->base; - connector = &intel_connector->base; -- encoder->encoder_type = DRM_MODE_ENCODER_LVDS; -- connector->connector_type = DRM_MODE_CONNECTOR_LVDS; -- -- if (device == 0) { -- intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; -- intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; -- } else if (device == 1) { -- intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; -- intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; -- } -- -- intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) | -+ encoder->encoder_type = DRM_MODE_ENCODER_LVDS; -+ connector->connector_type = DRM_MODE_CONNECTOR_LVDS; -+ -+ if (device == 0) { -+ intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; -+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; -+ } else if (device == 1) { -+ intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; -+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; -+ } -+ -+ intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) | - (1 << INTEL_SDVO_LVDS_CLONE_BIT)); - -- intel_sdvo_connector_init(encoder, connector); -- if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) -+ intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); -+ if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) - goto err; - - return true; -@@ -2307,7 +2255,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, - struct intel_sdvo_connector *intel_sdvo_connector, - int type) - { -- struct drm_device *dev = intel_sdvo->base.enc.dev; -+ struct drm_device *dev = intel_sdvo->base.base.dev; - struct intel_sdvo_tv_format format; - uint32_t format_map, i; - -@@ -2373,7 +2321,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, - struct intel_sdvo_connector *intel_sdvo_connector, - struct intel_sdvo_enhancements_reply enhancements) - { -- struct drm_device *dev = intel_sdvo->base.enc.dev; -+ struct drm_device *dev = intel_sdvo->base.base.dev; - struct drm_connector *connector = &intel_sdvo_connector->base.base; - uint16_t response, data_value[2]; - -@@ -2502,7 +2450,7 @@ intel_sdvo_create_enhance_property_lvds(struct intel_sdvo *intel_sdvo, - struct intel_sdvo_connector *intel_sdvo_connector, - struct intel_sdvo_enhancements_reply enhancements) - { -- struct drm_device *dev = intel_sdvo->base.enc.dev; -+ struct drm_device *dev = intel_sdvo->base.base.dev; - struct drm_connector *connector = &intel_sdvo_connector->base.base; - uint16_t response, data_value[2]; - -@@ -2535,7 +2483,43 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, - return intel_sdvo_create_enhance_property_lvds(intel_sdvo, intel_sdvo_connector, enhancements.reply); - else - return true; -+} -+ -+static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter, -+ struct i2c_msg *msgs, -+ int num) -+{ -+ struct intel_sdvo *sdvo = adapter->algo_data; - -+ if (!intel_sdvo_set_control_bus_switch(sdvo, sdvo->ddc_bus)) -+ return -EIO; -+ -+ return sdvo->i2c->algo->master_xfer(sdvo->i2c, msgs, num); -+} -+ -+static u32 intel_sdvo_ddc_proxy_func(struct i2c_adapter *adapter) -+{ -+ struct intel_sdvo *sdvo = adapter->algo_data; -+ return sdvo->i2c->algo->functionality(sdvo->i2c); -+} -+ -+static const struct i2c_algorithm intel_sdvo_ddc_proxy = { -+ .master_xfer = intel_sdvo_ddc_proxy_xfer, -+ .functionality = intel_sdvo_ddc_proxy_func -+}; -+ -+static bool -+intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo, -+ struct drm_device *dev) -+{ -+ sdvo->ddc.owner = THIS_MODULE; -+ sdvo->ddc.class = I2C_CLASS_DDC; -+ snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy"); -+ sdvo->ddc.dev.parent = &dev->pdev->dev; -+ sdvo->ddc.algo_data = sdvo; -+ sdvo->ddc.algo = &intel_sdvo_ddc_proxy; -+ -+ return i2c_add_adapter(&sdvo->ddc) == 0; - } - - bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) -@@ -2543,95 +2527,66 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_encoder *intel_encoder; - struct intel_sdvo *intel_sdvo; -- u8 ch[0x40]; - int i; -- u32 i2c_reg, ddc_reg, analog_ddc_reg; - - intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); - if (!intel_sdvo) - return false; - -+ if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) { -+ kfree(intel_sdvo); -+ return false; -+ } -+ - intel_sdvo->sdvo_reg = sdvo_reg; - - intel_encoder = &intel_sdvo->base; - intel_encoder->type = INTEL_OUTPUT_SDVO; -+ /* encoder type will be decided later */ -+ drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0); - -- if (HAS_PCH_SPLIT(dev)) { -- i2c_reg = PCH_GPIOE; -- ddc_reg = PCH_GPIOE; -- analog_ddc_reg = PCH_GPIOA; -- } else { -- i2c_reg = GPIOE; -- ddc_reg = GPIOE; -- analog_ddc_reg = GPIOA; -- } -- -- /* setup the DDC bus. */ -- if (IS_SDVOB(sdvo_reg)) -- intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOB"); -- else -- intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOC"); -- -- if (!intel_encoder->i2c_bus) -- goto err_inteloutput; -- -- intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg); -- -- /* Save the bit-banging i2c functionality for use by the DDC wrapper */ -- intel_sdvo_i2c_bit_algo.functionality = intel_encoder->i2c_bus->algo->functionality; -+ intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg) >> 1; -+ intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg); - - /* Read the regs to test if we can talk to the device */ - for (i = 0; i < 0x40; i++) { -- if (!intel_sdvo_read_byte(intel_sdvo, i, &ch[i])) { -+ u8 byte; -+ -+ if (!intel_sdvo_read_byte(intel_sdvo, i, &byte)) { - DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n", - IS_SDVOB(sdvo_reg) ? 'B' : 'C'); -- goto err_i2c; -+ goto err; - } - } - -- /* setup the DDC bus. */ -- if (IS_SDVOB(sdvo_reg)) { -- intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOB DDC BUS"); -- intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg, -- "SDVOB/VGA DDC BUS"); -+ if (IS_SDVOB(sdvo_reg)) - dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; -- } else { -- intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOC DDC BUS"); -- intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg, -- "SDVOC/VGA DDC BUS"); -+ else - dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; -- } -- if (intel_encoder->ddc_bus == NULL || intel_sdvo->analog_ddc_bus == NULL) -- goto err_i2c; - -- /* Wrap with our custom algo which switches to DDC mode */ -- intel_encoder->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; -- -- /* encoder type will be decided later */ -- drm_encoder_init(dev, &intel_encoder->enc, &intel_sdvo_enc_funcs, 0); -- drm_encoder_helper_add(&intel_encoder->enc, &intel_sdvo_helper_funcs); -+ drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); - - /* In default case sdvo lvds is false */ - if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) -- goto err_enc; -+ goto err; - - if (intel_sdvo_output_setup(intel_sdvo, - intel_sdvo->caps.output_flags) != true) { - DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", - IS_SDVOB(sdvo_reg) ? 'B' : 'C'); -- goto err_enc; -+ goto err; - } - - intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); - - /* Set the input timing to the screen. Assume always input 0. */ - if (!intel_sdvo_set_target_input(intel_sdvo)) -- goto err_enc; -+ goto err; - - if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, - &intel_sdvo->pixel_clock_min, - &intel_sdvo->pixel_clock_max)) -- goto err_enc; -+ goto err; - - DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " - "clock range %dMHz - %dMHz, " -@@ -2651,16 +2606,9 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) - (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); - return true; - --err_enc: -- drm_encoder_cleanup(&intel_encoder->enc); --err_i2c: -- if (intel_sdvo->analog_ddc_bus != NULL) -- intel_i2c_destroy(intel_sdvo->analog_ddc_bus); -- if (intel_encoder->ddc_bus != NULL) -- intel_i2c_destroy(intel_encoder->ddc_bus); -- if (intel_encoder->i2c_bus != NULL) -- intel_i2c_destroy(intel_encoder->i2c_bus); --err_inteloutput: -+err: -+ drm_encoder_cleanup(&intel_encoder->base); -+ i2c_del_adapter(&intel_sdvo->ddc); - kfree(intel_sdvo); - - return false; -diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c -index 4a117e3..2f76819 100644 ---- a/drivers/gpu/drm/i915/intel_tv.c -+++ b/drivers/gpu/drm/i915/intel_tv.c -@@ -48,7 +48,7 @@ struct intel_tv { - struct intel_encoder base; - - int type; -- char *tv_format; -+ const char *tv_format; - int margin[4]; - u32 save_TV_H_CTL_1; - u32 save_TV_H_CTL_2; -@@ -350,7 +350,7 @@ static const struct video_levels component_levels = { - - - struct tv_mode { -- char *name; -+ const char *name; - int clock; - int refresh; /* in millihertz (for precision) */ - u32 oversample; -@@ -900,7 +900,14 @@ static const struct tv_mode tv_modes[] = { - - static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder) - { -- return container_of(enc_to_intel_encoder(encoder), struct intel_tv, base); -+ return container_of(encoder, struct intel_tv, base.base); -+} -+ -+static struct intel_tv *intel_attached_tv(struct drm_connector *connector) -+{ -+ return container_of(intel_attached_encoder(connector), -+ struct intel_tv, -+ base); - } - - static void -@@ -922,7 +929,7 @@ intel_tv_dpms(struct drm_encoder *encoder, int mode) - } - - static const struct tv_mode * --intel_tv_mode_lookup (char *tv_format) -+intel_tv_mode_lookup(const char *tv_format) - { - int i; - -@@ -936,22 +943,23 @@ intel_tv_mode_lookup (char *tv_format) - } - - static const struct tv_mode * --intel_tv_mode_find (struct intel_tv *intel_tv) -+intel_tv_mode_find(struct intel_tv *intel_tv) - { - return intel_tv_mode_lookup(intel_tv->tv_format); - } - - static enum drm_mode_status --intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) -+intel_tv_mode_valid(struct drm_connector *connector, -+ struct drm_display_mode *mode) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_tv *intel_tv = enc_to_intel_tv(encoder); -+ struct intel_tv *intel_tv = intel_attached_tv(connector); - const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); - - /* Ensure TV refresh is close to desired refresh */ - if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000) - < 1000) - return MODE_OK; -+ - return MODE_CLOCK_RANGE; - } - -@@ -1131,7 +1139,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - color_conversion->av); - } - -- if (IS_I965G(dev)) -+ if (INTEL_INFO(dev)->gen >= 4) - I915_WRITE(TV_CLR_KNOBS, 0x00404000); - else - I915_WRITE(TV_CLR_KNOBS, 0x00606000); -@@ -1157,12 +1165,12 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); - - /* Wait for vblank for the disable to take effect */ -- if (!IS_I9XX(dev)) -+ if (IS_GEN2(dev)) - intel_wait_for_vblank(dev, intel_crtc->pipe); - -- I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); -+ I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE); - /* Wait for vblank for the disable to take effect. */ -- intel_wait_for_vblank(dev, intel_crtc->pipe); -+ intel_wait_for_pipe_off(dev, intel_crtc->pipe); - - /* Filter ctl must be set before TV_WIN_SIZE */ - I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); -@@ -1196,7 +1204,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); - for (i = 0; i < 43; i++) - I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); -- I915_WRITE(TV_DAC, 0); -+ I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE); - I915_WRITE(TV_CTL, tv_ctl); - } - -@@ -1228,15 +1236,13 @@ static const struct drm_display_mode reported_modes[] = { - static int - intel_tv_detect_type (struct intel_tv *intel_tv) - { -- struct drm_encoder *encoder = &intel_tv->base.enc; -+ struct drm_encoder *encoder = &intel_tv->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long irqflags; - u32 tv_ctl, save_tv_ctl; - u32 tv_dac, save_tv_dac; -- int type = DRM_MODE_CONNECTOR_Unknown; -- -- tv_dac = I915_READ(TV_DAC); -+ int type; - - /* Disable TV interrupts around load detect or we'll recurse */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); -@@ -1244,19 +1250,14 @@ intel_tv_detect_type (struct intel_tv *intel_tv) - PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); - -- /* -- * Detect TV by polling) -- */ -- save_tv_dac = tv_dac; -- tv_ctl = I915_READ(TV_CTL); -- save_tv_ctl = tv_ctl; -- tv_ctl &= ~TV_ENC_ENABLE; -- tv_ctl &= ~TV_TEST_MODE_MASK; -+ save_tv_dac = tv_dac = I915_READ(TV_DAC); -+ save_tv_ctl = tv_ctl = I915_READ(TV_CTL); -+ -+ /* Poll for TV detection */ -+ tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK); - tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; -- tv_dac &= ~TVDAC_SENSE_MASK; -- tv_dac &= ~DAC_A_MASK; -- tv_dac &= ~DAC_B_MASK; -- tv_dac &= ~DAC_C_MASK; -+ -+ tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK); - tv_dac |= (TVDAC_STATE_CHG_EN | - TVDAC_A_SENSE_CTL | - TVDAC_B_SENSE_CTL | -@@ -1265,37 +1266,40 @@ intel_tv_detect_type (struct intel_tv *intel_tv) - DAC_A_0_7_V | - DAC_B_0_7_V | - DAC_C_0_7_V); -+ - I915_WRITE(TV_CTL, tv_ctl); - I915_WRITE(TV_DAC, tv_dac); - POSTING_READ(TV_DAC); -- msleep(20); - -- tv_dac = I915_READ(TV_DAC); -- I915_WRITE(TV_DAC, save_tv_dac); -- I915_WRITE(TV_CTL, save_tv_ctl); -- POSTING_READ(TV_CTL); -- msleep(20); -+ intel_wait_for_vblank(intel_tv->base.base.dev, -+ to_intel_crtc(intel_tv->base.base.crtc)->pipe); - -- /* -- * A B C -- * 0 1 1 Composite -- * 1 0 X svideo -- * 0 0 0 Component -- */ -- if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { -- DRM_DEBUG_KMS("Detected Composite TV connection\n"); -- type = DRM_MODE_CONNECTOR_Composite; -- } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { -- DRM_DEBUG_KMS("Detected S-Video TV connection\n"); -- type = DRM_MODE_CONNECTOR_SVIDEO; -- } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { -- DRM_DEBUG_KMS("Detected Component TV connection\n"); -- type = DRM_MODE_CONNECTOR_Component; -- } else { -- DRM_DEBUG_KMS("No TV connection detected\n"); -- type = -1; -+ type = -1; -+ if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) { -+ DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac); -+ /* -+ * A B C -+ * 0 1 1 Composite -+ * 1 0 X svideo -+ * 0 0 0 Component -+ */ -+ if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { -+ DRM_DEBUG_KMS("Detected Composite TV connection\n"); -+ type = DRM_MODE_CONNECTOR_Composite; -+ } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { -+ DRM_DEBUG_KMS("Detected S-Video TV connection\n"); -+ type = DRM_MODE_CONNECTOR_SVIDEO; -+ } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { -+ DRM_DEBUG_KMS("Detected Component TV connection\n"); -+ type = DRM_MODE_CONNECTOR_Component; -+ } else { -+ DRM_DEBUG_KMS("Unrecognised TV connection\n"); -+ } - } - -+ I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN); -+ I915_WRITE(TV_CTL, save_tv_ctl); -+ - /* Restore interrupt config */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | -@@ -1311,8 +1315,7 @@ intel_tv_detect_type (struct intel_tv *intel_tv) - */ - static void intel_tv_find_better_format(struct drm_connector *connector) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_tv *intel_tv = enc_to_intel_tv(encoder); -+ struct intel_tv *intel_tv = intel_attached_tv(connector); - const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); - int i; - -@@ -1344,14 +1347,13 @@ static enum drm_connector_status - intel_tv_detect(struct drm_connector *connector, bool force) - { - struct drm_display_mode mode; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_tv *intel_tv = enc_to_intel_tv(encoder); -+ struct intel_tv *intel_tv = intel_attached_tv(connector); - int type; - - mode = reported_modes[0]; - drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); - -- if (encoder->crtc && encoder->crtc->enabled) { -+ if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) { - type = intel_tv_detect_type(intel_tv); - } else if (force) { - struct drm_crtc *crtc; -@@ -1375,11 +1377,10 @@ intel_tv_detect(struct drm_connector *connector, bool force) - return connector_status_connected; - } - --static struct input_res { -- char *name; -+static const struct input_res { -+ const char *name; - int w, h; --} input_res_table[] = --{ -+} input_res_table[] = { - {"640x480", 640, 480}, - {"800x600", 800, 600}, - {"1024x768", 1024, 768}, -@@ -1396,8 +1397,7 @@ static void - intel_tv_chose_preferred_modes(struct drm_connector *connector, - struct drm_display_mode *mode_ptr) - { -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_tv *intel_tv = enc_to_intel_tv(encoder); -+ struct intel_tv *intel_tv = intel_attached_tv(connector); - const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); - - if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480) -@@ -1422,15 +1422,14 @@ static int - intel_tv_get_modes(struct drm_connector *connector) - { - struct drm_display_mode *mode_ptr; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_tv *intel_tv = enc_to_intel_tv(encoder); -+ struct intel_tv *intel_tv = intel_attached_tv(connector); - const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); - int j, count = 0; - u64 tmp; - - for (j = 0; j < ARRAY_SIZE(input_res_table); - j++) { -- struct input_res *input = &input_res_table[j]; -+ const struct input_res *input = &input_res_table[j]; - unsigned int hactive_s = input->w; - unsigned int vactive_s = input->h; - -@@ -1488,9 +1487,8 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop - uint64_t val) - { - struct drm_device *dev = connector->dev; -- struct drm_encoder *encoder = intel_attached_encoder(connector); -- struct intel_tv *intel_tv = enc_to_intel_tv(encoder); -- struct drm_crtc *crtc = encoder->crtc; -+ struct intel_tv *intel_tv = intel_attached_tv(connector); -+ struct drm_crtc *crtc = intel_tv->base.base.crtc; - int ret = 0; - bool changed = false; - -@@ -1555,7 +1553,7 @@ static const struct drm_connector_funcs intel_tv_connector_funcs = { - static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = { - .mode_valid = intel_tv_mode_valid, - .get_modes = intel_tv_get_modes, -- .best_encoder = intel_attached_encoder, -+ .best_encoder = intel_best_encoder, - }; - - static const struct drm_encoder_funcs intel_tv_enc_funcs = { -@@ -1607,7 +1605,7 @@ intel_tv_init(struct drm_device *dev) - struct intel_encoder *intel_encoder; - struct intel_connector *intel_connector; - u32 tv_dac_on, tv_dac_off, save_tv_dac; -- char **tv_format_names; -+ char *tv_format_names[ARRAY_SIZE(tv_modes)]; - int i, initial_mode = 0; - - if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) -@@ -1661,15 +1659,15 @@ intel_tv_init(struct drm_device *dev) - drm_connector_init(dev, connector, &intel_tv_connector_funcs, - DRM_MODE_CONNECTOR_SVIDEO); - -- drm_encoder_init(dev, &intel_encoder->enc, &intel_tv_enc_funcs, -+ drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs, - DRM_MODE_ENCODER_TVDAC); - -- drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc); -+ intel_connector_attach_encoder(intel_connector, intel_encoder); - intel_encoder->type = INTEL_OUTPUT_TVOUT; - intel_encoder->crtc_mask = (1 << 0) | (1 << 1); - intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT); -- intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1)); -- intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT); -+ intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1)); -+ intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT); - intel_tv->type = DRM_MODE_CONNECTOR_Unknown; - - /* BIOS margin values */ -@@ -1678,21 +1676,19 @@ intel_tv_init(struct drm_device *dev) - intel_tv->margin[TV_MARGIN_RIGHT] = 46; - intel_tv->margin[TV_MARGIN_BOTTOM] = 37; - -- intel_tv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL); -+ intel_tv->tv_format = tv_modes[initial_mode].name; - -- drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs); -+ drm_encoder_helper_add(&intel_encoder->base, &intel_tv_helper_funcs); - drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs); - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - /* Create TV properties then attach current values */ -- tv_format_names = kmalloc(sizeof(char *) * ARRAY_SIZE(tv_modes), -- GFP_KERNEL); -- if (!tv_format_names) -- goto out; - for (i = 0; i < ARRAY_SIZE(tv_modes); i++) -- tv_format_names[i] = tv_modes[i].name; -- drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names); -+ tv_format_names[i] = (char *)tv_modes[i].name; -+ drm_mode_create_tv_properties(dev, -+ ARRAY_SIZE(tv_modes), -+ tv_format_names); - - drm_connector_attach_property(connector, dev->mode_config.tv_mode_property, - initial_mode); -@@ -1708,6 +1704,5 @@ intel_tv_init(struct drm_device *dev) - drm_connector_attach_property(connector, - dev->mode_config.tv_bottom_margin_property, - intel_tv->margin[TV_MARGIN_BOTTOM]); --out: - drm_sysfs_connector_add(connector); - } -diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h -index 3e5a51a..a4c66f6 100644 ---- a/include/drm/drm_crtc.h -+++ b/include/drm/drm_crtc.h -@@ -762,6 +762,7 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev, - extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv); - extern bool drm_detect_hdmi_monitor(struct edid *edid); -+extern bool drm_detect_monitor_audio(struct edid *edid); - extern int drm_mode_page_flip_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv); - extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, -diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h -index a49e791..83a389e 100644 ---- a/include/drm/drm_dp_helper.h -+++ b/include/drm/drm_dp_helper.h -@@ -23,6 +23,9 @@ - #ifndef _DRM_DP_HELPER_H_ - #define _DRM_DP_HELPER_H_ - -+#include -+#include -+ - /* From the VESA DisplayPort spec */ - - #define AUX_NATIVE_WRITE 0x8 -diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h -index e41c74f..8c641be 100644 ---- a/include/drm/i915_drm.h -+++ b/include/drm/i915_drm.h -@@ -286,6 +286,7 @@ typedef struct drm_i915_irq_wait { - #define I915_PARAM_HAS_PAGEFLIPPING 8 - #define I915_PARAM_HAS_EXECBUF2 9 - #define I915_PARAM_HAS_BSD 10 -+#define I915_PARAM_HAS_BLT 11 - - typedef struct drm_i915_getparam { - int param; -@@ -627,8 +628,11 @@ struct drm_i915_gem_execbuffer2 { - __u32 num_cliprects; - /** This is a struct drm_clip_rect *cliprects */ - __u64 cliprects_ptr; -+#define I915_EXEC_RING_MASK (7<<0) -+#define I915_EXEC_DEFAULT (0<<0) - #define I915_EXEC_RENDER (1<<0) --#define I915_EXEC_BSD (1<<1) -+#define I915_EXEC_BSD (2<<0) -+#define I915_EXEC_BLT (3<<0) - __u64 flags; - __u64 rsvd1; - __u64 rsvd2; -diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h -new file mode 100644 -index 0000000..d3c8194 ---- /dev/null -+++ b/include/drm/intel-gtt.h -@@ -0,0 +1,18 @@ -+/* Common header for intel-gtt.ko and i915.ko */ -+ -+#ifndef _DRM_INTEL_GTT_H -+#define _DRM_INTEL_GTT_H -+struct intel_gtt { -+ /* Number of stolen gtt entries at the beginning. */ -+ unsigned int gtt_stolen_entries; -+ /* Total number of gtt entries. */ -+ unsigned int gtt_total_entries; -+ /* Part of the gtt that is mappable by the cpu, for those chips where -+ * this is not the full gtt. */ -+ unsigned int gtt_mappable_entries; -+}; -+ -+struct intel_gtt *intel_gtt_get(void); -+ -+#endif -+ diff --git a/drm-intel-big-hammer.patch b/drm-intel-big-hammer.patch index 0d7f7f08d..63dc016b1 100644 --- a/drm-intel-big-hammer.patch +++ b/drm-intel-big-hammer.patch @@ -1,16 +1,16 @@ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c -index 6da2c6d..f508b86 100644 +index 37427e4..08af9db 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c -@@ -3738,6 +3738,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - if (ret) - goto pre_mutex_err; +@@ -2553,6 +2553,11 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, + + mutex_lock(&dev->struct_mutex); + /* We don't get the flushing right for these chipsets, use the -+ * big hammer for now to avoid random crashiness. */ ++ * big hamer for now to avoid random crashiness. */ + if (IS_I85X(dev) || IS_I865G(dev)) + wbinvd(); + - if (dev_priv->mm.suspended) { - mutex_unlock(&dev->struct_mutex); - ret = -EBUSY; + i915_verify_inactive(dev, __FILE__, __LINE__); + + if (dev_priv->mm.wedged) { diff --git a/drm-intel-make-lvds-work.patch b/drm-intel-make-lvds-work.patch index 6c089b89e..5ca0152da 100644 --- a/drm-intel-make-lvds-work.patch +++ b/drm-intel-make-lvds-work.patch @@ -1,20 +1,19 @@ -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 0cece04..63bbb4b 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -4580,7 +4580,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - struct drm_connector *connector, int dpms_mode) +diff -up linux-2.6.33.noarch/drivers/gpu/drm/i915/intel_display.c.orig linux-2.6.33.noarch/drivers/gpu/drm/i915/intel_display.c +--- linux-2.6.33.noarch/drivers/gpu/drm/i915/intel_display.c.orig 2010-03-31 16:59:39.901995671 -0400 ++++ linux-2.6.33.noarch/drivers/gpu/drm/i915/intel_display.c 2010-03-31 17:01:05.416996744 -0400 +@@ -3757,7 +3757,6 @@ struct drm_crtc *intel_get_load_detect_p + void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, int dpms_mode) { - struct drm_encoder *encoder = &intel_encoder->base; + struct drm_encoder *encoder = &intel_encoder->enc; - struct drm_device *dev = encoder->dev; struct drm_crtc *crtc = encoder->crtc; struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -@@ -4590,7 +4589,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - connector->encoder = NULL; +@@ -3767,7 +3766,6 @@ void intel_release_load_detect_pipe(stru + intel_encoder->base.encoder = NULL; intel_encoder->load_detect_temp = false; crtc->enabled = drm_helper_crtc_in_use(crtc); - drm_helper_disable_unused_functions(dev); } - /* Switch crtc and encoder back off if necessary */ + /* Switch crtc and output back off if necessary */ diff --git a/kernel.spec b/kernel.spec index c90b027a7..8ba295ee1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1226,7 +1226,7 @@ ApplyPatch acpi-update-battery-information-on-notification-0x81.patch ApplyPatch linux-2.6-debug-sizeof-structs.patch ApplyPatch linux-2.6-debug-nmi-timeout.patch ApplyPatch linux-2.6-debug-taint-vm.patch -###FIX###ApplyPatch linux-2.6-debug-vm-would-have-oomkilled.patch +ApplyPatch linux-2.6-debug-vm-would-have-oomkilled.patch ApplyPatch linux-2.6-debug-always-inline-kzalloc.patch ApplyPatch debug-tty-print-dev-name.patch @@ -1302,9 +1302,8 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM -#ApplyPatch drm-intel-2.6.37-rc2.patch -#ApplyPatch drm-intel-big-hammer.patch -#ApplyPatch drm-intel-make-lvds-work.patch +ApplyPatch drm-intel-big-hammer.patch +ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch radeon-mc-vram-map-needs-to-be-gt-pci-aperture.patch diff --git a/linux-2.6-debug-vm-would-have-oomkilled.patch b/linux-2.6-debug-vm-would-have-oomkilled.patch index dd8ba3f0a..8bd05ab06 100644 --- a/linux-2.6-debug-vm-would-have-oomkilled.patch +++ b/linux-2.6-debug-vm-would-have-oomkilled.patch @@ -1,26 +1,30 @@ -From 03657519851cd180983db4bd0c38eaeed4aa2962 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 11 Jan 2010 08:25:12 -0500 -Subject: linux-2.6-debug-vm-would-have-oomkilled.patch +From beb764ac03e52eba1a654afb4273fab1f9de3cff Mon Sep 17 00:00:00 2001 +From: Kyle McMartin +Date: Mon, 29 Nov 2010 20:59:14 -0500 +Subject: [PATCH] linux-2.6-debug-vm-would_have_oomkilled --- - kernel/sysctl.c | 8 ++++++++ - mm/oom_kill.c | 7 +++++++ - 2 files changed, 15 insertions(+), 0 deletions(-) + include/linux/oom.h | 1 + + kernel/sysctl.c | 7 +++++++ + mm/oom_kill.c | 8 ++++++++ + 3 files changed, 16 insertions(+), 0 deletions(-) +diff --git a/include/linux/oom.h b/include/linux/oom.h +index 5e3aa83..79a27b4 100644 +--- a/include/linux/oom.h ++++ b/include/linux/oom.h +@@ -72,5 +72,6 @@ extern struct task_struct *find_lock_task_mm(struct task_struct *p); + extern int sysctl_oom_dump_tasks; + extern int sysctl_oom_kill_allocating_task; + extern int sysctl_panic_on_oom; ++extern int sysctl_would_have_oomkilled; + #endif /* __KERNEL__*/ + #endif /* _INCLUDE_LINUX_OOM_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 8a68b24..72a4ff1 100644 +index 5abfa15..a0fed6d 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c -@@ -71,6 +71,7 @@ extern int sysctl_overcommit_ratio; - extern int sysctl_panic_on_oom; - extern int sysctl_oom_kill_allocating_task; - extern int sysctl_oom_dump_tasks; -+extern int sysctl_would_have_oomkilled; - extern int max_threads; - extern int core_uses_pid; - extern int suid_dumpable; -@@ -973,6 +974,13 @@ static struct ctl_table vm_table[] = { +@@ -1000,6 +1000,13 @@ static struct ctl_table vm_table[] = { .proc_handler = proc_dointvec, }, { @@ -28,37 +32,38 @@ index 8a68b24..72a4ff1 100644 + .data = &sysctl_would_have_oomkilled, + .maxlen = sizeof(sysctl_would_have_oomkilled), + .mode = 0644, -+ .proc_handler = &proc_dointvec, ++ .proc_handler = proc_dointvec, + }, + { .procname = "overcommit_ratio", .data = &sysctl_overcommit_ratio, .maxlen = sizeof(sysctl_overcommit_ratio), diff --git a/mm/oom_kill.c b/mm/oom_kill.c -index f52481b..a892f07 100644 +index 7dcca55..281ac39 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c -@@ -31,6 +31,7 @@ +@@ -35,6 +35,7 @@ int sysctl_panic_on_oom; int sysctl_oom_kill_allocating_task; - int sysctl_oom_dump_tasks; + int sysctl_oom_dump_tasks = 1; +int sysctl_would_have_oomkilled; static DEFINE_SPINLOCK(zone_scan_lock); - /* #define DEBUG */ -@@ -396,6 +397,12 @@ static void __oom_kill_task(struct task_struct *p, int verbose) - return; + #ifdef CONFIG_NUMA +@@ -477,6 +478,13 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, } -+ if (sysctl_would_have_oomkilled == 1) { -+ printk(KERN_ERR "Would have killed process %d (%s). But continuing instead.\n", -+ task_pid_nr(p), p->comm); -+ return; + task_lock(p); ++ if (sysctl_would_have_oomkilled) { ++ printk(KERN_ERR "%s: would have killed process %d (%s), but continuing instead...\n", ++ __func__, task_pid_nr(p), p->comm); ++ task_unlock(p); ++ return 0; + } + - if (verbose) - printk(KERN_ERR "Killed process %d (%s) " - "vsz:%lukB, anon-rss:%lukB, file-rss:%lukB\n", + pr_err("%s: Kill process %d (%s) score %d or sacrifice child\n", + message, task_pid_nr(p), p->comm, points); + task_unlock(p); -- -1.6.5.2 +1.7.3.2