drm/i915: don't always do full mode sets when infoframes are enabled
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 32cec9d208d410448e843c26fc2c7705c3c13c85..03d0b0cb8e05f0a3598ff7ae088b43f17d7dfe63 100644 (file)
@@ -2765,25 +2765,10 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        return 0;
 }
 
-void intel_display_handle_reset(struct drm_device *dev)
+static void intel_complete_page_flips(struct drm_device *dev)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
 
-       /*
-        * Flips in the rings have been nuked by the reset,
-        * so complete all pending flips so that user space
-        * will get its events and not get stuck.
-        *
-        * Also update the base address of all primary
-        * planes to the the last fb to make sure we're
-        * showing the correct fb after a reset.
-        *
-        * Need to make two loops over the crtcs so that we
-        * don't try to grab a crtc mutex before the
-        * pending_flip_queue really got woken up.
-        */
-
        for_each_crtc(dev, crtc) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
                enum plane plane = intel_crtc->plane;
@@ -2791,6 +2776,12 @@ void intel_display_handle_reset(struct drm_device *dev)
                intel_prepare_page_flip(dev, plane);
                intel_finish_page_flip_plane(dev, plane);
        }
+}
+
+static void intel_update_primary_planes(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
 
        for_each_crtc(dev, crtc) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -2810,6 +2801,79 @@ void intel_display_handle_reset(struct drm_device *dev)
        }
 }
 
+void intel_prepare_reset(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct intel_crtc *crtc;
+
+       /* no reset support for gen2 */
+       if (IS_GEN2(dev))
+               return;
+
+       /* reset doesn't touch the display */
+       if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
+               return;
+
+       drm_modeset_lock_all(dev);
+
+       /*
+        * Disabling the crtcs gracefully seems nicer. Also the
+        * g33 docs say we should at least disable all the planes.
+        */
+       for_each_intel_crtc(dev, crtc) {
+               if (crtc->active)
+                       dev_priv->display.crtc_disable(&crtc->base);
+       }
+}
+
+void intel_finish_reset(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+
+       /*
+        * Flips in the rings will be nuked by the reset,
+        * so complete all pending flips so that user space
+        * will get its events and not get stuck.
+        */
+       intel_complete_page_flips(dev);
+
+       /* no reset support for gen2 */
+       if (IS_GEN2(dev))
+               return;
+
+       /* reset doesn't touch the display */
+       if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
+               /*
+                * Flips in the rings have been nuked by the reset,
+                * so update the base address of all primary
+                * planes to the the last fb to make sure we're
+                * showing the correct fb after a reset.
+                */
+               intel_update_primary_planes(dev);
+               return;
+       }
+
+       /*
+        * The display has been reset as well,
+        * so need a full re-initialization.
+        */
+       intel_runtime_pm_disable_interrupts(dev_priv);
+       intel_runtime_pm_enable_interrupts(dev_priv);
+
+       intel_modeset_init_hw(dev);
+
+       spin_lock_irq(&dev_priv->irq_lock);
+       if (dev_priv->display.hpd_irq_setup)
+               dev_priv->display.hpd_irq_setup(dev);
+       spin_unlock_irq(&dev_priv->irq_lock);
+
+       intel_modeset_setup_hw_state(dev, true);
+
+       intel_hpd_init(dev_priv);
+
+       drm_modeset_unlock_all(dev);
+}
+
 static int
 intel_finish_fb(struct drm_framebuffer *old_fb)
 {
@@ -4758,7 +4822,7 @@ static void vlv_update_cdclk(struct drm_device *dev)
         * BSpec erroneously claims we should aim for 4MHz, but
         * in fact 1MHz is the correct frequency.
         */
-       I915_WRITE(GMBUSFREQ_VLV, dev_priv->vlv_cdclk_freq);
+       I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->vlv_cdclk_freq, 1000));
 }
 
 /* Adjust CDclk dividers to allow high res or save power if possible */
