Merge drm/drm-next into drm-misc-next
[linux-block.git] / drivers / gpu / drm / i915 / intel_display.c
index bd8956f2544d637d9a45a5e56d918bcb52d916ba..9382375d33b27258786b151a69b9eb1184902453 100644 (file)
@@ -5632,6 +5632,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
        struct intel_atomic_state *old_intel_state =
                to_intel_atomic_state(old_state);
        bool psl_clkgate_wa;
+       u32 pipe_chicken;
 
        if (WARN_ON(intel_crtc->active))
                return;
@@ -5691,6 +5692,17 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
         */
        intel_color_load_luts(&pipe_config->base);
 
+       /*
+        * Display WA #1153: enable hardware to bypass the alpha math
+        * and rounding for per-pixel values 00 and 0xff
+        */
+       if (INTEL_GEN(dev_priv) >= 11) {
+               pipe_chicken = I915_READ(PIPE_CHICKEN(pipe));
+               if (!(pipe_chicken & PER_PIXEL_ALPHA_BYPASS_EN))
+                       I915_WRITE_FW(PIPE_CHICKEN(pipe),
+                                     pipe_chicken | PER_PIXEL_ALPHA_BYPASS_EN);
+       }
+
        intel_ddi_set_pipe_settings(pipe_config);
        if (!transcoder_is_dsi(cpu_transcoder))
                intel_ddi_enable_transcoder_func(pipe_config);
@@ -5825,7 +5837,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
                intel_ddi_set_vc_payload_alloc(old_crtc_state, false);
 
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
+               intel_ddi_disable_transcoder_func(old_crtc_state);
 
        if (INTEL_GEN(dev_priv) >= 9)
                skylake_scaler_disable(intel_crtc);
@@ -9347,6 +9359,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
                switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
                default:
                        WARN(1, "unknown pipe linked to edp transcoder\n");
+                       /* fall through */
                case TRANS_DDI_EDP_INPUT_A_ONOFF:
                case TRANS_DDI_EDP_INPUT_A_ON:
                        trans_edp_pipe = PIPE_A;
@@ -9402,7 +9415,7 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
                 * registers/MIPI[BXT]. We can break out here early, since we
                 * need the same DSI PLL to be enabled for both DSI ports.
                 */
-               if (!intel_dsi_pll_is_enabled(dev_priv))
+               if (!bxt_dsi_pll_is_enabled(dev_priv))
                        break;
 
                /* XXX: this works for video mode only */
@@ -10724,7 +10737,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
        drm_connector_list_iter_begin(dev, &conn_iter);
        for_each_intel_connector_iter(connector, &conn_iter) {
                if (connector->base.state->crtc)
-                       drm_connector_unreference(&connector->base);
+                       drm_connector_put(&connector->base);
 
                if (connector->base.encoder) {
                        connector->base.state->best_encoder =
@@ -10732,7 +10745,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
                        connector->base.state->crtc =
                                connector->base.encoder->crtc;
 
-                       drm_connector_reference(&connector->base);
+                       drm_connector_get(&connector->base);
                } else {
                        connector->base.state->best_encoder = NULL;
                        connector->base.state->crtc = NULL;
@@ -11011,6 +11024,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
                case INTEL_OUTPUT_DDI:
                        if (WARN_ON(!HAS_DDI(to_i915(dev))))
                                break;
+                       /* else: fall through */
                case INTEL_OUTPUT_DP:
                case INTEL_OUTPUT_HDMI:
                case INTEL_OUTPUT_EDP:
@@ -12542,6 +12556,19 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat
        finish_wait(&dev_priv->gpu_error.wait_queue, &wait_reset);
 }
 
+static void intel_atomic_cleanup_work(struct work_struct *work)
+{
+       struct drm_atomic_state *state =
+               container_of(work, struct drm_atomic_state, commit_work);
+       struct drm_i915_private *i915 = to_i915(state->dev);
+
+       drm_atomic_helper_cleanup_planes(&i915->drm, state);
+       drm_atomic_helper_commit_cleanup_done(state);
+       drm_atomic_state_put(state);
+
+       intel_atomic_helper_free_state(i915);
+}
+
 static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
@@ -12702,13 +12729,16 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
                intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
        }
 
-       drm_atomic_helper_cleanup_planes(dev, state);
-
-       drm_atomic_helper_commit_cleanup_done(state);
-
-       drm_atomic_state_put(state);
-
-       intel_atomic_helper_free_state(dev_priv);
+       /*
+        * Defer the cleanup of the old state to a separate worker to not
+        * impede the current task (userspace for blocking modesets) that
+        * are executed inline. For out-of-line asynchronous modesets/flips,
+        * deferring to a new worker seems overkill, but we would place a
+        * schedule point (cond_resched()) here anyway to keep latencies
+        * down.
+        */
+       INIT_WORK(&state->commit_work, intel_atomic_cleanup_work);
+       schedule_work(&state->commit_work);
 }
 
 static void intel_atomic_commit_work(struct work_struct *work)
