Merge tag 'drm-intel-next-2014-02-14' of ssh://git.freedesktop.org/git/drm-intel...
authorDave Airlie <airlied@redhat.com>
Mon, 3 Mar 2014 21:51:41 +0000 (07:51 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 3 Mar 2014 21:51:41 +0000 (07:51 +1000)
- Fix the execbuf rebind performance regression due to topic/ppgtt (Chris).
- Fix up the connector cleanup ordering for sdvod i2c and dp aux devices (Imre).
- Try to preserve the firmware modeset config on driver load. And a bit of prep
  work for smooth takeover of the fb contents (Jesse).
- Prep cleanup for larger gtt address spaces on bdw (Ben).
- Improve our vblank_wait code to make hsw modesets faster (Paulo).
- Display debugfs file (Jesse).
- DRRS prep work from Vandana Kannan.
- pipestat interrupt handler to fix a few races around vblank/pageflip handling
  on byt (Imre).
- Improve display fuse handling for display-less SKUs (Damien).
- Drop locks while stalling for the gpu when serving pagefaults to improve
  interactivity (Chris).
- And as usual piles of other improvements and small fixes all over.

* tag 'drm-intel-next-2014-02-14' of ssh://git.freedesktop.org/git/drm-intel: (65 commits)
  drm/i915: fix NULL deref in the load detect code
  drm/i915: Only bind each object rather than for every execbuffer
  drm/i915: Directly return the vma from bind_to_vm
  drm/i915: Simplify i915_gem_object_ggtt_unpin
  drm/i915: Allow blocking in the PDE alloc when running low on gtt space
  drm/i915: Don't allocate context pages as mappable
  drm/i915: Handle set_cache_level errors in the status page setup
  drm/i915: Don't pin the status page as mappable
  drm/i915: Don't set PIN_MAPPABLE for legacy ringbuffers
  drm/i915: Handle set_cache_level errors in the pipe control scratch setup
  drm/i915: split PIN_GLOBAL out from PIN_MAPPABLE
  drm/i915: Consolidate binding parameters into flags
  drm/i915: sdvo: add i2c sysfs symlink to the connector's directory
  drm/i915: sdvo: fix error path in sdvo_connector_init
  drm/i915: dp: fix order of dp aux i2c device cleanup
  drm/i915: add unregister callback to connector
  drm/i915: don't reference null pointer at i915_sink_crc
  drm/i915/lvds: Remove dead code from failing case
  drm/i915: don't preserve inherited configs with nothing on v2
  drm/i915/bdw: Split up PPGTT cleanup
  ...

32 files changed:
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
include/drm/drm_crtc.h
include/drm/drm_fb_helper.h

index 3b7d32da16046ffcdc238ba41b1b03a3ec152435..35ea15d5ffffed35a4f494afe6df9a1a4e89a8ae 100644 (file)
@@ -215,6 +215,16 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] =
        { DRM_MODE_ENCODER_DSI, "DSI" },
 };
 
+static const struct drm_prop_enum_list drm_subpixel_enum_list[] =
+{
+       { SubPixelUnknown, "Unknown" },
+       { SubPixelHorizontalRGB, "Horizontal RGB" },
+       { SubPixelHorizontalBGR, "Horizontal BGR" },
+       { SubPixelVerticalRGB, "Vertical RGB" },
+       { SubPixelVerticalBGR, "Vertical BGR" },
+       { SubPixelNone, "None" },
+};
+
 void drm_connector_ida_init(void)
 {
        int i;
@@ -264,6 +274,19 @@ const char *drm_get_connector_status_name(enum drm_connector_status status)
 }
 EXPORT_SYMBOL(drm_get_connector_status_name);
 
+/**
+ * drm_get_subpixel_order_name - return a string for a given subpixel enum
+ * @order: enum of subpixel_order
+ *
+ * Note you could abuse this and return something out of bounds, but that
+ * would be a caller error.  No unscrubbed user data should make it here.
+ */
+const char *drm_get_subpixel_order_name(enum subpixel_order order)
+{
+       return drm_subpixel_enum_list[order].name;
+}
+EXPORT_SYMBOL(drm_get_subpixel_order_name);
+
 static char printable_char(int c)
 {
        return isascii(c) && isprint(c) ? c : '?';
index 98a03639b413d834d08c5c73c0ef08cec3d37c55..d99df15a78bc3be2c8ea9e154ba8d590b90ad3a3 100644 (file)
@@ -1136,7 +1136,7 @@ static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
        return count;
 }
 
-static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
+struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
 {
        struct drm_display_mode *mode;
 
@@ -1149,6 +1149,7 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_conn
        }
        return NULL;
 }
+EXPORT_SYMBOL(drm_has_preferred_mode);
 
 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
 {
@@ -1157,7 +1158,7 @@ static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
        return cmdline_mode->specified;
 }
 
-static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
+struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
                                                      int width, int height)
 {
        struct drm_cmdline_mode *cmdline_mode;
@@ -1197,6 +1198,7 @@ create_mode:
        list_add(&mode->head, &fb_helper_conn->connector->modes);
        return mode;
 }
+EXPORT_SYMBOL(drm_pick_cmdline_mode);
 
 static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
 {
index 2dc05c30b8007df6c8fe18bf21aaec4b0a07e516..d90a70744d9369609e64035e32395660b605a142 100644 (file)
@@ -1937,6 +1937,9 @@ static int i915_sink_crc(struct seq_file *m, void *data)
                if (connector->base.dpms != DRM_MODE_DPMS_ON)
                        continue;
 
+               if (!connector->base.encoder)
+                       continue;
+
                encoder = to_intel_encoder(connector->base.encoder);
                if (encoder->type != INTEL_OUTPUT_EDP)
                        continue;
@@ -2074,6 +2077,164 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
        return 0;
 }
 
+static void intel_seq_print_mode(struct seq_file *m, int tabs,
+                                struct drm_display_mode *mode)
+{
+       int i;
+
+       for (i = 0; i < tabs; i++)
+               seq_putc(m, '\t');
+
+       seq_printf(m, "id %d:\"%s\" freq %d clock %d hdisp %d hss %d hse %d htot %d vdisp %d vss %d vse %d vtot %d type 0x%x flags 0x%x\n",
+                  mode->base.id, mode->name,
+                  mode->vrefresh, mode->clock,
+                  mode->hdisplay, mode->hsync_start,
+                  mode->hsync_end, mode->htotal,
+                  mode->vdisplay, mode->vsync_start,
+                  mode->vsync_end, mode->vtotal,
+                  mode->type, mode->flags);
+}
+
+static void intel_encoder_info(struct seq_file *m,
+                              struct intel_crtc *intel_crtc,
+                              struct intel_encoder *intel_encoder)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_crtc *crtc = &intel_crtc->base;
+       struct intel_connector *intel_connector;
+       struct drm_encoder *encoder;
+
+       encoder = &intel_encoder->base;
+       seq_printf(m, "\tencoder %d: type: %s, connectors:\n",
+                  encoder->base.id, drm_get_encoder_name(encoder));
+       for_each_connector_on_encoder(dev, encoder, intel_connector) {
+               struct drm_connector *connector = &intel_connector->base;
+               seq_printf(m, "\t\tconnector %d: type: %s, status: %s",
+                          connector->base.id,
+                          drm_get_connector_name(connector),
+                          drm_get_connector_status_name(connector->status));
+               if (connector->status == connector_status_connected) {
+                       struct drm_display_mode *mode = &crtc->mode;
+                       seq_printf(m, ", mode:\n");
+                       intel_seq_print_mode(m, 2, mode);
+               } else {
+                       seq_putc(m, '\n');
+               }
+       }
+}
+
+static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_crtc *crtc = &intel_crtc->base;
+       struct intel_encoder *intel_encoder;
+
+       seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
+                  crtc->fb->base.id, crtc->x, crtc->y,
+                  crtc->fb->width, crtc->fb->height);
+       for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+               intel_encoder_info(m, intel_crtc, intel_encoder);
+}
+
+static void intel_panel_info(struct seq_file *m, struct intel_panel *panel)
+{
+       struct drm_display_mode *mode = panel->fixed_mode;
+
+       seq_printf(m, "\tfixed mode:\n");
+       intel_seq_print_mode(m, 2, mode);
+}
+
+static void intel_dp_info(struct seq_file *m,
+                         struct intel_connector *intel_connector)
+{
+       struct intel_encoder *intel_encoder = intel_connector->encoder;
+       struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+       seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
+       seq_printf(m, "\taudio support: %s\n", intel_dp->has_audio ? "yes" :
+                  "no");
+       if (intel_encoder->type == INTEL_OUTPUT_EDP)
+               intel_panel_info(m, &intel_connector->panel);
+}
+
+static void intel_hdmi_info(struct seq_file *m,
+                           struct intel_connector *intel_connector)
+{
+       struct intel_encoder *intel_encoder = intel_connector->encoder;
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
+
+       seq_printf(m, "\taudio support: %s\n", intel_hdmi->has_audio ? "yes" :
+                  "no");
+}
+
+static void intel_lvds_info(struct seq_file *m,
+                           struct intel_connector *intel_connector)
+{
+       intel_panel_info(m, &intel_connector->panel);
+}
+
+static void intel_connector_info(struct seq_file *m,
+                                struct drm_connector *connector)
+{
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_encoder *intel_encoder = intel_connector->encoder;
+
+       seq_printf(m, "connector %d: type %s, status: %s\n",
+                  connector->base.id, drm_get_connector_name(connector),
+                  drm_get_connector_status_name(connector->status));
+       if (connector->status == connector_status_connected) {
+               seq_printf(m, "\tname: %s\n", connector->display_info.name);
+               seq_printf(m, "\tphysical dimensions: %dx%dmm\n",
+                          connector->display_info.width_mm,
+                          connector->display_info.height_mm);
+               seq_printf(m, "\tsubpixel order: %s\n",
+                          drm_get_subpixel_order_name(connector->display_info.subpixel_order));
+               seq_printf(m, "\tCEA rev: %d\n",
+                          connector->display_info.cea_rev);
+       }
+       if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+           intel_encoder->type == INTEL_OUTPUT_EDP)
+               intel_dp_info(m, intel_connector);
+       else if (intel_encoder->type == INTEL_OUTPUT_HDMI)
+               intel_hdmi_info(m, intel_connector);
+       else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
+               intel_lvds_info(m, intel_connector);
+
+}
+
+static int i915_display_info(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_crtc *crtc;
+       struct drm_connector *connector;
+
+       drm_modeset_lock_all(dev);
+       seq_printf(m, "CRTC info\n");
+       seq_printf(m, "---------\n");
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+               seq_printf(m, "CRTC %d: pipe: %c, active: %s\n",
+                          crtc->base.id, pipe_name(intel_crtc->pipe),
+                          intel_crtc->active ? "yes" : "no");
+               if (intel_crtc->active)
+                       intel_crtc_info(m, intel_crtc);
+       }
+
+       seq_printf(m, "\n");
+       seq_printf(m, "Connector info\n");
+       seq_printf(m, "--------------\n");
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               intel_connector_info(m, connector);
+       }
+       drm_modeset_unlock_all(dev);
+
+       return 0;
+}
+
 struct pipe_crc_info {
        const char *name;
        struct drm_device *dev;
@@ -3519,6 +3680,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
        {"i915_energy_uJ", i915_energy_uJ, 0},
        {"i915_pc8_status", i915_pc8_status, 0},
        {"i915_power_domain_info", i915_power_domain_info, 0},
+       {"i915_display_info", i915_display_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
index 258b1be20db3cf93435d857ae8f4aa1432db00c2..7688abc83fc092381decca763d175fa93b6b6a20 100644 (file)
@@ -626,9 +626,8 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
                            struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-           master_priv->sarea_priv;
+       struct drm_i915_master_private *master_priv;
+       drm_i915_sarea_t *sarea_priv;
        drm_i915_batchbuffer_t *batch = data;
        int ret;
        struct drm_clip_rect *cliprects = NULL;
@@ -636,6 +635,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return -ENODEV;
 
+       master_priv = dev->primary->master->driver_priv;
+       sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv;
+
        if (!dev_priv->dri1.allow_batchbuffer) {
                DRM_ERROR("Batchbuffer ioctl disabled\n");
                return -EINVAL;
@@ -682,9 +684,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-           master_priv->sarea_priv;
+       struct drm_i915_master_private *master_priv;
+       drm_i915_sarea_t *sarea_priv;
        drm_i915_cmdbuffer_t *cmdbuf = data;
        struct drm_clip_rect *cliprects = NULL;
        void *batch_data;
@@ -696,6 +697,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return -ENODEV;
 
+       master_priv = dev->primary->master->driver_priv;
+       sarea_priv = (drm_i915_sarea_t *) master_priv->sarea_priv;
+
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (cmdbuf->num_cliprects < 0)
@@ -1442,7 +1446,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 
 static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 {
-       const struct intel_device_info *info = dev_priv->info;
+       const struct intel_device_info *info = &dev_priv->info;
 
 #define PRINT_S(name) "%s"
 #define SEP_EMPTY
@@ -1459,6 +1463,58 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 #undef SEP_COMMA
 }
 
+/*
+ * Determine various intel_device_info fields at runtime.
+ *
+ * Use it when either:
+ *   - it's judged too laborious to fill n static structures with the limit
+ *     when a simple if statement does the job,
+ *   - run-time checks (eg read fuse/strap registers) are needed.
+ *
+ * This function needs to be called:
+ *   - after the MMIO has been setup as we are reading registers,
+ *   - after the PCH has been detected,
+ *   - before the first usage of the fields it can tweak.
+ */
+static void intel_device_info_runtime_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_device_info *info;
+
+       info = (struct intel_device_info *)&dev_priv->info;
+
+       info->num_sprites = 1;
+       if (IS_VALLEYVIEW(dev))
+               info->num_sprites = 2;
+
+       if (i915.disable_display) {
+               DRM_INFO("Display disabled (module parameter)\n");
+               info->num_pipes = 0;
+       } else if (info->num_pipes > 0 &&
+                  (INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) &&
+                  !IS_VALLEYVIEW(dev)) {
+               u32 fuse_strap = I915_READ(FUSE_STRAP);
+               u32 sfuse_strap = I915_READ(SFUSE_STRAP);
+
+               /*
+                * SFUSE_STRAP is supposed to have a bit signalling the display
+                * is fused off. Unfortunately it seems that, at least in
+                * certain cases, fused off display means that PCH display
+                * reads don't land anywhere. In that case, we read 0s.
+                *
+                * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK
+                * should be set when taking over after the firmware.
+                */
+               if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
+                   sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
+                   (dev_priv->pch_type == PCH_CPT &&
+                    !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
+                       DRM_INFO("Display fused off, disabling\n");
+                       info->num_pipes = 0;
+               }
+       }
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1473,7 +1529,7 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
 int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
        struct drm_i915_private *dev_priv;
-       struct intel_device_info *info;
+       struct intel_device_info *info, *device_info;
        int ret = 0, mmio_bar, mmio_size;
        uint32_t aperture_size;
 
@@ -1496,7 +1552,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 = info;
+
+       /* copy initial configuration to dev_priv->info */
+       device_info = (struct intel_device_info *)&dev_priv->info;
+       *device_info = *info;
 
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->gpu_error.lock);
@@ -1635,9 +1694,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!IS_I945G(dev) && !IS_I945GM(dev))
                pci_enable_msi(dev->pdev);
 
-       dev_priv->num_plane = 1;
-       if (IS_VALLEYVIEW(dev))
-               dev_priv->num_plane = 2;
+       intel_device_info_runtime_init(dev);
 
        if (INTEL_INFO(dev)->num_pipes) {
                ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
index 9d8ca2a36fde7c7ce5c42963e8ba0f81f7c502c5..05cfcc163a72024c15ceed9be3fb5b3286049834 100644 (file)
@@ -79,7 +79,7 @@ enum plane {
 };
 #define plane_name(p) ((p) + 'A')
 
-#define sprite_name(p, s) ((p) * dev_priv->num_plane + (s) + 'A')
+#define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites + (s) + 'A')
 
 enum port {
        PORT_A = 0,
@@ -164,6 +164,10 @@ enum hpd_pin {
        list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
                if ((intel_encoder)->base.crtc == (__crtc))
 
+#define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
+       list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
+               if ((intel_connector)->base.encoder == (__encoder))
+
 struct drm_i915_private;
 
 enum intel_dpll_id {
@@ -530,6 +534,7 @@ struct intel_uncore {
 struct intel_device_info {
        u32 display_mmio_offset;
        u8 num_pipes:3;
+       u8 num_sprites:2;
        u8 gen;
        u8 ring_mask; /* Rings supported by the HW */
        DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
@@ -1390,7 +1395,7 @@ typedef struct drm_i915_private {
        struct drm_device *dev;
        struct kmem_cache *slab;
 
-       const struct intel_device_info *info;
+       const struct intel_device_info info;
 
        int relative_constants_mode;
 
@@ -1435,6 +1440,7 @@ typedef struct drm_i915_private {
        };
        u32 gt_irq_mask;
        u32 pm_irq_mask;
+       u32 pipestat_irq_mask[I915_MAX_PIPES];
 
        struct work_struct hotplug_work;
        bool enable_hotplug_processing;
@@ -1450,8 +1456,6 @@ typedef struct drm_i915_private {
        u32 hpd_event_bits;
        struct timer_list hotplug_reenable_timer;
 
-       int num_plane;
-
        struct i915_fbc fbc;
        struct intel_opregion opregion;
        struct intel_vbt_data vbt;
@@ -1501,8 +1505,8 @@ typedef struct drm_i915_private {
 
        struct sdvo_device_mapping sdvo_mappings[2];
 
-       struct drm_crtc *plane_to_crtc_mapping[3];
-       struct drm_crtc *pipe_to_crtc_mapping[3];
+       struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
+       struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
        wait_queue_head_t pending_flip_queue;
 
 #ifdef CONFIG_DEBUG_FS
@@ -1799,7 +1803,7 @@ struct drm_i915_file_private {
        atomic_t rps_wait_boost;
 };
 
-#define INTEL_INFO(dev)        (to_i915(dev)->info)
+#define INTEL_INFO(dev)        (&to_i915(dev)->info)
 
 #define IS_I830(dev)           ((dev)->pdev->device == 0x3577)
 #define IS_845G(dev)           ((dev)->pdev->device == 0x2562)
@@ -1953,18 +1957,20 @@ struct i915_params {
        int vbt_sdvo_panel_type;
        int enable_rc6;
        int enable_fbc;
-       bool enable_hangcheck;
        int enable_ppgtt;
        int enable_psr;
        unsigned int preliminary_hw_support;
        int disable_power_well;
        int enable_ips;
-       bool fastboot;
        int enable_pc8;
        int pc8_timeout;
+       int invert_brightness;
+       /* leave bools at the end to not create holes */
+       bool enable_hangcheck;
+       bool fastboot;
        bool prefault_disable;
        bool reset;
-       int invert_brightness;
+       bool disable_display;
 };
 extern struct i915_params i915 __read_mostly;
 
@@ -2012,10 +2018,12 @@ extern void intel_uncore_check_errors(struct drm_device *dev);
 extern void intel_uncore_fini(struct drm_device *dev);
 
 void
-i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask);
+i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
+                    u32 status_mask);
 
 void
-i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask);
+i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
+                     u32 status_mask);
 
 /* i915_gem.c */
 int i915_gem_init_ioctl(struct drm_device *dev, void *data,
@@ -2076,14 +2084,14 @@ void i915_init_vm(struct drm_i915_private *dev_priv,
 void i915_gem_free_object(struct drm_gem_object *obj);
 void i915_gem_vma_destroy(struct i915_vma *vma);
 
+#define PIN_MAPPABLE 0x1
+#define PIN_NONBLOCK 0x2
+#define PIN_GLOBAL 0x4
 int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
                                     struct i915_address_space *vm,
                                     uint32_t alignment,
-                                    bool map_and_fenceable,
-                                    bool nonblocking);
-void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
+                                    unsigned flags);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
-int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
 void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
@@ -2283,13 +2291,19 @@ i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj)
 static inline int __must_check
 i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
                      uint32_t alignment,
-                     bool map_and_fenceable,
-                     bool nonblocking)
+                     unsigned flags)
 {
-       return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment,
-                                  map_and_fenceable, nonblocking);
+       return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment, flags | PIN_GLOBAL);
 }
 
+static inline int
+i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj)
+{
+       return i915_vma_unbind(i915_gem_obj_to_ggtt(obj));
+}
+
+void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
+
 /* i915_gem_context.c */
 #define ctx_to_ppgtt(ctx) container_of((ctx)->vm, struct i915_hw_ppgtt, base)
 int __must_check i915_gem_context_init(struct drm_device *dev);
