]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 24 Jun 2016 06:29:45 +0000 (08:29 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 24 Jun 2016 06:29:45 +0000 (08:29 +0200)
Backmerge drm-next for the reworked device register/unregistering.
Chris Wilson needs that to be able to land his i915 load/unload
demidlayering.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
17 files changed:
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_guc_submission.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_link_training.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_guc.h
drivers/gpu/drm/i915/intel_gvt.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_runtime_pm.c

index 5b7526697838913b01b4d4f15ebee02e29663fa2..9989b6a26b1789473eff995650911b9eb05f7223 100644 (file)
@@ -2544,9 +2544,9 @@ static void i915_guc_client_info(struct seq_file *m,
 
        for_each_engine(engine, dev_priv) {
                seq_printf(m, "\tSubmissions: %llu %s\n",
-                               client->submissions[engine->guc_id],
+                               client->submissions[engine->id],
                                engine->name);
-               tot += client->submissions[engine->guc_id];
+               tot += client->submissions[engine->id];
        }
        seq_printf(m, "\tTotal: %llu\n", tot);
 }
@@ -2587,9 +2587,9 @@ static int i915_guc_info(struct seq_file *m, void *data)
        seq_printf(m, "\nGuC submissions:\n");
        for_each_engine(engine, dev_priv) {
                seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n",
-                       engine->name, guc.submissions[engine->guc_id],
-                       guc.last_seqno[engine->guc_id]);
-               total += guc.submissions[engine->guc_id];
+                       engine->name, guc.submissions[engine->id],
+                       guc.last_seqno[engine->id]);
+               total += guc.submissions[engine->id];
        }
        seq_printf(m, "\t%s: %llu\n", "Total", total);
 