@@ -13076,6 +13106,19 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                add_rps_boost_after_vblank(new_state->crtc, new_state->fence);
        }
 
+       /*
+        * We declare pageflips to be interactive and so merit a small bias
+        * towards upclocking to deliver the frame on time. By only changing
+        * the RPS thresholds to sample more regularly and aim for higher
+        * clocks we can hopefully deliver low power workloads (like kodi)
+        * that are not quite steady state without resorting to forcing
+        * maximum clocks following a vblank miss (see do_rps_boost()).
+        */
+       if (!intel_state->rps_interactive) {
+               intel_rps_mark_interactive(dev_priv, true);
+               intel_state->rps_interactive = true;
+       }
+
        return 0;
 }
 
@@ -13092,8 +13135,15 @@ void
 intel_cleanup_plane_fb(struct drm_plane *plane,
                       struct drm_plane_state *old_state)
 {
+       struct intel_atomic_state *intel_state =
+               to_intel_atomic_state(old_state->state);
        struct drm_i915_private *dev_priv = to_i915(plane->dev);
 
+       if (intel_state->rps_interactive) {
+               intel_rps_mark_interactive(dev_priv, false);
+               intel_state->rps_interactive = false;
+       }
+
        /* Should only be called after a successful intel_prepare_plane_fb()! */
        mutex_lock(&dev_priv->drm.struct_mutex);
        intel_plane_unpin_fb(to_intel_plane_state(old_state));
@@ -14107,7 +14157,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
                intel_ddi_init(dev_priv, PORT_B);
                intel_ddi_init(dev_priv, PORT_C);
 
-               intel_dsi_init(dev_priv);
+               vlv_dsi_init(dev_priv);
        } else if (HAS_DDI(dev_priv)) {
                int found;
 
@@ -14213,7 +14263,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
                                intel_hdmi_init(dev_priv, CHV_HDMID, PORT_D);
                }
 
-               intel_dsi_init(dev_priv);
+               vlv_dsi_init(dev_priv);
        } else if (!IS_GEN2(dev_priv) && !IS_PINEVIEW(dev_priv)) {
                bool found = false;
 
@@ -14495,11 +14545,6 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
                }
                break;
        case DRM_FORMAT_NV12:
-               if (mode_cmd->modifier[0] == I915_FORMAT_MOD_Y_TILED_CCS ||
-                   mode_cmd->modifier[0] == I915_FORMAT_MOD_Yf_TILED_CCS) {
-                       DRM_DEBUG_KMS("RC not to be enabled with NV12\n");
-                       goto err;
-               }
                if (INTEL_GEN(dev_priv) < 9 || IS_SKYLAKE(dev_priv) ||
                    IS_BROXTON(dev_priv)) {
                        DRM_DEBUG_KMS("unsupported pixel format: %s\n",
@@ -14826,6 +14871,18 @@ static void quirk_increase_t12_delay(struct drm_device *dev)
        DRM_INFO("Applying T12 delay quirk\n");
 }
 
+/*
+ * GeminiLake NUC HDMI outputs require additional off time
+ * this allows the onboard retimer to correctly sync to signal
+ */
+static void quirk_increase_ddi_disabled_time(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+
+       dev_priv->quirks |= QUIRK_INCREASE_DDI_DISABLED_TIME;
+       DRM_INFO("Applying Increase DDI Disabled quirk\n");
+}
+
 struct intel_quirk {
        int device;
        int subsystem_vendor;
@@ -14912,6 +14969,13 @@ static struct intel_quirk intel_quirks[] = {
 
        /* Toshiba Satellite P50-C-18C */
        { 0x191B, 0x1179, 0xF840, quirk_increase_t12_delay },
+
+       /* GeminiLake NUC */
+       { 0x3185, 0x8086, 0x2072, quirk_increase_ddi_disabled_time },
+       { 0x3184, 0x8086, 0x2072, quirk_increase_ddi_disabled_time },
+       /* ASRock ITX*/
+       { 0x3185, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
+       { 0x3184, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -15678,11 +15742,20 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
        for_each_intel_encoder(&dev_priv->drm, encoder) {
                u64 get_domains;
                enum intel_display_power_domain domain;
+               struct intel_crtc_state *crtc_state;
 
                if (!encoder->get_power_domains)
                        continue;
 
-               get_domains = encoder->get_power_domains(encoder);
+               /*
+                * MST-primary and inactive encoders don't have a crtc state
+                * and neither of these require any power domain references.
+                */
+               if (!encoder->base.crtc)
+                       continue;
+
+               crtc_state = to_intel_crtc_state(encoder->base.crtc->state);
+               get_domains = encoder->get_power_domains(encoder, crtc_state);
                for_each_power_domain(domain, get_domains)
                        intel_display_power_get(dev_priv, domain);
        }
@@ -15858,6 +15931,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
 
+       flush_workqueue(dev_priv->modeset_wq);
+
        flush_work(&dev_priv->atomic_helper.free_work);
        WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list));