Merge drm/drm-next into drm-intel-next-queued
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / display / intel_display.c
index 1bbe2c4..19a4d81 100644 (file)
@@ -154,7 +154,7 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc,
 static int intel_framebuffer_init(struct intel_framebuffer *ifb,
                                  struct drm_i915_gem_object *obj,
                                  struct drm_mode_fb_cmd2 *mode_cmd);
-static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state);
+static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
 static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state);
 static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
                                         const struct intel_link_m_n *m_n,
@@ -3449,6 +3449,14 @@ initial_plane_vma(struct drm_i915_private *i915,
        if (IS_ERR(obj))
                return NULL;
 
+       /*
+        * Mark it WT ahead of time to avoid changing the
+        * cache_level during fbdev initialization. The
+        * unbind there would get stuck waiting for rcu.
+        */
+       i915_gem_object_set_cache_coherency(obj, HAS_WT(i915) ?
+                                           I915_CACHE_WT : I915_CACHE_NONE);
+
        switch (plane_config->tiling) {
        case I915_TILING_NONE:
                break;
@@ -5033,18 +5041,14 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                intel_pps_unlock_regs_wa(dev_priv);
                intel_modeset_init_hw(dev_priv);
                intel_init_clock_gating(dev_priv);
-
-               spin_lock_irq(&dev_priv->irq_lock);
-               if (dev_priv->display.hpd_irq_setup)
-                       dev_priv->display.hpd_irq_setup(dev_priv);
-               spin_unlock_irq(&dev_priv->irq_lock);
+               intel_hpd_init(dev_priv);
 
                ret = __intel_display_resume(dev, state, ctx);
                if (ret)
                        drm_err(&dev_priv->drm,
                                "Restoring old state failed with %i\n", ret);
 
-               intel_hpd_init(dev_priv);
+               intel_hpd_poll_disable(dev_priv);
        }
 
        drm_atomic_state_put(state);
@@ -6285,6 +6289,105 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
                skl_detach_scaler(crtc, i);
 }
 
+static int cnl_coef_tap(int i)
+{
+       return i % 7;
+}
+
+static u16 cnl_nearest_filter_coef(int t)
+{
+       return t == 3 ? 0x0800 : 0x3000;
+}
+
+/*
+ *  Theory behind setting nearest-neighbor integer scaling:
+ *
+ *  17 phase of 7 taps requires 119 coefficients in 60 dwords per set.
+ *  The letter represents the filter tap (D is the center tap) and the number
+ *  represents the coefficient set for a phase (0-16).
+ *
+ *         +------------+------------------------+------------------------+
+ *         |Index value | Data value coeffient 1 | Data value coeffient 2 |
+ *         +------------+------------------------+------------------------+
+ *         |   00h      |          B0            |          A0            |
+ *         +------------+------------------------+------------------------+
+ *         |   01h      |          D0            |          C0            |
+ *         +------------+------------------------+------------------------+
+ *         |   02h      |          F0            |          E0            |
+ *         +------------+------------------------+------------------------+
+ *         |   03h      |          A1            |          G0            |
+ *         +------------+------------------------+------------------------+
+ *         |   04h      |          C1            |          B1            |
+ *         +------------+------------------------+------------------------+
+ *         |   ...      |          ...           |          ...           |
+ *         +------------+------------------------+------------------------+
+ *         |   38h      |          B16           |          A16           |
+ *         +------------+------------------------+------------------------+
+ *         |   39h      |          D16           |          C16           |
+ *         +------------+------------------------+------------------------+
+ *         |   3Ah      |          F16           |          C16           |
+ *         +------------+------------------------+------------------------+
+ *         |   3Bh      |        Reserved        |          G16           |
+ *         +------------+------------------------+------------------------+
+ *
+ *  To enable nearest-neighbor scaling:  program scaler coefficents with
+ *  the center tap (Dxx) values set to 1 and all other values set to 0 as per
+ *  SCALER_COEFFICIENT_FORMAT
+ *
+ */
+
+static void cnl_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
+                                            enum pipe pipe, int id, int set)
+{
+       int i;
+
+       intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set),
+                         PS_COEE_INDEX_AUTO_INC);
+
+       for (i = 0; i < 17 * 7; i += 2) {
+               u32 tmp;
+               int t;
+
+               t = cnl_coef_tap(i);
+               tmp = cnl_nearest_filter_coef(t);
+
+               t = cnl_coef_tap(i + 1);
+               tmp |= cnl_nearest_filter_coef(t) << 16;
+
+               intel_de_write_fw(dev_priv, CNL_PS_COEF_DATA_SET(pipe, id, set),
+                                 tmp);
+       }
+
+       intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set), 0);
+}
+
+inline u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set)
+{
+       if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) {
+               return (PS_FILTER_PROGRAMMED |
+                       PS_Y_VERT_FILTER_SELECT(set) |
+                       PS_Y_HORZ_FILTER_SELECT(set) |
+                       PS_UV_VERT_FILTER_SELECT(set) |
+                       PS_UV_HORZ_FILTER_SELECT(set));
+       }
+
+       return PS_FILTER_MEDIUM;
+}
+
+void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
+                            int id, int set, enum drm_scaling_filter filter)
+{
+       switch (filter) {
+       case DRM_SCALING_FILTER_DEFAULT:
+               break;
+       case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
+               cnl_program_nearest_filter_coefs(dev_priv, pipe, id, set);
+               break;
+       default:
+               MISSING_CASE(filter);
+       }
+}
+
 static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -6305,6 +6408,7 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
        int hscale, vscale;
        unsigned long irqflags;
        int id;
