Merge branch 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Jan 2010 02:16:17 +0000 (18:16 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Jan 2010 02:16:17 +0000 (18:16 -0800)
* 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel: (23 commits)
  drm/i915: remove full registers dump debug
  drm/i915: Add DP dpll limit on ironlake and use existing DPLL search function
  drm/i915: Select the correct BPC for LVDS on Ironlake
  drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in pipeconf on Ironlake
  drm/i915: Enable/disable the dithering for LVDS based on VBT setting
  drm/i915: Permit pinning whilst the device is 'suspended'
  drm/i915: Hold struct mutex whilst pinning power context bo.
  drm/i915: fix unused var
  drm/i915: Storage class should be before const qualifier
  drm/i915: remove render reclock support
  drm/i915: Fix RC6 suspend/resume
  drm/i915: execbuf2 support
  drm/i915: Reload hangcheck timer too for Ironlake
  drm/i915: only enable hotplug for detected outputs
  drm/i915: Track whether cursor needs physical address in intel_device_info
  drm/i915: Implement IS_* macros using static tables
  drm/i915: Move PCI IDs into i915 driver
  drm/i915: Update LVDS connector status when receiving ACPI LID event
  drm/i915: Add MALATA PC-81005 to ACPI LID quirk list
  drm/i915: implement new pm ops for i915
  ...

17 files changed:
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
include/drm/i915_drm.h

index 18476bf..9c9998c 100644 (file)
@@ -272,7 +272,7 @@ static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_co
                mem = kmap_atomic(pages[page], KM_USER0);
                for (i = 0; i < PAGE_SIZE; i += 4)
                        seq_printf(m, "%08x :  %08x\n", i, mem[i / 4]);
-               kunmap_atomic(pages[page], KM_USER0);
+               kunmap_atomic(mem, KM_USER0);
        }
 }
 
@@ -386,34 +386,6 @@ out:
        return 0;
 }
 
-static int i915_registers_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;
-       uint32_t reg;
-
-#define DUMP_RANGE(start, end) \
-       for (reg=start; reg < end; reg += 4) \
-       seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg));
-
-       DUMP_RANGE(0x00000, 0x00fff);   /* VGA registers */
-       DUMP_RANGE(0x02000, 0x02fff);   /* instruction, memory, interrupt control registers */
-       DUMP_RANGE(0x03000, 0x031ff);   /* FENCE and PPGTT control registers */
-       DUMP_RANGE(0x03200, 0x03fff);   /* frame buffer compression registers */
-       DUMP_RANGE(0x05000, 0x05fff);   /* I/O control registers */
-       DUMP_RANGE(0x06000, 0x06fff);   /* clock control registers */
-       DUMP_RANGE(0x07000, 0x07fff);   /* 3D internal debug registers */
-       DUMP_RANGE(0x07400, 0x088ff);   /* GPE debug registers */
-       DUMP_RANGE(0x0a000, 0x0afff);   /* display palette registers */
-       DUMP_RANGE(0x10000, 0x13fff);   /* MMIO MCHBAR */
-       DUMP_RANGE(0x30000, 0x3ffff);   /* overlay registers */
-       DUMP_RANGE(0x60000, 0x6ffff);   /* display engine pipeline registers */
-       DUMP_RANGE(0x70000, 0x72fff);   /* display and cursor registers */
-       DUMP_RANGE(0x73000, 0x73fff);   /* performance counters */
-
-       return 0;
-}
-
 static int
 i915_wedged_open(struct inode *inode,
                 struct file *filp)
@@ -519,7 +491,6 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
 }
 
 static struct drm_info_list i915_debugfs_list[] = {
-       {"i915_regs", i915_registers_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},
index 701bfea..c2b1108 100644 (file)
@@ -813,9 +813,13 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_PAGEFLIPPING:
                value = 1;
                break;
+       case I915_PARAM_HAS_EXECBUF2:
+               /* depends on GEM */
+               value = dev_priv->has_gem;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
-                                       param->param);
+                                param->param);
                return -EINVAL;
        }
 
@@ -1117,7 +1121,8 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_mm_node *compressed_fb, *compressed_llb;
-       unsigned long cfb_base, ll_base;
+       unsigned long cfb_base;
+       unsigned long ll_base = 0;
 
        /* Leave 1M for line length buffer & misc. */
        compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
@@ -1200,14 +1205,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
        dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
                0xff000000;
 
-       if (IS_MOBILE(dev) || IS_I9XX(dev))
-               dev_priv->cursor_needs_physical = true;
-       else
-               dev_priv->cursor_needs_physical = false;
-
-       if (IS_I965G(dev) || IS_G33(dev))
-               dev_priv->cursor_needs_physical = false;
-
        /* 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));
@@ -1257,6 +1254,8 @@ static int i915_load_modeset_init(struct drm_device *dev,
        if (ret)
                goto destroy_ringbuffer;
 
+       intel_modeset_init(dev);
+
        ret = drm_irq_install(dev);
        if (ret)
                goto destroy_ringbuffer;
@@ -1271,8 +1270,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
 
        I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
 
-       intel_modeset_init(dev);
-
        drm_helper_initial_config(dev);
 
        return 0;
@@ -1360,7 +1357,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        resource_size_t base, size;
-       int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+       int ret = 0, mmio_bar;
        uint32_t agp_size, prealloc_size, prealloc_start;
 
        /* i915 has 4 more counters */
@@ -1376,8 +1373,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = (void *)dev_priv;
        dev_priv->dev = dev;
+       dev_priv->info = (struct intel_device_info *) flags;
 
        /* Add register map (needed for suspend/resume) */
+       mmio_bar = IS_I9XX(dev) ? 0 : 1;
        base = drm_get_resource_start(dev, mmio_bar);
        size = drm_get_resource_len(dev, mmio_bar);
 
@@ -1652,6 +1651,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
index 24286ca..2ffffd7 100644 (file)
@@ -33,7 +33,6 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#include "drm_pciids.h"
 #include <linux/console.h>
 #include "drm_crtc_helper.h"
 
@@ -48,8 +47,124 @@ module_param_named(powersave, i915_powersave, int, 0400);
 
 static struct drm_driver driver;
 
