static void mx3_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->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct mx3_camera_buffer *buf = to_mx3_vb(vb); struct dma_async_tx_descriptor *txd = buf->txd; unsigned long flags; dev_dbg(icd->dev.parent, "Release%s DMA 0x%08x, queue %sempty\n", mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), list_empty(&buf->queue) ? "" : "not "); spin_lock_irqsave(&mx3_cam->lock, flags); if (mx3_cam->active == buf) mx3_cam->active = NULL; /* Doesn't hurt also if the list is empty */ list_del_init(&buf->queue); buf->state = CSI_BUF_NEEDS_INIT; if (txd) { buf->txd = NULL; if (mx3_cam->idmac_channel[0]) async_tx_ack(txd); } spin_unlock_irqrestore(&mx3_cam->lock, flags); }
/* * Calculate the __buffer__ (not data) size and number of buffers. */ static int mx3_videobuf_setup(struct vb2_queue *vq, unsigned int *count, unsigned int *num_planes, unsigned long sizes[], void *alloc_ctxs[]) { struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); if (bytes_per_line < 0) return bytes_per_line; if (!mx3_cam->idmac_channel[0]) return -EINVAL; *num_planes = 1; mx3_cam->sequence = 0; sizes[0] = bytes_per_line * icd->user_height; alloc_ctxs[0] = mx3_cam->alloc_ctx; if (!*count) *count = 32; if (sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) *count = MAX_VIDEO_MEM * 1024 * 1024 / sizes[0]; return 0; }
static int __devexit mx3_camera_remove(struct platform_device *pdev) { struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct mx3_camera_dev *mx3_cam = container_of(soc_host, struct mx3_camera_dev, soc_host); clk_put(mx3_cam->clk); soc_camera_host_unregister(soc_host); iounmap(mx3_cam->base); /* * The channel has either not been allocated, * or should have been released */ if (WARN_ON(mx3_cam->idmac_channel[0])) dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan); vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); vfree(mx3_cam); dmaengine_put(); dev_info(&pdev->dev, "i.MX3x Camera driver unloaded\n"); return 0; }
static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; unsigned long flags; BUG_ON(icd != pcdev->icd); ceu_write(pcdev, CEIER, 0); ceu_write(pcdev, CAPSR, 1 << 16); spin_lock_irqsave(&pcdev->lock, flags); if (pcdev->active) { list_del(&pcdev->active->queue); pcdev->active->state = VIDEOBUF_ERROR; wake_up_all(&pcdev->active->done); pcdev->active = NULL; } spin_unlock_irqrestore(&pcdev->lock, flags); pm_runtime_put_sync(ici->v4l2_dev.dev); dev_info(icd->dev.parent, "SuperH Mobile CEU driver detached from camera %d\n", icd->devnum); pcdev->icd = NULL; }
static void unicam_videobuf_queue(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->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; struct unicam_camera_buffer *buf = to_unicam_camera_vb(vb); unsigned long flags; dprintk("-enter"); dprintk("vb=0x%p vbuf=0x%p pbuf=0x%p size=%lu", vb, vb2_plane_vaddr(vb, 0), (void *)vb2_dma_contig_plane_dma_addr(vb, 0), vb2_get_plane_payload(vb, 0)); spin_lock_irqsave(&unicam_dev->lock, flags); list_add_tail(&buf->queue, &unicam_dev->capture); if (!unicam_dev->active) { unicam_dev->active = vb; /* use this buffer to trigger capture */ /* Configure HW only is streamon has been done * else only update active, HW would be configured * by streamon */ if(unicam_dev->streaming){ unicam_camera_update_buf(unicam_dev); if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2) unicam_camera_capture(unicam_dev); } } spin_unlock_irqrestore(&unicam_dev->lock, flags); dprintk("-exit"); }
static int __exit mx1_camera_remove(struct platform_device *pdev) { struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct mx1_camera_dev *pcdev = container_of(soc_host, struct mx1_camera_dev, soc_host); struct resource *res; imx_dma_free(pcdev->dma_chan); disable_fiq(pcdev->irq); mxc_set_irq_fiq(pcdev->irq, 0); release_fiq(&fh); clk_put(pcdev->clk); soc_camera_host_unregister(soc_host); iounmap(pcdev->base); res = pcdev->res; release_mem_region(res->start, resource_size(res)); kfree(pcdev); dev_info(&pdev->dev, "MX1 Camera driver unloaded\n"); return 0; }
static int gc0311_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); struct gc0311_priv *priv = to_gc0311(sd); char id; int ret; /* * We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ if (!icd->parent || to_soc_camera_host(icd->parent)->nr != icd->iface) { dev_err(&client->dev, "Parent missing or invalid!\n"); ret = -ENODEV; goto err; } ret = gc0311_read(client, REG_PID, &id); if (ret < 0) goto err; printk("product ID 0x%02x\n", id); if (id != 0xbb) { ret = -1; goto err; } priv->ident = V4L2_IDENT_GC0311; err: return ret; }
/** * @brief: for ak_videobuf_release, free buffer if camera stopped. * * @author: caolianming * @date: 2014-01-06 * @param [in] *vq: V4L2 buffer queue information structure * @param [in] *buf: ak camera drivers structure, include struct videobuf_buffer */ static void free_buffer(struct videobuf_queue *vq, struct ak_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; struct videobuf_buffer *vb = &buf->vb; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct ak_camera_dev *pcdev = ici->priv; isp_dbg("%s (vb=0x%p) buf[%d] 0x%08lx %d\n", __func__, vb, vb->i, vb->baddr, vb->bsize); BUG_ON(in_interrupt()); /* This waits until this buffer is out of danger, i.e., until it is no * longer in STATE_QUEUED or STATE_ACTIVE */ if (vb->state == VIDEOBUF_ACTIVE && !pcdev->dma_running) { printk("free_buffer: dma_running=%d, doesn't neee to wait\n", pcdev->dma_running); //vb->state = VIDEOBUF_ERROR; list_del(&vb->queue); } else { vb->state = VIDEOBUF_DONE; videobuf_waiton(vq, vb, 0, 0); } videobuf_dma_contig_free(vq, vb); vb->state = VIDEOBUF_NEEDS_INIT; }
/* * The following two functions absolutely depend on the fact, that * there can be only one camera on mx2 camera sensor interface */ static int mx2_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; int ret; u32 csicr1; if (pcdev->icd) return -EBUSY; ret = clk_enable(pcdev->clk_csi); if (ret < 0) return ret; csicr1 = CSICR1_MCLKEN; if (mx27_camera_emma(pcdev)) { csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | CSICR1_RXFF_LEVEL(0); } else if (cpu_is_mx27()) csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2); pcdev->csicr1 = csicr1; writel(pcdev->csicr1, pcdev->base_csi + CSICR1); pcdev->icd = icd; dev_info(icd->parent, "Camera driver attached to camera %d\n", icd->devnum); return 0; }
static void omap1_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct omap1_cam_buf *buf = container_of(vb, struct omap1_cam_buf, vb); struct soc_camera_device *icd = vq->priv_data; struct device *dev = icd->dev.parent; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct omap1_cam_dev *pcdev = ici->priv; switch (vb->state) { case VIDEOBUF_DONE: dev_dbg(dev, "%s (done)\n", __func__); break; case VIDEOBUF_ACTIVE: dev_dbg(dev, "%s (active)\n", __func__); break; case VIDEOBUF_QUEUED: dev_dbg(dev, "%s (queued)\n", __func__); break; case VIDEOBUF_PREPARED: dev_dbg(dev, "%s (prepared)\n", __func__); break; default: dev_dbg(dev, "%s (unknown %d)\n", __func__, vb->state); break; } free_buffer(vq, buf, pcdev->vb_mode); }
static void omap1_cam_init_videobuf(struct videobuf_queue *q, struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct omap1_cam_dev *pcdev = ici->priv; if (!sg_mode) videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, sizeof(struct omap1_cam_buf), icd, &icd->video_lock); else videobuf_queue_sg_init(q, &omap1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, sizeof(struct omap1_cam_buf), icd, &icd->video_lock); /* use videobuf mode (auto)selected with the module parameter */ pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG; /* * Ensure we substitute the videobuf-dma-contig version of the * mmap_mapper() callback with our own wrapper, used for switching * automatically to videobuf-dma-sg on buffer allocation failure. */ if (!sg_mode && q->int_ops->mmap_mapper != omap1_cam_mmap_mapper) { pcdev->mmap_mapper = q->int_ops->mmap_mapper; q->int_ops->mmap_mapper = omap1_cam_mmap_mapper; } }
static int __exit omap1_cam_remove(struct platform_device *pdev) { struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct omap1_cam_dev *pcdev = container_of(soc_host, struct omap1_cam_dev, soc_host); struct resource *res; free_irq(pcdev->irq, pcdev); omap_free_dma(pcdev->dma_ch); soc_camera_host_unregister(soc_host); iounmap(pcdev->base); res = pcdev->res; release_mem_region(res->start, resource_size(res)); clk_put(pcdev->clk); kfree(pcdev); dev_info(&pdev->dev, "OMAP1 Camera Interface driver unloaded\n"); return 0; }
/* videobuf operations */ static int unicam_videobuf_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, unsigned int *count, unsigned int *numplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = (struct unicam_camera_dev *)ici->priv; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd-> current_fmt->host_fmt); pr_debug("-enter"); if (bytes_per_line < 0) return bytes_per_line; *numplanes = 1; unicam_dev->sequence = 0; sizes[0] = bytes_per_line * icd->user_height; #if defined(CONFIG_VIDEOBUF2_DMA_CONTIG) alloc_ctxs[0] = unicam_dev->alloc_ctx; #endif if (!*count) *count = 2; pr_debug("no_of_buf=%d size=%u", *count, sizes[0]); pr_debug("-exit"); return 0; }
static int unicam_camera_s_ctrl(struct soc_camera_device *icd, struct v4l2_control *ctl) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; int ret = 0; if(ctl == NULL){ pr_err("Wrong host ops s_ctrl\n"); return -EINVAL; } switch(ctl->id){ case V4L2_CID_CAM_CAPTURE: pr_info("V4L2_CID_CAM_CAPTURE\n"); unicam_dev->cap_mode = 1; unicam_dev->cap_done = 0; /*for camera driver also invoke s_ctrl */ ret = -ENOIOCTLCMD; break; case V4L2_CID_CAM_CAPTURE_DONE: pr_info("V4L2_CID_CAM_CAPTURE_DONE\n"); unicam_dev->cap_mode = 0; /*for camera driver also invoke s_ctrl */ ret = -ENOIOCTLCMD; break; default: ret = -ENOIOCTLCMD; break; } return ret; }
/* Called under spinlock_irqsave(&pcdev->lock, ...) */ static void mx1_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx1_camera_dev *pcdev = ici->priv; struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); list_add_tail(&vb->queue, &pcdev->capture); vb->state = VIDEOBUF_ACTIVE; if (!pcdev->active) { pcdev->active = buf; /* setup sg list for future DMA */ if (!mx1_camera_setup_dma(pcdev)) { unsigned int temp; /* enable SOF irq */ temp = __raw_readl(pcdev->base + CSICR1) | CSICR1_SOF_INTEN; __raw_writel(temp, pcdev->base + CSICR1); } } }
static int unicam_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; int err = 0; if (unicam_dev->icd) { dev_warn(icd->dev.parent, "Unicam camera driver already attached to another client\n"); err = -EBUSY; goto eicd; } /* register irq */ err = request_irq(unicam_dev->irq, unicam_camera_isr, IRQF_DISABLED | IRQF_SHARED, UNICAM_CAM_DRV_NAME, unicam_dev); if (err) { dev_err(icd->dev.parent, "cound not install irq %d\n", unicam_dev->irq); err = -ENODEV; goto eirq; } unicam_dev->icd = icd; dev_info(icd->dev.parent, "Unicam Camera driver attached to camera %d\n", icd->devnum); eirq: eicd: return err; }
static void omap1_cam_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct omap1_cam_dev *pcdev = ici->priv; u32 ctrlclock; BUG_ON(icd != pcdev->icd); suspend_capture(pcdev); disable_capture(pcdev); sensor_reset(pcdev, true); /* disable and release system clocks */ ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); ctrlclock &= ~(MCLK_EN | DPLL_EN | CAMEXCLK_EN); CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); ctrlclock = (ctrlclock & ~FOSCMOD_MASK) | FOSCMOD_12MHz; CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock | MCLK_EN); CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~MCLK_EN); clk_disable(pcdev->clk); pcdev->icd = NULL; dev_dbg(icd->dev.parent, "OMAP1 Camera driver detached from camera %d\n", icd->devnum); }
static int ak_camera_remove(struct platform_device *pdev) { struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct ak_camera_dev *pcdev = container_of(soc_host, struct ak_camera_dev, soc_host); struct resource *res; CAMDBG("entry %s\n", __func__); /* free irq */ free_irq(pcdev->irq, pcdev); /* free clk */ clk_put(pcdev->clk); clk_put(pcdev->cis_sclk); soc_camera_host_unregister(soc_host); iounmap(pcdev->base); res = pcdev->res; release_mem_region(res->start, resource_size(res)); /* * @deconstruct the isp object. */ isp_module_fini(&pcdev->isp); kfree(pcdev); dev_info(&pdev->dev, "AK Camera driver unloaded\n"); return 0; }
static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; unsigned long flags; spin_lock_irqsave(&pcdev->lock, flags); if (pcdev->active == vb) { ceu_write(pcdev, CAPSR, 1 << 16); pcdev->active = NULL; } if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && !list_empty(&vb->queue)) { vb->state = VIDEOBUF_ERROR; list_del_init(&vb->queue); } spin_unlock_irqrestore(&pcdev->lock, flags); free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb)); }
/* * Videobuf operations */ static int socle_camera_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct socle_camera_dev *pcdev = ici->priv; int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; *size = PAGE_ALIGN(icd->width * icd->height * bytes_per_pixel); if (0 == *count) *count = 2; if (pcdev->video_limit) { // 20100607 cyli fix because dma_alloc_coherent() in videobuf-dma-contig.c use order aligned // while (*size * *count > pcdev->video_limit) while ((1 << (get_order(*size) + PAGE_SHIFT)) * *count > pcdev->video_limit) (*count)--; } // 20100402 cyli add pcdev->active = NULL; //printk( "socle_camera_videobuf_setup: count=%d, size=%d\n", *count, *size); return 0; }
static int ak_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *crop) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct ak_camera_dev *pcdev = ici->priv; int ret, width, height; isp_dbg("entry %s\n", __func__); if (pcdev->dma_running) { /* make sure streaming is not started */ v4l2_err(&ici->v4l2_dev, "Cannot change crop when streaming is ON\n"); return -EBUSY; } width = crop->c.width - crop->c.left; height = crop->c.height - crop->c.top; if ((crop->c.top < 0 || crop->c.left < 0) ||(((width * 3) < 18) || (height * 3) < 18) ||((width > 1280) || (height > 720))) { v4l2_err(&ici->v4l2_dev, "doesn't support negative values for top & left\n"); return -EINVAL; } if ((ret = isp_set_crop(&pcdev->isp, crop->c)) < 0) ret = v4l2_subdev_call(sd, video, s_crop, crop); return ret; }
/** * @brief: Called when the /dev/videox is close. close ISP and sensor device. * * @author: caolianming * @date: 2014-01-06 * @param [in] *icd: soc_camera_device information structure, * akcamera depends on the soc driver. */ static void ak_camera_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct ak_camera_dev *pcdev = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); CAMDBG("entry %s\n", __func__); BUG_ON(icd != pcdev->icd); v4l2_subdev_call(sd, core, reset, 0); isp_clear_irq(&pcdev->isp); isp_stop_capturing(&pcdev->isp); /* disable sensor clk */ clk_disable(pcdev->cis_sclk); /* disable the clock of isp module */ clk_disable(pcdev->clk); //ak_soft_reset(AK_SRESET_CAMERA); dev_info(icd->parent, "AK Camera driver detached from camera %d\n", icd->devnum); pcdev->active = NULL; pcdev->icd = NULL; CAMDBG("Leave %s\n", __func__); }
/** * @brief: for ak_videobuf_release, free buffer if camera stopped. * * @author: caolianming * @date: 2014-01-06 * @param [in] *vq: V4L2 buffer queue information structure * @param [in] *vb: V4L2 buffer information structure */ static void ak_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct ak_buffer *buf = container_of(vb, struct ak_buffer, vb); struct soc_camera_device *icd = vq->priv_data; // struct device *dev = icd->parent; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct ak_camera_dev *pcdev = ici->priv; unsigned long flags; isp_dbg("%s (vb=0x%p) buf[%d] 0x%08lx %d\n", __func__, vb, vb->i, vb->baddr, vb->bsize); spin_lock_irqsave(&pcdev->lock, flags); isp_clear_irq(&pcdev->isp); spin_unlock_irqrestore(&pcdev->lock, flags); switch (vb->state) { case VIDEOBUF_ACTIVE: CAMDBG("vb status: ACTIVE\n"); break; case VIDEOBUF_QUEUED: CAMDBG("vb status: QUEUED\n"); break; case VIDEOBUF_PREPARED: CAMDBG("vb status: PREPARED\n"); break; default: CAMDBG("vb status: unknown\n"); break; } free_buffer(vq, buf); }
/* * Videobuf operations */ static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct soc_camera_device *icd = vq->priv_data; int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct omap1_cam_dev *pcdev = ici->priv; if (bytes_per_line < 0) return bytes_per_line; *size = bytes_per_line * icd->user_height; if (!*count || *count < OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode)) *count = OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode); if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; dev_dbg(icd->dev.parent, "%s: count=%d, size=%d\n", __func__, *count, *size); return 0; }
static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); int i; BUG_ON(in_interrupt()); dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); /* * This waits until this buffer is out of danger, i.e., until it is no * longer in STATE_QUEUED or STATE_ACTIVE */ videobuf_waiton(vq, &buf->vb, 0, 0); videobuf_dma_unmap(vq->dev, dma); videobuf_dma_free(dma); for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) dma_free_coherent(ici->v4l2_dev.dev, buf->dmas[i].sg_size, buf->dmas[i].sg_cpu, buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; } buf->vb.state = VIDEOBUF_NEEDS_INIT; }
static void mx2_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct soc_camera_device *icd = vq->priv_data; 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%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); switch (vb->state) { case VIDEOBUF_ACTIVE: dev_info(icd->parent, "%s (active)\n", __func__); break; case VIDEOBUF_QUEUED: dev_info(icd->parent, "%s (queued)\n", __func__); break; case VIDEOBUF_PREPARED: dev_info(icd->parent, "%s (prepared)\n", __func__); break; default: dev_info(icd->parent, "%s (unknown) %d\n", __func__, vb->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 (vb->state == VIDEOBUF_QUEUED) { list_del(&vb->queue); vb->state = VIDEOBUF_ERROR; } else if (cpu_is_mx25() && vb->state == VIDEOBUF_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); vb->state = VIDEOBUF_ERROR; } spin_unlock_irqrestore(&pcdev->lock, flags); free_buffer(vq, buf); }
/** * @brief: getting image format information * * @author: caolianming * @date: 2014-01-06 * @param [in] *icd: soc_camera_device information structure, * akcamera depends on the soc driver. * @param [in] *f: image format */ static int ak_camera_get_formats(struct soc_camera_device *icd, unsigned int idx, struct soc_camera_format_xlate *xlate) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->parent; struct soc_camera_host *ici = to_soc_camera_host(dev); struct ak_camera_dev *pcdev = ici->priv; int ret, formats = 0; enum v4l2_mbus_pixelcode code; const struct soc_mbus_pixelfmt *fmt; CAMDBG("entry %s\n", __func__); ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); if (ret < 0) /* No more formats */ return 0; /* * @Note: ISP only support yuv420 output and jpeg out. * FIXME1: We miss jpeg here. * FIXME2: the output squence of YUV is actually UYVY. */ fmt = soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8); if (!fmt) { dev_warn(dev, "unsupported format code #%u: %d\n", idx, code); return 0; } CAMDBG("get format %s code=%d from sensor\n", fmt->name, code); /* Generic pass-through */ formats++; if (xlate) { xlate->host_fmt = fmt; xlate->code = code; xlate++; /* * @decide the default working mode of isp * @prefer RGB mode */ if (code < V4L2_MBUS_FMT_Y8_1X8) { pcdev->def_mode = ISP_RGB_VIDEO_OUT; //pcdev->def_mode = ISP_RGB_OUT; } if ((pcdev->def_mode != ISP_RGB_VIDEO_OUT) && (pcdev->def_mode != ISP_RGB_OUT)) { pcdev->def_mode = ISP_YUV_VIDEO_BYPASS; //pcdev->def_mode = ISP_YUV_BYPASS; } pcdev->isp.cur_mode = pcdev->def_mode; update_cur_mode_class(&pcdev->isp); dev_dbg(dev, "Providing format %s in pass-through mode\n", fmt->name); } return formats; }
static int unicam_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct device *dev = icd->dev.parent; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; const struct soc_camera_format_xlate *xlate = NULL; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_mbus_framefmt mf; int ret; u32 skip_frames = 0; dprintk("-enter"); xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { dev_warn(dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } mf.width = pix->width; mf.height = pix->height; mf.field = pix->field; mf.colorspace = pix->colorspace; mf.code = xlate->code; ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); if (mf.code != xlate->code) return -EINVAL; if (ret < 0) { dev_warn(dev, "Failed to configure for format %x\n", pix->pixelformat); return ret; } /*TODO limit here any maximum size */ ret = v4l2_subdev_call(sd, sensor, g_skip_frames, &skip_frames); if (ret < 0) { dev_warn(dev, "sensor driver doesn't implement g_skip_frames operation\n"); dev_warn(dev, "assuming zero skip frames\n"); skip_frames = 0; ret = 0; } unicam_dev->skip_frames = skip_frames; pix->width = mf.width; pix->height = mf.height; pix->field = mf.field; pix->colorspace = mf.colorspace; icd->current_fmt = xlate; iprintk("format set to %c%c%c%c res=%dx%d success=%d", pixfmtstr(pix->pixelformat), pix->width, pix->height, ret); dprintk("-exit"); return ret; }
/* * .queue_setup() is called to check whether the driver can accept the requested * number of buffers and to fill in plane sizes for the current frame format if * required */ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct rcar_vin_priv *priv = ici->priv; if (fmt) { const struct soc_camera_format_xlate *xlate; unsigned int bytes_per_line; int ret; xlate = soc_camera_xlate_by_fourcc(icd, fmt->fmt.pix.pixelformat); if (!xlate) return -EINVAL; ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width, xlate->host_fmt); if (ret < 0) return ret; bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret); ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line, fmt->fmt.pix.height); if (ret < 0) return ret; sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret); } else { /* Called from VIDIOC_REQBUFS or in compatibility mode */ sizes[0] = icd->sizeimage; } alloc_ctxs[0] = priv->alloc_ctx; if (!vq->num_buffers) priv->sequence = 0; if (!*count) *count = 2; priv->vb_count = *count; *num_planes = 1; /* Number of hardware slots */ if (is_continuous_transfer(priv)) priv->nr_hw_slots = MAX_BUFFER_NUM; else priv->nr_hw_slots = 1; dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); return 0; }
static int unicam_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *crop) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; if(crop == NULL) return -EINVAL; unicam_dev->crop = *crop; return 0; #if 0 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); pr_info("Configuring crop to %d %d\n", crop->c.width, crop->c.height); pr_info("Configuring top left to %d %d\n", crop->c.top, crop->c.left); v4l2_subdev_call(sd, video, s_stream, 0); spin_lock_irqsave(&unicam_dev->lock, flags); unicam_dev->crop = *crop; if(unicam_dev->streaming){ pr_info("Stopping stream\n"); unicam_stop(); } /* Configure new crop parameters */ mm_csi0_set_windowing_vertical(unicam_dev->crop.c.top, (unicam_dev->crop.c.top + unicam_dev->crop.c.height)); mm_csi0_cfg_pipeline_unpack(PIX_UNPACK_NONE); mm_csi0_cfg_pipeline_dpcm_dec(DPCM_DEC_NONE); mm_csi0_set_windowing_horizontal(unicam_dev->crop.c.left, (unicam_dev->crop.c.left + unicam_dev->crop.c.width)); mm_csi0_cfg_pipeline_dpcm_enc(DPCM_ENC_NONE); mm_csi0_cfg_pipeline_pack(PIX_PACK_NONE); mm_csi0_start_rx(); /* Re-configure buffer parameters */ unicam_camera_update_buf(unicam_dev); /* set data capture */ if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2) { idesc.fsi = 1; idesc.fei = 1; idesc.lci = 0; idesc.die = 1; idesc.dataline = 2; mm_csi0_config_int(&idesc, IMAGE_BUFFER); mm_csi0_config_int(&idesc, DATA_BUFFER); unicam_camera_capture(unicam_dev); } else { idesc.fsi = 0; idesc.fei = 0; idesc.lci = unicam_dev->icd->user_height; idesc.die = 0; idesc.dataline = 0; mm_csi0_config_int(&idesc, IMAGE_BUFFER); } spin_unlock_irqrestore(&unicam_dev->lock, flags); v4l2_subdev_call(sd, video, s_stream, 1); return 0; #endif }