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 Original line Diff line number Diff line
@@ -160,6 +160,7 @@ struct ipu_ic_priv {
	spinlock_t lock;
	spinlock_t lock;
	struct ipu_soc *ipu;
	struct ipu_soc *ipu;
	int use_count;
	int use_count;
	int irt_use_count;
	struct ipu_ic task[IC_NUM_TASKS];
	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);
	ipu_ic_write(ic, ic_conf, IC_CONF);


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

	spin_unlock_irqrestore(&priv->lock, flags);
	spin_unlock_irqrestore(&priv->lock, flags);
}
}
EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
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);
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)
int ipu_ic_enable(struct ipu_ic *ic)
{
{
	struct ipu_ic_priv *priv = ic->priv;
	struct ipu_ic_priv *priv = ic->priv;
	unsigned long flags;
	unsigned long flags;
	u32 module = IPU_CONF_IC_EN;


	spin_lock_irqsave(&priv->lock, flags);
	spin_lock_irqsave(&priv->lock, flags);


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

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


	priv->use_count++;
	priv->use_count++;


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

	spin_unlock_irqrestore(&priv->lock, flags);
	spin_unlock_irqrestore(&priv->lock, flags);


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


	spin_lock_irqsave(&priv->lock, flags);
	spin_lock_irqsave(&priv->lock, flags);


	priv->use_count--;
	priv->use_count--;


	if (!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)
	if (priv->use_count < 0)
		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);
	spin_unlock_irqrestore(&priv->lock, flags);


	return 0;
	return 0;