-static struct pci_device_id pciidlist[] = {
-       i915_PCI_IDS
+#define INTEL_VGA_DEVICE(id, info) {           \
+       .class = PCI_CLASS_DISPLAY_VGA << 8,    \
+       .class_mask = 0xffff00,                 \
+       .vendor = 0x8086,                       \
+       .device = id,                           \
+       .subvendor = PCI_ANY_ID,                \
+       .subdevice = PCI_ANY_ID,                \
+       .driver_data = (unsigned long) info }
+
+const static struct intel_device_info intel_i830_info = {
+       .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_845g_info = {
+       .is_i8xx = 1,
+};
+
+const static struct intel_device_info intel_i85x_info = {
+       .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_i865g_info = {
+       .is_i8xx = 1,
+};
+
+const static struct intel_device_info intel_i915g_info = {
+       .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i915gm_info = {
+       .is_i9xx = 1,  .is_mobile = 1, .has_fbc = 1,
+       .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i945g_info = {
+       .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i945gm_info = {
+       .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1,
+       .has_hotplug = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_i965g_info = {
+       .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_i965gm_info = {
+       .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
+       .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_g33_info = {
+       .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_g45_info = {
+       .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_gm45_info = {
+       .is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
+       .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_pineview_info = {
+       .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_ironlake_d_info = {
+       .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+       .has_pipe_cxsr = 1,
+       .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_ironlake_m_info = {
+       .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
+       .need_gfx_hws = 1, .has_rc6 = 1,
+       .has_hotplug = 1,
+};
+
+const static struct pci_device_id pciidlist[] = {
+       INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
+       INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
+       INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
+       INTEL_VGA_DEVICE(0x35e8, &intel_i85x_info),
+       INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
+       INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
+       INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
+       INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
+       INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
+       INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
+       INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
+       INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
+       INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
+       INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
+       INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
+       INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
+       INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
+       INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
+       INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
+       INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
+       INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
+       INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
+       INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
+       INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
+       {0, 0, 0}
 };
 
 #if defined(CONFIG_DRM_I915_KMS)
@@ -284,6 +399,52 @@ i915_pci_resume(struct pci_dev *pdev)
        return i915_resume(dev);
 }
 
+static int
+i915_pm_suspend(struct device *dev)
+{
+       return i915_pci_suspend(to_pci_dev(dev), PMSG_SUSPEND);
+}
+
+static int
+i915_pm_resume(struct device *dev)
+{
+       return i915_pci_resume(to_pci_dev(dev));
+}
+
+static int
+i915_pm_freeze(struct device *dev)
+{
+       return i915_pci_suspend(to_pci_dev(dev), PMSG_FREEZE);
+}
+
+static int
+i915_pm_thaw(struct device *dev)
+{
+       /* thaw during hibernate, do nothing! */
+       return 0;
+}
+
+static int
+i915_pm_poweroff(struct device *dev)
+{
+       return i915_pci_suspend(to_pci_dev(dev), PMSG_HIBERNATE);
+}
+
+static int
+i915_pm_restore(struct device *dev)
+{
+       return i915_pci_resume(to_pci_dev(dev));
+}
+
+const struct dev_pm_ops i915_pm_ops = {
+     .suspend = i915_pm_suspend,
+     .resume = i915_pm_resume,
+     .freeze = i915_pm_freeze,
+     .thaw = i915_pm_thaw,
+     .poweroff = i915_pm_poweroff,
+     .restore = i915_pm_restore,
+};
+
 static struct vm_operations_struct i915_gem_vm_ops = {
        .fault = i915_gem_fault,
        .open = drm_gem_vm_open,
@@ -303,8 +464,6 @@ static struct drm_driver driver = {
        .lastclose = i915_driver_lastclose,
        .preclose = i915_driver_preclose,
        .postclose = i915_driver_postclose,
-       .suspend = i915_suspend,
-       .resume = i915_resume,
        .device_is_agp = i915_driver_device_is_agp,
        .enable_vblank = i915_enable_vblank,
        .disable_vblank = i915_disable_vblank,
@@ -344,10 +503,7 @@ static struct drm_driver driver = {
                 .id_table = pciidlist,
                 .probe = i915_pci_probe,
                 .remove = i915_pci_remove,
-#ifdef CONFIG_PM
-                .resume = i915_pci_resume,
-                .suspend = i915_pci_suspend,
-#endif
+                .driver.pm = &i915_pm_ops,
        },
 
        .name = DRIVER_NAME,
index fbecac7..29dd676 100644 (file)
@@ -172,9 +172,31 @@ struct drm_i915_display_funcs {
 
 struct intel_overlay;
 
+struct intel_device_info {
+       u8 is_mobile : 1;
+       u8 is_i8xx : 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_ironlake : 1;
+       u8 has_fbc : 1;
+       u8 has_rc6 : 1;
+       u8 has_pipe_cxsr : 1;
+       u8 has_hotplug : 1;
+       u8 cursor_needs_physical : 1;
+};
+
 typedef struct drm_i915_private {
        struct drm_device *dev;
 
+       const struct intel_device_info *info;
+
        int has_gem;
 
        void __iomem *regs;
@@ -232,8 +254,6 @@ typedef struct drm_i915_private {
        int hangcheck_count;
        uint32_t last_acthd;
 
-       bool cursor_needs_physical;
-
        struct drm_mm vram;
 
        unsigned long cfb_size;
@@ -287,8 +307,6 @@ typedef struct drm_i915_private {
        u32 saveDSPACNTR;
        u32 saveDSPBCNTR;
        u32 saveDSPARB;
-       u32 saveRENDERSTANDBY;
-       u32 savePWRCTXA;
        u32 saveHWS;
        u32 savePIPEACONF;
        u32 savePIPEBCONF;
@@ -561,6 +579,7 @@ typedef struct drm_i915_private {
        u16 orig_clock;
        int child_dev_num;
        struct child_device_config *child_dev;
+       struct drm_connector *int_lvds_connector;
 } drm_i915_private_t;
 
 /** driver private structure attached to each drm_gem_object */
@@ -794,6 +813,8 @@ int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *file_priv);
 int i915_gem_execbuffer(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
+int i915_gem_execbuffer2(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
 int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
 int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
@@ -860,6 +881,9 @@ void i915_gem_shrinker_exit(void);
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
 void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
 void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
+bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
+                   int tiling_mode);
+bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj);
 
 /* i915_gem_debug.c */
 void i915_gem_dump_object(struct drm_gem_object *obj, int len,
@@ -982,67 +1006,33 @@ extern void g4x_disable_fbc(struct drm_device *dev);
 extern int i915_wrap_ring(struct drm_device * dev);
 extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
-#define IS_I830(dev) ((dev)->pci_device == 0x3577)
-#define IS_845G(dev) ((dev)->pci_device == 0x2562)
-#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
-#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
-#define IS_I8XX(dev) (IS_I830(dev) || IS_845G(dev) || IS_I85X(dev) || IS_I865G(dev))
-
-#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
-#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
-#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
-#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\
-                       (dev)->pci_device == 0x27AE)
-#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
-                      (dev)->pci_device == 0x2982 || \
-                      (dev)->pci_device == 0x2992 || \
-                      (dev)->pci_device == 0x29A2 || \
-                      (dev)->pci_device == 0x2A02 || \
-                      (dev)->pci_device == 0x2A12 || \
-                      (dev)->pci_device == 0x2A42 || \
-                      (dev)->pci_device == 0x2E02 || \
-                      (dev)->pci_device == 0x2E12 || \
-                      (dev)->pci_device == 0x2E22 || \
-                      (dev)->pci_device == 0x2E32 || \
-                      (dev)->pci_device == 0x2E42 || \
-                      (dev)->pci_device == 0x0042 || \
-                      (dev)->pci_device == 0x0046)
-
-#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
-                       (dev)->pci_device == 0x2A12)
-
-#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
-
-#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
-                    (dev)->pci_device == 0x2E12 || \
-                    (dev)->pci_device == 0x2E22 || \
-                    (dev)->pci_device == 0x2E32 || \
-                    (dev)->pci_device == 0x2E42 || \
-                    IS_GM45(dev))
-
-#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001)
-#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011)
-#define IS_PINEVIEW(dev) (IS_PINEVIEW_G(dev) || IS_PINEVIEW_M(dev))
-
-#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 || \
-                       (dev)->pci_device == 0x29B2 ||  \
-                       (dev)->pci_device == 0x29D2 ||  \
-                       (IS_PINEVIEW(dev)))
-
+#define INTEL_INFO(dev)        (((struct drm_i915_private *) (dev)->dev_private)->info)
+
+#define IS_I830(dev)           ((dev)->pci_device == 0x3577)
+#define IS_845G(dev)           ((dev)->pci_device == 0x2562)
+#define IS_I85X(dev)           ((dev)->pci_device == 0x3582)
+#define IS_I865G(dev)          ((dev)->pci_device == 0x2572)
+#define IS_I8XX(dev)           (INTEL_INFO(dev)->is_i8xx)
+#define IS_I915G(dev)          (INTEL_INFO(dev)->is_i915g)
+#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_GM45(dev)           ((dev)->pci_device == 0x2A42)
+#define IS_G4X(dev)            (INTEL_INFO(dev)->is_g4x)
+#define IS_PINEVIEW_G(dev)     ((dev)->pci_device == 0xa001)
+#define IS_PINEVIEW_M(dev)     ((dev)->pci_device == 0xa011)
+#define IS_PINEVIEW(dev)       (INTEL_INFO(dev)->is_pineview)
+#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)       (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev))
-
-#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
-                     IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \
-                     IS_IRONLAKE(dev))
+#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_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
-                       IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \
-                       IS_PINEVIEW(dev) || IS_IRONLAKE_M(dev))
+#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
 
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \
-                               IS_IRONLAKE(dev))
 /* 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.
  */
@@ -1054,17 +1044,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define SUPPORTS_EDP(dev)              (IS_IRONLAKE_M(dev))
 #define SUPPORTS_TV(dev)               (IS_I9XX(dev) && IS_MOBILE(dev) && \
                                        !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev))
-#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev))
+#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_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
-#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \
-                          (IS_I9XX(dev) || IS_GM45(dev)) && \
-                          !IS_PINEVIEW(dev) && \
-                          !IS_IRONLAKE(dev))
-#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IRONLAKE_M(dev))
+#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 PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
index 8c463cf..21950ef 100644 (file)
@@ -2021,9 +2021,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
        /* blow away mappings if mapped through GTT */
        i915_gem_release_mmap(obj);
 
-       if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-               i915_gem_clear_fence_reg(obj);
-
        /* Move the object to the CPU domain to ensure that
         * any possible CPU writes while it's not in the GTT
         * are flushed when we go to remap it. This will
@@ -2039,6 +2036,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
 
        BUG_ON(obj_priv->active);
 
+       /* 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);
@@ -2581,9 +2582,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
        bool retry_alloc = false;
        int ret;
 
-       if (dev_priv->mm.suspended)
-               return -EBUSY;
-
        if (obj_priv->madv != I915_MADV_WILLNEED) {
                DRM_ERROR("Attempting to bind a purgeable object\n");
                return -EINVAL;
@@ -3198,7 +3196,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
 static int
 i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                                 struct drm_file *file_priv,
-                                struct drm_i915_gem_exec_object *entry,
+                                struct drm_i915_gem_exec_object2 *entry,
                                 struct drm_i915_gem_relocation_entry *relocs)
 {
        struct drm_device *dev = obj->dev;
@@ -3206,12 +3204,35 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
        struct drm_i915_gem_object *obj_priv = obj->driver_private;
        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_obj_fenceable(dev, obj))
+               i915_gem_object_unbind(obj);
 
        /* 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;
 
+       /*
+        * 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) {
+                       if (ret != -EBUSY && ret != -ERESTARTSYS)
+                               DRM_ERROR("Failure to install fence: %d\n",
+                                         ret);
+                       i915_gem_object_unpin(obj);
+                       return ret;
+               }
+       }
+
        entry->offset = obj_priv->gtt_offset;
 
        /* Apply the relocations, using the GTT aperture to avoid cache
@@ -3373,7 +3394,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
  */
 static int
 i915_dispatch_gem_execbuffer(struct drm_device *dev,
-                             struct drm_i915_gem_execbuffer *exec,
+                             struct drm_i915_gem_execbuffer2 *exec,
                              struct drm_clip_rect *cliprects,
                              uint64_t exec_offset)
 {
@@ -3463,7 +3484,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
 }
 
 static int
-i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
+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)
 {
@@ -3478,8 +3499,10 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
        }
 
        *relocs = drm_calloc_large(reloc_count, sizeof(**relocs));
-       if (*relocs == NULL)
+       if (*relocs == NULL) {
+               DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count);
                return -ENOMEM;
+       }
 
        for (i = 0; i < buffer_count; i++) {
                struct drm_i915_gem_relocation_entry __user *user_relocs;
@@ -3503,7 +3526,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
 }
 
 static int
-i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
+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)
 {
@@ -3536,7 +3559,7 @@ err:
 }
 
 static int
-i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec,
+i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec,
                           uint64_t exec_offset)
 {
        uint32_t exec_start, exec_len;
@@ -3589,18 +3612,18 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev,
 }
 
 int
-i915_gem_execbuffer(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv)
+i915_gem_do_execbuffer(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv,
+                      struct drm_i915_gem_execbuffer2 *args,
+                      struct drm_i915_gem_exec_object2 *exec_list)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_gem_execbuffer *args = data;
-       struct drm_i915_gem_exec_object *exec_list = NULL;
        struct drm_gem_object **object_list = NULL;
        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;
-       int ret, ret2, i, pinned = 0;
+       int ret = 0, ret2, i, pinned = 0;
        uint64_t exec_offset;
        uint32_t seqno, flush_domains, reloc_index;
        int pin_tries, flips;
@@ -3614,25 +3637,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
                return -EINVAL;
        }
-       /* Copy in the exec list from userland */
-       exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
        object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
-       if (exec_list == NULL || object_list == NULL) {
-               DRM_ERROR("Failed to allocate exec or object list "
-                         "for %d buffers\n",
+       if (object_list == NULL) {
+               DRM_ERROR("Failed to allocate object list for %d buffers\n",
                          args->buffer_count);
                ret = -ENOMEM;
                goto pre_mutex_err;
        }
-       ret = copy_from_user(exec_list,
-                            (struct drm_i915_relocation_entry __user *)
-                            (uintptr_t) args->buffers_ptr,
-                            sizeof(*exec_list) * args->buffer_count);
-       if (ret != 0) {
-               DRM_ERROR("copy %d exec entries failed %d\n",
-                         args->buffer_count, ret);
-               goto pre_mutex_err;
-       }
 
        if (args->num_cliprects != 0) {
                cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects),
@@ -3884,20 +3895,6 @@ err:
 
        mutex_unlock(&dev->struct_mutex);
 
-       if (!ret) {
-               /* Copy the new buffer offsets back to the user's exec list. */
-               ret = copy_to_user((struct drm_i915_relocation_entry __user *)
-                                  (uintptr_t) args->buffers_ptr,
-                                  exec_list,
-                                  sizeof(*exec_list) * args->buffer_count);
-               if (ret) {
-                       ret = -EFAULT;
-                       DRM_ERROR("failed to copy %d exec entries "
-                                 "back to user (%d)\n",
-                                 args->buffer_count, ret);
-               }
-       }
-
        /* 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
@@ -3914,12 +3911,158 @@ err:
 
 pre_mutex_err:
        drm_free_large(object_list);
-       drm_free_large(exec_list);
        kfree(cliprects);
 
        return ret;
 }
 
+/*
+ * Legacy execbuffer just creates an exec2 list from the original exec object
+ * list array and passes it to the real function.
+ */
+int
+i915_gem_execbuffer(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_i915_gem_execbuffer *args = data;
+       struct drm_i915_gem_execbuffer2 exec2;
+       struct drm_i915_gem_exec_object *exec_list = NULL;
+       struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+       int ret, i;
+
+#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->buffer_count < 1) {
+               DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
+               return -EINVAL;
+       }
+
+       /* Copy in the exec list from userland */
+       exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
+       exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+       if (exec_list == NULL || exec2_list == NULL) {
+               DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+                         args->buffer_count);
+               drm_free_large(exec_list);
+               drm_free_large(exec2_list);
+               return -ENOMEM;
+       }
+       ret = copy_from_user(exec_list,
+                            (struct drm_i915_relocation_entry __user *)
+                            (uintptr_t) args->buffers_ptr,
+                            sizeof(*exec_list) * args->buffer_count);
+       if (ret != 0) {
+               DRM_ERROR("copy %d exec entries failed %d\n",
+                         args->buffer_count, ret);
+               drm_free_large(exec_list);
+               drm_free_large(exec2_list);
+               return -EFAULT;
+       }
+
+       for (i = 0; i < args->buffer_count; i++) {
+               exec2_list[i].handle = exec_list[i].handle;
+               exec2_list[i].relocation_count = exec_list[i].relocation_count;
+               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))
+                       exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
+               else
+                       exec2_list[i].flags = 0;
+       }
+
+       exec2.buffers_ptr = args->buffers_ptr;
+       exec2.buffer_count = args->buffer_count;
+       exec2.batch_start_offset = args->batch_start_offset;
+       exec2.batch_len = args->batch_len;
+       exec2.DR1 = args->DR1;
+       exec2.DR4 = args->DR4;
+       exec2.num_cliprects = args->num_cliprects;
+       exec2.cliprects_ptr = args->cliprects_ptr;
+       exec2.flags = 0;
+
+       ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
+       if (!ret) {
+               /* Copy the new buffer offsets back to the user's exec list. */
+               for (i = 0; i < args->buffer_count; i++)
+                       exec_list[i].offset = exec2_list[i].offset;
+               /* ... and back out to userspace */
+               ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+                                  (uintptr_t) args->buffers_ptr,
+                                  exec_list,
+                                  sizeof(*exec_list) * args->buffer_count);
+               if (ret) {
+                       ret = -EFAULT;
+                       DRM_ERROR("failed to copy %d exec entries "
+                                 "back to user (%d)\n",
+                                 args->buffer_count, ret);
+               }
+       } else {
+               DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret);
+       }
+
+       drm_free_large(exec_list);
+       drm_free_large(exec2_list);
+       return ret;
+}
+
+int
+i915_gem_execbuffer2(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
+{
+       struct drm_i915_gem_execbuffer2 *args = data;
+       struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+       int 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->buffer_count < 1) {
+               DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
+               return -EINVAL;
+       }
+
+       exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+       if (exec2_list == NULL) {
+               DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+                         args->buffer_count);
+               return -ENOMEM;
+       }
+       ret = copy_from_user(exec2_list,
+                            (struct drm_i915_relocation_entry __user *)
+                            (uintptr_t) args->buffers_ptr,
+                            sizeof(*exec2_list) * args->buffer_count);
+       if (ret != 0) {
+               DRM_ERROR("copy %d exec entries failed %d\n",
+                         args->buffer_count, ret);
+               drm_free_large(exec2_list);
+               return -EFAULT;
+       }
+
+       ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list);
+       if (!ret) {
+               /* Copy the new buffer offsets back to the user's exec list. */
+               ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+                                  (uintptr_t) args->buffers_ptr,
+                                  exec2_list,
+                                  sizeof(*exec2_list) * args->buffer_count);
+               if (ret) {
+                       ret = -EFAULT;
+                       DRM_ERROR("failed to copy %d exec entries "
+                                 "back to user (%d)\n",
+                                 args->buffer_count, ret);
+               }
+       }
+
+       drm_free_large(exec2_list);
+       return ret;
+}
+
 int
 i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
 {
@@ -3933,19 +4076,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
                if (ret)
                        return ret;
        }