@@ -4939,10 +5003,23 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
        int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
 
        if (req_cdclk != dev_priv->vlv_cdclk_freq) {
+               /*
+                * FIXME: We can end up here with all power domains off, yet
+                * with a CDCLK frequency other than the minimum. To account
+                * for this take the PIPE-A power domain, which covers the HW
+                * blocks needed for the following programming. This can be
+                * removed once it's guaranteed that we get here either with
+                * the minimum CDCLK set, or the required power domains
+                * enabled.
+                */
+               intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
+
                if (IS_CHERRYVIEW(dev))
                        cherryview_set_cdclk(dev, req_cdclk);
                else
                        valleyview_set_cdclk(dev, req_cdclk);
+
+               intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
        }
 }
 
@@ -5185,36 +5262,6 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
 {
 }
 
-static void intel_crtc_update_sarea(struct drm_crtc *crtc,
-                                   bool enabled)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_master_private *master_priv;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-
-       if (!dev->primary->master)
-               return;
-
-       master_priv = dev->primary->master->driver_priv;
-       if (!master_priv->sarea_priv)
-               return;
-
-       switch (pipe) {
-       case 0:
-               master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
-               master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0;
-               break;
-       case 1:
-               master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0;
-               master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0;
-               break;
-       default:
-               DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe));
-               break;
-       }
-}
-
 /* Master function to enable/disable CRTC and corresponding power wells */
 void intel_crtc_control(struct drm_crtc *crtc, bool enable)
 {
@@ -5258,8 +5305,6 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc)
                enable |= intel_encoder->connectors_active;
 
        intel_crtc_control(crtc, enable);
-
-       intel_crtc_update_sarea(crtc, enable);
 }
 
 static void intel_crtc_disable(struct drm_crtc *crtc)
@@ -5274,7 +5319,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
        WARN_ON(!crtc->enabled);
 
        dev_priv->display.crtc_disable(crtc);
-       intel_crtc_update_sarea(crtc, false);
        dev_priv->display.off(crtc);
 
        if (crtc->primary->fb) {
@@ -8369,7 +8413,7 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
                                     uint32_t width, uint32_t height)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum pipe pipe = intel_crtc->pipe;
        unsigned old_width;
@@ -8639,6 +8683,9 @@ retry:
                crtc = encoder->crtc;
 
                ret = drm_modeset_lock(&crtc->mutex, ctx);
+               if (ret)
+                       goto fail_unlock;
+               ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
                if (ret)
                        goto fail_unlock;
 
@@ -8676,6 +8723,9 @@ retry:
        }
 
        ret = drm_modeset_lock(&crtc->mutex, ctx);
+       if (ret)
+               goto fail_unlock;
+       ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
        if (ret)
                goto fail_unlock;
        intel_encoder->new_crtc = to_intel_crtc(crtc);
@@ -9137,6 +9187,10 @@ static bool page_flip_finished(struct intel_crtc *crtc)
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       if (i915_reset_in_progress(&dev_priv->gpu_error) ||
+           crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
+               return true;
+
        /*
         * The relevant registers doen't exist on pre-ctg.
         * As the flip done interrupt doesn't trigger for mmio
@@ -10034,6 +10088,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                      pipe_config->dp_m2_n2.link_n,
                      pipe_config->dp_m2_n2.tu);
 
+       DRM_DEBUG_KMS("audio: %i, infoframes: %i\n",
+                     pipe_config->has_audio,
+                     pipe_config->has_infoframe);
+
        DRM_DEBUG_KMS("requested mode:\n");
        drm_mode_debug_printmodeline(&pipe_config->requested_mode);
        DRM_DEBUG_KMS("adjusted mode:\n");
@@ -10095,6 +10153,48 @@ static bool check_encoder_cloning(struct intel_crtc *crtc)
        return true;
 }
 
+static bool check_digital_port_conflicts(struct drm_device *dev)
+{
+       struct intel_connector *connector;
+       unsigned int used_ports = 0;
+
+       /*
+        * Walk the connector list instead of the encoder
+        * list to detect the problem on ddi platforms
+        * where there's just one encoder per digital port.
+        */
+       list_for_each_entry(connector,
+                           &dev->mode_config.connector_list, base.head) {
+               struct intel_encoder *encoder = connector->new_encoder;
+
+               if (!encoder)
+                       continue;
+
+               WARN_ON(!encoder->new_crtc);
+
+               switch (encoder->type) {
+                       unsigned int port_mask;
+               case INTEL_OUTPUT_UNKNOWN:
+                       if (WARN_ON(!HAS_DDI(dev)))
+                               break;
+               case INTEL_OUTPUT_DISPLAYPORT:
+               case INTEL_OUTPUT_HDMI:
+               case INTEL_OUTPUT_EDP:
+                       port_mask = 1 << enc_to_dig_port(&encoder->base)->port;
+
+                       /* the same port mustn't appear more than once */
+                       if (used_ports & port_mask)
+                               return false;
+
+                       used_ports |= port_mask;
+               default:
+                       break;
+               }
+       }
+
+       return true;
+}
+
 static struct intel_crtc_config *
 intel_modeset_pipe_config(struct drm_crtc *crtc,
                          struct drm_framebuffer *fb,
@@ -10111,6 +10211,11 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
                return ERR_PTR(-EINVAL);
        }
 