@@ -2701,7 +2701,6 @@ static int i915_sink_crc(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
-       struct intel_encoder *encoder;
        struct intel_connector *connector;
        struct intel_dp *intel_dp = NULL;
        int ret;
@@ -2709,18 +2708,19 @@ static int i915_sink_crc(struct seq_file *m, void *data)
 
        drm_modeset_lock_all(dev);
        for_each_intel_connector(dev, connector) {
+               struct drm_crtc *crtc;
 
-               if (connector->base.dpms != DRM_MODE_DPMS_ON)
+               if (!connector->base.state->best_encoder)
                        continue;
 
-               if (!connector->base.encoder)
+               crtc = connector->base.state->crtc;
+               if (!crtc->state->active)
                        continue;
 
-               encoder = to_intel_encoder(connector->base.encoder);
-               if (encoder->type != INTEL_OUTPUT_EDP)
+               if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
                        continue;
 
-               intel_dp = enc_to_intel_dp(&encoder->base);
+               intel_dp = enc_to_intel_dp(connector->base.state->best_encoder);
 
                ret = intel_dp_sink_crc(intel_dp, crc);
                if (ret)
@@ -2950,7 +2950,7 @@ static void intel_dp_info(struct seq_file *m,
 
        seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
        seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
-       if (intel_encoder->type == INTEL_OUTPUT_EDP)
+       if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
                intel_panel_info(m, &intel_connector->panel);
 }
 
@@ -2989,14 +2989,26 @@ static void intel_connector_info(struct seq_file *m,
                seq_printf(m, "\tCEA rev: %d\n",
                           connector->display_info.cea_rev);
        }
-       if (intel_encoder) {
-               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)
+
+       if (!intel_encoder || intel_encoder->type == INTEL_OUTPUT_DP_MST)
+               return;
+
+       switch (connector->connector_type) {
+       case DRM_MODE_CONNECTOR_DisplayPort:
+       case DRM_MODE_CONNECTOR_eDP:
+               intel_dp_info(m, intel_connector);
+               break;
+       case DRM_MODE_CONNECTOR_LVDS:
+               if (intel_encoder->type == INTEL_OUTPUT_LVDS)
                        intel_lvds_info(m, intel_connector);
+               break;
+       case DRM_MODE_CONNECTOR_HDMIA:
+               if (intel_encoder->type == INTEL_OUTPUT_HDMI ||
+                   intel_encoder->type == INTEL_OUTPUT_UNKNOWN)
+                       intel_hdmi_info(m, intel_connector);
+               break;
+       default:
+               break;
        }
 
        seq_printf(m, "\tmodes:\n");
@@ -3374,31 +3386,16 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
 static void drrs_status_per_crtc(struct seq_file *m,
                struct drm_device *dev, struct intel_crtc *intel_crtc)
 {
-       struct intel_encoder *intel_encoder;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_drrs *drrs = &dev_priv->drrs;
        int vrefresh = 0;
+       struct drm_connector *connector;
 
-       for_each_encoder_on_crtc(dev, &intel_crtc->base, intel_encoder) {
-               /* Encoder connected on this CRTC */
-               switch (intel_encoder->type) {
-               case INTEL_OUTPUT_EDP:
-                       seq_puts(m, "eDP:\n");
-                       break;
-               case INTEL_OUTPUT_DSI:
-                       seq_puts(m, "DSI:\n");
-                       break;
-               case INTEL_OUTPUT_HDMI:
-                       seq_puts(m, "HDMI:\n");
-                       break;
-               case INTEL_OUTPUT_DISPLAYPORT:
-                       seq_puts(m, "DP:\n");
-                       break;
-               default:
-                       seq_printf(m, "Other encoder (id=%d).\n",
-                                               intel_encoder->type);
-                       return;
-               }
+       drm_for_each_connector(connector, dev) {
+               if (connector->state->crtc != &intel_crtc->base)
+                       continue;
+
+               seq_printf(m, "%s:\n", connector->name);
        }
 
        if (dev_priv->vbt.drrs_type == STATIC_DRRS_SUPPORT)
@@ -3461,18 +3458,16 @@ static int i915_drrs_status(struct seq_file *m, void *unused)
        struct intel_crtc *intel_crtc;
        int active_crtc_cnt = 0;
 
+       drm_modeset_lock_all(dev);
        for_each_intel_crtc(dev, intel_crtc) {
-               drm_modeset_lock(&intel_crtc->base.mutex, NULL);
-
                if (intel_crtc->base.state->active) {
                        active_crtc_cnt++;
                        seq_printf(m, "\nCRTC %d:  ", active_crtc_cnt);
 
                        drrs_status_per_crtc(m, dev, intel_crtc);
                }
-
-               drm_modeset_unlock(&intel_crtc->base.mutex);
        }
+       drm_modeset_unlock_all(dev);
 
        if (!active_crtc_cnt)
                seq_puts(m, "No active crtc found\n");
@@ -3490,17 +3485,23 @@ static int i915_dp_mst_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_encoder *encoder;
        struct intel_encoder *intel_encoder;
        struct intel_digital_port *intel_dig_port;
+       struct drm_connector *connector;
+
        drm_modeset_lock_all(dev);
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               intel_encoder = to_intel_encoder(encoder);
-               if (intel_encoder->type != INTEL_OUTPUT_DISPLAYPORT)
+       drm_for_each_connector(connector, dev) {
+               if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
                        continue;
-               intel_dig_port = enc_to_dig_port(encoder);
+
+               intel_encoder = intel_attached_encoder(connector);
+               if (!intel_encoder || intel_encoder->type == INTEL_OUTPUT_DP_MST)
+                       continue;
+
+               intel_dig_port = enc_to_dig_port(&intel_encoder->base);
                if (!intel_dig_port->dp.can_mst)
                        continue;
+
                seq_printf(m, "MST Source Port %c\n",
                           port_name(intel_dig_port->port));
                drm_dp_mst_dump_topology(m, &intel_dig_port->dp.mst_mgr);
index d15a461fa84a3ed56f7b7e5ae2f5951ff2523a43..e28c0ddc0837039efbf00b8601342fa50b8492ae 100644 (file)
@@ -525,18 +525,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
        /* Only enable hotplug handling once the fbdev is fully set up. */
        intel_hpd_init(dev_priv);
 
-       /*
-        * Some ports require correctly set-up hpd registers for detection to
-        * work properly (leading to ghost connected connector status), e.g. VGA
-        * on gm45.  Hence we can only set up the initial fbdev config after hpd
-        * irqs are fully enabled. Now we should scan for the initial config
-        * only once hotplug handling is enabled, but due to screwed-up locking
-        * around kms/fbdev init we can't protect the fdbev initial config
-        * scanning against hotplug events. Hence do this first and ignore the
-        * tiny window where we will loose hotplug notifactions.
-        */
-       intel_fbdev_initial_config_async(dev);
-
        drm_kms_helper_poll_init(dev);
 
        return 0;
@@ -1421,6 +1409,15 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
                intel_gpu_ips_init(dev_priv);
 
        i915_audio_component_init(dev_priv);
+
+       /*
+        * Some ports require correctly set-up hpd registers for detection to
+        * work properly (leading to ghost connected connector status), e.g. VGA
+        * on gm45.  Hence we can only set up the initial fbdev config after hpd
+        * irqs are fully enabled. We do it last so that the async config
+        * cannot run before the connectors are registered.
+        */
+       intel_fbdev_initial_config_async(dev);
 }
 
 /**
index 24a86c64d22ef6f0b1d0ef7db16460d0f772a21c..74d0a61de75af095bb492016c4ad9bcf927eb364 100644 (file)
@@ -2215,6 +2215,7 @@ struct drm_i915_gem_object {
 
        unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS;
 
+       unsigned int has_wc_mmap;
        unsigned int pin_display;
 
        struct sg_table *pages;
@@ -2267,6 +2268,12 @@ struct drm_i915_gem_object {
 };
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
 
+static inline bool
+i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
+{
+       return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE;
+}
+
 /*
  * Optimised SGL iterator for GEM objects
  */
@@ -2783,9 +2790,10 @@ struct drm_i915_cmd_table {
 #define HAS_BROKEN_CS_TLB(dev)         (IS_I830(dev) || IS_845G(dev))
 
 /* WaRsDisableCoarsePowerGating:skl,bxt */
-#define NEEDS_WaRsDisableCoarsePowerGating(dev) (IS_BXT_REVID(dev, 0, BXT_REVID_A1) || \
-                                                IS_SKL_GT3(dev) || \
-                                                IS_SKL_GT4(dev))
+#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
+       (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) || \
+        IS_SKL_GT3(dev_priv) || \
+        IS_SKL_GT4(dev_priv))
 
 /*
  * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
index 21d0dea573127722f24dfb470ef51a889c38a171..6abd5e59037342ec4fc2fc2ececcb84b5beb4dd8 100644 (file)
@@ -508,7 +508,7 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj,
 
        *needs_clflush = 0;
 
-       if (WARN_ON((obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE) == 0))
+       if (WARN_ON(!i915_gem_object_has_struct_page(obj)))
                return -EINVAL;
 
        if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) {
@@ -760,7 +760,7 @@ i915_gem_shmem_pread(struct drm_device *dev,
        int needs_clflush = 0;
        struct sg_page_iter sg_iter;
 
-       if (!obj->base.filp)
+       if (!i915_gem_object_has_struct_page(obj))
                return -ENODEV;
 
        user_data = u64_to_user_ptr(args->data_ptr);
@@ -1298,7 +1298,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
         * pread/pwrite currently are reading and writing from the CPU
         * perspective, requiring manual detiling by the client.
         */
-       if (!obj->base.filp || cpu_write_needs_clflush(obj)) {
+       if (!i915_gem_object_has_struct_page(obj) ||
+           cpu_write_needs_clflush(obj)) {
                ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file);
                /* Note that the gtt paths might fail with non-page-backed user
                 * pointers (e.g. gtt mappings when moving data between
@@ -1308,7 +1309,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
        if (ret == -EFAULT) {
                if (obj->phys_handle)
                        ret = i915_gem_phys_pwrite(obj, args, file);
-               else if (obj->base.filp)
+               else if (i915_gem_object_has_struct_page(obj))
                        ret = i915_gem_shmem_pwrite(dev, obj, args, file);
                else
                        ret = -ENODEV;
@@ -1809,6 +1810,13 @@ static struct intel_rps_client *to_rps_client(struct drm_file *file)
        return &fpriv->rps;
 }
 
+static enum fb_op_origin
+write_origin(struct drm_i915_gem_object *obj, unsigned domain)
+{
+       return domain == I915_GEM_DOMAIN_GTT && !obj->has_wc_mmap ?
+              ORIGIN_GTT : ORIGIN_CPU;
+}
+
 /**
  * Called when user space prepares to use an object with the CPU, either
  * through the mmap ioctl's mapping or a GTT mapping.
@@ -1865,9 +1873,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
                ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
 
        if (write_domain != 0)
-               intel_fb_obj_invalidate(obj,
-                                       write_domain == I915_GEM_DOMAIN_GTT ?
-                                       ORIGIN_GTT : ORIGIN_CPU);
+               intel_fb_obj_invalidate(obj, write_origin(obj, write_domain));
 
 unref:
        drm_gem_object_unreference(&obj->base);
@@ -1974,6 +1980,9 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
                else
                        addr = -ENOMEM;
                up_write(&mm->mmap_sem);
+
+               /* This may race, but that's ok, it only gets set */
+               WRITE_ONCE(to_intel_bo(obj)->has_wc_mmap, true);
        }
        drm_gem_object_unreference_unlocked(obj);
        if (IS_ERR((void *)addr))
@@ -5528,7 +5537,7 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
        struct page *page;
 
        /* Only default objects have per-page dirty tracking */
-       if (WARN_ON((obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE) == 0))
+       if (WARN_ON(!i915_gem_object_has_struct_page(obj)))
                return NULL;
 
        page = i915_gem_object_get_page(obj, n);
index 22a55ac4e51c32d27e9c17a07b4303c85e656bc6..355b6475e74c22a268c5890ef0cb7eb51f7f0642 100644 (file)
@@ -153,12 +153,11 @@ static int host2guc_sample_forcewake(struct intel_guc *guc,
                                     struct i915_guc_client *client)
 {
        struct drm_i915_private *dev_priv = guc_to_i915(guc);
-       struct drm_device *dev = dev_priv->dev;
        u32 data[2];
 
        data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
        /* WaRsDisableCoarsePowerGating:skl,bxt */
-       if (!intel_enable_rc6() || NEEDS_WaRsDisableCoarsePowerGating(dev))
+       if (!intel_enable_rc6() || NEEDS_WaRsDisableCoarsePowerGating(dev_priv))
                data[1] = 0;
        else
                /* bit 0 and 1 are for Render and Media domain separately */
@@ -582,7 +581,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
  */
 int i915_guc_submit(struct drm_i915_gem_request *rq)
 {
-       unsigned int engine_id = rq->engine->guc_id;
+       unsigned int engine_id = rq->engine->id;
        struct intel_guc *guc = &rq->i915->guc;
        struct i915_guc_client *client = guc->execbuf_client;
        int b_ret;
index 7effe68d552c9798837e6c55f35a6faf013cc651..8b13bfa47fbaaf2be040bfcd6a420ef8aaca0e1b 100644 (file)
@@ -224,6 +224,6 @@ module_param_named(enable_dpcd_backlight, i915.enable_dpcd_backlight, bool, 0600
 MODULE_PARM_DESC(enable_dpcd_backlight,
        "Enable support for DPCD backlight control (default:false)");
 
-module_param_named(enable_gvt, i915.enable_gvt, bool, 0600);
+module_param_named(enable_gvt, i915.enable_gvt, bool, 0400);
 MODULE_PARM_DESC(enable_gvt,
        "Enable support for Intel GVT-g graphics virtualization host support(default:false)");
index 0b2cd669ac05e6a4e1b64a8f7a57f9fbfff4c471..1141b8699dbeeabc9848fa0df0d9967c0d8c941b 100644 (file)
@@ -14710,6 +14710,11 @@ static void intel_setup_outputs(struct drm_device *dev)
        struct intel_encoder *encoder;
        bool dpd_is_edp = false;
 
+       /*
+        * intel_edp_init_connector() depends on this completing first, to
+        * prevent the registeration of both eDP and LVDS and the incorrect
+        * sharing of the PPS.
+        */
        intel_lvds_init(dev);
 
        if (intel_crt_present(dev))
index 0b84f8e5df50160da2881457d0c0fe965b686ae8..85f2801b16ed8b875b42f1394d99d135758466db 100644 (file)
@@ -426,6 +426,37 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
        return intel_dp->pps_pipe;
 }
 
+static int
+bxt_power_sequencer_idx(struct intel_dp *intel_dp)
+{
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       lockdep_assert_held(&dev_priv->pps_mutex);
+
+       /* We should never land here with regular DP ports */
+       WARN_ON(!is_edp(intel_dp));
+
+       /*
+        * TODO: BXT has 2 PPS instances. The correct port->PPS instance
+        * mapping needs to be retrieved from VBT, for now just hard-code to
+        * use instance #0 always.
+        */
+       if (!intel_dp->pps_reset)
+               return 0;
+
+       intel_dp->pps_reset = false;
+
+       /*
+        * Only the HW needs to be reprogrammed, the SW state is fixed and
+        * has been setup during connector init.
+        */
+       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+
+       return 0;
+}
+
 typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
                               enum pipe pipe);
 
@@ -507,12 +538,13 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
        intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
 }
 
-void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
+void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
        struct intel_encoder *encoder;
 
-       if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)))
+       if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
+                   !IS_BROXTON(dev)))
                return;
 
        /*
@@ -532,34 +564,71 @@ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
                        continue;
 
                intel_dp = enc_to_intel_dp(&encoder->base);
-               intel_dp->pps_pipe = INVALID_PIPE;
+               if (IS_BROXTON(dev))
+                       intel_dp->pps_reset = true;
+               else
+                       intel_dp->pps_pipe = INVALID_PIPE;
+       }
+}
+
+struct pps_registers {
+       i915_reg_t pp_ctrl;
+       i915_reg_t pp_stat;
+       i915_reg_t pp_on;
+       i915_reg_t pp_off;
+       i915_reg_t pp_div;
+};
+
+static void intel_pps_get_registers(struct drm_i915_private *dev_priv,
+                                   struct intel_dp *intel_dp,
+                                   struct pps_registers *regs)
+{
+       memset(regs, 0, sizeof(*regs));
+
+       if (IS_BROXTON(dev_priv)) {
+               int idx = bxt_power_sequencer_idx(intel_dp);
+
+               regs->pp_ctrl = BXT_PP_CONTROL(idx);
+               regs->pp_stat = BXT_PP_STATUS(idx);
+               regs->pp_on = BXT_PP_ON_DELAYS(idx);
+               regs->pp_off = BXT_PP_OFF_DELAYS(idx);
+       } else if (HAS_PCH_SPLIT(dev_priv)) {
+               regs->pp_ctrl = PCH_PP_CONTROL;
+               regs->pp_stat = PCH_PP_STATUS;
+               regs->pp_on = PCH_PP_ON_DELAYS;
+               regs->pp_off = PCH_PP_OFF_DELAYS;
+               regs->pp_div = PCH_PP_DIVISOR;
+       } else {
+               enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+
+               regs->pp_ctrl = VLV_PIPE_PP_CONTROL(pipe);
+               regs->pp_stat = VLV_PIPE_PP_STATUS(pipe);
+               regs->pp_on = VLV_PIPE_PP_ON_DELAYS(pipe);
+               regs->pp_off = VLV_PIPE_PP_OFF_DELAYS(pipe);
+               regs->pp_div = VLV_PIPE_PP_DIVISOR(pipe);
        }
 }
 
 static i915_reg_t
 _pp_ctrl_reg(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       struct pps_registers regs;
 
-       if (IS_BROXTON(dev))
-               return BXT_PP_CONTROL(0);
-       else if (HAS_PCH_SPLIT(dev))
-               return PCH_PP_CONTROL;
-       else
-               return VLV_PIPE_PP_CONTROL(vlv_power_sequencer_pipe(intel_dp));
+       intel_pps_get_registers(to_i915(intel_dp_to_dev(intel_dp)), intel_dp,
+                               &regs);
+
+       return regs.pp_ctrl;
 }
 
 static i915_reg_t
 _pp_stat_reg(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       struct pps_registers regs;
 
-       if (IS_BROXTON(dev))
-               return BXT_PP_STATUS(0);
-       else if (HAS_PCH_SPLIT(dev))
-               return PCH_PP_STATUS;
-       else
-               return VLV_PIPE_PP_STATUS(vlv_power_sequencer_pipe(intel_dp));
+       intel_pps_get_registers(to_i915(intel_dp_to_dev(intel_dp)), intel_dp,
+                               &regs);
+
+       return regs.pp_stat;
 }
 
 /* Reboot notifier handler to shutdown panel power to guarantee T12 timing
@@ -1693,6 +1762,9 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
 #define IDLE_CYCLE_MASK                (PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
 #define IDLE_CYCLE_VALUE       (0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
 
+static void intel_pps_verify_state(struct drm_i915_private *dev_priv,
+                                  struct intel_dp *intel_dp);
+
 static void wait_panel_status(struct intel_dp *intel_dp,
                                       u32 mask,
                                       u32 value)
@@ -1703,6 +1775,8 @@ static void wait_panel_status(struct intel_dp *intel_dp,
 
        lockdep_assert_held(&dev_priv->pps_mutex);
 
+       intel_pps_verify_state(dev_priv, intel_dp);
+
        pp_stat_reg = _pp_stat_reg(intel_dp);
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
@@ -4544,13 +4618,15 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
 
 void intel_dp_encoder_reset(struct drm_encoder *encoder)
 {
-       struct intel_dp *intel_dp;
+       struct drm_i915_private *dev_priv = to_i915(encoder->dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+       if (!HAS_DDI(dev_priv))
+               intel_dp->DP = I915_READ(intel_dp->output_reg);
 
        if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
                return;
 
-       intel_dp = enc_to_intel_dp(encoder);
-
        pps_lock(intel_dp);
 
        /*
@@ -4622,9 +4698,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
        intel_display_power_get(dev_priv, power_domain);
 
        if (long_hpd) {
-               /* indicate that we need to restart link training */
-               intel_dp->train_set_valid = false;
-
                intel_dp_long_pulse(intel_dp->attached_connector);
                if (intel_dp->is_mst)
                        ret = IRQ_HANDLED;