-       /*
-        * Pre-965 chips need a fence register set up in order to
-        * properly handle tiled surfaces.
-        */
-       if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
-               ret = i915_gem_object_get_fence_reg(obj);
-               if (ret != 0) {
-                       if (ret != -EBUSY && ret != -ERESTARTSYS)
-                               DRM_ERROR("Failure to install fence: %d\n",
-                                         ret);
-                       return ret;
-               }
-       }
+
        obj_priv->pin_count++;
 
        /* If the object is not active and not pending a flush,
index 30d6af6..df278b2 100644 (file)
@@ -304,35 +304,39 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
 
 
 /**
- * Returns the size of the fence for a tiled object of the given size.
+ * Returns whether an object is currently fenceable.  If not, it may need
+ * to be unbound and have its pitch adjusted.
  */
-static int
-i915_get_fence_size(struct drm_device *dev, int size)
+bool
+i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj)
 {
-       int i;
-       int start;
+       struct drm_i915_gem_object *obj_priv = obj->driver_private;
 
        if (IS_I965G(dev)) {
                /* The 965 can have fences at any page boundary. */
-               return ALIGN(size, 4096);
+               if (obj->size & 4095)
+                       return false;
+               return true;
+       } else if (IS_I9XX(dev)) {
+               if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
+                       return false;
        } else {
-               /* Align the size to a power of two greater than the smallest
-                * fence size.
-                */
-               if (IS_I9XX(dev))
-                       start = 1024 * 1024;
-               else
-                       start = 512 * 1024;
+               if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
+                       return false;
+       }
 
-               for (i = start; i < size; i <<= 1)
-                       ;
+       /* Power of two sized... */
+       if (obj->size & (obj->size - 1))
+               return false;
 
-               return i;
-       }
+       /* Objects must be size aligned as well */
+       if (obj_priv->gtt_offset & (obj->size - 1))
+               return false;
+       return true;
 }
 
 /* Check pitch constriants for all chips & tiling formats */
-static bool
+bool
 i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
 {
        int tile_width;
@@ -384,12 +388,6 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
        if (stride & (stride - 1))
                return false;
 
-       /* We don't 0handle the aperture area covered by the fence being bigger
-        * than the object size.
-        */
-       if (i915_get_fence_size(dev, size) != size)
-               return false;
-
        return true;
 }
 
index 85f4c5d..7cd8110 100644 (file)
@@ -313,6 +313,8 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
                        dev_priv->mm.irq_gem_seqno = seqno;
                        trace_i915_gem_request_complete(dev, seqno);
                        DRM_WAKEUP(&dev_priv->irq_queue);
+                       dev_priv->hangcheck_count = 0;
+                       mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
                }
 
                if (de_iir & DE_GSE)
@@ -1084,6 +1086,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
        (void) I915_READ(IER);
 }
 
+/*
+ * Must be called after intel_modeset_init or hotplug interrupts won't be
+ * enabled correctly.
+ */
 int i915_driver_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1106,19 +1112,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        if (I915_HAS_HOTPLUG(dev)) {
                u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
 
-               /* Leave other bits alone */
-               hotplug_en |= HOTPLUG_EN_MASK;
+               /* Note HDMI and DP share bits */
+               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
+                       hotplug_en |= CRT_HOTPLUG_INT_EN;
+               /* Ignore TV since it's buggy */
+
                I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 
-               dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
-                       TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
-                       SDVOB_HOTPLUG_INT_STATUS;
-               if (IS_G4X(dev)) {
-                       dev_priv->hotplug_supported_mask |=
-                               HDMIB_HOTPLUG_INT_STATUS |
-                               HDMIC_HOTPLUG_INT_STATUS |
-                               HDMID_HOTPLUG_INT_STATUS;
-               }
                /* Enable in IER... */
                enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
                /* and unmask in IMR */
index 974b3cf..149d360 100644 (file)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
 #define CRT_HOTPLUG_MASK                       (0x3fc) /* Bits 9-2 */
 #define CRT_FORCE_HOTPLUG_MASK                 0xfffffe1f
-#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \
-                        HDMIC_HOTPLUG_INT_EN |   \
-                        HDMID_HOTPLUG_INT_EN |   \
-                        SDVOB_HOTPLUG_INT_EN |   \
-                        SDVOC_HOTPLUG_INT_EN |   \
-                        CRT_HOTPLUG_INT_EN)
-
 
 #define PORT_HOTPLUG_STAT      0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS             (1 << 29)
 #define   LVDS_PORT_EN                 (1 << 31)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
 #define   LVDS_PIPEB_SELECT            (1 << 30)
