Commit 4e3b2f0d authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2026-02-05' of...

Merge tag 'drm-misc-fixes-2026-02-05' of https://gitlab.freedesktop.org/drm/misc/kernel

 into drm-fixes

drm-misc-fixes for v6.19 final:

nouveau
-------
Revert adding atomic commit functions as it regresses pre-nv50.
Fix bugs exposed by enabling 570 firmware.

gma500
------
Revert a regression caused by vblank changes.

mgag200
-------
Replace a busy loop with a polling loop to fix that blocking 1 cpu for 300 ms roughly every 20 minutes.

bridge
------
imx8mp-hdmi-pa: Use runtime pm to fix a bug in channel ordering.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patch.msgid.link/c0077ea5-faeb-4b0c-bd4a-ea2384d6dc0c@linux.intel.com
parents 18f7fcd5 40b24d9c
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <drm/bridge/dw_hdmi.h>
#include <sound/asoundef.h>
@@ -33,6 +34,7 @@

struct imx8mp_hdmi_pai {
	struct regmap	*regmap;
	struct device	*dev;
};

static void imx8mp_hdmi_pai_enable(struct dw_hdmi *dw_hdmi, int channel,
@@ -43,6 +45,9 @@ static void imx8mp_hdmi_pai_enable(struct dw_hdmi *dw_hdmi, int channel,
	struct imx8mp_hdmi_pai *hdmi_pai = pdata->priv_audio;
	int val;

	if (pm_runtime_resume_and_get(hdmi_pai->dev) < 0)
		return;

	/* PAI set control extended */
	val =  WTMK_HIGH(3) | WTMK_LOW(3);
	val |= NUM_CH(channel);
@@ -85,6 +90,8 @@ static void imx8mp_hdmi_pai_disable(struct dw_hdmi *dw_hdmi)

	/* Stop PAI */
	regmap_write(hdmi_pai->regmap, HTX_PAI_CTRL, 0);

	pm_runtime_put_sync(hdmi_pai->dev);
}

static const struct regmap_config imx8mp_hdmi_pai_regmap_config = {
@@ -101,6 +108,7 @@ static int imx8mp_hdmi_pai_bind(struct device *dev, struct device *master, void
	struct imx8mp_hdmi_pai *hdmi_pai;
	struct resource *res;
	void __iomem *base;
	int ret;

	hdmi_pai = devm_kzalloc(dev, sizeof(*hdmi_pai), GFP_KERNEL);
	if (!hdmi_pai)
@@ -121,6 +129,13 @@ static int imx8mp_hdmi_pai_bind(struct device *dev, struct device *master, void
	plat_data->disable_audio = imx8mp_hdmi_pai_disable;
	plat_data->priv_audio = hdmi_pai;

	hdmi_pai->dev = dev;
	ret = devm_pm_runtime_enable(dev);
	if (ret < 0) {
		dev_err(dev, "failed to enable PM runtime: %d\n", ret);
		return ret;
	}

	return 0;
}

+13 −23
Original line number Diff line number Diff line
@@ -250,7 +250,6 @@ static irqreturn_t gma_irq_handler(int irq, void *arg)
void gma_irq_preinstall(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
	struct drm_crtc *crtc;
	unsigned long irqflags;

	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
@@ -261,15 +260,10 @@ void gma_irq_preinstall(struct drm_device *dev)
	PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE);
	PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE);

	drm_for_each_crtc(crtc, dev) {
		struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);

		if (vblank->enabled) {
			u32 mask = drm_crtc_index(crtc) ? _PSB_VSYNC_PIPEB_FLAG :
				_PSB_VSYNC_PIPEA_FLAG;
			dev_priv->vdc_irq_mask |= mask;
		}
	}
	if (dev->vblank[0].enabled)
		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
	if (dev->vblank[1].enabled)
		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;

	/* Revisit this area - want per device masks ? */
	if (dev_priv->ops->hotplug)
@@ -284,8 +278,8 @@ void gma_irq_preinstall(struct drm_device *dev)
void gma_irq_postinstall(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
	struct drm_crtc *crtc;
	unsigned long irqflags;
	unsigned int i;

	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);

@@ -298,13 +292,11 @@ void gma_irq_postinstall(struct drm_device *dev)
	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);

	drm_for_each_crtc(crtc, dev) {
		struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);

		if (vblank->enabled)
			gma_enable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
	for (i = 0; i < dev->num_crtcs; ++i) {
		if (dev->vblank[i].enabled)
			gma_enable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
		else
			gma_disable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
			gma_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
	}

	if (dev_priv->ops->hotplug_enable)
