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

Commit 9b556953 authored by Javier Martin's avatar Javier Martin Committed by Mauro Carvalho Chehab
Browse files

[media] mx2_camera: Remove i.mx25 support



i.MX25 support has been broken for several releases
now and nobody seems to care about it.

Signed-off-by: default avatarJavier Martin <javier.martin@vista-silicon.com>
[g.liakhovetski@gmx.de: rebased on top of cpu_is_mx27() removal]
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 70e176a5
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -70,13 +70,12 @@ config VIDEO_MX2_HOSTSUPPORT
	bool

config VIDEO_MX2
	tristate "i.MX27/i.MX25 Camera Sensor Interface driver"
	depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || (ARCH_MX25 && BROKEN))
	tristate "i.MX27 Camera Sensor Interface driver"
	depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27
	select VIDEOBUF2_DMA_CONTIG
	select VIDEO_MX2_HOSTSUPPORT
	---help---
	  This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor
	  Interface
	  This is a v4l2 driver for the i.MX27 Camera Sensor Interface

config VIDEO_ATMEL_ISI
	tristate "ATMEL Image Sensor Interface (ISI) support"
+112 −364
Original line number Diff line number Diff line
/*
 * V4L2 Driver for i.MX27/i.MX25 camera host
 * V4L2 Driver for i.MX27 camera host
 *
 * Copyright (C) 2008, Sascha Hauer, Pengutronix
 * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography
@@ -63,9 +63,7 @@
#define CSICR1_RF_OR_INTEN	(1 << 24)
#define CSICR1_STATFF_LEVEL	(3 << 22)
#define CSICR1_STATFF_INTEN	(1 << 21)
#define CSICR1_RXFF_LEVEL(l)	(((l) & 3) << 19)	/* MX27 */
#define CSICR1_FB2_DMA_INTEN	(1 << 20)		/* MX25 */
#define CSICR1_FB1_DMA_INTEN	(1 << 19)		/* MX25 */
#define CSICR1_RXFF_LEVEL(l)	(((l) & 3) << 19)
#define CSICR1_RXFF_INTEN	(1 << 18)
#define CSICR1_SOF_POL		(1 << 17)
#define CSICR1_SOF_INTEN	(1 << 16)
@@ -87,45 +85,15 @@
#define SHIFT_RXFF_LEVEL	19
#define SHIFT_MCLKDIV		12

/* control reg 3 */
#define CSICR3_FRMCNT		(0xFFFF << 16)
#define CSICR3_FRMCNT_RST	(1 << 15)
#define CSICR3_DMA_REFLASH_RFF	(1 << 14)
#define CSICR3_DMA_REFLASH_SFF	(1 << 13)
#define CSICR3_DMA_REQ_EN_RFF	(1 << 12)
#define CSICR3_DMA_REQ_EN_SFF	(1 << 11)
#define CSICR3_RXFF_LEVEL(l)	(((l) & 7) << 4)	/* MX25 */
#define CSICR3_CSI_SUP		(1 << 3)
#define CSICR3_ZERO_PACK_EN	(1 << 2)
#define CSICR3_ECC_INT_EN	(1 << 1)
#define CSICR3_ECC_AUTO_EN	(1 << 0)

#define SHIFT_FRMCNT		16

/* csi status reg */
#define CSISR_SFF_OR_INT	(1 << 25)
#define CSISR_RFF_OR_INT	(1 << 24)
#define CSISR_STATFF_INT	(1 << 21)
#define CSISR_DMA_TSF_FB2_INT	(1 << 20)	/* MX25 */
#define CSISR_DMA_TSF_FB1_INT	(1 << 19)	/* MX25 */
#define CSISR_RXFF_INT		(1 << 18)
#define CSISR_EOF_INT		(1 << 17)
#define CSISR_SOF_INT		(1 << 16)
#define CSISR_F2_INT		(1 << 15)
#define CSISR_F1_INT		(1 << 14)
#define CSISR_COF_INT		(1 << 13)
#define CSISR_ECC_INT		(1 << 1)
#define CSISR_DRDY		(1 << 0)

#define CSICR1			0x00
#define CSICR2			0x04
#define CSISR_IMX25		0x18
#define CSISR_IMX27		0x08
#define CSISR			0x08
#define CSISTATFIFO		0x0c
#define CSIRFIFO		0x10
#define CSIRXCNT		0x14
#define CSICR3_IMX25		0x08
#define CSICR3_IMX27		0x1c
#define CSICR3			0x1c
#define CSIDMASA_STATFIFO	0x20
#define CSIDMATA_STATFIFO	0x24
#define CSIDMASA_FB1		0x28
@@ -269,7 +237,6 @@ struct mx2_buffer {
};

enum mx2_camera_type {
	IMX25_CAMERA,
	IMX27_CAMERA,
};

