[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: Javier Martin <javier.martin@vista-silicon.com> [g.liakhovetski@gmx.de: rebased on top of cpu_is_mx27() removal] Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
70e176a5a9
commit
9b55695322
2 changed files with 121 additions and 374 deletions
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
writel(0, pcdev->base_emma + PRP_CNTL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -501,11 +442,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);
|
||||
|
@ -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,92 +700,90 @@ 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;
|
||||
buf->state = MX2_STATE_ACTIVE;
|
||||
|
||||
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;
|
||||
buf->state = MX2_STATE_ACTIVE;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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[0].discard = true;
|
||||
list_add_tail(&pcdev->buf_discard[0].queue,
|
||||
&pcdev->discard);
|
||||
|
||||
pcdev->buf_discard[1].discard = true;
|
||||
list_add_tail(&pcdev->buf_discard[1].queue,
|
||||
&pcdev->discard);
|
||||
|
||||
mx2_prp_resize_commit(pcdev);
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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[0].discard = true;
|
||||
list_add_tail(&pcdev->buf_discard[0].queue,
|
||||
&pcdev->discard);
|
||||
|
||||
pcdev->buf_discard[1].discard = true;
|
||||
list_add_tail(&pcdev->buf_discard[1].queue,
|
||||
&pcdev->discard);
|
||||
|
||||
mx2_prp_resize_commit(pcdev);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -976,29 +798,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);
|
||||
|
||||
b = pcdev->discard_buffer;
|
||||
pcdev->discard_buffer = NULL;
|
||||
|
||||
spin_unlock_irqrestore(&pcdev->lock, flags);
|
||||
|
||||
dma_free_coherent(ici->v4l2_dev.dev,
|
||||
pcdev->discard_size, b, pcdev->discard_buffer_dma);
|
||||
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;
|
||||
|
||||
spin_unlock_irqrestore(&pcdev->lock, flags);
|
||||
|
||||
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);
|
||||
}
|
||||
ret = mx27_camera_emma_prp_reset(pcdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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).
|
||||
*/
|
||||
pix->width &= ~0x7;
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
@ -1491,7 +1270,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) {
|
||||
|
@ -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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue