aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mx3_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-03-13 05:08:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:21 -0400
commit09e231b35173313cd92e27532e5028f2042dcee4 (patch)
tree3ecda063aa52f954d2f797921bdce131d7f1cc28 /drivers/media/video/mx3_camera.c
parent1cd3c0fa927084549005fc22e54d99684b314f14 (diff)
V4L/DVB (11024): soc-camera: separate S_FMT and S_CROP operations
As host and camera drivers become more complex, differences between S_FMT and S_CROP functionality grow, this patch separates them. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mx3_camera.c')
-rw-r--r--drivers/media/video/mx3_camera.c157
1 files changed, 97 insertions, 60 deletions
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index f525dc48f6ca..70629e172e65 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -544,16 +544,14 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
544} 544}
545 545
546static bool channel_change_requested(struct soc_camera_device *icd, 546static bool channel_change_requested(struct soc_camera_device *icd,
547 const struct soc_camera_format_xlate *xlate, 547 struct v4l2_rect *rect)
548 __u32 pixfmt, struct v4l2_rect *rect)
549{ 548{
550 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 549 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
551 struct mx3_camera_dev *mx3_cam = ici->priv; 550 struct mx3_camera_dev *mx3_cam = ici->priv;
552 struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; 551 struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
553 552
554 /* So far only one configuration is supported */ 553 /* Do buffers have to be re-allocated or channel re-configured? */
555 return pixfmt || (ichan && rect->width * rect->height > 554 return ichan && rect->width * rect->height > icd->width * icd->height;
556 icd->width * icd->height);
557} 555}
558 556
559static int test_platform_param(struct mx3_camera_dev *mx3_cam, 557static int test_platform_param(struct mx3_camera_dev *mx3_cam,
@@ -733,61 +731,10 @@ passthrough:
733 return formats; 731 return formats;
734} 732}
735 733
736static int mx3_camera_set_fmt(struct soc_camera_device *icd, 734static void configure_geometry(struct mx3_camera_dev *mx3_cam,
737 __u32 pixfmt, struct v4l2_rect *rect) 735 struct v4l2_rect *rect)
738{ 736{
739 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
740 struct mx3_camera_dev *mx3_cam = ici->priv;
741 const struct soc_camera_format_xlate *xlate;
742 u32 ctrl, width_field, height_field; 737 u32 ctrl, width_field, height_field;
743 int ret;
744
745 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
746 if (pixfmt && !xlate) {
747 dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
748 return -EINVAL;
749 }
750
751 /*
752 * We now know pixel formats and can decide upon DMA-channel(s)
753 * So far only direct camera-to-memory is supported
754 */
755 if (channel_change_requested(icd, xlate, pixfmt, rect)) {
756 dma_cap_mask_t mask;
757 struct dma_chan *chan;
758 struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
759 /* We have to use IDMAC_IC_7 for Bayer / generic data */
760 struct dma_chan_request rq = {.mx3_cam = mx3_cam,
761 .id = IDMAC_IC_7};
762
763 if (*ichan) {
764 struct videobuf_buffer *vb, *_vb;
765 dma_release_channel(&(*ichan)->dma_chan);
766 *ichan = NULL;
767 mx3_cam->active = NULL;
768 list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
769 list_del_init(&vb->queue);
770 vb->state = VIDEOBUF_ERROR;
771 wake_up(&vb->done);
772 }
773 }
774
775 dma_cap_zero(mask);
776 dma_cap_set(DMA_SLAVE, mask);
777 dma_cap_set(DMA_PRIVATE, mask);
778 chan = dma_request_channel(mask, chan_filter, &rq);
779 if (!chan)
780 return -EBUSY;
781
782 *ichan = to_idmac_chan(chan);
783 (*ichan)->client = mx3_cam;
784 }
785
786 /*
787 * Might have to perform a complete interface initialisation like in
788 * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
789 * mxc_v4l2_s_fmt()
790 */
791 738
792 /* Setup frame size - this cannot be changed on-the-fly... */ 739 /* Setup frame size - this cannot be changed on-the-fly... */
793 width_field = rect->width - 1; 740 width_field = rect->width - 1;
@@ -808,9 +755,98 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
808 * No need to free resources here if we fail, we'll see if we need to 755 * No need to free resources here if we fail, we'll see if we need to
809 * do this next time we are called 756 * do this next time we are called
810 */ 757 */
758}
759
760static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
761{
762 dma_cap_mask_t mask;
763 struct dma_chan *chan;
764 struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
765 /* We have to use IDMAC_IC_7 for Bayer / generic data */
766 struct dma_chan_request rq = {.mx3_cam = mx3_cam,
767 .id = IDMAC_IC_7};
768
769 if (*ichan) {
770 struct videobuf_buffer *vb, *_vb;
771 dma_release_channel(&(*ichan)->dma_chan);
772 *ichan = NULL;
773 mx3_cam->active = NULL;
774 list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
775 list_del_init(&vb->queue);
776 vb->state = VIDEOBUF_ERROR;
777 wake_up(&vb->done);
778 }
779 }
780
781 dma_cap_zero(mask);
782 dma_cap_set(DMA_SLAVE, mask);
783 dma_cap_set(DMA_PRIVATE, mask);
784 chan = dma_request_channel(mask, chan_filter, &rq);
785 if (!chan)
786 return -EBUSY;
787
788 *ichan = to_idmac_chan(chan);
789 (*ichan)->client = mx3_cam;
790
791 return 0;
792}
793
794static int mx3_camera_set_crop(struct soc_camera_device *icd,
795 struct v4l2_rect *rect)
796{
797 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
798 struct mx3_camera_dev *mx3_cam = ici->priv;
799
800 /*
801 * We now know pixel formats and can decide upon DMA-channel(s)
802 * So far only direct camera-to-memory is supported
803 */
804 if (channel_change_requested(icd, rect)) {
805 int ret = acquire_dma_channel(mx3_cam);
806 if (ret < 0)
807 return ret;
808 }
809
810 configure_geometry(mx3_cam, rect);
811
812 return icd->ops->set_crop(icd, rect);
813}
814
815static int mx3_camera_set_fmt(struct soc_camera_device *icd,
816 struct v4l2_format *f)
817{
818 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
819 struct mx3_camera_dev *mx3_cam = ici->priv;
820 const struct soc_camera_format_xlate *xlate;
821 struct v4l2_pix_format *pix = &f->fmt.pix;
822 struct v4l2_rect rect = {
823 .left = icd->x_current,
824 .top = icd->y_current,
825 .width = pix->width,
826 .height = pix->height,
827 };
828 int ret;
829
830 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
831 if (!xlate) {
832 dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
833 return -EINVAL;
834 }
835
836 ret = acquire_dma_channel(mx3_cam);
837 if (ret < 0)
838 return ret;
839
840 /*
841 * Might have to perform a complete interface initialisation like in
842 * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
843 * mxc_v4l2_s_fmt()
844 */
845
846 configure_geometry(mx3_cam, &rect);
811 847
812 ret = icd->ops->set_fmt(icd, pixfmt ? xlate->cam_fmt->fourcc : 0, rect); 848 ret = icd->ops->set_fmt(icd, f);
813 if (pixfmt && !ret) { 849 if (!ret) {
814 icd->buswidth = xlate->buswidth; 850 icd->buswidth = xlate->buswidth;
815 icd->current_fmt = xlate->host_fmt; 851 icd->current_fmt = xlate->host_fmt;
816 } 852 }
@@ -1031,6 +1067,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
1031 .suspend = mx3_camera_suspend, 1067 .suspend = mx3_camera_suspend,
1032 .resume = mx3_camera_resume, 1068 .resume = mx3_camera_resume,
1033#endif 1069#endif
1070 .set_crop = mx3_camera_set_crop,
1034 .set_fmt = mx3_camera_set_fmt, 1071 .set_fmt = mx3_camera_set_fmt,
1035 .try_fmt = mx3_camera_try_fmt, 1072 .try_fmt = mx3_camera_try_fmt,
1036 .get_formats = mx3_camera_get_formats, 1073 .get_formats = mx3_camera_get_formats,