@@ -297,8 +264,6 @@ struct mx2_camera_dev {
	struct mx2_buffer	*fb2_active;

	u32			csicr1;
	u32			reg_csisr;
	u32			reg_csicr3;
	enum mx2_camera_type	devtype;

	struct mx2_buf_internal buf_discard[2];
@@ -314,9 +279,6 @@ struct mx2_camera_dev {

static struct platform_device_id mx2_camera_devtype[] = {
	{
		.name = "imx25-camera",
		.driver_data = IMX25_CAMERA,
	}, {
		.name = "imx27-camera",
		.driver_data = IMX27_CAMERA,
	}, {
@@ -325,16 +287,6 @@ static struct platform_device_id mx2_camera_devtype[] = {
};
MODULE_DEVICE_TABLE(platform, mx2_camera_devtype);

static inline int is_imx25_camera(struct mx2_camera_dev *pcdev)
{
	return pcdev->devtype == IMX25_CAMERA;
}

static inline int is_imx27_camera(struct mx2_camera_dev *pcdev)
{
	return pcdev->devtype == IMX27_CAMERA;
}

static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf)
{
	return container_of(int_buf, struct mx2_buffer, internal);
@@ -462,21 +414,10 @@ static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev,

static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
{
	unsigned long flags;

	clk_disable_unprepare(pcdev->clk_csi_ahb);
	clk_disable_unprepare(pcdev->clk_csi_per);
	writel(0, pcdev->base_csi + CSICR1);
	if (is_imx27_camera(pcdev)) {
	writel(0, pcdev->base_emma + PRP_CNTL);
	} else if (is_imx25_camera(pcdev)) {
		spin_lock_irqsave(&pcdev->lock, flags);
		pcdev->fb1_active = NULL;
		pcdev->fb2_active = NULL;
		writel(0, pcdev->base_csi + CSIDMASA_FB1);
		writel(0, pcdev->base_csi + CSIDMASA_FB2);
		spin_unlock_irqrestore(&pcdev->lock, flags);
	}
}

/*
@@ -501,10 +442,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
	if (ret < 0)
		goto exit_csi_ahb;

	csicr1 = CSICR1_MCLKEN;

	if (is_imx27_camera(pcdev))
		csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
	csicr1 = CSICR1_MCLKEN | CSICR1_PRP_IF_EN | CSICR1_FCC |
		CSICR1_RXFF_LEVEL(0);

	pcdev->csicr1 = csicr1;
@@ -539,65 +477,6 @@ static void mx2_camera_remove_device(struct soc_camera_device *icd)
	pcdev->icd = NULL;
}

static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
		int state)
{
	struct vb2_buffer *vb;
	struct mx2_buffer *buf;
	struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active :
		&pcdev->fb2_active;
	u32 fb_reg = fb == 1 ? CSIDMASA_FB1 : CSIDMASA_FB2;
	unsigned long flags;

	spin_lock_irqsave(&pcdev->lock, flags);

	if (*fb_active == NULL)
		goto out;

	vb = &(*fb_active)->vb;
	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));

	v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
	vb->v4l2_buf.sequence++;
	vb2_buffer_done(vb, VB2_BUF_STATE_DONE);

	if (list_empty(&pcdev->capture)) {
		buf = NULL;
		writel(0, pcdev->base_csi + fb_reg);
	} else {
		buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
				internal.queue);
		vb = &buf->vb;
		list_del(&buf->internal.queue);
		buf->state = MX2_STATE_ACTIVE;
		writel(vb2_dma_contig_plane_dma_addr(vb, 0),
		       pcdev->base_csi + fb_reg);
	}

	*fb_active = buf;

out:
	spin_unlock_irqrestore(&pcdev->lock, flags);
}

static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
{
	struct mx2_camera_dev *pcdev = data;
	u32 status = readl(pcdev->base_csi + pcdev->reg_csisr);

	if (status & CSISR_DMA_TSF_FB1_INT)
		mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE);
	else if (status & CSISR_DMA_TSF_FB2_INT)
		mx25_camera_frame_done(pcdev, 2, MX2_STATE_DONE);

	/* FIXME: handle CSISR_RFF_OR_INT */

	writel(status, pcdev->base_csi + pcdev->reg_csisr);

	return IRQ_HANDLED;
}

/*
 *  Videobuf operations
 */
@@ -678,54 +557,17 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
	buf->state = MX2_STATE_QUEUED;
	list_add_tail(&buf->internal.queue, &pcdev->capture);

	if (is_imx25_camera(pcdev)) {
		u32 csicr3, dma_inten = 0;

		if (pcdev->fb1_active == NULL) {
			writel(vb2_dma_contig_plane_dma_addr(vb, 0),
					pcdev->base_csi + CSIDMASA_FB1);
			pcdev->fb1_active = buf;
			dma_inten = CSICR1_FB1_DMA_INTEN;
		} else if (pcdev->fb2_active == NULL) {
			writel(vb2_dma_contig_plane_dma_addr(vb, 0),
					pcdev->base_csi + CSIDMASA_FB2);
			pcdev->fb2_active = buf;
			dma_inten = CSICR1_FB2_DMA_INTEN;
		}

		if (dma_inten) {
			list_del(&buf->internal.queue);
			buf->state = MX2_STATE_ACTIVE;

			csicr3 = readl(pcdev->base_csi + pcdev->reg_csicr3);

			/* Reflash DMA */
			writel(csicr3 | CSICR3_DMA_REFLASH_RFF,
					pcdev->base_csi + pcdev->reg_csicr3);

			/* clear & enable interrupts */
			writel(dma_inten, pcdev->base_csi + pcdev->reg_csisr);
			pcdev->csicr1 |= dma_inten;
			writel(pcdev->csicr1, pcdev->base_csi + CSICR1);

			/* enable DMA */
			csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1);
			writel(csicr3, pcdev->base_csi + pcdev->reg_csicr3);
		}
	}

	spin_unlock_irqrestore(&pcdev->lock, flags);
}

static void mx2_videobuf_release(struct vb2_buffer *vb)
{
#ifdef DEBUG
	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
	struct mx2_camera_dev *pcdev = ici->priv;
	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
	unsigned long flags;

#ifdef DEBUG
	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));

