From patchwork Thu Aug 14 09:24:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: akash.goel@intel.com X-Patchwork-Id: 4723241 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 401999F375 for ; Thu, 14 Aug 2014 09:20:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 40743200FF for ; Thu, 14 Aug 2014 09:20:14 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 065E8201DD for ; Thu, 14 Aug 2014 09:20:13 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 72AB26E646; Thu, 14 Aug 2014 02:20:12 -0700 (PDT) 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 ESMTP id D3BF86E646 for ; Thu, 14 Aug 2014 02:20:11 -0700 (PDT) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.fm.intel.com with ESMTP; 14 Aug 2014 02:12:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,862,1389772800"; d="scan'208";a="372277601" Received: from akashgoe-desktop.iind.intel.com ([10.223.82.144]) by FMSMGA003.fm.intel.com with ESMTP; 14 Aug 2014 02:16:46 -0700 From: akash.goel@intel.com To: intel-gfx@lists.freedesktop.org Date: Thu, 14 Aug 2014 14:54:24 +0530 Message-Id: <1408008267-11443-4-git-send-email-akash.goel@intel.com> X-Mailer: git-send-email 1.9.2 In-Reply-To: <1408008267-11443-1-git-send-email-akash.goel@intel.com> References: <1408008267-11443-1-git-send-email-akash.goel@intel.com> Cc: shobhit.kumar@intel.com, Akash Goel Subject: [Intel-gfx] [PATCH 3/6] drm/i915: Added Max down-scale ratio checks when enabling Panel fitter X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 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-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Akash Goel This patch adds a check on the Max down scale ratio supported by the Panel fitter. If Source width/height is too big, that the downscale ratio of more than 1.125 is needed to fit into the Output window, then that configuration will be rejected. Signed-off-by: Akash Goel Signed-off-by: Pallavi G --- drivers/gpu/drm/i915/intel_panel.c | 113 ++++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 15f2979..350e94d 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -33,6 +33,22 @@ #include #include "intel_drv.h" +/* Max Downscale ratio of 1.125, expressed in 1.12 fixed point format */ +#define MAX_DOWNSCALE_RATIO (0x9 << 9) + +static inline u32 panel_fitter_scaling(u32 source, u32 target) +{ + /* + * Floating point operation is not supported. So the FACTOR + * is defined, which can avoid the floating point computation + * when calculating the panel ratio. + */ +#define ACCURACY 12 +#define FACTOR (1 << ACCURACY) + u32 ratio = source * FACTOR / target; + return (FACTOR * ratio + FACTOR/2) / FACTOR; +} + void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -103,6 +119,7 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, { struct drm_display_mode *adjusted_mode; int x, y, width, height; + u32 pf_horizontal_ratio, pf_vertical_ratio; adjusted_mode = &pipe_config->adjusted_mode; @@ -161,6 +178,19 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, return false; } + pf_horizontal_ratio = panel_fitter_scaling(pipe_config->pipe_src_w, + width); + pf_vertical_ratio = panel_fitter_scaling(pipe_config->pipe_src_h, + height); + + if (pf_horizontal_ratio > MAX_DOWNSCALE_RATIO) { + DRM_DEBUG_KMS("Src width is too big to downscale\n"); + return false; + } else if (pf_vertical_ratio > MAX_DOWNSCALE_RATIO) { + DRM_DEBUG_KMS("Src height is too big to downscale\n"); + return false; + } + done: pipe_config->pch_pfit.pos = (x << 16) | y; pipe_config->pch_pfit.size = (width << 16) | height; @@ -211,21 +241,9 @@ centre_vertically(struct drm_display_mode *mode, mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width; } -static inline u32 panel_fitter_scaling(u32 source, u32 target) -{ - /* - * Floating point operation is not supported. So the FACTOR - * is defined, which can avoid the floating point computation - * when calculating the panel ratio. - */ -#define ACCURACY 12 -#define FACTOR (1 << ACCURACY) - u32 ratio = source * FACTOR / target; - return (FACTOR * ratio + FACTOR/2) / FACTOR; -} - static void i965_scale_aspect(struct intel_crtc_config *pipe_config, - u32 *pfit_control) + u32 *pfit_control, + u32 *pf_horizontal_ratio, u32 *pf_vertical_ratio) { struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; u32 scaled_width = adjusted_mode->hdisplay * @@ -234,19 +252,39 @@ static void i965_scale_aspect(struct intel_crtc_config *pipe_config, adjusted_mode->vdisplay; /* 965+ is easy, it does everything in hw */ - if (scaled_width > scaled_height) + if (scaled_width > scaled_height) { *pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR; - else if (scaled_width < scaled_height) + *pf_horizontal_ratio = + panel_fitter_scaling(pipe_config->pipe_src_w, + scaled_height / pipe_config->pipe_src_h); + *pf_vertical_ratio = panel_fitter_scaling(pipe_config->pipe_src_h, + adjusted_mode->vdisplay); + } + else if (scaled_width < scaled_height) { *pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER; - else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w) + *pf_vertical_ratio = + panel_fitter_scaling(pipe_config->pipe_src_h, + scaled_width / pipe_config->pipe_src_w); + *pf_horizontal_ratio = panel_fitter_scaling(pipe_config->pipe_src_w, + adjusted_mode->hdisplay); + } + else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w) { *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; + *pf_horizontal_ratio = + panel_fitter_scaling(pipe_config->pipe_src_w, + adjusted_mode->hdisplay); + *pf_vertical_ratio = + panel_fitter_scaling(pipe_config->pipe_src_h, + adjusted_mode->vdisplay); + } } static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, u32 *pfit_control, u32 *pfit_pgm_ratios, - u32 *border) + u32 *border, + u32 *pf_horizontal_ratio, u32 *pf_vertical_ratio) { struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; u32 scaled_width = adjusted_mode->hdisplay * @@ -264,11 +302,15 @@ static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, centre_horizontally(adjusted_mode, scaled_height / pipe_config->pipe_src_h); + *pf_horizontal_ratio = + panel_fitter_scaling(pipe_config->pipe_src_w, + scaled_height / pipe_config->pipe_src_h); *border = LVDS_BORDER_ENABLE; if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) { bits = panel_fitter_scaling(pipe_config->pipe_src_h, adjusted_mode->vdisplay); + *pf_vertical_ratio = bits; *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | bits << PFIT_VERT_SCALE_SHIFT); @@ -280,11 +322,15 @@ static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, centre_vertically(adjusted_mode, scaled_width / pipe_config->pipe_src_w); + *pf_vertical_ratio = + panel_fitter_scaling(pipe_config->pipe_src_h, + scaled_width / pipe_config->pipe_src_w); *border = LVDS_BORDER_ENABLE; if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) { bits = panel_fitter_scaling(pipe_config->pipe_src_w, adjusted_mode->hdisplay); + *pf_horizontal_ratio = bits; *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | bits << PFIT_VERT_SCALE_SHIFT); @@ -298,6 +344,13 @@ static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); + + *pf_horizontal_ratio = + panel_fitter_scaling(pipe_config->pipe_src_w, + adjusted_mode->hdisplay); + *pf_vertical_ratio = + panel_fitter_scaling(pipe_config->pipe_src_h, + adjusted_mode->vdisplay); } } @@ -308,6 +361,7 @@ bool intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, struct drm_device *dev = intel_crtc->base.dev; u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; struct drm_display_mode *adjusted_mode; + u32 pf_horizontal_ratio = 0, pf_vertical_ratio = 0; adjusted_mode = &pipe_config->adjusted_mode; @@ -325,20 +379,31 @@ bool intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); centre_vertically(adjusted_mode, pipe_config->pipe_src_h); border = LVDS_BORDER_ENABLE; + /* 1:1 scaling */ + pf_horizontal_ratio = pf_vertical_ratio = 1; break; case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ if (INTEL_INFO(dev)->gen >= 4) - i965_scale_aspect(pipe_config, &pfit_control); + i965_scale_aspect(pipe_config, &pfit_control, + &pf_horizontal_ratio, &pf_vertical_ratio); else i9xx_scale_aspect(pipe_config, &pfit_control, - &pfit_pgm_ratios, &border); + &pfit_pgm_ratios, &border, + &pf_horizontal_ratio, + &pf_vertical_ratio); break; case DRM_MODE_SCALE_FULLSCREEN: /* * Full scaling, even if it changes the aspect ratio. * Fortunately this is all done for us in hw. */ + pf_horizontal_ratio = + panel_fitter_scaling(pipe_config->pipe_src_w, + adjusted_mode->hdisplay); + pf_vertical_ratio = + panel_fitter_scaling(pipe_config->pipe_src_h, + adjusted_mode->vdisplay); if (pipe_config->pipe_src_h != adjusted_mode->vdisplay || pipe_config->pipe_src_w != adjusted_mode->hdisplay) { pfit_control |= PFIT_ENABLE; @@ -356,6 +421,14 @@ bool intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, return false; } + if (pf_horizontal_ratio > MAX_DOWNSCALE_RATIO) { + DRM_DEBUG_KMS("Src width is too big to downscale\n"); + return false; + } else if (pf_vertical_ratio > MAX_DOWNSCALE_RATIO) { + DRM_DEBUG_KMS("Src height is too big to downscale\n"); + return false; + } + /* 965+ wants fuzzy fitting */ /* FIXME: handle multiple panels by failing gracefully */ if (INTEL_INFO(dev)->gen >= 4)