@@ -2331,8 +2345,7 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
                                          int min_size,
                                          unsigned alignment,
                                          unsigned cache_level,
-                                         bool mappable,
-                                         bool nonblock);
+                                         unsigned flags);
 int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
 int i915_gem_evict_everything(struct drm_device *dev);
 
@@ -2547,6 +2560,7 @@ extern void intel_modeset_suspend_hw(struct drm_device *dev);
 extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
+extern void intel_connector_unregister(struct intel_connector *);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void intel_modeset_setup_hw_state(struct drm_device *dev,
                                         bool force_restore);
index a8a069f97c56f63e21677fb0c7b93df317934666..3618bb0cda0a84c89c5856da4593c53a8b01b77c 100644 (file)
@@ -43,12 +43,6 @@ static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *o
 static __must_check int
 i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
                               bool readonly);
-static __must_check int
-i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
-                          struct i915_address_space *vm,
-                          unsigned alignment,
-                          bool map_and_fenceable,
-                          bool nonblocking);
 static int i915_gem_phys_pwrite(struct drm_device *dev,
                                struct drm_i915_gem_object *obj,
                                struct drm_i915_gem_pwrite *args,
@@ -605,7 +599,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
        char __user *user_data;
        int page_offset, page_length, ret;
 
-       ret = i915_gem_obj_ggtt_pin(obj, 0, true, true);
+       ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE | PIN_NONBLOCK);
        if (ret)
                goto out;
 
@@ -1014,7 +1008,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                        struct timespec *timeout,
                        struct drm_i915_file_private *file_priv)
 {
-       drm_i915_private_t *dev_priv = ring->dev->dev_private;
+       struct drm_device *dev = ring->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        const bool irq_test_in_progress =
                ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
        struct timespec before, now;
@@ -1029,7 +1024,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
 
        timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
 
-       if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) {
+       if (INTEL_INFO(dev)->gen >= 6 && can_wait_boost(file_priv)) {
                gen6_rps_boost(dev_priv);
                if (file_priv)
                        mod_delayed_work(dev_priv->wq,
@@ -1184,7 +1179,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
  */
 static __must_check int
 i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
-                                           struct drm_file *file,
+                                           struct drm_i915_file_private *file_priv,
                                            bool readonly)
 {
        struct drm_device *dev = obj->base.dev;
@@ -1211,7 +1206,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
 
        reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
        mutex_unlock(&dev->struct_mutex);
-       ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file->driver_priv);
+       ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file_priv);
        mutex_lock(&dev->struct_mutex);
        if (ret)
                return ret;
@@ -1260,7 +1255,9 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
         * We will repeat the flush holding the lock in the normal manner
         * to catch cases where we are gazumped.
         */
-       ret = i915_gem_object_wait_rendering__nonblocking(obj, file, !write_domain);
+       ret = i915_gem_object_wait_rendering__nonblocking(obj,
+                                                         file->driver_priv,
+                                                         !write_domain);
        if (ret)
                goto unref;
 
@@ -1392,6 +1389,15 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        trace_i915_gem_object_fault(obj, page_offset, true, write);
 
+       /* Try to flush the object off the GPU first without holding the lock.
+        * Upon reacquiring the lock, we will perform our sanity checks and then
+        * repeat the flush holding the lock in the normal manner to catch cases
+        * where we are gazumped.
+        */
+       ret = i915_gem_object_wait_rendering__nonblocking(obj, NULL, !write);
+       if (ret)
+               goto unlock;
+
        /* Access to snoopable pages through the GTT is incoherent. */
        if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) {
                ret = -EINVAL;
@@ -1399,7 +1405,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        /* Now bind it into the GTT if needed */
-       ret = i915_gem_obj_ggtt_pin(obj,  0, true, false);
+       ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_MAPPABLE);
        if (ret)
                goto unlock;
 
@@ -1618,7 +1624,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
        }
 
        if (obj->madv != I915_MADV_WILLNEED) {
-               DRM_ERROR("Attempting to mmap a purgeable buffer\n");
+               DRM_DEBUG("Attempting to mmap a purgeable buffer\n");
                ret = -EFAULT;
                goto out;
        }
@@ -1972,7 +1978,7 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
                return 0;
 
        if (obj->madv != I915_MADV_WILLNEED) {
-               DRM_ERROR("Attempting to obtain a purgeable object\n");
+               DRM_DEBUG("Attempting to obtain a purgeable object\n");
                return -EFAULT;
        }
 
@@ -2709,7 +2715,6 @@ int i915_vma_unbind(struct i915_vma *vma)
 
        if (!drm_mm_node_allocated(&vma->node)) {
                i915_gem_vma_destroy(vma);
-
                return 0;
        }
 
@@ -2761,26 +2766,6 @@ int i915_vma_unbind(struct i915_vma *vma)
        return 0;
 }
 
-/**
- * Unbinds an object from the global GTT aperture.
- */
-int
-i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj)
-{
-       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-       struct i915_address_space *ggtt = &dev_priv->gtt.base;
-
-       if (!i915_gem_obj_ggtt_bound(obj))
-               return 0;
-
-       if (i915_gem_obj_to_ggtt(obj)->pin_count)
-               return -EBUSY;
-
-       BUG_ON(obj->pages == NULL);
-
-       return i915_vma_unbind(i915_gem_obj_to_vma(obj, ggtt));
-}
-
 int i915_gpu_idle(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -3203,18 +3188,17 @@ static void i915_gem_verify_gtt(struct drm_device *dev)
 /**
  * Finds free space in the GTT aperture and binds the object there.
  */
-static int
+static struct i915_vma *
 i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
                           struct i915_address_space *vm,
                           unsigned alignment,
-                          bool map_and_fenceable,
-                          bool nonblocking)
+                          unsigned flags)
 {
        struct drm_device *dev = obj->base.dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 size, fence_size, fence_alignment, unfenced_alignment;
        size_t gtt_max =
-               map_and_fenceable ? dev_priv->gtt.mappable_end : vm->total;
+               flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total;
        struct i915_vma *vma;
        int ret;
 
@@ -3226,41 +3210,39 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
                                                     obj->tiling_mode, true);
        unfenced_alignment =
                i915_gem_get_gtt_alignment(dev,
-                                                   obj->base.size,
-                                                   obj->tiling_mode, false);
+                                          obj->base.size,
+                                          obj->tiling_mode, false);
 
        if (alignment == 0)
-               alignment = map_and_fenceable ? fence_alignment :
+               alignment = flags & PIN_MAPPABLE ? fence_alignment :
                                                unfenced_alignment;
-       if (map_and_fenceable && alignment & (fence_alignment - 1)) {
-               DRM_ERROR("Invalid object alignment requested %u\n", alignment);
-               return -EINVAL;
+       if (flags & PIN_MAPPABLE && alignment & (fence_alignment - 1)) {
+               DRM_DEBUG("Invalid object alignment requested %u\n", alignment);
+               return ERR_PTR(-EINVAL);
        }
 
-       size = map_and_fenceable ? fence_size : obj->base.size;
+       size = flags & PIN_MAPPABLE ? fence_size : obj->base.size;
 
        /* If the object is bigger than the entire aperture, reject it early
         * before evicting everything in a vain attempt to find space.
         */
        if (obj->base.size > gtt_max) {
-               DRM_ERROR("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
+               DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
                          obj->base.size,
-                         map_and_fenceable ? "mappable" : "total",
+                         flags & PIN_MAPPABLE ? "mappable" : "total",
                          gtt_max);
-               return -E2BIG;
+               return ERR_PTR(-E2BIG);
        }
 
        ret = i915_gem_object_get_pages(obj);
        if (ret)
-               return ret;
+               return ERR_PTR(ret);
 
        i915_gem_object_pin_pages(obj);
 
        vma = i915_gem_obj_lookup_or_create_vma(obj, vm);
-       if (IS_ERR(vma)) {
-               ret = PTR_ERR(vma);
+       if (IS_ERR(vma))
                goto err_unpin;
-       }
 
 search_free:
        ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
@@ -3269,9 +3251,7 @@ search_free:
                                                  DRM_MM_SEARCH_DEFAULT);
        if (ret) {
                ret = i915_gem_evict_something(dev, vm, size, alignment,
-                                              obj->cache_level,
-                                              map_and_fenceable,
-                                              nonblocking);
+                                              obj->cache_level, flags);
                if (ret == 0)
                        goto search_free;
 
@@ -3302,19 +3282,23 @@ search_free:
                obj->map_and_fenceable = mappable && fenceable;
        }
 
-       WARN_ON(map_and_fenceable && !obj->map_and_fenceable);
+       WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
+
+       trace_i915_vma_bind(vma, flags);
+       vma->bind_vma(vma, obj->cache_level,
+                     flags & (PIN_MAPPABLE | PIN_GLOBAL) ? GLOBAL_BIND : 0);
 
-       trace_i915_vma_bind(vma, map_and_fenceable);
        i915_gem_verify_gtt(dev);
-       return 0;
+       return vma;
 
 err_remove_node:
        drm_mm_remove_node(&vma->node);
 err_free_vma:
        i915_gem_vma_destroy(vma);
+       vma = ERR_PTR(ret);
 err_unpin:
        i915_gem_object_unpin_pages(obj);
-       return ret;
+       return vma;
 }
 
 bool
@@ -3506,7 +3490,9 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
                }
 
                list_for_each_entry(vma, &obj->vma_list, vma_link)
-                       vma->bind_vma(vma, cache_level, 0);
+                       if (drm_mm_node_allocated(&vma->node))
+                               vma->bind_vma(vma, cache_level,
+                                             obj->has_global_gtt_mapping ? GLOBAL_BIND : 0);
        }
 
        list_for_each_entry(vma, &obj->vma_list, vma_link)
@@ -3675,7 +3661,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
         * (e.g. libkms for the bootup splash), we have to ensure that we
         * always use map_and_fenceable for all scanout buffers.
         */
-       ret = i915_gem_obj_ggtt_pin(obj, alignment, true, false);
+       ret = i915_gem_obj_ggtt_pin(obj, alignment, PIN_MAPPABLE);
        if (ret)
                goto err_unpin_display;
 