+/* LVDS dithering flag on 965/g4x platform */
+#define   LVDS_ENABLE_DITHER           (1 << 25)
 /* Enable border for unscaled (or aspect-scaled) display */
 #define   LVDS_BORDER_ENABLE           (1 << 15)
 /*
 
 /* Display & cursor control */
 
+/* dithering flag on Ironlake */
+#define PIPE_ENABLE_DITHER     (1 << 4)
 /* Pipe A */
 #define PIPEADSL               0x70000
 #define PIPEACONF              0x70008
index d5ebb00..a3b90c9 100644 (file)
@@ -732,12 +732,6 @@ int i915_save_state(struct drm_device *dev)
 
        pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
 
-       /* Render Standby */
-       if (I915_HAS_RC6(dev)) {
-               dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
-               dev_priv->savePWRCTXA = I915_READ(PWRCTXA);
-       }
-
        /* Hardware status page */
        dev_priv->saveHWS = I915_READ(HWS_PGA);
 
@@ -793,12 +787,6 @@ int i915_restore_state(struct drm_device *dev)
 
        pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
 
-       /* Render Standby */
-       if (I915_HAS_RC6(dev)) {
-               I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
-               I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA);
-       }
-
        /* Hardware status page */
        I915_WRITE(HWS_PGA, dev_priv->saveHWS);
 
index 9f3d3e5..ddefc87 100644 (file)
@@ -548,4 +548,6 @@ void intel_crt_init(struct drm_device *dev)
        drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
        drm_sysfs_connector_add(connector);
+
+       dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
 }
index 52cd9b0..002612f 100644 (file)
@@ -262,6 +262,14 @@ struct intel_limit {
 #define IRONLAKE_P2_LVDS_FAST    7  /* double channel */
 #define IRONLAKE_P2_DOT_LIMIT    225000 /* 225Mhz */
 
+#define IRONLAKE_P_DISPLAY_PORT_MIN    10
+#define IRONLAKE_P_DISPLAY_PORT_MAX    20
+#define IRONLAKE_P2_DISPLAY_PORT_FAST  10
+#define IRONLAKE_P2_DISPLAY_PORT_SLOW  10
+#define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0
+#define IRONLAKE_P1_DISPLAY_PORT_MIN   1
+#define IRONLAKE_P1_DISPLAY_PORT_MAX   2
+
 static bool
 intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                    int target, int refclk, intel_clock_t *best_clock);
@@ -271,9 +279,6 @@ intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 static bool
 intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                        int target, int refclk, intel_clock_t *best_clock);
-static bool
-intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                            int target, int refclk, intel_clock_t *best_clock);
 
 static bool
 intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
@@ -496,7 +501,7 @@ static const intel_limit_t intel_limits_ironlake_sdvo = {
        .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
                 .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW,
                 .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST },
-       .find_pll = intel_ironlake_find_best_PLL,
+       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_ironlake_lvds = {
@@ -511,7 +516,30 @@ static const intel_limit_t intel_limits_ironlake_lvds = {
        .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
                 .p2_slow = IRONLAKE_P2_LVDS_SLOW,
                 .p2_fast = IRONLAKE_P2_LVDS_FAST },
-       .find_pll = intel_ironlake_find_best_PLL,
+       .find_pll = intel_g4x_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_display_port = {
+        .dot = { .min = IRONLAKE_DOT_MIN,
+                 .max = IRONLAKE_DOT_MAX },
+        .vco = { .min = IRONLAKE_VCO_MIN,
+                 .max = IRONLAKE_VCO_MAX},
+        .n   = { .min = IRONLAKE_N_MIN,
+                 .max = IRONLAKE_N_MAX },
+        .m   = { .min = IRONLAKE_M_MIN,
+                 .max = IRONLAKE_M_MAX },
+        .m1  = { .min = IRONLAKE_M1_MIN,
+                 .max = IRONLAKE_M1_MAX },
+        .m2  = { .min = IRONLAKE_M2_MIN,
+                 .max = IRONLAKE_M2_MAX },
+        .p   = { .min = IRONLAKE_P_DISPLAY_PORT_MIN,
+                 .max = IRONLAKE_P_DISPLAY_PORT_MAX },
+        .p1  = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN,
+                 .max = IRONLAKE_P1_DISPLAY_PORT_MAX},
+        .p2  = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT,
+                 .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW,
+                 .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST },
+        .find_pll = intel_find_pll_ironlake_dp,
 };
 
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
@@ -519,6 +547,9 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
        const intel_limit_t *limit;
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
                limit = &intel_limits_ironlake_lvds;
+       else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+                       HAS_eDP)
+               limit = &intel_limits_ironlake_display_port;
        else
                limit = &intel_limits_ironlake_sdvo;
 
@@ -791,7 +822,13 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
        found = false;
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+               int lvds_reg;
+
+               if (IS_IRONLAKE(dev))
+                       lvds_reg = PCH_LVDS;
+               else
+                       lvds_reg = LVDS;
+               if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) ==
                    LVDS_CLKB_POWER_UP)
                        clock.p2 = limit->p2.p2_fast;
                else
@@ -839,6 +876,11 @@ 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;
@@ -857,68 +899,6 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
        return true;
 }
 
-static bool
-intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                            int target, int refclk, intel_clock_t *best_clock)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       intel_clock_t clock;
-       int err_most = 47;
-       int err_min = 10000;
-
-       /* eDP has only 2 clock choice, no n/m/p setting */
-       if (HAS_eDP)
-               return true;
-
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
-               return intel_find_pll_ironlake_dp(limit, crtc, target,
-                                              refclk, best_clock);
-
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP)
-                       clock.p2 = limit->p2.p2_fast;
-               else
-                       clock.p2 = limit->p2.p2_slow;
-       } else {
-               if (target < limit->p2.dot_limit)
-                       clock.p2 = limit->p2.p2_slow;
-               else
-                       clock.p2 = limit->p2.p2_fast;
-       }
-
-       memset(best_clock, 0, sizeof(*best_clock));
-       for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
-               /* based on hardware requriment prefer smaller n to precision */
-               for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
-                       /* based on hardware requirment prefere larger m1,m2 */
-                       for (clock.m1 = limit->m1.max;
-                            clock.m1 >= limit->m1.min; clock.m1--) {
-                               for (clock.m2 = limit->m2.max;
-                                    clock.m2 >= limit->m2.min; clock.m2--) {
-                                       int this_err;
-
-                                       intel_clock(dev, refclk, &clock);
-                                       if (!intel_PLL_is_valid(crtc, &clock))
-                                               continue;
-                                       this_err = abs((10000 - (target*10000/clock.dot)));
-                                       if (this_err < err_most) {
-                                               *best_clock = clock;
-                                               /* found on first matching */
-                                               goto out;
-                                       } else if (this_err < err_min) {
-                                               *best_clock = clock;
-                                               err_min = this_err;
-                                       }
-                               }
-                       }
-               }
-       }
-out:
-       return true;
-}
-
 /* DisplayPort has only two frequencies, 162MHz and 270MHz */
 static bool
 intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
@@ -1493,6 +1473,10 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
        int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
        u32 temp;
        int tries = 5, j, n;
+       u32 pipe_bpc;
+
+       temp = I915_READ(pipeconf_reg);
+       pipe_bpc = temp & PIPE_BPC_MASK;
 
        /* 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.
@@ -1524,6 +1508,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 
                        /* 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);
                        I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
                                        FDI_SEL_PCDCLK |
                                        FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
@@ -1666,6 +1656,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 
                        /* 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);
 
@@ -1745,6 +1741,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                I915_READ(fdi_tx_reg);
 
                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);
 
@@ -1789,7 +1788,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                                }
                        }
                }
-
+               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 PCH DPLL */
@@ -2448,7 +2452,7 @@ static void pineview_enable_cxsr(struct drm_device *dev, unsigned long clock,
  * A value of 5us seems to be a good balance; safe for very low end
  * platforms but not overly aggressive on lower latency configs.
  */
-const static int latency_ns = 5000;
+static const int latency_ns = 5000;
 
 static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
 {
@@ -2559,7 +2563,7 @@ static void g4x_update_wm(struct drm_device *dev,  int planea_clock,
        /* Calc sr entries for one plane configs */
        if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
                /* self-refresh has much higher latency */
-               const static int sr_latency_ns = 12000;
+               static const int sr_latency_ns = 12000;
 
                sr_clock = planea_clock ? planea_clock : planeb_clock;
                line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2598,7 +2602,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
        /* Calc sr entries for one plane configs */
        if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
                /* self-refresh has much higher latency */
-               const static int sr_latency_ns = 12000;
+               static const int sr_latency_ns = 12000;
 
                sr_clock = planea_clock ? planea_clock : planeb_clock;
                line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2667,7 +2671,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
        if (HAS_FW_BLC(dev) && sr_hdisplay &&
            (!planea_clock || !planeb_clock)) {
                /* self-refresh has much higher latency */
-               const static int sr_latency_ns = 6000;
+               static const int sr_latency_ns = 6000;
 
                sr_clock = planea_clock ? planea_clock : planeb_clock;
                line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2969,6 +2973,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
                /* determine panel color depth */
                temp = I915_READ(pipeconf_reg);
+               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)
+                               temp |= PIPE_8BPC;
+                       else
+                               temp |= PIPE_6BPC;
+               } else
+                       temp |= PIPE_8BPC;
+               I915_WRITE(pipeconf_reg, temp);
+               I915_READ(pipeconf_reg);
 
                switch (temp & PIPE_BPC_MASK) {
                case PIPE_8BPC:
@@ -3195,7 +3211,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                 * 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 (IS_IRONLAKE(dev))
+                                       pipeconf |= PIPE_ENABLE_DITHER;
+                               else
+                                       lvds |= LVDS_ENABLE_DITHER;
+                       } else {
+                               if (IS_IRONLAKE(dev))
+                                       pipeconf &= ~PIPE_ENABLE_DITHER;
+                               else
+                                       lvds &= ~LVDS_ENABLE_DITHER;
+                       }
+               }
                I915_WRITE(lvds_reg, lvds);
                I915_READ(lvds_reg);
        }
@@ -3385,7 +3414,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 
        /* we only need to pin inside GTT if cursor is non-phy */
        mutex_lock(&dev->struct_mutex);
-       if (!dev_priv->cursor_needs_physical) {
+       if (!dev_priv->info->cursor_needs_physical) {
                ret = i915_gem_object_pin(bo, PAGE_SIZE);
                if (ret) {
                        DRM_ERROR("failed to pin cursor bo\n");
@@ -3420,7 +3449,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        I915_WRITE(base, addr);
 
        if (intel_crtc->cursor_bo) {
-               if (dev_priv->cursor_needs_physical) {
+               if (dev_priv->info->cursor_needs_physical) {
                        if (intel_crtc->cursor_bo != bo)
                                i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
                } else
@@ -3779,125 +3808,6 @@ static void intel_gpu_idle_timer(unsigned long arg)
        queue_work(dev_priv->wq, &dev_priv->idle_work);
 }
 
-void intel_increase_renderclock(struct drm_device *dev, bool schedule)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (IS_IRONLAKE(dev))
-               return;
-
-       if (!dev_priv->render_reclock_avail) {
-               DRM_DEBUG_DRIVER("not reclocking render clock\n");
-               return;
-       }
-
-       /* Restore render clock frequency to original value */
-       if (IS_G4X(dev) || IS_I9XX(dev))
-               pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock);
-       else if (IS_I85X(dev))
-               pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock);
-       DRM_DEBUG_DRIVER("increasing render clock frequency\n");
-
-       /* Schedule downclock */
-       if (schedule)
-               mod_timer(&dev_priv->idle_timer, jiffies +
-                         msecs_to_jiffies(GPU_IDLE_TIMEOUT));
-}
-
-void intel_decrease_renderclock(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (IS_IRONLAKE(dev))
-               return;
-
-       if (!dev_priv->render_reclock_avail) {
-               DRM_DEBUG_DRIVER("not reclocking render clock\n");
-               return;
-       }
-
-       if (IS_G4X(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK;
-               gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I965G(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~I965_GC_RENDER_CLOCK_MASK;
-               gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I945G(dev) || IS_I945GM(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~I945_GC_RENDER_CLOCK_MASK;
-               gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I915G(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~I915_GC_RENDER_CLOCK_MASK;
-               gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       } else if (IS_I85X(dev)) {
-               u16 hpllcc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, HPLLCC, &hpllcc);
-
-               /* Up to maximum... */
-               hpllcc &= ~GC_CLOCK_CONTROL_MASK;
-               hpllcc |= GC_CLOCK_133_200;
-
-               pci_write_config_word(dev->pdev, HPLLCC, hpllcc);
-       }
-       DRM_DEBUG_DRIVER("decreasing render clock frequency\n");
-}
-
-/* Note that no increase function is needed for this - increase_renderclock()
- *  will also rewrite these bits
- */
-void intel_decrease_displayclock(struct drm_device *dev)
-{
-       if (IS_IRONLAKE(dev))
-               return;
-
-       if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) ||
-           IS_I915GM(dev)) {
-               u16 gcfgc;
-
-               /* Adjust render clock... */
-               pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-               /* Down to minimum... */
-               gcfgc &= ~0xf0;
-               gcfgc |= 0x80;
-
-               pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-       }
-}
-
 #define CRTC_IDLE_TIMEOUT 1000 /* ms */
 
 static void intel_crtc_idle_timer(unsigned long arg)
@@ -4011,12 +3921,6 @@ static void intel_idle_update(struct work_struct *work)
 
        mutex_lock(&dev->struct_mutex);
 
-       /* GPU isn't processing, downclock it. */
-       if (!dev_priv->busy) {
-               intel_decrease_renderclock(dev);
-               intel_decrease_displayclock(dev);
-       }
-
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
                if (!crtc->fb)
@@ -4050,13 +3954,11 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return;
 
-       if (!dev_priv->busy) {
+       if (!dev_priv->busy)
                dev_priv->busy = true;
-               intel_increase_renderclock(dev, true);
-       } else {
+       else
                mod_timer(&dev_priv->idle_timer, jiffies +
                          msecs_to_jiffies(GPU_IDLE_TIMEOUT));
-       }
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (!crtc->fb)
@@ -4400,29 +4302,43 @@ static void intel_setup_outputs(struct drm_device *dev)
                bool found = false;
 
                if (I915_READ(SDVOB) & SDVO_DETECTED) {
+                       DRM_DEBUG_KMS("probing SDVOB\n");
                        found = intel_sdvo_init(dev, SDVOB);
-                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
+                               DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
                                intel_hdmi_init(dev, SDVOB);
+                       }
 
-                       if (!found && SUPPORTS_INTEGRATED_DP(dev))
+                       if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
+                               DRM_DEBUG_KMS("probing DP_B\n");
                                intel_dp_init(dev, DP_B);
+                       }
                }
 
                /* Before G4X SDVOC doesn't have its own detect register */
 