@@ -4707,82 +4780,93 @@ static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
 }
 
 static void
-intel_dp_init_panel_power_sequencer(struct drm_device *dev,
-                                   struct intel_dp *intel_dp)
+intel_pps_readout_hw_state(struct drm_i915_private *dev_priv,
+                          struct intel_dp *intel_dp, struct edp_power_seq *seq)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct edp_power_seq cur, vbt, spec,
-               *final = &intel_dp->pps_delays;
        u32 pp_on, pp_off, pp_div = 0, pp_ctl = 0;
-       i915_reg_t pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
-
-       lockdep_assert_held(&dev_priv->pps_mutex);
-
-       /* already initialized? */
-       if (final->t11_t12 != 0)
-               return;
+       struct pps_registers regs;
 
-       if (IS_BROXTON(dev)) {
-               /*
-                * TODO: BXT has 2 sets of PPS registers.
-                * Correct Register for Broxton need to be identified
-                * using VBT. hardcoding for now
-                */
-               pp_ctrl_reg = BXT_PP_CONTROL(0);
-               pp_on_reg = BXT_PP_ON_DELAYS(0);
-               pp_off_reg = BXT_PP_OFF_DELAYS(0);
-       } else if (HAS_PCH_SPLIT(dev)) {
-               pp_ctrl_reg = PCH_PP_CONTROL;
-               pp_on_reg = PCH_PP_ON_DELAYS;
-               pp_off_reg = PCH_PP_OFF_DELAYS;
-               pp_div_reg = PCH_PP_DIVISOR;
-       } else {
-               enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-
-               pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
-               pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
-               pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe);
-               pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
-       }
+       intel_pps_get_registers(dev_priv, intel_dp, &regs);
 
        /* Workaround: Need to write PP_CONTROL with the unlock key as
         * the very first thing. */
        pp_ctl = ironlake_get_pp_control(intel_dp);
 
