diff options
author | Javier Martin <javier.martin@vista-silicon.com> | 2012-01-30 07:14:11 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-08 07:40:45 -0500 |
commit | fb51cbdd3ec868b903bd706aa7db065c8c36bcd4 (patch) | |
tree | bf747879b2c7bf6a0b4926f3f89b432c9f3deb0d | |
parent | c6a41e3271c61f6f5aec1a91b4458330d4266e5f (diff) |
[media] media i.MX27 camera: add start_stream and stop_stream callbacks
Add "start_stream" and "stop_stream" callback in order to enable
and disable the eMMa-PrP properly and save CPU usage avoiding
IRQs when the device is not streaming. This also makes the driver
return 0 as the sequence number of the first frame.
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
[g.liakhovetski@gmx.de: remove the mx27_camera_emma() macro]
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/mx2_camera.c | 100 |
1 files changed, 75 insertions, 25 deletions
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 22f5dbcf6db8..2e232092fc10 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c | |||
@@ -373,7 +373,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) | |||
373 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); | 373 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); |
374 | 374 | ||
375 | pcdev->icd = icd; | 375 | pcdev->icd = icd; |
376 | pcdev->frame_count = 0; | 376 | pcdev->frame_count = -1; |
377 | 377 | ||
378 | dev_info(icd->parent, "Camera driver attached to camera %d\n", | 378 | dev_info(icd->parent, "Camera driver attached to camera %d\n", |
379 | icd->devnum); | 379 | icd->devnum); |
@@ -644,11 +644,79 @@ static void mx2_videobuf_release(struct vb2_buffer *vb) | |||
644 | spin_unlock_irqrestore(&pcdev->lock, flags); | 644 | spin_unlock_irqrestore(&pcdev->lock, flags); |
645 | } | 645 | } |
646 | 646 | ||
647 | static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) | ||
648 | { | ||
649 | struct soc_camera_device *icd = soc_camera_from_vb2q(q); | ||
650 | struct soc_camera_host *ici = | ||
651 | to_soc_camera_host(icd->parent); | ||
652 | struct mx2_camera_dev *pcdev = ici->priv; | ||
653 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
654 | |||
655 | if (cpu_is_mx27()) { | ||
656 | unsigned long flags; | ||
657 | if (count < 2) | ||
658 | return -EINVAL; | ||
659 | |||
660 | spin_lock_irqsave(&pcdev->lock, flags); | ||
661 | if (prp->cfg.channel == 1) { | ||
662 | writel(PRP_CNTL_CH1EN | | ||
663 | PRP_CNTL_CSIEN | | ||
664 | prp->cfg.in_fmt | | ||
665 | prp->cfg.out_fmt | | ||
666 | PRP_CNTL_CH1_LEN | | ||
667 | PRP_CNTL_CH1BYP | | ||
668 | PRP_CNTL_CH1_TSKIP(0) | | ||
669 | PRP_CNTL_IN_TSKIP(0), | ||
670 | pcdev->base_emma + PRP_CNTL); | ||
671 | } else { | ||
672 | writel(PRP_CNTL_CH2EN | | ||
673 | PRP_CNTL_CSIEN | | ||
674 | prp->cfg.in_fmt | | ||
675 | prp->cfg.out_fmt | | ||
676 | PRP_CNTL_CH2_LEN | | ||
677 | PRP_CNTL_CH2_TSKIP(0) | | ||
678 | PRP_CNTL_IN_TSKIP(0), | ||
679 | pcdev->base_emma + PRP_CNTL); | ||
680 | } | ||
681 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
682 | } | ||
683 | |||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | static int mx2_stop_streaming(struct vb2_queue *q) | ||
688 | { | ||
689 | struct soc_camera_device *icd = soc_camera_from_vb2q(q); | ||
690 | struct soc_camera_host *ici = | ||
691 | to_soc_camera_host(icd->parent); | ||
692 | struct mx2_camera_dev *pcdev = ici->priv; | ||
693 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
694 | unsigned long flags; | ||
695 | u32 cntl; | ||
696 | |||
697 | spin_lock_irqsave(&pcdev->lock, flags); | ||
698 | if (cpu_is_mx27()) { | ||
699 | cntl = readl(pcdev->base_emma + PRP_CNTL); | ||
700 | if (prp->cfg.channel == 1) { | ||
701 | writel(cntl & ~PRP_CNTL_CH1EN, | ||
702 | pcdev->base_emma + PRP_CNTL); | ||
703 | } else { | ||
704 | writel(cntl & ~PRP_CNTL_CH2EN, | ||
705 | pcdev->base_emma + PRP_CNTL); | ||
706 | } | ||
707 | } | ||
708 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
709 | |||
710 | return 0; | ||
711 | } | ||
712 | |||
647 | static struct vb2_ops mx2_videobuf_ops = { | 713 | static struct vb2_ops mx2_videobuf_ops = { |
648 | .queue_setup = mx2_videobuf_setup, | 714 | .queue_setup = mx2_videobuf_setup, |
649 | .buf_prepare = mx2_videobuf_prepare, | 715 | .buf_prepare = mx2_videobuf_prepare, |
650 | .buf_queue = mx2_videobuf_queue, | 716 | .buf_queue = mx2_videobuf_queue, |
651 | .buf_cleanup = mx2_videobuf_release, | 717 | .buf_cleanup = mx2_videobuf_release, |
718 | .start_streaming = mx2_start_streaming, | ||
719 | .stop_streaming = mx2_stop_streaming, | ||
652 | }; | 720 | }; |
653 | 721 | ||
654 | static int mx2_camera_init_videobuf(struct vb2_queue *q, | 722 | static int mx2_camera_init_videobuf(struct vb2_queue *q, |
@@ -706,16 +774,6 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, | |||
706 | writel(pcdev->discard_buffer_dma, | 774 | writel(pcdev->discard_buffer_dma, |
707 | pcdev->base_emma + PRP_DEST_RGB2_PTR); | 775 | pcdev->base_emma + PRP_DEST_RGB2_PTR); |
708 | 776 | ||
709 | writel(PRP_CNTL_CH1EN | | ||
710 | PRP_CNTL_CSIEN | | ||
711 | prp->cfg.in_fmt | | ||
712 | prp->cfg.out_fmt | | ||
713 | PRP_CNTL_CH1_LEN | | ||
714 | PRP_CNTL_CH1BYP | | ||
715 | PRP_CNTL_CH1_TSKIP(0) | | ||
716 | PRP_CNTL_IN_TSKIP(0), | ||
717 | pcdev->base_emma + PRP_CNTL); | ||
718 | |||
719 | writel((icd->user_width << 16) | icd->user_height, | 777 | writel((icd->user_width << 16) | icd->user_height, |
720 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | 778 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); |
721 | writel((icd->user_width << 16) | icd->user_height, | 779 | writel((icd->user_width << 16) | icd->user_height, |
@@ -743,15 +801,6 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, | |||
743 | pcdev->base_emma + PRP_SOURCE_CR_PTR); | 801 | pcdev->base_emma + PRP_SOURCE_CR_PTR); |
744 | } | 802 | } |
745 | 803 | ||
746 | writel(PRP_CNTL_CH2EN | | ||
747 | PRP_CNTL_CSIEN | | ||
748 | prp->cfg.in_fmt | | ||
749 | prp->cfg.out_fmt | | ||
750 | PRP_CNTL_CH2_LEN | | ||
751 | PRP_CNTL_CH2_TSKIP(0) | | ||
752 | PRP_CNTL_IN_TSKIP(0), | ||
753 | pcdev->base_emma + PRP_CNTL); | ||
754 | |||
755 | writel((icd->user_width << 16) | icd->user_height, | 804 | writel((icd->user_width << 16) | icd->user_height, |
756 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | 805 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); |
757 | 806 | ||
@@ -1156,11 +1205,12 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1156 | 1205 | ||
1157 | list_del_init(&buf->queue); | 1206 | list_del_init(&buf->queue); |
1158 | do_gettimeofday(&vb->v4l2_buf.timestamp); | 1207 | do_gettimeofday(&vb->v4l2_buf.timestamp); |
1159 | pcdev->frame_count++; | ||
1160 | vb->v4l2_buf.sequence = pcdev->frame_count; | 1208 | vb->v4l2_buf.sequence = pcdev->frame_count; |
1161 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | 1209 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); |
1162 | } | 1210 | } |
1163 | 1211 | ||
1212 | pcdev->frame_count++; | ||
1213 | |||
1164 | if (list_empty(&pcdev->capture)) { | 1214 | if (list_empty(&pcdev->capture)) { |
1165 | if (prp->cfg.channel == 1) { | 1215 | if (prp->cfg.channel == 1) { |
1166 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + | 1216 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + |