ALT Linux kernel packages development
 help / color / mirror / Atom feed
From: Daniil Gnusarev <gnusarevda@basealt.ru>
To: devel-kernel@lists.altlinux.org
Subject: [d-kernel] [PATCH 37/39] drm: baikal-m: add vblank events, fix mode switching
Date: Mon, 14 Oct 2024 18:02:18 +0400
Message-ID: <20241014140221.535985-38-gnusarevda@basealt.ru> (raw)
In-Reply-To: <20241014140221.535985-1-gnusarevda@basealt.ru>

Added support for vblank events, which eliminated the slowness of
the graphical environment. In addition, for the case of several monitors,
the pitch parameter is taken into account, which solves the problem of
only vertical arrangement of screens.

Signed-off-by: Daniil Gnusarev <gnusarevda@basealt.ru>
---
 drivers/gpu/drm/baikal/baikal_vdu_crtc.c  | 58 ++++++++++++++++++-----
 drivers/gpu/drm/baikal/baikal_vdu_drm.h   | 18 +++++++
 drivers/gpu/drm/baikal/baikal_vdu_drv.c   | 16 +++++--
 drivers/gpu/drm/baikal/baikal_vdu_plane.c |  5 ++
 4 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/baikal/baikal_vdu_crtc.c b/drivers/gpu/drm/baikal/baikal_vdu_crtc.c
index 50327813c04b3..b51231719fc9c 100644
--- a/drivers/gpu/drm/baikal/baikal_vdu_crtc.c
+++ b/drivers/gpu/drm/baikal/baikal_vdu_crtc.c
@@ -36,6 +36,13 @@ irqreturn_t baikal_vdu_irq(int irq, void *data)
 	irq_stat = readl(priv->regs + IVR);
 	raw_stat = readl(priv->regs + ISR);
 