@@ -744,29 +586,11 @@ static void mx2_videobuf_release(struct vb2_buffer *vb)
#endif

	/*
	 * Terminate only queued but inactive buffers. Active buffers are
	 * released when they become inactive after videobuf_waiton().
	 *
	 * FIXME: implement forced termination of active buffers for mx27 and
	 * mx27 eMMA, so that the user won't get stuck in an uninterruptible
	 * state. This requires a specific handling for each of the these DMA
	 * types.
	 */

	spin_lock_irqsave(&pcdev->lock, flags);
	if (is_imx25_camera(pcdev) && buf->state == MX2_STATE_ACTIVE) {
		if (pcdev->fb1_active == buf) {
			pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN;
			writel(0, pcdev->base_csi + CSIDMASA_FB1);
			pcdev->fb1_active = NULL;
		} else if (pcdev->fb2_active == buf) {
			pcdev->csicr1 &= ~CSICR1_FB2_DMA_INTEN;
			writel(0, pcdev->base_csi + CSIDMASA_FB2);
			pcdev->fb2_active = NULL;
		}
		writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
	}
	spin_unlock_irqrestore(&pcdev->lock, flags);
}

static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
@@ -876,9 +700,8 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
	struct mx2_buffer *buf;
	unsigned long phys;
	int bytesperline;

	if (is_imx27_camera(pcdev)) {
	unsigned long flags;

	if (count < 2)
		return -EINVAL;

@@ -920,8 +743,8 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
	 */
	pcdev->discard_size = icd->user_height * bytesperline;
	pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
				pcdev->discard_size, &pcdev->discard_buffer_dma,
				GFP_ATOMIC);
					pcdev->discard_size,
					&pcdev->discard_buffer_dma, GFP_ATOMIC);
	if (!pcdev->discard_buffer) {
		spin_unlock_irqrestore(&pcdev->lock, flags);
		return -ENOMEM;
@@ -960,7 +783,6 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
		       pcdev->base_emma + PRP_CNTL);
	}
	spin_unlock_irqrestore(&pcdev->lock, flags);
	}

	return 0;
}
@@ -976,7 +798,6 @@ static int mx2_stop_streaming(struct vb2_queue *q)
	void *b;
	u32 cntl;

	if (is_imx27_camera(pcdev)) {
	spin_lock_irqsave(&pcdev->lock, flags);

	cntl = readl(pcdev->base_emma + PRP_CNTL);
@@ -998,7 +819,6 @@ static int mx2_stop_streaming(struct vb2_queue *q)

	dma_free_coherent(ici->v4l2_dev.dev,
			  pcdev->discard_size, b, pcdev->discard_buffer_dma);
	}

	return 0;
}
@@ -1128,16 +948,9 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
	if (bytesperline < 0)
		return bytesperline;

	if (is_imx27_camera(pcdev)) {
	ret = mx27_camera_emma_prp_reset(pcdev);
	if (ret)
		return ret;
	} else if (is_imx25_camera(pcdev)) {
		writel((bytesperline * icd->user_height) >> 2,
				pcdev->base_csi + CSIRXCNT);
		writel((bytesperline << 16) | icd->user_height,
				pcdev->base_csi + CSIIMAG_PARA);
	}

	writel(pcdev->csicr1, pcdev->base_csi + CSICR1);

