]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: Always read out M2_N2 in intel_cpu_transcoder_get_m_n, v2.
[linux.git] / drivers / gpu / drm / i915 / intel_display.c
index d2246ec8a87e4c624d0a93c6f0d97501f6465d7f..505e2983e5523423bc6aaa6dea034768c5447772 100644 (file)
@@ -74,55 +74,6 @@ static const uint64_t i9xx_format_modifiers[] = {
        DRM_FORMAT_MOD_INVALID
 };
 
-static const uint32_t skl_primary_formats[] = {
-       DRM_FORMAT_C8,
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_XBGR8888,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_ABGR8888,
-       DRM_FORMAT_XRGB2101010,
-       DRM_FORMAT_XBGR2101010,
-       DRM_FORMAT_YUYV,
-       DRM_FORMAT_YVYU,
-       DRM_FORMAT_UYVY,
-       DRM_FORMAT_VYUY,
-};
-
-static const uint32_t skl_pri_planar_formats[] = {
-       DRM_FORMAT_C8,
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_XBGR8888,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_ABGR8888,
-       DRM_FORMAT_XRGB2101010,
-       DRM_FORMAT_XBGR2101010,
-       DRM_FORMAT_YUYV,
-       DRM_FORMAT_YVYU,
-       DRM_FORMAT_UYVY,
-       DRM_FORMAT_VYUY,
-       DRM_FORMAT_NV12,
-};
-
-static const uint64_t skl_format_modifiers_noccs[] = {
-       I915_FORMAT_MOD_Yf_TILED,
-       I915_FORMAT_MOD_Y_TILED,
-       I915_FORMAT_MOD_X_TILED,
-       DRM_FORMAT_MOD_LINEAR,
-       DRM_FORMAT_MOD_INVALID
-};
-
-static const uint64_t skl_format_modifiers_ccs[] = {
-       I915_FORMAT_MOD_Yf_TILED_CCS,
-       I915_FORMAT_MOD_Y_TILED_CCS,
-       I915_FORMAT_MOD_Yf_TILED,
-       I915_FORMAT_MOD_Y_TILED,
-       I915_FORMAT_MOD_X_TILED,
-       DRM_FORMAT_MOD_LINEAR,
-       DRM_FORMAT_MOD_INVALID
-};
-
 /* Cursor formats */
 static const uint32_t intel_cursor_formats[] = {
        DRM_FORMAT_ARGB8888,
@@ -143,9 +94,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *ifb,
                                  struct drm_mode_fb_cmd2 *mode_cmd);
 static void intel_set_pipe_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(struct intel_crtc *crtc,
-                                        struct intel_link_m_n *m_n,
-                                        struct intel_link_m_n *m2_n2);
+static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
+                                        const struct intel_link_m_n *m_n,
+                                        const struct intel_link_m_n *m2_n2);
 static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state);
 static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state);
 static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state);
@@ -4888,7 +4839,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
                if (pixel_format == DRM_FORMAT_NV12)
                        need_scaling = true;
 
-       if (crtc_state->ycbcr420 && scaler_user == SKL_CRTC_INDEX)
+       if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
+           scaler_user == SKL_CRTC_INDEX)
                need_scaling = true;
 
        /*
@@ -5605,14 +5557,14 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
                intel_prepare_shared_dpll(pipe_config);
 
        if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(intel_crtc, M1_N1);
+               intel_dp_set_m_n(pipe_config, M1_N1);
 
        intel_set_pipe_timings(pipe_config);
        intel_set_pipe_src_size(pipe_config);
 
        if (pipe_config->has_pch_encoder) {
-               intel_cpu_transcoder_set_m_n(intel_crtc,
-                                    &pipe_config->fdi_m_n, NULL);
+               intel_cpu_transcoder_set_m_n(pipe_config,
+                                            &pipe_config->fdi_m_n, NULL);
        }
 
        ironlake_set_pipeconf(pipe_config);
@@ -5728,7 +5680,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
        intel_encoders_pre_enable(crtc, pipe_config, old_state);
 
        if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(intel_crtc, M1_N1);
+               intel_dp_set_m_n(pipe_config, M1_N1);
 
        if (!transcoder_is_dsi(cpu_transcoder))
                intel_set_pipe_timings(pipe_config);
@@ -5742,8 +5694,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
        }
 
        if (pipe_config->has_pch_encoder) {
-               intel_cpu_transcoder_set_m_n(intel_crtc,
-                                    &pipe_config->fdi_m_n, NULL);
+               intel_cpu_transcoder_set_m_n(pipe_config,
+                                            &pipe_config->fdi_m_n, NULL);
        }
 
        if (!transcoder_is_dsi(cpu_transcoder))
@@ -6070,7 +6022,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
                return;
 
        if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(intel_crtc, M1_N1);
+               intel_dp_set_m_n(pipe_config, M1_N1);
 
        intel_set_pipe_timings(pipe_config);
        intel_set_pipe_src_size(pipe_config);
@@ -6140,7 +6092,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
        i9xx_set_pll_dividers(pipe_config);
 
        if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(intel_crtc, M1_N1);
+               intel_dp_set_m_n(pipe_config, M1_N1);
 
        intel_set_pipe_timings(pipe_config);
        intel_set_pipe_src_size(pipe_config);
@@ -6373,66 +6325,6 @@ static void intel_connector_verify_state(struct drm_crtc_state *crtc_state,
        }
 }
 
-int intel_connector_init(struct intel_connector *connector)
-{
-       struct intel_digital_connector_state *conn_state;
-
-       /*
-        * Allocate enough memory to hold intel_digital_connector_state,
-        * This might be a few bytes too many, but for connectors that don't
-        * need it we'll free the state and allocate a smaller one on the first
-        * succesful commit anyway.
-        */
-       conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
-       if (!conn_state)
-               return -ENOMEM;
-
-       __drm_atomic_helper_connector_reset(&connector->base,
-                                           &conn_state->base);
-
-       return 0;
-}
-
-struct intel_connector *intel_connector_alloc(void)
-{
-       struct intel_connector *connector;
-
-       connector = kzalloc(sizeof *connector, GFP_KERNEL);
-       if (!connector)
-               return NULL;
-
-       if (intel_connector_init(connector) < 0) {
-               kfree(connector);
-               return NULL;
-       }
-
-       return connector;
-}
-
-/*
- * Free the bits allocated by intel_connector_alloc.
- * This should only be used after intel_connector_alloc has returned
- * successfully, and before drm_connector_init returns successfully.
- * Otherwise the destroy callbacks for the connector and the state should
- * take care of proper cleanup/free
- */
-void intel_connector_free(struct intel_connector *connector)
-{
-       kfree(to_intel_digital_connector_state(connector->base.state));
-       kfree(connector);
-}
-
-/* Simple connector->get_hw_state implementation for encoders that support only
- * one connector and no cloning and hence the encoder state determines the state
- * of the connector. */
-bool intel_connector_get_hw_state(struct intel_connector *connector)
-{
-       enum pipe pipe = 0;
-       struct intel_encoder *encoder = connector->encoder;
-
-       return encoder->get_hw_state(encoder, &pipe);
-}
-
 static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
 {
        if (crtc_state->base.enable && crtc_state->has_pch_encoder)
@@ -6699,7 +6591,9 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
                return -EINVAL;
        }
 
-       if (pipe_config->ycbcr420 && pipe_config->base.ctm) {
+       if ((pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
+            pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) &&
+            pipe_config->base.ctm) {
                /*
                 * There is only one pipe CSC unit per pipe, and we need that
                 * for output conversion from RGB->YCBCR. So if CTM is already
@@ -6865,12 +6759,12 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
        vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 }
 
-static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
-                                        struct intel_link_m_n *m_n)
+static void intel_pch_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
+                                        const struct intel_link_m_n *m_n)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = crtc->pipe;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
 
        I915_WRITE(PCH_TRANS_DATA_M1(pipe), TU_SIZE(m_n->tu) | m_n->gmch_m);
        I915_WRITE(PCH_TRANS_DATA_N1(pipe), m_n->gmch_n);
@@ -6878,25 +6772,39 @@ static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
        I915_WRITE(PCH_TRANS_LINK_N1(pipe), m_n->link_n);
 }
 
-static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
-                                        struct intel_link_m_n *m_n,
-                                        struct intel_link_m_n *m2_n2)
+static bool transcoder_has_m2_n2(struct drm_i915_private *dev_priv,
+                                enum transcoder transcoder)
 {
+       if (IS_HASWELL(dev_priv))
+               return transcoder == TRANSCODER_EDP;
+
+       /*
+        * Strictly speaking some registers are available before
+        * gen7, but we only support DRRS on gen7+
+        */
+       return IS_GEN7(dev_priv) || IS_CHERRYVIEW(dev_priv);
+}
+
+static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
+                                        const struct intel_link_m_n *m_n,
+                                        const struct intel_link_m_n *m2_n2)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       int pipe = crtc->pipe;
-       enum transcoder transcoder = crtc->config->cpu_transcoder;
+       enum pipe pipe = crtc->pipe;
+       enum transcoder transcoder = crtc_state->cpu_transcoder;
 
        if (INTEL_GEN(dev_priv) >= 5) {
                I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
                I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
                I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
                I915_WRITE(PIPE_LINK_N1(transcoder), m_n->link_n);
-               /* M2_N2 registers to be set only for gen < 8 (M2_N2 available
-                * for gen < 8) and if DRRS is supported (to make sure the
-                * registers are not unnecessarily accessed).
+               /*
+                *  M2_N2 registers are set only if DRRS is supported
+                * (to make sure the registers are not unnecessarily accessed).
                 */
-               if (m2_n2 && (IS_CHERRYVIEW(dev_priv) ||
-                   INTEL_GEN(dev_priv) < 8) && crtc->config->has_drrs) {
+               if (m2_n2 && crtc_state->has_drrs &&
+                   transcoder_has_m2_n2(dev_priv, transcoder)) {
                        I915_WRITE(PIPE_DATA_M2(transcoder),
                                        TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
                        I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n);
@@ -6911,29 +6819,29 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
        }
 }
 
-void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n)
+void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state, enum link_m_n_set m_n)
 {
-       struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
+       const struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
 
        if (m_n == M1_N1) {
-               dp_m_n = &crtc->config->dp_m_n;
-               dp_m2_n2 = &crtc->config->dp_m2_n2;
+               dp_m_n = &crtc_state->dp_m_n;
+               dp_m2_n2 = &crtc_state->dp_m2_n2;
        } else if (m_n == M2_N2) {
 
                /*
                 * M2_N2 registers are not supported. Hence m2_n2 divider value
                 * needs to be programmed into M1_N1.
                 */
-               dp_m_n = &crtc->config->dp_m2_n2;
+               dp_m_n = &crtc_state->dp_m2_n2;
        } else {
                DRM_ERROR("Unsupported divider value\n");
                return;
        }
 
-       if (crtc->config->has_pch_encoder)
-               intel_pch_transcoder_set_m_n(crtc, &crtc->config->dp_m_n);
+       if (crtc_state->has_pch_encoder)
+               intel_pch_transcoder_set_m_n(crtc_state, &crtc_state->dp_m_n);
        else
-               intel_cpu_transcoder_set_m_n(crtc, dp_m_n, dp_m2_n2);
+               intel_cpu_transcoder_set_m_n(crtc_state, dp_m_n, dp_m2_n2);
 }
 
 static void vlv_compute_dpll(struct intel_crtc *crtc,
@@ -7032,8 +6940,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
 
        /* Set HBR and RBR LPF coefficients */
        if (pipe_config->port_clock == 162000 ||
-           intel_crtc_has_type(crtc->config, INTEL_OUTPUT_ANALOG) ||
-           intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
+           intel_crtc_has_type(pipe_config, INTEL_OUTPUT_ANALOG) ||
+           intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
                vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
                                 0x009f0003);
        else
@@ -7060,7 +6968,7 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
 
        coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe));
        coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
-       if (intel_crtc_has_dp_encoder(crtc->config))
+       if (intel_crtc_has_dp_encoder(pipe_config))
                coreclk |= 0x01000000;
        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
 
@@ -7897,6 +7805,49 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
        pipe_config->port_clock = chv_calc_dpll_params(refclk, &clock);
 }
 
