From patchwork Tue Mar 4 10:11:41 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: 3760661 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 38B6ABF13A for ; Tue, 4 Mar 2014 10:09:55 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0C6352041F for ; Tue, 4 Mar 2014 10:09:54 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 7A92F2021C for ; Tue, 4 Mar 2014 10:09:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3B2B2FB5EE; Tue, 4 Mar 2014 02:09:50 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 85AC8FB5EE for ; Tue, 4 Mar 2014 02:09:48 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 04 Mar 2014 02:09:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,583,1389772800"; d="scan'208";a="485706556" Received: from akashgoe-desktop.iind.intel.com ([10.223.82.34]) by fmsmga001.fm.intel.com with ESMTP; 04 Mar 2014 02:09:36 -0800 From: akash.goel@intel.com To: intel-gfx@lists.freedesktop.org Date: Tue, 4 Mar 2014 15:41:41 +0530 Message-Id: <1393927901-4664-1-git-send-email-akash.goel@intel.com> X-Mailer: git-send-email 1.8.5.2 Cc: Akash Goel Subject: [Intel-gfx] [RFC] drm/i915 : Added a new 'window size' property for connector X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.2 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 Added a new 'window size' property for connectors. This can be used to control the output window size of Panel fitter. Also addd a new mode 'Manual' to existing 'scaling mode' property. Signed-off-by: G Pallavi Signed-off-by: Akash Goel --- drivers/gpu/drm/drm_crtc.c | 1 + drivers/gpu/drm/i915/intel_dp.c | 58 ++++++++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 8 +++ drivers/gpu/drm/i915/intel_panel.c | 104 +++++++++++++++++++++++++++++++++++++ include/drm/drm_crtc.h | 3 ++ include/uapi/drm/drm_mode.h | 1 + 6 files changed, 167 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 35ea15d..1d237b5 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -123,6 +123,7 @@ static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { DRM_MODE_SCALE_FULLSCREEN, "Full" }, { DRM_MODE_SCALE_CENTER, "Center" }, { DRM_MODE_SCALE_ASPECT, "Full aspect" }, + { DRM_MODE_SCALE_MANUAL, "Manual" }, }; /* diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c512d78..c697b7a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -886,12 +886,22 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { intel_fixed_panel_mode(intel_connector->panel.fixed_mode, adjusted_mode); - if (!HAS_PCH_SPLIT(dev)) - intel_gmch_panel_fitting(intel_crtc, pipe_config, - intel_connector->panel.fitting_mode); - else - intel_pch_panel_fitting(intel_crtc, pipe_config, - intel_connector->panel.fitting_mode); + if (!HAS_PCH_SPLIT(dev)) { + if (intel_connector->panel.fitting_mode == DRM_MODE_SCALE_MANUAL) + intel_gmch_manual_panel_fitting(intel_crtc, pipe_config, + intel_connector->panel.display_window_size); + else + intel_gmch_panel_fitting(intel_crtc, pipe_config, + intel_connector->panel.fitting_mode); + } + else { + if (intel_connector->panel.fitting_mode == DRM_MODE_SCALE_MANUAL) + intel_pch_manual_panel_fitting(intel_crtc, pipe_config, + intel_connector->panel.display_window_size); + else + intel_pch_panel_fitting(intel_crtc, pipe_config, + intel_connector->panel.fitting_mode); + } } if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) @@ -3376,14 +3386,36 @@ intel_dp_set_property(struct drm_connector *connector, } if (intel_connector->panel.fitting_mode == val) { - /* the eDP scaling property is not changed */ - return 0; + /* Check if display window size has changed */ + if ((val == DRM_MODE_SCALE_MANUAL) && + intel_connector->panel.display_window_size_changed) + intel_connector->panel.display_window_size_changed = 0; + else { + /* the eDP scaling property is not changed */ + return 0; + } } intel_connector->panel.fitting_mode = val; + if (val != DRM_MODE_SCALE_MANUAL) + intel_connector->panel.display_window_size = 0; + goto done; } + if (is_edp(intel_dp) && + property == connector->dev->mode_config.window_size_property) { + if (intel_connector->panel.display_window_size == val) { + /* the eDP panel window size property is not changed */ + intel_connector->panel.display_window_size_changed = 0; + return 0; + } + intel_connector->panel.display_window_size = val; + intel_connector->panel.display_window_size_changed = 1; + + return 0; + } + return -EINVAL; done: @@ -3517,6 +3549,16 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect connector->dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_ASPECT); intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT; + + connector->dev->mode_config.window_size_property = + drm_property_create_range(connector->dev, 0, + "window size", 0, 0xFFFFFFFF); + drm_object_attach_property( + &connector->base, + connector->dev->mode_config.window_size_property, + 0); + intel_connector->panel.display_window_size = 0; + intel_connector->panel.display_window_size_changed = 0; } } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a4ffc02..5247b6b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -157,6 +157,8 @@ struct intel_panel { struct drm_display_mode *fixed_mode; struct drm_display_mode *downclock_mode; int fitting_mode; + u32 display_window_size; + bool display_window_size_changed; /* backlight */ struct { @@ -841,9 +843,15 @@ void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, void intel_pch_panel_fitting(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config, int fitting_mode); +void intel_pch_manual_panel_fitting(struct intel_crtc *intel_crtc, + struct intel_crtc_config *pipe_config, + u32 display_window_size); void intel_gmch_panel_fitting(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config, int fitting_mode); +void intel_gmch_manual_panel_fitting(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config, + u32 display_window_size); void intel_panel_set_backlight(struct intel_connector *connector, u32 level, u32 max); int intel_panel_setup_backlight(struct drm_connector *connector); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index cb05840..2965975 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -114,6 +114,48 @@ done: pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; } +void +intel_pch_manual_panel_fitting(struct intel_crtc *intel_crtc, + struct intel_crtc_config *pipe_config, + u32 display_window_size) +{ + struct drm_display_mode *adjusted_mode; + int x, y; + u32 tot_width, tot_height; + u32 dst_width, dst_height; + + adjusted_mode = &pipe_config->adjusted_mode; + + tot_width = adjusted_mode->crtc_hdisplay; + tot_height = adjusted_mode->crtc_vdisplay; + + dst_width = ((display_window_size >> 16) & 0xffff); + dst_height = (display_window_size & 0xffff); + + x = y = 0; + + if (tot_width < dst_width) { + DRM_ERROR("width is too big\n"); + return; + } else if (dst_width & 1) { + DRM_ERROR("width must be even\n"); + return; + } else if (tot_height < dst_height) { + DRM_ERROR("height is too big\n"); + return; + } else if (dst_height & 1) { + DRM_ERROR("height must be even\n"); + return; + } + + x = (adjusted_mode->hdisplay - dst_width + 1)/2; + y = (adjusted_mode->vdisplay - dst_height + 1)/2; + + pipe_config->pch_pfit.pos = (x << 16) | y; + pipe_config->pch_pfit.size = (dst_width << 16) | dst_height; + pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; +} + static void centre_horizontally(struct drm_display_mode *mode, int width) @@ -323,6 +365,68 @@ out: pipe_config->gmch_pfit.lvds_border_bits = border; } +void intel_gmch_manual_panel_fitting(struct intel_crtc *intel_crtc, + struct intel_crtc_config *pipe_config, + u32 display_window_size) +{ + u32 pfit_control = 0, border = 0; + u32 pf_horizontal_ratio, pf_vertical_ratio; + struct drm_display_mode *adjusted_mode; + u32 tot_width, tot_height; + u32 src_width, src_height; /* pipesrc.x, pipesrc.y */ + u32 dst_width, dst_height; + + adjusted_mode = &pipe_config->adjusted_mode; + + src_width = pipe_config->pipe_src_w; + src_height = pipe_config->pipe_src_h; + + tot_width = adjusted_mode->crtc_hdisplay; + tot_height = adjusted_mode->crtc_vdisplay; + + dst_width = ((display_window_size >> 16) & 0xffff); + dst_height = (display_window_size & 0xffff); + + pf_horizontal_ratio = panel_fitter_scaling(src_width, dst_width); + pf_vertical_ratio = panel_fitter_scaling(src_height, dst_height); + +/* Max Downscale ratio of 1.125, expressed in 1.12 fixed point format */ +#define MAX_DOWNSCALE_RATIO (0x9 << 9) + + if (pf_horizontal_ratio > MAX_DOWNSCALE_RATIO) { + DRM_ERROR("width is too small\n"); + return; + } else if (tot_width < dst_width) { + DRM_ERROR("width is too big\n"); + return; + } else if (dst_width & 1) { + DRM_ERROR("width must be even\n"); + return; + } else if (pf_vertical_ratio > MAX_DOWNSCALE_RATIO) { + DRM_ERROR("height is too small\n"); + return; + } else if (tot_height < dst_height) { + DRM_ERROR("height is too big\n"); + return; + } else if (dst_height & 1) { + DRM_ERROR("height must be even\n"); + return; + } + + centre_horizontally(adjusted_mode, dst_width); + centre_vertically(adjusted_mode, dst_height); + border = LVDS_BORDER_ENABLE; + + /* PFIT_SCALING_PROGRAMMED is de-featured on BYT */ + pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; + pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | PFIT_FILTER_FUZZY); + + pipe_config->gmch_pfit.control = pfit_control; + pipe_config->gmch_pfit.lvds_border_bits = border; + + return; +} + static u32 intel_panel_compute_brightness(struct intel_connector *connector, u32 val) { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f764654..625d7fd 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -902,6 +902,9 @@ struct drm_mode_config { struct drm_property *scaling_mode_property; struct drm_property *dirty_info_property; + /* Panel fitter output property */ + struct drm_property *window_size_property; + /* dumb ioctl parameters */ uint32_t preferred_depth, prefer_shadow; diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index f104c26..a187dac 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -87,6 +87,7 @@ #define DRM_MODE_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ #define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ #define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ +#define DRM_MODE_SCALE_MANUAL 4 /* User can control display window size */ /* Dithering mode options */ #define DRM_MODE_DITHERING_OFF 0