@@ -1424,7 +1237,6 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
	struct mx2_camera_dev *pcdev = ici->priv;
	struct mx2_fmt_cfg *emma_prp;
	unsigned int width_limit;
	int ret;

	dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n",
@@ -1436,44 +1248,11 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
		return -EINVAL;
	}

	/* limit to MX25 hardware capabilities */
	if (is_imx25_camera(pcdev)) {
		if (xlate->host_fmt->bits_per_sample <= 8)
			width_limit = 0xffff * 4;
		else
			width_limit = 0xffff * 2;
		/* CSIIMAG_PARA limit */
		if (pix->width > width_limit)
			pix->width = width_limit;
		if (pix->height > 0xffff)
			pix->height = 0xffff;

		pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
				xlate->host_fmt);
		if (pix->bytesperline < 0)
			return pix->bytesperline;
		pix->sizeimage = soc_mbus_image_size(xlate->host_fmt,
						pix->bytesperline, pix->height);
		/* Check against the CSIRXCNT limit */
		if (pix->sizeimage > 4 * 0x3ffff) {
			/* Adjust geometry, preserve aspect ratio */
			unsigned int new_height = int_sqrt(div_u64(0x3ffffULL *
					4 * pix->height, pix->bytesperline));
			pix->width = new_height * pix->width / pix->height;
			pix->height = new_height;
			pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
							xlate->host_fmt);
			BUG_ON(pix->bytesperline < 0);
			pix->sizeimage = soc_mbus_image_size(xlate->host_fmt,
						pix->bytesperline, pix->height);
		}
	} else {
	/*
		 * Width must be a multiple of 8 as requested by the CSI.
		 * (Table 39-2 in the i.MX27 Reference Manual).
	 * limit to MX27 hardware capabilities: width must be a multiple of 8 as
	 * requested by the CSI. (Table 39-2 in the i.MX27 Reference Manual).
	 */
	pix->width &= ~0x7;
	}

	/* limit to sensor capabilities */
	mf.width	= pix->width;
@@ -1777,20 +1556,6 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
		goto exit;
	}

	pcdev->devtype = pdev->id_entry->driver_data;
	switch (pcdev->devtype) {
	case IMX25_CAMERA:
		pcdev->reg_csisr = CSISR_IMX25;
		pcdev->reg_csicr3 = CSICR3_IMX25;
		break;
	case IMX27_CAMERA:
		pcdev->reg_csisr = CSISR_IMX27;
		pcdev->reg_csicr3 = CSICR3_IMX27;
		break;
	default:
		break;
	}

	pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb");
	if (IS_ERR(pcdev->clk_csi_ahb)) {
		dev_err(&pdev->dev, "Could not get csi ahb clock\n");
@@ -1836,20 +1601,9 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
	pcdev->dev = &pdev->dev;
	platform_set_drvdata(pdev, pcdev);

	if (is_imx25_camera(pcdev)) {
		err = devm_request_irq(&pdev->dev, irq_csi, mx25_camera_irq, 0,
				       MX2_CAM_DRV_NAME, pcdev);
		if (err) {
			dev_err(pcdev->dev, "Camera interrupt register failed \n");
			goto exit;
		}
	}

	if (is_imx27_camera(pcdev)) {
	err = mx27_camera_emma_init(pdev);
	if (err)
		goto exit;
	}

	/*
	 * We're done with drvdata here.  Clear the pointer so that
@@ -1862,8 +1616,6 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
	pcdev->soc_host.priv		= pcdev;
	pcdev->soc_host.v4l2_dev.dev	= &pdev->dev;
	pcdev->soc_host.nr		= pdev->id;
	if (is_imx25_camera(pcdev))
		pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE;

	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
	if (IS_ERR(pcdev->alloc_ctx)) {
@@ -1882,10 +1634,8 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
exit_free_emma:
	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
eallocctx:
	if (is_imx27_camera(pcdev)) {
	clk_disable_unprepare(pcdev->clk_emma_ipg);
	clk_disable_unprepare(pcdev->clk_emma_ahb);
	}
exit:
	return err;
}
@@ -1900,10 +1650,8 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)

	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);

	if (is_imx27_camera(pcdev)) {
	clk_disable_unprepare(pcdev->clk_emma_ipg);
	clk_disable_unprepare(pcdev->clk_emma_ahb);
	}

	dev_info(&pdev->dev, "MX2 Camera driver unloaded\n");

@@ -1932,7 +1680,7 @@ static void __exit mx2_camera_exit(void)
module_init(mx2_camera_init);
module_exit(mx2_camera_exit);

MODULE_DESCRIPTION("i.MX27/i.MX25 SoC Camera Host driver");
MODULE_DESCRIPTION("i.MX27 SoC Camera Host driver");
MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>");
MODULE_LICENSE("GPL");
MODULE_VERSION(MX2_CAM_VERSION);