aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mx3_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mx3_camera.c')
-rw-r--r--drivers/media/video/mx3_camera.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index 502e2a40964c..c7680eb83664 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -400,6 +400,35 @@ static int mx3_videobuf_init(struct vb2_buffer *vb)
400 return 0; 400 return 0;
401} 401}
402 402
403static int mx3_stop_streaming(struct vb2_queue *q)
404{
405 struct soc_camera_device *icd = soc_camera_from_vb2q(q);
406 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
407 struct mx3_camera_dev *mx3_cam = ici->priv;
408 struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
409 struct dma_chan *chan;
410 struct mx3_camera_buffer *buf, *tmp;
411 unsigned long flags;
412
413 if (ichan) {
414 chan = &ichan->dma_chan;
415 chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
416 }
417
418 spin_lock_irqsave(&mx3_cam->lock, flags);
419
420 mx3_cam->active = NULL;
421
422 list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) {
423 buf->state = CSI_BUF_NEEDS_INIT;
424 list_del_init(&buf->queue);
425 }
426
427 spin_unlock_irqrestore(&mx3_cam->lock, flags);
428
429 return 0;
430}
431
403static struct vb2_ops mx3_videobuf_ops = { 432static struct vb2_ops mx3_videobuf_ops = {
404 .queue_setup = mx3_videobuf_setup, 433 .queue_setup = mx3_videobuf_setup,
405 .buf_prepare = mx3_videobuf_prepare, 434 .buf_prepare = mx3_videobuf_prepare,
@@ -408,6 +437,7 @@ static struct vb2_ops mx3_videobuf_ops = {
408 .buf_init = mx3_videobuf_init, 437 .buf_init = mx3_videobuf_init,
409 .wait_prepare = soc_camera_unlock, 438 .wait_prepare = soc_camera_unlock,
410 .wait_finish = soc_camera_lock, 439 .wait_finish = soc_camera_lock,
440 .stop_streaming = mx3_stop_streaming,
411}; 441};
412 442
413static int mx3_camera_init_videobuf(struct vb2_queue *q, 443static int mx3_camera_init_videobuf(struct vb2_queue *q,
@@ -658,8 +688,8 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id
658 688
659 fmt = soc_mbus_get_fmtdesc(code); 689 fmt = soc_mbus_get_fmtdesc(code);
660 if (!fmt) { 690 if (!fmt) {
661 dev_err(icd->dev.parent, 691 dev_warn(icd->dev.parent,
662 "Invalid format code #%u: %d\n", idx, code); 692 "Unsupported format code #%u: %d\n", idx, code);
663 return 0; 693 return 0;
664 } 694 }
665 695
@@ -712,13 +742,9 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id
712 742
713static void configure_geometry(struct mx3_camera_dev *mx3_cam, 743static void configure_geometry(struct mx3_camera_dev *mx3_cam,
714 unsigned int width, unsigned int height, 744 unsigned int width, unsigned int height,
715 enum v4l2_mbus_pixelcode code) 745 const struct soc_mbus_pixelfmt *fmt)
716{ 746{
717 u32 ctrl, width_field, height_field; 747 u32 ctrl, width_field, height_field;
718 const struct soc_mbus_pixelfmt *fmt;
719
720 fmt = soc_mbus_get_fmtdesc(code);
721 BUG_ON(!fmt);
722 748
723 if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) { 749 if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) {
724 /* 750 /*
@@ -726,8 +752,10 @@ static void configure_geometry(struct mx3_camera_dev *mx3_cam,
726 * the width parameter count the number of samples to 752 * the width parameter count the number of samples to
727 * capture to complete the whole image width. 753 * capture to complete the whole image width.
728 */ 754 */
729 width *= soc_mbus_samples_per_pixel(fmt); 755 unsigned int num, den;
730 BUG_ON(width < 0); 756 int ret = soc_mbus_samples_per_pixel(fmt, &num, &den);
757 BUG_ON(ret < 0);
758 width = width * num / den;
731 } 759 }
732 760
733 /* Setup frame size - this cannot be changed on-the-fly... */ 761 /* Setup frame size - this cannot be changed on-the-fly... */
@@ -774,8 +802,8 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
774 */ 802 */
775static inline void stride_align(__u32 *width) 803static inline void stride_align(__u32 *width)
776{ 804{
777 if (((*width + 7) & ~7) < 4096) 805 if (ALIGN(*width, 8) < 4096)
778 *width = (*width + 7) & ~7; 806 *width = ALIGN(*width, 8);
779 else 807 else
780 *width = *width & ~7; 808 *width = *width & ~7;
781} 809}
@@ -801,11 +829,14 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
801 if (ret < 0) 829 if (ret < 0)
802 return ret; 830 return ret;
803 831
804 /* The capture device might have changed its output */ 832 /* The capture device might have changed its output sizes */
805 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); 833 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
806 if (ret < 0) 834 if (ret < 0)
807 return ret; 835 return ret;
808 836
837 if (mf.code != icd->current_fmt->code)
838 return -EINVAL;
839
809 if (mf.width & 7) { 840 if (mf.width & 7) {
810 /* Ouch! We can only handle 8-byte aligned width... */ 841 /* Ouch! We can only handle 8-byte aligned width... */
811 stride_align(&mf.width); 842 stride_align(&mf.width);
@@ -815,7 +846,8 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
815 } 846 }
816 847
817 if (mf.width != icd->user_width || mf.height != icd->user_height) 848 if (mf.width != icd->user_width || mf.height != icd->user_height)
818 configure_geometry(mx3_cam, mf.width, mf.height, mf.code); 849 configure_geometry(mx3_cam, mf.width, mf.height,
850 icd->current_fmt->host_fmt);
819 851
820 dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", 852 dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
821 mf.width, mf.height); 853 mf.width, mf.height);
@@ -853,7 +885,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
853 * mxc_v4l2_s_fmt() 885 * mxc_v4l2_s_fmt()
854 */ 886 */
855 887
856 configure_geometry(mx3_cam, pix->width, pix->height, xlate->code); 888 configure_geometry(mx3_cam, pix->width, pix->height, xlate->host_fmt);
857 889
858 mf.width = pix->width; 890 mf.width = pix->width;
859 mf.height = pix->height; 891 mf.height = pix->height;