-       pp_on = I915_READ(pp_on_reg);
-       pp_off = I915_READ(pp_off_reg);
-       if (!IS_BROXTON(dev)) {
-               I915_WRITE(pp_ctrl_reg, pp_ctl);
-               pp_div = I915_READ(pp_div_reg);
+       pp_on = I915_READ(regs.pp_on);
+       pp_off = I915_READ(regs.pp_off);
+       if (!IS_BROXTON(dev_priv)) {
+               I915_WRITE(regs.pp_ctrl, pp_ctl);
+               pp_div = I915_READ(regs.pp_div);
        }
 
        /* Pull timing values out of registers */
-       cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
-               PANEL_POWER_UP_DELAY_SHIFT;
+       seq->t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
+                    PANEL_POWER_UP_DELAY_SHIFT;
 
-       cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
-               PANEL_LIGHT_ON_DELAY_SHIFT;
+       seq->t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
+                 PANEL_LIGHT_ON_DELAY_SHIFT;
 
-       cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
-               PANEL_LIGHT_OFF_DELAY_SHIFT;
+       seq->t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
+                 PANEL_LIGHT_OFF_DELAY_SHIFT;
 
-       cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
-               PANEL_POWER_DOWN_DELAY_SHIFT;
+       seq->t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
+                  PANEL_POWER_DOWN_DELAY_SHIFT;
 
-       if (IS_BROXTON(dev)) {
+       if (IS_BROXTON(dev_priv)) {
                u16 tmp = (pp_ctl & BXT_POWER_CYCLE_DELAY_MASK) >>
                        BXT_POWER_CYCLE_DELAY_SHIFT;
                if (tmp > 0)
-                       cur.t11_t12 = (tmp - 1) * 1000;
+                       seq->t11_t12 = (tmp - 1) * 1000;
                else
-                       cur.t11_t12 = 0;
+                       seq->t11_t12 = 0;
        } else {
-               cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
+               seq->t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
                       PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
        }
+}
+
+static void
+intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq)
+{
+       DRM_DEBUG_KMS("%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+                     state_name,
+                     seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
+}
+
+static void
+intel_pps_verify_state(struct drm_i915_private *dev_priv,
+                      struct intel_dp *intel_dp)
+{
+       struct edp_power_seq hw;
+       struct edp_power_seq *sw = &intel_dp->pps_delays;
 
-       DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
-                     cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+       intel_pps_readout_hw_state(dev_priv, intel_dp, &hw);
+
+       if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
+           hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
+               DRM_ERROR("PPS state mismatch\n");
+               intel_pps_dump_state("sw", sw);
+               intel_pps_dump_state("hw", &hw);
+       }
+}
+
+static void
+intel_dp_init_panel_power_sequencer(struct drm_device *dev,
+                                   struct intel_dp *intel_dp)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct edp_power_seq cur, vbt, spec,
+               *final = &intel_dp->pps_delays;
+
+       lockdep_assert_held(&dev_priv->pps_mutex);
+
+       /* already initialized? */
+       if (final->t11_t12 != 0)
+               return;
+
+       intel_pps_readout_hw_state(dev_priv, intel_dp, &cur);
+
+       intel_pps_dump_state("cur", &cur);
 
        vbt = dev_priv->vbt.edp.pps;
 