-               if (I915_READ(SDVOB) & SDVO_DETECTED)
+               if (I915_READ(SDVOB) & SDVO_DETECTED) {
+                       DRM_DEBUG_KMS("probing SDVOC\n");
                        found = intel_sdvo_init(dev, SDVOC);
+               }
 
                if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
 
-                       if (SUPPORTS_INTEGRATED_HDMI(dev))
+                       if (SUPPORTS_INTEGRATED_HDMI(dev)) {
+                               DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
                                intel_hdmi_init(dev, SDVOC);
-                       if (SUPPORTS_INTEGRATED_DP(dev))
+                       }
+                       if (SUPPORTS_INTEGRATED_DP(dev)) {
+                               DRM_DEBUG_KMS("probing DP_C\n");
                                intel_dp_init(dev, DP_C);
+                       }
                }
 
-               if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
+               if (SUPPORTS_INTEGRATED_DP(dev) &&
+                   (I915_READ(DP_D) & DP_DETECTED)) {
+                       DRM_DEBUG_KMS("probing DP_D\n");
                        intel_dp_init(dev, DP_D);
+               }
        } else if (IS_I8XX(dev))
                intel_dvo_init(dev);
 
@@ -4527,6 +4443,42 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
        .fb_changed = intelfb_probe,
 };
 
+static struct drm_gem_object *
+intel_alloc_power_context(struct drm_device *dev)
+{
+       struct drm_gem_object *pwrctx;
+       int ret;
+
+       pwrctx = drm_gem_object_alloc(dev, 4096);
+       if (!pwrctx) {
+               DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
+               return NULL;
+       }
+
+       mutex_lock(&dev->struct_mutex);
+       ret = i915_gem_object_pin(pwrctx, 4096);
+       if (ret) {
+               DRM_ERROR("failed to pin power context: %d\n", ret);
+               goto err_unref;
+       }
+
+       ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1);
+       if (ret) {
+               DRM_ERROR("failed to set-domain on power context: %d\n", ret);
+               goto err_unpin;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return pwrctx;
+
+err_unpin:
+       i915_gem_object_unpin(pwrctx);
+err_unref:
+       drm_gem_object_unreference(pwrctx);
+       mutex_unlock(&dev->struct_mutex);
+       return NULL;
+}
+
 void intel_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4579,42 +4531,27 @@ void intel_init_clock_gating(struct drm_device *dev)
         * GPU can automatically power down the render unit if given a page
         * to save state.
         */
-       if (I915_HAS_RC6(dev)) {
-               struct drm_gem_object *pwrctx;
-               struct drm_i915_gem_object *obj_priv;
-               int ret;
+       if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
+               struct drm_i915_gem_object *obj_priv = NULL;
 
                if (dev_priv->pwrctx) {
                        obj_priv = dev_priv->pwrctx->driver_private;
                } else {
-                       pwrctx = drm_gem_object_alloc(dev, 4096);
-                       if (!pwrctx) {
-                               DRM_DEBUG("failed to alloc power context, "
-                                         "RC6 disabled\n");
-                               goto out;
-                       }
+                       struct drm_gem_object *pwrctx;
 
-                       ret = i915_gem_object_pin(pwrctx, 4096);
-                       if (ret) {
-                               DRM_ERROR("failed to pin power context: %d\n",
-                                         ret);
-                               drm_gem_object_unreference(pwrctx);
-                               goto out;
+                       pwrctx = intel_alloc_power_context(dev);
+                       if (pwrctx) {
+                               dev_priv->pwrctx = pwrctx;
+                               obj_priv = pwrctx->driver_private;
                        }
-
-                       i915_gem_object_set_to_gtt_domain(pwrctx, 1);
-
-                       dev_priv->pwrctx = pwrctx;
-                       obj_priv = pwrctx->driver_private;
                }
 
-               I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
-               I915_WRITE(MCHBAR_RENDER_STANDBY,
-                          I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
+               if (obj_priv) {
+                       I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
+                       I915_WRITE(MCHBAR_RENDER_STANDBY,
+                                  I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
+               }
        }
-
-out:
-       return;
 }
 
 /* Set up chip specific display functions */
@@ -4770,7 +4707,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
                del_timer_sync(&intel_crtc->idle_timer);
        }
 
-       intel_increase_renderclock(dev, false);
        del_timer_sync(&dev_priv->idle_timer);
 
        if (dev_priv->display.disable_fbc)
index 4e7aa8b..1349d9f 100644 (file)
@@ -1402,14 +1402,20 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        break;
                case DP_B:
                case PCH_DP_B:
+                       dev_priv->hotplug_supported_mask |=
+                               HDMIB_HOTPLUG_INT_STATUS;
                        name = "DPDDC-B";
                        break;
                case DP_C:
                case PCH_DP_C:
+                       dev_priv->hotplug_supported_mask |=
+                               HDMIC_HOTPLUG_INT_STATUS;
                        name = "DPDDC-C";
                        break;
                case DP_D:
                case PCH_DP_D:
+                       dev_priv->hotplug_supported_mask |=
+                               HDMID_HOTPLUG_INT_STATUS;
                        name = "DPDDC-D";
                        break;
        }
index f04dbbe..0643194 100644 (file)
@@ -303,21 +303,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        if (sdvox_reg == SDVOB) {
                intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
+               dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == SDVOC) {
                intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
+               dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMIB) {
                intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
                                                                "HDMIB");
