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

Commit f74de500 authored by Timur Tabi's avatar Timur Tabi
Browse files

drivers/video: fsl-diu-fb: streamline enabling of interrupts



Remove functions request_irq_local() and free_irq_local(), and merge
their code into the functions that handle opening and closing the
framebuffer.  We also improve the way that interrupts are enabled.

Also implement a work-around for broken U-Boots that leave the DIU
interrupts enabled.

Signed-off-by: default avatarTimur Tabi <timur@freescale.com>
parent e95c17e9
Loading
Loading
Loading
Loading
+34 −39
Original line number Diff line number Diff line
@@ -1224,9 +1224,23 @@ static int fsl_diu_open(struct fb_info *info, int user)
		res = fsl_diu_set_par(info);
		if (res < 0)
			mfbi->count--;
		else
		else {
			struct fsl_diu_data *data = mfbi->parent;

#ifdef CONFIG_NOT_COHERENT_CACHE
			/*
			 * Enable underrun detection and vertical sync
			 * interrupts.
			 */
			clrbits32(&data->diu_reg->int_mask,
				  INT_UNDRUN | INT_VSYNC);
#else
			/* Enable underrun detection */
			clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
#endif
			fsl_diu_enable_panel(info);
		}
	}

	spin_unlock(&diu_lock);
	return res;
@@ -1241,8 +1255,13 @@ static int fsl_diu_release(struct fb_info *info, int user)

	spin_lock(&diu_lock);
	mfbi->count--;
	if (mfbi->count == 0)
	if (mfbi->count == 0) {
		struct fsl_diu_data *data = mfbi->parent;

		/* Disable interrupts */
		out_be32(&data->diu_reg->int_mask, 0xffffffff);
		fsl_diu_disable_panel(info);
	}

	spin_unlock(&diu_lock);
	return res;
@@ -1380,7 +1399,7 @@ static void uninstall_fb(struct fb_info *info)
static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
{
	struct diu __iomem *hw = dev_id;
	unsigned int status = in_be32(&hw->int_status);
	uint32_t status = in_be32(&hw->int_status);

	if (status) {
		/* This is the workaround for underrun */
@@ -1405,40 +1424,6 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
	return IRQ_NONE;
}

static int request_irq_local(struct fsl_diu_data *data)
{
	struct diu __iomem *hw = data->diu_reg;
	u32 ints;
	int ret;

	/* Read to clear the status */
	in_be32(&hw->int_status);

	ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
	if (!ret) {
		ints = INT_PARERR | INT_LS_BF_VS;
#if !defined(CONFIG_NOT_COHERENT_CACHE)
		ints |=	INT_VSYNC;
#endif

		/* Read to clear the status */
		in_be32(&hw->int_status);
		out_be32(&hw->int_mask, ints);
	}

	return ret;
}

static void free_irq_local(struct fsl_diu_data *data)
{
	struct diu __iomem *hw = data->diu_reg;

	/* Disable all LCDC interrupt */
	out_be32(&hw->int_mask, 0x1f);

	free_irq(data->irq, NULL);
}

#ifdef CONFIG_PM
/*
 * Power management hooks. Note that we won't be called from IRQ context,
@@ -1621,7 +1606,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
		}
	}

	if (request_irq_local(data)) {
	/*
	 * Older versions of U-Boot leave interrupts enabled, so disable
	 * all of them and clear the status register.
	 */
	out_be32(&data->diu_reg->int_mask, 0xffffffff);
	in_be32(&data->diu_reg->int_status);

	ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
			  &data->diu_reg);
	if (ret) {
		dev_err(&pdev->dev, "could not claim irq\n");
		goto error;
	}
@@ -1656,7 +1650,8 @@ static int fsl_diu_remove(struct platform_device *pdev)

	data = dev_get_drvdata(&pdev->dev);
	disable_lcdc(&data->fsl_diu_info[0]);
	free_irq_local(data);

	free_irq(data->irq, &data->diu_reg);

	for (i = 0; i < NUM_AOIS; i++)
		uninstall_fb(&data->fsl_diu_info[i]);