@@ -4798,8 +4882,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
         * too. */
        spec.t11_t12 = (510 + 100) * 10;
 
-       DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
-                     vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);
+       intel_pps_dump_state("vbt", &vbt);
 
        /* Use the max of the register settings and vbt. If both are
         * unset, fall back to the spec limits. */
@@ -4827,6 +4910,16 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 
        DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
                      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+
+       /*
+        * We override the HW backlight delays to 1 because we do manual waits
+        * on them. For T8, even BSpec recommends doing it. For T9, if we
+        * don't do this, we'll end up waiting for the backlight off delay
+        * twice: once when we do the manual sleep, and once when we disable
+        * the panel and wait for the PP_STATUS bit to become zero.
+        */
+       final->t8 = 1;
+       final->t9 = 1;
 }
 
 static void
@@ -4836,50 +4929,22 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp_on, pp_off, pp_div, port_sel = 0;
        int div = dev_priv->rawclk_freq / 1000;
-       i915_reg_t pp_on_reg, pp_off_reg, pp_div_reg, pp_ctrl_reg;
+       struct pps_registers regs;
        enum port port = dp_to_dig_port(intel_dp)->port;
        const struct edp_power_seq *seq = &intel_dp->pps_delays;
 
        lockdep_assert_held(&dev_priv->pps_mutex);
 
-       if (IS_BROXTON(dev)) {
-               /*
-                * TODO: BXT has 2 sets of PPS registers.
-                * Correct Register for Broxton need to be identified
-                * using VBT. hardcoding for now
-                */
-               pp_ctrl_reg = BXT_PP_CONTROL(0);
-               pp_on_reg = BXT_PP_ON_DELAYS(0);
-               pp_off_reg = BXT_PP_OFF_DELAYS(0);
-
-       } else if (HAS_PCH_SPLIT(dev)) {
-               pp_on_reg = PCH_PP_ON_DELAYS;
-               pp_off_reg = PCH_PP_OFF_DELAYS;
-               pp_div_reg = PCH_PP_DIVISOR;
-       } else {
-               enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-
-               pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
-               pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe);
-               pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
-       }
+       intel_pps_get_registers(dev_priv, intel_dp, &regs);
 
-       /*
-        * And finally store the new values in the power sequencer. The
-        * backlight delays are set to 1 because we do manual waits on them. For
-        * T8, even BSpec recommends doing it. For T9, if we don't do this,
-        * we'll end up waiting for the backlight off delay twice: once when we
-        * do the manual sleep, and once when we disable the panel and wait for
-        * the PP_STATUS bit to become zero.
-        */
        pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