+static void intel_get_crtc_ycbcr_config(struct intel_crtc *crtc,
+                                       struct intel_crtc_state *pipe_config)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum intel_output_format output = INTEL_OUTPUT_FORMAT_RGB;
+
+       pipe_config->lspcon_downsampling = false;
+
+       if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) {
+               u32 tmp = I915_READ(PIPEMISC(crtc->pipe));
+
+               if (tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV) {
+                       bool ycbcr420_enabled = tmp & PIPEMISC_YUV420_ENABLE;
+                       bool blend = tmp & PIPEMISC_YUV420_MODE_FULL_BLEND;
+
+                       if (ycbcr420_enabled) {
+                               /* We support 4:2:0 in full blend mode only */
+                               if (!blend)
+                                       output = INTEL_OUTPUT_FORMAT_INVALID;
+                               else if (!(IS_GEMINILAKE(dev_priv) ||
+                                          INTEL_GEN(dev_priv) >= 10))
+                                       output = INTEL_OUTPUT_FORMAT_INVALID;
+                               else
+                                       output = INTEL_OUTPUT_FORMAT_YCBCR420;
+                       } else {
+                               /*
+                                * 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 = true;
+                               output = INTEL_OUTPUT_FORMAT_YCBCR444;
+                       }
+               }
+       }
+
+       pipe_config->output_format = output;
+}
+
 static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                                 struct intel_crtc_state *pipe_config)
 {
@@ -7909,6 +7860,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = NULL;
 
@@ -8530,11 +8482,13 @@ static void haswell_set_pipemisc(const struct intel_crtc_state *crtc_state)
                if (crtc_state->dither)
                        val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
 
-               if (crtc_state->ycbcr420) {
-                       val |= PIPEMISC_OUTPUT_COLORSPACE_YUV |
-                               PIPEMISC_YUV420_ENABLE |
+               if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
+                   crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
+                       val |= PIPEMISC_OUTPUT_COLORSPACE_YUV;
+
+               if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+                       val |= PIPEMISC_YUV420_ENABLE |
                                PIPEMISC_YUV420_MODE_FULL_BLEND;
-               }
 
                I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
        }
@@ -8745,12 +8699,8 @@ static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
                m_n->gmch_n = I915_READ(PIPE_DATA_N1(transcoder));
                m_n->tu = ((I915_READ(PIPE_DATA_M1(transcoder))
                            & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
-               /* Read M2_N2 registers only for gen < 8 (M2_N2 available for
-                * gen < 8) and if DRRS is supported (to make sure the
-                * registers are not unnecessarily read).
-                */
-               if (m2_n2 && INTEL_GEN(dev_priv) < 8 &&
-                       crtc->config->has_drrs) {
+
+               if (m2_n2 && transcoder_has_m2_n2(dev_priv, transcoder)) {
                        m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder));
                        m2_n2->link_n = I915_READ(PIPE_LINK_N2(transcoder));
                        m2_n2->gmch_m = I915_READ(PIPE_DATA_M2(transcoder))
@@ -8958,6 +8908,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = NULL;
 
@@ -9592,27 +9543,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        }
 
        intel_get_pipe_src_size(crtc, pipe_config);
+       intel_get_crtc_ycbcr_config(crtc, pipe_config);
 
        pipe_config->gamma_mode =
                I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
 
-       if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) {
-               u32 tmp = I915_READ(PIPEMISC(crtc->pipe));
-               bool clrspace_yuv = tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV;
-
-               if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10) {
-                       bool blend_mode_420 = tmp &
-                                             PIPEMISC_YUV420_MODE_FULL_BLEND;
-
-                       pipe_config->ycbcr420 = tmp & PIPEMISC_YUV420_ENABLE;
-                       if (pipe_config->ycbcr420 != clrspace_yuv ||
-                           pipe_config->ycbcr420 != blend_mode_420)
-                               DRM_DEBUG_KMS("Bad 4:2:0 mode (%08x)\n", tmp);
-               } else if (clrspace_yuv) {
-                       DRM_DEBUG_KMS("YCbCr 4:2:0 Unsupported\n");
-               }
-       }
-
        power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
        if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
                power_domain_mask |= BIT_ULL(power_domain);