@@ -3831,52 +3817,49 @@ int
 i915_gem_object_pin(struct drm_i915_gem_object *obj,
                    struct i915_address_space *vm,
                    uint32_t alignment,
-                   bool map_and_fenceable,
-                   bool nonblocking)
+                   unsigned flags)
 {
-       const u32 flags = map_and_fenceable ? GLOBAL_BIND : 0;
        struct i915_vma *vma;
        int ret;
 
-       WARN_ON(map_and_fenceable && !i915_is_ggtt(vm));
+       if (WARN_ON(flags & (PIN_GLOBAL | PIN_MAPPABLE) && !i915_is_ggtt(vm)))
+               return -EINVAL;
 
        vma = i915_gem_obj_to_vma(obj, vm);
-
        if (vma) {
                if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
                        return -EBUSY;
 
                if ((alignment &&
                     vma->node.start & (alignment - 1)) ||
-                   (map_and_fenceable && !obj->map_and_fenceable)) {
+                   (flags & PIN_MAPPABLE && !obj->map_and_fenceable)) {
                        WARN(vma->pin_count,
                             "bo is already pinned with incorrect alignment:"
                             " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
                             " obj->map_and_fenceable=%d\n",
                             i915_gem_obj_offset(obj, vm), alignment,
-                            map_and_fenceable,
+                            flags & PIN_MAPPABLE,
                             obj->map_and_fenceable);
                        ret = i915_vma_unbind(vma);
                        if (ret)
                                return ret;
+
+                       vma = NULL;
                }
        }
 
-       if (!i915_gem_obj_bound(obj, vm)) {
-               ret = i915_gem_object_bind_to_vm(obj, vm, alignment,
-                                                map_and_fenceable,
-                                                nonblocking);
-               if (ret)
-                       return ret;
-
+       if (vma == NULL || !drm_mm_node_allocated(&vma->node)) {
+               vma = i915_gem_object_bind_to_vm(obj, vm, alignment, flags);
+               if (IS_ERR(vma))
+                       return PTR_ERR(vma);
        }
 
-       vma = i915_gem_obj_to_vma(obj, vm);
-
-       vma->bind_vma(vma, obj->cache_level, flags);
+       if (flags & PIN_GLOBAL && !obj->has_global_gtt_mapping)
+               vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
 
-       i915_gem_obj_to_vma(obj, vm)->pin_count++;
-       obj->pin_mappable |= map_and_fenceable;
+       vma->pin_count++;
+       if (flags & PIN_MAPPABLE)
+               obj->pin_mappable |= true;
 
        return 0;
 }
@@ -3916,13 +3899,13 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
        }
 
        if (obj->madv != I915_MADV_WILLNEED) {
-               DRM_ERROR("Attempting to pin a purgeable buffer\n");
+               DRM_DEBUG("Attempting to pin a purgeable buffer\n");
                ret = -EFAULT;
                goto out;
        }
 
        if (obj->pin_filp != NULL && obj->pin_filp != file) {
-               DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
+               DRM_DEBUG("Already pinned in i915_gem_pin_ioctl(): %d\n",
                          args->handle);
                ret = -EINVAL;
                goto out;
@@ -3934,7 +3917,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
        }
 
        if (obj->user_pin_count == 0) {
-               ret = i915_gem_obj_ggtt_pin(obj, args->alignment, true, false);
+               ret = i915_gem_obj_ggtt_pin(obj, args->alignment, PIN_MAPPABLE);
                if (ret)
                        goto out;
        }
@@ -3969,7 +3952,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
        }
 
        if (obj->pin_filp != file) {
-               DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
+               DRM_DEBUG("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
                          args->handle);
                ret = -EINVAL;
                goto out;
index 19fd3629795c5a2075664c8313c027983730085f..f8c21a6dd6635a599121baa73221819febb65762 100644 (file)
@@ -258,8 +258,7 @@ i915_gem_create_context(struct drm_device *dev,
                 * context.
                 */
                ret = i915_gem_obj_ggtt_pin(ctx->obj,
-                                           get_context_alignment(dev),
-                                           false, false);
+                                           get_context_alignment(dev), 0);
                if (ret) {
                        DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
                        goto err_destroy;
@@ -335,8 +334,7 @@ void i915_gem_context_reset(struct drm_device *dev)
 
                if (i == RCS) {
                        WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
-                                                     get_context_alignment(dev),
-                                                     false, false));
+                                                     get_context_alignment(dev), 0));
                        /* Fake a finish/inactive */
                        dctx->obj->base.write_domain = 0;
                        dctx->obj->active = 0;
@@ -612,8 +610,7 @@ static int do_switch(struct intel_ring_buffer *ring,
        /* Trying to pin first makes error handling easier. */
        if (ring == &dev_priv->ring[RCS]) {
                ret = i915_gem_obj_ggtt_pin(to->obj,
-                                           get_context_alignment(ring->dev),
-                                           false, false);
+                                           get_context_alignment(ring->dev), 0);
                if (ret)
                        return ret;
        }
index 5168d6a080541cf48cd10cccdc05fbdb02ff04cd..8a78f7885cba887ed3dc8a36534b9368062f0467 100644 (file)
@@ -68,7 +68,7 @@ mark_free(struct i915_vma *vma, struct list_head *unwind)
 int
 i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
                         int min_size, unsigned alignment, unsigned cache_level,
-                        bool mappable, bool nonblocking)
+                        unsigned flags)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct list_head eviction_list, unwind_list;
@@ -76,7 +76,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
        int ret = 0;
        int pass = 0;
 
-       trace_i915_gem_evict(dev, min_size, alignment, mappable);
+       trace_i915_gem_evict(dev, min_size, alignment, flags);
 
        /*
         * The goal is to evict objects and amalgamate space in LRU order.
@@ -102,7 +102,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
         */
 
        INIT_LIST_HEAD(&unwind_list);
-       if (mappable) {
+       if (flags & PIN_MAPPABLE) {
                BUG_ON(!i915_is_ggtt(vm));
                drm_mm_init_scan_with_range(&vm->mm, min_size,
                                            alignment, cache_level, 0,
@@ -117,7 +117,7 @@ search_again:
                        goto found;
        }
 
-       if (nonblocking)
+       if (flags & PIN_NONBLOCK)
                goto none;
 
        /* Now merge in the soon-to-be-expired objects... */
@@ -141,7 +141,7 @@ none:
        /* Can we unpin some objects such as idle hw contents,
         * or pending flips?
         */
-       if (nonblocking)
+       if (flags & PIN_NONBLOCK)
                return -ENOSPC;
 
        /* Only idle the GPU and repeat the search once */
index 032def901f983e2e9b9ef8137a111b35a0ab4c72..d7229ad2bd221b39e8ef3cf07c328a4555224ffd 100644 (file)
@@ -544,19 +544,23 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
        struct drm_i915_gem_object *obj = vma->obj;
        struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
        bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
-       bool need_fence, need_mappable;
-       u32 flags = (entry->flags & EXEC_OBJECT_NEEDS_GTT) &&
-               !vma->obj->has_global_gtt_mapping ? GLOBAL_BIND : 0;
+       bool need_fence;
+       unsigned flags;
        int ret;
 
+       flags = 0;
+
        need_fence =
                has_fenced_gpu_access &&
                entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
                obj->tiling_mode != I915_TILING_NONE;
-       need_mappable = need_fence || need_reloc_mappable(vma);
+       if (need_fence || need_reloc_mappable(vma))
+               flags |= PIN_MAPPABLE;
 
-       ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, need_mappable,
-                                 false);
+       if (entry->flags & EXEC_OBJECT_NEEDS_GTT)
+               flags |= PIN_GLOBAL;
+
+       ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags);
        if (ret)
                return ret;
 
@@ -585,8 +589,6 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
                obj->base.pending_write_domain = I915_GEM_DOMAIN_RENDER;
        }
 
-       vma->bind_vma(vma, obj->cache_level, flags);
-
        return 0;
 }
 
index a4364ae1a2d66a62e3cd106f7c6d982c304f6315..9673cffb07f346dd11dbf486cb0b4ec28eb2ba1d 100644 (file)
@@ -319,36 +319,53 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
                kunmap_atomic(pt_vaddr);
 }
 
-static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt)
+{
+       int i;
+
+       for (i = 0; i < ppgtt->num_pd_pages ; i++)
+               kfree(ppgtt->gen8_pt_dma_addr[i]);
+
+       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
+       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
+}
+
+static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt)
 {
-       struct i915_hw_ppgtt *ppgtt =
-               container_of(vm, struct i915_hw_ppgtt, base);
        int i, j;
 
-       list_del(&vm->global_link);
-       drm_mm_takedown(&vm->mm);
+       for (i = 0; i < ppgtt->num_pd_pages; i++) {
+               /* TODO: In the future we'll support sparse mappings, so this
+                * will have to change. */
+               if (!ppgtt->pd_dma_addr[i])
+                       continue;
 
-       for (i = 0; i < ppgtt->num_pd_pages ; i++) {
-               if (ppgtt->pd_dma_addr[i]) {
-                       pci_unmap_page(ppgtt->base.dev->pdev,
-                                      ppgtt->pd_dma_addr[i],
-                                      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+               pci_unmap_page(ppgtt->base.dev->pdev,
+                              ppgtt->pd_dma_addr[i],
+                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 
-                       for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
-                               dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
-                               if (addr)
-                                       pci_unmap_page(ppgtt->base.dev->pdev,
-                                                      addr,
-                                                      PAGE_SIZE,
-                                                      PCI_DMA_BIDIRECTIONAL);
+               for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
+                       dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
+                       if (addr)
+                               pci_unmap_page(ppgtt->base.dev->pdev,
+                                      addr,
+                                      PAGE_SIZE,
+                                      PCI_DMA_BIDIRECTIONAL);
 
-                       }
                }
-               kfree(ppgtt->gen8_pt_dma_addr[i]);
        }
+}
 
-       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
-       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
+static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
+{
+       struct i915_hw_ppgtt *ppgtt =
+               container_of(vm, struct i915_hw_ppgtt, base);
+
+       list_del(&vm->global_link);
+       drm_mm_takedown(&vm->mm);
+
+       gen8_ppgtt_unmap_pages(ppgtt);
+       gen8_ppgtt_free(ppgtt);
 }
 
 /**
@@ -868,7 +885,7 @@ alloc:
        if (ret == -ENOSPC && !retried) {
                ret = i915_gem_evict_something(dev, &dev_priv->gtt.base,
                                               GEN6_PD_SIZE, GEN6_PD_ALIGN,
-                                              I915_CACHE_NONE, false, true);
+                                              I915_CACHE_NONE, 0);
                if (ret)
                        return ret;
 
index e9c94c91c6a59a40a45d11cccf90f9d9cfd2e637..f68aee31e565d757d21bb1895178ef0f52224ab7 100644 (file)
@@ -419,6 +419,16 @@ done:
        return ret;
 }
 
+static bool __cpu_fifo_underrun_reporting_enabled(struct drm_device *dev,
+                                                 enum pipe pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       return !intel_crtc->cpu_fifo_underrun_disabled;
+}
+
 /**
  * intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages
  * @dev: drm device
@@ -473,38 +483,102 @@ done:
 
 
 void
-i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask)
+__i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                      u32 enable_mask, u32 status_mask)
 {
        u32 reg = PIPESTAT(pipe);
-       u32 pipestat = I915_READ(reg) & 0x7fff0000;
+       u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if ((pipestat & mask) == mask)
+       if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+                        status_mask & ~PIPESTAT_INT_STATUS_MASK))
+               return;
+
+       if ((pipestat & enable_mask) == enable_mask)
                return;
 
+       dev_priv->pipestat_irq_mask[pipe] |= status_mask;
+
        /* Enable the interrupt, clear any pending status */
-       pipestat |= mask | (mask >> 16);
+       pipestat |= enable_mask | status_mask;
        I915_WRITE(reg, pipestat);
        POSTING_READ(reg);
 }
 
 void
-i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask)
+__i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                       u32 enable_mask, u32 status_mask)
 {
        u32 reg = PIPESTAT(pipe);
-       u32 pipestat = I915_READ(reg) & 0x7fff0000;
+       u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if ((pipestat & mask) == 0)
+       if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
+                        status_mask & ~PIPESTAT_INT_STATUS_MASK))
+               return;
+
+       if ((pipestat & enable_mask) == 0)
                return;
 
-       pipestat &= ~mask;
+       dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
+
+       pipestat &= ~enable_mask;
        I915_WRITE(reg, pipestat);
        POSTING_READ(reg);
 }
 
+static u32 vlv_get_pipestat_enable_mask(struct drm_device *dev, u32 status_mask)
+{
+       u32 enable_mask = status_mask << 16;
+
+       /*
+        * On pipe A we don't support the PSR interrupt yet, on pipe B the
+        * same bit MBZ.
+        */
+       if (WARN_ON_ONCE(status_mask & PIPE_A_PSR_STATUS_VLV))
+               return 0;
+
+       enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
+                        SPRITE0_FLIP_DONE_INT_EN_VLV |
+                        SPRITE1_FLIP_DONE_INT_EN_VLV);
+       if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
+               enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
+       if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
+               enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
+
+       return enable_mask;
+}
+
+void
+i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                    u32 status_mask)
+{
+       u32 enable_mask;
+
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+                                                          status_mask);
+       else
+               enable_mask = status_mask << 16;
+       __i915_enable_pipestat(dev_priv, pipe, enable_mask, status_mask);
+}
+
+void
+i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
+                     u32 status_mask)
+{
+       u32 enable_mask;
+
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
+                                                          status_mask);
+       else
+               enable_mask = status_mask << 16;
+       __i915_disable_pipestat(dev_priv, pipe, enable_mask, status_mask);
+}
+
 /**
  * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
  */
@@ -518,10 +592,10 @@ static void i915_enable_asle_pipestat(struct drm_device *dev)
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
        if (INTEL_INFO(dev)->gen >= 4)
                i915_enable_pipestat(dev_priv, PIPE_A,
-                                    PIPE_LEGACY_BLC_EVENT_ENABLE);
+                                    PIPE_LEGACY_BLC_EVENT_STATUS);
 
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
@@ -1479,18 +1553,48 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
 static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pipe_stats[I915_MAX_PIPES];
+       u32 pipe_stats[I915_MAX_PIPES] = { };
        int pipe;
 
        spin_lock(&dev_priv->irq_lock);
        for_each_pipe(pipe) {
-               int reg = PIPESTAT(pipe);
-               pipe_stats[pipe] = I915_READ(reg);
+               int reg;
+               u32 mask, iir_bit = 0;
+
+               /*
+                * PIPESTAT bits get signalled even when the interrupt is
+                * disabled with the mask bits, and some of the status bits do
+                * not generate interrupts at all (like the underrun bit). Hence
+                * we need to be careful that we only handle what we want to
+                * handle.
+                */
+               mask = 0;
+               if (__cpu_fifo_underrun_reporting_enabled(dev, pipe))
+                       mask |= PIPE_FIFO_UNDERRUN_STATUS;
+
+               switch (pipe) {
+               case PIPE_A:
+                       iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+                       break;
+               case PIPE_B:
+                       iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+                       break;
+               }
+               if (iir & iir_bit)
+                       mask |= dev_priv->pipestat_irq_mask[pipe];
+
+               if (!mask)
+                       continue;
+
+               reg = PIPESTAT(pipe);
+               mask |= PIPESTAT_INT_ENABLE_MASK;
+               pipe_stats[pipe] = I915_READ(reg) & mask;
 
                /*
                 * Clear the PIPE*STAT regs before the IIR
                 */
-               if (pipe_stats[pipe] & 0x8000ffff)
+               if (pipe_stats[pipe] & (PIPE_FIFO_UNDERRUN_STATUS |
+                                       PIPESTAT_INT_STATUS_MASK))
                        I915_WRITE(reg, pipe_stats[pipe]);
        }
        spin_unlock(&dev_priv->irq_lock);
@@ -2269,13 +2373,13 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe)
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        if (INTEL_INFO(dev)->gen >= 4)
                i915_enable_pipestat(dev_priv, pipe,
-                                    PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                                    PIPE_START_VBLANK_INTERRUPT_STATUS);
        else
                i915_enable_pipestat(dev_priv, pipe,
-                                    PIPE_VBLANK_INTERRUPT_ENABLE);
+                                    PIPE_VBLANK_INTERRUPT_STATUS);
 
        /* maintain vblank delivery even in deep C-states */