-               (1 << PANEL_LIGHT_ON_DELAY_SHIFT);
-       pp_off = (1 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
+               (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
+       pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
                 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
        /* Compute the divisor for the pp clock, simply match the Bspec
         * formula. */
        if (IS_BROXTON(dev)) {
-               pp_div = I915_READ(pp_ctrl_reg);
+               pp_div = I915_READ(regs.pp_ctrl);
                pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK;
                pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000)
                                << BXT_POWER_CYCLE_DELAY_SHIFT);
@@ -4902,19 +4967,19 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 
        pp_on |= port_sel;
 
-       I915_WRITE(pp_on_reg, pp_on);
-       I915_WRITE(pp_off_reg, pp_off);
+       I915_WRITE(regs.pp_on, pp_on);
+       I915_WRITE(regs.pp_off, pp_off);
        if (IS_BROXTON(dev))
-               I915_WRITE(pp_ctrl_reg, pp_div);
+               I915_WRITE(regs.pp_ctrl, pp_div);
        else
-               I915_WRITE(pp_div_reg, pp_div);
+               I915_WRITE(regs.pp_div, pp_div);
 
        DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
-                     I915_READ(pp_on_reg),
-                     I915_READ(pp_off_reg),
+                     I915_READ(regs.pp_on),
+                     I915_READ(regs.pp_off),
                      IS_BROXTON(dev) ?
-                     (I915_READ(pp_ctrl_reg) & BXT_POWER_CYCLE_DELAY_MASK) :
-                     I915_READ(pp_div_reg));
+                     (I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK) :
+                     I915_READ(regs.pp_div));
 }
 
 /**
@@ -5317,8 +5382,32 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        if (!is_edp(intel_dp))
                return true;
 
+       /*
+        * On IBX/CPT we may get here with LVDS already registered. Since the
+        * driver uses the only internal power sequencer available for both
+        * eDP and LVDS bail out early in this case to prevent interfering
+        * with an already powered-on LVDS power sequencer.
+        */
+       if (intel_get_lvds_encoder(dev)) {
+               WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
+               DRM_INFO("LVDS was detected, not registering eDP\n");
+
+               return false;
+       }
+
        pps_lock(intel_dp);
+
+       intel_dp_init_panel_power_timestamps(intel_dp);
+
+       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+               vlv_initial_power_sequencer_setup(intel_dp);
+       } else {
+               intel_dp_init_panel_power_sequencer(dev, intel_dp);
+               intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+       }
+
        intel_edp_panel_vdd_sanitize(intel_dp);
+
        pps_unlock(intel_dp);
 
        /* Cache DPCD and EDID for edp. */
@@ -5332,14 +5421,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        } else {
                /* if this fails, presume the device is a ghost */
                DRM_INFO("failed to retrieve link info, disabling eDP\n");
-               return false;
+               goto out_vdd_off;
        }
 
-       /* We now know it's not a ghost, init power sequence regs. */
-       pps_lock(intel_dp);
-       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
-       pps_unlock(intel_dp);
-
        mutex_lock(&dev->mode_config.mutex);
        edid = drm_get_edid(connector, &intel_dp->aux.ddc);
        if (edid) {
@@ -5407,6 +5491,18 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        intel_panel_setup_backlight(connector, pipe);
 
        return true;
+
+out_vdd_off:
+       cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+       /*
+        * vdd might still be enabled do to the delayed vdd off.
+        * Make sure vdd is actually turned off here.
+        */
+       pps_lock(intel_dp);
+       edp_panel_vdd_off_sync(intel_dp);
+       pps_unlock(intel_dp);
+
+       return false;
 }
 
 bool
@@ -5512,16 +5608,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                BUG();
        }
 
-       if (is_edp(intel_dp)) {
-               pps_lock(intel_dp);
-               intel_dp_init_panel_power_timestamps(intel_dp);
-               if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
-                       vlv_initial_power_sequencer_setup(intel_dp);
-               else
-                       intel_dp_init_panel_power_sequencer(dev, intel_dp);
-               pps_unlock(intel_dp);
-       }
-
        ret = intel_dp_aux_init(intel_dp, intel_connector);
        if (ret)
                goto fail;
@@ -5554,16 +5640,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        return true;
 
 fail:
-       if (is_edp(intel_dp)) {
-               cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-               /*
-                * vdd might still be enabled do to the delayed vdd off.
-                * Make sure vdd is actually turned off here.
-                */
-               pps_lock(intel_dp);
-               edp_panel_vdd_off_sync(intel_dp);
-               pps_unlock(intel_dp);
-       }
        drm_connector_unregister(connector);
        drm_connector_cleanup(connector);
 
index 0b8eefc2acc5d93088b960e4714bce55944df82e..60fb39cd220b4a01f5b9469a5de29ee496abe61f 100644 (file)
@@ -85,8 +85,7 @@ static bool
 intel_dp_reset_link_train(struct intel_dp *intel_dp,
                        uint8_t dp_train_pat)
 {
-       if (!intel_dp->train_set_valid)
-               memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
+       memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
        intel_dp_set_signal_levels(intel_dp);
        return intel_dp_set_link_train(intel_dp, dp_train_pat);
 }
@@ -161,23 +160,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
                        break;
                }
 
-               /*
-                * if we used previously trained voltage and pre-emphasis values
-                * and we don't get clock recovery, reset link training values
-                */
-               if (intel_dp->train_set_valid) {
-                       DRM_DEBUG_KMS("clock recovery not ok, reset");
-                       /* clear the flag as we are not reusing train set */
-                       intel_dp->train_set_valid = false;
-                       if (!intel_dp_reset_link_train(intel_dp,
-                                                      DP_TRAINING_PATTERN_1 |
-                                                      DP_LINK_SCRAMBLING_DISABLE)) {
-                               DRM_ERROR("failed to enable link training\n");
-                               return;
-                       }
-                       continue;
-               }
-
                /* Check to see if we've tried the max voltage */
                for (i = 0; i < intel_dp->lane_count; i++)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