@@ -11028,6 +10963,20 @@ static void snprintf_output_types(char *buf, size_t len,
        WARN_ON_ONCE(output_types != 0);
 }
 
+static const char * const output_format_str[] = {
+       [INTEL_OUTPUT_FORMAT_INVALID] = "Invalid",
+       [INTEL_OUTPUT_FORMAT_RGB] = "RGB",
+       [INTEL_OUTPUT_FORMAT_YCBCR420] = "YCBCR4:2:0",
+       [INTEL_OUTPUT_FORMAT_YCBCR444] = "YCBCR4:4:4",
+};
+
+static const char *output_formats(enum intel_output_format format)
+{
+       if (format >= ARRAY_SIZE(output_format_str))
+               format = INTEL_OUTPUT_FORMAT_INVALID;
+       return output_format_str[format];
+}
+
 static void intel_dump_pipe_config(struct intel_crtc *crtc,
                                   struct intel_crtc_state *pipe_config,
                                   const char *context)
@@ -11047,6 +10996,9 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
        DRM_DEBUG_KMS("output_types: %s (0x%x)\n",
                      buf, pipe_config->output_types);
 
+       DRM_DEBUG_KMS("output format: %s\n",
+                     output_formats(pipe_config->output_format));
+
        DRM_DEBUG_KMS("cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n",
                      transcoder_name(pipe_config->cpu_transcoder),
                      pipe_config->pipe_bpp, pipe_config->dither);
@@ -11056,9 +11008,6 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                                      pipe_config->fdi_lanes,
                                      &pipe_config->fdi_m_n);
 
-       if (pipe_config->ycbcr420)
-               DRM_DEBUG_KMS("YCbCr 4:2:0 output enabled\n");
-
        if (intel_crtc_has_dp_encoder(pipe_config)) {
                intel_dump_m_n_config(pipe_config, "dp m_n",
                                pipe_config->lane_count, &pipe_config->dp_m_n);
@@ -11636,6 +11585,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
        PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end);
 
        PIPE_CONF_CHECK_I(pixel_multiplier);
+       PIPE_CONF_CHECK_I(output_format);
        PIPE_CONF_CHECK_BOOL(has_hdmi_sink);
        if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) ||
            IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
@@ -11644,7 +11594,6 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
        PIPE_CONF_CHECK_BOOL(hdmi_scrambling);
        PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio);
        PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_infoframe);
-       PIPE_CONF_CHECK_BOOL(ycbcr420);
 
        PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio);
 
@@ -13473,56 +13422,6 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
        }
 }
 
-static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
-                                          u32 format, u64 modifier)
-{
-       struct intel_plane *plane = to_intel_plane(_plane);
-
-       switch (modifier) {
-       case DRM_FORMAT_MOD_LINEAR:
-       case I915_FORMAT_MOD_X_TILED:
-       case I915_FORMAT_MOD_Y_TILED:
-       case I915_FORMAT_MOD_Yf_TILED:
-               break;
-       case I915_FORMAT_MOD_Y_TILED_CCS:
-       case I915_FORMAT_MOD_Yf_TILED_CCS:
-               if (!plane->has_ccs)
-                       return false;
-               break;
-       default:
-               return false;
-       }
-
-       switch (format) {
-       case DRM_FORMAT_XRGB8888:
-       case DRM_FORMAT_XBGR8888:
-       case DRM_FORMAT_ARGB8888:
-       case DRM_FORMAT_ABGR8888:
-               if (is_ccs_modifier(modifier))
-                       return true;
-               /* fall through */
-       case DRM_FORMAT_RGB565:
-       case DRM_FORMAT_XRGB2101010:
-       case DRM_FORMAT_XBGR2101010:
-       case DRM_FORMAT_YUYV:
-       case DRM_FORMAT_YVYU:
-       case DRM_FORMAT_UYVY:
-       case DRM_FORMAT_VYUY:
-       case DRM_FORMAT_NV12:
-               if (modifier == I915_FORMAT_MOD_Yf_TILED)
-                       return true;
-               /* fall through */
-       case DRM_FORMAT_C8:
-               if (modifier == DRM_FORMAT_MOD_LINEAR ||
-                   modifier == I915_FORMAT_MOD_X_TILED ||
-                   modifier == I915_FORMAT_MOD_Y_TILED)
-                       return true;
-               /* fall through */
-       default:
-               return false;
-       }
-}
-
 static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
                                              u32 format, u64 modifier)
 {
@@ -13530,17 +13429,6 @@ static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
                format == DRM_FORMAT_ARGB8888;
 }
 
