Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58e366eb authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Philipp Zabel
Browse files

gpu: ipu-v3: Fix IRT usage



There can be multiple IC tasks using the IRT, so the IRT needs
a separate use counter. Create a private ipu_irt_enable() to
enable the IRT module when any IC task requires rotation, and
ipu_irt_disable() when a task no longer needs the IRT.

Signed-off-by: default avatarSteve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent ea6bead7
Loading
Loading
Loading
Loading
+31 −9
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct ipu_ic_priv {
	spinlock_t lock;
	struct ipu_soc *ipu;
	int use_count;
	int irt_use_count;
	struct ipu_ic task[IC_NUM_TASKS];
};

@@ -379,8 +380,6 @@ void ipu_ic_task_disable(struct ipu_ic *ic)

	ipu_ic_write(ic, ic_conf, IC_CONF);

	ic->rotation = ic->graphics = false;

	spin_unlock_irqrestore(&priv->lock, flags);
}
EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
@@ -629,22 +628,41 @@ int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
}
EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);

static void ipu_irt_enable(struct ipu_ic *ic)
{
	struct ipu_ic_priv *priv = ic->priv;

	if (!priv->irt_use_count)
		ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);

	priv->irt_use_count++;
}

static void ipu_irt_disable(struct ipu_ic *ic)
{
	struct ipu_ic_priv *priv = ic->priv;

	if (priv->irt_use_count) {
		if (!--priv->irt_use_count)
			ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
	}
}

int ipu_ic_enable(struct ipu_ic *ic)
{
	struct ipu_ic_priv *priv = ic->priv;
	unsigned long flags;
	u32 module = IPU_CONF_IC_EN;

	spin_lock_irqsave(&priv->lock, flags);

	if (ic->rotation)
		module |= IPU_CONF_ROT_EN;

	if (!priv->use_count)
		ipu_module_enable(priv->ipu, module);
		ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);

	priv->use_count++;

	if (ic->rotation)
		ipu_irt_enable(ic);

	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
@@ -655,18 +673,22 @@ int ipu_ic_disable(struct ipu_ic *ic)
{
	struct ipu_ic_priv *priv = ic->priv;
	unsigned long flags;
	u32 module = IPU_CONF_IC_EN | IPU_CONF_ROT_EN;

	spin_lock_irqsave(&priv->lock, flags);

	priv->use_count--;

	if (!priv->use_count)
		ipu_module_disable(priv->ipu, module);
		ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);

	if (priv->use_count < 0)
		priv->use_count = 0;

	if (ic->rotation)
		ipu_irt_disable(ic);

	ic->rotation = ic->graphics = false;

	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;