From patchwork Fri Apr 21 09:18:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liviu Dudau X-Patchwork-Id: 97885 Delivered-To: patch@linaro.org Received: by 10.140.109.52 with SMTP id k49csp226197qgf; Fri, 21 Apr 2017 02:19:59 -0700 (PDT) X-Received: by 10.84.241.194 with SMTP id t2mr13232594plm.48.1492766399514; Fri, 21 Apr 2017 02:19:59 -0700 (PDT) Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [131.252.210.177]) by mx.google.com with ESMTPS id r17si9726271pgg.119.2017.04.21.02.19.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 21 Apr 2017 02:19:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) client-ip=131.252.210.177; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4A90E6E3F9; Fri, 21 Apr 2017 09:19:00 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from cam-smtp0.cambridge.arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7193F6E131 for ; Fri, 21 Apr 2017 09:18:52 +0000 (UTC) Received: from e110455-lin.cambridge.arm.com (e110455-lin.cambridge.arm.com [10.2.131.9]) by cam-smtp0.cambridge.arm.com (8.13.8/8.13.8) with ESMTP id v3L9ImWb025801; Fri, 21 Apr 2017 10:18:49 +0100 From: Liviu Dudau To: Brian Starkey Subject: [PATCH 12/12] drm: mali-dp: Check the mclk rate and allow up/down scaling Date: Fri, 21 Apr 2017 10:18:48 +0100 Message-Id: <20170421091848.4666-13-Liviu.Dudau@arm.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170421091848.4666-1-Liviu.Dudau@arm.com> References: <20170421091848.4666-1-Liviu.Dudau@arm.com> Cc: Mihail Atanassov , Mali DP Maintainers , DRI devel X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Mihail Atanassov When downscaling, mclk needs to be sufficiently higher than pxlclk in order to be able to fetch the higher-resolution data and produce output pixels. When not scaling, or when upscaling, mclk can be equal to pxlclk. Since the driver doesn't control mclk, just ensure that the requirement is satisfied with the current clock rate. Signed-off-by: Mihail Atanassov Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_crtc.c | 23 ++++++------- drivers/gpu/drm/arm/malidp_hw.c | 70 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/arm/malidp_hw.h | 4 +++ 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index b0f0365efd23..19f1f3b34691 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -36,13 +36,6 @@ static bool malidp_crtc_mode_fixup(struct drm_crtc *crtc, long rate, req_rate = mode->crtc_clock * 1000; if (req_rate) { - rate = clk_round_rate(hwdev->mclk, req_rate); - if (rate < req_rate) { - DRM_DEBUG_DRIVER("mclk clock unable to reach %d kHz\n", - mode->crtc_clock); - return false; - } - rate = clk_round_rate(hwdev->pxlclk, req_rate); if (rate != req_rate) { DRM_DEBUG_DRIVER("pxlclk doesn't support %ld Hz\n", @@ -250,17 +243,21 @@ static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc, static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc, struct drm_crtc_state *state) { + struct malidp_drm *malidp = crtc_to_malidp_device(crtc); + struct malidp_hw_device *hwdev = malidp->dev; struct malidp_crtc_state *cs = to_malidp_crtc_state(state); struct malidp_se_config *s = &cs->scaler_config; struct drm_plane *plane; + struct videomode vm; const struct drm_plane_state *pstate; u32 h_upscale_factor = 0; /* U16.16 */ u32 v_upscale_factor = 0; /* U16.16 */ u8 scaling = cs->scaled_planes_mask; + int ret; if (!scaling) { s->scale_enable = false; - return 0; + goto mclk_calc; } /* The scaling engine can only handle one plane at a time. */ @@ -284,10 +281,6 @@ static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc, h_upscale_factor = (u32)(crtc_w / pstate->src_w); v_upscale_factor = (u32)(crtc_h / pstate->src_h); - /* Downscaling won't work when mclk == pxlclk. */ - if (!(h_upscale_factor >> 16) || !(v_upscale_factor >> 16)) - return -EINVAL; - s->enhancer_enable = ((h_upscale_factor >> 16) >= 2 || (v_upscale_factor >> 16) >= 2); @@ -323,6 +316,12 @@ static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc, s->scale_enable = true; s->hcoeff = malidp_se_select_coeffs(h_upscale_factor); s->vcoeff = malidp_se_select_coeffs(v_upscale_factor); + +mclk_calc: + drm_display_mode_to_videomode(&state->adjusted_mode, &vm); + ret = hwdev->se_calc_mclk(hwdev, s, &vm); + if (ret < 0) + return -EINVAL; return 0; } diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index e444c23a8261..28360b8542f7 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -12,6 +12,7 @@ * in an attempt to provide to the rest of the driver code a unified view */ +#include #include #include #include @@ -334,6 +335,39 @@ static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, return 0; } +static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev, + struct malidp_se_config *se_config, + struct videomode *vm) +{ + unsigned long mclk; + unsigned long pxlclk = vm->pixelclock; /* Hz */ + unsigned long htotal = vm->hactive + vm->hfront_porch + + vm->hback_porch + vm->hsync_len; + unsigned long input_size = se_config->input_w * se_config->input_h; + unsigned long a = 10; + long ret; + + /* + * mclk = max(a, 1.5) * pxlclk + * + * To avoid float calculaiton, using 15 instead of 1.5 and div by + * 10 to get mclk. + */ + if (se_config->scale_enable) { + a = 15 * input_size / (htotal * se_config->output_h); + if (a < 15) + a = 15; + } + mclk = a * pxlclk / 10; + ret = clk_get_rate(hwdev->mclk); + if (ret < mclk) { + DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n", + mclk / 1000); + return -EINVAL; + } + return ret; +} + static int malidp550_query_hw(struct malidp_hw_device *hwdev) { u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); @@ -521,6 +555,39 @@ static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, return 0; } +static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev, + struct malidp_se_config *se_config, + struct videomode *vm) +{ + unsigned long mclk; + unsigned long pxlclk = vm->pixelclock; + unsigned long htotal = vm->hactive + vm->hfront_porch + + vm->hback_porch + vm->hsync_len; + unsigned long numerator = 1, denominator = 1; + long ret; + + if (se_config->scale_enable) { + numerator = max(se_config->input_w, se_config->output_w) * + se_config->input_h; + numerator += se_config->output_w * + (se_config->output_h - + min(se_config->input_h, se_config->output_h)); + denominator = (htotal - 2) * se_config->output_h; + } + + /* mclk can't be slower than pxlclk. */ + if (numerator < denominator) + numerator = denominator = 1; + mclk = (pxlclk * numerator) / denominator; + ret = clk_get_rate(hwdev->mclk); + if (ret < mclk) { + DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n", + mclk / 1000); + return -EINVAL; + } + return ret; +} + static int malidp650_query_hw(struct malidp_hw_device *hwdev) { u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); @@ -586,6 +653,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .modeset = malidp500_modeset, .rotmem_required = malidp500_rotmem_required, .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs, + .se_calc_mclk = malidp500_se_calc_mclk, .features = MALIDP_DEVICE_LV_HAS_3_STRIDES, }, [MALIDP_550] = { @@ -622,6 +690,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .modeset = malidp550_modeset, .rotmem_required = malidp550_rotmem_required, .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, + .se_calc_mclk = malidp550_se_calc_mclk, .features = 0, }, [MALIDP_650] = { @@ -659,6 +728,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { .modeset = malidp550_modeset, .rotmem_required = malidp550_rotmem_required, .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, + .se_calc_mclk = malidp550_se_calc_mclk, .features = 0, }, }; diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index a93ae0a951a3..849ad9a30c3a 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -177,6 +177,10 @@ struct malidp_hw_device { struct malidp_se_config *se_config, struct malidp_se_config *old_config); + long (*se_calc_mclk)(struct malidp_hw_device *hwdev, + struct malidp_se_config *se_config, + struct videomode *vm); + u8 features; u8 min_line_size;