+               dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMIC) {
                intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
                                                                "HDMIC");
+               dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMID) {
                intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
                                                                "HDMID");
+               dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
        }
        if (!intel_output->ddc_bus)
                goto err_connector;
index 3118ce2..f4b4aa2 100644 (file)
@@ -608,6 +608,13 @@ static const struct dmi_system_id bad_lid_status[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"),
                },
        },
+       {
+               .ident = "PC-81005",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MALATA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"),
+               },
+       },
        { }
 };
 
@@ -679,7 +686,14 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
        struct drm_i915_private *dev_priv =
                container_of(nb, struct drm_i915_private, lid_notifier);
        struct drm_device *dev = dev_priv->dev;
+       struct drm_connector *connector = dev_priv->int_lvds_connector;
 
+       /*
+        * check and update the status of LVDS connector after receiving
+        * the LID nofication event.
+        */
+       if (connector)
+               connector->status = connector->funcs->detect(connector);
        if (!acpi_lid_open()) {
                dev_priv->modeset_on_lid = 1;
                return NOTIFY_OK;
@@ -854,65 +868,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
        { }     /* terminating entry */
 };
 
-#ifdef CONFIG_ACPI
-/*
- * check_lid_device -- check whether @handle is an ACPI LID device.
- * @handle: ACPI device handle
- * @level : depth in the ACPI namespace tree
- * @context: the number of LID device when we find the device
- * @rv: a return value to fill if desired (Not use)
- */
-static acpi_status
-check_lid_device(acpi_handle handle, u32 level, void *context,
-                       void **return_value)
-{
-       struct acpi_device *acpi_dev;
-       int *lid_present = context;
-
-       acpi_dev = NULL;
-       /* Get the acpi device for device handle */
-       if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) {
-               /* If there is no ACPI device for handle, return */
-               return AE_OK;
-       }
-
-       if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7))
-               *lid_present = 1;
-
-       return AE_OK;
-}
-
-/**
- * check whether there exists the ACPI LID device by enumerating the ACPI
- * device tree.
- */
-static int intel_lid_present(void)
-{
-       int lid_present = 0;
-
-       if (acpi_disabled) {
-               /* If ACPI is disabled, there is no ACPI device tree to
-                * check, so assume the LID device would have been present.
-                */
-               return 1;
-       }
-
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                               ACPI_UINT32_MAX,
-                               check_lid_device, NULL, &lid_present, NULL);
-
-       return lid_present;
-}
-#else
-static int intel_lid_present(void)
-{
-       /* In the absence of ACPI built in, assume that the LID device would
-        * have been present.
-        */
-       return 1;
-}
-#endif
-
 /**
  * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
  * @dev: drm device
@@ -1031,12 +986,8 @@ void intel_lvds_init(struct drm_device *dev)
        if (dmi_check_system(intel_no_lvds))
                return;
 
-       /*
-        * Assume LVDS is present if there's an ACPI lid device or if the
-        * device is present in the VBT.
-        */
-       if (!lvds_is_present_in_vbt(dev) && !intel_lid_present()) {
-               DRM_DEBUG_KMS("LVDS is not present in VBT and no lid detected\n");
+       if (!lvds_is_present_in_vbt(dev)) {
+               DRM_DEBUG_KMS("LVDS is not present in VBT\n");
                return;
        }
 
@@ -1180,6 +1131,8 @@ out:
                DRM_DEBUG_KMS("lid notifier registration failed\n");
                dev_priv->lid_notifier.notifier_call = NULL;
        }
+       /* keep the LVDS connector */
+       dev_priv->int_lvds_connector = connector;
        drm_sysfs_connector_add(connector);
        return;
 
index 24a3dc9..de5144c 100644 (file)
@@ -2662,6 +2662,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
 
 bool intel_sdvo_init(struct drm_device *dev, int output_device)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_connector *connector;
        struct intel_output *intel_output;
        struct intel_sdvo_priv *sdvo_priv;
@@ -2708,10 +2709,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
                sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
                                                "SDVOB/VGA DDC BUS");
+               dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
        } else {
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
                sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
                                                "SDVOC/VGA DDC BUS");
+               dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
        }
 
        if (intel_output->ddc_bus == NULL)
index 552ec11..1d5b9b7 100644 (file)
@@ -1840,6 +1840,8 @@ intel_tv_init(struct drm_device *dev)
        drm_connector_attach_property(connector,
                                   dev->mode_config.tv_bottom_margin_property,
                                   tv_priv->margin[TV_MARGIN_BOTTOM]);
+
+       dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS;
 out:
        drm_sysfs_connector_add(connector);
 }
index ec3f5e8..b64a8d7 100644 (file)
@@ -188,6 +188,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_MADVISE   0x26
 #define DRM_I915_OVERLAY_PUT_IMAGE     0x27
 #define DRM_I915_OVERLAY_ATTRS 0x28
+#define DRM_I915_GEM_EXECBUFFER2       0x29
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -207,6 +208,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
 #define DRM_IOCTL_I915_GEM_INIT                DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
 #define DRM_IOCTL_I915_GEM_EXECBUFFER  DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
 #define DRM_IOCTL_I915_GEM_PIN         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
 #define DRM_IOCTL_I915_GEM_UNPIN       DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
 #define DRM_IOCTL_I915_GEM_BUSY                DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
@@ -272,6 +274,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_NUM_FENCES_AVAIL      6
 #define I915_PARAM_HAS_OVERLAY           7
 #define I915_PARAM_HAS_PAGEFLIPPING     8
+#define I915_PARAM_HAS_EXECBUF2          9
 
 typedef struct drm_i915_getparam {
        int param;
@@ -567,6 +570,57 @@ struct drm_i915_gem_execbuffer {
        __u64 cliprects_ptr;
 };
 
+struct drm_i915_gem_exec_object2 {
+       /**
+        * User's handle for a buffer to be bound into the GTT for this
+        * operation.
+        */
+       __u32 handle;
+
+       /** Number of relocations to be performed on this buffer */
+       __u32 relocation_count;
+       /**
+        * Pointer to array of struct drm_i915_gem_relocation_entry containing
+        * the relocations to be performed in this buffer.
+        */
+       __u64 relocs_ptr;
+
+       /** Required alignment in graphics aperture */
+       __u64 alignment;
+
+       /**
+        * Returned value of the updated offset of the object, for future
+        * presumed_offset writes.
+        */
+       __u64 offset;
+
+#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
+       __u64 flags;
+       __u64 rsvd1;
+       __u64 rsvd2;
+};
+
+struct drm_i915_gem_execbuffer2 {
+       /**
+        * List of gem_exec_object2 structs
+        */
+       __u64 buffers_ptr;
+       __u32 buffer_count;
+
+       /** Offset in the batchbuffer to start execution from. */
+       __u32 batch_start_offset;
+       /** Bytes used in batchbuffer from batch_start_offset */
+       __u32 batch_len;
+       __u32 DR1;
+       __u32 DR4;
+       __u32 num_cliprects;
+       /** This is a struct drm_clip_rect *cliprects */
+       __u64 cliprects_ptr;
+       __u64 flags; /* currently unused */
+       __u64 rsvd1;
+       __u64 rsvd2;
+};
+
 struct drm_i915_gem_pin {
        /** Handle of the buffer to be pinned. */
        __u32 handle;