diff options
author | Javier Martin <javier.martin@vista-silicon.com> | 2011-12-14 11:30:14 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-06 08:02:07 -0500 |
commit | f410991dcf1fc3ad1d3311b79b4f1b917224ebed (patch) | |
tree | 30228a0d10531612307e0d164b06d84426274e67 /drivers/media/video/mx2_camera.c | |
parent | d8ec0961ce5a9ddbece875c2b6fc028cb750df3a (diff) |
[media] i.MX27 camera: add support for YUV420 format
This patch uses channel 2 of the eMMa-PrP to convert
format provided by the sensor to YUV420.
This format is very useful since it is used by the
internal H.264 encoder.
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mx2_camera.c')
-rw-r--r-- | drivers/media/video/mx2_camera.c | 291 |
1 files changed, 241 insertions, 50 deletions
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index ffbfbfe05169..e635ab3c71e7 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c | |||
@@ -210,6 +210,22 @@ | |||
210 | 210 | ||
211 | #define MAX_VIDEO_MEM 16 | 211 | #define MAX_VIDEO_MEM 16 |
212 | 212 | ||
213 | struct mx2_prp_cfg { | ||
214 | int channel; | ||
215 | u32 in_fmt; | ||
216 | u32 out_fmt; | ||
217 | u32 src_pixel; | ||
218 | u32 ch1_pixel; | ||
219 | u32 irq_flags; | ||
220 | }; | ||
221 | |||
222 | /* prp configuration for a client-host fmt pair */ | ||
223 | struct mx2_fmt_cfg { | ||
224 | enum v4l2_mbus_pixelcode in_fmt; | ||
225 | u32 out_fmt; | ||
226 | struct mx2_prp_cfg cfg; | ||
227 | }; | ||
228 | |||
213 | struct mx2_camera_dev { | 229 | struct mx2_camera_dev { |
214 | struct device *dev; | 230 | struct device *dev; |
215 | struct soc_camera_host soc_host; | 231 | struct soc_camera_host soc_host; |
@@ -241,6 +257,7 @@ struct mx2_camera_dev { | |||
241 | void *discard_buffer; | 257 | void *discard_buffer; |
242 | dma_addr_t discard_buffer_dma; | 258 | dma_addr_t discard_buffer_dma; |
243 | size_t discard_size; | 259 | size_t discard_size; |
260 | struct mx2_fmt_cfg *emma_prp; | ||
244 | }; | 261 | }; |
245 | 262 | ||
246 | /* buffer for one video frame */ | 263 | /* buffer for one video frame */ |
@@ -253,6 +270,59 @@ struct mx2_buffer { | |||
253 | int bufnum; | 270 | int bufnum; |
254 | }; | 271 | }; |
255 | 272 | ||
273 | static struct mx2_fmt_cfg mx27_emma_prp_table[] = { | ||
274 | /* | ||
275 | * This is a generic configuration which is valid for most | ||
276 | * prp input-output format combinations. | ||
277 | * We set the incomming and outgoing pixelformat to a | ||
278 | * 16 Bit wide format and adjust the bytesperline | ||
279 | * accordingly. With this configuration the inputdata | ||
280 | * will not be changed by the emma and could be any type | ||
281 | * of 16 Bit Pixelformat. | ||
282 | */ | ||
283 | { | ||
284 | .in_fmt = 0, | ||
285 | .out_fmt = 0, | ||
286 | .cfg = { | ||
287 | .channel = 1, | ||
288 | .in_fmt = PRP_CNTL_DATA_IN_RGB16, | ||
289 | .out_fmt = PRP_CNTL_CH1_OUT_RGB16, | ||
290 | .src_pixel = 0x2ca00565, /* RGB565 */ | ||
291 | .ch1_pixel = 0x2ca00565, /* RGB565 */ | ||
292 | .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | | ||
293 | PRP_INTR_CH1FC | PRP_INTR_LBOVF, | ||
294 | } | ||
295 | }, | ||
296 | { | ||
297 | .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8, | ||
298 | .out_fmt = V4L2_PIX_FMT_YUV420, | ||
299 | .cfg = { | ||
300 | .channel = 2, | ||
301 | .in_fmt = PRP_CNTL_DATA_IN_YUV422, | ||
302 | .out_fmt = PRP_CNTL_CH2_OUT_YUV420, | ||
303 | .src_pixel = 0x22000888, /* YUV422 (YUYV) */ | ||
304 | .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | | ||
305 | PRP_INTR_CH2FC | PRP_INTR_LBOVF | | ||
306 | PRP_INTR_CH2OVF, | ||
307 | } | ||
308 | }, | ||
309 | }; | ||
310 | |||
311 | static struct mx2_fmt_cfg *mx27_emma_prp_get_format( | ||
312 | enum v4l2_mbus_pixelcode in_fmt, | ||
313 | u32 out_fmt) | ||
314 | { | ||
315 | int i; | ||
316 | |||
317 | for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++) | ||
318 | if ((mx27_emma_prp_table[i].in_fmt == in_fmt) && | ||
319 | (mx27_emma_prp_table[i].out_fmt == out_fmt)) { | ||
320 | return &mx27_emma_prp_table[i]; | ||
321 | } | ||
322 | /* If no match return the most generic configuration */ | ||
323 | return &mx27_emma_prp_table[0]; | ||
324 | }; | ||
325 | |||
256 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) | 326 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) |
257 | { | 327 | { |
258 | unsigned long flags; | 328 | unsigned long flags; |
@@ -719,51 +789,74 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, | |||
719 | struct soc_camera_host *ici = | 789 | struct soc_camera_host *ici = |
720 | to_soc_camera_host(icd->parent); | 790 | to_soc_camera_host(icd->parent); |
721 | struct mx2_camera_dev *pcdev = ici->priv; | 791 | struct mx2_camera_dev *pcdev = ici->priv; |
792 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
793 | u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; | ||
794 | |||
795 | if (prp->cfg.channel == 1) { | ||
796 | writel(pcdev->discard_buffer_dma, | ||
797 | pcdev->base_emma + PRP_DEST_RGB1_PTR); | ||
798 | writel(pcdev->discard_buffer_dma, | ||
799 | pcdev->base_emma + PRP_DEST_RGB2_PTR); | ||
800 | |||
801 | writel(PRP_CNTL_CH1EN | | ||
802 | PRP_CNTL_CSIEN | | ||
803 | prp->cfg.in_fmt | | ||
804 | prp->cfg.out_fmt | | ||
805 | PRP_CNTL_CH1_LEN | | ||
806 | PRP_CNTL_CH1BYP | | ||
807 | PRP_CNTL_CH1_TSKIP(0) | | ||
808 | PRP_CNTL_IN_TSKIP(0), | ||
809 | pcdev->base_emma + PRP_CNTL); | ||
810 | |||
811 | writel((icd->user_width << 16) | icd->user_height, | ||
812 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | ||
813 | writel((icd->user_width << 16) | icd->user_height, | ||
814 | pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); | ||
815 | writel(bytesperline, | ||
816 | pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); | ||
817 | writel(prp->cfg.src_pixel, | ||
818 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); | ||
819 | writel(prp->cfg.ch1_pixel, | ||
820 | pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); | ||
821 | } else { /* channel 2 */ | ||
822 | writel(pcdev->discard_buffer_dma, | ||
823 | pcdev->base_emma + PRP_DEST_Y_PTR); | ||
824 | writel(pcdev->discard_buffer_dma, | ||
825 | pcdev->base_emma + PRP_SOURCE_Y_PTR); | ||
826 | |||
827 | if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { | ||
828 | writel(pcdev->discard_buffer_dma + imgsize, | ||
829 | pcdev->base_emma + PRP_DEST_CB_PTR); | ||
830 | writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), | ||
831 | pcdev->base_emma + PRP_DEST_CR_PTR); | ||
832 | writel(pcdev->discard_buffer_dma + imgsize, | ||
833 | pcdev->base_emma + PRP_SOURCE_CB_PTR); | ||
834 | writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), | ||
835 | pcdev->base_emma + PRP_SOURCE_CR_PTR); | ||
836 | } | ||
722 | 837 | ||
723 | writel(pcdev->discard_buffer_dma, | 838 | writel(PRP_CNTL_CH2EN | |
724 | pcdev->base_emma + PRP_DEST_RGB1_PTR); | ||
725 | writel(pcdev->discard_buffer_dma, | ||
726 | pcdev->base_emma + PRP_DEST_RGB2_PTR); | ||
727 | |||
728 | /* | ||
729 | * We only use the EMMA engine to get rid of the broken | ||
730 | * DMA Engine. No color space consversion at the moment. | ||
731 | * We set the incomming and outgoing pixelformat to an | ||
732 | * 16 Bit wide format and adjust the bytesperline | ||
733 | * accordingly. With this configuration the inputdata | ||
734 | * will not be changed by the emma and could be any type | ||
735 | * of 16 Bit Pixelformat. | ||
736 | */ | ||
737 | writel(PRP_CNTL_CH1EN | | ||
738 | PRP_CNTL_CSIEN | | 839 | PRP_CNTL_CSIEN | |
739 | PRP_CNTL_DATA_IN_RGB16 | | 840 | prp->cfg.in_fmt | |
740 | PRP_CNTL_CH1_OUT_RGB16 | | 841 | prp->cfg.out_fmt | |
741 | PRP_CNTL_CH1_LEN | | 842 | PRP_CNTL_CH2_LEN | |
742 | PRP_CNTL_CH1BYP | | 843 | PRP_CNTL_CH2_TSKIP(0) | |
743 | PRP_CNTL_CH1_TSKIP(0) | | ||
744 | PRP_CNTL_IN_TSKIP(0), | 844 | PRP_CNTL_IN_TSKIP(0), |
745 | pcdev->base_emma + PRP_CNTL); | 845 | pcdev->base_emma + PRP_CNTL); |
746 | 846 | ||
747 | writel(((bytesperline >> 1) << 16) | icd->user_height, | 847 | writel((icd->user_width << 16) | icd->user_height, |
748 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | 848 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); |
749 | writel(((bytesperline >> 1) << 16) | icd->user_height, | 849 | |
750 | pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); | 850 | writel((icd->user_width << 16) | icd->user_height, |
751 | writel(bytesperline, | 851 | pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); |
752 | pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); | 852 | |
753 | writel(0x2ca00565, /* RGB565 */ | 853 | writel(prp->cfg.src_pixel, |
754 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); | 854 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); |
755 | writel(0x2ca00565, /* RGB565 */ | 855 | |
756 | pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); | 856 | } |
757 | 857 | ||
758 | /* Enable interrupts */ | 858 | /* Enable interrupts */ |
759 | writel(PRP_INTR_RDERR | | 859 | writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); |
760 | PRP_INTR_CH1WERR | | ||
761 | PRP_INTR_CH2WERR | | ||
762 | PRP_INTR_CH1FC | | ||
763 | PRP_INTR_CH2FC | | ||
764 | PRP_INTR_LBOVF | | ||
765 | PRP_INTR_CH2OVF, | ||
766 | pcdev->base_emma + PRP_INTR_CNTL); | ||
767 | } | 860 | } |
768 | 861 | ||
769 | static int mx2_camera_set_bus_param(struct soc_camera_device *icd) | 862 | static int mx2_camera_set_bus_param(struct soc_camera_device *icd) |
@@ -910,9 +1003,58 @@ static int mx2_camera_set_crop(struct soc_camera_device *icd, | |||
910 | return ret; | 1003 | return ret; |
911 | } | 1004 | } |
912 | 1005 | ||
1006 | static int mx2_camera_get_formats(struct soc_camera_device *icd, | ||
1007 | unsigned int idx, | ||
1008 | struct soc_camera_format_xlate *xlate) | ||
1009 | { | ||
1010 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1011 | const struct soc_mbus_pixelfmt *fmt; | ||
1012 | struct device *dev = icd->parent; | ||
1013 | enum v4l2_mbus_pixelcode code; | ||
1014 | int ret, formats = 0; | ||
1015 | |||
1016 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); | ||
1017 | if (ret < 0) | ||
1018 | /* no more formats */ | ||
1019 | return 0; | ||
1020 | |||
1021 | fmt = soc_mbus_get_fmtdesc(code); | ||
1022 | if (!fmt) { | ||
1023 | dev_err(dev, "Invalid format code #%u: %d\n", idx, code); | ||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
1027 | if (code == V4L2_MBUS_FMT_YUYV8_2X8) { | ||
1028 | formats++; | ||
1029 | if (xlate) { | ||
1030 | /* | ||
1031 | * CH2 can output YUV420 which is a standard format in | ||
1032 | * soc_mediabus.c | ||
1033 | */ | ||
1034 | xlate->host_fmt = | ||
1035 | soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8); | ||
1036 | xlate->code = code; | ||
1037 | dev_dbg(dev, "Providing host format %s for sensor code %d\n", | ||
1038 | xlate->host_fmt->name, code); | ||
1039 | xlate++; | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | /* Generic pass-trough */ | ||
1044 | formats++; | ||
1045 | if (xlate) { | ||
1046 | xlate->host_fmt = fmt; | ||
1047 | xlate->code = code; | ||
1048 | xlate++; | ||
1049 | } | ||
1050 | return formats; | ||
1051 | } | ||
1052 | |||
913 | static int mx2_camera_set_fmt(struct soc_camera_device *icd, | 1053 | static int mx2_camera_set_fmt(struct soc_camera_device *icd, |
914 | struct v4l2_format *f) | 1054 | struct v4l2_format *f) |
915 | { | 1055 | { |
1056 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1057 | struct mx2_camera_dev *pcdev = ici->priv; | ||
916 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1058 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
917 | const struct soc_camera_format_xlate *xlate; | 1059 | const struct soc_camera_format_xlate *xlate; |
918 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1060 | struct v4l2_pix_format *pix = &f->fmt.pix; |
@@ -945,6 +1087,10 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd, | |||
945 | pix->colorspace = mf.colorspace; | 1087 | pix->colorspace = mf.colorspace; |
946 | icd->current_fmt = xlate; | 1088 | icd->current_fmt = xlate; |
947 | 1089 | ||
1090 | if (mx27_camera_emma(pcdev)) | ||
1091 | pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, | ||
1092 | xlate->host_fmt->fourcc); | ||
1093 | |||
948 | return 0; | 1094 | return 0; |
949 | } | 1095 | } |
950 | 1096 | ||
@@ -1010,7 +1156,12 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1010 | 1156 | ||
1011 | if (mf.field == V4L2_FIELD_ANY) | 1157 | if (mf.field == V4L2_FIELD_ANY) |
1012 | mf.field = V4L2_FIELD_NONE; | 1158 | mf.field = V4L2_FIELD_NONE; |
1013 | if (mf.field != V4L2_FIELD_NONE) { | 1159 | /* |
1160 | * Driver supports interlaced images provided they have | ||
1161 | * both fields so that they can be processed as if they | ||
1162 | * were progressive. | ||
1163 | */ | ||
1164 | if (mf.field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf.field)) { | ||
1014 | dev_err(icd->parent, "Field type %d unsupported.\n", | 1165 | dev_err(icd->parent, "Field type %d unsupported.\n", |
1015 | mf.field); | 1166 | mf.field); |
1016 | return -EINVAL; | 1167 | return -EINVAL; |
@@ -1172,6 +1323,7 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { | |||
1172 | .remove = mx2_camera_remove_device, | 1323 | .remove = mx2_camera_remove_device, |
1173 | .set_fmt = mx2_camera_set_fmt, | 1324 | .set_fmt = mx2_camera_set_fmt, |
1174 | .set_crop = mx2_camera_set_crop, | 1325 | .set_crop = mx2_camera_set_crop, |
1326 | .get_formats = mx2_camera_get_formats, | ||
1175 | .try_fmt = mx2_camera_try_fmt, | 1327 | .try_fmt = mx2_camera_try_fmt, |
1176 | .init_videobuf = mx2_camera_init_videobuf, | 1328 | .init_videobuf = mx2_camera_init_videobuf, |
1177 | .reqbufs = mx2_camera_reqbufs, | 1329 | .reqbufs = mx2_camera_reqbufs, |
@@ -1183,6 +1335,8 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { | |||
1183 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | 1335 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, |
1184 | int bufnum, int state) | 1336 | int bufnum, int state) |
1185 | { | 1337 | { |
1338 | u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; | ||
1339 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
1186 | struct mx2_buffer *buf; | 1340 | struct mx2_buffer *buf; |
1187 | struct videobuf_buffer *vb; | 1341 | struct videobuf_buffer *vb; |
1188 | unsigned long phys; | 1342 | unsigned long phys; |
@@ -1196,12 +1350,22 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1196 | vb = &buf->vb; | 1350 | vb = &buf->vb; |
1197 | #ifdef DEBUG | 1351 | #ifdef DEBUG |
1198 | phys = videobuf_to_dma_contig(vb); | 1352 | phys = videobuf_to_dma_contig(vb); |
1199 | if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum) | 1353 | if (prp->cfg.channel == 1) { |
1200 | != phys) { | 1354 | if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + |
1201 | dev_err(pcdev->dev, "%p != %p\n", phys, | 1355 | 4 * bufnum) != phys) { |
1202 | readl(pcdev->base_emma + | 1356 | dev_err(pcdev->dev, "%p != %p\n", phys, |
1203 | PRP_DEST_RGB1_PTR + | 1357 | readl(pcdev->base_emma + |
1204 | 4 * bufnum)); | 1358 | PRP_DEST_RGB1_PTR + |
1359 | 4 * bufnum)); | ||
1360 | } | ||
1361 | } else { | ||
1362 | if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - | ||
1363 | 0x14 * bufnum) != phys) { | ||
1364 | dev_err(pcdev->dev, "%p != %p\n", phys, | ||
1365 | readl(pcdev->base_emma + | ||
1366 | PRP_DEST_Y_PTR - | ||
1367 | 0x14 * bufnum)); | ||
1368 | } | ||
1205 | } | 1369 | } |
1206 | #endif | 1370 | #endif |
1207 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, | 1371 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, |
@@ -1216,8 +1380,22 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1216 | } | 1380 | } |
1217 | 1381 | ||
1218 | if (list_empty(&pcdev->capture)) { | 1382 | if (list_empty(&pcdev->capture)) { |
1219 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + | 1383 | if (prp->cfg.channel == 1) { |
1220 | PRP_DEST_RGB1_PTR + 4 * bufnum); | 1384 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + |
1385 | PRP_DEST_RGB1_PTR + 4 * bufnum); | ||
1386 | } else { | ||
1387 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + | ||
1388 | PRP_DEST_Y_PTR - | ||
1389 | 0x14 * bufnum); | ||
1390 | if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { | ||
1391 | writel(pcdev->discard_buffer_dma + imgsize, | ||
1392 | pcdev->base_emma + PRP_DEST_CB_PTR - | ||
1393 | 0x14 * bufnum); | ||
1394 | writel(pcdev->discard_buffer_dma + | ||
1395 | ((5 * imgsize) / 4), pcdev->base_emma + | ||
1396 | PRP_DEST_CR_PTR - 0x14 * bufnum); | ||
1397 | } | ||
1398 | } | ||
1221 | return; | 1399 | return; |
1222 | } | 1400 | } |
1223 | 1401 | ||
@@ -1232,7 +1410,18 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1232 | vb->state = VIDEOBUF_ACTIVE; | 1410 | vb->state = VIDEOBUF_ACTIVE; |
1233 | 1411 | ||
1234 | phys = videobuf_to_dma_contig(vb); | 1412 | phys = videobuf_to_dma_contig(vb); |
1235 | writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); | 1413 | if (prp->cfg.channel == 1) { |
1414 | writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); | ||
1415 | } else { | ||
1416 | writel(phys, pcdev->base_emma + | ||
1417 | PRP_DEST_Y_PTR - 0x14 * bufnum); | ||
1418 | if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { | ||
1419 | writel(phys + imgsize, pcdev->base_emma + | ||
1420 | PRP_DEST_CB_PTR - 0x14 * bufnum); | ||
1421 | writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + | ||
1422 | PRP_DEST_CR_PTR - 0x14 * bufnum); | ||
1423 | } | ||
1424 | } | ||
1236 | } | 1425 | } |
1237 | 1426 | ||
1238 | static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | 1427 | static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) |
@@ -1252,10 +1441,12 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | |||
1252 | * the next one. | 1441 | * the next one. |
1253 | */ | 1442 | */ |
1254 | cntl = readl(pcdev->base_emma + PRP_CNTL); | 1443 | cntl = readl(pcdev->base_emma + PRP_CNTL); |
1255 | writel(cntl & ~PRP_CNTL_CH1EN, pcdev->base_emma + PRP_CNTL); | 1444 | writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), |
1445 | pcdev->base_emma + PRP_CNTL); | ||
1256 | writel(cntl, pcdev->base_emma + PRP_CNTL); | 1446 | writel(cntl, pcdev->base_emma + PRP_CNTL); |
1257 | } | 1447 | } |
1258 | if ((status & (3 << 5)) == (3 << 5) | 1448 | if ((((status & (3 << 5)) == (3 << 5)) || |
1449 | ((status & (3 << 3)) == (3 << 3))) | ||
1259 | && !list_empty(&pcdev->active_bufs)) { | 1450 | && !list_empty(&pcdev->active_bufs)) { |
1260 | /* | 1451 | /* |
1261 | * Both buffers have triggered, process the one we're expecting | 1452 | * Both buffers have triggered, process the one we're expecting |
@@ -1266,9 +1457,9 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | |||
1266 | mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); | 1457 | mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); |
1267 | status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ | 1458 | status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ |
1268 | } | 1459 | } |
1269 | if (status & (1 << 6)) | 1460 | if ((status & (1 << 6)) || (status & (1 << 4))) |
1270 | mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); | 1461 | mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); |
1271 | if (status & (1 << 5)) | 1462 | if ((status & (1 << 5)) || (status & (1 << 3))) |
1272 | mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); | 1463 | mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); |
1273 | 1464 | ||
1274 | writel(status, pcdev->base_emma + PRP_INTRSTATUS); | 1465 | writel(status, pcdev->base_emma + PRP_INTRSTATUS); |