-static const struct drm_plane_funcs skl_plane_funcs = {
-       .update_plane = drm_atomic_helper_update_plane,
-       .disable_plane = drm_atomic_helper_disable_plane,
-       .destroy = intel_plane_destroy,
-       .atomic_get_property = intel_plane_atomic_get_property,
-       .atomic_set_property = intel_plane_atomic_set_property,
-       .atomic_duplicate_state = intel_plane_duplicate_state,
-       .atomic_destroy_state = intel_plane_destroy_state,
-       .format_mod_supported = skl_plane_format_mod_supported,
-};
-
 static const struct drm_plane_funcs i965_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
@@ -13725,177 +13613,90 @@ static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
                return i9xx_plane == PLANE_A;
 }
 
-static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
-                             enum pipe pipe, enum plane_id plane_id)
-{
-       if (!HAS_FBC(dev_priv))
-               return false;
-
-       return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
-}
-
-bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
-                         enum pipe pipe, enum plane_id plane_id)
-{
-       /*
-        * FIXME: ICL requires two hardware planes for scanning out NV12
-        * framebuffers. Do not advertize support until this is implemented.
-        */
-       if (INTEL_GEN(dev_priv) >= 11)
-               return false;
-
-       if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
-               return false;
-
-       if (INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
-               return false;
-
-       if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
-               return false;
-
-       return true;
-}
-
 static struct intel_plane *
 intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-       struct intel_plane *primary = NULL;
-       struct intel_plane_state *state = NULL;
+       struct intel_plane *plane;
        const struct drm_plane_funcs *plane_funcs;
-       const uint32_t *intel_primary_formats;
        unsigned int supported_rotations;
        unsigned int possible_crtcs;
-       unsigned int num_formats;
-       const uint64_t *modifiers;
+       const u64 *modifiers;
+       const u32 *formats;
+       int num_formats;
        int ret;
 
-       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
-       if (!primary) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       state = intel_create_plane_state(&primary->base);
-       if (!state) {
-               ret = -ENOMEM;
-               goto fail;
-       }
+       if (INTEL_GEN(dev_priv) >= 9)
+               return skl_universal_plane_create(dev_priv, pipe,
+                                                 PLANE_PRIMARY);
 
-       primary->base.state = &state->base;
+       plane = intel_plane_alloc();
+       if (IS_ERR(plane))
+               return plane;
 
-       primary->pipe = pipe;
+       plane->pipe = pipe;
        /*
         * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
         * port is hooked to pipe B. Hence we want plane A feeding pipe B.
         */
        if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4)
-               primary->i9xx_plane = (enum i9xx_plane_id) !pipe;
-       else
-               primary->i9xx_plane = (enum i9xx_plane_id) pipe;
-       primary->id = PLANE_PRIMARY;
-       primary->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, primary->id);
-
-       if (INTEL_GEN(dev_priv) >= 9)
-               primary->has_fbc = skl_plane_has_fbc(dev_priv,
-                                                    primary->pipe,
-                                                    primary->id);
+               plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
        else
-               primary->has_fbc = i9xx_plane_has_fbc(dev_priv,
-                                                     primary->i9xx_plane);
+               plane->i9xx_plane = (enum i9xx_plane_id) pipe;
+       plane->id = PLANE_PRIMARY;
+       plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
 