@@ -284,7 +266,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
                /* Make sure clock is still ok */
                if (!drm_dp_clock_recovery_ok(link_status,
                                              intel_dp->lane_count)) {
-                       intel_dp->train_set_valid = false;
                        intel_dp_link_training_clock_recovery(intel_dp);
                        intel_dp_set_link_train(intel_dp,
                                                training_pattern |
@@ -301,7 +282,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 
                /* Try 5 times, then try clock recovery if that fails */
                if (tries > 5) {
-                       intel_dp->train_set_valid = false;
                        intel_dp_link_training_clock_recovery(intel_dp);
                        intel_dp_set_link_train(intel_dp,
                                                training_pattern |
@@ -322,10 +302,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 
        intel_dp_set_idle_link_train(intel_dp);
 
-       if (channel_eq) {
-               intel_dp->train_set_valid = true;
+       if (channel_eq)
                DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
-       }
 }
 
 void intel_dp_stop_link_train(struct intel_dp *intel_dp)
index 7d0e071fe3553cf185e42c846c1181d4a13cd0ee..1f82dccfcd58c17b6aaddb295c5890ef247c059d 100644 (file)
@@ -159,6 +159,7 @@ struct intel_framebuffer {
 struct intel_fbdev {
        struct drm_fb_helper helper;
        struct intel_framebuffer *fb;
+       async_cookie_t cookie;
        int preferred_bpp;
 };
 
@@ -861,6 +862,11 @@ struct intel_dp {
         * this port. Only relevant on VLV/CHV.
         */
        enum pipe pps_pipe;
+       /*
+        * Set if the sequencer may be reset due to a power transition,
+        * requiring a reinitialization. Only relevant on BXT.
+        */
+       bool pps_reset;
        struct edp_power_seq pps_delays;
 
        bool can_mst; /* this port supports mst */
@@ -886,8 +892,6 @@ struct intel_dp {
        /* This is called before a link training is starterd */
        void (*prepare_link_retrain)(struct intel_dp *intel_dp);
 
-       bool train_set_valid;
-
        /* Displayport compliance testing */
        unsigned long compliance_test_type;
        unsigned long compliance_test_data;
@@ -1340,7 +1344,7 @@ void intel_dp_mst_resume(struct drm_device *dev);
 int intel_dp_max_link_rate(struct intel_dp *intel_dp);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
 void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
-void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
+void intel_power_sequencer_reset(struct drm_i915_private *dev_priv);
 uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
 void intel_plane_destroy(struct drm_plane *plane);
 void intel_edp_drrs_enable(struct intel_dp *intel_dp);
@@ -1453,6 +1457,7 @@ void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
 
 /* intel_lvds.c */
 void intel_lvds_init(struct drm_device *dev);
+struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev);
 bool intel_is_dual_link_lvds(struct drm_device *dev);
 
 
index ecabd59ffbaf2b67df06832e945801fdc7385ebb..97110533dcaa49b5668714f946d586f318c73a24 100644 (file)
@@ -818,21 +818,14 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
        struct intel_fbc *fbc = &dev_priv->fbc;
-       bool enable_by_default = IS_HASWELL(dev_priv) ||
-                                IS_BROADWELL(dev_priv);
 
        if (intel_vgpu_active(dev_priv)) {
                fbc->no_fbc_reason = "VGPU is active";
                return false;
        }
 
-       if (i915.enable_fbc < 0 && !enable_by_default) {
-               fbc->no_fbc_reason = "disabled per chip default";
-               return false;
-       }
-
        if (!i915.enable_fbc) {
-               fbc->no_fbc_reason = "disabled per module param";
+               fbc->no_fbc_reason = "disabled per module param or by default";
                return false;
        }
 
@@ -993,13 +986,13 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
        if (!fbc_supported(dev_priv))
                return;
 
-       if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP)
-               return;
-
        mutex_lock(&fbc->lock);
 
        fbc->busy_bits &= ~frontbuffer_bits;
 
+       if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP)
+               goto out;
+
        if (!fbc->busy_bits && fbc->enabled &&
            (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) {
                if (fbc->active)
@@ -1008,6 +1001,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
                        __intel_fbc_post_update(fbc->crtc);
        }
 
+out:
        mutex_unlock(&fbc->lock);
 }
 
@@ -1220,6 +1214,26 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv)
                        dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
 }
 
+/*
+ * The DDX driver changes its behavior depending on the value it reads from
+ * i915.enable_fbc, so sanitize it by translating the default value into either
+ * 0 or 1 in order to allow it to know what's going on.
+ *
+ * Notice that this is done at driver initialization and we still allow user
+ * space to change the value during runtime without sanitizing it again. IGT
+ * relies on being able to change i915.enable_fbc at runtime.
+ */
+static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
+{
+       if (i915.enable_fbc >= 0)
+               return !!i915.enable_fbc;
+
+       if (IS_BROADWELL(dev_priv))
+               return 1;
+
+       return 0;
+}
+
 /**
  * intel_fbc_init - Initialize FBC
  * @dev_priv: the i915 device
@@ -1237,6 +1251,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
        fbc->active = false;
        fbc->work.scheduled = false;
 
+       i915.enable_fbc = intel_sanitize_fbc_option(dev_priv);
+       DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", i915.enable_fbc);
+
        if (!HAS_FBC(dev_priv)) {
                fbc->no_fbc_reason = "unsupported by this chipset";
                return;
index 4babefc51eb2da6a29b528edc07fd0a37c2ffa28..16d73eaa46fb95809a1ff27af202cbff51a307a1 100644 (file)
@@ -538,8 +538,7 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
        .fb_probe = intelfb_create,
 };
 
-static void intel_fbdev_destroy(struct drm_device *dev,
-                               struct intel_fbdev *ifbdev)
+static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
 {
        /* We rely on the object-free to release the VMA pinning for
         * the info->screen_base mmaping. Leaking the VMA is simpler than
@@ -552,12 +551,14 @@ static void intel_fbdev_destroy(struct drm_device *dev,
        drm_fb_helper_fini(&ifbdev->helper);
 
        if (ifbdev->fb) {
-               mutex_lock(&dev->struct_mutex);
+               mutex_lock(&ifbdev->helper.dev->struct_mutex);
                intel_unpin_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
-               mutex_unlock(&dev->struct_mutex);
+               mutex_unlock(&ifbdev->helper.dev->struct_mutex);
 
                drm_framebuffer_remove(&ifbdev->fb->base);
        }
+
+       kfree(ifbdev);
 }
 
 /*
@@ -732,32 +733,44 @@ int intel_fbdev_init(struct drm_device *dev)
 
 static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
 {
-       struct drm_i915_private *dev_priv = data;
-       struct intel_fbdev *ifbdev = dev_priv->fbdev;
+       struct intel_fbdev *ifbdev = data;
 
        /* Due to peculiar init order wrt to hpd handling this is separate. */
        if (drm_fb_helper_initial_config(&ifbdev->helper,
                                         ifbdev->preferred_bpp))
-               intel_fbdev_fini(dev_priv->dev);
+               intel_fbdev_fini(ifbdev->helper.dev);
 }
 
 void intel_fbdev_initial_config_async(struct drm_device *dev)
 {
-       async_schedule(intel_fbdev_initial_config, to_i915(dev));
+       struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
+
+       ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
+}
+
+static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
+{
+       if (!ifbdev->cookie)
+               return;
+
+       /* Only serialises with all preceding async calls, hence +1 */
+       async_synchronize_cookie(ifbdev->cookie + 1);
+       ifbdev->cookie = 0;
 }
 
 void intel_fbdev_fini(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       if (!dev_priv->fbdev)
+       struct intel_fbdev *ifbdev = dev_priv->fbdev;
+
+       if (!ifbdev)
                return;
 
        flush_work(&dev_priv->fbdev_suspend_work);
-
        if (!current_is_async())
-               async_synchronize_full();
-       intel_fbdev_destroy(dev, dev_priv->fbdev);
-       kfree(dev_priv->fbdev);
+               intel_fbdev_sync(ifbdev);
+
+       intel_fbdev_destroy(ifbdev);
        dev_priv->fbdev = NULL;
 }
 
