示例#1
0
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);
}
示例#2
0
/*
 * 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;
}
示例#3
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;
}
示例#4
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");
}
示例#6
0
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;
}
示例#7
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;
}
示例#8
0
/**
 * @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;
}
示例#9
0
/*
 * 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;
}
示例#10
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);
}
示例#11
0
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;
	}
}
示例#12
0
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;
}
示例#15
0
/* 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;
}
示例#17
0
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);
}
示例#18
0
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;
}
示例#19
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));
}
示例#20
0
/*
 *  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;
}
示例#21
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;
}
示例#22
0
/**
 * @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__);	
}
示例#23
0
/**
 * @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);
}
示例#24
0
/*
 *  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;
}
示例#25
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;
}
示例#26
0
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);
}
示例#27
0
/**
 * @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;
}
示例#29
0
/*
 * .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
}