-       if (dev_priv->info->gen == 3)
+       if (INTEL_INFO(dev)->gen == 3)
                I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS));
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
@@ -2309,7 +2413,7 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        i915_enable_pipestat(dev_priv, pipe,
-                            PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                            PIPE_START_VBLANK_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
        return 0;
@@ -2340,12 +2444,12 @@ static void i915_disable_vblank(struct drm_device *dev, int pipe)
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       if (dev_priv->info->gen == 3)
+       if (INTEL_INFO(dev)->gen == 3)
                I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
 
        i915_disable_pipestat(dev_priv, pipe,
-                             PIPE_VBLANK_INTERRUPT_ENABLE |
-                             PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                             PIPE_VBLANK_INTERRUPT_STATUS |
+                             PIPE_START_VBLANK_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -2368,7 +2472,7 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        i915_disable_pipestat(dev_priv, pipe,
-                             PIPE_START_VBLANK_INTERRUPT_ENABLE);
+                             PIPE_START_VBLANK_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -2916,8 +3020,8 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        u32 enable_mask;
-       u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV |
-               PIPE_CRC_DONE_ENABLE;
+       u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
+               PIPE_CRC_DONE_INTERRUPT_STATUS;
        unsigned long irqflags;
 
        enable_mask = I915_DISPLAY_PORT_INTERRUPT;
@@ -2948,7 +3052,7 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
        i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
@@ -3171,8 +3275,8 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
        return 0;
@@ -3354,8 +3458,8 @@ static int i915_irq_postinstall(struct drm_device *dev)
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
        return 0;
@@ -3564,9 +3668,9 @@ static int i965_irq_postinstall(struct drm_device *dev)
        /* Interrupt setup is already guaranteed to be single-threaded, this is
         * just to make the assert_spin_locked check happy. */
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE);
-       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
+       i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
        /*
index c743057b65117a4b9fae192b8ebcd7c018e3cb5a..3b482585c5ae9a43a9c80eef18fe465743b6de33 100644 (file)
@@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
        .prefault_disable = 0,
        .reset = true,
        .invert_brightness = 0,
+       .disable_display = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -153,3 +154,6 @@ MODULE_PARM_DESC(invert_brightness,
        "report PCI device ID, subsystem vendor and subsystem device ID "
        "to dri-devel@lists.freedesktop.org, if your machine needs it. "
        "It will then be included in an upcoming module version.");
+
+module_param_named(disable_display, i915.disable_display, bool, 0600);
+MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
index cc3ea049269b0bd903aa42e7d9e91c5cfcce98fd..2f564ce37d2cbb55bfb9f7fb59f34a0cfeed7dd6 100644 (file)
 #define _3D_CHICKEN3   0x02090
 #define  _3D_CHICKEN_SF_DISABLE_OBJEND_CULL            (1 << 10)
 #define  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL         (1 << 5)
-#define  _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x)      ((x)<<1)
+#define  _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x)      ((x)<<1) /* gen8+ */
+#define  _3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH  (1 << 1) /* gen6 */
 
 #define MI_MODE                0x0209c
 # define VS_TIMER_DISPATCH                             (1 << 6)
  */
 #define DPLL_A_OFFSET 0x6014
 #define DPLL_B_OFFSET 0x6018
-#define DPLL(pipe) (dev_priv->info->dpll_offsets[pipe] + \
-                   dev_priv->info->display_mmio_offset)
+#define DPLL(pipe) (dev_priv->info.dpll_offsets[pipe] + \
+                   dev_priv->info.display_mmio_offset)
 
 #define VGA0   0x6000
 #define VGA1   0x6004
 
 #define DPLL_A_MD_OFFSET 0x601c /* 965+ only */
 #define DPLL_B_MD_OFFSET 0x6020 /* 965+ only */
-#define DPLL_MD(pipe) (dev_priv->info->dpll_md_offsets[pipe] + \
-                      dev_priv->info->display_mmio_offset)
+#define DPLL_MD(pipe) (dev_priv->info.dpll_md_offsets[pipe] + \
+                      dev_priv->info.display_mmio_offset)
 
 /*
  * UDI pixel divider, controlling how many pixels are stuffed into a packet.
 #define  DSTATE_PLL_D3_OFF                     (1<<3)
 #define  DSTATE_GFX_CLOCK_GATING               (1<<1)
 #define  DSTATE_DOT_CLOCK_GATING               (1<<0)
-#define DSPCLK_GATE_D  (dev_priv->info->display_mmio_offset + 0x6200)
+#define DSPCLK_GATE_D  (dev_priv->info.display_mmio_offset + 0x6200)
 # define DPUNIT_B_CLOCK_GATE_DISABLE           (1 << 30) /* 965 */
 # define VSUNIT_CLOCK_GATE_DISABLE             (1 << 29) /* 965 */
 # define VRHUNIT_CLOCK_GATE_DISABLE            (1 << 28) /* 965 */
  */
 #define PALETTE_A_OFFSET 0xa000
 #define PALETTE_B_OFFSET 0xa800
-#define PALETTE(pipe) (dev_priv->info->palette_offsets[pipe] + \
-                      dev_priv->info->display_mmio_offset)
+#define PALETTE(pipe) (dev_priv->info.palette_offsets[pipe] + \
+                      dev_priv->info.display_mmio_offset)
 
 /* MCH MMIO space */
 
 #define TRANSCODER_C_OFFSET 0x62000
 #define TRANSCODER_EDP_OFFSET 0x6f000
 
-#define _TRANSCODER2(pipe, reg) (dev_priv->info->trans_offsets[(pipe)] - \
-       dev_priv->info->trans_offsets[TRANSCODER_A] + (reg) + \
-       dev_priv->info->display_mmio_offset)
+#define _TRANSCODER2(pipe, reg) (dev_priv->info.trans_offsets[(pipe)] - \
+       dev_priv->info.trans_offsets[TRANSCODER_A] + (reg) + \
+       dev_priv->info.display_mmio_offset)
 
 #define HTOTAL(trans) _TRANSCODER2(trans, _HTOTAL_A)
 #define HBLANK(trans) _TRANSCODER2(trans, _HBLANK_A)
 
 
 /* Hotplug control (945+ only) */
-#define PORT_HOTPLUG_EN                (dev_priv->info->display_mmio_offset + 0x61110)
+#define PORT_HOTPLUG_EN                (dev_priv->info.display_mmio_offset + 0x61110)
 #define   PORTB_HOTPLUG_INT_EN                 (1 << 29)
 #define   PORTC_HOTPLUG_INT_EN                 (1 << 28)
 #define   PORTD_HOTPLUG_INT_EN                 (1 << 27)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV       (0 << 2)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
 
-#define PORT_HOTPLUG_STAT      (dev_priv->info->display_mmio_offset + 0x61114)
+#define PORT_HOTPLUG_STAT      (dev_priv->info.display_mmio_offset + 0x61114)
 /*
  * HDMI/DP bits are gen4+
  *
 #define VIDEO_DIP_CTL          0x61170
 /* Pre HSW: */
 #define   VIDEO_DIP_ENABLE             (1 << 31)
-#define   VIDEO_DIP_PORT_B             (1 << 29)
-#define   VIDEO_DIP_PORT_C             (2 << 29)
-#define   VIDEO_DIP_PORT_D             (3 << 29)
+#define   VIDEO_DIP_PORT(port)         ((port) << 29)
 #define   VIDEO_DIP_PORT_MASK          (3 << 29)
 #define   VIDEO_DIP_ENABLE_GCP         (1 << 25)
 #define   VIDEO_DIP_ENABLE_AVI         (1 << 21)
 #define PP_DIVISOR     0x61210
 
 /* Panel fitting */
-#define PFIT_CONTROL   (dev_priv->info->display_mmio_offset + 0x61230)
+#define PFIT_CONTROL   (dev_priv->info.display_mmio_offset + 0x61230)
 #define   PFIT_ENABLE          (1 << 31)
 #define   PFIT_PIPE_MASK       (3 << 29)
 #define   PFIT_PIPE_SHIFT      29
 #define   PFIT_SCALING_PROGRAMMED (1 << 26)
 #define   PFIT_SCALING_PILLAR  (2 << 26)
 #define   PFIT_SCALING_LETTER  (3 << 26)
-#define PFIT_PGM_RATIOS        (dev_priv->info->display_mmio_offset + 0x61234)
+#define PFIT_PGM_RATIOS        (dev_priv->info.display_mmio_offset + 0x61234)
 /* Pre-965 */
 #define                PFIT_VERT_SCALE_SHIFT           20
 #define                PFIT_VERT_SCALE_MASK            0xfff00000
 #define                PFIT_HORIZ_SCALE_SHIFT_965      0
 #define                PFIT_HORIZ_SCALE_MASK_965       0x00001fff
 
-#define PFIT_AUTO_RATIOS (dev_priv->info->display_mmio_offset + 0x61238)
+#define PFIT_AUTO_RATIOS (dev_priv->info.display_mmio_offset + 0x61238)
 
-#define _VLV_BLC_PWM_CTL2_A (dev_priv->info->display_mmio_offset + 0x61250)
-#define _VLV_BLC_PWM_CTL2_B (dev_priv->info->display_mmio_offset + 0x61350)
+#define _VLV_BLC_PWM_CTL2_A (dev_priv->info.display_mmio_offset + 0x61250)
+#define _VLV_BLC_PWM_CTL2_B (dev_priv->info.display_mmio_offset + 0x61350)
 #define VLV_BLC_PWM_CTL2(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \
                                     _VLV_BLC_PWM_CTL2_B)
 
-#define _VLV_BLC_PWM_CTL_A (dev_priv->info->display_mmio_offset + 0x61254)
-#define _VLV_BLC_PWM_CTL_B (dev_priv->info->display_mmio_offset + 0x61354)
+#define _VLV_BLC_PWM_CTL_A (dev_priv->info.display_mmio_offset + 0x61254)
+#define _VLV_BLC_PWM_CTL_B (dev_priv->info.display_mmio_offset + 0x61354)
 #define VLV_BLC_PWM_CTL(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL_A, \
                                    _VLV_BLC_PWM_CTL_B)
 
-#define _VLV_BLC_HIST_CTL_A (dev_priv->info->display_mmio_offset + 0x61260)
-#define _VLV_BLC_HIST_CTL_B (dev_priv->info->display_mmio_offset + 0x61360)
+#define _VLV_BLC_HIST_CTL_A (dev_priv->info.display_mmio_offset + 0x61260)
+#define _VLV_BLC_HIST_CTL_B (dev_priv->info.display_mmio_offset + 0x61360)
 #define VLV_BLC_HIST_CTL(pipe) _PIPE(pipe, _VLV_BLC_HIST_CTL_A, \
                                     _VLV_BLC_HIST_CTL_B)
 
 /* Backlight control */
-#define BLC_PWM_CTL2   (dev_priv->info->display_mmio_offset + 0x61250) /* 965+ only */
+#define BLC_PWM_CTL2   (dev_priv->info.display_mmio_offset + 0x61250) /* 965+ only */
 #define   BLM_PWM_ENABLE               (1 << 31)
 #define   BLM_COMBINATION_MODE         (1 << 30) /* gen4 only */
 #define   BLM_PIPE_SELECT              (1 << 29)
 #define   BLM_PHASE_IN_COUNT_MASK      (0xff << 8)
 #define   BLM_PHASE_IN_INCR_SHIFT      (0)
 #define   BLM_PHASE_IN_INCR_MASK       (0xff << 0)
-#define BLC_PWM_CTL    (dev_priv->info->display_mmio_offset + 0x61254)
+#define BLC_PWM_CTL    (dev_priv->info.display_mmio_offset + 0x61254)
 /*
  * This is the most significant 15 bits of the number of backlight cycles in a
  * complete cycle of the modulated backlight control.
 #define   BACKLIGHT_DUTY_CYCLE_MASK_PNV                (0xfffe)
 #define   BLM_POLARITY_PNV                     (1 << 0) /* pnv only */
 
-#define BLC_HIST_CTL   (dev_priv->info->display_mmio_offset + 0x61260)
+#define BLC_HIST_CTL   (dev_priv->info.display_mmio_offset + 0x61260)
 
 /* New registers for PCH-split platforms. Safe where new bits show up, the
  * register layout machtes with gen4 BLC_PWM_CTL[12]. */
 #define   PIPE_LEGACY_BLC_EVENT_ENABLE         (1UL<<22)
 #define   PIPE_ODD_FIELD_INTERRUPT_ENABLE      (1UL<<21)
 #define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE     (1UL<<20)
+#define   PIPE_B_PSR_INTERRUPT_ENABLE_VLV      (1UL<<19)
 #define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE     (1UL<<18) /* pre-965 */
 #define   PIPE_START_VBLANK_INTERRUPT_ENABLE   (1UL<<18) /* 965 or later */
 #define   PIPE_VBLANK_INTERRUPT_ENABLE         (1UL<<17)
 #define   PIPE_DISPLAY_LINE_COMPARE_STATUS     (1UL<<8)
 #define   PIPE_DPST_EVENT_STATUS               (1UL<<7)
 #define   PIPE_LEGACY_BLC_EVENT_STATUS         (1UL<<6)
+#define   PIPE_A_PSR_STATUS_VLV                        (1UL<<6)
 #define   PIPE_ODD_FIELD_INTERRUPT_STATUS      (1UL<<5)
 #define   PIPE_EVEN_FIELD_INTERRUPT_STATUS     (1UL<<4)
+#define   PIPE_B_PSR_STATUS_VLV                        (1UL<<3)
 #define   PIPE_HOTPLUG_TV_INTERRUPT_STATUS     (1UL<<2) /* pre-965 */
 #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 PIPESTAT_INT_ENABLE_MASK               0x7fff0000
+#define PIPESTAT_INT_STATUS_MASK               0x0000ffff
+
 #define PIPE_A_OFFSET  0x70000
 #define PIPE_B_OFFSET  0x71000
 #define PIPE_C_OFFSET  0x72000
  */
 #define PIPE_EDP_OFFSET        0x7f000
 
-#define _PIPE2(pipe, reg) (dev_priv->info->pipe_offsets[pipe] - \
-       dev_priv->info->pipe_offsets[PIPE_A] + (reg) + \
-       dev_priv->info->display_mmio_offset)
+#define _PIPE2(pipe, reg) (dev_priv->info.pipe_offsets[pipe] - \
+       dev_priv->info.pipe_offsets[PIPE_A] + (reg) + \
+       dev_priv->info.display_mmio_offset)
 
 #define PIPECONF(pipe) _PIPE2(pipe, _PIPEACONF)
 #define PIPEDSL(pipe)  _PIPE2(pipe, _PIPEADSL)
 #define   DSPARB_BEND_SHIFT    9 /* on 855 */
 #define   DSPARB_AEND_SHIFT    0
 
-#define DSPFW1                 (dev_priv->info->display_mmio_offset + 0x70034)
+#define DSPFW1                 (dev_priv->info.display_mmio_offset + 0x70034)
 #define   DSPFW_SR_SHIFT       23
 #define   DSPFW_SR_MASK                (0x1ff<<23)
 #define   DSPFW_CURSORB_SHIFT  16
 #define   DSPFW_PLANEB_SHIFT   8
 #define   DSPFW_PLANEB_MASK    (0x7f<<8)
 #define   DSPFW_PLANEA_MASK    (0x7f)
-#define DSPFW2                 (dev_priv->info->display_mmio_offset + 0x70038)
+#define DSPFW2                 (dev_priv->info.display_mmio_offset + 0x70038)
 #define   DSPFW_CURSORA_MASK   0x00003f00
 #define   DSPFW_CURSORA_SHIFT  8
 #define   DSPFW_PLANEC_MASK    (0x7f)
-#define DSPFW3                 (dev_priv->info->display_mmio_offset + 0x7003c)
+#define DSPFW3                 (dev_priv->info.display_mmio_offset + 0x7003c)
 #define   DSPFW_HPLL_SR_EN     (1<<31)
 #define   DSPFW_CURSOR_SR_SHIFT        24
 #define   PINEVIEW_SELF_REFRESH_EN     (1<<30)
 #define   DSPFW_HPLL_CURSOR_SHIFT      16
 #define   DSPFW_HPLL_CURSOR_MASK       (0x3f<<16)
 #define   DSPFW_HPLL_SR_MASK           (0x1ff)
