aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/platform/soc_camera/mx2_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/soc_camera/mx2_camera.c')
-rw-r--r--drivers/media/platform/soc_camera/mx2_camera.c529
1 files changed, 112 insertions, 417 deletions
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index 4a574f3cfb2..ffba7d91f41 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -28,7 +28,6 @@
#include <linux/time.h>
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <linux/mutex.h>
#include <linux/clk.h>
#include <media/v4l2-common.h>
@@ -64,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)
@@ -88,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
@@ -249,12 +216,6 @@ struct mx2_fmt_cfg {
struct mx2_prp_cfg cfg;
};
-enum mx2_buffer_state {
- MX2_STATE_QUEUED,
- MX2_STATE_ACTIVE,
- MX2_STATE_DONE,
-};
-
struct mx2_buf_internal {
struct list_head queue;
int bufnum;
@@ -265,12 +226,10 @@ struct mx2_buf_internal {
struct mx2_buffer {
/* common v4l buffer stuff -- must be first */
struct vb2_buffer vb;
- enum mx2_buffer_state state;
struct mx2_buf_internal internal;
};
enum mx2_camera_type {
- IMX25_CAMERA,
IMX27_CAMERA,
};
@@ -298,8 +257,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];
@@ -315,9 +272,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,
}, {
@@ -326,16 +280,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);
@@ -463,21 +407,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);
- }
+ writel(0, pcdev->base_emma + PRP_CNTL);
}
/*
@@ -502,11 +435,8 @@ 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_RXFF_LEVEL(0);
+ csicr1 = CSICR1_MCLKEN | CSICR1_PRP_IF_EN | CSICR1_FCC |
+ CSICR1_RXFF_LEVEL(0);
pcdev->csicr1 = csicr1;
writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
@@ -540,65 +470,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));
-
- do_gettimeofday(&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
*/
@@ -676,97 +547,8 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
spin_lock_irqsave(&pcdev->lock, flags);
- 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)
-{
- 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));
-
- switch (buf->state) {
- case MX2_STATE_ACTIVE:
- dev_info(icd->parent, "%s (active)\n", __func__);
- break;
- case MX2_STATE_QUEUED:
- dev_info(icd->parent, "%s (queued)\n", __func__);
- break;
- default:
- dev_info(icd->parent, "%s (unknown) %d\n", __func__,
- buf->state);
- break;
- }
-#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);
}
@@ -877,91 +659,87 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
struct mx2_buffer *buf;
unsigned long phys;
int bytesperline;
+ unsigned long flags;
- if (is_imx27_camera(pcdev)) {
- unsigned long flags;
- if (count < 2)
- return -EINVAL;
+ if (count < 2)
+ return -EINVAL;
- spin_lock_irqsave(&pcdev->lock, flags);
+ spin_lock_irqsave(&pcdev->lock, flags);
- buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
- internal.queue);
- buf->internal.bufnum = 0;
- vb = &buf->vb;
- buf->state = MX2_STATE_ACTIVE;
+ buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
+ internal.queue);
+ buf->internal.bufnum = 0;
+ vb = &buf->vb;
- phys = vb2_dma_contig_plane_dma_addr(vb, 0);
- mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
- list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
+ phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
+ list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
- buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
- internal.queue);
- buf->internal.bufnum = 1;
- vb = &buf->vb;
- buf->state = MX2_STATE_ACTIVE;
+ buf = list_first_entry(&pcdev->capture, struct mx2_buffer,
+ internal.queue);
+ buf->internal.bufnum = 1;
+ vb = &buf->vb;
- phys = vb2_dma_contig_plane_dma_addr(vb, 0);
- mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
- list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
-
- bytesperline = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
- if (bytesperline < 0) {
- spin_unlock_irqrestore(&pcdev->lock, flags);
- return bytesperline;
- }
+ phys = vb2_dma_contig_plane_dma_addr(vb, 0);
+ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum);
+ list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
- /*
- * I didn't manage to properly enable/disable the prp
- * on a per frame basis during running transfers,
- * thus we allocate a buffer here and use it to
- * discard frames when no buffer is available.
- * Feel free to work on this ;)
- */
- 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_KERNEL);
- if (!pcdev->discard_buffer) {
- spin_unlock_irqrestore(&pcdev->lock, flags);
- return -ENOMEM;
- }
+ bytesperline = soc_mbus_bytes_per_line(icd->user_width,
+ icd->current_fmt->host_fmt);
+ if (bytesperline < 0) {
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+ return bytesperline;
+ }
- pcdev->buf_discard[0].discard = true;
- list_add_tail(&pcdev->buf_discard[0].queue,
- &pcdev->discard);
+ /*
+ * I didn't manage to properly enable/disable the prp
+ * on a per frame basis during running transfers,
+ * thus we allocate a buffer here and use it to
+ * discard frames when no buffer is available.
+ * Feel free to work on this ;)
+ */
+ 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);
+ if (!pcdev->discard_buffer) {
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+ return -ENOMEM;
+ }
- pcdev->buf_discard[1].discard = true;
- list_add_tail(&pcdev->buf_discard[1].queue,
- &pcdev->discard);
+ pcdev->buf_discard[0].discard = true;
+ list_add_tail(&pcdev->buf_discard[0].queue,
+ &pcdev->discard);
- mx2_prp_resize_commit(pcdev);
+ pcdev->buf_discard[1].discard = true;
+ list_add_tail(&pcdev->buf_discard[1].queue,
+ &pcdev->discard);
- mx27_camera_emma_buf_init(icd, bytesperline);
+ mx2_prp_resize_commit(pcdev);
- if (prp->cfg.channel == 1) {
- writel(PRP_CNTL_CH1EN |
- PRP_CNTL_CSIEN |
- prp->cfg.in_fmt |
- prp->cfg.out_fmt |
- PRP_CNTL_CH1_LEN |
- PRP_CNTL_CH1BYP |
- PRP_CNTL_CH1_TSKIP(0) |
- PRP_CNTL_IN_TSKIP(0),
- pcdev->base_emma + PRP_CNTL);
- } else {
- writel(PRP_CNTL_CH2EN |
- PRP_CNTL_CSIEN |
- prp->cfg.in_fmt |
- prp->cfg.out_fmt |
- PRP_CNTL_CH2_LEN |
- PRP_CNTL_CH2_TSKIP(0) |
- PRP_CNTL_IN_TSKIP(0),
- pcdev->base_emma + PRP_CNTL);
- }
- spin_unlock_irqrestore(&pcdev->lock, flags);
+ mx27_camera_emma_buf_init(icd, bytesperline);
+
+ if (prp->cfg.channel == 1) {
+ writel(PRP_CNTL_CH1EN |
+ PRP_CNTL_CSIEN |
+ prp->cfg.in_fmt |
+ prp->cfg.out_fmt |
+ PRP_CNTL_CH1_LEN |
+ PRP_CNTL_CH1BYP |
+ PRP_CNTL_CH1_TSKIP(0) |
+ PRP_CNTL_IN_TSKIP(0),
+ pcdev->base_emma + PRP_CNTL);
+ } else {
+ writel(PRP_CNTL_CH2EN |
+ PRP_CNTL_CSIEN |
+ prp->cfg.in_fmt |
+ prp->cfg.out_fmt |
+ PRP_CNTL_CH2_LEN |
+ PRP_CNTL_CH2_TSKIP(0) |
+ PRP_CNTL_IN_TSKIP(0),
+ pcdev->base_emma + PRP_CNTL);
}
+ spin_unlock_irqrestore(&pcdev->lock, flags);
return 0;
}
@@ -977,29 +755,27 @@ static int mx2_stop_streaming(struct vb2_queue *q)
void *b;
u32 cntl;
- if (is_imx27_camera(pcdev)) {
- spin_lock_irqsave(&pcdev->lock, flags);
+ spin_lock_irqsave(&pcdev->lock, flags);
- cntl = readl(pcdev->base_emma + PRP_CNTL);
- if (prp->cfg.channel == 1) {
- writel(cntl & ~PRP_CNTL_CH1EN,
- pcdev->base_emma + PRP_CNTL);
- } else {
- writel(cntl & ~PRP_CNTL_CH2EN,
- pcdev->base_emma + PRP_CNTL);
- }
- INIT_LIST_HEAD(&pcdev->capture);
- INIT_LIST_HEAD(&pcdev->active_bufs);
- INIT_LIST_HEAD(&pcdev->discard);
+ cntl = readl(pcdev->base_emma + PRP_CNTL);
+ if (prp->cfg.channel == 1) {
+ writel(cntl & ~PRP_CNTL_CH1EN,
+ pcdev->base_emma + PRP_CNTL);
+ } else {
+ writel(cntl & ~PRP_CNTL_CH2EN,
+ pcdev->base_emma + PRP_CNTL);
+ }
+ INIT_LIST_HEAD(&pcdev->capture);
+ INIT_LIST_HEAD(&pcdev->active_bufs);
+ INIT_LIST_HEAD(&pcdev->discard);
- b = pcdev->discard_buffer;
- pcdev->discard_buffer = NULL;
+ b = pcdev->discard_buffer;
+ pcdev->discard_buffer = NULL;
- spin_unlock_irqrestore(&pcdev->lock, flags);
+ spin_unlock_irqrestore(&pcdev->lock, flags);
- dma_free_coherent(ici->v4l2_dev.dev,
- pcdev->discard_size, b, pcdev->discard_buffer_dma);
- }
+ dma_free_coherent(ici->v4l2_dev.dev,
+ pcdev->discard_size, b, pcdev->discard_buffer_dma);
return 0;
}
@@ -1008,7 +784,6 @@ static struct vb2_ops mx2_videobuf_ops = {
.queue_setup = mx2_videobuf_setup,
.buf_prepare = mx2_videobuf_prepare,
.buf_queue = mx2_videobuf_queue,
- .buf_cleanup = mx2_videobuf_release,
.start_streaming = mx2_start_streaming,
.stop_streaming = mx2_stop_streaming,
};
@@ -1129,16 +904,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);
- }
+ ret = mx27_camera_emma_prp_reset(pcdev);
+ if (ret)
+ return ret;
writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
@@ -1425,7 +1193,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",
@@ -1437,40 +1204,11 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
return -EINVAL;
}
- /* FIXME: implement MX27 limits */
-
- /* 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);
- }
- }
+ /*
+ * 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;
@@ -1488,7 +1226,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
/* If the sensor does not support image size try PrP resizing */
emma_prp = mx27_emma_prp_get_format(xlate->code,
- xlate->host_fmt->fourcc);
+ xlate->host_fmt->fourcc);
if ((mf.width != pix->width || mf.height != pix->height) &&
emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
@@ -1600,7 +1338,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
vb2_get_plane_payload(vb, 0));
list_del_init(&buf->internal.queue);
- do_gettimeofday(&vb->v4l2_buf.timestamp);
+ v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
vb->v4l2_buf.sequence = pcdev->frame_count;
if (err)
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
@@ -1634,7 +1372,6 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
vb = &buf->vb;
- buf->state = MX2_STATE_ACTIVE;
phys = vb2_dma_contig_plane_dma_addr(vb, 0);
mx27_update_emma_buf(pcdev, phys, bufnum);
@@ -1774,20 +1511,6 @@ static int 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");
@@ -1833,20 +1556,9 @@ static int 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;
- }
+ err = mx27_camera_emma_init(pdev);
+ if (err)
+ goto exit;
/*
* We're done with drvdata here. Clear the pointer so that
@@ -1859,8 +1571,6 @@ static int 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)) {
@@ -1879,10 +1589,8 @@ static int 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);
- }
+ clk_disable_unprepare(pcdev->clk_emma_ipg);
+ clk_disable_unprepare(pcdev->clk_emma_ahb);
exit:
return err;
}
@@ -1897,10 +1605,8 @@ static int 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);
- }
+ clk_disable_unprepare(pcdev->clk_emma_ipg);
+ clk_disable_unprepare(pcdev->clk_emma_ahb);
dev_info(&pdev->dev, "MX2 Camera driver unloaded\n");
@@ -1913,23 +1619,12 @@ static struct platform_driver mx2_camera_driver = {
},
.id_table = mx2_camera_devtype,
.remove = mx2_camera_remove,
+ .probe = mx2_camera_probe,
};
+module_platform_driver(mx2_camera_driver);
-static int __init mx2_camera_init(void)
-{
- return platform_driver_probe(&mx2_camera_driver, &mx2_camera_probe);
-}
-
-static void __exit mx2_camera_exit(void)
-{
- return platform_driver_unregister(&mx2_camera_driver);
-}
-
-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);