+       if (!check_digital_port_conflicts(dev)) {
+               DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
+               return ERR_PTR(-EINVAL);
+       }
+
        pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
        if (!pipe_config)
                return ERR_PTR(-ENOMEM);
@@ -10913,7 +11018,6 @@ intel_modeset_compute_config(struct drm_crtc *crtc,
        }
        intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
                               "[modeset]");
-       to_intel_crtc(crtc)->new_config = pipe_config;
 
 out:
        return pipe_config;
@@ -10939,6 +11043,9 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 
        *saved_mode = crtc->mode;
 
+       if (modeset_pipes)
+               to_intel_crtc(crtc)->new_config = pipe_config;
+
        /*
         * See if the config requires any additional preparation, e.g.
         * to adjust global state with pipes off.  We need to do this
@@ -11472,14 +11579,16 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
                ret = PTR_ERR(pipe_config);
                goto fail;
        } else if (pipe_config) {
-               if (to_intel_crtc(set->crtc)->new_config->has_audio !=
+               if (pipe_config->has_audio !=
                    to_intel_crtc(set->crtc)->config.has_audio)
                        config->mode_changed = true;
 
-               /* Force mode sets for any infoframe stuff */
-               if (to_intel_crtc(set->crtc)->new_config->has_infoframe ||
-                   to_intel_crtc(set->crtc)->config.has_infoframe)
-                       config->mode_changed = true;
+               /*
+                * Note we have an issue here with infoframes: current code
+                * only updates them on the full mode set path per hw
+                * requirements.  So here we should be checking for any
+                * required changes and forcing a mode set.
+                */
        }
 
        /* set_mode will free it in the mode_changed case */
@@ -12905,6 +13014,9 @@ static struct intel_quirk intel_quirks[] = {
        /* Acer C720 Chromebook (Core i3 4005U) */
        { 0x0a16, 0x1025, 0x0a11, quirk_backlight_present },
 
+       /* Apple Macbook 2,1 (Core 2 T7400) */
+       { 0x27a2, 0x8086, 0x7270, quirk_backlight_present },
+
        /* Toshiba CB35 Chromebook (Celeron 2955U) */
        { 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
 
@@ -13540,11 +13652,13 @@ void intel_modeset_cleanup(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_connector *connector;
 
+       intel_disable_gt_powersave(dev);
+
        intel_backlight_unregister(dev);
 
        /*
         * Interrupts and polling as the first thing to avoid creating havoc.
-        * Too much stuff here (turning of rps, connectors, ...) would
+        * Too much stuff here (turning of connectors, ...) would
         * experience fancy races otherwise.
         */
        intel_irq_uninstall(dev_priv);
@@ -13561,8 +13675,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        intel_disable_fbc(dev);
 
-       intel_disable_gt_powersave(dev);
-
        ironlake_teardown_rc6(dev);
 
        mutex_unlock(&dev->struct_mutex);
This page took 0.067894 seconds and 5 git commands to generate.