+	if (irq_stat & INTR_VCT) {
+		priv->counters[10]++;
+		if (priv->vblank)
+			drm_crtc_handle_vblank(&priv->crtc);
+		status = IRQ_HANDLED;
+	}
+
 	if (raw_stat & INTR_UFU) {
 		priv->counters[4]++;
 		status = IRQ_HANDLED;
@@ -228,6 +235,7 @@ static void baikal_vdu_crtc_helper_mode_set_nofb(struct drm_crtc *crtc)
 	unsigned int ppl, hsw, hfp, hbp;
 	unsigned int lpp, vsw, vfp, vbp;
 	unsigned int reg;
+	unsigned long flags;
 	int ret = 0;
 
 	drm_mode_debug_printmodeline(mode);
@@ -260,29 +268,31 @@ static void baikal_vdu_crtc_helper_mode_set_nofb(struct drm_crtc *crtc)
 		DRM_ERROR("Cannot set desired pixel clock (%lu Hz)\n", rate);
 
 	ppl = mode->hdisplay / 16;
-	if (priv->index == CRTC_LVDS && priv-> num_lanes == 2) {
+	if (priv->index == CRTC_LVDS && priv->num_lanes == 2) {
 		hsw = mode->hsync_end - mode->hsync_start;
 		hfp = mode->hsync_start - mode->hdisplay - 1;
+		hbp = mode->htotal - mode->hsync_end;
 	} else {
 		hsw = mode->hsync_end - mode->hsync_start - 1;
-		hfp = mode->hsync_start - mode->hdisplay;
+		hfp = mode->hsync_start - mode->hdisplay - 1;
+		hbp = mode->htotal - mode->hsync_end - 1;
 	}
-	hbp = mode->htotal - mode->hsync_end;
 
 	lpp = mode->vdisplay;
 	vsw = mode->vsync_end - mode->vsync_start;
 	vfp = mode->vsync_start - mode->vdisplay;
 	vbp = mode->vtotal - mode->vsync_end;
 
+	spin_lock_irqsave(&priv->lock, flags);
 	writel((HTR_HFP(hfp) & HTR_HFP_MASK) |
 			(HTR_PPL(ppl) & HTR_PPL_MASK) |
 			(HTR_HBP(hbp) & HTR_HBP_MASK) |
 			(HTR_HSW(hsw) & HTR_HSW_MASK),
 			priv->regs + HTR);
-
 	if (mode->hdisplay > 4080 || ppl * 16 != mode->hdisplay)
 		writel((HPPLOR_HPPLO(mode->hdisplay) & HPPLOR_HPPLO_MASK) | HPPLOR_HPOE,
-				priv->regs + HPPLOR);
+			priv->regs + HPPLOR);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	writel((VTR1_VSW(vsw) & VTR1_VSW_MASK) |
 			(VTR1_VFP(vfp) & VTR1_VFP_MASK) |
@@ -314,8 +324,8 @@ static enum drm_mode_status baikal_vdu_mode_valid(struct drm_crtc *crtc,
 	                const struct drm_display_mode *mode)
 {
 	struct baikal_vdu_private *priv = crtc_to_baikal_vdu(crtc);
-	if (!priv->mode_override && (mode->hdisplay > 2560 ||
-			mode->vdisplay > 1440))
+	if (!priv->mode_override && (mode->hdisplay > 4096 ||
+			mode->vdisplay > 4096))
 		return MODE_BAD;
 	else
 		return MODE_OK;
@@ -329,8 +339,19 @@ static void baikal_vdu_crtc_helper_enable(struct drm_crtc *crtc,
 	u32 cntl, gpio;
 
 	DRM_DEV_DEBUG_DRIVER(crtc->dev->dev, "enabling pixel clock\n");
+
+	writel(ISCR_VSC_VFP, priv->regs + ISCR);
+
+	/* hold clock domain reset; disable clocking */
+	writel(0, priv->regs + PCTR);
+
 	baikal_vdu_crtc_clk_enable(priv);
 
+	/* release clock reset; enable clocking */
+	cntl = readl(priv->regs + PCTR);
+	cntl |= PCTR_PCR + PCTR_PCI;
+	writel(cntl, priv->regs + PCTR);
+
 	/* Set 16-word input FIFO watermark */
 	/* Enable and Power Up */
 	cntl = readl(priv->regs + CR1);
@@ -373,16 +394,14 @@ static void baikal_vdu_crtc_helper_enable(struct drm_crtc *crtc,
 		cntl |= CR1_OPS_LCD24;
 	writel(cntl, priv->regs + CR1);
 
-	writel(0x3ffff, priv->regs + ISR);
-	writel(INTR_FER, priv->regs + IMR);
+	drm_crtc_vblank_on(crtc);
 }
 
 void baikal_vdu_crtc_helper_disable(struct drm_crtc *crtc)
 {
 	struct baikal_vdu_private *priv = crtc_to_baikal_vdu(crtc);
 
-	writel(0x3ffff, priv->regs + ISR);
-	writel(0, priv->regs + IMR);
+	drm_crtc_vblank_off(crtc);
 
 	/* Disable clock */
 	DRM_DEV_DEBUG_DRIVER(crtc->dev->dev, "disabling pixel clock\n");
@@ -406,6 +425,21 @@ static void baikal_vdu_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	}
 }
 
+static int baikal_vdu_enable_vblank(struct drm_crtc *crtc)
+{
+	struct baikal_vdu_private *priv = crtc_to_baikal_vdu(crtc);
+
+	baikal_vdu_set_irq(priv, true, true);
+	return 0;
+}
+
+static void baikal_vdu_disable_vblank(struct drm_crtc *crtc)
+{
+	struct baikal_vdu_private *priv = crtc_to_baikal_vdu(crtc);
+
+	baikal_vdu_set_irq(priv, true, false);
+}
+
 const struct drm_crtc_funcs crtc_funcs = {
 	.set_config = drm_atomic_helper_set_config,
 	.page_flip = drm_atomic_helper_page_flip,
@@ -413,6 +447,8 @@ const struct drm_crtc_funcs crtc_funcs = {
 	.destroy = drm_crtc_cleanup,
 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.enable_vblank = baikal_vdu_enable_vblank,
+	.disable_vblank = baikal_vdu_disable_vblank,
 };
 
 const struct drm_crtc_helper_funcs crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/baikal/baikal_vdu_drm.h b/drivers/gpu/drm/baikal/baikal_vdu_drm.h
index 90dc57bac7ae2..d5dfde4b6750c 100644
--- a/drivers/gpu/drm/baikal/baikal_vdu_drm.h
+++ b/drivers/gpu/drm/baikal/baikal_vdu_drm.h
@@ -19,6 +19,8 @@
 #include <linux/gpio.h>
 #include <linux/backlight.h>
 
+#include "baikal_vdu_regs.h"
+
 #define CRTC_HDMI	0
 #define CRTC_LVDS	1
 
@@ -54,6 +56,7 @@ struct baikal_vdu_private {
 	int data_mapping;
 	int off;
 	int ready;
+	bool vblank;
 
 	/* backlight */
 	struct gpio_desc *enable_gpio;
@@ -84,6 +87,21 @@ struct baikal_hdmi_bridge {
 };
 
 /* Generic functions */
+
+static inline void baikal_vdu_set_irq(struct baikal_vdu_private *priv, bool irq, bool vblank)
+{
+	u32 val;
+
+	priv->vblank = vblank && irq;
+
+	val = priv->vblank ? INTR_VCT + INTR_FER : INTR_FER;
+	val = irq ? val : 0;
+
+	/* clear interrupt status */
+	writel(0x3ffff, priv->regs + ISR);
+	writel(val, priv->regs + IMR);
+}
+
 inline void baikal_vdu_switch_on(struct baikal_vdu_private *priv);
 
 inline void baikal_vdu_switch_off(struct baikal_vdu_private *priv);
diff --git a/drivers/gpu/drm/baikal/baikal_vdu_drv.c b/drivers/gpu/drm/baikal/baikal_vdu_drv.c
index a951c6661ffa6..63a4916b33e93 100644
--- a/drivers/gpu/drm/baikal/baikal_vdu_drv.c
+++ b/drivers/gpu/drm/baikal/baikal_vdu_drv.c
@@ -33,6 +33,7 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
 
 #include "baikal_vdu_drm.h"
 #include "baikal_vdu_regs.h"
@@ -286,7 +287,7 @@ static int baikal_vdu_allocate_irq(struct platform_device *pdev,
 	}
 
 	/* turn off interrupts before requesting the irq */
-	writel(0, priv->regs + IMR);
+	baikal_vdu_set_irq(priv, false, false);
 	ret = request_irq(priv->irq, baikal_vdu_irq, IRQF_SHARED, dev->driver->name, priv);
 	if (ret != 0)
 		dev_err(dev, "%s %s: IRQ %d allocation failed\n", __func__, priv->name, priv->irq);
@@ -295,8 +296,7 @@ static int baikal_vdu_allocate_irq(struct platform_device *pdev,
 
 static void baikal_vdu_free_irq(struct baikal_vdu_private *priv)
 {
-	writel(0, priv->regs + IMR);
-	writel(0x3ffff, priv->regs + ISR);
+	baikal_vdu_set_irq(priv, false, false);
 	free_irq(priv->irq, priv->drm->dev);
 }
 
@@ -476,6 +476,14 @@ static int baikal_vdu_drm_probe(struct platform_device *pdev)
 	lvds->ready = lvds->ready & !lvds->off;
 	dev_info(dev, "%s output %s\n", hdmi->name, hdmi->ready ? "enabled" : "disabled");
 	dev_info(dev, "%s output %s\n", lvds->name, lvds->ready ? "enabled" : "disabled");
+
+	ret = drm_vblank_init(drm, (hdmi->ready ? 1 : 0) +
+				   (lvds->ready ? 1 : 0));
+	if (ret) {
+		dev_err(dev, "failed to init vblank\n");
+		goto out_config;
+	}
+
 	baikal_vdu_remove_efifb(drm);
 
 	if (hdmi->ready || lvds->ready) {
@@ -489,7 +497,9 @@ static int baikal_vdu_drm_probe(struct platform_device *pdev)
 			dev_err(dev, "failed to register DRM device\n");
 			goto out_config;
 		}
+
 		drm_fbdev_dma_setup(drm, 32);
+
 #if defined(CONFIG_DEBUG_FS)
 		if (hdmi->ready)
 			baikal_vdu_hdmi_debugfs_init(drm->primary);
diff --git a/drivers/gpu/drm/baikal/baikal_vdu_plane.c b/drivers/gpu/drm/baikal/baikal_vdu_plane.c
index d9bdb95a8d962..490110f7e50ce 100644
--- a/drivers/gpu/drm/baikal/baikal_vdu_plane.c
+++ b/drivers/gpu/drm/baikal/baikal_vdu_plane.c
@@ -87,6 +87,11 @@ static void baikal_vdu_primary_plane_atomic_update(struct drm_plane *plane,
 	}
 
 	writel(cntl, priv->regs + CR1);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	writel((fb->pitches[0] / DIV_ROUND_UP(drm_format_info_bpp(fb->format, 0), 8)) |
+		HPPLOR_HPOE, priv->regs + HPPLOR);
+	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static const struct drm_plane_helper_funcs baikal_vdu_primary_plane_helper_funcs = {
-- 
2.42.2



  parent reply	other threads:[~2024-10-14 14:02 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-14 14:01 [d-kernel] [PATCH 00/39] Support Baikal-M in un-def in p11 Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 01/39] Baikal Electronics SoC family Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 02/39] Clk: Add clock drivers for Baikal BE-M1000 with new firmware Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 03/39] USB: Add support for Baikal USB PHY Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 04/39] PCI: Add support for PCIe controller for Baikal BE-M1000 Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 05/39] AHCI SATA: Add support " Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 06/39] UART: Add support for UART " Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 07/39] cpufreq-dt: don't load on Baikal-M SoC Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 08/39] Sound: add support for Baikal BE-M1000 I2S Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 09/39] sound: baikal-i2s: paper over RX overrun warnings on Baikal-M Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 10/39] net: stmmac: support of Baikal-BE1000 SoCs GMAC Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 11/39] net: fwnode_get_phy_id: consider all compatible strings Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 12/39] hwmon: bt1-pvt: access registers via pvt_{readl, writel} helpers Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 13/39] hwmon: bt1-pvt: define pvt_readl/pvt_writel for Baikal-M SoC Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 14/39] hwmon: bt1-pvt: adjusted probing " Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 15/39] hwmon: bt1-pvt: added compatible baikal, pvt Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 16/39] PVT: support register addressing with new firmware Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 17/39] drm: add Baikal-M SoC video display unit driver Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 18/39] drm/bridge: dw-hdmi: support ahb audio hw revision 0x2a Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 19/39] dt-bindings: dw-hdmi: added ahb-audio-regshift Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 20/39] drm/bridge: dw-hdmi: force ahb audio register offset for Baikal-M Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 21/39] drm/panfrost: forcibly set dma-coherent on Baikal-M Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 22/39] drm/panfrost: disable devfreq " Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 23/39] bmc: add board management controller driver Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 24/39] pm: disable all sleep states on Baikal-M based boards Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 25/39] sound: dwc-i2s: paper over RX overrun warnings on Baikal-M Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 26/39] sound: dwc-i2s: request all IRQs specified in device tree Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 27/39] usb: dwc3: of-simple: added compatible string for Baikal-M SoC Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 28/39] serial: 8250_dw: verify clock rate in dw8250_set_termios Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 29/39] clk: use "cmu-id" if there is no "reg" in devicetree Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 30/39] pci: baikal-pcie: driver compatibility with SDK earlier than 5.7 Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 31/39] pci: baikal-pcie: driver compatibility with SDK versions 5.4 Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 32/39] dw-pcie: refuse to load on Baikal-M with recent firmware Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 33/39] drm: baikal-vdu: driver compatibility with SDK earlier than 5.9 Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 34/39] input: new driver - serdev-serio Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 35/39] input: added TF307 serio PS/2 emulator driver Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 36/39] input: tp_serio: catch up API changes Daniil Gnusarev
2024-10-14 14:02 ` Daniil Gnusarev [this message]
2024-10-14 14:02 ` [d-kernel] [PATCH 38/39] drm: baikal-vdu: disable backlight driver loading Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 39/39] config-aarch64: enable more configs for baikal-m support Daniil Gnusarev
2024-10-14 14:28 ` [d-kernel] [PATCH 00/39] Support Baikal-M in un-def in p11 Vitaly Chikunov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241014140221.535985-38-gnusarevda@basealt.ru \
    --to=gnusarevda@basealt.ru \
    --cc=devel-kernel@lists.altlinux.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

ALT Linux kernel packages development

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel-kernel/0 devel-kernel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel-kernel devel-kernel/ http://lore.altlinux.org/devel-kernel \
		devel-kernel@altlinux.org devel-kernel@altlinux.ru devel-kernel@altlinux.com
	public-inbox-index devel-kernel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git