-#define DSPFW4                 (dev_priv->info->display_mmio_offset + 0x70070)
-#define DSPFW7                 (dev_priv->info->display_mmio_offset + 0x7007c)
+#define DSPFW4                 (dev_priv->info.display_mmio_offset + 0x70070)
+#define DSPFW7                 (dev_priv->info.display_mmio_offset + 0x7007c)
 
 /* drain latency register values*/
 #define DRAIN_LATENCY_PRECISION_32     32
 #define   PIPE_PIXEL_MASK         0x00ffffff
 #define   PIPE_PIXEL_SHIFT        0
 /* GM45+ just has to be different */
-#define _PIPEA_FRMCOUNT_GM45   (dev_priv->info->display_mmio_offset + 0x70040)
-#define _PIPEA_FLIPCOUNT_GM45  (dev_priv->info->display_mmio_offset + 0x70044)
+#define _PIPEA_FRMCOUNT_GM45   (dev_priv->info.display_mmio_offset + 0x70040)
+#define _PIPEA_FLIPCOUNT_GM45  (dev_priv->info.display_mmio_offset + 0x70044)
 #define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45)
 
 /* Cursor A & B regs */
-#define _CURACNTR              (dev_priv->info->display_mmio_offset + 0x70080)
+#define _CURACNTR              (dev_priv->info.display_mmio_offset + 0x70080)
 /* Old style CUR*CNTR flags (desktop 8xx) */
 #define   CURSOR_ENABLE                0x80000000
 #define   CURSOR_GAMMA_ENABLE  0x40000000
 #define   MCURSOR_PIPE_B       (1 << 28)
 #define   MCURSOR_GAMMA_ENABLE  (1 << 26)
 #define   CURSOR_TRICKLE_FEED_DISABLE  (1 << 14)
-#define _CURABASE              (dev_priv->info->display_mmio_offset + 0x70084)
-#define _CURAPOS               (dev_priv->info->display_mmio_offset + 0x70088)
+#define _CURABASE              (dev_priv->info.display_mmio_offset + 0x70084)
+#define _CURAPOS               (dev_priv->info.display_mmio_offset + 0x70088)
 #define   CURSOR_POS_MASK       0x007FF
 #define   CURSOR_POS_SIGN       0x8000
 #define   CURSOR_X_SHIFT        0
 #define   CURSOR_Y_SHIFT        16
 #define CURSIZE                        0x700a0
-#define _CURBCNTR              (dev_priv->info->display_mmio_offset + 0x700c0)
-#define _CURBBASE              (dev_priv->info->display_mmio_offset + 0x700c4)
-#define _CURBPOS               (dev_priv->info->display_mmio_offset + 0x700c8)
+#define _CURBCNTR              (dev_priv->info.display_mmio_offset + 0x700c0)
+#define _CURBBASE              (dev_priv->info.display_mmio_offset + 0x700c4)
+#define _CURBPOS               (dev_priv->info.display_mmio_offset + 0x700c8)
 
 #define _CURBCNTR_IVB          0x71080
 #define _CURBBASE_IVB          0x71084
 #define I915_HI_DISPBASE(val)  (val & DISP_BASEADDR_MASK)
 
 /* VBIOS flags */
-#define SWF00                  (dev_priv->info->display_mmio_offset + 0x71410)
-#define SWF01                  (dev_priv->info->display_mmio_offset + 0x71414)
-#define SWF02                  (dev_priv->info->display_mmio_offset + 0x71418)
-#define SWF03                  (dev_priv->info->display_mmio_offset + 0x7141c)
-#define SWF04                  (dev_priv->info->display_mmio_offset + 0x71420)
-#define SWF05                  (dev_priv->info->display_mmio_offset + 0x71424)
-#define SWF06                  (dev_priv->info->display_mmio_offset + 0x71428)
-#define SWF10                  (dev_priv->info->display_mmio_offset + 0x70410)
-#define SWF11                  (dev_priv->info->display_mmio_offset + 0x70414)
-#define SWF14                  (dev_priv->info->display_mmio_offset + 0x71420)
-#define SWF30                  (dev_priv->info->display_mmio_offset + 0x72414)
-#define SWF31                  (dev_priv->info->display_mmio_offset + 0x72418)
-#define SWF32                  (dev_priv->info->display_mmio_offset + 0x7241c)
+#define SWF00                  (dev_priv->info.display_mmio_offset + 0x71410)
+#define SWF01                  (dev_priv->info.display_mmio_offset + 0x71414)
+#define SWF02                  (dev_priv->info.display_mmio_offset + 0x71418)
+#define SWF03                  (dev_priv->info.display_mmio_offset + 0x7141c)
+#define SWF04                  (dev_priv->info.display_mmio_offset + 0x71420)
+#define SWF05                  (dev_priv->info.display_mmio_offset + 0x71424)
+#define SWF06                  (dev_priv->info.display_mmio_offset + 0x71428)
+#define SWF10                  (dev_priv->info.display_mmio_offset + 0x70410)
+#define SWF11                  (dev_priv->info.display_mmio_offset + 0x70414)
+#define SWF14                  (dev_priv->info.display_mmio_offset + 0x71420)
+#define SWF30                  (dev_priv->info.display_mmio_offset + 0x72414)
+#define SWF31                  (dev_priv->info.display_mmio_offset + 0x72418)
+#define SWF32                  (dev_priv->info.display_mmio_offset + 0x7241c)
 
 /* Pipe B */
-#define _PIPEBDSL              (dev_priv->info->display_mmio_offset + 0x71000)
-#define _PIPEBCONF             (dev_priv->info->display_mmio_offset + 0x71008)
-#define _PIPEBSTAT             (dev_priv->info->display_mmio_offset + 0x71024)
+#define _PIPEBDSL              (dev_priv->info.display_mmio_offset + 0x71000)
+#define _PIPEBCONF             (dev_priv->info.display_mmio_offset + 0x71008)
+#define _PIPEBSTAT             (dev_priv->info.display_mmio_offset + 0x71024)
 #define _PIPEBFRAMEHIGH                0x71040
 #define _PIPEBFRAMEPIXEL       0x71044
-#define _PIPEB_FRMCOUNT_GM45   (dev_priv->info->display_mmio_offset + 0x71040)
-#define _PIPEB_FLIPCOUNT_GM45  (dev_priv->info->display_mmio_offset + 0x71044)
+#define _PIPEB_FRMCOUNT_GM45   (dev_priv->info.display_mmio_offset + 0x71040)
+#define _PIPEB_FLIPCOUNT_GM45  (dev_priv->info.display_mmio_offset + 0x71044)
 
 
 /* Display B control */
-#define _DSPBCNTR              (dev_priv->info->display_mmio_offset + 0x71180)
+#define _DSPBCNTR              (dev_priv->info.display_mmio_offset + 0x71180)
 #define   DISPPLANE_ALPHA_TRANS_ENABLE         (1<<15)
 #define   DISPPLANE_ALPHA_TRANS_DISABLE                0
 #define   DISPPLANE_SPRITE_ABOVE_DISPLAY       0
 #define   DISPPLANE_SPRITE_ABOVE_OVERLAY       (1)
-#define _DSPBADDR              (dev_priv->info->display_mmio_offset + 0x71184)
-#define _DSPBSTRIDE            (dev_priv->info->display_mmio_offset + 0x71188)
-#define _DSPBPOS               (dev_priv->info->display_mmio_offset + 0x7118C)
-#define _DSPBSIZE              (dev_priv->info->display_mmio_offset + 0x71190)
-#define _DSPBSURF              (dev_priv->info->display_mmio_offset + 0x7119C)
-#define _DSPBTILEOFF           (dev_priv->info->display_mmio_offset + 0x711A4)
-#define _DSPBOFFSET            (dev_priv->info->display_mmio_offset + 0x711A4)
-#define _DSPBSURFLIVE          (dev_priv->info->display_mmio_offset + 0x711AC)
+#define _DSPBADDR              (dev_priv->info.display_mmio_offset + 0x71184)
+#define _DSPBSTRIDE            (dev_priv->info.display_mmio_offset + 0x71188)
+#define _DSPBPOS               (dev_priv->info.display_mmio_offset + 0x7118C)
+#define _DSPBSIZE              (dev_priv->info.display_mmio_offset + 0x71190)
+#define _DSPBSURF              (dev_priv->info.display_mmio_offset + 0x7119C)
+#define _DSPBTILEOFF           (dev_priv->info.display_mmio_offset + 0x711A4)
+#define _DSPBOFFSET            (dev_priv->info.display_mmio_offset + 0x711A4)
+#define _DSPBSURFLIVE          (dev_priv->info.display_mmio_offset + 0x711AC)
 
 /* Sprite A control */
 #define _DVSACNTR              0x72180
 #define  ILK_ELPIN_409_SELECT  (1 << 25)
 #define  ILK_DPARB_GATE        (1<<22)
 #define  ILK_VSDPFD_FULL       (1<<21)
-#define ILK_DISPLAY_CHICKEN_FUSES      0x42014
-#define  ILK_INTERNAL_GRAPHICS_DISABLE (1<<31)
-#define  ILK_INTERNAL_DISPLAY_DISABLE  (1<<30)
-#define  ILK_DISPLAY_DEBUG_DISABLE     (1<<29)
-#define  ILK_HDCP_DISABLE              (1<<25)
-#define  ILK_eDP_A_DISABLE             (1<<24)
-#define  ILK_DESKTOP                   (1<<23)
+#define FUSE_STRAP                     0x42014
+#define  ILK_INTERNAL_GRAPHICS_DISABLE (1 << 31)
+#define  ILK_INTERNAL_DISPLAY_DISABLE  (1 << 30)
+#define  ILK_DISPLAY_DEBUG_DISABLE     (1 << 29)
+#define  ILK_HDCP_DISABLE              (1 << 25)
+#define  ILK_eDP_A_DISABLE             (1 << 24)
+#define  HSW_CDCLK_LIMIT               (1 << 24)
+#define  ILK_DESKTOP                   (1 << 23)
 
 #define ILK_DSPCLK_GATE_D                      0x42020
 #define   ILK_VRHUNIT_CLOCK_GATE_DISABLE       (1 << 28)
 #define HSW_SCRATCH1                           0xb038
 #define  HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE  (1<<27)
 
-#define HSW_FUSE_STRAP         0x42014
-#define  HSW_CDCLK_LIMIT       (1 << 24)
-
 /* PCH */
 
 /* south display engine interrupt: IBX */
 #define   GEN8_CENTROID_PIXEL_OPT_DIS  (1<<8)
 #define   GEN8_SAMPLER_POWER_BYPASS_DIS        (1<<1)
 
-#define G4X_AUD_VID_DID                        (dev_priv->info->display_mmio_offset + 0x62020)
+#define G4X_AUD_VID_DID                        (dev_priv->info.display_mmio_offset + 0x62020)
 #define INTEL_AUDIO_DEVCL              0x808629FB
 #define INTEL_AUDIO_DEVBLC             0x80862801
 #define INTEL_AUDIO_DEVCTG             0x80862802
 
 /* SFUSE_STRAP */
 #define SFUSE_STRAP                    0xc2014
+#define  SFUSE_STRAP_FUSE_LOCK         (1<<13)
+#define  SFUSE_STRAP_DISPLAY_DISABLED  (1<<7)
 #define  SFUSE_STRAP_DDIB_DETECTED     (1<<2)
 #define  SFUSE_STRAP_DDIC_DETECTED     (1<<1)
 #define  SFUSE_STRAP_DDID_DETECTED     (1<<0)
 #define  READ_DATA_VALID(n)                            (1 << (n))
 
 /* For UMS only (deprecated): */
-#define _PALETTE_A (dev_priv->info->display_mmio_offset + 0xa000)
-#define _PALETTE_B (dev_priv->info->display_mmio_offset + 0xa800)
-#define _DPLL_A (dev_priv->info->display_mmio_offset + 0x6014)
-#define _DPLL_B (dev_priv->info->display_mmio_offset + 0x6018)
-#define _DPLL_A_MD (dev_priv->info->display_mmio_offset + 0x601c)
-#define _DPLL_B_MD (dev_priv->info->display_mmio_offset + 0x6020)
+#define _PALETTE_A (dev_priv->info.display_mmio_offset + 0xa000)
+#define _PALETTE_B (dev_priv->info.display_mmio_offset + 0xa800)
+#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
+#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
+#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
+#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
 
 #endif /* _I915_REG_H_ */
index 6e580c98dede727175cf0542b0a1024ad0e2a5da..b95a380958dbe8b55c275cd8b047f92f5ebbe81b 100644 (file)
@@ -34,15 +34,15 @@ TRACE_EVENT(i915_gem_object_create,
 );
 
 TRACE_EVENT(i915_vma_bind,
-           TP_PROTO(struct i915_vma *vma, bool mappable),
-           TP_ARGS(vma, mappable),
+           TP_PROTO(struct i915_vma *vma, unsigned flags),
+           TP_ARGS(vma, flags),
 
            TP_STRUCT__entry(
                             __field(struct drm_i915_gem_object *, obj)
                             __field(struct i915_address_space *, vm)
                             __field(u32, offset)
                             __field(u32, size)
-                            __field(bool, mappable)
+                            __field(unsigned, flags)
                             ),
 
            TP_fast_assign(
@@ -50,12 +50,12 @@ TRACE_EVENT(i915_vma_bind,
                           __entry->vm = vma->vm;
                           __entry->offset = vma->node.start;
                           __entry->size = vma->node.size;
-                          __entry->mappable = mappable;
+                          __entry->flags = flags;
                           ),
 
            TP_printk("obj=%p, offset=%08x size=%x%s vm=%p",
                      __entry->obj, __entry->offset, __entry->size,
-                     __entry->mappable ? ", mappable" : "",
+                     __entry->flags & PIN_MAPPABLE ? ", mappable" : "",
                      __entry->vm)
 );
 
@@ -196,26 +196,26 @@ DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
 );
 
 TRACE_EVENT(i915_gem_evict,
-           TP_PROTO(struct drm_device *dev, u32 size, u32 align, bool mappable),
-           TP_ARGS(dev, size, align, mappable),
+           TP_PROTO(struct drm_device *dev, u32 size, u32 align, unsigned flags),
+           TP_ARGS(dev, size, align, flags),
 
            TP_STRUCT__entry(
                             __field(u32, dev)
                             __field(u32, size)
                             __field(u32, align)
-                            __field(bool, mappable)
+                            __field(unsigned, flags)
                            ),
 
            TP_fast_assign(
                           __entry->dev = dev->primary->index;
                           __entry->size = size;
                           __entry->align = align;
-                          __entry->mappable = mappable;
+                          __entry->flags = flags;
                          ),
 
            TP_printk("dev=%d, size=%d, align=%d %s",
                      __entry->dev, __entry->size, __entry->align,
-                     __entry->mappable ? ", mappable" : "")
+                     __entry->flags & PIN_MAPPABLE ? ", mappable" : "")
 );
 
 TRACE_EVENT(i915_gem_evict_everything,
index 5b444a4b625caa449d26eebaf12126253344521d..9864aa1ccbe825a09d9b341af911996994b87915 100644 (file)
@@ -833,6 +833,7 @@ void intel_crt_init(struct drm_device *dev)
                crt->base.get_hw_state = intel_crt_get_hw_state;
        }
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
index cd65dd04ba20f8385417971f4f7a2b200e393bda..2643d3b8b67daefda6e13f235a14cacfb19ef10f 100644 (file)
@@ -1415,7 +1415,7 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
 
        if (lcpll & LCPLL_CD_SOURCE_FCLK) {
                return 800000;
-       } else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) {
+       } else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) {
                return 450000;
        } else if (freq == LCPLL_CLK_FREQ_450) {
                return 450000;
index 0f4cbd0aa59e03cd2ea1030d09069a97ee5cd25e..f19e6ea36dc4f0eb28462d8744fb6d51b97d5951 100644 (file)
@@ -51,7 +51,10 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
 
 static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
                          int x, int y, struct drm_framebuffer *old_fb);
-
+static int intel_framebuffer_init(struct drm_device *dev,
+                                 struct intel_framebuffer *ifb,
+                                 struct drm_mode_fb_cmd2 *mode_cmd,
+                                 struct drm_i915_gem_object *obj);
 
 typedef struct {
        int     min, max;
@@ -1030,7 +1033,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
        u32 val;
 
        /* ILK FDI PLL is always enabled */
-       if (dev_priv->info->gen == 5)
+       if (INTEL_INFO(dev_priv->dev)->gen == 5)
                return;
 
        /* On Haswell, DDI ports are responsible for the FDI PLL setup */
@@ -1189,7 +1192,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
        u32 val;
 
        if (IS_VALLEYVIEW(dev)) {
-               for (i = 0; i < dev_priv->num_plane; i++) {
+               for (i = 0; i < INTEL_INFO(dev)->num_sprites; i++) {
                        reg = SPCNTR(pipe, i);
                        val = I915_READ(reg);
                        WARN((val & SP_ENABLE),
@@ -1443,7 +1446,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
        assert_pipe_disabled(dev_priv, crtc->pipe);
 
        /* No really, not for ILK+ */
-       BUG_ON(dev_priv->info->gen >= 5);
+       BUG_ON(INTEL_INFO(dev)->gen >= 5);
 
        /* PLL is protected by panel, make sure we can write it */
        if (IS_MOBILE(dev) && !IS_I830(dev))
@@ -1549,11 +1552,12 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
  */
 static void ironlake_enable_shared_dpll(struct intel_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 
        /* PCH PLLs only available on ILK, SNB and IVB */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev)->gen < 5);
        if (WARN_ON(pll == NULL))
                return;
 
@@ -1578,11 +1582,12 @@ static void ironlake_enable_shared_dpll(struct intel_crtc *crtc)
 
 static void intel_disable_shared_dpll(struct intel_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 
        /* PCH only available on ILK+ */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev)->gen < 5);
        if (WARN_ON(pll == NULL))
               return;
 
@@ -1617,7 +1622,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        uint32_t reg, val, pipeconf_val;
 
        /* PCH only available on ILK+ */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev)->gen < 5);
 
        /* Make sure PCH DPLL is enabled */
        assert_shared_dpll_enabled(dev_priv,
@@ -1670,7 +1675,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        u32 val, pipeconf_val;
 
        /* PCH only available on ILK+ */
-       BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(INTEL_INFO(dev_priv->dev)->gen < 5);
 
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
@@ -1744,21 +1749,16 @@ static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
 
 /**
  * intel_enable_pipe - enable a pipe, asserting requirements
- * @dev_priv: i915 private structure
- * @pipe: pipe to enable
- * @pch_port: on ILK+, is this pipe driving a PCH port or not
+ * @crtc: crtc responsible for the pipe
  *
- * Enable @pipe, making sure that various hardware specific requirements
+ * Enable @crtc's pipe, making sure that various hardware specific requirements
  * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
- *
- * @pipe should be %PIPE_A or %PIPE_B.
- *
- * Will wait until the pipe is actually running (i.e. first vblank) before
- * returning.
  */
-static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
-                             bool pch_port, bool dsi)
+static void intel_enable_pipe(struct intel_crtc *crtc)
 {
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = crtc->pipe;
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
        enum pipe pch_transcoder;
@@ -1780,12 +1780,12 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
         * need the check.
         */
        if (!HAS_PCH_SPLIT(dev_priv->dev))
-               if (dsi)
+               if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DSI))
                        assert_dsi_pll_enabled(dev_priv);
                else
                        assert_pll_enabled(dev_priv, pipe);
        else {
-               if (pch_port) {
+               if (crtc->config.has_pch_encoder) {
                        /* if driving the PCH, we need FDI enabled */
                        assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
                        assert_fdi_tx_pll_enabled(dev_priv,
@@ -1796,11 +1796,24 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
-       if (val & PIPECONF_ENABLE)
+       if (val & PIPECONF_ENABLE) {
+               WARN_ON(!(pipe == PIPE_A &&
+                         dev_priv->quirks & QUIRK_PIPEA_FORCE));
                return;
+       }
 
        I915_WRITE(reg, val | PIPECONF_ENABLE);
-       intel_wait_for_vblank(dev_priv->dev, pipe);
+       POSTING_READ(reg);
+
+       /*
+        * There's no guarantee the pipe will really start running now. It
+        * depends on the Gen, the output type and the relative order between
+        * pipe and plane enabling. Avoid waiting on HSW+ since it's not
+        * necessary.
+        * TODO: audit the previous gens.
+        */
+       if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
+               intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
 /**
@@ -1851,7 +1864,8 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 void intel_flush_primary_plane(struct drm_i915_private *dev_priv,
                               enum plane plane)
 {
-       u32 reg = dev_priv->info->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane);
+       struct drm_device *dev = dev_priv->dev;
+       u32 reg = INTEL_INFO(dev)->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane);
 
        I915_WRITE(reg, I915_READ(reg));
        POSTING_READ(reg);
@@ -1929,6 +1943,14 @@ static bool need_vtd_wa(struct drm_device *dev)
        return false;
 }
 
+static int intel_align_height(struct drm_device *dev, int height, bool tiled)
+{
+       int tile_height;
+
+       tile_height = tiled ? (IS_GEN2(dev) ? 16 : 8) : 1;
+       return ALIGN(height, tile_height);
+}
+
 int
 intel_pin_and_fence_fb_obj(struct drm_device *dev,
                           struct drm_i915_gem_object *obj,
@@ -2299,33 +2321,6 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
        return ret;
 }
 
-static void intel_crtc_update_sarea_pos(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);
-
-       if (!dev->primary->master)
-               return;
-
-       master_priv = dev->primary->master->driver_priv;
-       if (!master_priv->sarea_priv)
-               return;
-
-       switch (intel_crtc->pipe) {
-       case 0:
-               master_priv->sarea_priv->pipeA_x = x;
-               master_priv->sarea_priv->pipeA_y = y;
-               break;
-       case 1:
-               master_priv->sarea_priv->pipeB_x = x;
-               master_priv->sarea_priv->pipeB_y = y;
-               break;
-       default:
-               break;
-       }
-}
-
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                    struct drm_framebuffer *fb)
@@ -2413,8 +2408,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        intel_edp_psr_update(dev);
        mutex_unlock(&dev->struct_mutex);
 
-       intel_crtc_update_sarea_pos(crtc, x, y);
-
        return 0;
 }
 
@@ -3587,8 +3580,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        intel_crtc_load_lut(crtc);
 
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe,
-                         intel_crtc->config.has_pch_encoder, false);
+       intel_enable_pipe(intel_crtc);
        intel_enable_primary_plane(dev_priv, plane, pipe);
        intel_enable_planes(crtc);
        intel_crtc_update_cursor(crtc, true);
@@ -3733,8 +3725,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        intel_ddi_enable_transcoder_func(crtc);
 
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe,
-                         intel_crtc->config.has_pch_encoder, false);
+       intel_enable_pipe(intel_crtc);
 
        if (intel_crtc->config.has_pch_encoder)
                lpt_pch_enable(crtc);
@@ -3748,16 +3739,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
         * to change the workaround. */
        haswell_mode_set_planes_workaround(intel_crtc);
        haswell_crtc_enable_planes(crtc);
-
-       /*
-        * There seems to be a race in PCH platform hw (at least on some
-        * outputs) where an enabled pipe still completes any pageflip right
-        * away (as if the pipe is off) instead of waiting for vblank. As soon
-        * as the first vblank happend, everything works as expected. Hence just
-        * wait for one vblank before returning to avoid strange things
-        * happening.
-        */
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@ -4169,7 +4150,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
        intel_crtc_load_lut(crtc);
 
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe, false, is_dsi);
+       intel_enable_pipe(intel_crtc);
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
        intel_enable_primary_plane(dev_priv, plane, pipe);
        intel_enable_planes(crtc);
@@ -4208,7 +4189,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
        intel_crtc_load_lut(crtc);
 
        intel_update_watermarks(crtc);
-       intel_enable_pipe(dev_priv, pipe, false, false);
+       intel_enable_pipe(intel_crtc);
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
        intel_enable_primary_plane(dev_priv, plane, pipe);
        intel_enable_planes(crtc);
@@ -5256,25 +5237,23 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
        pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w;
 }
 
-static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc,
-                                            struct intel_crtc_config *pipe_config)
+void intel_mode_from_pipe_config(struct drm_display_mode *mode,
+                                struct intel_crtc_config *pipe_config)
 {
-       struct drm_crtc *crtc = &intel_crtc->base;
+       mode->hdisplay = pipe_config->adjusted_mode.crtc_hdisplay;
+       mode->htotal = pipe_config->adjusted_mode.crtc_htotal;
+       mode->hsync_start = pipe_config->adjusted_mode.crtc_hsync_start;
+       mode->hsync_end = pipe_config->adjusted_mode.crtc_hsync_end;
 
-       crtc->mode.hdisplay = pipe_config->adjusted_mode.crtc_hdisplay;
-       crtc->mode.htotal = pipe_config->adjusted_mode.crtc_htotal;
-       crtc->mode.hsync_start = pipe_config->adjusted_mode.crtc_hsync_start;
-       crtc->mode.hsync_end = pipe_config->adjusted_mode.crtc_hsync_end;
+       mode->vdisplay = pipe_config->adjusted_mode.crtc_vdisplay;
+       mode->vtotal = pipe_config->adjusted_mode.crtc_vtotal;
+       mode->vsync_start = pipe_config->adjusted_mode.crtc_vsync_start;
+       mode->vsync_end = pipe_config->adjusted_mode.crtc_vsync_end;
 
-       crtc->mode.vdisplay = pipe_config->adjusted_mode.crtc_vdisplay;
-       crtc->mode.vtotal = pipe_config->adjusted_mode.crtc_vtotal;
-       crtc->mode.vsync_start = pipe_config->adjusted_mode.crtc_vsync_start;
-       crtc->mode.vsync_end = pipe_config->adjusted_mode.crtc_vsync_end;
+       mode->flags = pipe_config->adjusted_mode.flags;
 
-       crtc->mode.flags = pipe_config->adjusted_mode.flags;
-
-       crtc->mode.clock = pipe_config->adjusted_mode.crtc_clock;
-       crtc->mode.flags |= pipe_config->adjusted_mode.flags;
+       mode->clock = pipe_config->adjusted_mode.crtc_clock;
+       mode->flags |= pipe_config->adjusted_mode.flags;
 }
 
 static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
@@ -7577,7 +7556,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->info->cursor_needs_physical) {
+       if (!INTEL_INFO(dev)->cursor_needs_physical) {
                unsigned alignment;
 
                if (obj->tiling_mode) {
@@ -7625,7 +7604,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 
  finish:
        if (intel_crtc->cursor_bo) {
-               if (dev_priv->info->cursor_needs_physical) {
+               if (INTEL_INFO(dev)->cursor_needs_physical) {
                        if (intel_crtc->cursor_bo != obj)
                                i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
                } else
@@ -7687,10 +7666,10 @@ static struct drm_display_mode load_detect_mode = {
                 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
 };
 
-static struct drm_framebuffer *
-intel_framebuffer_create(struct drm_device *dev,
-                        struct drm_mode_fb_cmd2 *mode_cmd,
-                        struct drm_i915_gem_object *obj)
+struct drm_framebuffer *
+__intel_framebuffer_create(struct drm_device *dev,
+                          struct drm_mode_fb_cmd2 *mode_cmd,
+                          struct drm_i915_gem_object *obj)
 {
        struct intel_framebuffer *intel_fb;
        int ret;
@@ -7701,12 +7680,7 @@ intel_framebuffer_create(struct drm_device *dev,
                return ERR_PTR(-ENOMEM);
        }
 
-       ret = i915_mutex_lock_interruptible(dev);
-       if (ret)
-               goto err;
-
        ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
-       mutex_unlock(&dev->struct_mutex);
        if (ret)
                goto err;
 
@@ -7718,6 +7692,23 @@ err:
        return ERR_PTR(ret);
 }
 
+struct drm_framebuffer *
+intel_framebuffer_create(struct drm_device *dev,
+                        struct drm_mode_fb_cmd2 *mode_cmd,
+                        struct drm_i915_gem_object *obj)
+{
+       struct drm_framebuffer *fb;
+       int ret;
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ERR_PTR(ret);
+       fb = __intel_framebuffer_create(dev, mode_cmd, obj);
+       mutex_unlock(&dev->struct_mutex);
+
+       return fb;
+}
+
 static u32
 intel_framebuffer_pitch_for_width(int width, int bpp)
 {
@@ -7763,14 +7754,16 @@ mode_fits_in_fbdev(struct drm_device *dev,
        struct drm_i915_gem_object *obj;
        struct drm_framebuffer *fb;
 
-       if (dev_priv->fbdev == NULL)
+       if (!dev_priv->fbdev)
                return NULL;
 
-       obj = dev_priv->fbdev->ifb.obj;
-       if (obj == NULL)
+       if (!dev_priv->fbdev->fb)
                return NULL;
 
-       fb = &dev_priv->fbdev->ifb.base;
+       obj = dev_priv->fbdev->fb->obj;
+       BUG_ON(!obj);
+
+       fb = &dev_priv->fbdev->fb->base;
        if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
                                                               fb->bits_per_pixel))
                return NULL;
@@ -8220,7 +8213,7 @@ void intel_mark_idle(struct drm_device *dev)
                intel_decrease_pllclock(crtc);
        }
 
-       if (dev_priv->info->gen >= 6)
+       if (INTEL_INFO(dev)->gen >= 6)
                gen6_rps_idle(dev->dev_private);
 }
 
@@ -10384,8 +10377,7 @@ static bool has_edp_a(struct drm_device *dev)
        if ((I915_READ(DP_A) & DP_DETECTED) == 0)
                return false;
 
-       if (IS_GEN5(dev) &&
-           (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
+       if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
                return false;
 
        return true;
@@ -10538,18 +10530,13 @@ static void intel_setup_outputs(struct drm_device *dev)
        drm_helper_move_panel_connectors_to_head(dev);
 }
 
-void intel_framebuffer_fini(struct intel_framebuffer *fb)
-{
-       drm_framebuffer_cleanup(&fb->base);
-       WARN_ON(!fb->obj->framebuffer_references--);
-       drm_gem_object_unreference_unlocked(&fb->obj->base);
-}
-
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
-       intel_framebuffer_fini(intel_fb);
+       drm_framebuffer_cleanup(fb);
+       WARN_ON(!intel_fb->obj->framebuffer_references--);
+       drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
        kfree(intel_fb);
 }
 
@@ -10573,7 +10560,7 @@ int intel_framebuffer_init(struct drm_device *dev,
                           struct drm_mode_fb_cmd2 *mode_cmd,
                           struct drm_i915_gem_object *obj)
 {
-       int aligned_height, tile_height;
+       int aligned_height;
        int pitch_limit;
        int ret;
 
@@ -10667,9 +10654,8 @@ int intel_framebuffer_init(struct drm_device *dev,
        if (mode_cmd->offsets[0] != 0)
                return -EINVAL;
 
-       tile_height = IS_GEN2(dev) ? 16 : 8;
-       aligned_height = ALIGN(mode_cmd->height,
-                              obj->tiling_mode ? tile_height : 1);
+       aligned_height = intel_align_height(dev, mode_cmd->height,
+                                           obj->tiling_mode);
        /* FIXME drm helper for size checks (especially planar formats)? */
        if (obj->base.size < aligned_height * mode_cmd->pitches[0])
                return -EINVAL;
@@ -11049,7 +11035,7 @@ void intel_modeset_init(struct drm_device *dev)
 
        for_each_pipe(i) {
                intel_crtc_init(dev, i);
-               for (j = 0; j < dev_priv->num_plane; j++) {
+               for (j = 0; j < INTEL_INFO(dev)->num_sprites; j++) {
                        ret = intel_plane_init(dev, i, j);
                        if (ret)
                                DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
@@ -11069,6 +11055,8 @@ void intel_modeset_init(struct drm_device *dev)
 
        /* Just in case the BIOS is doing something questionable. */
        intel_disable_fbc(dev);
+
+       intel_modeset_setup_hw_state(dev, false);
 }
 
 static void
@@ -11375,8 +11363,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
        list_for_each_entry(crtc, &dev->mode_config.crtc_list,
                            base.head) {
                if (crtc->active && i915.fastboot) {
-                       intel_crtc_mode_from_pipe_config(crtc, &crtc->config);
-
+                       intel_mode_from_pipe_config(&crtc->base.mode, &crtc->config);
                        DRM_DEBUG_KMS("[CRTC:%d] found active mode: ",
                                      crtc->base.base.id);
                        drm_mode_debug_printmodeline(&crtc->base.mode);
@@ -11436,10 +11423,14 @@ void intel_modeset_gem_init(struct drm_device *dev)
        intel_modeset_init_hw(dev);
 
        intel_setup_overlay(dev);
+}
 
-       mutex_lock(&dev->mode_config.mutex);
-       intel_modeset_setup_hw_state(dev, false);
-       mutex_unlock(&dev->mode_config.mutex);
+void intel_connector_unregister(struct intel_connector *intel_connector)
+{
+       struct drm_connector *connector = &intel_connector->base;
+
+       intel_panel_destroy_backlight(connector);
+       drm_sysfs_connector_remove(connector);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -11486,8 +11477,10 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        /* destroy the backlight and sysfs files before encoders/connectors */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               intel_panel_destroy_backlight(connector);
-               drm_sysfs_connector_remove(connector);
+               struct intel_connector *intel_connector;
+
+               intel_connector = to_intel_connector(connector);
+               intel_connector->unregister(intel_connector);
        }
 
        drm_mode_config_cleanup(dev);
@@ -11520,12 +11513,24 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
        unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
        u16 gmch_ctrl;
 
-       pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
+       if (pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl)) {
+               DRM_ERROR("failed to read control word\n");
+               return -EIO;
+       }
+
+       if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !state)
+               return 0;
+
        if (state)
                gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
        else
                gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-       pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
+
+       if (pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl)) {
+               DRM_ERROR("failed to write control word\n");
+               return -EIO;
+       }
+
        return 0;
 }
 
index bd1df502bc34faaf36effec0665d45d5019f20a8..c512d78af271aff044ad853f0cdeb8f0ed002fa1 100644 (file)
@@ -784,6 +784,16 @@ out:
        return ret;
 }
 
+static void
+intel_dp_connector_unregister(struct intel_connector *intel_connector)
+{
+       struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base);
+
+       sysfs_remove_link(&intel_connector->base.kdev->kobj,
+                         intel_dp->adapter.dev.kobj.name);
+       intel_connector_unregister(intel_connector);
+}
+
 static int
 intel_dp_i2c_init(struct intel_dp *intel_dp,
                  struct intel_connector *intel_connector, const char *name)
@@ -801,9 +811,19 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
        strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
        intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
        intel_dp->adapter.algo_data = &intel_dp->algo;
-       intel_dp->adapter.dev.parent = intel_connector->base.kdev;
+       intel_dp->adapter.dev.parent = intel_connector->base.dev->dev;
 
        ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
+       if (ret < 0)
+               return ret;
+
+       ret = sysfs_create_link(&intel_connector->base.kdev->kobj,
+                               &intel_dp->adapter.dev.kobj,
+                               intel_dp->adapter.dev.kobj.name);
+
+       if (ret < 0)
+               i2c_del_adapter(&intel_dp->adapter);
+
        return ret;
 }
 
@@ -3739,7 +3759,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                        fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
        }
 