+       u32 ps_ctrl;
 
        if (!crtc_state->pch_pfit.enabled)
                return;
@@ -6321,10 +6425,16 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
 
        id = scaler_state->scaler_id;
 
+       ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
+       ps_ctrl |=  PS_SCALER_EN | scaler_state->scalers[id].mode;
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
-       intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
-                         PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
+       skl_scaler_setup_filter(dev_priv, pipe, id, 0,
+                               crtc_state->hw.scaling_filter);
+
+       intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), ps_ctrl);
+
        intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, id),
                          PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase));
        intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, id),
@@ -7000,7 +7110,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
        if (intel_crtc_has_dp_encoder(new_crtc_state))
                intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(new_crtc_state);
+       intel_set_transcoder_timings(new_crtc_state);
        intel_set_pipe_src_size(new_crtc_state);
 
        if (new_crtc_state->has_pch_encoder)
@@ -7145,7 +7255,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
        intel_encoders_pre_enable(state, crtc);
 
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_set_pipe_timings(new_crtc_state);
+               intel_set_transcoder_timings(new_crtc_state);
 
        intel_set_pipe_src_size(new_crtc_state);
 
@@ -7353,23 +7463,23 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
 
 enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port)
 {
-       if (IS_ROCKETLAKE(i915) && port >= PORT_D)
-               return (enum phy)port - 1;
+       if (IS_ROCKETLAKE(i915) && port >= PORT_TC1)
+               return PHY_C + port - PORT_TC1;
        else if (IS_JSL_EHL(i915) && port == PORT_D)
                return PHY_A;
 
-       return (enum phy)port;
+       return PHY_A + port - PORT_A;
 }
 
 enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port)
 {
        if (!intel_phy_is_tc(dev_priv, intel_port_to_phy(dev_priv, port)))
-               return PORT_TC_NONE;
+               return TC_PORT_NONE;
 
        if (INTEL_GEN(dev_priv) >= 12)
-               return port - PORT_D;
-
-       return port - PORT_C;
+               return TC_PORT_1 + port - PORT_TC1;
+       else
+               return TC_PORT_1 + port - PORT_C;
 }
 
 enum intel_display_power_domain intel_port_to_power_domain(enum port port)
@@ -7540,7 +7650,7 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state,
        if (intel_crtc_has_dp_encoder(new_crtc_state))
                intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(new_crtc_state);
+       intel_set_transcoder_timings(new_crtc_state);
        intel_set_pipe_src_size(new_crtc_state);
 
        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
@@ -7608,7 +7718,7 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state,
        if (intel_crtc_has_dp_encoder(new_crtc_state))
                intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(new_crtc_state);
+       intel_set_transcoder_timings(new_crtc_state);
        intel_set_pipe_src_size(new_crtc_state);
 
        i9xx_set_pipeconf(new_crtc_state);
@@ -8225,7 +8335,7 @@ static void compute_m_n(unsigned int m, unsigned int n,
         * which the devices expect also in synchronous clock mode.
         */
        if (constant_n)
-               *ret_n = 0x8000;
+               *ret_n = DP_LINK_CONSTANT_N_VALUE;
        else
                *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
 
@@ -8862,7 +8972,7 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,
        crtc_state->dpll_hw_state.dpll = dpll;
 }
 
-static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state)
+static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
@@ -8948,8 +9058,8 @@ static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)
                return intel_de_read(dev_priv, PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK;
 }
 
-static void intel_get_pipe_timings(struct intel_crtc *crtc,
-                                  struct intel_crtc_state *pipe_config)
+static void intel_get_transcoder_timings(struct intel_crtc *crtc,
+                                        struct intel_crtc_state *pipe_config)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -9572,7 +9682,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        if (INTEL_GEN(dev_priv) < 4)
                pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
 
-       intel_get_pipe_timings(crtc, pipe_config);
+       intel_get_transcoder_timings(crtc, pipe_config);
        intel_get_pipe_src_size(crtc, pipe_config);
 
        i9xx_get_pfit_config(pipe_config);