@@ -827,6 +840,8 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
        if (!ifbdev)
                return;
 
+       intel_fbdev_sync(ifbdev);
+
        fb_helper = &ifbdev->helper;
 
        ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
index 4df80cc9a29168fea10cc79e3531e80efd2ab9f5..3e3e743740c01a2651850836f4fee970ea294b42 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "intel_guc_fwif.h"
 #include "i915_guc_reg.h"
+#include "intel_ringbuffer.h"
 
 struct drm_i915_gem_request;
 
@@ -86,7 +87,7 @@ struct i915_guc_client {
        int retcode;
 
        /* Per-engine counts of GuC submissions */
-       uint64_t submissions[GUC_MAX_ENGINES_NUM];
+       uint64_t submissions[I915_NUM_ENGINES];
 };
 
 enum intel_guc_fw_status {
@@ -143,8 +144,8 @@ struct intel_guc {
        uint32_t action_fail;           /* Total number of failures     */
        int32_t action_err;             /* Last error code              */
 
-       uint64_t submissions[GUC_MAX_ENGINES_NUM];
-       uint32_t last_seqno[GUC_MAX_ENGINES_NUM];
+       uint64_t submissions[I915_NUM_ENGINES];
+       uint32_t last_seqno[I915_NUM_ENGINES];
 };
 
 /* intel_guc_loader.c */
index 9fa458ce40a6aabf3fe7097a306fd4db807d3e97..434f4d5c553ddf6d263a5af78e491b94ce1cfce3 100644 (file)
@@ -63,7 +63,7 @@ int intel_gvt_init(struct drm_i915_private *dev_priv)
 
        if (!is_supported_device(dev_priv)) {
                DRM_DEBUG_DRIVER("Unsupported device. GVT-g is disabled\n");
-               return 0;
+               goto bail;
        }
 
        /*
@@ -72,16 +72,20 @@ int intel_gvt_init(struct drm_i915_private *dev_priv)
        ret = intel_gvt_init_host();
        if (ret) {
                DRM_DEBUG_DRIVER("Not in host or MPT modules not found\n");
-               return 0;
+               goto bail;
        }
 
        ret = intel_gvt_init_device(dev_priv);
        if (ret) {
                DRM_DEBUG_DRIVER("Fail to init GVT device\n");
-               return 0;
+               goto bail;
        }
 
        return 0;
+
+bail:
+       i915.enable_gvt = 0;
+       return 0;
 }
 
 /**
index e9082185a375ff0a0627529b49b75c29ff5e9a0f..935b53642948421de4900427001a7c0a542318e2 100644 (file)
@@ -810,20 +810,22 @@ static const struct dmi_system_id intel_dual_link_lvds[] = {
        { }     /* terminating entry */
 };
 
-bool intel_is_dual_link_lvds(struct drm_device *dev)
+struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev)
 {
-       struct intel_encoder *encoder;
-       struct intel_lvds_encoder *lvds_encoder;
+       struct intel_encoder *intel_encoder;
 
-       for_each_intel_encoder(dev, encoder) {
-               if (encoder->type == INTEL_OUTPUT_LVDS) {
-                       lvds_encoder = to_lvds_encoder(&encoder->base);
+       for_each_intel_encoder(dev, intel_encoder)
+               if (intel_encoder->type == INTEL_OUTPUT_LVDS)
+                       return intel_encoder;
 
-                       return lvds_encoder->is_dual_link;
-               }
-       }
+       return NULL;
+}
 
-       return false;
+bool intel_is_dual_link_lvds(struct drm_device *dev)
+{
+       struct intel_encoder *encoder = intel_get_lvds_encoder(dev);
+
+       return encoder && to_lvds_encoder(&encoder->base)->is_dual_link;
 }
 
 static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
index 658a756596574ffc176a8d151c04bd0ed4bc6228..c94521cc476c94abe5f7cb1a1399ce9f210c5a37 100644 (file)
@@ -4844,6 +4844,12 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv)
                        gen6_rps_reset_ei(dev_priv);
                I915_WRITE(GEN6_PMINTRMSK,
                           gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
+
+               /* Ensure we start at the user's desired frequency */
+               intel_set_rps(dev_priv,
+                             clamp(dev_priv->rps.cur_freq,
+                                   dev_priv->rps.min_freq_softlimit,
+                                   dev_priv->rps.max_freq_softlimit));
        }
        mutex_unlock(&dev_priv->rps.hw_lock);
 }
index e856d49d6dc3304a0c3f5feeb9796c37f575ea09..22b46f5f027369136de3f2604e0095b0b2bb0a39 100644 (file)
@@ -578,6 +578,7 @@ void bxt_enable_dc9(struct drm_i915_private *dev_priv)
 
        DRM_DEBUG_KMS("Enabling DC9\n");
 
+       intel_power_sequencer_reset(dev_priv);
        gen9_set_dc_state(dev_priv, DC_STATE_EN_DC9);
 }
 
@@ -1112,7 +1113,7 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
        /* make sure we're done processing display irqs */
        synchronize_irq(dev_priv->dev->irq);
 
-       vlv_power_sequencer_reset(dev_priv);
+       intel_power_sequencer_reset(dev_priv);
 }
 
 static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,