-       intel_panel_init(&intel_connector->panel, fixed_mode);
+       intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
        intel_panel_setup_backlight(connector);
 
        return true;
@@ -3808,6 +3828,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
        else
                intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_dp_connector_unregister;
 
        intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
        if (HAS_DDI(dev)) {
index 44067bce5e04ba9eb4c72a3fe5f8f178261b97ab..a4ffc021c317c2ba00db3371c57c750d4ebf6da9 100644 (file)
@@ -110,7 +110,7 @@ struct intel_framebuffer {
 
 struct intel_fbdev {
        struct drm_fb_helper helper;
-       struct intel_framebuffer ifb;
+       struct intel_framebuffer *fb;
        struct list_head fbdev_list;
        struct drm_display_mode *our_mode;
 };
@@ -187,6 +187,14 @@ struct intel_connector {
         * and active (i.e. dpms ON state). */
        bool (*get_hw_state)(struct intel_connector *);
 
+       /*
+        * Removes all interfaces through which the connector is accessible
+        * - like sysfs, debugfs entries -, so that no new operations can be
+        * started on the connector. Also makes sure all currently pending
+        * operations finish before returing.
+        */
+       void (*unregister)(struct intel_connector *);
+
        /* Panel info for eDP and LVDS */
        struct intel_panel panel;
 
@@ -681,11 +689,10 @@ int intel_pin_and_fence_fb_obj(struct drm_device *dev,
                               struct drm_i915_gem_object *obj,
                               struct intel_ring_buffer *pipelined);
 void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
-int intel_framebuffer_init(struct drm_device *dev,
-                          struct intel_framebuffer *ifb,
+struct drm_framebuffer *
+__intel_framebuffer_create(struct drm_device *dev,
                           struct drm_mode_fb_cmd2 *mode_cmd,
                           struct drm_i915_gem_object *obj);
-void intel_framebuffer_fini(struct intel_framebuffer *fb);
 void intel_prepare_page_flip(struct drm_device *dev, int plane);
 void intel_finish_page_flip(struct drm_device *dev, int pipe);
 void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
@@ -727,6 +734,8 @@ void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_device *dev, bool enable);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
+void intel_mode_from_pipe_config(struct drm_display_mode *mode,
+                                struct intel_crtc_config *pipe_config);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
@@ -824,7 +833,8 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
 
 /* intel_panel.c */
 int intel_panel_init(struct intel_panel *panel,
-                    struct drm_display_mode *fixed_mode);
+                    struct drm_display_mode *fixed_mode,
+                    struct drm_display_mode *downclock_mode);
 void intel_panel_fini(struct intel_panel *panel);
 void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
                            struct drm_display_mode *adjusted_mode);
index fabbf0d895cf2a5e133d804d5e8e05f0f26f79ad..3ee1db1407b054bad37ae3c9f86d050614f05892 100644 (file)
@@ -586,6 +586,7 @@ bool intel_dsi_init(struct drm_device *dev)
        intel_encoder->get_config = intel_dsi_get_config;
 
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) {
                dsi = &intel_dsi_devices[i];
@@ -624,7 +625,7 @@ bool intel_dsi_init(struct drm_device *dev)
        }
 
        fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
-       intel_panel_init(&intel_connector->panel, fixed_mode);
+       intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
 
        return true;
 
index eeff998e52efdea93534ffb680582503f9f2a56c..86eeb8b7d435835e722afe86867c8a80890cad9e 100644 (file)
@@ -477,6 +477,7 @@ void intel_dvo_init(struct drm_device *dev)
        intel_encoder->compute_config = intel_dvo_compute_config;
        intel_encoder->mode_set = intel_dvo_mode_set;
        intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        /* Now, try to find a controller */
        for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
index d6a8a716018dfe1e8dc760277bac8a756aaa8497..19be4bfbcc59507c966b2397177109fa792d9c05 100644 (file)
@@ -62,6 +62,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
 {
        struct intel_fbdev *ifbdev =
                container_of(helper, struct intel_fbdev, helper);
+       struct drm_framebuffer *fb;
        struct drm_device *dev = helper->dev;
        struct drm_mode_fb_cmd2 mode_cmd = {};
        struct drm_i915_gem_object *obj;
@@ -93,13 +94,17 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
        /* Flush everything out, we'll be doing GTT only from now on */
        ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
        if (ret) {
-               DRM_ERROR("failed to pin fb: %d\n", ret);
+               DRM_ERROR("failed to pin obj: %d\n", ret);
                goto out_unref;
        }
 
-       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
-       if (ret)
+       fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
+       if (IS_ERR(fb)) {
+               ret = PTR_ERR(fb);
                goto out_unpin;
+       }
+
+       ifbdev->fb = to_intel_framebuffer(fb);
 
        return 0;
 
@@ -116,7 +121,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 {
        struct intel_fbdev *ifbdev =
                container_of(helper, struct intel_fbdev, helper);
-       struct intel_framebuffer *intel_fb = &ifbdev->ifb;
+       struct intel_framebuffer *intel_fb = ifbdev->fb;
        struct drm_device *dev = helper->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct fb_info *info;
@@ -126,11 +131,12 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
        mutex_lock(&dev->struct_mutex);
 
-       if (!intel_fb->obj) {
+       if (!intel_fb || WARN_ON(!intel_fb->obj)) {
                DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
                ret = intelfb_alloc(helper, sizes);
                if (ret)
                        goto out_unlock;
+               intel_fb = ifbdev->fb;
        } else {
                DRM_DEBUG_KMS("re-using BIOS fb\n");
                sizes->fb_width = intel_fb->base.width;
@@ -148,7 +154,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
        info->par = helper;
 
-       fb = &ifbdev->ifb.base;
+       fb = &ifbdev->fb->base;
 
        ifbdev->helper.fb = fb;
        ifbdev->helper.fbdev = info;
@@ -194,7 +200,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
         * If the object is stolen however, it will be full of whatever
         * garbage was left in there.
         */
-       if (ifbdev->ifb.obj->stolen)
+       if (ifbdev->fb->obj->stolen)
                memset_io(info->screen_base, 0, info->screen_size);
 
        /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
@@ -236,7 +242,152 @@ static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
        *blue = intel_crtc->lut_b[regno] << 8;
 }
 
+static struct drm_fb_helper_crtc *
+intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
+{
+       int i;
+
+       for (i = 0; i < fb_helper->crtc_count; i++)
+               if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
+                       return &fb_helper->crtc_info[i];
+
+       return NULL;
+}
+
+/*
+ * Try to read the BIOS display configuration and use it for the initial
+ * fb configuration.
+ *
+ * The BIOS or boot loader will generally create an initial display
+ * configuration for us that includes some set of active pipes and displays.
+ * This routine tries to figure out which pipes and connectors are active
+ * and stuffs them into the crtcs and modes array given to us by the
+ * drm_fb_helper code.
+ *
+ * The overall sequence is:
+ *   intel_fbdev_init - from driver load
+ *     intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data
+ *     drm_fb_helper_init - build fb helper structs
+ *     drm_fb_helper_single_add_all_connectors - more fb helper structs
+ *   intel_fbdev_initial_config - apply the config
+ *     drm_fb_helper_initial_config - call ->probe then register_framebuffer()
+ *         drm_setup_crtcs - build crtc config for fbdev
+ *           intel_fb_initial_config - find active connectors etc
+ *         drm_fb_helper_single_fb_probe - set up fbdev
+ *           intelfb_create - re-use or alloc fb, build out fbdev structs
+ *
+ * Note that we don't make special consideration whether we could actually
+ * switch to the selected modes without a full modeset. E.g. when the display
+ * is in VGA mode we need to recalculate watermarks and set a new high-res
+ * framebuffer anyway.
+ */
+static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
+                                   struct drm_fb_helper_crtc **crtcs,
+                                   struct drm_display_mode **modes,
+                                   bool *enabled, int width, int height)
+{
+       struct drm_device *dev = fb_helper->dev;
+       int i, j;
+       bool *save_enabled;
+       bool any_enabled = false;
+
+       save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
+                              GFP_KERNEL);
+       if (!save_enabled)
+               return false;
+
+       memcpy(save_enabled, enabled, dev->mode_config.num_connector);
+
+       for (i = 0; i < fb_helper->connector_count; i++) {
+               struct drm_fb_helper_connector *fb_conn;
+               struct drm_connector *connector;
+               struct drm_encoder *encoder;
+               struct drm_fb_helper_crtc *new_crtc;
+
+               fb_conn = fb_helper->connector_info[i];
+               connector = fb_conn->connector;
+               if (!enabled[i]) {
+                       DRM_DEBUG_KMS("connector %d not enabled, skipping\n",
+                                     connector->base.id);
+                       continue;
+               }
+
+               encoder = connector->encoder;
+               if (!encoder || WARN_ON(!encoder->crtc)) {
+                       DRM_DEBUG_KMS("connector %d has no encoder or crtc, skipping\n",
+                                     connector->base.id);
+                       enabled[i] = false;
+                       continue;
+               }
+
+               new_crtc = intel_fb_helper_crtc(fb_helper, encoder->crtc);
+
+               /*
+                * Make sure we're not trying to drive multiple connectors
+                * with a single CRTC, since our cloning support may not
+                * match the BIOS.
+                */
+               for (j = 0; j < fb_helper->connector_count; j++) {
+                       if (crtcs[j] == new_crtc) {
+                               any_enabled = false;
+                               goto out;
+                       }
+               }
+
+               DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
+                             fb_conn->connector->base.id);
+
+               /* go for command line mode first */
+               modes[i] = drm_pick_cmdline_mode(fb_conn, width, height);
+
+               /* try for preferred next */
+               if (!modes[i]) {
+                       DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
+                                     fb_conn->connector->base.id);
+                       modes[i] = drm_has_preferred_mode(fb_conn, width,
+                                                         height);
+               }
+
+               /* last resort: use current mode */
+               if (!modes[i]) {
+                       /*
+                        * IMPORTANT: We want to use the adjusted mode (i.e.
+                        * after the panel fitter upscaling) as the initial
+                        * config, not the input mode, which is what crtc->mode
+                        * usually contains. But since our current fastboot
+                        * code puts a mode derived from the post-pfit timings
+                        * into crtc->mode this works out correctly. We don't
+                        * use hwmode anywhere right now, so use it for this
+                        * since the fb helper layer wants a pointer to
+                        * something we own.
+                        */
+                       intel_mode_from_pipe_config(&encoder->crtc->hwmode,
+                                                   &to_intel_crtc(encoder->crtc)->config);
+                       modes[i] = &encoder->crtc->hwmode;
+               }
+               crtcs[i] = new_crtc;
+
+               DRM_DEBUG_KMS("connector %s on crtc %d: %s\n",
+                             drm_get_connector_name(connector),
+                             encoder->crtc->base.id,
+                             modes[i]->name);
+
+               any_enabled = true;
+       }
+
+out:
+       if (!any_enabled) {
+               memcpy(enabled, save_enabled, dev->mode_config.num_connector);
+               kfree(save_enabled);
+               return false;
+       }
+
+       kfree(save_enabled);
+       return true;
+}
+
 static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
+       .initial_config = intel_fb_initial_config,
        .gamma_set = intel_crtc_fb_gamma_set,
        .gamma_get = intel_crtc_fb_gamma_get,
        .fb_probe = intelfb_create,
@@ -258,8 +409,8 @@ static void intel_fbdev_destroy(struct drm_device *dev,
 
        drm_fb_helper_fini(&ifbdev->helper);
 
-       drm_framebuffer_unregister_private(&ifbdev->ifb.base);
-       intel_framebuffer_fini(&ifbdev->ifb);
+       drm_framebuffer_unregister_private(&ifbdev->fb->base);
+       drm_framebuffer_remove(&ifbdev->fb->base);
 }
 
 int intel_fbdev_init(struct drm_device *dev)
@@ -322,7 +473,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state)
         * been restored from swap. If the object is stolen however, it will be
         * full of whatever garbage was left in there.
         */
-       if (state == FBINFO_STATE_RUNNING && ifbdev->ifb.obj->stolen)
+       if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
                memset_io(info->screen_base, 0, info->screen_size);
 
        fb_set_suspend(info, state);
index 43872f00822a063b2fae6acd90ef7a039163b8eb..98d68ab04de462b9c655ce94cb0b2d02074af66d 100644 (file)
@@ -425,7 +425,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
        struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
        u32 reg = VIDEO_DIP_CTL;
        u32 val = I915_READ(reg);
-       u32 port;
+       u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
 
        assert_hdmi_port_disabled(intel_hdmi);
 