@@ -345,8 +337,8 @@ void gma_irq_uninstall(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
	struct pci_dev *pdev = to_pci_dev(dev->dev);
	struct drm_crtc *crtc;
	unsigned long irqflags;
	unsigned int i;

	if (!dev_priv->irq_enabled)
		return;
@@ -358,11 +350,9 @@ void gma_irq_uninstall(struct drm_device *dev)

	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);

	drm_for_each_crtc(crtc, dev) {
		struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);

		if (vblank->enabled)
			gma_disable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
	for (i = 0; i < dev->num_crtcs; ++i) {
		if (dev->vblank[i].enabled)
			gma_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
	}

	dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
+12 −19
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only

#include <linux/delay.h>
#include <linux/iopoll.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
@@ -12,7 +13,7 @@
void mgag200_bmc_stop_scanout(struct mga_device *mdev)
{
	u8 tmp;
	int iter_max;
	int ret;

	/*
	 * 1 - The first step is to inform the BMC of an upcoming mode
@@ -42,30 +43,22 @@ void mgag200_bmc_stop_scanout(struct mga_device *mdev)

	/*
	 * 3a- The third step is to verify if there is an active scan.
	 * We are waiting for a 0 on remhsyncsts <XSPAREREG<0>).
	 * We are waiting for a 0 on remhsyncsts (<XSPAREREG<0>).
	 */
	iter_max = 300;
	while (!(tmp & 0x1) && iter_max) {
		WREG8(DAC_INDEX, MGA1064_SPAREREG);
		tmp = RREG8(DAC_DATA);
		udelay(1000);
		iter_max--;
	}
	ret = read_poll_timeout(RREG_DAC, tmp, !(tmp & 0x1),
				1000, 300000, false,
				MGA1064_SPAREREG);
	if (ret == -ETIMEDOUT)
		return;

	/*
	 * 3b- This step occurs only if the remove is actually
	 * 3b- This step occurs only if the remote BMC is actually
	 * scanning. We are waiting for the end of the frame which is
	 * a 1 on remvsyncsts (XSPAREREG<1>)
	 */
	if (iter_max) {
		iter_max = 300;
		while ((tmp & 0x2) && iter_max) {
			WREG8(DAC_INDEX, MGA1064_SPAREREG);
			tmp = RREG8(DAC_DATA);
			udelay(1000);
			iter_max--;
		}
	}
	(void)read_poll_timeout(RREG_DAC, tmp, (tmp & 0x2),
				1000, 300000, false,
				MGA1064_SPAREREG);
}

void mgag200_bmc_start_scanout(struct mga_device *mdev)
+6 −0
Original line number Diff line number Diff line
@@ -111,6 +111,12 @@
#define DAC_INDEX 0x3c00
#define DAC_DATA 0x3c0a

#define RREG_DAC(reg)						\
	({							\
		WREG8(DAC_INDEX, reg);				\
		RREG8(DAC_DATA);				\
	})							\

#define WREG_DAC(reg, v)					\
	do {							\
		WREG8(DAC_INDEX, reg);				\
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ struct nvif_client {

int  nvif_client_ctor(struct nvif_client *parent, const char *name, struct nvif_client *);
void nvif_client_dtor(struct nvif_client *);
int  nvif_client_suspend(struct nvif_client *);
int  nvif_client_suspend(struct nvif_client *, bool);
int  nvif_client_resume(struct nvif_client *);

/*XXX*/
Loading