@@ -10692,6 +10802,10 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
            val & PLANE_CTL_FLIP_HORIZONTAL)
                plane_config->rotation |= DRM_MODE_REFLECT_X;
 
+       /* 90/270 degree rotation would require extra work */
+       if (drm_rotation_90_or_270(plane_config->rotation))
+               goto error;
+
        base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
        plane_config->base = base;
 
@@ -10853,7 +10967,7 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->pixel_multiplier = 1;
        }
 
-       intel_get_pipe_timings(crtc, pipe_config);
+       intel_get_transcoder_timings(crtc, pipe_config);
        intel_get_pipe_src_size(crtc, pipe_config);
 
        ilk_get_pfit_config(pipe_config);
@@ -11270,7 +11384,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
        if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
            INTEL_GEN(dev_priv) >= 11) {
                hsw_get_ddi_port_state(crtc, pipe_config);
-               intel_get_pipe_timings(crtc, pipe_config);
+               intel_get_transcoder_timings(crtc, pipe_config);
        }
 
        intel_get_pipe_src_size(crtc, pipe_config);
@@ -11286,18 +11400,6 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
        } else {
                pipe_config->output_format =
                        bdw_get_pipemisc_output_format(crtc);
-
-               /*
-                * Currently there is no interface defined to
-                * check user preference between RGB/YCBCR444
-                * or YCBCR420. So the only possible case for
-                * YCBCR444 usage is driving YCBCR420 output
-                * with LSPCON, when pipe is configured for
-                * YCBCR444 output and LSPCON takes care of
-                * downsampling it.
-                */
-               pipe_config->lspcon_downsampling =
-                       pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444;
        }
 
        pipe_config->gamma_mode = intel_de_read(dev_priv,
@@ -13358,6 +13460,7 @@ intel_crtc_copy_uapi_to_hw_state(struct intel_crtc_state *crtc_state)
        crtc_state->hw.active = crtc_state->uapi.active;
        crtc_state->hw.mode = crtc_state->uapi.mode;
        crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode;
+       crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter;
        intel_crtc_copy_uapi_to_hw_state_nomodeset(crtc_state);
 }
 
@@ -13369,6 +13472,7 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
                    drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0);
 
        crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
+       crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
 
        /* copy color blobs to uapi */
        drm_property_replace_blob(&crtc_state->uapi.degamma_lut,
@@ -13553,12 +13657,6 @@ encoder_retry:
                    "hw max bpp: %i, pipe bpp: %i, dithering: %i\n",
                    base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
 
-       /*
-        * Make drm_calc_timestamping_constants in
-        * drm_atomic_helper_update_legacy_modeset_state() happy
-        */
-       pipe_config->uapi.adjusted_mode = pipe_config->hw.adjusted_mode;
-
        return 0;
 }
 
@@ -16969,6 +17067,11 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
                dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
        }
 
+       if (INTEL_GEN(dev_priv) >= 10)
+               drm_crtc_create_scaling_filter_property(&crtc->base,
+                                               BIT(DRM_SCALING_FILTER_DEFAULT) |
+                                               BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
+
        intel_color_init(crtc);
 
        intel_crtc_crc_init(crtc);
@@ -17113,17 +17216,17 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
        if (IS_ROCKETLAKE(dev_priv)) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
-               intel_ddi_init(dev_priv, PORT_D);       /* DDI TC1 */
-               intel_ddi_init(dev_priv, PORT_E);       /* DDI TC2 */
+               intel_ddi_init(dev_priv, PORT_TC1);
+               intel_ddi_init(dev_priv, PORT_TC2);
        } else if (INTEL_GEN(dev_priv) >= 12) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
-               intel_ddi_init(dev_priv, PORT_D);
-               intel_ddi_init(dev_priv, PORT_E);
-               intel_ddi_init(dev_priv, PORT_F);
-               intel_ddi_init(dev_priv, PORT_G);
-               intel_ddi_init(dev_priv, PORT_H);
-               intel_ddi_init(dev_priv, PORT_I);
+               intel_ddi_init(dev_priv, PORT_TC1);
+               intel_ddi_init(dev_priv, PORT_TC2);
+               intel_ddi_init(dev_priv, PORT_TC3);
+               intel_ddi_init(dev_priv, PORT_TC4);
+               intel_ddi_init(dev_priv, PORT_TC5);
+               intel_ddi_init(dev_priv, PORT_TC6);
                icl_dsi_init(dev_priv);
        } else if (IS_JSL_EHL(dev_priv)) {
                intel_ddi_init(dev_priv, PORT_A);
@@ -18266,6 +18369,7 @@ int intel_modeset_init(struct drm_i915_private *i915)
 
        /* Only enable hotplug handling once the fbdev is fully set up. */
        intel_hpd_init(i915);
+       intel_hpd_poll_disable(i915);
 
        intel_init_ipc(i915);