From patchwork Wed Jun 7 09:49:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kumar, Mahesh" X-Patchwork-Id: 9771123 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9D7B660350 for ; Wed, 7 Jun 2017 09:45:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7C7E028479 for ; Wed, 7 Jun 2017 09:45:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F64828459; Wed, 7 Jun 2017 09:45:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9C65E28459 for ; Wed, 7 Jun 2017 09:45:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4338F6E223; Wed, 7 Jun 2017 09:45:40 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0D81B6E223 for ; Wed, 7 Jun 2017 09:45:39 +0000 (UTC) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Jun 2017 02:45:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.39,310,1493708400"; d="scan'208";a="865435788" Received: from unknown (HELO localhost.localdomain) ([10.223.25.241]) by FMSMGA003.fm.intel.com with ESMTP; 07 Jun 2017 02:45:35 -0700 From: Mahesh Kumar To: intel-gfx@lists.freedesktop.org Date: Wed, 7 Jun 2017 15:19:05 +0530 Message-Id: <20170607094905.16014-1-mahesh1.kumar@intel.com> X-Mailer: git-send-email 2.11.0 Cc: dhinakaran.pandiyan@intel.com, maarten.lankhorst@intel.com Subject: [Intel-gfx] [PATCH] [RFC] drm/i915/skl+: enable PF_ID interlace mode in SKL X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP In previous GEN default Interlace mode enabled is IF-ID mode, but IF-ID mode has many limitations in SKL. This mode doesn't support y-tiling, 90-270 rotation is not supported & YUV-420 planar source pixel formats are not supported with above mode. This patch make changes to use PF-ID Interlace mode in SKL+ platforms. PF-ID mode require one scaler to be attached in pipe-scaling mode. During WM calculation adjusted pixel rate need to be doubled. During max_supported_pixel_format calculation vertical downscale is 2.0. Signed-off-by: Mahesh Kumar Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90238 --- drivers/gpu/drm/i915/intel_atomic.c | 13 ++++++++++ drivers/gpu/drm/i915/intel_display.c | 47 +++++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_drv.h | 10 ++++++++ drivers/gpu/drm/i915/intel_panel.c | 9 +++++-- drivers/gpu/drm/i915/intel_pm.c | 17 ++++++++++++- 5 files changed, 87 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index d791b3ef89b5..06ed2fc449d7 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -248,6 +248,13 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, return -EINVAL; } + if (num_scalers_need > 1 && + scaler_state->scaler_users & (1 << SKL_CRTC_INDEX) && + scaler_state->scaler_users & (1 << SKL_PF_ID_INDEX)) { + DRM_ERROR("Can't attach scaler to CRTC in Interlace Mode\n"); + return -EINVAL; + } + /* walkthrough scaler_users bits and start assigning scalers */ for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { int *scaler_id; @@ -264,6 +271,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, /* panel fitter case: assign as a crtc scaler */ scaler_id = &scaler_state->scaler_id; + } else if (i == SKL_PF_ID_INDEX) { + name = "PF-ID INTERLACE MODE"; + idx = intel_crtc->base.base.id; + + /* PF-ID interlaced mode case: needs a pipe scaler */ + scaler_id = &scaler_state->scaler_id; } else { name = "PLANE"; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 85ac32549e85..15c79b46d645 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, */ need_scaling = src_w != dst_w || src_h != dst_h; + if ((crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + && scaler_user == SKL_PF_ID_INDEX) + /* PF-ID Interlace mode needs a scaler */ + need_scaling = true; + /* * if plane is being disabled or scaler is no more required or force detach * - free scaler binded to this plane/crtc @@ -4635,16 +4640,24 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, * scaler can be assigned to other user. Actual register * update to free the scaler is done in plane/panel-fit programming. * For this purpose crtc/plane_state->scaler_id isn't reset here. + * Now Interlace mode is a new user of pipe-scaler, so free the scaler-id + * only if call is for respective user. If no user for scaler free it. */ if (force_detach || !need_scaling) { - if (*scaler_id >= 0) { + if (*scaler_id >= 0 && + scaler_state->scaler_users & (1 << scaler_user)) { scaler_state->scaler_users &= ~(1 << scaler_user); scaler_state->scalers[*scaler_id].in_use = 0; DRM_DEBUG_KMS("scaler_user index %u.%u: " "Staged freeing scaler id %d scaler_users = 0x%x\n", - intel_crtc->pipe, scaler_user, *scaler_id, - scaler_state->scaler_users); + intel_crtc->pipe, scaler_user, + *scaler_id, scaler_state->scaler_users); + + *scaler_id = -1; + } + if (*scaler_id >= 0 && !scaler_state->scaler_users) { + scaler_state->scalers[*scaler_id].in_use = 0; *scaler_id = -1; } return 0; @@ -4691,6 +4704,16 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state) adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay); } +static int skl_update_scaler_crtc_pf_id_output(struct intel_crtc_state *state) +{ + const struct drm_display_mode *mode = &state->base.adjusted_mode; + + return skl_update_scaler(state, !state->base.active, + SKL_PF_ID_INDEX, &state->scaler_state.scaler_id, + state->pipe_src_w, state->pipe_src_h, + mode->crtc_hdisplay, mode->crtc_vdisplay); +} + /** * skl_update_scaler_plane - Stages update to scaler state for a given plane. * @@ -6258,6 +6281,15 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, } } + if (INTEL_GEN(dev_priv) >= 9) { + if (skl_update_scaler_crtc_pf_id_output(pipe_config)) { + DRM_ERROR("Unable to set scaler for PF-ID mode\n"); + return -EINVAL; + } + intel_pch_panel_fitting(crtc, pipe_config, + DRM_MODE_SCALE_FULLSCREEN); + } + if (adjusted_mode->crtc_clock > clock_limit) { DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", adjusted_mode->crtc_clock, clock_limit, @@ -8045,9 +8077,12 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) if (IS_HASWELL(dev_priv) && intel_crtc->config->dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); - if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) - val |= PIPECONF_INTERLACED_ILK; - else + if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { + if (INTEL_GEN(dev_priv) >= 9) + val |= PIPECONF_PFIT_PF_INTERLACED_ILK; + else + val |= PIPECONF_INTERLACED_ILK; + } else val |= PIPECONF_PROGRESSIVE; I915_WRITE(PIPECONF(cpu_transcoder), val); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 83dd40905821..d4546f6498b9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -483,6 +483,7 @@ struct intel_crtc_scaler_state { * avilability. */ #define SKL_CRTC_INDEX 31 +#define SKL_PF_ID_INDEX 29 unsigned scaler_users; /* scaler used by crtc for panel fitting purpose */ @@ -1206,6 +1207,15 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) return container_of(intel_hdmi, struct intel_digital_port, hdmi); } +static inline bool +is_skl_interlace_mode(struct drm_i915_private *dev_priv, + const struct drm_display_mode *mode) +{ + if (INTEL_GEN(dev_priv) < 9) + return false; + return mode->flags & DRM_MODE_FLAG_INTERLACE; +} + /* intel_fifo_underrun.c */ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv, enum pipe pipe, bool enable); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 4114cb3f14e7..fae7fe7802f8 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -108,9 +108,14 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; int x = 0, y = 0, width = 0, height = 0; - /* Native modes don't need fitting */ + /* + * Native modes don't need fitting + * PF-ID Interlace mode in SKL+ require a pipe scaler + */ if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && - adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h) + adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h && + !(is_skl_interlace_mode(to_i915(intel_crtc->base.dev), + adjusted_mode))) goto done; switch (fitting_mode) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index aa9d8cef7ce0..dfb21f00fbed 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3873,15 +3873,18 @@ static uint_fixed_16_16_t skl_pipe_downscale_amount(const struct intel_crtc_state *crtc_state) { uint_fixed_16_16_t pipe_downscale = u32_to_fixed_16_16(1); + const struct drm_display_mode *mode; if (!crtc_state->base.enable) return pipe_downscale; + mode = &crtc_state->base.adjusted_mode; if (crtc_state->pch_pfit.enabled) { uint32_t src_w, src_h, dst_w, dst_h; uint32_t pfit_size = crtc_state->pch_pfit.size; uint_fixed_16_16_t fp_w_ratio, fp_h_ratio; uint_fixed_16_16_t downscale_h, downscale_w; + uint_fixed_16_16_t min_h_downscale; src_w = crtc_state->pipe_src_w; src_h = crtc_state->pipe_src_h; @@ -3891,10 +3894,19 @@ skl_pipe_downscale_amount(const struct intel_crtc_state *crtc_state) if (!dst_w || !dst_h) return pipe_downscale; + /* + * Interlace mode require 1 scaler so no other scaler can be + * attached to pipe. PF-ID mode is equivalent to 2.0 vertical + * downscale. + */ + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + min_h_downscale = u32_to_fixed_16_16(2); + else + min_h_downscale = u32_to_fixed_16_16(1); fp_w_ratio = fixed_16_16_div(src_w, dst_w); fp_h_ratio = fixed_16_16_div(src_h, dst_h); downscale_w = max_fixed_16_16(fp_w_ratio, u32_to_fixed_16_16(1)); - downscale_h = max_fixed_16_16(fp_h_ratio, u32_to_fixed_16_16(1)); + downscale_h = max_fixed_16_16(fp_h_ratio, min_h_downscale); pipe_downscale = mul_fixed16(downscale_w, downscale_h); } @@ -4418,6 +4430,9 @@ skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate, * with additional adjustments for plane-specific scaling. */ adjusted_pixel_rate = cstate->pixel_rate; + if (cstate->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + adjusted_pixel_rate *= 2; + downscale_amount = skl_plane_downscale_amount(cstate, pstate); return mul_round_up_u32_fixed16(adjusted_pixel_rate,