@@ -449,18 +449,6 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
                return;
        }
 
-       switch (intel_dig_port->port) {
-       case PORT_B:
-               port = VIDEO_DIP_PORT_B;
-               break;
-       case PORT_C:
-               port = VIDEO_DIP_PORT_C;
-               break;
-       default:
-               BUG();
-               return;
-       }
-
        if (port != (val & VIDEO_DIP_PORT_MASK)) {
                if (val & VIDEO_DIP_ENABLE) {
                        val &= ~VIDEO_DIP_ENABLE;
@@ -491,7 +479,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
        struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
        u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
        u32 val = I915_READ(reg);
-       u32 port;
+       u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
 
        assert_hdmi_port_disabled(intel_hdmi);
 
@@ -507,21 +495,6 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
                return;
        }
 
-       switch (intel_dig_port->port) {
-       case PORT_B:
-               port = VIDEO_DIP_PORT_B;
-               break;
-       case PORT_C:
-               port = VIDEO_DIP_PORT_C;
-               break;
-       case PORT_D:
-               port = VIDEO_DIP_PORT_D;
-               break;
-       default:
-               BUG();
-               return;
-       }
-
        if (port != (val & VIDEO_DIP_PORT_MASK)) {
                if (val & VIDEO_DIP_ENABLE) {
                        val &= ~VIDEO_DIP_ENABLE;
@@ -1263,6 +1236,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
        else
                intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        intel_hdmi_add_properties(intel_hdmi, connector);
 
index 3f3043b4ff26bebf4647771ba166483f72375992..fecff3c2b9e18aecc13435262def62312cb60037 100644 (file)
@@ -899,6 +899,7 @@ void intel_lvds_init(struct drm_device *dev)
        struct drm_encoder *encoder;
        struct drm_display_mode *scan; /* *modes, *bios_mode; */
        struct drm_display_mode *fixed_mode = NULL;
+       struct drm_display_mode *downclock_mode = NULL;
        struct edid *edid;
        struct drm_crtc *crtc;
        u32 lvds;
@@ -957,6 +958,7 @@ void intel_lvds_init(struct drm_device *dev)
        intel_encoder->get_hw_state = intel_lvds_get_hw_state;
        intel_encoder->get_config = intel_lvds_get_config;
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        intel_encoder->type = INTEL_OUTPUT_LVDS;
@@ -1032,15 +1034,14 @@ void intel_lvds_init(struct drm_device *dev)
 
                        fixed_mode = drm_mode_duplicate(dev, scan);
                        if (fixed_mode) {
-                               intel_connector->panel.downclock_mode =
+                               downclock_mode =
                                        intel_find_panel_downclock(dev,
                                        fixed_mode, connector);
-                               if (intel_connector->panel.downclock_mode !=
-                                       NULL && i915.lvds_downclock) {
+                               if (downclock_mode != NULL &&
+                                       i915.lvds_downclock) {
                                        /* We found the downclock for LVDS. */
                                        dev_priv->lvds_downclock_avail = true;
                                        dev_priv->lvds_downclock =
-                                               intel_connector->panel.
                                                downclock_mode->clock;
                                        DRM_DEBUG_KMS("LVDS downclock is found"
                                        " in EDID. Normal clock %dKhz, "
@@ -1116,7 +1117,7 @@ out:
        }
        drm_sysfs_connector_add(connector);
 
-       intel_panel_init(&intel_connector->panel, fixed_mode);
+       intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
        intel_panel_setup_backlight(connector);
 
        return;
@@ -1125,8 +1126,6 @@ failed:
        DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
        drm_connector_cleanup(connector);
        drm_encoder_cleanup(encoder);
-       if (fixed_mode)
-               drm_mode_destroy(dev, fixed_mode);
        kfree(lvds_encoder);
        kfree(lvds_connector);
        return;
index 424f0946d8c47995ffdadebcb1ef22548502fdad..ac519cb46f22a93f3a774d97d1f0fb43886b6942 100644 (file)
@@ -1349,7 +1349,7 @@ void intel_setup_overlay(struct drm_device *dev)
                }
                overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
        } else {
-               ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, true, false);
+               ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE);
                if (ret) {
                        DRM_ERROR("failed to pin overlay register bo\n");
                        goto out_free_bo;
index f1ee2c4d282e6136b135688577b3d9e3bea5e2c1..5bc3f6ea101423de36184bbf17791dd2970b1066 100644 (file)
@@ -1190,9 +1190,11 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev)
 }
 
 int intel_panel_init(struct intel_panel *panel,
-                    struct drm_display_mode *fixed_mode)
+                    struct drm_display_mode *fixed_mode,
+                    struct drm_display_mode *downclock_mode)
 {
        panel->fixed_mode = fixed_mode;
+       panel->downclock_mode = downclock_mode;
 
        return 0;
 }
index f74d7f506aa9ac6d1bde42afed687984295ad968..a6b877a4a916ef0dfb092ad85e548b5fb1d6ae98 100644 (file)
@@ -2741,7 +2741,7 @@ intel_alloc_context_page(struct drm_device *dev)
                return NULL;
        }
 
-       ret = i915_gem_obj_ggtt_pin(ctx, 4096, true, false);
+       ret = i915_gem_obj_ggtt_pin(ctx, 4096, 0);
        if (ret) {
                DRM_ERROR("failed to pin power context: %d\n", ret);
                goto err_unref;
@@ -3196,16 +3196,10 @@ static void valleyview_disable_rps(struct drm_device *dev)
 
 static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
 {
-       if (IS_GEN6(dev))
-               DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
-
-       if (IS_HASWELL(dev))
-               DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
-
        DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
-                       (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
-                       (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
-                       (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
+                (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
+                (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
+                (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
 }
 
 int intel_enable_rc6(const struct drm_device *dev)
@@ -3222,14 +3216,10 @@ int intel_enable_rc6(const struct drm_device *dev)
        if (INTEL_INFO(dev)->gen == 5)
                return 0;
 
-       if (IS_HASWELL(dev))
-               return INTEL_RC6_ENABLE;
-
-       /* snb/ivb have more than one rc6 state. */
-       if (INTEL_INFO(dev)->gen == 6)
-               return INTEL_RC6_ENABLE;
+       if (IS_IVYBRIDGE(dev))
+               return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
 
-       return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
+       return INTEL_RC6_ENABLE;
 }
 
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
@@ -3286,10 +3276,10 @@ static void gen8_enable_rps(struct drm_device *dev)
        /* 3: Enable RC6 */
        if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
                rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
-       DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
+       intel_print_rc6_info(dev, rc6_mask);
        I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
-                       GEN6_RC_CTL_EI_MODE(1) |
-                       rc6_mask);
+                                   GEN6_RC_CTL_EI_MODE(1) |
+                                   rc6_mask);
 
        /* 4 Program defaults and thresholds for RPS*/
        I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */
@@ -3903,9 +3893,10 @@ static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
        unsigned long val;
 
-       if (dev_priv->info->gen != 5)
+       if (INTEL_INFO(dev)->gen != 5)
                return 0;
 
        spin_lock_irq(&mchdev_lock);
@@ -3934,6 +3925,7 @@ unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
 
 static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
 {
+       struct drm_device *dev = dev_priv->dev;
        static const struct v_table {
                u16 vd; /* in .1 mil */
                u16 vm; /* in .1 mil */
@@ -4067,7 +4059,7 @@ static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
                { 16000, 14875, },
                { 16125, 15000, },
        };
-       if (dev_priv->info->is_mobile)
+       if (INTEL_INFO(dev)->is_mobile)
                return v_table[pxvid].vm;
        else
                return v_table[pxvid].vd;
@@ -4110,7 +4102,9 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
 
 void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 {
-       if (dev_priv->info->gen != 5)
+       struct drm_device *dev = dev_priv->dev;
+
+       if (INTEL_INFO(dev)->gen != 5)
                return;
 
        spin_lock_irq(&mchdev_lock);
@@ -4159,9 +4153,10 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
        unsigned long val;
 
-       if (dev_priv->info->gen != 5)
+       if (INTEL_INFO(dev)->gen != 5)
                return 0;
 
        spin_lock_irq(&mchdev_lock);
@@ -4697,6 +4692,14 @@ static void gen6_init_clock_gating(struct drm_device *dev)
        I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) |
                   _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL);
 
+       /*
+        * Bspec says:
+        * "This bit must be set if 3DSTATE_CLIP clip mode is set to normal and
+        * 3DSTATE_SF number of SF output attributes is more than 16."
+        */
+       I915_WRITE(_3D_CHICKEN3,
+                  _MASKED_BIT_ENABLE(_3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH));
+
        /*
         * According to the spec the following bits should be
         * set in order to enable memory self-refresh and fbc:
index 8c1c0bc3e630868ca98980bab93a6f6d75fac5cf..b340c7587629379a34f4db7753a87e25d7a7728f 100644 (file)
@@ -531,9 +531,11 @@ init_pipe_control(struct intel_ring_buffer *ring)
                goto err;
        }
 
-       i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+       ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+       if (ret)
+               goto err_unref;
 
-       ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, true, false);
+       ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0);
        if (ret)
                goto err_unref;
 
@@ -1271,12 +1273,13 @@ static int init_status_page(struct intel_ring_buffer *ring)
                goto err;
        }
 
-       i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+       ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+       if (ret)
+               goto err_unref;
 
-       ret = i915_gem_obj_ggtt_pin(obj, 4096, true, false);
-       if (ret != 0) {
+       ret = i915_gem_obj_ggtt_pin(obj, 4096, 0);
+       if (ret)
                goto err_unref;
-       }
 
        ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
        ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
@@ -1356,7 +1359,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 
        ring->obj = obj;
 
-       ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, true, false);
+       ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
        if (ret)
                goto err_unref;
 
@@ -1513,7 +1516,8 @@ static int ring_wait_for_space(struct intel_ring_buffer *ring, int n)
                        return 0;
                }
 
-               if (dev->primary->master) {
+               if (!drm_core_check_feature(dev, DRIVER_MODESET) &&
+                   dev->primary->master) {
                        struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
                        if (master_priv->sarea_priv)
                                master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
@@ -1939,7 +1943,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
                        return -ENOMEM;
                }
 
-               ret = i915_gem_obj_ggtt_pin(obj, 0, true, false);
+               ret = i915_gem_obj_ggtt_pin(obj, 0, 0);
                if (ret != 0) {
                        drm_gem_object_unreference(&obj->base);
                        DRM_ERROR("Failed to ping batch bo\n");
index 95bdfb3c431c8467b105c616f6d5f9567505804f..825853d82a4d5e579f729cbe3a069e9c7b7618c3 100644 (file)
@@ -2382,24 +2382,62 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)
 }
 
 static void
+intel_sdvo_connector_unregister(struct intel_connector *intel_connector)
+{
+       struct drm_connector *drm_connector;
+       struct intel_sdvo *sdvo_encoder;
+
+       drm_connector = &intel_connector->base;
+       sdvo_encoder = intel_attached_sdvo(&intel_connector->base);
+
+       sysfs_remove_link(&drm_connector->kdev->kobj,
+                         sdvo_encoder->ddc.dev.kobj.name);
+       intel_connector_unregister(intel_connector);
+}
+
+static int
 intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
                          struct intel_sdvo *encoder)
 {
-       drm_connector_init(encoder->base.base.dev,
-                          &connector->base.base,
+       struct drm_connector *drm_connector;
+       int ret;
+
+       drm_connector = &connector->base.base;
+       ret = drm_connector_init(encoder->base.base.dev,
+                          drm_connector,
                           &intel_sdvo_connector_funcs,
                           connector->base.base.connector_type);
+       if (ret < 0)
+               return ret;
 
-       drm_connector_helper_add(&connector->base.base,
+       drm_connector_helper_add(drm_connector,
                                 &intel_sdvo_connector_helper_funcs);
 
        connector->base.base.interlace_allowed = 1;
        connector->base.base.doublescan_allowed = 0;
        connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
        connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
+       connector->base.unregister = intel_sdvo_connector_unregister;
 
        intel_connector_attach_encoder(&connector->base, &encoder->base);
-       drm_sysfs_connector_add(&connector->base.base);
+       ret = drm_sysfs_connector_add(drm_connector);
+       if (ret < 0)
+               goto err1;
+
+       ret = sysfs_create_link(&encoder->ddc.dev.kobj,
+                               &drm_connector->kdev->kobj,
+                               encoder->ddc.dev.kobj.name);
+       if (ret < 0)
+               goto err2;
+
+       return 0;
+
+err2:
+       drm_sysfs_connector_remove(drm_connector);
+err1:
+       drm_connector_cleanup(drm_connector);
+
+       return ret;
 }
 
 static void
@@ -2459,7 +2497,11 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo->is_hdmi = true;
        }
 
-       intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+       if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+               kfree(intel_sdvo_connector);
+               return false;
+       }
+
        if (intel_sdvo->is_hdmi)
                intel_sdvo_add_hdmi_properties(intel_sdvo, intel_sdvo_connector);
 
@@ -2490,7 +2532,10 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
        intel_sdvo->is_tv = true;
 
-       intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+       if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+               kfree(intel_sdvo_connector);
+               return false;
+       }
 
        if (!intel_sdvo_tv_create_property(intel_sdvo, intel_sdvo_connector, type))
                goto err;
@@ -2534,8 +2579,11 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
        }
 
-       intel_sdvo_connector_init(intel_sdvo_connector,
-                                 intel_sdvo);
+       if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+               kfree(intel_sdvo_connector);
+               return false;
+       }
+
        return true;
 }
 
@@ -2566,7 +2614,11 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
        }
 
-       intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+       if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+               kfree(intel_sdvo_connector);
+               return false;
+       }
+
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
                goto err;
 
index 22cf0f4ba24871ad2697306aaec37a577496837f..b64fc1c6ff3f65287258e883ff8a420f931cd9f4 100644 (file)
@@ -1189,8 +1189,8 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
                i915_disable_pipestat(dev_priv, 0,
-                                     PIPE_HOTPLUG_INTERRUPT_ENABLE |
-                                     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
+                                     PIPE_HOTPLUG_INTERRUPT_STATUS |
+                                     PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
                spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
        }
 
@@ -1266,8 +1266,8 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
        if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
                spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
                i915_enable_pipestat(dev_priv, 0,
-                                    PIPE_HOTPLUG_INTERRUPT_ENABLE |
-                                    PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
+                                    PIPE_HOTPLUG_INTERRUPT_STATUS |
+                                    PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
                spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
        }
 
@@ -1634,6 +1634,7 @@ intel_tv_init(struct drm_device *dev)
        intel_encoder->disable = intel_disable_tv;
        intel_encoder->get_hw_state = intel_tv_get_hw_state;
        intel_connector->get_hw_state = intel_connector_get_hw_state;
+       intel_connector->unregister = intel_connector_unregister;
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        intel_encoder->type = INTEL_OUTPUT_TVOUT;
index 8f3dee09757999c7c959e284250142c143d37d7d..f7646548660d7e98e160d2dac40d1f12b310a48d 100644 (file)
@@ -994,6 +994,7 @@ extern void drm_encoder_cleanup(struct drm_encoder *encoder);
 
 extern const char *drm_get_connector_name(const struct drm_connector *connector);
 extern const char *drm_get_connector_status_name(enum drm_connector_status status);
+extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
 extern const char *drm_get_dpms_name(int val);
 extern const char *drm_get_dvi_i_subconnector_name(int val);
 extern const char *drm_get_dvi_i_select_name(int val);
index 471f276ce8f741638ad6ced787aa7f943457e751..2d659dc39972f9a30dce9d9b1bfd6cdd8a9e9606 100644 (file)
@@ -121,5 +121,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
 int drm_fb_helper_debug_enter(struct fb_info *info);
 int drm_fb_helper_debug_leave(struct fb_info *info);
+struct drm_display_mode *
+drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
+                       int width, int height);
+struct drm_display_mode *
+drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
+                     int width, int height);
 
 #endif