-       if (primary->has_fbc) {
+       plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
+       if (plane->has_fbc) {
                struct intel_fbc *fbc = &dev_priv->fbc;
 
-               fbc->possible_framebuffer_bits |= primary->frontbuffer_bit;
+               fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
        }
 
-       if (INTEL_GEN(dev_priv) >= 9) {
-               primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
-                                                    PLANE_PRIMARY);
-
-               if (skl_plane_has_planar(dev_priv, pipe, PLANE_PRIMARY)) {
-                       intel_primary_formats = skl_pri_planar_formats;
-                       num_formats = ARRAY_SIZE(skl_pri_planar_formats);
-               } else {
-                       intel_primary_formats = skl_primary_formats;
-                       num_formats = ARRAY_SIZE(skl_primary_formats);
-               }
-
-               if (primary->has_ccs)
-                       modifiers = skl_format_modifiers_ccs;
-               else
-                       modifiers = skl_format_modifiers_noccs;
-
-               primary->max_stride = skl_plane_max_stride;
-               primary->update_plane = skl_update_plane;
-               primary->disable_plane = skl_disable_plane;
-               primary->get_hw_state = skl_plane_get_hw_state;
-               primary->check_plane = skl_plane_check;
-
-               plane_funcs = &skl_plane_funcs;
-       } else if (INTEL_GEN(dev_priv) >= 4) {
-               intel_primary_formats = i965_primary_formats;
+       if (INTEL_GEN(dev_priv) >= 4) {
+               formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
                modifiers = i9xx_format_modifiers;
 
-               primary->max_stride = i9xx_plane_max_stride;
-               primary->update_plane = i9xx_update_plane;
-               primary->disable_plane = i9xx_disable_plane;
-               primary->get_hw_state = i9xx_plane_get_hw_state;
-               primary->check_plane = i9xx_plane_check;
+               plane->max_stride = i9xx_plane_max_stride;
+               plane->update_plane = i9xx_update_plane;
+               plane->disable_plane = i9xx_disable_plane;
+               plane->get_hw_state = i9xx_plane_get_hw_state;
+               plane->check_plane = i9xx_plane_check;
 
                plane_funcs = &i965_plane_funcs;
        } else {
-               intel_primary_formats = i8xx_primary_formats;
+               formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
                modifiers = i9xx_format_modifiers;
 
-               primary->max_stride = i9xx_plane_max_stride;
-               primary->update_plane = i9xx_update_plane;
-               primary->disable_plane = i9xx_disable_plane;
-               primary->get_hw_state = i9xx_plane_get_hw_state;
-               primary->check_plane = i9xx_plane_check;
+               plane->max_stride = i9xx_plane_max_stride;
+               plane->update_plane = i9xx_update_plane;
+               plane->disable_plane = i9xx_disable_plane;
+               plane->get_hw_state = i9xx_plane_get_hw_state;
+               plane->check_plane = i9xx_plane_check;
 
                plane_funcs = &i8xx_plane_funcs;
        }
 
        possible_crtcs = BIT(pipe);
 
-       if (INTEL_GEN(dev_priv) >= 9)
-               ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
-                                              possible_crtcs, plane_funcs,
-                                              intel_primary_formats, num_formats,
-                                              modifiers,
-                                              DRM_PLANE_TYPE_PRIMARY,
-                                              "plane 1%c", pipe_name(pipe));
-       else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-               ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+       if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+               ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
                                               possible_crtcs, plane_funcs,
-                                              intel_primary_formats, num_formats,
-                                              modifiers,
+                                              formats, num_formats, modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "primary %c", pipe_name(pipe));
        else
-               ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+               ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
                                               possible_crtcs, plane_funcs,
-                                              intel_primary_formats, num_formats,
-                                              modifiers,
+                                              formats, num_formats, modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "plane %c",
-                                              plane_name(primary->i9xx_plane));
+                                              plane_name(plane->i9xx_plane));
        if (ret)
                goto fail;
 
-       if (INTEL_GEN(dev_priv) >= 10) {
-               supported_rotations =
-                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
-                       DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 |
-                       DRM_MODE_REFLECT_X;
-       } else if (INTEL_GEN(dev_priv) >= 9) {
-               supported_rotations =
-                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
-                       DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
-       } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+       if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
                supported_rotations =
                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
                        DRM_MODE_REFLECT_X;
@@ -13907,33 +13708,16 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
        }
 
        if (INTEL_GEN(dev_priv) >= 4)
-               drm_plane_create_rotation_property(&primary->base,
+               drm_plane_create_rotation_property(&plane->base,
                                                   DRM_MODE_ROTATE_0,
                                                   supported_rotations);
 
-       if (INTEL_GEN(dev_priv) >= 9) {
-               drm_plane_create_color_properties(&primary->base,
-                                                 BIT(DRM_COLOR_YCBCR_BT601) |
-                                                 BIT(DRM_COLOR_YCBCR_BT709),
-                                                 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
-                                                 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
-                                                 DRM_COLOR_YCBCR_BT709,
-                                                 DRM_COLOR_YCBCR_LIMITED_RANGE);
-
-               drm_plane_create_alpha_property(&primary->base);
-               drm_plane_create_blend_mode_property(&primary->base,
-                                                    BIT(DRM_MODE_BLEND_PIXEL_NONE) |
-                                                    BIT(DRM_MODE_BLEND_PREMULTI) |
-                                                    BIT(DRM_MODE_BLEND_COVERAGE));
-       }
-
-       drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
+       drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
 
-       return primary;
+       return plane;
 
 fail:
-       kfree(state);
-       kfree(primary);
+       intel_plane_free(plane);
 
        return ERR_PTR(ret);
 }
@@ -13942,24 +13726,13 @@ static struct intel_plane *
 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
                          enum pipe pipe)
 {
-       struct intel_plane *cursor = NULL;
-       struct intel_plane_state *state = NULL;
        unsigned int possible_crtcs;
+       struct intel_plane *cursor;
        int ret;
 
-       cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
-       if (!cursor) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       state = intel_create_plane_state(&cursor->base);
-       if (!state) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       cursor->base.state = &state->base;
+       cursor = intel_plane_alloc();
+       if (IS_ERR(cursor))
+               return cursor;
 
        cursor->pipe = pipe;
        cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
@@ -14009,8 +13782,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
        return cursor;
 
 fail:
-       kfree(state);
-       kfree(cursor);
+       intel_plane_free(cursor);
 
        return ERR_PTR(ret);
 }
@@ -14564,13 +14336,19 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
                        goto err;
                }
                /* fall through */
-       case I915_FORMAT_MOD_Y_TILED:
        case I915_FORMAT_MOD_Yf_TILED:
+               if (mode_cmd->pixel_format == DRM_FORMAT_C8) {
+                       DRM_DEBUG_KMS("Indexed format does not support Yf tiling\n");
+                       goto err;
+               }
+               /* fall through */
+       case I915_FORMAT_MOD_Y_TILED:
                if (INTEL_GEN(dev_priv) < 9) {
                        DRM_DEBUG_KMS("Unsupported tiling 0x%llx!\n",
                                      mode_cmd->modifier[0]);
                        goto err;
                }
+               break;
        case DRM_FORMAT_MOD_LINEAR:
        case I915_FORMAT_MOD_X_TILED:
                break;
@@ -16066,29 +15844,6 @@ void intel_display_resume(struct drm_device *dev)
                drm_atomic_state_put(state);
 }
 
-int intel_connector_register(struct drm_connector *connector)
-{
-       struct intel_connector *intel_connector = to_intel_connector(connector);
-       int ret;
-
-       ret = intel_backlight_device_register(intel_connector);
-       if (ret)
-               goto err;
-
-       return 0;
-
-err:
-       return ret;
-}
-
-void intel_connector_unregister(struct drm_connector *connector)
-{
-       struct intel_connector *intel_connector = to_intel_connector(connector);
-
-       intel_backlight_device_unregister(intel_connector);
-       intel_panel_destroy_backlight(connector);
-}
-
 static void intel_hpd_poll_fini(struct drm_device *dev)
 {
        struct intel_connector *connector;
@@ -16148,13 +15903,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
        destroy_workqueue(dev_priv->modeset_wq);
 }
 
-void intel_connector_attach_encoder(struct intel_connector *connector,
-                                   struct intel_encoder *encoder)
-{
-       connector->encoder = encoder;
-       drm_connector_attach_encoder(&connector->base, &encoder->base);
-}
-
 /*
  * set vga decode state - true == enable VGA decode
  */