From patchwork Fri May 5 12:43:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jocelyn Falempe X-Patchwork-Id: 13232655 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 B90ABC77B7C for ; Fri, 5 May 2023 12:44:04 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 971F110E5E5; Fri, 5 May 2023 12:44:03 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 59F1910E5E0 for ; Fri, 5 May 2023 12:43:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1683290638; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DWyLOzQNjqYlCOZeFyj0X0JpaxDAeBIQzfMhl2eKC4E=; b=MqsZ7+gW1WEvvm6mGrjqpMMFQ51qFVEukcIuYAUo/+DgmhoIiQqfOu9GF6ty+722HhInY7 3BYPcSxxDa1wuqyZs+fX8g6RjGmXSSprRNpuyZFe2etTTJ4kl+2TYbZ4g7Q8hI8w5gvLjc 6K310uqDquWXRAO1rAIod3YG9B9K8Fs= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-128-46aCN84eP9u-nB-owG66zQ-1; Fri, 05 May 2023 08:43:54 -0400 X-MC-Unique: 46aCN84eP9u-nB-owG66zQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 65F3185A5A3; Fri, 5 May 2023 12:43:54 +0000 (UTC) Received: from hydra.redhat.com (unknown [10.39.193.149]) by smtp.corp.redhat.com (Postfix) with ESMTP id 55A952166B32; Fri, 5 May 2023 12:43:51 +0000 (UTC) From: Jocelyn Falempe To: dri-devel@lists.freedesktop.org, tzimmermann@suse.de, airlied@redhat.com, javierm@redhat.com, lyude@redhat.com Subject: [PATCH 1/4] drm/mgag200: Rename constant MGAREG_Status to MGAREG_STATUS Date: Fri, 5 May 2023 14:43:34 +0200 Message-Id: <20230505124337.854845-2-jfalempe@redhat.com> In-Reply-To: <20230505124337.854845-1-jfalempe@redhat.com> References: <20230505124337.854845-1-jfalempe@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Thomas Zimmermann Register constants are upper case. Fix MGAREG_Status accordingly. Signed-off-by: Thomas Zimmermann Reviewed-by: Gerd Hoffmann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 6 +++--- drivers/gpu/drm/mgag200/mgag200_reg.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 0a5aaf78172a..9a24b9c00745 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -109,12 +109,12 @@ static inline void mga_wait_vsync(struct mga_device *mdev) unsigned int status = 0; do { - status = RREG32(MGAREG_Status); + status = RREG32(MGAREG_STATUS); } while ((status & 0x08) && time_before(jiffies, timeout)); timeout = jiffies + HZ/10; status = 0; do { - status = RREG32(MGAREG_Status); + status = RREG32(MGAREG_STATUS); } while (!(status & 0x08) && time_before(jiffies, timeout)); } @@ -123,7 +123,7 @@ static inline void mga_wait_busy(struct mga_device *mdev) unsigned long timeout = jiffies + HZ; unsigned int status = 0; do { - status = RREG8(MGAREG_Status + 2); + status = RREG8(MGAREG_STATUS + 2); } while ((status & 0x01) && time_before(jiffies, timeout)); } diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index 1019ffd6c260..aa73463674e4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -102,7 +102,7 @@ #define MGAREG_EXEC 0x0100 #define MGAREG_FIFOSTATUS 0x1e10 -#define MGAREG_Status 0x1e14 +#define MGAREG_STATUS 0x1e14 #define MGAREG_CACHEFLUSH 0x1fff #define MGAREG_ICLEAR 0x1e18 #define MGAREG_IEN 0x1e1c From patchwork Fri May 5 12:43:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jocelyn Falempe X-Patchwork-Id: 13232654 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 46C2EC77B7F for ; Fri, 5 May 2023 12:44:01 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A4E7310E5E2; Fri, 5 May 2023 12:44:00 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id D33A210E5E0 for ; Fri, 5 May 2023 12:43:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1683290637; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Exx8mlpZ66CC9pAIjScJZ+nWMgkWLxHkaw+pfAl66Qo=; b=cOWb6cPw6ngzJm+CLvKxX0Ij1UZJ/3U6ulauIH8KouGi87QWCAylWvWeuSGf03PLqe5cXd gxeh9GuyBOT6edWZv/QRrzxt8f4LwXWRg2/yTd5d+MRDlXNpaOszDE/Vf7LnKwsUNtBwHm 6APsFztxL5pK9Pm8mjZoFGm5+8Itm6M= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-407-sSPRxhPRPOqWSWpuZpvp6Q-1; Fri, 05 May 2023 08:43:56 -0400 X-MC-Unique: sSPRxhPRPOqWSWpuZpvp6Q-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id D600D1C04B4F; Fri, 5 May 2023 12:43:55 +0000 (UTC) Received: from hydra.redhat.com (unknown [10.39.193.149]) by smtp.corp.redhat.com (Postfix) with ESMTP id A14E62166B31; Fri, 5 May 2023 12:43:54 +0000 (UTC) From: Jocelyn Falempe To: dri-devel@lists.freedesktop.org, tzimmermann@suse.de, airlied@redhat.com, javierm@redhat.com, lyude@redhat.com Subject: [PATCH 2/4] drm/mgag200: Simplify offset and scale computation. Date: Fri, 5 May 2023 14:43:35 +0200 Message-Id: <20230505124337.854845-3-jfalempe@redhat.com> In-Reply-To: <20230505124337.854845-1-jfalempe@redhat.com> References: <20230505124337.854845-1-jfalempe@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jocelyn Falempe Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Now that the driver handles only 16, 24 and 32-bit framebuffer, it can be simplified. No functional changes. offset: 16bit: (bppshift = 1) offset = width >> (4 - bppshift) => width / 8 => pitch / 16 24bit: (bppshift = 0) offset = (width * 3) >> (4 - bppshift) => width * 3 / 16 => pitch / 16 32bit: (bppshift = 2) offset = width >> (4 - bppshift) => width / 4 => pitch / 16 scale: 16bit: scale = (1 << bppshift) - 1 => 1 24bit: scale = ((1 << bppshift) * 3) - 1 => 2 32bit: scale = (1 << bppshift) - 1 => 3 Signed-off-by: Jocelyn Falempe --- drivers/gpu/drm/mgag200/mgag200_mode.c | 63 +++++++------------------- 1 file changed, 16 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 9a24b9c00745..7d8c65372ac4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -280,30 +280,16 @@ void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mod WREG8(MGA_MISC_OUT, misc); } -static u8 mgag200_get_bpp_shift(const struct drm_format_info *format) -{ - static const u8 bpp_shift[] = {0, 1, 0, 2}; - - return bpp_shift[format->cpp[0] - 1]; -} - /* * Calculates the HW offset value from the framebuffer's pitch. The * offset is a multiple of the pixel size and depends on the display - * format. + * format. With width in pixels and pitch in bytes, the formula is: + * offset = width * bpp / 128 = pitch / 16 */ static u32 mgag200_calculate_offset(struct mga_device *mdev, const struct drm_framebuffer *fb) { - u32 offset = fb->pitches[0] / fb->format->cpp[0]; - u8 bppshift = mgag200_get_bpp_shift(fb->format); - - if (fb->format->cpp[0] * 8 == 24) - offset = (offset * 3) >> (4 - bppshift); - else - offset = offset >> (4 - bppshift); - - return offset; + return fb->pitches[0] >> 4; } static void mgag200_set_offset(struct mga_device *mdev, @@ -326,48 +312,25 @@ static void mgag200_set_offset(struct mga_device *mdev, void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format) { struct drm_device *dev = &mdev->base; - unsigned int bpp, bppshift, scale; + unsigned int scale; u8 crtcext3, xmulctrl; - bpp = format->cpp[0] * 8; - - bppshift = mgag200_get_bpp_shift(format); - switch (bpp) { - case 24: - scale = ((1 << bppshift) * 3) - 1; - break; - default: - scale = (1 << bppshift) - 1; - break; - } - - RREG_ECRT(3, crtcext3); - - switch (bpp) { - case 8: - xmulctrl = MGA1064_MUL_CTL_8bits; - break; - case 16: - if (format->depth == 15) - xmulctrl = MGA1064_MUL_CTL_15bits; - else - xmulctrl = MGA1064_MUL_CTL_16bits; + switch (format->format) { + case DRM_FORMAT_RGB565: + xmulctrl = MGA1064_MUL_CTL_16bits; break; - case 24: + case DRM_FORMAT_RGB888: xmulctrl = MGA1064_MUL_CTL_24bits; break; - case 32: + case DRM_FORMAT_XRGB8888: xmulctrl = MGA1064_MUL_CTL_32_24bits; break; default: /* BUG: We should have caught this problem already. */ - drm_WARN_ON(dev, "invalid format depth\n"); + drm_WARN_ON(dev, "invalid drm format\n"); return; } - crtcext3 &= ~GENMASK(2, 0); - crtcext3 |= scale; - WREG_DAC(MGA1064_MUL_CTL, xmulctrl); WREG_GFX(0, 0x00); @@ -383,6 +346,12 @@ void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_in WREG_GFX(7, 0x0f); WREG_GFX(8, 0x0f); + /* scale is the number of bytes per pixels - 1 */ + scale = format->cpp[0] - 1; + + RREG_ECRT(3, crtcext3); + crtcext3 &= ~GENMASK(2, 0); + crtcext3 |= scale; WREG_ECRT(3, crtcext3); } From patchwork Fri May 5 12:43:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jocelyn Falempe X-Patchwork-Id: 13232658 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 C660EC77B75 for ; Fri, 5 May 2023 12:45:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 10A4C10E5E4; Fri, 5 May 2023 12:45:12 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id C87EA10E5E4 for ; Fri, 5 May 2023 12:45:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1683290709; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DjX6kqPEJ/qzmXANpzOrPz2+nR/DYefmobmnJ058wHA=; b=bgxj7L1bkAaacihUKMuG0OAHC7wc1UcGG8gEOUmvIJheIrJwV3+30InxKKhfGBJP6BQURE mS28UHHIG1jH0vTMgf0XuDGYdr8uh6z2ErU/ybMkPfaS4nT1W17rPpFHGOdgJifJ57URiP tksqIST2itq54hsuMgZIMIXiX8yTPmw= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-2-KofdnPEmOp2IXgRs4dC8yg-1; Fri, 05 May 2023 08:43:57 -0400 X-MC-Unique: KofdnPEmOp2IXgRs4dC8yg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 237B4884629; Fri, 5 May 2023 12:43:57 +0000 (UTC) Received: from hydra.redhat.com (unknown [10.39.193.149]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1D12D2166B31; Fri, 5 May 2023 12:43:55 +0000 (UTC) From: Jocelyn Falempe To: dri-devel@lists.freedesktop.org, tzimmermann@suse.de, airlied@redhat.com, javierm@redhat.com, lyude@redhat.com Subject: [PATCH 3/4] drm/mgag200: Add IRQ support Date: Fri, 5 May 2023 14:43:36 +0200 Message-Id: <20230505124337.854845-4-jfalempe@redhat.com> In-Reply-To: <20230505124337.854845-1-jfalempe@redhat.com> References: <20230505124337.854845-1-jfalempe@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jocelyn Falempe Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Register irq, and enable the softrap irq. This patch has no functional impact since softrap irq can't be triggered without DMA. Signed-off-by: Jocelyn Falempe --- drivers/gpu/drm/mgag200/mgag200_drv.c | 41 +++++++++++++++++++++++++++ drivers/gpu/drm/mgag200/mgag200_drv.h | 3 ++ drivers/gpu/drm/mgag200/mgag200_reg.h | 3 ++ 3 files changed, 47 insertions(+) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 976f0ab2006b..3566fcdfe1e4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -110,12 +110,43 @@ resource_size_t mgag200_device_probe_vram(struct mga_device *mdev) return mgag200_probe_vram(mdev->vram, resource_size(mdev->vram_res)); } +irqreturn_t mgag200_driver_irq_handler(int irq, void *arg) +{ + struct mga_device *mdev = (struct mga_device *) arg; + u32 status; + + status = RREG32(MGAREG_STATUS); + + if (status & MGAIRQ_SOFTRAP) { + WREG32(MGAREG_ICLEAR, MGAIRQ_SOFTRAP); + mdev->dma_in_use = 0; + wake_up(&mdev->waitq); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +void mgag200_init_irq(struct mga_device *mdev) +{ + /* Disable *all* interrupts */ + WREG32(MGAREG_IEN, 0); + /* Clear bits if they're already high */ + WREG32(MGAREG_ICLEAR, 0xf); +} + +void mgag200_enable_irq(struct mga_device *mdev) +{ + /* Enable only Softrap IRQ */ + WREG32(MGAREG_IEN, MGAIRQ_SOFTRAP); +} + int mgag200_device_preinit(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; struct pci_dev *pdev = to_pci_dev(dev->dev); resource_size_t start, len; struct resource *res; + int ret; /* BAR 1 contains registers */ @@ -153,6 +184,16 @@ int mgag200_device_preinit(struct mga_device *mdev) if (!mdev->vram) return -ENOMEM; + mgag200_init_irq(mdev); + ret = devm_request_irq(dev->dev, pdev->irq, mgag200_driver_irq_handler, + IRQF_SHARED, "mgag200_irq", mdev); + if (ret < 0) { + drm_err(dev, "devm_request_irq(VRAM) failed %d\n", ret); + return -ENXIO; + } + init_waitqueue_head(&mdev->waitq); + + mgag200_enable_irq(mdev); return 0; } diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 9e604dbb8e44..02175bfaf5a8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -291,6 +291,9 @@ struct mga_device { void __iomem *vram; resource_size_t vram_available; + wait_queue_head_t waitq; + int dma_in_use; + struct drm_plane primary_plane; struct drm_crtc crtc; struct drm_encoder encoder; diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index aa73463674e4..748c8e18e938 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -107,6 +107,9 @@ #define MGAREG_ICLEAR 0x1e18 #define MGAREG_IEN 0x1e1c +/* same bit shift for MGAREG_IEN, MGAREG_ICLEAR and MGAREG_STATUS */ +#define MGAIRQ_SOFTRAP BIT(0) + #define MGAREG_VCOUNT 0x1e20 #define MGAREG_Reset 0x1e40 From patchwork Fri May 5 12:43:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jocelyn Falempe X-Patchwork-Id: 13232657 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 0A68BC77B7C for ; Fri, 5 May 2023 12:44:09 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0A07210E5EB; Fri, 5 May 2023 12:44:05 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1577010E5E5 for ; Fri, 5 May 2023 12:44:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1683290642; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GwFFl/ubgbXCOJKo8Ww+s/ws1L8r6SYBfBUZWnnnee0=; b=A6zdaPOM+sTzlG96lzq563KiwO4Cp0OH+V0siAkLwGPeydCAk2s8XOF/ggHVMmOI5z/zRX dhxytPSvn1vZzGjDjYvzVPN0bBDr+3lCnRA5zLv1BA+trsVMfcmFWW+XYUoyIwtd4dw00a tdlfUBbjWx6TxQ7T+mu3uRMIJeWt4tY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-501-_i7U2GcQOv6qRmzBgSefSg-1; Fri, 05 May 2023 08:43:59 -0400 X-MC-Unique: _i7U2GcQOv6qRmzBgSefSg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E815685A5A3; Fri, 5 May 2023 12:43:58 +0000 (UTC) Received: from hydra.redhat.com (unknown [10.39.193.149]) by smtp.corp.redhat.com (Postfix) with ESMTP id AEDBC2166B31; Fri, 5 May 2023 12:43:57 +0000 (UTC) From: Jocelyn Falempe To: dri-devel@lists.freedesktop.org, tzimmermann@suse.de, airlied@redhat.com, javierm@redhat.com, lyude@redhat.com Subject: [PATCH 4/4] drm/mgag200: Use DMA to copy the framebuffer to the VRAM Date: Fri, 5 May 2023 14:43:37 +0200 Message-Id: <20230505124337.854845-5-jfalempe@redhat.com> In-Reply-To: <20230505124337.854845-1-jfalempe@redhat.com> References: <20230505124337.854845-1-jfalempe@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jocelyn Falempe Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Even if the transfer is not faster, it brings significant improvement in latencies and CPU usage. CPU usage drops from 100% of one core to 3% when continuously refreshing the screen. The primary DMA is used to send commands (register write), and the secondary DMA to send the pixel data. It uses the ILOAD command (chapter 4.5.7 in G200 specification), which allows to load an image, or a part of an image from system memory to VRAM. The last command sent, is a softrap command, which triggers an IRQ when the DMA transfer is complete. For 16bits and 24bits pixel width, each line is padded to make sure, the DMA transfer is a multiple of 32bits. The padded bytes won't be drawn on the screen, so they don't need to be initialized. Signed-off-by: Jocelyn Falempe --- drivers/gpu/drm/mgag200/Makefile | 3 +- drivers/gpu/drm/mgag200/mgag200_dma.c | 114 +++++++++++++++++++++ drivers/gpu/drm/mgag200/mgag200_drv.c | 2 + drivers/gpu/drm/mgag200/mgag200_drv.h | 25 +++++ drivers/gpu/drm/mgag200/mgag200_mode.c | 131 ++++++++++++++++++++++++- drivers/gpu/drm/mgag200/mgag200_reg.h | 25 +++++ 6 files changed, 295 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/mgag200/mgag200_dma.c diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile index 182e224c460d..96e23dc5572c 100644 --- a/drivers/gpu/drm/mgag200/Makefile +++ b/drivers/gpu/drm/mgag200/Makefile @@ -11,6 +11,7 @@ mgag200-y := \ mgag200_g200se.o \ mgag200_g200wb.o \ mgag200_i2c.o \ - mgag200_mode.o + mgag200_mode.o \ + mgag200_dma.o obj-$(CONFIG_DRM_MGAG200) += mgag200.o diff --git a/drivers/gpu/drm/mgag200/mgag200_dma.c b/drivers/gpu/drm/mgag200/mgag200_dma.c new file mode 100644 index 000000000000..fe063fa2b5f1 --- /dev/null +++ b/drivers/gpu/drm/mgag200/mgag200_dma.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2023 Red Hat + * + * Authors: Jocelyn Falempe + * + */ + +#include +#include + +#include "mgag200_drv.h" +#include "mgag200_reg.h" + +/* Maximum number of command block for one DMA transfert + * iload should only use 4 blocks + */ +#define MGA_MAX_CMD 50 + +#define MGA_DMA_SIZE (4 * 1024 * 1024) +#define MGA_MIN_DMA_SIZE (64 * 1024) + +/* + * Allocate coherent buffers for DMA transfert. + * We need two buffers, one for the commands, and one for the data. + * If allocation fails, mdev->dma_buf will be NULL, and the driver will + * fallback to memcpy(). + */ +void mgag200_dma_allocate(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + int size; + /* Allocate the command buffer */ + mdev->cmd = dmam_alloc_coherent(dev->dev, MGA_MAX_CMD * sizeof(*mdev->cmd), + &mdev->cmd_handle, GFP_KERNEL); + + if (!mdev->cmd) { + drm_warn(dev, "DMA command buffer allocation failed, fallback to cpu copy\n"); + return; + } + + for (size = MGA_DMA_SIZE; size >= MGA_MIN_DMA_SIZE; size = size >> 1) { + mdev->dma_buf = dmam_alloc_coherent(dev->dev, size, &mdev->dma_handle, GFP_KERNEL); + if (mdev->dma_buf) + break; + } + if (!mdev->dma_buf) { + drm_warn(dev, "DMA data buffer allocation failed, fallback to cpu copy\n"); + return; + } + mdev->dma_size = size; + drm_info(dev, "Using DMA with a %dk data buffer\n", size / 1024); +} + +/* + * Matrox uses commands block to program the hardware through DMA. + * Each command is a register write, and each block contains 4 commands + * packed in 5 words(u32). + * First word is the 4 register index (8bit) to write for the 4 commands, + * followed by the four values to be written. + */ +void mgag200_dma_add_block(struct mga_device *mdev, + u32 reg0, u32 val0, + u32 reg1, u32 val1, + u32 reg2, u32 val2, + u32 reg3, u32 val3) +{ + if (mdev->cmd_idx >= MGA_MAX_CMD) { + pr_err("mgag200: exceeding the DMA command buffer size\n"); + return; + } + + mdev->cmd[mdev->cmd_idx] = (struct mga_cmd_block) { + .cmd = DMAREG(reg0) | DMAREG(reg1) << 8 | DMAREG(reg2) << 16 | DMAREG(reg3) << 24, + .v0 = val0, + .v1 = val1, + .v2 = val2, + .v3 = val3}; + mdev->cmd_idx++; +} + +void mgag200_dma_run_cmd(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + u32 primend; + int ret; + + /* Add a last block to trigger the softrap interrupt */ + mgag200_dma_add_block(mdev, + MGAREG_DMAPAD, 0, + MGAREG_DMAPAD, 0, + MGAREG_DMAPAD, 0, + MGAREG_SOFTRAP, 0); + + primend = mdev->cmd_handle + mdev->cmd_idx * sizeof(struct mga_cmd_block); + + // Use primary DMA to send the commands + WREG32(MGAREG_PRIMADDR, (u32) mdev->cmd_handle); + WREG32(MGAREG_PRIMEND, primend); + mdev->dma_in_use = 1; + + ret = wait_event_timeout(mdev->waitq, mdev->dma_in_use == 0, HZ); + + if (mdev->dma_in_use) { + drm_err(dev, "DMA transfert timed out\n"); + /* something goes wrong, reset the DMA engine */ + WREG8(MGAREG_OPMODE, MGAOPM_DMA_BLIT); + mdev->dma_in_use = 0; + } + + /* reset command index to start a new sequence */ + mdev->cmd_idx = 0; +} + diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 3566fcdfe1e4..c863487526e7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -184,6 +184,8 @@ int mgag200_device_preinit(struct mga_device *mdev) if (!mdev->vram) return -ENOMEM; + mgag200_dma_allocate(mdev); + mgag200_init_irq(mdev); ret = devm_request_irq(dev->dev, pdev->irq, mgag200_driver_irq_handler, IRQF_SHARED, "mgag200_irq", mdev); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 02175bfaf5a8..f5060fdc16f9 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -277,6 +277,14 @@ struct mgag200_device_funcs { void (*pixpllc_atomic_update)(struct drm_crtc *crtc, struct drm_atomic_state *old_state); }; +struct mga_cmd_block { + u32 cmd; + u32 v0; + u32 v1; + u32 v2; + u32 v3; +} __packed; + struct mga_device { struct drm_device base; @@ -291,6 +299,14 @@ struct mga_device { void __iomem *vram; resource_size_t vram_available; + void *dma_buf; + size_t dma_size; + dma_addr_t dma_handle; + + struct mga_cmd_block *cmd; + int cmd_idx; + dma_addr_t cmd_handle; + wait_queue_head_t waitq; int dma_in_use; @@ -446,4 +462,13 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev); /* mgag200_i2c.c */ int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c); +/* mgag200_dma.c */ +void mgag200_dma_allocate(struct mga_device *mdev); +void mgag200_dma_add_block(struct mga_device *mdev, + u32 reg0, u32 val0, + u32 reg1, u32 val1, + u32 reg2, u32 val2, + u32 reg3, u32 val3); +void mgag200_dma_run_cmd(struct mga_device *mdev); + #endif /* __MGAG200_DRV_H__ */ diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 7d8c65372ac4..7825ec4323d2 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -398,13 +398,132 @@ static void mgag200_disable_display(struct mga_device *mdev) WREG_ECRT(0x01, crtcext1); } +static void mgag200_dwg_setup(struct mga_device *mdev, struct drm_framebuffer *fb) +{ + u32 maccess; + + drm_dbg(&mdev->base, "Setup DWG with %dx%d %p4cc\n", + fb->width, fb->height, &fb->format->format); + + switch (fb->format->format) { + case DRM_FORMAT_RGB565: + maccess = MGAMAC_PW16; + break; + case DRM_FORMAT_RGB888: + maccess = MGAMAC_PW24; + break; + case DRM_FORMAT_XRGB8888: + maccess = MGAMAC_PW32; + break; + } + WREG32(MGAREG_MACCESS, maccess); + + /* Framebuffer width in pixel */ + WREG32(MGAREG_PITCH, fb->width); + + /* Sane default value for the drawing engine registers */ + WREG32(MGAREG_DSTORG, 0); + WREG32(MGAREG_YDSTORG, 0); + WREG32(MGAREG_SRCORG, 0); + WREG32(MGAREG_CXBNDRY, 0x0FFF0000); + WREG32(MGAREG_YTOP, 0); + WREG32(MGAREG_YBOT, 0x00FFFFFF); + + /* Activate blit mode DMA, only write the low part of the register */ + WREG8(MGAREG_OPMODE, MGAOPM_DMA_BLIT); +} + +/* + * ILOAD allows to load an image from system memory to the VRAM, and with FXBNDRY, YDST and YDSTLEN, + * you can transfert a rectangle, so it's perfect when used with a damage clip. + */ +static void mgag200_iload_cmd(struct mga_device *mdev, int x, int y, int width, int height, + int width_padded, int cpp) +{ + int size = width_padded * height; + u32 iload; + + iload = MGADWG_ILOAD | MGADWG_SGNZERO | MGADWG_SHIFTZERO | MGADWG_REPLACE | MGADWG_CLIPDIS + | MGADWG_BFCOL; + + mgag200_dma_add_block(mdev, + MGAREG_DWGCTL, iload, + MGAREG_FXBNDRY, (((x + width - 1) << 16) | x), + MGAREG_AR0, (width_padded / cpp) - 1, + MGAREG_AR3, 0); + + mgag200_dma_add_block(mdev, + MGAREG_AR5, 0, + MGAREG_YDST, y, + MGAREG_DMAPAD, 0, + MGAREG_DMAPAD, 0); + + mgag200_dma_add_block(mdev, + MGAREG_DMAPAD, 0, + MGAREG_LEN | MGAREG_EXEC, height, + MGAREG_SECADDR, mdev->dma_handle | 1, + /* Writing SECEND should always be the last command of a block */ + MGAREG_SECEND, mdev->dma_handle + size); +} + +static void mgag200_dma_copy(struct mga_device *mdev, const void *src, u32 pitch, + struct drm_rect *clip, int cpp) +{ + int i; + int width = drm_rect_width(clip); + int height = drm_rect_height(clip); + + /* pad each line to 32bits boundaries see section 4.5.7 of G200 Specification */ + int width_padded = round_up(width * cpp, 4); + + for (i = 0; i < height; i++) + memcpy(mdev->dma_buf + width_padded * i, + src + (((clip->y1 + i) * pitch) + clip->x1 * cpp), + width * cpp); + + mgag200_iload_cmd(mdev, clip->x1, clip->y1, width, height, width_padded, cpp); + mgag200_dma_run_cmd(mdev); +} + +/* + * If the DMA coherent buffer is smaller than damage rectangle, we need to + * split it into multiple DMA transfert. + */ +static void mgag200_dma_damage(struct mga_device *mdev, const struct iosys_map *vmap, + struct drm_framebuffer *fb, struct drm_rect *clip) +{ + u32 pitch = fb->pitches[0]; + const void *src = vmap[0].vaddr; + struct drm_rect subclip; + int y1; + int lines; + int cpp = fb->format->cpp[0]; + + /* Number of lines that fits in one DMA buffer */ + lines = min(drm_rect_height(clip), (int) mdev->dma_size / (drm_rect_width(clip) * cpp)); + + subclip.x1 = clip->x1; + subclip.x2 = clip->x2; + + for (y1 = clip->y1; y1 < clip->y2; y1 += lines) { + subclip.y1 = y1; + subclip.y2 = min(clip->y2, y1 + lines); + mgag200_dma_copy(mdev, src, pitch, &subclip, cpp); + } +} + static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_map *vmap, struct drm_framebuffer *fb, struct drm_rect *clip) { - struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram); - - iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip)); - drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip); + if (mdev->dma_buf) { + /* Fast path, use DMA */ + mgag200_dma_damage(mdev, vmap, fb, clip); + } else { + struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram); + + iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip)); + drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip); + } } /* @@ -475,6 +594,10 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane, if (!fb) return; + if (!old_plane_state->fb || fb->format != old_plane_state->fb->format + || fb->width != old_plane_state->fb->width) + mgag200_dwg_setup(mdev, fb); + drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); drm_atomic_for_each_plane_damage(&iter, &damage) { mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage); diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index 748c8e18e938..256ac92dae56 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -116,6 +116,9 @@ #define MGAREG_OPMODE 0x1e54 +#define MGAREG_PRIMADDR 0x1e58 +#define MGAREG_PRIMEND 0x1e5c + /* Warp Registers */ #define MGAREG_WIADDR 0x1dc0 #define MGAREG_WIADDR2 0x1dd8 @@ -200,6 +203,8 @@ /* See table on 4-43 for bop ALU operations */ +#define MGADWG_REPLACE (0xC << 16) + /* See table on 4-44 for translucidity masks */ #define MGADWG_BMONOLEF ( 0x00 << 25 ) @@ -218,6 +223,8 @@ #define MGADWG_PATTERN ( 0x01 << 29 ) #define MGADWG_TRANSC ( 0x01 << 30 ) +#define MGADWG_CLIPDIS ( 0x01 << 31 ) + #define MGAREG_MISC_WRITE 0x3c2 #define MGAREG_MISC_READ 0x3cc #define MGAREG_MEM_MISC_WRITE 0x1fc2 @@ -605,6 +612,9 @@ # define MGA_TC2_SELECT_TMU1 (0x80000000) #define MGAREG_TEXTRANS 0x2c34 #define MGAREG_TEXTRANSHIGH 0x2c38 +#define MGAREG_SECADDR 0x2c40 +#define MGAREG_SECEND 0x2c44 +#define MGAREG_SOFTRAP 0x2c48 #define MGAREG_TEXFILTER 0x2c58 # define MGA_MIN_NRST (0x00000000) # define MGA_MIN_BILIN (0x00000002) @@ -691,4 +701,19 @@ #define MGA_AGP2XPLL_ENABLE 0x1 #define MGA_AGP2XPLL_DISABLE 0x0 + +#define DWGREG0 0x1c00 +#define DWGREG0_END 0x1dff +#define DWGREG1 0x2c00 +#define DWGREG1_END 0x2dff + +/* These macros convert register address to the 8 bit command index used with DMA + * It remaps 0x1c00-0x1dff to 0x00-0x7f (REG0) + * and 0x2c00-0x2dff to 0x80-0xff (REG1) + */ +#define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END) +#define DMAREG0(r) ((u8)((r - DWGREG0) >> 2)) +#define DMAREG1(r) ((u8)(((r - DWGREG1) >> 2) | 0x80)) +#define DMAREG(r) (ISREG0((r)) ? DMAREG0((r)) : DMAREG1((r))) + #endif