From patchwork Wed Oct 16 14:31:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838548 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B5E2AD2A524 for ; Wed, 16 Oct 2024 14:31:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4C99E10E71D; Wed, 16 Oct 2024 14:31:40 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="NPlyR9qf"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1AF8210E71D for ; Wed, 16 Oct 2024 14:31:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089100; x=1760625100; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=nlyRcJy+tBDiZa+mUH73YFxbdmtc4Q1+a7dW4T5iuDg=; b=NPlyR9qfY+XKnTibXOPELYOKUduoZQ4wHBnD43zfDMzql/fPNEg/BL9g 3dxJ1aokW0+KLdTpUHBj9UamCKPOJuMiqfB5oHSVYlVlLENyDoFfv3eWK 8xGJWfbY0DJP6B3kP+1XrsBTqzizlUDXm74gjuigKVpUpVM9y6HK8wyLV n2zs/JMZwn0eayWBRoHOFC7SgdlcCP9br7uqI4wcvT/qT0DeDquWVS3Sa 438zPu9QzzDTlILgSTPZkONBp68utvf0k6hV8yCF/Gn0/paLlNcbwz4ob Gz4AZaZANCpMQjBObLvdCI6mYBoRf7C0pNFZPBKBujy7G2dv9VagxC0Xn Q==; X-CSE-ConnectionGUID: A2bQ3JXFQeGmdeTi7HdS0Q== X-CSE-MsgGUID: E6W3MH7uRf+RhgaXmckaSw== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630696" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630696" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:40 -0700 X-CSE-ConnectionGUID: LVk7GKYYRIO/KSHbL5Rzww== X-CSE-MsgGUID: GoQ4X3YOQMyrpp0xALyfNw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288370" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:38 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:37 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 1/9] drm/i915/pfit: Check pipe source size against pfit limits on ILK-BDW Date: Wed, 16 Oct 2024 17:31:26 +0300 Message-ID: <20241016143134.26903-2-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä The ILK-BDW panel fitter imposes extra limits on the maximum pipe source size we can use. Check for that. Only HSW/BDW are really affected by this since on older platforms the max hdisplay/vdisplay matches the max PIPESRC. But we'll put in the limits for all the platforms just to keep things clear. Note that pch_panel_fitting() is also used on SKL+, but we'll skip the checks for those as it's all supposed to be handled in the unified scaler code. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_panel.c | 52 +++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 71454ddef20f..b77017144818 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -383,15 +383,54 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, "current (BIOS)"); } +static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + int max_src_w, max_src_h; + + if (DISPLAY_VER(display) >= 8) { + max_src_w = 4096; + max_src_h = 4096; + } else if (DISPLAY_VER(display) >= 7) { + /* + * PF0 7x5 capable + * PF1 3x3 capable (could be switched to 7x5 + * mode on HSW when PF2 unused) + * PF2 3x3 capable + * + * This assumes we use a 1:1 mapping between pipe and PF. + */ + max_src_w = crtc->pipe == PIPE_A ? 4096 : 2048; + max_src_h = 4096; + } else { + max_src_w = 4096; + max_src_h = 4096; + } + + if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] source size (%dx%d) exceeds pfit max (%dx%d)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, pipe_src_h, max_src_w, max_src_h); + return -EINVAL; + } + + return 0; +} + /* adjusted_mode has been preset to be the panel's fixed mode */ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_display *display = to_intel_display(crtc_state); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - int x, y, width, height; + int ret, x, y, width, height; /* Native modes don't need fitting */ if (adjusted_mode->crtc_hdisplay == pipe_src_w && @@ -453,6 +492,17 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, x, y, width, height); crtc_state->pch_pfit.enabled = true; + /* + * SKL+ have unified scalers for pipes/planes so the + * checks are done in a single place for all scalers. + */ + if (DISPLAY_VER(display) >= 9) + return 0; + + ret = intel_pch_pfit_check_src_size(crtc_state); + if (ret) + return ret; + return 0; } From patchwork Wed Oct 16 14:31:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838549 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4F49CD2A520 for ; Wed, 16 Oct 2024 14:31:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EFDE310E71E; Wed, 16 Oct 2024 14:31:43 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="T7kyKF6o"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id C5FF610E71E for ; Wed, 16 Oct 2024 14:31:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089103; x=1760625103; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=vjIZscGEj2vwRQShtLPLXyVxulH7Wy6RfotH+snPOWc=; b=T7kyKF6o9U0HPAiY1DaaK6D/HxGYDa5uq+JY2hflUx2U5ZzMic5qzdOi +OObO0JMi3aTwfvAZuzkm4X0VHgzgyLnWLzum0/Lntfo0MMrl6SPSTg9X 0kiyTBFMxAYMl5Vnwb8iF1we4lrPf/PK5uDf720UEYy+hJ9xAMAI8ix8G H6VdH6nmQlhlzaHTE+6KaymeAz61tuo/uQJentV0DLZ8+7DJVIcvhI68o 6E1XuNDw1wFLpskl9+nft4V8UWmMbJloz54oDBdh9yzVGOuFUVCLN8EYR sn7bJdAOismlat9ysbNRKm+1p1njvimC3pAS4RBTnsS2jPN3JLv888oss g==; X-CSE-ConnectionGUID: gRt4Z8XlRymWtZq+jtJyHQ== X-CSE-MsgGUID: MUKEDInfQ7+7B7QOlwbqAw== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630702" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630702" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:43 -0700 X-CSE-ConnectionGUID: st21jazdRRmG9tVwMHU0Zw== X-CSE-MsgGUID: g4rYvU0GR2uDqCeMzfjQGw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288374" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:41 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:40 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 2/9] drm/i915/pfit: Check pfit scaling factors on ILK-BDW Date: Wed, 16 Oct 2024 17:31:27 +0300 Message-ID: <20241016143134.26903-3-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä Make sure we're not exceeding the max scaling factors for the panel fitter on ILK-BDW. SKL+ is skipped here since this is all supposed to be handled by the unified scaler code. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_panel.c | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index b77017144818..fb7def772376 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -421,6 +421,41 @@ static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_sta return 0; } +static int intel_pch_pfit_check_scaling(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_rect *dst = &crtc_state->pch_pfit.dst; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + int hscale, vscale, max_scale = 0x12000; /* 1.125 */ + struct drm_rect src; + + drm_rect_init(&src, 0, 0, pipe_src_w << 16, pipe_src_h << 16); + + hscale = drm_rect_calc_hscale(&src, dst, 0, max_scale); + if (hscale < 0) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) exceeds max (0x%x)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, drm_rect_width(dst), + max_scale); + return hscale; + } + + vscale = drm_rect_calc_vscale(&src, dst, 0, max_scale); + if (vscale < 0) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) exceeds max (0x%x)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_h, drm_rect_height(dst), + max_scale); + return vscale; + } + + return 0; +} + /* adjusted_mode has been preset to be the panel's fixed mode */ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -503,6 +538,10 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, if (ret) return ret; + ret = intel_pch_pfit_check_scaling(crtc_state); + if (ret) + return ret; + return 0; } From patchwork Wed Oct 16 14:31:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838550 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 60F3FD2A523 for ; Wed, 16 Oct 2024 14:31:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0A8EF10E728; Wed, 16 Oct 2024 14:31:46 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="CYNA+/HR"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id 85C0710E721 for ; Wed, 16 Oct 2024 14:31:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089105; x=1760625105; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=WEpHR7BZB5gQ/HEMy/vyDMsj5UQow1xInIh9TIXYXyg=; b=CYNA+/HRU0FUj8nFRZsTuAH6gY/Mraj8sYvjfExxozaeX7n5erpwitlq 1vkTV3ehJOSo1mAHZG5V112GOX1DQKzEFQdmzutgxAcKve5dq/fSALWCw eNC4lF+qYvFcLZaMtxWZgi2h7kZqjJSUTF8Ab0moZQNnpPjZPekwrNbtP krw2CfBEJJ7prTdRXYmPHgiE7woxf0r8Cs+MrA5ikO6tfsuuZB4KWeufr cQtlJTnAuSCGFZSrsgbYYkJDpil+7ql7Xu2lXjcR5QCoEh8mJPbbZUWWM v0KPy4g0tqLtZcAAS7QnMdDZpEEFgURzcYmVGpbH8ZJ7mHikrlBI62UyX g==; X-CSE-ConnectionGUID: m6lEkr88StCr0uqksdDQzQ== X-CSE-MsgGUID: /kxVEZ53SVOQpHDtcVIH3A== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630710" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630710" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:45 -0700 X-CSE-ConnectionGUID: B3W9a7b8SxeWsEfXNQFQdg== X-CSE-MsgGUID: UFkKBGasRey3lYoS+/wvpA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288376" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:43 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:42 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 3/9] drm/i915/pfit: Reject pfit downscaling for GMCH platforms Date: Wed, 16 Oct 2024 17:31:28 +0300 Message-ID: <20241016143134.26903-4-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä Gen2/3 pfit doesn't support downscaling at all, so reject it. On i965+ downscaling is supported by the hardware (max scale factor < 2.0), but as downscaling increases the effective pixel rate we can't safely allow it unless intel_crtc_compute_pixel_rate() gets fixed. Probably the best solution would be to calculate (at least an apporiximate) pfit destination window and use ilk_pipe_pixel_rate() for all platforms. For now reject downscaling on all gmch platforms. The intel ddx has a similar check for this in userspace, modesetting ddx does not. And presumably wayland compositors also do not make such assumptions in userspace. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_panel.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index fb7def772376..89cac3b3fd02 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -681,6 +681,7 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; @@ -693,6 +694,25 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, adjusted_mode->crtc_vdisplay == pipe_src_h) goto out; + /* + * TODO: implement downscaling for i965+. Need to account + * for downscaling in intel_crtc_compute_pixel_rate(). + */ + if (adjusted_mode->crtc_hdisplay < pipe_src_w) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) not supported\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, adjusted_mode->crtc_hdisplay); + return -EINVAL; + } + if (adjusted_mode->crtc_vdisplay < pipe_src_h) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) not supported\n", + crtc->base.base.id, crtc->base.name, + pipe_src_h, adjusted_mode->crtc_vdisplay); + return -EINVAL; + } + switch (conn_state->scaling_mode) { case DRM_MODE_SCALE_CENTER: /* From patchwork Wed Oct 16 14:31:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838551 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B616D2A521 for ; Wed, 16 Oct 2024 14:31:49 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0E16B10E71F; Wed, 16 Oct 2024 14:31:49 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="NuXIY1FO"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id 52BB810E721 for ; Wed, 16 Oct 2024 14:31:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089108; x=1760625108; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=rILhbZatsP5gBsAfURazEO8AFYKP1pdrMZsS0VRjhdo=; b=NuXIY1FOSvuPd/gEb0djTX4YUnuVTn17vFQfXXTcQoexA7gncbcOQLqn gUAkJ0YdwSOSG7IZMr5r+2gV2w51JfFraMs6oMpzMu9jLXCKHZaAjT4PZ J3c1v5TRMtR7M+Dvpd7s9KwoubBHfzVsV3gH3HV2tkfDfc6X689P1HMqi qaVXw/SBWg4I5jxjnd/F/U9qMu9RK9NpR1d6C4oE/gvOZPGvoQ131iTou JZhJRzNiRwhiwu5gMcaARxNAE2zkENPIv/Cpc1spvxMQmtnF5Nn6jeHqv xSkYZsY9HhPHEJHc9YvTsEwM7TCX6G4ptQPoeQTW5CwMh67pQ71Z0zPns A==; X-CSE-ConnectionGUID: iQKit0VpRruYMQFdnQbtaw== X-CSE-MsgGUID: 97zncRSxSr2kZgnE5vf8gA== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630717" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630717" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:48 -0700 X-CSE-ConnectionGUID: UctYDYsERz+MOnf5Kx+FaQ== X-CSE-MsgGUID: lfAnJC7dTyi8PXxLz6BS3g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288381" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:46 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:45 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 4/9] drm/i915/pfit: Check pfit minimum timings in pre-SKL Date: Wed, 16 Oct 2024 17:31:29 +0300 Message-ID: <20241016143134.26903-5-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä Transcoder hdisplay/vdisplay have documented minimum limits when using the panel fitter. Enforce those limits for all pre-SKL platforms. SKL+ handles everything in the unified scaler code instead. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_panel.c | 59 +++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 89cac3b3fd02..dc843892b01b 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -456,6 +456,24 @@ static int intel_pch_pfit_check_scaling(const struct intel_crtc_state *crtc_stat return 0; } +static int intel_pch_pfit_check_timings(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + + if (adjusted_mode->crtc_vdisplay < 7) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n", + crtc->base.base.id, crtc->base.name, + adjusted_mode->crtc_vdisplay, 7); + return -EINVAL; + } + + return 0; +} + /* adjusted_mode has been preset to be the panel's fixed mode */ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -542,6 +560,10 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, if (ret) return ret; + ret = intel_pch_pfit_check_timings(crtc_state); + if (ret) + return ret; + return 0; } @@ -678,6 +700,38 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, } } +static int intel_gmch_pfit_check_timings(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int min; + + if (DISPLAY_VER(display) >= 4) + min = 3; + else + min = 2; + + if (adjusted_mode->crtc_hdisplay < min) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] horizontal active (%d) below minimum (%d) for pfit\n", + crtc->base.base.id, crtc->base.name, + adjusted_mode->crtc_hdisplay, min); + return -EINVAL; + } + + if (adjusted_mode->crtc_vdisplay < min) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n", + crtc->base.base.id, crtc->base.name, + adjusted_mode->crtc_vdisplay, min); + return -EINVAL; + } + + return 0; +} + static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { @@ -772,7 +826,10 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios; crtc_state->gmch_pfit.lvds_border_bits = border; - return 0; + if ((pfit_control & PFIT_ENABLE) == 0) + return 0; + + return intel_gmch_pfit_check_timings(crtc_state); } int intel_panel_fitting(struct intel_crtc_state *crtc_state, From patchwork Wed Oct 16 14:31:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838552 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7756FD2A521 for ; Wed, 16 Oct 2024 14:31:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1D5F310E17B; Wed, 16 Oct 2024 14:31:52 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="b8llPkpp"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1389F10E723 for ; Wed, 16 Oct 2024 14:31:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089111; x=1760625111; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=fXEF7wMZKSbRQWPe77V8ulHFcadx9k3qF3Qu/sb9Kv0=; b=b8llPkppYe7sV0H+oa6CHwcvYoc7B0yhvhR1oYdJG/WfoPPMF7onVCpD IhJRzcECBOTrBEVQ8UzkSKJKxCT1iwEfCZ+FRcT+6eQRmUHxfEIhge2aj KArcgDhQYj9M+R0Os2DmeNda3CvkaSKNRLJ5zs6MffeV1sHnJz1PfTrg2 NSzvugPvs/BoFsdlpJECZXQpxtJpIHHX0i1KccQh2wveN9SkYx2r3/jyl vBtS3Ynn5ntkaKn/HiC+uhdOSQi/n/slu8UjWeMVhtQbE3v/TuX8gYpww 0MEyehgMK1sW5KVJB2zu0xzl+5DrimDta1V0jVwEnYB+ZrXMWoY1QapkS g==; X-CSE-ConnectionGUID: AbgZ3q+ZTMuUi8f9Jx8hqw== X-CSE-MsgGUID: Y6w3Qef0Q22W3/IZMLdbig== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630721" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630721" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:51 -0700 X-CSE-ConnectionGUID: FK61gxIFTDyRTAETVaKatA== X-CSE-MsgGUID: dRrJW9VXSiuqFiGb+CRgtw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288385" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:49 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:48 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 5/9] drm/i915/pfit: Reject cloning when using pfit on ILK-BDW Date: Wed, 16 Oct 2024 17:31:30 +0300 Message-ID: <20241016143134.26903-6-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä The panel fitter lives inside the pipe and so would affect all cloned outputs. However the relevant properties (scaling mode, TV margins) are per-connector so we could end up with a situation where each cloned output wants a different pfit configuration. Let's just reject pfit usage with cloning entirely. Currently not an issue as we don't yet expose the TV margin properties, but if/when we add those to HDMI we could end up in this situation. For eDP/DP we don't support cloning anyyway. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_panel.c | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index dc843892b01b..593e41907d53 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -474,6 +474,29 @@ static int intel_pch_pfit_check_timings(const struct intel_crtc_state *crtc_stat return 0; } +static int intel_pch_pfit_check_cloning(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + /* + * The panel fitter is in the pipe and thus would affect every + * cloned output. The relevant properties (scaling mode, TV + * margins) are per-connector so we'd have to make sure each + * output sets them up identically. Seems like a very niche use + * case so let's just reject cloning entirely when pfit is used. + */ + if (crtc_state->uapi.encoder_mask && + !is_power_of_2(crtc_state->uapi.encoder_mask)) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] no pfit when cloning\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + + return 0; +} + /* adjusted_mode has been preset to be the panel's fixed mode */ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -564,6 +587,10 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, if (ret) return ret; + ret = intel_pch_pfit_check_cloning(crtc_state); + if (ret) + return ret; + return 0; } From patchwork Wed Oct 16 14:31:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838553 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6DA3FD2A520 for ; Wed, 16 Oct 2024 14:31:55 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1A89910E726; Wed, 16 Oct 2024 14:31:55 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="gVR4UFqT"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id E4B7710E723 for ; Wed, 16 Oct 2024 14:31:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089114; x=1760625114; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=eZKq3gAk6FfVwfFCJUWurod8gRTcyQXr4C4sO/4kvHY=; b=gVR4UFqTJi8wL4q10ZWoLjYFhw4HuansLEj1fBpM1NDDk4EOLdCZBqWf m/Hrdc3xBAJIpFJ+hyE1SgtSdomDRz+OV9enrH0GJCsLxkBwAOWwEpweM o5RV2jx3lIRniVQwasE/YFUnSrtlH/iyfPYSrxya9TSPbG9RS9fkUnyAj dWKExSkCCDGTVqdcJHj/FZCB6iLDP0tQHZtHCtNNXXaWjYC9NYg7khLlR uHnH5KPhiNML4KxXE/5EneksNGekfMucX1xrEABCaSBBgTYJp5evANJFB q1grwdDCFRNyIUVoupyxcjXMiNWaNxrUGpk7yYpt3jcGMmIzyY5JmYqeG A==; X-CSE-ConnectionGUID: KO0QnQI5THWKcepvsmx84Q== X-CSE-MsgGUID: 0yf5H2xPQGazHRJ8R+TG5Q== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630725" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630725" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:54 -0700 X-CSE-ConnectionGUID: x1XouKQLSjWPJw8pXje2BA== X-CSE-MsgGUID: 8l+tfMYUQDq/06AGe8yjHw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288389" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:52 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:51 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 6/9] drm/i915/pfit: Check pfit destination window on ILK-BDW Date: Wed, 16 Oct 2024 17:31:31 +0300 Message-ID: <20241016143134.26903-7-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä The ILK-BDW panel fitter has several restrictions on the destination window size. Check for those and reject the configuration if things aren't entirely proper. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_panel.c | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 593e41907d53..d66ce8537f7d 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -383,6 +383,57 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, "current (BIOS)"); } +static int intel_pch_pfit_check_dst_window(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + const struct drm_rect *dst = &crtc_state->pch_pfit.dst; + int width = drm_rect_width(dst); + int height = drm_rect_height(dst); + int x = dst->x1; + int y = dst->y1; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE && + (y & 1 || height & 1)) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") misaligned for interlaced output\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + /* + * "Restriction : When pipe scaling is enabled, the scaled + * output must equal the pipe active area, so Pipe active + * size = (2 * PF window position) + PF window size." + * + * The vertical direction seems more forgiving than the + * horizontal direction, but still has some issues so + * let's follow the same hard rule for both. + */ + if (adjusted_mode->crtc_hdisplay != 2 * x + width || + adjusted_mode->crtc_vdisplay != 2 * y + height) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") not centered\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + /* + * "Restriction : The X position must not be programmed + * to be 1 (28:16=0 0000 0000 0001b)." + */ + if (x == 1) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") badly positioned\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + return 0; +} + static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); @@ -575,6 +626,10 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, if (DISPLAY_VER(display) >= 9) return 0; + ret = intel_pch_pfit_check_dst_window(crtc_state); + if (ret) + return ret; + ret = intel_pch_pfit_check_src_size(crtc_state); if (ret) return ret; From patchwork Wed Oct 16 14:31:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838554 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AE973D2A520 for ; Wed, 16 Oct 2024 14:31:58 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5AA1F10E720; Wed, 16 Oct 2024 14:31:58 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="XKTwUTod"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id BB09A10E72D for ; Wed, 16 Oct 2024 14:31:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089117; x=1760625117; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=5eY77/1OIZXR6ceUbCJEM4l2yf1eiBrKDbq+3mnwaAU=; b=XKTwUTodUZcUblEdHEc12ops9Xy4A4FxFbK8grkDaaKaFDyr1zeF2qlv ccK3eEJVz+g8wo+2j0FGFNJcTUJ4/G+pMEr7zZeJqG5WCNIcB0K0UFy7E PFuwQtxPDQouAhpw45+RVcaMEK5mrNmrFD+E9hMaY30tCQnd1cb7lRWkc 5kvXsBz7FbpTQzNASqbNOXPTbS9Tho3vUVUqF2e79lGsg4E/p5ATkDrBk GDTCZ8QfaL6atsgTmRGDZpR9y+eX0Q62zDmAULEC5PlfEQqUpymBVxxpB WWi3BQVPl2aJ6QTSPKvnxnw1MHaPMP3blRkkWDWlXE3RsZ8t4fLG8zCJg w==; X-CSE-ConnectionGUID: irC9vJUlR+mQNiODKP+GPA== X-CSE-MsgGUID: LBONI8IlR6KsaoTJR2RCJQ== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630728" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630728" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:56 -0700 X-CSE-ConnectionGUID: dYCGuILSQmWsPHWlH2v2iQ== X-CSE-MsgGUID: BvSfpgC6RMyhxo1RhGO44w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288393" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:54 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:53 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 7/9] drm/i915/panel: Convert panel code to intel_display Date: Wed, 16 Oct 2024 17:31:32 +0300 Message-ID: <20241016143134.26903-8-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä struct intel_display will replace struct drm_i915_private as the main thing for display code. Convert the panel code to use it (as much as possible at this stage). Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 3 +- drivers/gpu/drm/i915/display/intel_dpll.c | 27 ++++++++---- drivers/gpu/drm/i915/display/intel_panel.c | 44 +++++++++---------- drivers/gpu/drm/i915/display/intel_panel.h | 4 +- .../gpu/drm/i915/display/intel_pch_refclk.c | 9 ++-- 5 files changed, 47 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index f73d576fd99e..045ad6539c65 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2003,12 +2003,13 @@ intel_c10pll_tables_get(struct intel_crtc_state *crtc_state, static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll; int i; if (intel_crtc_has_dp_encoder(crtc_state)) { - if (intel_panel_use_ssc(i915)) { + if (intel_panel_use_ssc(display)) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); pll_state->ssc_enabled = diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index b679c5391fe6..c0a3c4b53b0a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1003,6 +1003,7 @@ static u32 i9xx_dpll(const struct intel_crtc_state *crtc_state, const struct dpll *clock, const struct dpll *reduced_clock) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dpll; @@ -1061,7 +1062,7 @@ static u32 i9xx_dpll(const struct intel_crtc_state *crtc_state, if (crtc_state->sdvo_tv_clock) dpll |= PLL_REF_INPUT_TVCLKINBC; else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv)) + intel_panel_use_ssc(display)) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; @@ -1095,6 +1096,7 @@ static u32 i8xx_dpll(const struct intel_crtc_state *crtc_state, const struct dpll *clock, const struct dpll *reduced_clock) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dpll; @@ -1131,7 +1133,7 @@ static u32 i8xx_dpll(const struct intel_crtc_state *crtc_state, dpll |= DPLL_DVO_2X_MODE; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv)) + intel_panel_use_ssc(display)) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; @@ -1237,11 +1239,12 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, static int ilk_fb_cb_factor(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && - ((intel_panel_use_ssc(i915) && i915->display.vbt.lvds_ssc_freq == 100000) || + ((intel_panel_use_ssc(display) && i915->display.vbt.lvds_ssc_freq == 100000) || (HAS_PCH_IBX(i915) && intel_is_dual_link_lvds(i915)))) return 25; @@ -1271,6 +1274,7 @@ static u32 ilk_dpll(const struct intel_crtc_state *crtc_state, const struct dpll *clock, const struct dpll *reduced_clock) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dpll; @@ -1332,7 +1336,7 @@ static u32 ilk_dpll(const struct intel_crtc_state *crtc_state, WARN_ON(reduced_clock->p2 != clock->p2); if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv)) + intel_panel_use_ssc(display)) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; @@ -1356,6 +1360,7 @@ static void ilk_compute_dpll(struct intel_crtc_state *crtc_state, static int ilk_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(state); struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1368,7 +1373,7 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, return 0; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_panel_use_ssc(dev_priv)) { + if (intel_panel_use_ssc(display)) { drm_dbg_kms(&dev_priv->drm, "using SSC reference clock of %d kHz\n", dev_priv->display.vbt.lvds_ssc_freq); @@ -1532,6 +1537,7 @@ static int vlv_crtc_compute_clock(struct intel_atomic_state *state, static int g4x_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(state); struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1539,7 +1545,7 @@ static int g4x_crtc_compute_clock(struct intel_atomic_state *state, int refclk = 96000; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_panel_use_ssc(dev_priv)) { + if (intel_panel_use_ssc(display)) { refclk = dev_priv->display.vbt.lvds_ssc_freq; drm_dbg_kms(&dev_priv->drm, "using SSC reference clock of %d kHz\n", @@ -1581,6 +1587,7 @@ static int g4x_crtc_compute_clock(struct intel_atomic_state *state, static int pnv_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(state); struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1588,7 +1595,7 @@ static int pnv_crtc_compute_clock(struct intel_atomic_state *state, int refclk = 96000; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_panel_use_ssc(dev_priv)) { + if (intel_panel_use_ssc(display)) { refclk = dev_priv->display.vbt.lvds_ssc_freq; drm_dbg_kms(&dev_priv->drm, "using SSC reference clock of %d kHz\n", @@ -1619,6 +1626,7 @@ static int pnv_crtc_compute_clock(struct intel_atomic_state *state, static int i9xx_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(state); struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1626,7 +1634,7 @@ static int i9xx_crtc_compute_clock(struct intel_atomic_state *state, int refclk = 96000; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_panel_use_ssc(dev_priv)) { + if (intel_panel_use_ssc(display)) { refclk = dev_priv->display.vbt.lvds_ssc_freq; drm_dbg_kms(&dev_priv->drm, "using SSC reference clock of %d kHz\n", @@ -1659,6 +1667,7 @@ static int i9xx_crtc_compute_clock(struct intel_atomic_state *state, static int i8xx_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(state); struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1666,7 +1675,7 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state, int refclk = 48000; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_panel_use_ssc(dev_priv)) { + if (intel_panel_use_ssc(display)) { refclk = dev_priv->display.vbt.lvds_ssc_freq; drm_dbg_kms(&dev_priv->drm, "using SSC reference clock of %d kHz\n", diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index d66ce8537f7d..7fa0a54a3d3a 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -45,10 +45,8 @@ #include "intel_quirks.h" #include "intel_vrr.h" -bool intel_panel_use_ssc(struct drm_i915_private *i915) +bool intel_panel_use_ssc(struct intel_display *display) { - struct intel_display *display = &i915->display; - if (display->params.panel_use_ssc >= 0) return display->params.panel_use_ssc != 0; return display->vbt.lvds_use_ssc && @@ -252,7 +250,7 @@ int intel_panel_compute_config(struct intel_connector *connector, static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); const struct drm_display_mode *preferred_mode = intel_panel_preferred_fixed_mode(connector); struct drm_display_mode *mode, *next; @@ -261,7 +259,7 @@ static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connect if (!is_alt_fixed_mode(mode, preferred_mode)) continue; - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] using alternate EDID fixed mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, DRM_MODE_ARG(mode)); @@ -272,7 +270,7 @@ static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connect static void intel_panel_add_edid_preferred_mode(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct drm_display_mode *scan, *fixed_mode = NULL; if (list_empty(&connector->base.probed_modes)) @@ -290,7 +288,7 @@ static void intel_panel_add_edid_preferred_mode(struct intel_connector *connecto fixed_mode = list_first_entry(&connector->base.probed_modes, typeof(*fixed_mode), head); - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] using %s EDID fixed mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, fixed_mode->type & DRM_MODE_TYPE_PREFERRED ? "preferred" : "first", @@ -303,16 +301,16 @@ static void intel_panel_add_edid_preferred_mode(struct intel_connector *connecto static void intel_panel_destroy_probed_modes(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct drm_display_mode *mode, *next; list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] not using EDID mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, DRM_MODE_ARG(mode)); list_del(&mode->head); - drm_mode_destroy(&i915->drm, mode); + drm_mode_destroy(display->drm, mode); } } @@ -329,7 +327,7 @@ static void intel_panel_add_fixed_mode(struct intel_connector *connector, struct drm_display_mode *fixed_mode, const char *type) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct drm_display_info *info = &connector->base.display_info; if (!fixed_mode) @@ -340,7 +338,7 @@ static void intel_panel_add_fixed_mode(struct intel_connector *connector, info->width_mm = fixed_mode->width_mm; info->height_mm = fixed_mode->height_mm; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n", + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, type, DRM_MODE_ARG(fixed_mode)); @@ -349,7 +347,7 @@ static void intel_panel_add_fixed_mode(struct intel_connector *connector, void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); const struct drm_display_mode *mode; mode = connector->panel.vbt.lfp_vbt_mode; @@ -357,13 +355,13 @@ void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector) return; intel_panel_add_fixed_mode(connector, - drm_mode_duplicate(&i915->drm, mode), + drm_mode_duplicate(display->drm, mode), "VBT LFP"); } void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); const struct drm_display_mode *mode; mode = connector->panel.vbt.sdvo_lvds_vbt_mode; @@ -371,7 +369,7 @@ void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector) return; intel_panel_add_fixed_mode(connector, - drm_mode_duplicate(&i915->drm, mode), + drm_mode_duplicate(display->drm, mode), "VBT SDVO"); } @@ -819,7 +817,6 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); @@ -861,7 +858,7 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, break; case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ - if (DISPLAY_VER(dev_priv) >= 4) + if (DISPLAY_VER(display) >= 4) i965_scale_aspect(crtc_state, &pfit_control); else i9xx_scale_aspect(crtc_state, &pfit_control, @@ -875,7 +872,7 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, if (pipe_src_h != adjusted_mode->crtc_vdisplay || pipe_src_w != adjusted_mode->crtc_hdisplay) { pfit_control |= PFIT_ENABLE; - if (DISPLAY_VER(dev_priv) >= 4) + if (DISPLAY_VER(display) >= 4) pfit_control |= PFIT_SCALING_AUTO; else pfit_control |= (PFIT_VERT_AUTO_SCALE | @@ -891,7 +888,7 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, /* 965+ wants fuzzy fitting */ /* FIXME: handle multiple panels by failing gracefully */ - if (DISPLAY_VER(dev_priv) >= 4) + if (DISPLAY_VER(display) >= 4) pfit_control |= PFIT_PIPE(crtc->pipe) | PFIT_FILTER_FUZZY; out: @@ -901,7 +898,7 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, } /* Make sure pre-965 set dither correctly for 18bpp panels. */ - if (DISPLAY_VER(dev_priv) < 4 && crtc_state->pipe_bpp == 18) + if (DISPLAY_VER(display) < 4 && crtc_state->pipe_bpp == 18) pfit_control |= PFIT_PANEL_8TO6_DITHER_ENABLE; crtc_state->gmch_pfit.control = pfit_control; @@ -917,10 +914,9 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, int intel_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc_state); - if (HAS_GMCH(i915)) + if (HAS_GMCH(display)) return gmch_panel_fitting(crtc_state, conn_state); else return pch_panel_fitting(crtc_state, conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 15a8c897b33f..d6dd88473555 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -14,9 +14,9 @@ struct drm_connector; struct drm_connector_state; struct drm_display_mode; struct drm_edid; -struct drm_i915_private; struct intel_connector; struct intel_crtc_state; +struct intel_display; struct intel_encoder; void intel_panel_init_alloc(struct intel_connector *connector); @@ -25,7 +25,7 @@ int intel_panel_init(struct intel_connector *connector, void intel_panel_fini(struct intel_connector *connector); enum drm_connector_status intel_panel_detect(struct drm_connector *connector, bool force); -bool intel_panel_use_ssc(struct drm_i915_private *i915); +bool intel_panel_use_ssc(struct intel_display *display); const struct drm_display_mode * intel_panel_preferred_fixed_mode(struct intel_connector *connector); const struct drm_display_mode * diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 713cfba71475..84c55971e91a 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -491,6 +491,7 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; struct intel_encoder *encoder; struct intel_shared_dpll *pll; int i; @@ -572,11 +573,11 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv) if (has_panel) { final |= DREF_SSC_SOURCE_ENABLE; - if (intel_panel_use_ssc(dev_priv) && can_ssc) + if (intel_panel_use_ssc(display) && can_ssc) final |= DREF_SSC1_ENABLE; if (has_cpu_edp) { - if (intel_panel_use_ssc(dev_priv) && can_ssc) + if (intel_panel_use_ssc(display) && can_ssc) final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; else final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; @@ -604,7 +605,7 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv) val |= DREF_SSC_SOURCE_ENABLE; /* SSC must be turned on before enabling the CPU output */ - if (intel_panel_use_ssc(dev_priv) && can_ssc) { + if (intel_panel_use_ssc(display) && can_ssc) { drm_dbg_kms(&dev_priv->drm, "Using SSC on panel\n"); val |= DREF_SSC1_ENABLE; } else { @@ -620,7 +621,7 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv) /* Enable CPU source on CPU attached eDP */ if (has_cpu_edp) { - if (intel_panel_use_ssc(dev_priv) && can_ssc) { + if (intel_panel_use_ssc(display) && can_ssc) { drm_dbg_kms(&dev_priv->drm, "Using SSC on eDP\n"); val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; From patchwork Wed Oct 16 14:31:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838555 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 83851D2A521 for ; Wed, 16 Oct 2024 14:32:01 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2E6CD10E727; Wed, 16 Oct 2024 14:32:01 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="dnJLwo5J"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id CCB7F10E722 for ; Wed, 16 Oct 2024 14:31:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089120; x=1760625120; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=3xUrPVgxZqGUg3wifGitG5AF+iF59OchKv0tIqour1g=; b=dnJLwo5JXz7mpNvyR0kp9eNVoaVwAVZz6Wwp7RrzhGNrk8j4u1G5mWX2 WVZJtGkFmyOzqgy9DhJK/BA/YbLvZ36pNvfngq1xxvVEQb0Olnsb1qkA5 esnQHKHLpFCmmTOnqIXko5htNAcu2AjOYCdloNNN2RFcvpQ4HN4EEtp8h O8rhGTVELolltHwjh1qLtuMElmSFoGrd+OrWDrP+MKZMW3tdn4z+4L9b/ KXqxjt6EiaZJSrn+SSggf5IfsPU/s2TZV5PF4wa+ySVyN3MvV1NTIkwc5 D+AgyEBT1hrB2oIEofF7rDGcwueKceWa/972uE+gdRQCaf9VuZO41SovE g==; X-CSE-ConnectionGUID: NC9qA/ZNSvSYCCZ9duSK5Q== X-CSE-MsgGUID: zUYu4pFKQguBvIpG5LtzYQ== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630738" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630738" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:31:59 -0700 X-CSE-ConnectionGUID: 1QYIJgHyQrmXiEZH5MN/gA== X-CSE-MsgGUID: rzRVZHKjQ++HvT3tqRUTEA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288402" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:31:57 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:56 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 8/9] drm/i915/pfit: Extract intel_pfit.c Date: Wed, 16 Oct 2024 17:31:33 +0300 Message-ID: <20241016143134.26903-9-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä The panel fitter code doesn't really have much to do with the rest of intel_panel.c, so extract it all into its own file. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/icl_dsi.c | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 1 + drivers/gpu/drm/i915/display/intel_hdmi.c | 1 + drivers/gpu/drm/i915/display/intel_lvds.c | 1 + drivers/gpu/drm/i915/display/intel_panel.c | 546 +------------------- drivers/gpu/drm/i915/display/intel_panel.h | 2 - drivers/gpu/drm/i915/display/intel_pfit.c | 554 +++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_pfit.h | 15 + drivers/gpu/drm/i915/display/vlv_dsi.c | 1 + drivers/gpu/drm/xe/Makefile | 1 + 11 files changed, 578 insertions(+), 546 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_pfit.c create mode 100644 drivers/gpu/drm/i915/display/intel_pfit.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index e033bcaef4f3..31710d98cad5 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -339,6 +339,7 @@ i915-y += \ display/intel_lspcon.o \ display/intel_lvds.o \ display/intel_panel.o \ + display/intel_pfit.o \ display/intel_pps.o \ display/intel_qp_tables.o \ display/intel_sdvo.o \ diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 87a27d91d15d..115d79c80b9a 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -46,6 +46,7 @@ #include "intel_dsi.h" #include "intel_dsi_vbt.h" #include "intel_panel.h" +#include "intel_pfit.h" #include "intel_vdsc.h" #include "intel_vdsc_regs.h" #include "skl_scaler.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6b27fabd61c3..7e02da8f84a7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -83,6 +83,7 @@ #include "intel_modeset_lock.h" #include "intel_panel.h" #include "intel_pch_display.h" +#include "intel_pfit.h" #include "intel_pps.h" #include "intel_psr.h" #include "intel_runtime_pm.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 72ac910bf6ec..6a16194b1105 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -62,6 +62,7 @@ #include "intel_hdmi.h" #include "intel_lspcon.h" #include "intel_panel.h" +#include "intel_pfit.h" #include "intel_snps_phy.h" static void diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 5f753ee743c6..5d022b4215ee 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -52,6 +52,7 @@ #include "intel_lvds.h" #include "intel_lvds_regs.h" #include "intel_panel.h" +#include "intel_pfit.h" #include "intel_pps_regs.h" /* Private structure for the integrated LVDS support */ diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 7fa0a54a3d3a..313bd3f35ace 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -33,14 +33,13 @@ #include -#include "i915_reg.h" +#include "i915_drv.h" #include "intel_backlight.h" #include "intel_connector.h" -#include "intel_de.h" +#include "intel_display_core.h" #include "intel_display_driver.h" #include "intel_display_types.h" #include "intel_drrs.h" -#include "intel_lvds_regs.h" #include "intel_panel.h" #include "intel_quirks.h" #include "intel_vrr.h" @@ -381,547 +380,6 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, "current (BIOS)"); } -static int intel_pch_pfit_check_dst_window(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - const struct drm_rect *dst = &crtc_state->pch_pfit.dst; - int width = drm_rect_width(dst); - int height = drm_rect_height(dst); - int x = dst->x1; - int y = dst->y1; - - if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE && - (y & 1 || height & 1)) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") misaligned for interlaced output\n", - crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); - return -EINVAL; - } - - /* - * "Restriction : When pipe scaling is enabled, the scaled - * output must equal the pipe active area, so Pipe active - * size = (2 * PF window position) + PF window size." - * - * The vertical direction seems more forgiving than the - * horizontal direction, but still has some issues so - * let's follow the same hard rule for both. - */ - if (adjusted_mode->crtc_hdisplay != 2 * x + width || - adjusted_mode->crtc_vdisplay != 2 * y + height) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") not centered\n", - crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); - return -EINVAL; - } - - /* - * "Restriction : The X position must not be programmed - * to be 1 (28:16=0 0000 0000 0001b)." - */ - if (x == 1) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") badly positioned\n", - crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); - return -EINVAL; - } - - return 0; -} - -static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); - int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - int max_src_w, max_src_h; - - if (DISPLAY_VER(display) >= 8) { - max_src_w = 4096; - max_src_h = 4096; - } else if (DISPLAY_VER(display) >= 7) { - /* - * PF0 7x5 capable - * PF1 3x3 capable (could be switched to 7x5 - * mode on HSW when PF2 unused) - * PF2 3x3 capable - * - * This assumes we use a 1:1 mapping between pipe and PF. - */ - max_src_w = crtc->pipe == PIPE_A ? 4096 : 2048; - max_src_h = 4096; - } else { - max_src_w = 4096; - max_src_h = 4096; - } - - if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] source size (%dx%d) exceeds pfit max (%dx%d)\n", - crtc->base.base.id, crtc->base.name, - pipe_src_w, pipe_src_h, max_src_w, max_src_h); - return -EINVAL; - } - - return 0; -} - -static int intel_pch_pfit_check_scaling(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_rect *dst = &crtc_state->pch_pfit.dst; - int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); - int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - int hscale, vscale, max_scale = 0x12000; /* 1.125 */ - struct drm_rect src; - - drm_rect_init(&src, 0, 0, pipe_src_w << 16, pipe_src_h << 16); - - hscale = drm_rect_calc_hscale(&src, dst, 0, max_scale); - if (hscale < 0) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) exceeds max (0x%x)\n", - crtc->base.base.id, crtc->base.name, - pipe_src_w, drm_rect_width(dst), - max_scale); - return hscale; - } - - vscale = drm_rect_calc_vscale(&src, dst, 0, max_scale); - if (vscale < 0) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) exceeds max (0x%x)\n", - crtc->base.base.id, crtc->base.name, - pipe_src_h, drm_rect_height(dst), - max_scale); - return vscale; - } - - return 0; -} - -static int intel_pch_pfit_check_timings(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - - if (adjusted_mode->crtc_vdisplay < 7) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n", - crtc->base.base.id, crtc->base.name, - adjusted_mode->crtc_vdisplay, 7); - return -EINVAL; - } - - return 0; -} - -static int intel_pch_pfit_check_cloning(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - - /* - * The panel fitter is in the pipe and thus would affect every - * cloned output. The relevant properties (scaling mode, TV - * margins) are per-connector so we'd have to make sure each - * output sets them up identically. Seems like a very niche use - * case so let's just reject cloning entirely when pfit is used. - */ - if (crtc_state->uapi.encoder_mask && - !is_power_of_2(crtc_state->uapi.encoder_mask)) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] no pfit when cloning\n", - crtc->base.base.id, crtc->base.name); - return -EINVAL; - } - - return 0; -} - -/* adjusted_mode has been preset to be the panel's fixed mode */ -static int pch_panel_fitting(struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); - int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - int ret, x, y, width, height; - - /* Native modes don't need fitting */ - if (adjusted_mode->crtc_hdisplay == pipe_src_w && - adjusted_mode->crtc_vdisplay == pipe_src_h && - crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420) - return 0; - - switch (conn_state->scaling_mode) { - case DRM_MODE_SCALE_CENTER: - width = pipe_src_w; - height = pipe_src_h; - x = (adjusted_mode->crtc_hdisplay - width + 1)/2; - y = (adjusted_mode->crtc_vdisplay - height + 1)/2; - break; - - case DRM_MODE_SCALE_ASPECT: - /* Scale but preserve the aspect ratio */ - { - u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; - u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; - if (scaled_width > scaled_height) { /* pillar */ - width = scaled_height / pipe_src_h; - if (width & 1) - width++; - x = (adjusted_mode->crtc_hdisplay - width + 1) / 2; - y = 0; - height = adjusted_mode->crtc_vdisplay; - } else if (scaled_width < scaled_height) { /* letter */ - height = scaled_width / pipe_src_w; - if (height & 1) - height++; - y = (adjusted_mode->crtc_vdisplay - height + 1) / 2; - x = 0; - width = adjusted_mode->crtc_hdisplay; - } else { - x = y = 0; - width = adjusted_mode->crtc_hdisplay; - height = adjusted_mode->crtc_vdisplay; - } - } - break; - - case DRM_MODE_SCALE_NONE: - WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w); - WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h); - fallthrough; - case DRM_MODE_SCALE_FULLSCREEN: - x = y = 0; - width = adjusted_mode->crtc_hdisplay; - height = adjusted_mode->crtc_vdisplay; - break; - - default: - MISSING_CASE(conn_state->scaling_mode); - return -EINVAL; - } - - drm_rect_init(&crtc_state->pch_pfit.dst, - x, y, width, height); - crtc_state->pch_pfit.enabled = true; - - /* - * SKL+ have unified scalers for pipes/planes so the - * checks are done in a single place for all scalers. - */ - if (DISPLAY_VER(display) >= 9) - return 0; - - ret = intel_pch_pfit_check_dst_window(crtc_state); - if (ret) - return ret; - - ret = intel_pch_pfit_check_src_size(crtc_state); - if (ret) - return ret; - - ret = intel_pch_pfit_check_scaling(crtc_state); - if (ret) - return ret; - - ret = intel_pch_pfit_check_timings(crtc_state); - if (ret) - return ret; - - ret = intel_pch_pfit_check_cloning(crtc_state); - if (ret) - return ret; - - return 0; -} - -static void -centre_horizontally(struct drm_display_mode *adjusted_mode, - int width) -{ - u32 border, sync_pos, blank_width, sync_width; - - /* keep the hsync and hblank widths constant */ - sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; - blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; - sync_pos = (blank_width - sync_width + 1) / 2; - - border = (adjusted_mode->crtc_hdisplay - width + 1) / 2; - border += border & 1; /* make the border even */ - - adjusted_mode->crtc_hdisplay = width; - adjusted_mode->crtc_hblank_start = width + border; - adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width; - - adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos; - adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width; -} - -static void -centre_vertically(struct drm_display_mode *adjusted_mode, - int height) -{ - u32 border, sync_pos, blank_width, sync_width; - - /* keep the vsync and vblank widths constant */ - sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; - blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start; - sync_pos = (blank_width - sync_width + 1) / 2; - - border = (adjusted_mode->crtc_vdisplay - height + 1) / 2; - - adjusted_mode->crtc_vdisplay = height; - adjusted_mode->crtc_vblank_start = height + border; - adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width; - - adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos; - adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width; -} - -static 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_state *crtc_state, - u32 *pfit_control) -{ - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); - int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; - u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; - - /* 965+ is easy, it does everything in hw */ - if (scaled_width > scaled_height) - *pfit_control |= PFIT_ENABLE | - PFIT_SCALING_PILLAR; - else if (scaled_width < scaled_height) - *pfit_control |= PFIT_ENABLE | - PFIT_SCALING_LETTER; - else if (adjusted_mode->crtc_hdisplay != pipe_src_w) - *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; -} - -static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, - u32 *pfit_control, u32 *pfit_pgm_ratios, - u32 *border) -{ - struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); - int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; - u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; - u32 bits; - - /* - * For earlier chips we have to calculate the scaling - * ratio by hand and program it into the - * PFIT_PGM_RATIO register - */ - if (scaled_width > scaled_height) { /* pillar */ - centre_horizontally(adjusted_mode, - scaled_height / pipe_src_h); - - *border = LVDS_BORDER_ENABLE; - if (pipe_src_h != adjusted_mode->crtc_vdisplay) { - bits = panel_fitter_scaling(pipe_src_h, - adjusted_mode->crtc_vdisplay); - - *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) | - PFIT_VERT_SCALE(bits)); - *pfit_control |= (PFIT_ENABLE | - PFIT_VERT_INTERP_BILINEAR | - PFIT_HORIZ_INTERP_BILINEAR); - } - } else if (scaled_width < scaled_height) { /* letter */ - centre_vertically(adjusted_mode, - scaled_width / pipe_src_w); - - *border = LVDS_BORDER_ENABLE; - if (pipe_src_w != adjusted_mode->crtc_hdisplay) { - bits = panel_fitter_scaling(pipe_src_w, - adjusted_mode->crtc_hdisplay); - - *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) | - PFIT_VERT_SCALE(bits)); - *pfit_control |= (PFIT_ENABLE | - PFIT_VERT_INTERP_BILINEAR | - PFIT_HORIZ_INTERP_BILINEAR); - } - } else { - /* Aspects match, Let hw scale both directions */ - *pfit_control |= (PFIT_ENABLE | - PFIT_VERT_AUTO_SCALE | - PFIT_HORIZ_AUTO_SCALE | - PFIT_VERT_INTERP_BILINEAR | - PFIT_HORIZ_INTERP_BILINEAR); - } -} - -static int intel_gmch_pfit_check_timings(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - int min; - - if (DISPLAY_VER(display) >= 4) - min = 3; - else - min = 2; - - if (adjusted_mode->crtc_hdisplay < min) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] horizontal active (%d) below minimum (%d) for pfit\n", - crtc->base.base.id, crtc->base.name, - adjusted_mode->crtc_hdisplay, min); - return -EINVAL; - } - - if (adjusted_mode->crtc_vdisplay < min) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n", - crtc->base.base.id, crtc->base.name, - adjusted_mode->crtc_vdisplay, min); - return -EINVAL; - } - - return 0; -} - -static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; - struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); - int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); - - /* Native modes don't need fitting */ - if (adjusted_mode->crtc_hdisplay == pipe_src_w && - adjusted_mode->crtc_vdisplay == pipe_src_h) - goto out; - - /* - * TODO: implement downscaling for i965+. Need to account - * for downscaling in intel_crtc_compute_pixel_rate(). - */ - if (adjusted_mode->crtc_hdisplay < pipe_src_w) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) not supported\n", - crtc->base.base.id, crtc->base.name, - pipe_src_w, adjusted_mode->crtc_hdisplay); - return -EINVAL; - } - if (adjusted_mode->crtc_vdisplay < pipe_src_h) { - drm_dbg_kms(display->drm, - "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) not supported\n", - crtc->base.base.id, crtc->base.name, - pipe_src_h, adjusted_mode->crtc_vdisplay); - return -EINVAL; - } - - switch (conn_state->scaling_mode) { - case DRM_MODE_SCALE_CENTER: - /* - * For centered modes, we have to calculate border widths & - * heights and modify the values programmed into the CRTC. - */ - centre_horizontally(adjusted_mode, pipe_src_w); - centre_vertically(adjusted_mode, pipe_src_h); - border = LVDS_BORDER_ENABLE; - break; - case DRM_MODE_SCALE_ASPECT: - /* Scale but preserve the aspect ratio */ - if (DISPLAY_VER(display) >= 4) - i965_scale_aspect(crtc_state, &pfit_control); - else - i9xx_scale_aspect(crtc_state, &pfit_control, - &pfit_pgm_ratios, &border); - break; - case DRM_MODE_SCALE_FULLSCREEN: - /* - * Full scaling, even if it changes the aspect ratio. - * Fortunately this is all done for us in hw. - */ - if (pipe_src_h != adjusted_mode->crtc_vdisplay || - pipe_src_w != adjusted_mode->crtc_hdisplay) { - pfit_control |= PFIT_ENABLE; - if (DISPLAY_VER(display) >= 4) - pfit_control |= PFIT_SCALING_AUTO; - else - pfit_control |= (PFIT_VERT_AUTO_SCALE | - PFIT_VERT_INTERP_BILINEAR | - PFIT_HORIZ_AUTO_SCALE | - PFIT_HORIZ_INTERP_BILINEAR); - } - break; - default: - MISSING_CASE(conn_state->scaling_mode); - return -EINVAL; - } - - /* 965+ wants fuzzy fitting */ - /* FIXME: handle multiple panels by failing gracefully */ - if (DISPLAY_VER(display) >= 4) - pfit_control |= PFIT_PIPE(crtc->pipe) | PFIT_FILTER_FUZZY; - -out: - if ((pfit_control & PFIT_ENABLE) == 0) { - pfit_control = 0; - pfit_pgm_ratios = 0; - } - - /* Make sure pre-965 set dither correctly for 18bpp panels. */ - if (DISPLAY_VER(display) < 4 && crtc_state->pipe_bpp == 18) - pfit_control |= PFIT_PANEL_8TO6_DITHER_ENABLE; - - crtc_state->gmch_pfit.control = pfit_control; - crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios; - crtc_state->gmch_pfit.lvds_border_bits = border; - - if ((pfit_control & PFIT_ENABLE) == 0) - return 0; - - return intel_gmch_pfit_check_timings(crtc_state); -} - -int intel_panel_fitting(struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - - if (HAS_GMCH(display)) - return gmch_panel_fitting(crtc_state, conn_state); - else - return pch_panel_fitting(crtc_state, conn_state); -} - enum drm_connector_status intel_panel_detect(struct drm_connector *connector, bool force) { diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index d6dd88473555..b60d12322e5d 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -42,8 +42,6 @@ enum drrs_type intel_panel_drrs_type(struct intel_connector *connector); enum drm_mode_status intel_panel_mode_valid(struct intel_connector *connector, const struct drm_display_mode *mode); -int intel_panel_fitting(struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode); void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_pfit.c b/drivers/gpu/drm/i915/display/intel_pfit.c new file mode 100644 index 000000000000..50861aa78a89 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pfit.c @@ -0,0 +1,554 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_display_core.h" +#include "intel_display_driver.h" +#include "intel_display_types.h" +#include "intel_lvds_regs.h" +#include "intel_pfit.h" + +static int intel_pch_pfit_check_dst_window(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + const struct drm_rect *dst = &crtc_state->pch_pfit.dst; + int width = drm_rect_width(dst); + int height = drm_rect_height(dst); + int x = dst->x1; + int y = dst->y1; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE && + (y & 1 || height & 1)) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") misaligned for interlaced output\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + /* + * "Restriction : When pipe scaling is enabled, the scaled + * output must equal the pipe active area, so Pipe active + * size = (2 * PF window position) + PF window size." + * + * The vertical direction seems more forgiving than the + * horizontal direction, but still has some issues so + * let's follow the same hard rule for both. + */ + if (adjusted_mode->crtc_hdisplay != 2 * x + width || + adjusted_mode->crtc_vdisplay != 2 * y + height) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") not centered\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + /* + * "Restriction : The X position must not be programmed + * to be 1 (28:16=0 0000 0000 0001b)." + */ + if (x == 1) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit window (" DRM_RECT_FMT ") badly positioned\n", + crtc->base.base.id, crtc->base.name, DRM_RECT_ARG(dst)); + return -EINVAL; + } + + return 0; +} + +static int intel_pch_pfit_check_src_size(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + int max_src_w, max_src_h; + + if (DISPLAY_VER(display) >= 8) { + max_src_w = 4096; + max_src_h = 4096; + } else if (DISPLAY_VER(display) >= 7) { + /* + * PF0 7x5 capable + * PF1 3x3 capable (could be switched to 7x5 + * mode on HSW when PF2 unused) + * PF2 3x3 capable + * + * This assumes we use a 1:1 mapping between pipe and PF. + */ + max_src_w = crtc->pipe == PIPE_A ? 4096 : 2048; + max_src_h = 4096; + } else { + max_src_w = 4096; + max_src_h = 4096; + } + + if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] source size (%dx%d) exceeds pfit max (%dx%d)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, pipe_src_h, max_src_w, max_src_h); + return -EINVAL; + } + + return 0; +} + +static int intel_pch_pfit_check_scaling(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_rect *dst = &crtc_state->pch_pfit.dst; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + int hscale, vscale, max_scale = 0x12000; /* 1.125 */ + struct drm_rect src; + + drm_rect_init(&src, 0, 0, pipe_src_w << 16, pipe_src_h << 16); + + hscale = drm_rect_calc_hscale(&src, dst, 0, max_scale); + if (hscale < 0) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) exceeds max (0x%x)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, drm_rect_width(dst), + max_scale); + return hscale; + } + + vscale = drm_rect_calc_vscale(&src, dst, 0, max_scale); + if (vscale < 0) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) exceeds max (0x%x)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_h, drm_rect_height(dst), + max_scale); + return vscale; + } + + return 0; +} + +static int intel_pch_pfit_check_timings(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + + if (adjusted_mode->crtc_vdisplay < 7) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n", + crtc->base.base.id, crtc->base.name, + adjusted_mode->crtc_vdisplay, 7); + return -EINVAL; + } + + return 0; +} + +static int intel_pch_pfit_check_cloning(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + /* + * The panel fitter is in the pipe and thus would affect every + * cloned output. The relevant properties (scaling mode, TV + * margins) are per-connector so we'd have to make sure each + * output sets them up identically. Seems like a very niche use + * case so let's just reject cloning entirely when pfit is used. + */ + if (crtc_state->uapi.encoder_mask && + !is_power_of_2(crtc_state->uapi.encoder_mask)) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] no pfit when cloning\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + + return 0; +} + +/* adjusted_mode has been preset to be the panel's fixed mode */ +static int pch_panel_fitting(struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + int ret, x, y, width, height; + + /* Native modes don't need fitting */ + if (adjusted_mode->crtc_hdisplay == pipe_src_w && + adjusted_mode->crtc_vdisplay == pipe_src_h && + crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420) + return 0; + + switch (conn_state->scaling_mode) { + case DRM_MODE_SCALE_CENTER: + width = pipe_src_w; + height = pipe_src_h; + x = (adjusted_mode->crtc_hdisplay - width + 1)/2; + y = (adjusted_mode->crtc_vdisplay - height + 1)/2; + break; + + case DRM_MODE_SCALE_ASPECT: + /* Scale but preserve the aspect ratio */ + { + u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; + u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; + + if (scaled_width > scaled_height) { /* pillar */ + width = scaled_height / pipe_src_h; + if (width & 1) + width++; + x = (adjusted_mode->crtc_hdisplay - width + 1) / 2; + y = 0; + height = adjusted_mode->crtc_vdisplay; + } else if (scaled_width < scaled_height) { /* letter */ + height = scaled_width / pipe_src_w; + if (height & 1) + height++; + y = (adjusted_mode->crtc_vdisplay - height + 1) / 2; + x = 0; + width = adjusted_mode->crtc_hdisplay; + } else { + x = y = 0; + width = adjusted_mode->crtc_hdisplay; + height = adjusted_mode->crtc_vdisplay; + } + } + break; + + case DRM_MODE_SCALE_NONE: + WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w); + WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h); + fallthrough; + case DRM_MODE_SCALE_FULLSCREEN: + x = y = 0; + width = adjusted_mode->crtc_hdisplay; + height = adjusted_mode->crtc_vdisplay; + break; + + default: + MISSING_CASE(conn_state->scaling_mode); + return -EINVAL; + } + + drm_rect_init(&crtc_state->pch_pfit.dst, + x, y, width, height); + crtc_state->pch_pfit.enabled = true; + + /* + * SKL+ have unified scalers for pipes/planes so the + * checks are done in a single place for all scalers. + */ + if (DISPLAY_VER(display) >= 9) + return 0; + + ret = intel_pch_pfit_check_dst_window(crtc_state); + if (ret) + return ret; + + ret = intel_pch_pfit_check_src_size(crtc_state); + if (ret) + return ret; + + ret = intel_pch_pfit_check_scaling(crtc_state); + if (ret) + return ret; + + ret = intel_pch_pfit_check_timings(crtc_state); + if (ret) + return ret; + + ret = intel_pch_pfit_check_cloning(crtc_state); + if (ret) + return ret; + + return 0; +} + +static void +centre_horizontally(struct drm_display_mode *adjusted_mode, + int width) +{ + u32 border, sync_pos, blank_width, sync_width; + + /* keep the hsync and hblank widths constant */ + sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; + blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; + sync_pos = (blank_width - sync_width + 1) / 2; + + border = (adjusted_mode->crtc_hdisplay - width + 1) / 2; + border += border & 1; /* make the border even */ + + adjusted_mode->crtc_hdisplay = width; + adjusted_mode->crtc_hblank_start = width + border; + adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width; + + adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos; + adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width; +} + +static void +centre_vertically(struct drm_display_mode *adjusted_mode, + int height) +{ + u32 border, sync_pos, blank_width, sync_width; + + /* keep the vsync and vblank widths constant */ + sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; + blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start; + sync_pos = (blank_width - sync_width + 1) / 2; + + border = (adjusted_mode->crtc_vdisplay - height + 1) / 2; + + adjusted_mode->crtc_vdisplay = height; + adjusted_mode->crtc_vblank_start = height + border; + adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width; + + adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos; + adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width; +} + +static 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_state *crtc_state, + u32 *pfit_control) +{ + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; + u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; + + /* 965+ is easy, it does everything in hw */ + if (scaled_width > scaled_height) + *pfit_control |= PFIT_ENABLE | + PFIT_SCALING_PILLAR; + else if (scaled_width < scaled_height) + *pfit_control |= PFIT_ENABLE | + PFIT_SCALING_LETTER; + else if (adjusted_mode->crtc_hdisplay != pipe_src_w) + *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; +} + +static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, + u32 *pfit_control, u32 *pfit_pgm_ratios, + u32 *border) +{ + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; + u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; + u32 bits; + + /* + * For earlier chips we have to calculate the scaling + * ratio by hand and program it into the + * PFIT_PGM_RATIO register + */ + if (scaled_width > scaled_height) { /* pillar */ + centre_horizontally(adjusted_mode, + scaled_height / pipe_src_h); + + *border = LVDS_BORDER_ENABLE; + if (pipe_src_h != adjusted_mode->crtc_vdisplay) { + bits = panel_fitter_scaling(pipe_src_h, + adjusted_mode->crtc_vdisplay); + + *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) | + PFIT_VERT_SCALE(bits)); + *pfit_control |= (PFIT_ENABLE | + PFIT_VERT_INTERP_BILINEAR | + PFIT_HORIZ_INTERP_BILINEAR); + } + } else if (scaled_width < scaled_height) { /* letter */ + centre_vertically(adjusted_mode, + scaled_width / pipe_src_w); + + *border = LVDS_BORDER_ENABLE; + if (pipe_src_w != adjusted_mode->crtc_hdisplay) { + bits = panel_fitter_scaling(pipe_src_w, + adjusted_mode->crtc_hdisplay); + + *pfit_pgm_ratios |= (PFIT_HORIZ_SCALE(bits) | + PFIT_VERT_SCALE(bits)); + *pfit_control |= (PFIT_ENABLE | + PFIT_VERT_INTERP_BILINEAR | + PFIT_HORIZ_INTERP_BILINEAR); + } + } else { + /* Aspects match, Let hw scale both directions */ + *pfit_control |= (PFIT_ENABLE | + PFIT_VERT_AUTO_SCALE | + PFIT_HORIZ_AUTO_SCALE | + PFIT_VERT_INTERP_BILINEAR | + PFIT_HORIZ_INTERP_BILINEAR); + } +} + +static int intel_gmch_pfit_check_timings(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int min; + + if (DISPLAY_VER(display) >= 4) + min = 3; + else + min = 2; + + if (adjusted_mode->crtc_hdisplay < min) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] horizontal active (%d) below minimum (%d) for pfit\n", + crtc->base.base.id, crtc->base.name, + adjusted_mode->crtc_hdisplay, min); + return -EINVAL; + } + + if (adjusted_mode->crtc_vdisplay < min) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] vertical active (%d) below minimum (%d) for pfit\n", + crtc->base.base.id, crtc->base.name, + adjusted_mode->crtc_vdisplay, min); + return -EINVAL; + } + + return 0; +} + +static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + + /* Native modes don't need fitting */ + if (adjusted_mode->crtc_hdisplay == pipe_src_w && + adjusted_mode->crtc_vdisplay == pipe_src_h) + goto out; + + /* + * TODO: implement downscaling for i965+. Need to account + * for downscaling in intel_crtc_compute_pixel_rate(). + */ + if (adjusted_mode->crtc_hdisplay < pipe_src_w) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit horizontal downscaling (%d->%d) not supported\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, adjusted_mode->crtc_hdisplay); + return -EINVAL; + } + if (adjusted_mode->crtc_vdisplay < pipe_src_h) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit vertical downscaling (%d->%d) not supported\n", + crtc->base.base.id, crtc->base.name, + pipe_src_h, adjusted_mode->crtc_vdisplay); + return -EINVAL; + } + + switch (conn_state->scaling_mode) { + case DRM_MODE_SCALE_CENTER: + /* + * For centered modes, we have to calculate border widths & + * heights and modify the values programmed into the CRTC. + */ + centre_horizontally(adjusted_mode, pipe_src_w); + centre_vertically(adjusted_mode, pipe_src_h); + border = LVDS_BORDER_ENABLE; + break; + case DRM_MODE_SCALE_ASPECT: + /* Scale but preserve the aspect ratio */ + if (DISPLAY_VER(display) >= 4) + i965_scale_aspect(crtc_state, &pfit_control); + else + i9xx_scale_aspect(crtc_state, &pfit_control, + &pfit_pgm_ratios, &border); + break; + case DRM_MODE_SCALE_FULLSCREEN: + /* + * Full scaling, even if it changes the aspect ratio. + * Fortunately this is all done for us in hw. + */ + if (pipe_src_h != adjusted_mode->crtc_vdisplay || + pipe_src_w != adjusted_mode->crtc_hdisplay) { + pfit_control |= PFIT_ENABLE; + if (DISPLAY_VER(display) >= 4) + pfit_control |= PFIT_SCALING_AUTO; + else + pfit_control |= (PFIT_VERT_AUTO_SCALE | + PFIT_VERT_INTERP_BILINEAR | + PFIT_HORIZ_AUTO_SCALE | + PFIT_HORIZ_INTERP_BILINEAR); + } + break; + default: + MISSING_CASE(conn_state->scaling_mode); + return -EINVAL; + } + + /* 965+ wants fuzzy fitting */ + /* FIXME: handle multiple panels by failing gracefully */ + if (DISPLAY_VER(display) >= 4) + pfit_control |= PFIT_PIPE(crtc->pipe) | PFIT_FILTER_FUZZY; + +out: + if ((pfit_control & PFIT_ENABLE) == 0) { + pfit_control = 0; + pfit_pgm_ratios = 0; + } + + /* Make sure pre-965 set dither correctly for 18bpp panels. */ + if (DISPLAY_VER(display) < 4 && crtc_state->pipe_bpp == 18) + pfit_control |= PFIT_PANEL_8TO6_DITHER_ENABLE; + + crtc_state->gmch_pfit.control = pfit_control; + crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios; + crtc_state->gmch_pfit.lvds_border_bits = border; + + if ((pfit_control & PFIT_ENABLE) == 0) + return 0; + + return intel_gmch_pfit_check_timings(crtc_state); +} + +int intel_panel_fitting(struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + if (HAS_GMCH(display)) + return gmch_panel_fitting(crtc_state, conn_state); + else + return pch_panel_fitting(crtc_state, conn_state); +} diff --git a/drivers/gpu/drm/i915/display/intel_pfit.h b/drivers/gpu/drm/i915/display/intel_pfit.h new file mode 100644 index 000000000000..add8d78de2c9 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pfit.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_PFIT_H__ +#define __INTEL_PFIT_H__ + +struct drm_connector_state; +struct intel_crtc_state; + +int intel_panel_fitting(struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); + +#endif /* __INTEL_PFIT_H__ */ diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 32d15bd9a358..9383eedee2d4 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -44,6 +44,7 @@ #include "intel_dsi_vbt.h" #include "intel_fifo_underrun.h" #include "intel_panel.h" +#include "intel_pfit.h" #include "skl_scaler.h" #include "vlv_dsi.h" #include "vlv_dsi_pll.h" diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index da80c29aa363..bc7a04ce69fd 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -252,6 +252,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_modeset_setup.o \ i915-display/intel_modeset_verify.o \ i915-display/intel_panel.o \ + i915-display/intel_pfit.o \ i915-display/intel_pmdemand.o \ i915-display/intel_pps.o \ i915-display/intel_psr.o \ From patchwork Wed Oct 16 14:31:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 13838556 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C4AF2D2A524 for ; Wed, 16 Oct 2024 14:32:04 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6FAC710E721; Wed, 16 Oct 2024 14:32:04 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="f7TNaABi"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0072910E721 for ; Wed, 16 Oct 2024 14:32:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729089123; x=1760625123; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=OUUDeYCZc5tItICOo5b71CbirMSWMnvsz15neaL+uBQ=; b=f7TNaABi80dJcyIu9XVe3EPE8qveunazUqf03UGlqnoFCY1njW7m6YWJ CbfjiIDugJtZcowWIm7V67W3rxzYRrKiLW7OgyjzLbO4ifZJq5WRGXHc2 gTQngk1Ee14P4dl2C7gmp5UOMTF1s3XPOY1It5uXcqCZW3m8KRiHm3Ck/ VzmVykBrHU5bC+ObvM4wWvZFoDljzNsEZJAXLeAlqpCQ0jXcJMYcebhv8 8WpLbLfwnaabNQE7WlhdupYPnez4tC/dfdwvMXekUyxDLJJSc5dtosz9v IOeEMIH4cua4V7uLG3qNVcXWydZh53/WTUr9iMAwh16peCvCndhg0U73S g==; X-CSE-ConnectionGUID: CMdTaFscRNOmspBCn9wrPA== X-CSE-MsgGUID: cYaFyxfwQmKb5uu4wKB0iQ== X-IronPort-AV: E=McAfee;i="6700,10204,11226"; a="28630750" X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="28630750" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Oct 2024 07:32:02 -0700 X-CSE-ConnectionGUID: P+7/jSpMSwOThv17SjLidg== X-CSE-MsgGUID: 2/L/Tg2bQ++P1lpKXI7I4w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,208,1725346800"; d="scan'208";a="78288404" Received: from stinkpipe.fi.intel.com (HELO stinkbox) ([10.237.72.74]) by fmviesa008.fm.intel.com with SMTP; 16 Oct 2024 07:32:00 -0700 Received: by stinkbox (sSMTP sendmail emulation); Wed, 16 Oct 2024 17:31:59 +0300 From: Ville Syrjala To: intel-gfx@lists.freedesktop.org Subject: [PATCH 9/9] drm/i915: Remove ckey/format checks from skl_update_scaler_plane() Date: Wed, 16 Oct 2024 17:31:34 +0300 Message-ID: <20241016143134.26903-10-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241016143134.26903-1-ville.syrjala@linux.intel.com> References: <20241016143134.26903-1-ville.syrjala@linux.intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Ville Syrjälä skl_plane_check() already takes care to reject scaling when an unsupported pixel format or color keying is used. No need to replicate that in the scaler code. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/skl_scaler.c | 77 +++-------------------- 1 file changed, 10 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index baa601d27815..7dbc99b02eaa 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -272,7 +272,6 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); struct drm_framebuffer *fb = plane_state->hw.fb; - int ret; bool force_detach = !fb || !plane_state->uapi.visible; bool need_scaler = false; @@ -281,72 +280,16 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, fb && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) need_scaler = true; - ret = skl_update_scaler(crtc_state, force_detach, - drm_plane_index(&intel_plane->base), - &plane_state->scaler_id, - drm_rect_width(&plane_state->uapi.src) >> 16, - drm_rect_height(&plane_state->uapi.src) >> 16, - drm_rect_width(&plane_state->uapi.dst), - drm_rect_height(&plane_state->uapi.dst), - fb ? fb->format : NULL, - fb ? fb->modifier : 0, - need_scaler); - - if (ret || plane_state->scaler_id < 0) - return ret; - - /* check colorkey */ - if (plane_state->ckey.flags) { - drm_dbg_kms(&dev_priv->drm, - "[PLANE:%d:%s] scaling with color key not allowed", - intel_plane->base.base.id, - intel_plane->base.name); - return -EINVAL; - } - - /* Check src format */ - switch (fb->format->format) { - case DRM_FORMAT_RGB565: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_NV12: - case DRM_FORMAT_XYUV8888: - case DRM_FORMAT_P010: - case DRM_FORMAT_P012: - case DRM_FORMAT_P016: - case DRM_FORMAT_Y210: - case DRM_FORMAT_Y212: - case DRM_FORMAT_Y216: - case DRM_FORMAT_XVYU2101010: - case DRM_FORMAT_XVYU12_16161616: - case DRM_FORMAT_XVYU16161616: - break; - case DRM_FORMAT_XBGR16161616F: - case DRM_FORMAT_ABGR16161616F: - case DRM_FORMAT_XRGB16161616F: - case DRM_FORMAT_ARGB16161616F: - if (DISPLAY_VER(dev_priv) >= 11) - break; - fallthrough; - default: - drm_dbg_kms(&dev_priv->drm, - "[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n", - intel_plane->base.base.id, intel_plane->base.name, - fb->base.id, fb->format->format); - return -EINVAL; - } - - return 0; + return skl_update_scaler(crtc_state, force_detach, + drm_plane_index(&intel_plane->base), + &plane_state->scaler_id, + drm_rect_width(&plane_state->uapi.src) >> 16, + drm_rect_height(&plane_state->uapi.src) >> 16, + drm_rect_width(&plane_state->uapi.dst), + drm_rect_height(&plane_state->uapi.dst), + fb ? fb->format : NULL, + fb ? fb->modifier : 0, + need_scaler); } static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,